diff --git a/Documentation/ABI/stable/sysfs-bus-nvmem b/Documentation/ABI/stable/sysfs-bus-nvmem index c399323f37de..aa89adf18bc5 100644 --- a/Documentation/ABI/stable/sysfs-bus-nvmem +++ b/Documentation/ABI/stable/sysfs-bus-nvmem @@ -1,6 +1,23 @@ +What: /sys/bus/nvmem/devices/.../force_ro +Date: June 2024 +KernelVersion: 6.11 +Contact: Marek Vasut +Description: + This read/write attribute allows users to set read-write + devices as read-only and back to read-write from userspace. + This can be used to unlock and relock write-protection of + devices which are generally locked, except during sporadic + programming operation. + Read returns '0' or '1' for read-write or read-only modes + respectively. + Write parses one of 'YyTt1NnFf0', or [oO][NnFf] for "on" + and "off", i.e. what kstrbool() supports. + Note: This file is only present if CONFIG_NVMEM_SYSFS + is enabled. + What: /sys/bus/nvmem/devices/.../nvmem Date: July 2015 -KernelVersion: 4.2 +KernelVersion: 4.2 Contact: Srinivas Kandagatla Description: This file allows user to read/write the raw NVMEM contents. @@ -20,3 +37,14 @@ Description: ... * 0001000 + +What: /sys/bus/nvmem/devices/.../type +Date: November 2018 +KernelVersion: 5.0 +Contact: Alexandre Belloni +Description: + This read-only attribute allows user to read the NVMEM + device type. Supported types are "Unknown", "EEPROM", + "OTP", "Battery backed", "FRAM". + Note: This file is only present if CONFIG_NVMEM_SYSFS + is enabled. diff --git a/Documentation/ABI/stable/sysfs-driver-misc-cp500 b/Documentation/ABI/stable/sysfs-driver-misc-cp500 new file mode 100644 index 000000000000..525bd18a2db4 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-driver-misc-cp500 @@ -0,0 +1,25 @@ +What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/0000:XX:XX.X/version +Date: June 2024 +KernelVersion: 6.11 +Contact: Gerhard Engleder +Description: Version of the FPGA configuration bitstream as printable string. + This file is read only. +Users: KEBA + +What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/0000:XX:XX.X/keep_cfg +Date: June 2024 +KernelVersion: 6.11 +Contact: Gerhard Engleder +Description: Flag which signals if FPGA shall keep or reload configuration + bitstream on reset. Normal FPGA behavior and default is to keep + configuration bitstream and to only reset the configured logic. + + Reloading configuration on reset enables an update of the + configuration bitstream with a simple reboot. Otherwise it is + necessary to power cycle the device to reload the new + configuration bitstream. + + This file is read/write. The values are as follows: + 1 = keep configuration bitstream on reset, default + 0 = reload configuration bitstream on reset +Users: KEBA diff --git a/Documentation/ABI/testing/sysfs-bus-iio-inv_icm42600 b/Documentation/ABI/testing/sysfs-bus-iio-inv_icm42600 new file mode 100644 index 000000000000..7eeacfb7650d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-inv_icm42600 @@ -0,0 +1,18 @@ +What: /sys/bus/iio/devices/iio:deviceX/in_accel_power_mode +KernelVersion: 6.11 +Contact: linux-iio@vger.kernel.org +Description: + Accelerometer power mode. Setting this attribute will set the + requested power mode to use if the ODR support it. If ODR + support only 1 mode, power mode will be enforced. + Reading this attribute will return the current accelerometer + power mode if the sensor is on, or the requested value if the + sensor is off. The value between real and requested value can + be different for ODR supporting only 1 mode. + +What: /sys/bus/iio/devices/iio:deviceX/in_accel_power_mode_available +KernelVersion: 6.11 +Contact: linux-iio@vger.kernel.org +Description: + List of available accelerometer power modes that can be set in + in_accel_power_mode attribute. diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd index 5a775b8f6543..fc82aa4e54b0 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd +++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd @@ -75,3 +75,13 @@ Description: The default value is 1 (GNU Remote Debug command). Other permissible value is 0 which is for vendor defined debug target. + +What: /sys/bus/pci/drivers/xhci_hcd/.../dbc_poll_interval_ms +Date: February 2024 +Contact: Mathias Nyman +Description: + This attribute adjust the polling interval used to check for + DbC events. Unit is milliseconds. Accepted values range from 0 + up to 5000. The default value is 64 ms. + This polling interval is used while DbC is enabled but has no + active data transfers. diff --git a/Documentation/PCI/endpoint/pci-endpoint.rst b/Documentation/PCI/endpoint/pci-endpoint.rst index 4f5622a65555..21507e3cc238 100644 --- a/Documentation/PCI/endpoint/pci-endpoint.rst +++ b/Documentation/PCI/endpoint/pci-endpoint.rst @@ -172,8 +172,8 @@ by the PCI endpoint function driver. * bind: ops to perform when a EPC device has been bound to EPF device * unbind: ops to perform when a binding has been lost between a EPC device and EPF device - * linkup: ops to perform when the EPC device has established a - connection with a host system + * add_cfs: optional ops to create function specific configfs + attributes The PCI Function driver can then register the PCI EPF driver by using pci_epf_register_driver(). diff --git a/Documentation/PCI/pciebus-howto.rst b/Documentation/PCI/pciebus-howto.rst index a0027e8fb0d0..f344452651e1 100644 --- a/Documentation/PCI/pciebus-howto.rst +++ b/Documentation/PCI/pciebus-howto.rst @@ -139,7 +139,7 @@ driver data structure. static struct pcie_port_service_driver root_aerdrv = { .name = (char *)device_name, - .id_table = &service_id[0], + .id_table = service_id, .probe = aerdrv_load, .remove = aerdrv_unload, diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1f77c701b878..fd8622aed1b7 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -792,6 +792,25 @@ Documentation/networking/netconsole.rst for an alternative. + :.[,options] + Use the specified serial port on the serial core bus. + The addressing uses DEVNAME of the physical serial port + device, followed by the serial core controller instance, + and the serial port instance. The options are the same + as documented for the ttyS addressing above. + + The mapping of the serial ports to the tty instances + can be viewed with: + + $ ls -d /sys/bus/serial-base/devices/*:*.*/tty/* + /sys/bus/serial-base/devices/00:04:0.0/tty/ttyS0 + + In the above example, the console can be addressed with + console=00:04:0.0. Note that a console addressed this + way will only get added when the related device driver + is ready. The use of an earlycon parameter in addition to + the console may be desired for console output early on. + uart[8250],io,[,options] uart[8250],mmio,[,options] uart[8250],mmio16,[,options] @@ -4549,6 +4568,38 @@ bridges without forcing it upstream. Note: this removes isolation between devices and may put more devices in an IOMMU group. + config_acs= + Format: + @[; ...] + Specify one or more PCI devices (in the format + specified above) optionally prepended with flags + and separated by semicolons. The respective + capabilities will be enabled, disabled or + unchanged based on what is specified in + flags. + + ACS Flags is defined as follows: + bit-0 : ACS Source Validation + bit-1 : ACS Translation Blocking + bit-2 : ACS P2P Request Redirect + bit-3 : ACS P2P Completion Redirect + bit-4 : ACS Upstream Forwarding + bit-5 : ACS P2P Egress Control + bit-6 : ACS Direct Translated P2P + Each bit can be marked as: + '0' – force disabled + '1' – force enabled + 'x' – unchanged + For example, + pci=config_acs=10x + would configure all devices that support + ACS to enable P2P Request Redirect, disable + Translation Blocking, and leave Source + Validation unchanged from whatever power-up + or firmware set it to. + + Note: this may remove isolation between devices + and may put more devices in an IOMMU group. force_floating [S390] Force usage of floating interrupts. nomio [S390] Do not use MIO instructions. norid [S390] ignore the RID field and force use of @@ -7041,6 +7092,9 @@ usb-storage.delay_use= [UMS] The delay in seconds before a new device is scanned for Logical Units (default 1). + Optionally the delay in milliseconds if the value has + suffix with "ms". + Example: delay_use=2567ms usb-storage.quirks= [UMS] A list of quirks entries to supplement or diff --git a/Documentation/devicetree/bindings/counter/ti-eqep.yaml b/Documentation/devicetree/bindings/counter/ti-eqep.yaml index 85f1ff83afe7..c882ab5fcf1f 100644 --- a/Documentation/devicetree/bindings/counter/ti-eqep.yaml +++ b/Documentation/devicetree/bindings/counter/ti-eqep.yaml @@ -11,7 +11,9 @@ maintainers: properties: compatible: - const: ti,am3352-eqep + enum: + - ti,am3352-eqep + - ti,am62-eqep reg: maxItems: 1 @@ -21,19 +23,35 @@ properties: maxItems: 1 clocks: - description: The clock that determines the SYSCLKOUT rate for the eQEP - peripheral. + description: The functional and interface clock that determines the clock + rate for the eQEP peripheral. maxItems: 1 clock-names: const: sysclkout + power-domains: + maxItems: 1 + +allOf: + - if: + properties: + compatible: + contains: + enum: + - ti,am62-eqep + then: + properties: + clock-names: false + + required: + - power-domains + required: - compatible - reg - interrupts - clocks - - clock-names additionalProperties: false @@ -43,7 +61,6 @@ examples: compatible = "ti,am3352-eqep"; reg = <0x180 0x80>; clocks = <&l4ls_gclk>; - clock-names = "sysclkout"; interrupts = <79>; }; diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml index 3c36cd0510de..e396e47b2f13 100644 --- a/Documentation/devicetree/bindings/eeprom/at24.yaml +++ b/Documentation/devicetree/bindings/eeprom/at24.yaml @@ -18,7 +18,9 @@ select: properties: compatible: contains: - pattern: "^atmel,(24(c|cs|mac)[0-9]+|spd)$" + anyOf: + - pattern: "^atmel,(24(c|cs|mac)[0-9]+|spd)$" + - enum: ["microchip,24aa025e48", "microchip,24aa025e64"] required: - compatible @@ -102,9 +104,6 @@ properties: pattern: spd$ # These are special cases that don't conform to the above pattern. # Each requires a standard at24 model as fallback. - - items: - - const: belling,bl24c16a - - const: atmel,24c16 - items: - enum: - rohm,br24g01 @@ -122,16 +121,25 @@ properties: - rohm,br24g04 - const: atmel,24c04 - items: - - const: renesas,r1ex24016 + - enum: + - belling,bl24c16a + - renesas,r1ex24016 - const: atmel,24c16 - items: - const: giantec,gt24c32a - const: atmel,24c32 + - items: + - const: onnn,n24s64b + - const: atmel,24c64 - items: - enum: - renesas,r1ex24128 - samsung,s524ad0xd1 - const: atmel,24c128 + - items: + - const: microchip,24aa025e48 + - items: + - const: microchip,24aa025e64 - pattern: '^atmel,24c(32|64)d-wl$' # Actual vendor is st label: diff --git a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml index 26bed558c6b8..c4cc8af18280 100644 --- a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml @@ -30,6 +30,9 @@ properties: clocks: minItems: 1 + power-domains: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml b/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml index b2d19cfb87ad..e61cdb5b16ef 100644 --- a/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/atmel,at91sam-i2c.yaml @@ -26,6 +26,7 @@ properties: - microchip,sam9x60-i2c - items: - enum: + - microchip,sama7d65-i2c - microchip,sama7g5-i2c - microchip,sam9x7-i2c - const: microchip,sam9x60-i2c @@ -36,12 +37,6 @@ properties: interrupts: maxItems: 1 - "#address-cells": - const: 1 - - "#size-cells": - const: 0 - clocks: maxItems: 1 @@ -72,8 +67,6 @@ required: - compatible - reg - interrupts - - "#address-cells" - - "#size-cells" - clocks allOf: @@ -86,6 +79,7 @@ allOf: - atmel,sama5d4-i2c - atmel,sama5d2-i2c - microchip,sam9x60-i2c + - microchip,sama7d65-i2c - microchip,sama7g5-i2c then: properties: diff --git a/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml b/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml index 7070c04469ed..ac9ddf228c82 100644 --- a/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml @@ -76,21 +76,21 @@ else: examples: - | - bsca: i2c@f0406200 { - clock-frequency = <390000>; - compatible = "brcm,brcmstb-i2c"; - interrupt-parent = <&irq0_intc>; - reg = <0xf0406200 0x58>; - interrupts = <0x18>; - interrupt-names = "upg_bsca"; - }; + bsca: i2c@f0406200 { + compatible = "brcm,brcmstb-i2c"; + reg = <0xf0406200 0x58>; + clock-frequency = <390000>; + interrupt-parent = <&irq0_intc>; + interrupts = <0x18>; + interrupt-names = "upg_bsca"; + }; - | - ddc0: i2c@7ef04500 { - compatible = "brcm,bcm2711-hdmi-i2c"; - reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>; - reg-names = "bsc", "auto-i2c"; - clock-frequency = <390000>; - }; + ddc0: i2c@7ef04500 { + compatible = "brcm,bcm2711-hdmi-i2c"; + reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>; + reg-names = "bsc", "auto-i2c"; + clock-frequency = <390000>; + }; ... diff --git a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml index b813f6d4810c..1eaf00b90a77 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.yaml @@ -109,65 +109,65 @@ examples: // Example for a bus to be demuxed. It contains various I2C clients for // HDMI, so the bus is named "i2c-hdmi": i2chdmi: i2c-mux3 { - compatible = "i2c-demux-pinctrl"; - i2c-parent = <&iic2>, <&i2c2>, <&gpioi2c2>; - i2c-bus-name = "i2c-hdmi"; - #address-cells = <1>; - #size-cells = <0>; + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&iic2>, <&i2c2>, <&gpioi2c2>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; - ak4643: codec@12 { - compatible = "asahi-kasei,ak4643"; - #sound-dai-cells = <0>; - reg = <0x12>; + ak4643: codec@12 { + compatible = "asahi-kasei,ak4643"; + #sound-dai-cells = <0>; + reg = <0x12>; + }; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin1ep0>; + }; }; + }; - composite-in@20 { - compatible = "adi,adv7180"; - reg = <0x20>; + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio1>; + interrupts = <15 IRQ_TYPE_LEVEL_LOW>; + clocks = <&cec_clock>; + clock-names = "cec"; - port { - adv7180: endpoint { - bus-width = <8>; - remote-endpoint = <&vin1ep0>; - }; + avdd-supply = <&fixedregulator1v8>; + dvdd-supply = <&fixedregulator1v8>; + pvdd-supply = <&fixedregulator1v8>; + dvdd-3v-supply = <&fixedregulator3v3>; + bgvdd-supply = <&fixedregulator1v8>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&lvds0_out>; }; - }; + }; - hdmi@39 { - compatible = "adi,adv7511w"; - reg = <0x39>; - interrupt-parent = <&gpio1>; - interrupts = <15 IRQ_TYPE_LEVEL_LOW>; - clocks = <&cec_clock>; - clock-names = "cec"; - - avdd-supply = <&fixedregulator1v8>; - dvdd-supply = <&fixedregulator1v8>; - pvdd-supply = <&fixedregulator1v8>; - dvdd-3v-supply = <&fixedregulator3v3>; - bgvdd-supply = <&fixedregulator1v8>; - - adi,input-depth = <8>; - adi,input-colorspace = "rgb"; - adi,input-clock = "1x"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - adv7511_in: endpoint { - remote-endpoint = <&lvds0_out>; - }; - }; - - port@1 { - reg = <1>; - adv7511_out: endpoint { - remote-endpoint = <&hdmi_con_out>; - }; - }; + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con_out>; }; + }; }; + }; }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt b/Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt deleted file mode 100644 index 4101aa621ad4..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt +++ /dev/null @@ -1,33 +0,0 @@ -NXP I2C controller for LPC2xxx/178x/18xx/43xx - -Required properties: - - compatible: must be "nxp,lpc1788-i2c" - - reg: physical address and length of the device registers - - interrupts: a single interrupt specifier - - clocks: clock for the device - - #address-cells: should be <1> - - #size-cells: should be <0> - -Optional properties: -- clock-frequency: the desired I2C bus clock frequency in Hz; in - absence of this property the default value is used (100 kHz). - -Example: -i2c0: i2c@400a1000 { - compatible = "nxp,lpc1788-i2c"; - reg = <0x400a1000 0x1000>; - interrupts = <18>; - clocks = <&ccu1 CLK_APB1_I2C0>; - #address-cells = <1>; - #size-cells = <0>; -}; - -&i2c0 { - clock-frequency = <400000>; - - lm75@48 { - compatible = "nxp,lm75"; - reg = <0x48>; - }; -}; - diff --git a/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml b/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml index 424a4fc218b6..92fbc1a2671a 100644 --- a/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml @@ -87,12 +87,6 @@ properties: interrupts: maxItems: 1 - '#address-cells': - const: 1 - - '#size-cells': - const: 0 - clocks: minItems: 1 maxItems: 2 diff --git a/Documentation/devicetree/bindings/i2c/nxp,lpc1788-i2c.yaml b/Documentation/devicetree/bindings/i2c/nxp,lpc1788-i2c.yaml new file mode 100644 index 000000000000..9a1b95c2d03c --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/nxp,lpc1788-i2c.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/nxp,lpc1788-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP I2C controller for LPC2xxx/178x/18xx/43xx + +maintainers: + - Vladimir Zapolskiy + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + const: nxp,lpc1788-i2c + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-frequency: + description: the desired I2C bus clock frequency in Hz + default: 100000 + + resets: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include "dt-bindings/clock/lpc18xx-ccu.h" + + i2c@400a1000 { + compatible = "nxp,lpc1788-i2c"; + reg = <0x400a1000 0x1000>; + interrupts = <18>; + clocks = <&ccu1 CLK_APB1_I2C0>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml b/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml index 17c1102562be..551cfa6f885a 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml +++ b/Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml @@ -44,11 +44,11 @@ examples: #include iic0: i2c@e0070000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "renesas,iic-emev2"; - reg = <0xe0070000 0x28>; - interrupts = ; - clocks = <&iic0_sclk>; - clock-names = "sclk"; + compatible = "renesas,iic-emev2"; + reg = <0xe0070000 0x28>; + interrupts = ; + clocks = <&iic0_sclk>; + clock-names = "sclk"; + #address-cells = <1>; + #size-cells = <0>; }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml b/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml index 51b220da461b..6cc60c3f61cd 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml @@ -153,14 +153,14 @@ examples: #include i2c0: i2c@e6508000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "renesas,i2c-r8a7791", "renesas,rcar-gen2-i2c"; - reg = <0xe6508000 0x40>; - interrupts = ; - clock-frequency = <400000>; - clocks = <&cpg CPG_MOD 931>; - power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; - resets = <&cpg 931>; - i2c-scl-internal-delay-ns = <6>; + compatible = "renesas,i2c-r8a7791", "renesas,rcar-gen2-i2c"; + reg = <0xe6508000 0x40>; + interrupts = ; + clock-frequency = <400000>; + clocks = <&cpg CPG_MOD 931>; + power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; + resets = <&cpg 931>; + i2c-scl-internal-delay-ns = <6>; + #address-cells = <1>; + #size-cells = <0>; }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,riic.yaml b/Documentation/devicetree/bindings/i2c/renesas,riic.yaml index 91ecf17b7a81..7993fe463c4c 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,riic.yaml +++ b/Documentation/devicetree/bindings/i2c/renesas,riic.yaml @@ -97,21 +97,21 @@ examples: #include i2c0: i2c@fcfee000 { - compatible = "renesas,riic-r7s72100", "renesas,riic-rz"; - reg = <0xfcfee000 0x44>; - interrupts = , - , - , - , - , - , - , - ; - interrupt-names = "tei", "ri", "ti", "spi", "sti", "naki", "ali", - "tmoi"; - clocks = <&mstp9_clks R7S72100_CLK_I2C0>; - clock-frequency = <100000>; - power-domains = <&cpg_clocks>; - #address-cells = <1>; - #size-cells = <0>; + compatible = "renesas,riic-r7s72100", "renesas,riic-rz"; + reg = <0xfcfee000 0x44>; + interrupts = , + , + , + , + , + , + , + ; + interrupt-names = "tei", "ri", "ti", "spi", "sti", "naki", "ali", + "tmoi"; + clocks = <&mstp9_clks R7S72100_CLK_I2C0>; + clock-frequency = <100000>; + power-domains = <&cpg_clocks>; + #address-cells = <1>; + #size-cells = <0>; }; diff --git a/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml b/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml index 04e4ffd80bc0..ec5222a1224f 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml +++ b/Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml @@ -134,16 +134,16 @@ examples: #include iic0: i2c@e6500000 { - compatible = "renesas,iic-r8a7790", "renesas,rcar-gen2-iic", - "renesas,rmobile-iic"; - reg = <0xe6500000 0x425>; - interrupts = ; - clocks = <&cpg CPG_MOD 318>; - clock-frequency = <400000>; - dmas = <&dmac0 0x61>, <&dmac0 0x62>, <&dmac1 0x61>, <&dmac1 0x62>; - dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; - resets = <&cpg 318>; - #address-cells = <1>; - #size-cells = <0>; + compatible = "renesas,iic-r8a7790", "renesas,rcar-gen2-iic", + "renesas,rmobile-iic"; + reg = <0xe6500000 0x425>; + interrupts = ; + clocks = <&cpg CPG_MOD 318>; + clock-frequency = <400000>; + dmas = <&dmac0 0x61>, <&dmac0 0x62>, <&dmac1 0x61>, <&dmac1 0x62>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 318>; + #address-cells = <1>; + #size-cells = <0>; }; diff --git a/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml b/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml index 1303502cf265..bbc568485627 100644 --- a/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/samsung,s3c2410-i2c.yaml @@ -26,9 +26,6 @@ properties: - samsung,exynos850-i2c - const: samsung,s3c2440-i2c - '#address-cells': - const: 1 - clocks: maxItems: 1 @@ -73,9 +70,6 @@ properties: $ref: /schemas/types.yaml#/definitions/phandle description: Pandle to syscon used to control the system registers. - '#size-cells': - const: 0 - required: - compatible - reg diff --git a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml index d9293c57f573..60035a787e5c 100644 --- a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml @@ -33,6 +33,10 @@ properties: - const: snps,designware-i2c - description: Baikal-T1 SoC System I2C controller const: baikal,bt1-sys-i2c + - description: T-HEAD TH1520 SoCs I2C controller + items: + - const: thead,th1520-i2c + - const: snps,designware-i2c reg: minItems: 1 diff --git a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml index 8fd8be76875e..457bb0702ed9 100644 --- a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml @@ -145,31 +145,31 @@ examples: #include #include //Example 1 (with st,stm32f4-i2c compatible) - i2c@40005400 { - compatible = "st,stm32f4-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40005400 0x400>; - interrupts = <31>, - <32>; - resets = <&rcc 277>; - clocks = <&rcc 0 149>; - }; + i2c@40005400 { + compatible = "st,stm32f4-i2c"; + reg = <0x40005400 0x400>; + interrupts = <31>, + <32>; + resets = <&rcc 277>; + clocks = <&rcc 0 149>; + #address-cells = <1>; + #size-cells = <0>; + }; - | #include #include //Example 2 (with st,stm32f7-i2c compatible) - i2c@40005800 { - compatible = "st,stm32f7-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40005800 0x400>; - interrupts = <31>, - <32>; - resets = <&rcc STM32F7_APB1_RESET(I2C1)>; - clocks = <&rcc 1 CLK_I2C1>; - }; + i2c@40005800 { + compatible = "st,stm32f7-i2c"; + reg = <0x40005800 0x400>; + interrupts = <31>, + <32>; + resets = <&rcc STM32F7_APB1_RESET(I2C1)>; + clocks = <&rcc 1 CLK_I2C1>; + #address-cells = <1>; + #size-cells = <0>; + }; - | #include @@ -178,16 +178,16 @@ examples: #include #include #include - i2c@40013000 { - compatible = "st,stm32mp15-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40013000 0x400>; - interrupts = , - ; - clocks = <&rcc I2C2_K>; - resets = <&rcc I2C2_R>; - i2c-scl-rising-time-ns = <185>; - i2c-scl-falling-time-ns = <20>; - st,syscfg-fmp = <&syscfg 0x4 0x2>; - }; + i2c@40013000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40013000 0x400>; + interrupts = , + ; + clocks = <&rcc I2C2_K>; + resets = <&rcc I2C2_R>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + st,syscfg-fmp = <&syscfg 0x4 0x2>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml b/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml index 781108ae1ce3..8c2e35fabf5b 100644 --- a/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml @@ -37,16 +37,8 @@ properties: clock-names: const: fck - clock-frequency: true - power-domains: true - "#address-cells": - const: 1 - - "#size-cells": - const: 0 - ti,hwmods: description: Must be "i2c", n being the instance number (1-based). @@ -55,38 +47,34 @@ properties: $ref: /schemas/types.yaml#/definitions/string deprecated: true -# subnode's properties -patternProperties: - "@[0-9a-f]+$": - type: object - description: - Flash device uses the below defined properties in the subnode. - required: - compatible - reg - interrupts -additionalProperties: false +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# -if: - properties: - compatible: - enum: - - ti,omap2420-i2c - - ti,omap2430-i2c - - ti,omap3-i2c - - ti,omap4-i2c + - if: + properties: + compatible: + enum: + - ti,omap2420-i2c + - ti,omap2430-i2c + - ti,omap3-i2c + - ti,omap4-i2c -then: - properties: - ti,hwmods: - items: - - pattern: "^i2c([1-9])$" + then: + properties: + ti,hwmods: + items: + - pattern: "^i2c([1-9])$" -else: - properties: - ti,hwmods: false + else: + properties: + ti,hwmods: false + +unevaluatedProperties: false examples: - | @@ -94,9 +82,9 @@ examples: #include main_i2c0: i2c@2000000 { - compatible = "ti,j721e-i2c", "ti,omap4-i2c"; - reg = <0x2000000 0x100>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - }; + compatible = "ti,j721e-i2c", "ti,omap4-i2c"; + reg = <0x2000000 0x100>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml index 36775f8f71df..8e7835cf36fd 100644 --- a/Documentation/devicetree/bindings/iio/adc/adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml @@ -38,6 +38,25 @@ properties: The first value specifies the positive input pin, the second specifies the negative input pin. + single-channel: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + When devices combine single-ended and differential channels, allow the + channel for a single element to be specified, independent of reg (as for + differential channels). If this and diff-channels are not present reg + shall be used instead. + + common-mode-channel: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Some ADCs have differential input pins that can be used to measure + single-ended or pseudo-differential inputs. This property can be used + in addition to single-channel to signal software that this channel is + not differential but still specify two inputs. + + The input pair is specified by setting single-channel to the positive + input pin and common-mode-channel to the negative pin. + settling-time-us: description: Time between enabling the channel and first stable readings. @@ -50,4 +69,15 @@ properties: device design and can interact with other characteristics such as settling time. +anyOf: + - oneOf: + - required: + - reg + - diff-channels + - required: + - reg + - single-channel + - required: + - reg + additionalProperties: true diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml index ea6cfcd0aff4..17c5d39cc2c1 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml @@ -19,7 +19,18 @@ description: | primarily for measurement of signals close to DC but also delivers outstanding performance with input bandwidths out to ~10kHz. + Analog Devices AD411x ADC's: + The AD411X family encompasses a series of low power, low noise, 24-bit, + sigma-delta analog-to-digital converters that offer a versatile range of + specifications. They integrate an analog front end suitable for processing + fully differential/single-ended and bipolar voltage inputs. + Datasheets for supported chips: + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4111.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4112.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4114.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4115.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD4116.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7172-2.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7172-4.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7173-8.pdf @@ -31,6 +42,11 @@ description: | properties: compatible: enum: + - adi,ad4111 + - adi,ad4112 + - adi,ad4114 + - adi,ad4115 + - adi,ad4116 - adi,ad7172-2 - adi,ad7172-4 - adi,ad7173-8 @@ -129,10 +145,56 @@ patternProperties: maximum: 15 diff-channels: + description: | + This property is used for defining the inputs of a differential + voltage channel. The first value is the positive input and the second + value is the negative input of the channel. + + Family AD411x supports a dedicated VINCOM voltage input. + To select it set the second channel to 16. + (VIN2, VINCOM) -> diff-channels = <2 16> + + There are special values that can be selected besides the voltage + analog inputs: + 21: REF+ + 22: REF− + + Supported only by AD7172-2, AD7172-4, AD7175-2, AD7175-8, AD7177-2, + must be paired together and can be used to monitor the power supply + of the ADC: + 19: ((AVDD1 − AVSS)/5)+ + 20: ((AVDD1 − AVSS)/5)− + items: minimum: 0 maximum: 31 + single-channel: + description: | + This property is used for defining a current channel or the positive + input of a voltage channel (single-ended or pseudo-differential). + + Models AD4111 and AD4112 support current channels. + Example: (IIN2+, IIN2−) -> single-channel = <2> + To correctly configure a current channel set the "adi,current-channel" + property to true. + + To configure a single-ended/pseudo-differential channel set the + "common-mode-channel" property to the desired negative voltage input. + + When used as a voltage channel, special inputs are valid as well. + minimum: 0 + maximum: 31 + + common-mode-channel: + description: + This property is used for defining the negative input of a + single-ended or pseudo-differential voltage channel. + + Special inputs are valid as well. + minimum: 0 + maximum: 31 + adi,reference-select: description: | Select the reference source to use when converting on @@ -154,9 +216,31 @@ patternProperties: - avdd default: refout-avss + adi,current-channel: + $ref: /schemas/types.yaml#/definitions/flag + description: | + Signal that the selected inputs are current channels. + Only available on AD4111 and AD4112. + required: - reg - - diff-channels + + allOf: + - oneOf: + - required: [single-channel] + properties: + diff-channels: false + - required: [diff-channels] + properties: + single-channel: false + adi,current-channel: false + common-mode-channel: false + + - if: + required: [common-mode-channel] + then: + properties: + adi,current-channel: false required: - compatible @@ -166,7 +250,6 @@ allOf: - $ref: /schemas/spi/spi-peripheral-props.yaml# # Only ad7172-4, ad7173-8 and ad7175-8 support vref2 - # Other models have [0-3] channel registers - if: properties: compatible: @@ -187,6 +270,37 @@ allOf: - vref - refout-avss - avdd + + - if: + properties: + compatible: + contains: + enum: + - adi,ad4114 + - adi,ad4115 + - adi,ad4116 + - adi,ad7173-8 + - adi,ad7175-8 + then: + patternProperties: + "^channel@[0-9a-f]$": + properties: + reg: + maximum: 15 + + - if: + properties: + compatible: + contains: + enum: + - adi,ad7172-2 + - adi,ad7175-2 + - adi,ad7176-2 + - adi,ad7177-2 + then: + patternProperties: + "^channel@[0-9a-f]$": + properties: reg: maximum: 3 @@ -210,6 +324,34 @@ allOf: required: - adi,reference-select + - if: + properties: + compatible: + contains: + enum: + - adi,ad4111 + - adi,ad4112 + - adi,ad4114 + - adi,ad4115 + - adi,ad4116 + then: + properties: + avdd2-supply: false + + - if: + properties: + compatible: + not: + contains: + enum: + - adi,ad4111 + - adi,ad4112 + then: + patternProperties: + "^channel@[0-9a-f]$": + properties: + adi,current-channel: false + - if: anyOf: - required: [clock-names] @@ -221,6 +363,7 @@ allOf: unevaluatedProperties: false examples: + # Example AD7173-8 with external reference connected to REF+/REF-: - | #include #include @@ -277,3 +420,50 @@ examples: }; }; }; + + # Example AD4111 with current channel and single-ended channel: + - | + #include + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad4111"; + reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "rdy"; + interrupt-parent = <&gpio>; + spi-max-frequency = <5000000>; + gpio-controller; + #gpio-cells = <2>; + #clock-cells = <0>; + + channel@0 { + reg = <0>; + bipolar; + diff-channels = <4 5>; + }; + + // Single ended channel VIN2/VINCOM + channel@1 { + reg = <1>; + bipolar; + single-channel = <2>; + common-mode-channel = <16>; + }; + + // Current channel IN2+/IN2- + channel@2 { + reg = <2>; + single-channel = <2>; + adi,current-channel; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml index 16def2985ab4..a03da9489ed9 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml @@ -21,8 +21,15 @@ properties: - adi,ad7190 - adi,ad7192 - adi,ad7193 + - adi,ad7194 - adi,ad7195 + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + reg: maxItems: 1 @@ -41,6 +48,11 @@ properties: interrupts: maxItems: 1 + aincom-supply: + description: | + AINCOM voltage supply. Analog inputs AINx are referenced to this input + when configured for pseudo-differential operation. + dvdd-supply: description: DVdd voltage supply @@ -84,6 +96,42 @@ properties: description: see Documentation/devicetree/bindings/iio/adc/adc.yaml type: boolean +patternProperties: + "^channel@[0-9a-f]+$": + type: object + $ref: adc.yaml + unevaluatedProperties: false + + properties: + reg: + description: The channel index. + minimum: 0 + maximum: 271 + + diff-channels: + description: + Both inputs can be connected to pins AIN1 to AIN16 by choosing the + appropriate value from 1 to 16. + items: + minimum: 1 + maximum: 16 + + single-channel: + description: + Positive input can be connected to pins AIN1 to AIN16 by choosing the + appropriate value from 1 to 16. Negative input is connected to AINCOM. + items: + minimum: 1 + maximum: 16 + + oneOf: + - required: + - reg + - diff-channels + - required: + - reg + - single-channel + required: - compatible - reg @@ -98,6 +146,17 @@ required: allOf: - $ref: /schemas/spi/spi-peripheral-props.yaml# + - if: + properties: + compatible: + enum: + - adi,ad7190 + - adi,ad7192 + - adi,ad7193 + - adi,ad7195 + then: + patternProperties: + "^channel@[0-9a-f]+$": false unevaluatedProperties: false @@ -117,6 +176,7 @@ examples: clock-names = "mclk"; interrupts = <25 0x2>; interrupt-parent = <&gpio>; + aincom-supply = <&aincom>; dvdd-supply = <&dvdd>; avdd-supply = <&avdd>; vref-supply = <&vref>; @@ -127,3 +187,38 @@ examples: adi,burnout-currents-enable; }; }; + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7194"; + reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + + spi-max-frequency = <1000000>; + spi-cpol; + spi-cpha; + clocks = <&ad7192_mclk>; + clock-names = "mclk"; + interrupts = <25 0x2>; + interrupt-parent = <&gpio>; + aincom-supply = <&aincom>; + dvdd-supply = <&dvdd>; + avdd-supply = <&avdd>; + vref-supply = <&vref>; + + channel@0 { + reg = <0>; + diff-channels = <1 6>; + }; + + channel@1 { + reg = <1>; + single-channel = <1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml new file mode 100644 index 000000000000..899b777017ce --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml @@ -0,0 +1,148 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7380.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices Simultaneous Sampling Analog to Digital Converters + +maintainers: + - Michael Hennerich + - Nuno Sá + +description: | + * https://www.analog.com/en/products/ad7380.html + * https://www.analog.com/en/products/ad7381.html + * https://www.analog.com/en/products/ad7383.html + * https://www.analog.com/en/products/ad7384.html + * https://www.analog.com/en/products/ad7380-4.html + * https://www.analog.com/en/products/ad7381-4.html + * https://www.analog.com/en/products/ad7383-4.html + * https://www.analog.com/en/products/ad7384-4.html + +$ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - adi,ad7380 + - adi,ad7381 + - adi,ad7383 + - adi,ad7384 + - adi,ad7380-4 + - adi,ad7381-4 + - adi,ad7383-4 + - adi,ad7384-4 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 80000000 + spi-cpol: true + spi-cpha: true + + vcc-supply: + description: A 3V to 3.6V supply that powers the chip. + + vlogic-supply: + description: + A 1.65V to 3.6V supply for the logic pins. + + refio-supply: + description: + A 2.5V to 3.3V supply for the external reference voltage. When omitted, + the internal 2.5V reference is used. + + aina-supply: + description: + The common mode voltage supply for the AINA- pin on pseudo-differential + chips. + + ainb-supply: + description: + The common mode voltage supply for the AINB- pin on pseudo-differential + chips. + + ainc-supply: + description: + The common mode voltage supply for the AINC- pin on pseudo-differential + chips. + + aind-supply: + description: + The common mode voltage supply for the AIND- pin on pseudo-differential + chips. + + interrupts: + description: + When the device is using 1-wire mode, this property is used to optionally + specify the ALERT interrupt. + maxItems: 1 + +required: + - compatible + - reg + - vcc-supply + - vlogic-supply + +unevaluatedProperties: false + +allOf: + # pseudo-differential chips require common mode voltage supplies, + # true differential chips don't use them + - if: + properties: + compatible: + enum: + - adi,ad7383 + - adi,ad7384 + - adi,ad7383-4 + - adi,ad7384-4 + then: + required: + - aina-supply + - ainb-supply + else: + properties: + aina-supply: false + ainb-supply: false + - if: + properties: + compatible: + enum: + - adi,ad7383-4 + - adi,ad7384-4 + then: + required: + - ainc-supply + - aind-supply + else: + properties: + ainc-supply: false + aind-supply: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7380"; + reg = <0>; + + spi-cpol; + spi-cpha; + spi-max-frequency = <80000000>; + + interrupts = <27 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio0>; + + vcc-supply = <&supply_3_3V>; + vlogic-supply = <&supply_3_3V>; + refio-supply = <&supply_2_5V>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml index 7fa46df1f4fb..00fdaed11cbd 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -11,6 +11,7 @@ maintainers: description: | Analog Devices AD7606 Simultaneous Sampling ADC + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7605-4.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf @@ -19,9 +20,9 @@ properties: compatible: enum: - adi,ad7605-4 - - adi,ad7606-8 - - adi,ad7606-6 - adi,ad7606-4 + - adi,ad7606-6 + - adi,ad7606-8 # Referred to as AD7606 (without -8) in the datasheet - adi,ad7606b - adi,ad7616 diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml index 7e8328e9ce13..f748f3a60b35 100644 --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml @@ -66,6 +66,9 @@ properties: nvmem-cell-names: const: temperature_calib + power-domains: + maxItems: 1 + allOf: - if: properties: diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,mt6359-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,mt6359-auxadc.yaml new file mode 100644 index 000000000000..6497c416094d --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/mediatek,mt6359-auxadc.yaml @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/mediatek,mt6359-auxadc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6350 series PMIC AUXADC + +maintainers: + - AngeloGioacchino Del Regno + +description: + The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found + in some MediaTek PMICs, performing various PMIC related measurements + such as battery and PMIC internal voltage regulators temperatures, + accessory detection resistance (usually, for a 3.5mm audio jack) + other than voltages for various PMIC internal components. + +properties: + compatible: + enum: + - mediatek,mt6357-auxadc + - mediatek,mt6358-auxadc + - mediatek,mt6359-auxadc + + "#io-channel-cells": + const: 1 + +required: + - compatible + - "#io-channel-cells" + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml index c1b1324fa132..2722edab1d9a 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml @@ -246,6 +246,10 @@ patternProperties: From common IIO binding. Used to pipe external sigma delta modulator or internal ADC output to DFSDM channel. + port: + $ref: /schemas/sound/audio-graph-port.yaml# + unevaluatedProperties: false + required: - compatible - "#sound-dai-cells" diff --git a/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml b/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml index d605999ffe28..718f633c6e04 100644 --- a/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml +++ b/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml @@ -18,6 +18,7 @@ properties: enum: - ti,ads1015 - ti,ads1115 + - ti,tla2021 - ti,tla2024 reg: diff --git a/Documentation/devicetree/bindings/iio/adc/ti,ads1119.yaml b/Documentation/devicetree/bindings/iio/adc/ti,ads1119.yaml new file mode 100644 index 000000000000..ba6850ab1f90 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,ads1119.yaml @@ -0,0 +1,155 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,ads1119.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments ADS1119 ADC + +maintainers: + - João Paulo Gonçalves + +description: + The TI ADS1119 is a precision 16-bit ADC over I2C that offers single-ended and + differential measurements using a multiplexed input. It features a programmable + gain, a programmable sample rate, an internal oscillator and voltage reference, + and a 50/60Hz rejection filter. + +properties: + compatible: + const: ti,ads1119 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + reset-gpios: + maxItems: 1 + + avdd-supply: true + dvdd-supply: true + + vref-supply: + description: + ADC external reference voltage (VREF). + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - avdd-supply + - dvdd-supply + +patternProperties: + "^channel@([0-6])$": + $ref: adc.yaml + type: object + properties: + reg: + minimum: 0 + maximum: 6 + + diff-channels: + description: + Differential input channels AIN0-AIN1, AIN2-AIN3 and AIN1-AIN2. + oneOf: + - items: + - const: 0 + - const: 1 + - items: + - const: 2 + - const: 3 + - items: + - const: 1 + - const: 2 + + single-channel: + description: + Single-ended input channels AIN0, AIN1, AIN2 and AIN3. + minimum: 0 + maximum: 3 + + oneOf: + - required: + - diff-channels + - required: + - single-channel + + required: + - reg + + unevaluatedProperties: false + +additionalProperties: false + +examples: + - | + + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + adc@40 { + compatible = "ti,ads1119"; + reg = <0x40>; + interrupt-parent = <&gpio1>; + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + avdd-supply = <®_avdd_ads1119>; + dvdd-supply = <®_dvdd_ads1119>; + vref-supply = <®_vref_ads1119>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + + channel@0 { + reg = <0>; + single-channel = <0>; + }; + + channel@1 { + reg = <1>; + diff-channels = <0 1>; + }; + + channel@2 { + reg = <2>; + single-channel = <3>; + }; + + channel@3 { + reg = <3>; + single-channel = <1>; + }; + + channel@4 { + reg = <4>; + single-channel = <2>; + }; + + channel@5 { + reg = <5>; + diff-channels = <1 2>; + }; + + channel@6 { + reg = <6>; + diff-channels = <2 3>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/chemical/sciosense,ens160.yaml b/Documentation/devicetree/bindings/iio/chemical/sciosense,ens160.yaml new file mode 100644 index 000000000000..267033a68abb --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/sciosense,ens160.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/chemical/sciosense,ens160.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ScioSense ENS160 multi-gas sensor + +maintainers: + - Gustavo Silva + +description: | + Digital Multi-Gas Sensor for Monitoring Indoor Air Quality. + + Datasheet: + https://www.sciosense.com/wp-content/uploads/2023/12/ENS160-Datasheet.pdf + +properties: + compatible: + enum: + - sciosense,ens160 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vdd-supply: true + vddio-supply: true + +required: + - compatible + - reg + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + gas-sensor@52 { + compatible = "sciosense,ens160"; + reg = <0x52>; + interrupt-parent = <&gpio0>; + interrupts = <19 IRQ_TYPE_EDGE_FALLING>; + }; + }; + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + gas-sensor@0 { + compatible = "sciosense,ens160"; + reg = <0>; + spi-max-frequency = <10000000>; + interrupt-parent = <&gpio>; + interrupts = <19 IRQ_TYPE_EDGE_FALLING>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml index 8265d709094d..fc8b97f82077 100644 --- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml +++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml @@ -13,13 +13,17 @@ maintainers: description: | Bindings for the Analog Devices AD3552R DAC device and similar. Datasheet can be found here: + https://www.analog.com/media/en/technical-documentation/data-sheets/ad3541r.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/ad3542r.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad3551r.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/ad3552r.pdf properties: compatible: enum: + - adi,ad3541r - adi,ad3542r + - adi,ad3551r - adi,ad3552r reg: @@ -92,13 +96,13 @@ patternProperties: maximum: 511 minimum: -511 - adi,gain-scaling-p-inv-log2: - description: GainP = 1 / ( 2 ^ adi,gain-scaling-p-inv-log2) + adi,gain-scaling-p: + description: GainP = 1 / ( 2 ^ adi,gain-scaling-p) $ref: /schemas/types.yaml#/definitions/uint32 enum: [0, 1, 2, 3] - adi,gain-scaling-n-inv-log2: - description: GainN = 1 / ( 2 ^ adi,gain-scaling-n-inv-log2) + adi,gain-scaling-n: + description: GainN = 1 / ( 2 ^ adi,gain-scaling-n) $ref: /schemas/types.yaml#/definitions/uint32 enum: [0, 1, 2, 3] @@ -107,8 +111,8 @@ patternProperties: required: - adi,gain-offset - - adi,gain-scaling-p-inv-log2 - - adi,gain-scaling-n-inv-log2 + - adi,gain-scaling-p + - adi,gain-scaling-n - adi,rfb-ohms required: @@ -128,7 +132,9 @@ allOf: properties: compatible: contains: - const: adi,ad3542r + enum: + - adi,ad3541r + - adi,ad3542r then: patternProperties: "^channel@([0-1])$": @@ -158,7 +164,9 @@ allOf: properties: compatible: contains: - const: adi,ad3552r + enum: + - adi,ad3551r + - adi,ad3552r then: patternProperties: "^channel@([0-1])$": @@ -182,6 +190,21 @@ allOf: - const: -10000000 - const: 10000000 + - if: + properties: + compatible: + contains: + enum: + - adi,ad3541r + - adi,ad3551r + then: + properties: + channel@1: false + channel@0: + properties: + reg: + const: 0 + required: - compatible - reg @@ -208,8 +231,8 @@ examples: reg = <1>; custom-output-range-config { adi,gain-offset = <5>; - adi,gain-scaling-p-inv-log2 = <1>; - adi,gain-scaling-n-inv-log2 = <2>; + adi,gain-scaling-p = <1>; + adi,gain-scaling-n = <2>; adi,rfb-ohms = <1>; }; }; diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,adf4350.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,adf4350.yaml index 43cbf27114c7..d1d1311332f8 100644 --- a/Documentation/devicetree/bindings/iio/frequency/adi,adf4350.yaml +++ b/Documentation/devicetree/bindings/iio/frequency/adi,adf4350.yaml @@ -28,6 +28,12 @@ properties: clock-names: const: clkin + '#clock-cells': + const: 0 + + clock-output-names: + maxItems: 1 + gpios: maxItems: 1 description: Lock detect GPIO. diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml index 9b7ad609f7db..9d185f7bfdcb 100644 --- a/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml @@ -30,12 +30,19 @@ properties: - adi,adis16467-2 - adi,adis16467-3 - adi,adis16500 + - adi,adis16501 - adi,adis16505-1 - adi,adis16505-2 - adi,adis16505-3 - adi,adis16507-1 - adi,adis16507-2 - adi,adis16507-3 + - adi,adis16575-2 + - adi,adis16575-3 + - adi,adis16576-2 + - adi,adis16576-3 + - adi,adis16577-2 + - adi,adis16577-3 reg: maxItems: 1 @@ -90,12 +97,19 @@ allOf: contains: enum: - adi,adis16500 + - adi,adis16501 - adi,adis16505-1 - adi,adis16505-2 - adi,adis16505-3 - adi,adis16507-1 - adi,adis16507-2 - adi,adis16507-3 + - adi,adis16575-2 + - adi,adis16575-3 + - adi,adis16576-2 + - adi,adis16576-3 + - adi,adis16577-2 + - adi,adis16577-3 then: properties: @@ -112,6 +126,23 @@ allOf: dependencies: adi,sync-mode: [ clocks ] + - if: + properties: + compatible: + contains: + enum: + - adi,adis16575-2 + - adi,adis16575-3 + - adi,adis16576-2 + - adi,adis16576-3 + - adi,adis16577-2 + - adi,adis16577-3 + + then: + properties: + spi-max-frequency: + maximum: 15000000 + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml index 56e0dc20f5e4..e3eec38897bf 100644 --- a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml @@ -23,6 +23,12 @@ properties: - adi,adis16497-1 - adi,adis16497-2 - adi,adis16497-3 + - adi,adis16545-1 + - adi,adis16545-2 + - adi,adis16545-3 + - adi,adis16547-1 + - adi,adis16547-2 + - adi,adis16547-3 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml index 47cfba939ca6..3b0a2d8b2e91 100644 --- a/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml +++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml @@ -16,7 +16,11 @@ description: | properties: compatible: - const: bosch,bmi160 + oneOf: + - const: bosch,bmi160 + - items: + - const: bosch,bmi120 + - const: bosch,bmi160 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml b/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml index 91c318746bf3..ecf2339e02f6 100644 --- a/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml +++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml @@ -4,14 +4,19 @@ $id: http://devicetree.org/schemas/iio/light/vishay,veml6075.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Vishay VEML6075 UVA and UVB sensor +title: Vishay VEML6075 UVA/B and VEML6040 RGBW sensors maintainers: - Javier Carrasco +description: + VEML6040 datasheet at https://www.vishay.com/docs/84276/veml6040.pdf + properties: compatible: - const: vishay,veml6075 + enum: + - vishay,veml6040 + - vishay,veml6075 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml index fff7e3d83a02..71c1ee33a393 100644 --- a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml +++ b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml @@ -26,6 +26,7 @@ properties: - st,lis2dw12 - st,lis2hh12 - st,lis2dh12-accel + - st,lis2ds12 - st,lis302dl - st,lis331dl-accel - st,lis331dlh-accel diff --git a/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt deleted file mode 100644 index 513d94d6e899..000000000000 --- a/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt +++ /dev/null @@ -1,60 +0,0 @@ -TI-NSPIRE Keypad - -Required properties: -- compatible: Compatible property value should be "ti,nspire-keypad". - -- reg: Physical base address of the peripheral and length of memory mapped - region. - -- interrupts: The interrupt number for the peripheral. - -- scan-interval: How often to scan in us. Based on a APB speed of 33MHz, the - maximum and minimum delay time is ~2000us and ~500us respectively - -- row-delay: How long to wait before scanning each row. - -- clocks: The clock this peripheral is attached to. - -- linux,keymap: The keymap to use - (see Documentation/devicetree/bindings/input/matrix-keymap.txt) - -Optional properties: -- active-low: Specify that the keypad is active low (i.e. logical low signifies - a key press). - -Example: - -input { - compatible = "ti,nspire-keypad"; - reg = <0x900E0000 0x1000>; - interrupts = <16>; - - scan-interval = <1000>; - row-delay = <200>; - - clocks = <&apb_pclk>; - - linux,keymap = < - 0x0000001c 0x0001001c 0x00040039 - 0x0005002c 0x00060015 0x0007000b - 0x0008000f 0x0100002d 0x01010011 - 0x0102002f 0x01030004 0x01040016 - 0x01050014 0x0106001f 0x01070002 - 0x010a006a 0x02000013 0x02010010 - 0x02020019 0x02030007 0x02040018 - 0x02050031 0x02060032 0x02070005 - 0x02080028 0x0209006c 0x03000026 - 0x03010025 0x03020024 0x0303000a - 0x03040017 0x03050023 0x03060022 - 0x03070008 0x03080035 0x03090069 - 0x04000021 0x04010012 0x04020020 - 0x0404002e 0x04050030 0x0406001e - 0x0407000d 0x04080037 0x04090067 - 0x05010038 0x0502000c 0x0503001b - 0x05040034 0x0505001a 0x05060006 - 0x05080027 0x0509000e 0x050a006f - 0x0600002b 0x0602004e 0x06030068 - 0x06040003 0x0605006d 0x06060009 - 0x06070001 0x0609000f 0x0708002a - 0x0709001d 0x070a0033 >; -}; diff --git a/Documentation/devicetree/bindings/input/ti,nspire-keypad.yaml b/Documentation/devicetree/bindings/input/ti,nspire-keypad.yaml new file mode 100644 index 000000000000..ed3cfff13add --- /dev/null +++ b/Documentation/devicetree/bindings/input/ti,nspire-keypad.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/ti,nspire-keypad.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI-NSPIRE Keypad + +maintainers: + - Andrew Davis + +allOf: + - $ref: input.yaml# + - $ref: matrix-keymap.yaml# + +properties: + compatible: + enum: + - ti,nspire-keypad + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + scan-interval: + $ref: /schemas/types.yaml#/definitions/uint32 + description: How often to scan in us. Based on a APB speed of 33MHz, the + maximum and minimum delay time is ~2000us and ~500us respectively + + row-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: How long to wait between scanning each row in us. + + active-low: + description: Specify that the keypad is active low. + +required: + - compatible + - reg + - interrupts + - clocks + - scan-interval + - row-delay + - linux,keymap + +unevaluatedProperties: false + +examples: + - | + #include + keypad@900e0000 { + compatible = "ti,nspire-keypad"; + reg = <0x900e0000 0x1000>; + interrupts = <16>; + + clocks = <&apb_pclk>; + + scan-interval = <1000>; + row-delay = <200>; + + linux,keymap = < + MATRIX_KEY(0, 0, KEY_ENTER) + MATRIX_KEY(0, 1, KEY_ENTER) + MATRIX_KEY(0, 4, KEY_SPACE) + MATRIX_KEY(0, 5, KEY_Z) + MATRIX_KEY(0, 6, KEY_Y) + MATRIX_KEY(0, 7, KEY_0) + >; + }; diff --git a/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt b/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt index 81f6bda97d3c..399c87782935 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ads7846.txt @@ -57,6 +57,7 @@ Optional properties: pendown-gpio (u32). pendown-gpio GPIO handle describing the pin the !PENIRQ line is connected to. + ti,hsync-gpios GPIO line to poll for hsync wakeup-source use any event on touchscreen as wakeup event. (Legacy property support: "linux,wakeup") touchscreen-size-x General touchscreen binding, see [1]. diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml index 745e57c05176..379721027bf8 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml @@ -39,6 +39,7 @@ properties: - edt,edt-ft5406 - edt,edt-ft5506 - evervision,ev-ft5726 + - focaltech,ft5426 - focaltech,ft5452 - focaltech,ft6236 - focaltech,ft8719 diff --git a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml index 9dc25d30a0a8..1c7ae05a8c15 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml @@ -14,10 +14,14 @@ allOf: properties: compatible: - enum: - - eeti,exc3000 - - eeti,exc80h60 - - eeti,exc80h84 + oneOf: + - const: eeti,exc3000 + - const: eeti,exc80h60 + - const: eeti,exc80h84 + - items: + - enum: + - eeti,exc81w32 + - const: eeti,exc80h84 reg: const: 0x2a interrupts: diff --git a/Documentation/devicetree/bindings/input/touchscreen/ektf2127.txt b/Documentation/devicetree/bindings/input/touchscreen/ektf2127.txt deleted file mode 100644 index c9f2c9f578e3..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/ektf2127.txt +++ /dev/null @@ -1,25 +0,0 @@ -* Elan eKTF2127 I2C touchscreen controller - -Required properties: - - compatible : "elan,ektf2127" or "elan,ektf2132" - - reg : I2C slave address of the chip (0x40) - - interrupts : interrupt specification for the ektf2127 interrupt - - power-gpios : GPIO specification for the pin connected to the - ektf2127's wake input. This needs to be driven high - to take ektf2127 out of its low power state - -For additional optional properties see: touchscreen.txt - -Example: - -i2c@00000000 { - ektf2127: touchscreen@15 { - compatible = "elan,ektf2127"; - reg = <0x15>; - interrupt-parent = <&pio>; - interrupts = <6 11 IRQ_TYPE_EDGE_FALLING> - power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; - touchscreen-inverted-x; - touchscreen-swapped-x-y; - }; -}; diff --git a/Documentation/devicetree/bindings/input/touchscreen/elan,ektf2127.yaml b/Documentation/devicetree/bindings/input/touchscreen/elan,ektf2127.yaml new file mode 100644 index 000000000000..ff0ec3fd24c5 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/elan,ektf2127.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/touchscreen/elan,ektf2127.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Elan eKTF2127 I2C touchscreen controller + +maintainers: + - Siebren Vroegindeweij + +allOf: + - $ref: touchscreen.yaml# + +properties: + compatible: + enum: + - elan,ektf2127 + - elan,ektf2132 + - elan,ektf2232 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + power-gpios: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - power-gpios + +unevaluatedProperties: false + +examples: + - | + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + touchscreen@15 { + compatible = "elan,ektf2127"; + reg = <0x15>; + interrupt-parent = <&pio>; + interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>; + power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; + touchscreen-inverted-x; + touchscreen-swapped-x-y; + }; + }; +... diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml b/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml index f42b23d532eb..f5cfacb5e966 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml @@ -15,6 +15,7 @@ allOf: properties: compatible: enum: + - himax,hx83100a - himax,hx83112b reg: diff --git a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml index 77ba280b3bdc..e24cbd960993 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml @@ -16,6 +16,7 @@ properties: compatible: enum: - imagis,ist3032c + - imagis,ist3038 - imagis,ist3038b - imagis,ist3038c diff --git a/Documentation/devicetree/bindings/interconnect/mediatek,mt8183-emi.yaml b/Documentation/devicetree/bindings/interconnect/mediatek,mt8183-emi.yaml new file mode 100644 index 000000000000..017c8478b2a7 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/mediatek,mt8183-emi.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/mediatek,mt8183-emi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek External Memory Interface (EMI) Interconnect + +maintainers: + - AngeloGioacchino Del Regno + +description: | + EMI interconnect providers support system bandwidth requirements through + Dynamic Voltage Frequency Scaling Resource Collector (DVFSRC) hardware. + The provider is able to communicate with the DVFSRC through Secure Monitor + Call (SMC). + + ICC provider ICC Nodes + ---- ---- + _________ |CPU | |--- |VPU | + _____ | |----- ---- | ---- + | |->| DRAM | ---- | ---- + |DRAM |->|scheduler|----- |GPU | |--- |DISP| + | |->| (EMI) | ---- | ---- + |_____|->|_________|---. ----- | ---- + /|\ `-|MMSYS|--|--- |VDEC| + | ----- | ---- + | | ---- + | change DRAM freq |--- |VENC| + -------- | ---- + SMC --> | DVFSRC | | ---- + -------- |--- |IMG | + | ---- + | ---- + |--- |CAM | + ---- + +properties: + compatible: + enum: + - mediatek,mt8183-emi + - mediatek,mt8195-emi + + '#interconnect-cells': + const: 1 + +required: + - compatible + - '#interconnect-cells' + +unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8953.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8953.yaml new file mode 100644 index 000000000000..732e9fa001a4 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8953.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,msm8953.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm MSM8953 Network-On-Chip interconnect + +maintainers: + - Barnabas Czeman + +description: | + The Qualcomm MSM8953 interconnect providers support adjusting the + bandwidth requirements between the various NoC fabrics. + + See also: + - dt-bindings/interconnect/qcom,msm8953.h + +properties: + compatible: + enum: + - qcom,msm8953-bimc + - qcom,msm8953-pcnoc + - qcom,msm8953-snoc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + maxItems: 1 + + '#interconnect-cells': + const: 2 + +patternProperties: + '^interconnect-[a-z0-9\-]+$': + type: object + $ref: qcom,rpm-common.yaml# + unevaluatedProperties: false + description: + The interconnect providers do not have a separate QoS register space, + but share parent's space. + + properties: + compatible: + const: qcom,msm8953-snoc-mm + + required: + - compatible + - '#interconnect-cells' + +required: + - compatible + - reg + - '#interconnect-cells' + +allOf: + - $ref: qcom,rpm-common.yaml# + - if: + properties: + compatible: + const: qcom,msm8953-pcnoc + + then: + properties: + clocks: + items: + - description: PCNOC USB3 AXI Clock. + + clock-names: + const: pcnoc_usb3_axi + + required: + - clocks + - clock-names + else: + properties: + clocks: false + clock-names: false + +additionalProperties: false + +examples: + - | + #include + + snoc: interconnect@580000 { + compatible = "qcom,msm8953-snoc"; + reg = <0x580000 0x16080>; + + #interconnect-cells = <2>; + + snoc_mm: interconnect-snoc { + compatible = "qcom,msm8953-snoc-mm"; + + #interconnect-cells = <2>; + }; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml index b135597d9489..9fce7203bd42 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml @@ -35,6 +35,10 @@ properties: reg: maxItems: 1 + clocks: + minItems: 1 + maxItems: 2 + required: - compatible @@ -53,10 +57,50 @@ allOf: required: - reg + - if: + properties: + compatible: + contains: + enum: + - qcom,sc7280-aggre1-noc + then: + properties: + clocks: + items: + - description: aggre UFS PHY AXI clock + - description: aggre USB3 PRIM AXI clock + + - if: + properties: + compatible: + contains: + enum: + - qcom,sc7280-aggre2-noc + then: + properties: + clocks: + items: + - description: RPMH CC IPA clock + + - if: + properties: + compatible: + contains: + enum: + - qcom,sc7280-aggre1-noc + - qcom,sc7280-aggre2-noc + then: + required: + - clocks + else: + properties: + clocks: false + unevaluatedProperties: false examples: - | + #include interconnect { compatible = "qcom,sc7280-clk-virt"; #interconnect-cells = <2>; @@ -69,3 +113,12 @@ examples: #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; + + interconnect@16e0000 { + reg = <0x016e0000 0x1c080>; + compatible = "qcom,sc7280-aggre1-noc"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + clocks = <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>; + }; diff --git a/Documentation/devicetree/bindings/misc/qemu,vcpu-stall-detector.yaml b/Documentation/devicetree/bindings/misc/qemu,vcpu-stall-detector.yaml index 1aebeb696ee0..e12d80be00cd 100644 --- a/Documentation/devicetree/bindings/misc/qemu,vcpu-stall-detector.yaml +++ b/Documentation/devicetree/bindings/misc/qemu,vcpu-stall-detector.yaml @@ -29,6 +29,9 @@ properties: Defaults to 10 if unset. default: 10 + interrupts: + maxItems: 1 + timeout-sec: description: | The stall detector expiration timeout measured in seconds. @@ -43,9 +46,12 @@ additionalProperties: false examples: - | + #include + vmwdt@9030000 { compatible = "qemu,vcpu-stall-detector"; reg = <0x9030000 0x10000>; clock-frequency = <10>; timeout-sec = <8>; + interrupts = ; }; diff --git a/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml b/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml index 9801fe6f91b5..99ddc9a4af05 100644 --- a/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml @@ -28,6 +28,9 @@ properties: description: phandle to the secure-monitor node $ref: /schemas/types.yaml#/definitions/phandle + power-domains: + maxItems: 1 + required: - compatible - clocks diff --git a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml index cf5f9e22bb7e..32b8c1eb4e80 100644 --- a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml @@ -28,7 +28,9 @@ properties: - enum: - mediatek,mt7622-efuse - mediatek,mt7623-efuse + - mediatek,mt7981-efuse - mediatek,mt7986-efuse + - mediatek,mt7988-efuse - mediatek,mt8173-efuse - mediatek,mt8183-efuse - mediatek,mt8186-efuse diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml b/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml index 6fba42156db6..c41608863d6c 100644 --- a/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml @@ -13,6 +13,35 @@ description: |+ MediaTek MT7621 PCIe subsys supports a single Root Complex (RC) with 3 Root Ports. Each Root Port supports a Gen1 1-lane Link + MT7621 PCIe HOST Topology + + .-------. + | | + | CPU | + | | + '-------' + | + | + | + v + .------------------. + .-----------| HOST/PCI Bridge |------------. + | '------------------' | Type1 + BUS0 | | | Access + v v v On Bus0 + .-------------. .-------------. .-------------. + | VIRTUAL P2P | | VIRTUAL P2P | | VIRTUAL P2P | + | BUS0 | | BUS0 | | BUS0 | + | DEV0 | | DEV1 | | DEV2 | + '-------------' '-------------' '-------------' + Type0 | Type0 | Type0 | + Access BUS1 | Access BUS2| Access BUS3| + On Bus1 v On Bus2 v On Bus3 v + .----------. .----------. .----------. + | Device 0 | | Device 0 | | Device 0 | + | Func 0 | | Func 0 | | Func 0 | + '----------' '----------' '----------' + allOf: - $ref: /schemas/pci/pci-host-bridge.yaml# diff --git a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml index 5d7aec5f54e7..612633ba59e2 100644 --- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml +++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml @@ -10,21 +10,13 @@ maintainers: - Daire McNamara allOf: - - $ref: /schemas/pci/pci-host-bridge.yaml# + - $ref: plda,xpressrich3-axi-common.yaml# - $ref: /schemas/interrupt-controller/msi-controller.yaml# properties: compatible: const: microchip,pcie-host-1.0 # PolarFire - reg: - maxItems: 2 - - reg-names: - items: - - const: cfg - - const: apb - clocks: description: Fabric Interface Controllers, FICs, are the interface between the FPGA @@ -52,18 +44,6 @@ properties: items: pattern: '^fic[0-3]$' - interrupts: - minItems: 1 - items: - - description: PCIe host controller - - description: builtin MSI controller - - interrupt-names: - minItems: 1 - items: - - const: pcie - - const: msi - ranges: minItems: 1 maxItems: 3 @@ -72,39 +52,6 @@ properties: minItems: 1 maxItems: 6 - msi-controller: - description: Identifies the node as an MSI controller. - - msi-parent: - description: MSI controller the device is capable of using. - - interrupt-controller: - type: object - properties: - '#address-cells': - const: 0 - - '#interrupt-cells': - const: 1 - - interrupt-controller: true - - required: - - '#address-cells' - - '#interrupt-cells' - - interrupt-controller - - additionalProperties: false - -required: - - reg - - reg-names - - "#interrupt-cells" - - interrupts - - interrupt-map-mask - - interrupt-map - - msi-controller - unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml new file mode 100644 index 000000000000..7a57a80052a0 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/plda,xpressrich3-axi-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PLDA XpressRICH PCIe host common properties + +maintainers: + - Daire McNamara + - Kevin Xie + +description: + Generic PLDA XpressRICH PCIe host common properties. + +allOf: + - $ref: /schemas/pci/pci-host-bridge.yaml# + +properties: + reg: + maxItems: 2 + + reg-names: + items: + - const: cfg + - const: apb + + interrupts: + minItems: 1 + items: + - description: PCIe host controller + - description: builtin MSI controller + + interrupt-names: + minItems: 1 + items: + - const: pcie + - const: msi + + msi-controller: + description: Identifies the node as an MSI controller. + + msi-parent: + description: MSI controller the device is capable of using. + + interrupt-controller: + type: object + properties: + '#address-cells': + const: 0 + + '#interrupt-cells': + const: 1 + + interrupt-controller: true + + required: + - '#address-cells' + - '#interrupt-cells' + - interrupt-controller + + additionalProperties: false + +required: + - reg + - reg-names + - interrupts + - msi-controller + - "#interrupt-cells" + - interrupt-map-mask + - interrupt-map + +additionalProperties: true + +... diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml index a223ce029cab..46802f7d9482 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml @@ -13,6 +13,7 @@ properties: compatible: oneOf: - enum: + - qcom,sa8775p-pcie-ep - qcom,sdx55-pcie-ep - qcom,sm8450-pcie-ep - items: @@ -20,6 +21,7 @@ properties: - const: qcom,sdx55-pcie-ep reg: + minItems: 6 items: - description: Qualcomm-specific PARF configuration registers - description: DesignWare PCIe registers @@ -27,8 +29,10 @@ properties: - description: Address Translation Unit (ATU) registers - description: Memory region used to map remote RC address space - description: BAR memory region + - description: DMA register space reg-names: + minItems: 6 items: - const: parf - const: dbi @@ -36,13 +40,14 @@ properties: - const: atu - const: addr_space - const: mmio + - const: dma clocks: - minItems: 7 + minItems: 5 maxItems: 8 clock-names: - minItems: 7 + minItems: 5 maxItems: 8 qcom,perst-regs: @@ -57,14 +62,18 @@ properties: - description: Perst separation enable offset interrupts: + minItems: 2 items: - description: PCIe Global interrupt - description: PCIe Doorbell interrupt + - description: DMA interrupt interrupt-names: + minItems: 2 items: - const: global - const: doorbell + - const: dma reset-gpios: description: GPIO used as PERST# input signal @@ -125,6 +134,10 @@ allOf: - qcom,sdx55-pcie-ep then: properties: + reg: + maxItems: 6 + reg-names: + maxItems: 6 clocks: items: - description: PCIe Auxiliary clock @@ -143,6 +156,10 @@ allOf: - const: slave_q2a - const: sleep - const: ref + interrupts: + maxItems: 2 + interrupt-names: + maxItems: 2 - if: properties: @@ -152,6 +169,10 @@ allOf: - qcom,sm8450-pcie-ep then: properties: + reg: + maxItems: 6 + reg-names: + maxItems: 6 clocks: items: - description: PCIe Auxiliary clock @@ -172,6 +193,45 @@ allOf: - const: ref - const: ddrss_sf_tbu - const: aggre_noc_axi + interrupts: + maxItems: 2 + interrupt-names: + maxItems: 2 + + - if: + properties: + compatible: + contains: + enum: + - qcom,sa8775p-pcie-ep + then: + properties: + reg: + minItems: 7 + maxItems: 7 + reg-names: + minItems: 7 + maxItems: 7 + clocks: + items: + - description: PCIe Auxiliary clock + - description: PCIe CFG AHB clock + - description: PCIe Master AXI clock + - description: PCIe Slave AXI clock + - description: PCIe Slave Q2A AXI clock + clock-names: + items: + - const: aux + - const: cfg + - const: bus_master + - const: bus_slave + - const: slave_q2a + interrupts: + minItems: 3 + maxItems: 3 + interrupt-names: + minItems: 3 + maxItems: 3 unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml index 1496d6993ab4..d8c0afaa4b19 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml @@ -69,6 +69,10 @@ properties: - const: msi6 - const: msi7 + operating-points-v2: true + opp-table: + type: object + resets: maxItems: 1 diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml index 1074310a8e7a..a9db0a231563 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml @@ -19,11 +19,10 @@ properties: const: qcom,pcie-x1e80100 reg: - minItems: 5 + minItems: 6 maxItems: 6 reg-names: - minItems: 5 items: - const: parf # Qualcomm specific registers - const: dbi # DesignWare PCIe registers diff --git a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie-common.yaml b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie-common.yaml new file mode 100644 index 000000000000..cc9adfc7611c --- /dev/null +++ b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie-common.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/rockchip-dw-pcie-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DesignWare based PCIe RC/EP controller on Rockchip SoCs + +maintainers: + - Shawn Lin + - Simon Xue + - Heiko Stuebner + +description: |+ + Generic properties for the DesignWare based PCIe RC/EP controller on Rockchip + SoCs. + +properties: + clocks: + minItems: 5 + items: + - description: AHB clock for PCIe master + - description: AHB clock for PCIe slave + - description: AHB clock for PCIe dbi + - description: APB clock for PCIe + - description: Auxiliary clock for PCIe + - description: PIPE clock + - description: Reference clock for PCIe + + clock-names: + minItems: 5 + items: + - const: aclk_mst + - const: aclk_slv + - const: aclk_dbi + - const: pclk + - const: aux + - const: pipe + - const: ref + + interrupts: + minItems: 5 + items: + - description: + Combined system interrupt, which is used to signal the following + interrupts - phy_link_up, dll_link_up, link_req_rst_not, hp_pme, + hp, hp_msi, link_auto_bw, link_auto_bw_msi, bw_mgt, bw_mgt_msi, + edma_wr, edma_rd, dpa_sub_upd, rbar_update, link_eq_req, ep_elbi_app + - description: + Combined PM interrupt, which is used to signal the following + interrupts - linkst_in_l1sub, linkst_in_l1, linkst_in_l2, + linkst_in_l0s, linkst_out_l1sub, linkst_out_l1, linkst_out_l2, + linkst_out_l0s, pm_dstate_update + - description: + Combined message interrupt, which is used to signal the following + interrupts - ven_msg, unlock_msg, ltr_msg, cfg_pme, cfg_pme_msi, + pm_pme, pm_to_ack, pm_turnoff, obff_idle, obff_obff, obff_cpu_active + - description: + Combined legacy interrupt, which is used to signal the following + interrupts - inta, intb, intc, intd, tx_inta, tx_intb, tx_intc, + tx_intd + - description: + Combined error interrupt, which is used to signal the following + interrupts - aer_rc_err, aer_rc_err_msi, rx_cpl_timeout, + tx_cpl_timeout, cor_err_sent, nf_err_sent, f_err_sent, cor_err_rx, + nf_err_rx, f_err_rx, radm_qoverflow + - description: + eDMA write channel 0 interrupt + - description: + eDMA write channel 1 interrupt + - description: + eDMA read channel 0 interrupt + - description: + eDMA read channel 1 interrupt + + interrupt-names: + minItems: 5 + items: + - const: sys + - const: pmc + - const: msg + - const: legacy + - const: err + - const: dma0 + - const: dma1 + - const: dma2 + - const: dma3 + + num-lanes: true + + phys: + maxItems: 1 + + phy-names: + const: pcie-phy + + power-domains: + maxItems: 1 + + resets: + minItems: 1 + maxItems: 2 + + reset-names: + oneOf: + - const: pipe + - items: + - const: pwr + - const: pipe + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - num-lanes + - phys + - phy-names + - power-domains + - resets + - reset-names + +additionalProperties: true + +... diff --git a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie-ep.yaml new file mode 100644 index 000000000000..f2d1137aff50 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie-ep.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/rockchip-dw-pcie-ep.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DesignWare based PCIe Endpoint controller on Rockchip SoCs + +maintainers: + - Niklas Cassel + +description: |+ + RK3588 SoC PCIe Endpoint controller is based on the Synopsys DesignWare + PCIe IP and thus inherits all the common properties defined in + snps,dw-pcie-ep.yaml. + +allOf: + - $ref: /schemas/pci/snps,dw-pcie-ep.yaml# + - $ref: /schemas/pci/rockchip-dw-pcie-common.yaml# + +properties: + compatible: + enum: + - rockchip,rk3568-pcie-ep + - rockchip,rk3588-pcie-ep + + reg: + items: + - description: Data Bus Interface (DBI) registers + - description: Data Bus Interface (DBI) shadow registers + - description: Rockchip designed configuration registers + - description: Memory region used to map remote RC address space + - description: Internal Address Translation Unit (iATU) registers + + reg-names: + items: + - const: dbi + - const: dbi2 + - const: apb + - const: addr_space + - const: atu + +required: + - interrupts + - interrupt-names + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + pcie3x4_ep: pcie-ep@fe150000 { + compatible = "rockchip,rk3588-pcie-ep"; + reg = <0xa 0x40000000 0x0 0x00100000>, + <0xa 0x40100000 0x0 0x00100000>, + <0x0 0xfe150000 0x0 0x00010000>, + <0x9 0x00000000 0x0 0x40000000>, + <0xa 0x40300000 0x0 0x00100000>; + reg-names = "dbi", "dbi2", "apb", "addr_space", "atu"; + clocks = <&cru ACLK_PCIE_4L_MSTR>, <&cru ACLK_PCIE_4L_SLV>, + <&cru ACLK_PCIE_4L_DBI>, <&cru PCLK_PCIE_4L>, + <&cru CLK_PCIE_AUX0>, <&cru CLK_PCIE4L_PIPE>; + clock-names = "aclk_mst", "aclk_slv", + "aclk_dbi", "pclk", + "aux", "pipe"; + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "sys", "pmc", "msg", "legacy", "err", + "dma0", "dma1", "dma2", "dma3"; + max-link-speed = <3>; + num-lanes = <4>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; + power-domains = <&power RK3588_PD_PCIE>; + resets = <&cru SRST_PCIE0_POWER_UP>, <&cru SRST_P_PCIE0>; + reset-names = "pwr", "pipe"; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml index 5f719218c472..550d8a684af3 100644 --- a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/pci/rockchip-dw-pcie.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: DesignWare based PCIe controller on Rockchip SoCs +title: DesignWare based PCIe Root Complex controller on Rockchip SoCs maintainers: - Shawn Lin @@ -12,12 +12,13 @@ maintainers: - Heiko Stuebner description: |+ - RK3568 SoC PCIe host controller is based on the Synopsys DesignWare + RK3568 SoC PCIe Root Complex controller is based on the Synopsys DesignWare PCIe IP and thus inherits all the common properties defined in snps,dw-pcie.yaml. allOf: - $ref: /schemas/pci/snps,dw-pcie.yaml# + - $ref: /schemas/pci/rockchip-dw-pcie-common.yaml# properties: compatible: @@ -40,61 +41,6 @@ properties: - const: apb - const: config - clocks: - minItems: 5 - items: - - description: AHB clock for PCIe master - - description: AHB clock for PCIe slave - - description: AHB clock for PCIe dbi - - description: APB clock for PCIe - - description: Auxiliary clock for PCIe - - description: PIPE clock - - description: Reference clock for PCIe - - clock-names: - minItems: 5 - items: - - const: aclk_mst - - const: aclk_slv - - const: aclk_dbi - - const: pclk - - const: aux - - const: pipe - - const: ref - - interrupts: - items: - - description: - Combined system interrupt, which is used to signal the following - interrupts - phy_link_up, dll_link_up, link_req_rst_not, hp_pme, - hp, hp_msi, link_auto_bw, link_auto_bw_msi, bw_mgt, bw_mgt_msi, - edma_wr, edma_rd, dpa_sub_upd, rbar_update, link_eq_req, ep_elbi_app - - description: - Combined PM interrupt, which is used to signal the following - interrupts - linkst_in_l1sub, linkst_in_l1, linkst_in_l2, - linkst_in_l0s, linkst_out_l1sub, linkst_out_l1, linkst_out_l2, - linkst_out_l0s, pm_dstate_update - - description: - Combined message interrupt, which is used to signal the following - interrupts - ven_msg, unlock_msg, ltr_msg, cfg_pme, cfg_pme_msi, - pm_pme, pm_to_ack, pm_turnoff, obff_idle, obff_obff, obff_cpu_active - - description: - Combined legacy interrupt, which is used to signal the following - interrupts - inta, intb, intc, intd - - description: - Combined error interrupt, which is used to signal the following - interrupts - aer_rc_err, aer_rc_err_msi, rx_cpl_timeout, - tx_cpl_timeout, cor_err_sent, nf_err_sent, f_err_sent, cor_err_rx, - nf_err_rx, f_err_rx, radm_qoverflow - - interrupt-names: - items: - - const: sys - - const: pmc - - const: msg - - const: legacy - - const: err - legacy-interrupt-controller: description: Interrupt controller node for handling legacy PCI interrupts. type: object @@ -119,47 +65,14 @@ properties: msi-map: true - num-lanes: true - - phys: - maxItems: 1 - - phy-names: - const: pcie-phy - - power-domains: - maxItems: 1 - ranges: minItems: 2 maxItems: 3 - resets: - minItems: 1 - maxItems: 2 - - reset-names: - oneOf: - - const: pipe - - items: - - const: pwr - - const: pipe - vpcie3v3-supply: true required: - - compatible - - reg - - reg-names - - clocks - - clock-names - msi-map - - num-lanes - - phys - - phy-names - - power-domains - - resets - - reset-names unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml index bbdb01d22848..f474b9e3fc7e 100644 --- a/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml +++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml @@ -100,7 +100,7 @@ properties: for new bindings. oneOf: - description: See native 'elbi/app' CSR region for details. - enum: [ link, appl ] + enum: [ apb, link, appl ] - description: See native 'atu' CSR region for details. enum: [ atu_dma ] allOf: @@ -151,12 +151,21 @@ properties: Application-specific IRQ raised depending on the vendor-specific events basis. const: app + - description: + Interrupts triggered when the controller itself (in Endpoint mode) + has sent an Assert_INT{A,B,C,D}/Desassert_INT{A,B,C,D} message to + the upstream device. + pattern: "^tx_int(a|b|c|d)$" + - description: + Combined interrupt signal raised when the controller has sent an + Assert_INT{A,B,C,D} message. See "^tx_int(a|b|c|d)$" for details. + const: legacy - description: Vendor-specific IRQ names. Consider using the generic names above for new bindings. oneOf: - description: See native "app" IRQ for details - enum: [ intr ] + enum: [ intr, sys, pmc, msg, err ] max-functions: maximum: 32 diff --git a/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml new file mode 100644 index 000000000000..67151aaa3948 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml @@ -0,0 +1,120 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/starfive,jh7110-pcie.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JH7110 PCIe host controller + +maintainers: + - Kevin Xie + +allOf: + - $ref: plda,xpressrich3-axi-common.yaml# + +properties: + compatible: + const: starfive,jh7110-pcie + + clocks: + items: + - description: NOC bus clock + - description: Transport layer clock + - description: AXI MST0 clock + - description: APB clock + + clock-names: + items: + - const: noc + - const: tl + - const: axi_mst0 + - const: apb + + resets: + items: + - description: AXI MST0 reset + - description: AXI SLAVE0 reset + - description: AXI SLAVE reset + - description: PCIE BRIDGE reset + - description: PCIE CORE reset + - description: PCIE APB reset + + reset-names: + items: + - const: mst0 + - const: slv0 + - const: slv + - const: brg + - const: core + - const: apb + + starfive,stg-syscon: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + The phandle to System Register Controller syscon node. + + perst-gpios: + description: GPIO controlled connection to PERST# signal + maxItems: 1 + + phys: + description: + Specified PHY is attached to PCIe controller. + maxItems: 1 + +required: + - clocks + - resets + - starfive,stg-syscon + +unevaluatedProperties: false + +examples: + - | + #include + soc { + #address-cells = <2>; + #size-cells = <2>; + + pcie@940000000 { + compatible = "starfive,jh7110-pcie"; + reg = <0x9 0x40000000 0x0 0x10000000>, + <0x0 0x2b000000 0x0 0x1000000>; + reg-names = "cfg", "apb"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>, + <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>; + starfive,stg-syscon = <&stg_syscon>; + bus-range = <0x0 0xff>; + interrupt-parent = <&plic>; + interrupts = <56>; + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>, + <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>, + <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>, + <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>; + msi-controller; + clocks = <&syscrg 86>, + <&stgcrg 10>, + <&stgcrg 8>, + <&stgcrg 9>; + clock-names = "noc", "tl", "axi_mst0", "apb"; + resets = <&stgcrg 11>, + <&stgcrg 12>, + <&stgcrg 13>, + <&stgcrg 14>, + <&stgcrg 15>, + <&stgcrg 16>; + perst-gpios = <&gpios 26 GPIO_ACTIVE_LOW>; + phys = <&pciephy0>; + + pcie_intc0: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml b/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml index 4770ce02fcc3..989fb0fa2577 100644 --- a/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml +++ b/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml @@ -92,7 +92,7 @@ examples: <0 0 0 3 &pcie_intc_0 2>, <0 0 0 4 &pcie_intc_0 3>; bus-range = <0x00 0xff>; - ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>, + ranges = <0x02000000 0x0 0xe0010000 0x0 0xe0010000 0x0 0x10000000>, <0x43000000 0x80 0x00000000 0x80 0x00000000 0x0 0x80000000>; msi-map = <0x0 &its_gic 0x0 0x10000>; reg = <0x0 0xfca10000 0x0 0x1000>, diff --git a/Documentation/devicetree/bindings/serial/mediatek,uart.yaml b/Documentation/devicetree/bindings/serial/mediatek,uart.yaml index 303d02ca4e1b..ff61ffdcad1d 100644 --- a/Documentation/devicetree/bindings/serial/mediatek,uart.yaml +++ b/Documentation/devicetree/bindings/serial/mediatek,uart.yaml @@ -37,6 +37,7 @@ properties: - mediatek,mt7623-uart - mediatek,mt7629-uart - mediatek,mt7986-uart + - mediatek,mt7988-uart - mediatek,mt8127-uart - mediatek,mt8135-uart - mediatek,mt8173-uart diff --git a/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml index 5dec15b7e7c3..88871480018e 100644 --- a/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml +++ b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.yaml @@ -28,6 +28,9 @@ properties: clocks: maxItems: 1 + reset-gpios: + maxItems: 1 + clock-frequency: description: When there is no clock provider visible to the platform, this @@ -91,6 +94,7 @@ unevaluatedProperties: false examples: - | #include + #include i2c { #address-cells = <1>; #size-cells = <0>; @@ -120,6 +124,7 @@ examples: compatible = "nxp,sc16is752"; reg = <0x54>; clocks = <&clk20m>; + reset-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; interrupt-parent = <&gpio3>; interrupts = <7 IRQ_TYPE_EDGE_FALLING>; nxp,modem-control-line-ports = <0 1>; /* Ports 0 and 1 as modem control lines */ diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml index f3a3eb2831e9..afc7c05898a1 100644 --- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml @@ -9,9 +9,6 @@ title: Renesas Serial Communication Interface with FIFO (SCIF) maintainers: - Geert Uytterhoeven -allOf: - - $ref: serial.yaml# - properties: compatible: oneOf: @@ -83,6 +80,8 @@ properties: - renesas,scif-r9a08g045 # RZ/G3S - const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback + - const: renesas,scif-r9a09g057 # RZ/V2H(P) + reg: maxItems: 1 @@ -90,11 +89,6 @@ properties: oneOf: - items: - description: A combined interrupt - - items: - - description: Error interrupt - - description: Receive buffer full interrupt - - description: Transmit buffer empty interrupt - - description: Break interrupt - items: - description: Error interrupt - description: Receive buffer full interrupt @@ -102,21 +96,23 @@ properties: - description: Break interrupt - description: Data Ready interrupt - description: Transmit End interrupt + - description: Transmit End/Data Ready interrupt + - description: Receive buffer full interrupt (EDGE trigger) + - description: Transmit buffer empty interrupt (EDGE trigger) + minItems: 4 interrupt-names: - oneOf: - - items: - - const: eri - - const: rxi - - const: txi - - const: bri - - items: - - const: eri - - const: rxi - - const: txi - - const: bri - - const: dri - - const: tei + minItems: 4 + items: + - const: eri + - const: rxi + - const: txi + - const: bri + - const: dri + - const: tei + - const: tei-dri + - const: rxi-edge + - const: txi-edge clocks: minItems: 1 @@ -161,18 +157,92 @@ required: - clock-names - power-domains -if: - properties: - compatible: - contains: - enum: - - renesas,rcar-gen2-scif - - renesas,rcar-gen3-scif - - renesas,rcar-gen4-scif - - renesas,scif-r9a07g044 -then: - required: - - resets +allOf: + - $ref: serial.yaml# + + - if: + properties: + compatible: + contains: + enum: + - renesas,rcar-gen2-scif + - renesas,rcar-gen3-scif + - renesas,rcar-gen4-scif + - renesas,scif-r9a07g044 + - renesas,scif-r9a09g057 + then: + required: + - resets + + - if: + properties: + compatible: + contains: + enum: + - renesas,rcar-gen1-scif + - renesas,rcar-gen2-scif + - renesas,rcar-gen3-scif + - renesas,rcar-gen4-scif + then: + properties: + interrupts: + maxItems: 1 + + interrupt-names: false + else: + required: + - interrupt-names + + - if: + properties: + compatible: + contains: + enum: + - renesas,scif-r7s72100 + then: + properties: + interrupts: + minItems: 4 + maxItems: 4 + + interrupt-names: + maxItems: 4 + + - if: + properties: + compatible: + contains: + enum: + - renesas,scif-r7s9210 + - renesas,scif-r9a07g044 + then: + properties: + interrupts: + minItems: 6 + maxItems: 6 + + interrupt-names: + minItems: 6 + maxItems: 6 + + - if: + properties: + compatible: + contains: + const: renesas,scif-r9a09g057 + then: + properties: + clocks: + maxItems: 1 + + clock-names: + maxItems: 1 + + interrupts: + minItems: 9 + + interrupt-names: + minItems: 9 unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml index 1001d2a6ace8..4cdb0dcaccf3 100644 --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml @@ -13,6 +13,20 @@ allOf: - $ref: serial.yaml# - $ref: rs485.yaml# + - if: + properties: + compatible: + contains: + const: starfive,jh7110-uart + then: + properties: + resets: + minItems: 2 + else: + properties: + resets: + maxItems: 1 + properties: compatible: oneOf: @@ -48,6 +62,7 @@ properties: - enum: - starfive,jh7100-hsuart - starfive,jh7100-uart + - starfive,jh7110-uart - const: snps,dw-apb-uart - const: snps,dw-apb-uart @@ -82,7 +97,8 @@ properties: type: boolean resets: - maxItems: 1 + minItems: 1 + maxItems: 2 reg-shift: true diff --git a/Documentation/devicetree/bindings/serial/via,vt8500-uart.yaml b/Documentation/devicetree/bindings/serial/via,vt8500-uart.yaml new file mode 100644 index 000000000000..9c6819241a49 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/via,vt8500-uart.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/serial/via,vt8500-uart.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: VIA VT8500 and WonderMedia WM8xxx UART Controller + +maintainers: + - Alexey Charkov + +allOf: + - $ref: serial.yaml + +properties: + compatible: + enum: + - via,vt8500-uart # up to WM8850/WM8950 + - wm,wm8880-uart # for WM8880 and later + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + reg: + maxItems: 1 + +required: + - compatible + - clocks + - interrupts + - reg + +unevaluatedProperties: false + +examples: + - | + serial@d8200000 { + compatible = "via,vt8500-uart"; + reg = <0xd8200000 0x1040>; + interrupts = <32>; + clocks = <&clkuart0>; + }; diff --git a/Documentation/devicetree/bindings/serial/vt8500-uart.txt b/Documentation/devicetree/bindings/serial/vt8500-uart.txt deleted file mode 100644 index 2b64e6107fb3..000000000000 --- a/Documentation/devicetree/bindings/serial/vt8500-uart.txt +++ /dev/null @@ -1,27 +0,0 @@ -* VIA VT8500 and WonderMedia WM8xxx UART Controller - -Required properties: -- compatible: should be "via,vt8500-uart" (for VIA/WonderMedia chips up to and - including WM8850/WM8950), or "wm,wm8880-uart" (for WM8880 and later) - -- reg: base physical address of the controller and length of memory mapped - region. - -- interrupts: hardware interrupt number - -- clocks: shall be the input parent clock phandle for the clock. This should - be the 24Mhz reference clock. - -Aliases may be defined to ensure the correct ordering of the uarts. - -Example: - aliases { - serial0 = &uart0; - }; - - uart0: serial@d8200000 { - compatible = "via,vt8500-uart"; - reg = <0xd8200000 0x1040>; - interrupts = <32>; - clocks = <&clkuart0>; - }; diff --git a/Documentation/devicetree/bindings/usb/cdns,usb3.yaml b/Documentation/devicetree/bindings/usb/cdns,usb3.yaml index 69a93a0722f0..f454ddd9bbaa 100644 --- a/Documentation/devicetree/bindings/usb/cdns,usb3.yaml +++ b/Documentation/devicetree/bindings/usb/cdns,usb3.yaml @@ -42,8 +42,11 @@ properties: - const: otg - const: wakeup - dr_mode: - enum: [host, otg, peripheral] + port: + $ref: /schemas/graph.yaml#/properties/port + description: + This port is used with the 'usb-role-switch' property to connect the + cdns3 to type C connector. maximum-speed: enum: [super-speed, high-speed, full-speed] @@ -70,6 +73,9 @@ properties: description: Enable resetting of PHY if Rx fail is detected type: boolean +dependencies: + port: [ usb-role-switch ] + required: - compatible - reg @@ -77,7 +83,10 @@ required: - interrupts - interrupt-names -additionalProperties: false +allOf: + - $ref: usb-drd.yaml# + +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml index 4f36a22aa6d7..a5f2e3442a0e 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.yaml +++ b/Documentation/devicetree/bindings/usb/dwc2.yaml @@ -188,7 +188,7 @@ required: - clocks - clock-names -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/usb/fsl,usb2.yaml b/Documentation/devicetree/bindings/usb/fsl,usb2.yaml new file mode 100644 index 000000000000..caedf11db284 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/fsl,usb2.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/fsl,usb2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale SOC USB controllers + +maintainers: + - Frank Li + +description: | + The device node for a USB controller that is part of a Freescale + SOC is as described in the document "Open Firmware Recommended + Practice: Universal Serial Bus" with the following modifications + and additions. + +properties: + compatible: + oneOf: + - enum: + - fsl-usb2-mph + - fsl-usb2-dr + - items: + - enum: + - fsl-usb2-dr-v2.2 + - fsl-usb2-dr-v2.5 + - const: fsl-usb2-dr + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + phy_type: + $ref: /schemas/types.yaml#/definitions/string + enum: [ulpi, serial, utmi, utmi_wide] + + port0: + $ref: /schemas/types.yaml#/definitions/flag + description: + Indicates port0 is connected for fsl-usb2-mph compatible controllers. + + port1: + $ref: /schemas/types.yaml#/definitions/flag + description: + Indicates port1 is connected for "fsl-usb2-mph" compatible controllers. + + fsl,invert-drvvbus: + $ref: /schemas/types.yaml#/definitions/flag + description: + for MPC5121 USB0 only. Indicates the + port power polarity of internal PHY signal DRVVBUS is inverted. + + fsl,invert-pwr-fault: + $ref: /schemas/types.yaml#/definitions/flag + description: + for MPC5121 USB0 only. Indicates + the PWR_FAULT signal polarity is inverted. + +required: + - compatible + - reg + - interrupts + - phy_type + +allOf: + - $ref: usb-drd.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + usb@22000 { + compatible = "fsl-usb2-mph"; + reg = <22000 1000>; + interrupts = <27 IRQ_TYPE_EDGE_RISING>; + phy_type = "ulpi"; + port0; + port1; + }; + + - | + #include + + usb@23000 { + compatible = "fsl-usb2-dr"; + reg = <23000 1000>; + interrupts = <26 IRQ_TYPE_EDGE_RISING>; + dr_mode = "otg"; + phy_type = "ulpi"; + }; diff --git a/Documentation/devicetree/bindings/usb/fsl-usb.txt b/Documentation/devicetree/bindings/usb/fsl-usb.txt deleted file mode 100644 index 0b08b006c5ea..000000000000 --- a/Documentation/devicetree/bindings/usb/fsl-usb.txt +++ /dev/null @@ -1,81 +0,0 @@ -Freescale SOC USB controllers - -The device node for a USB controller that is part of a Freescale -SOC is as described in the document "Open Firmware Recommended -Practice : Universal Serial Bus" with the following modifications -and additions : - -Required properties : - - compatible : Should be "fsl-usb2-mph" for multi port host USB - controllers, or "fsl-usb2-dr" for dual role USB controllers - or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121. - Wherever applicable, the IP version of the USB controller should - also be mentioned (for eg. fsl-usb2-dr-v2.2 for bsc9132). - - phy_type : For multi port host USB controllers, should be one of - "ulpi", or "serial". For dual role USB controllers, should be - one of "ulpi", "utmi", "utmi_wide", or "serial". - - reg : Offset and length of the register set for the device - - port0 : boolean; if defined, indicates port0 is connected for - fsl-usb2-mph compatible controllers. Either this property or - "port1" (or both) must be defined for "fsl-usb2-mph" compatible - controllers. - - port1 : boolean; if defined, indicates port1 is connected for - fsl-usb2-mph compatible controllers. Either this property or - "port0" (or both) must be defined for "fsl-usb2-mph" compatible - controllers. - - dr_mode : indicates the working mode for "fsl-usb2-dr" compatible - controllers. Can be "host", "peripheral", or "otg". Default to - "host" if not defined for backward compatibility. - -Recommended properties : - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - -Optional properties : - - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the - port power polarity of internal PHY signal DRVVBUS is inverted. - - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates - the PWR_FAULT signal polarity is inverted. - -Example multi port host USB controller device node : - usb@22000 { - compatible = "fsl-usb2-mph"; - reg = <22000 1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupt-parent = <700>; - interrupts = <27 1>; - phy_type = "ulpi"; - port0; - port1; - }; - -Example dual role USB controller device node : - usb@23000 { - compatible = "fsl-usb2-dr"; - reg = <23000 1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupt-parent = <700>; - interrupts = <26 1>; - dr_mode = "otg"; - phy = "ulpi"; - }; - -Example dual role USB controller device node for MPC5121ADS: - - usb@4000 { - compatible = "fsl,mpc5121-usb2-dr"; - reg = <0x4000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupt-parent = < &ipic >; - interrupts = <44 0x8>; - dr_mode = "otg"; - phy_type = "utmi_wide"; - fsl,invert-drvvbus; - fsl,invert-pwr-fault; - }; diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml index 37cf5249e526..fc833363cfb4 100644 --- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml +++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml @@ -9,9 +9,6 @@ title: Genesys Logic USB hub controller maintainers: - Icenowy Zheng -allOf: - - $ref: usb-device.yaml# - properties: compatible: enum: @@ -27,17 +24,44 @@ properties: vdd-supply: description: - the regulator that provides 3.3V core power to the hub. + The regulator that provides 3.3V or 5.0V core power to the hub. peer-hub: $ref: /schemas/types.yaml#/definitions/phandle description: - phandle to the peer hub on the controller. + For onboard hub controllers that support USB 3.x and USB 2.0 hubs + with shared resets and power supplies, this property is used to identify + the hubs with which these are shared. required: - compatible - reg +allOf: + - $ref: usb-device.yaml# + - if: + properties: + compatible: + contains: + enum: + - usb5e3,608 + then: + properties: + peer-hub: false + vdd-supply: false + + - if: + properties: + compatible: + contains: + enum: + - usb5e3,610 + - usb5e3,620 + then: + properties: + peer-hub: true + vdd-supply: true + additionalProperties: false examples: @@ -54,3 +78,29 @@ examples: reset-gpios = <&pio 7 2 GPIO_ACTIVE_LOW>; }; }; + + - | + #include + usb { + dr_mode = "host"; + #address-cells = <1>; + #size-cells = <0>; + + /* 2.0 hub on port 1 */ + hub_2_0: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + peer-hub = <&hub_3_0>; + reset-gpios = <&gpio 20 GPIO_ACTIVE_LOW>; + vdd-supply = <&vcc_5v>; + }; + + /* 3.1 hub on port 4 */ + hub_3_0: hub@2 { + compatible = "usb5e3,620"; + reg = <2>; + peer-hub = <&hub_2_0>; + reset-gpios = <&gpio 20 GPIO_ACTIVE_LOW>; + vdd-supply = <&vcc_5v>; + }; + }; diff --git a/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml b/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml index 88e1607cf053..8a5f837eff94 100644 --- a/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml +++ b/Documentation/devicetree/bindings/usb/gpio-sbu-mux.yaml @@ -22,6 +22,7 @@ properties: - nxp,cbdtu02043 - onnn,fsusb43l10x - pericom,pi3usb102 + - ti,tmuxhs4212 - const: gpio-sbu-mux enable-gpios: @@ -44,13 +45,18 @@ properties: required: - compatible - - enable-gpios - select-gpios - orientation-switch - port allOf: - $ref: usb-switch.yaml# + - if: + required: + - mode-switch + then: + required: + - enable-gpios additionalProperties: false diff --git a/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml b/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml index c5e9ce2e7bc2..27b909de4992 100644 --- a/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml +++ b/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml @@ -34,6 +34,13 @@ properties: clocks: maxItems: 1 + microchip,ext-vbus-drv: + description: + Some ULPI USB PHYs do not support an internal VBUS supply and driving + the CPEN pin requires the configuration of the UPLI_USE__EXTVBUS + bit in ULPI_BUSCONTROL. + $ref: /schemas/types.yaml#/definitions/flag + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index cf633d488c3f..efde47a5b145 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -30,6 +30,8 @@ properties: - qcom,sa8775p-dwc3 - qcom,sc7180-dwc3 - qcom,sc7280-dwc3 + - qcom,sc8180x-dwc3 + - qcom,sc8180x-dwc3-mp - qcom,sc8280xp-dwc3 - qcom,sc8280xp-dwc3-mp - qcom,sdm660-dwc3 @@ -334,6 +336,8 @@ allOf: contains: enum: - qcom,qcm2290-dwc3 + - qcom,sc8180x-dwc3 + - qcom,sc8180x-dwc3-mp - qcom,sm6115-dwc3 - qcom,sm6125-dwc3 - qcom,sm8150-dwc3 @@ -448,6 +452,7 @@ allOf: - qcom,sa8775p-dwc3 - qcom,sc7180-dwc3 - qcom,sc7280-dwc3 + - qcom,sc8180x-dwc3 - qcom,sc8280xp-dwc3 - qcom,sdm670-dwc3 - qcom,sdm845-dwc3 @@ -475,6 +480,30 @@ allOf: - const: dm_hs_phy_irq - const: ss_phy_irq + - if: + properties: + compatible: + contains: + enum: + - qcom,sc8180x-dwc3-mp + then: + properties: + interrupts: + minItems: 10 + maxItems: 10 + interrupt-names: + items: + - const: pwr_event_1 + - const: pwr_event_2 + - const: hs_phy_1 + - const: hs_phy_2 + - const: dp_hs_phy_1 + - const: dm_hs_phy_1 + - const: dp_hs_phy_2 + - const: dm_hs_phy_2 + - const: ss_phy_1 + - const: ss_phy_2 + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index db06afedd818..928e687385ab 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1270,6 +1270,8 @@ patternProperties: description: Schindler "^schneider,.*": description: Schneider Electric + "^sciosense,.*": + description: ScioSense B.V. "^seagate,.*": description: Seagate Technology PLC "^seeed,.*": diff --git a/Documentation/driver-api/dmaengine/client.rst b/Documentation/driver-api/dmaengine/client.rst index ecf139f73da4..d491e385d61a 100644 --- a/Documentation/driver-api/dmaengine/client.rst +++ b/Documentation/driver-api/dmaengine/client.rst @@ -80,6 +80,10 @@ The details of these operations are: - slave_sg: DMA a list of scatter gather buffers from/to a peripheral + - peripheral_dma_vec: DMA an array of scatter gather buffers from/to a + peripheral. Similar to slave_sg, but uses an array of dma_vec + structures instead of a scatterlist. + - dma_cyclic: Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. @@ -102,6 +106,11 @@ The details of these operations are: unsigned int sg_len, enum dma_data_direction direction, unsigned long flags); + struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec( + struct dma_chan *chan, const struct dma_vec *vecs, + size_t nents, enum dma_data_direction direction, + unsigned long flags); + struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); diff --git a/Documentation/driver-api/dmaengine/provider.rst b/Documentation/driver-api/dmaengine/provider.rst index ceac2a300e32..3085f8b460fa 100644 --- a/Documentation/driver-api/dmaengine/provider.rst +++ b/Documentation/driver-api/dmaengine/provider.rst @@ -433,6 +433,12 @@ supported. - residue: Provides the residue bytes of the transfer for those that support residue. +- ``device_prep_peripheral_dma_vec`` + + - Similar to ``device_prep_slave_sg``, but it takes a pointer to a + array of ``dma_vec`` structures, which (in the long run) will replace + scatterlists. + - ``device_issue_pending`` - Takes the first transaction descriptor in the pending queue, @@ -544,6 +550,10 @@ dma_cookie_t - Not really relevant any more since the introduction of ``virt-dma`` that abstracts it away. +dma_vec + +- A small structure that contains a DMA address and length. + DMA_CTRL_ACK - If clear, the descriptor cannot be reused by provider until the diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst index 10eced6c2e46..c840b597912c 100644 --- a/Documentation/i2c/busses/i2c-i801.rst +++ b/Documentation/i2c/busses/i2c-i801.rst @@ -48,6 +48,7 @@ Supported adapters: * Intel Raptor Lake (PCH) * Intel Meteor Lake (SOC and PCH) * Intel Birch Stream (SOC) + * Intel Arrow Lake (SOC) Datasheets: Publicly available at the Intel website diff --git a/Documentation/i2c/slave-testunit-backend.rst b/Documentation/i2c/slave-testunit-backend.rst index ecfc2abec32d..37142a48ab35 100644 --- a/Documentation/i2c/slave-testunit-backend.rst +++ b/Documentation/i2c/slave-testunit-backend.rst @@ -16,9 +16,9 @@ Note that this is a device for testing and debugging. It should not be enabled in a production build. And while there is some versioning and we try hard to keep backward compatibility, there is no stable ABI guaranteed! -Instantiating the device is regular. Example for bus 0, address 0x30: +Instantiating the device is regular. Example for bus 0, address 0x30:: -# echo "slave-testunit 0x1030" > /sys/bus/i2c/devices/i2c-0/new_device + # echo "slave-testunit 0x1030" > /sys/bus/i2c/devices/i2c-0/new_device After that, you will have a write-only device listening. Reads will just return an 8-bit version number of the testunit. When writing, the device consists of 4 @@ -26,14 +26,17 @@ an 8-bit version number of the testunit. When writing, the device consists of 4 written to start a testcase, i.e. you usually write 4 bytes to the device. The registers are: -0x00 CMD - which test to trigger -0x01 DATAL - configuration byte 1 for the test -0x02 DATAH - configuration byte 2 for the test -0x03 DELAY - delay in n * 10ms until test is started +.. csv-table:: + :header: "Offset", "Name", "Description" -Using 'i2cset' from the i2c-tools package, the generic command looks like: + 0x00, CMD, which test to trigger + 0x01, DATAL, configuration byte 1 for the test + 0x02, DATAH, configuration byte 2 for the test + 0x03, DELAY, delay in n * 10ms until test is started -# i2cset -y i +Using 'i2cset' from the i2c-tools package, the generic command looks like:: + + # i2cset -y i DELAY is a generic parameter which will delay the execution of the test in CMD. While a command is running (including the delay), new commands will not be @@ -45,44 +48,88 @@ result in the transfer not being acknowledged. Commands -------- -0x00 NOOP (reserved for future use) +0x00 NOOP +~~~~~~~~~ -0x01 READ_BYTES (also needs master mode) - DATAL - address to read data from (lower 7 bits, highest bit currently unused) - DATAH - number of bytes to read +Reserved for future use. -This is useful to test if your bus master driver is handling multi-master -correctly. You can trigger the testunit to read bytes from another device on -the bus. If the bus master under test also wants to access the bus at the same -time, the bus will be busy. Example to read 128 bytes from device 0x50 after -50ms of delay: +0x01 READ_BYTES +~~~~~~~~~~~~~~~ -# i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i +.. list-table:: + :header-rows: 1 -0x02 SMBUS_HOST_NOTIFY (also needs master mode) - DATAL - low byte of the status word to send - DATAH - high byte of the status word to send + * - CMD + - DATAL + - DATAH + - DELAY -This test will send an SMBUS_HOST_NOTIFY message to the host. Note that the -status word is currently ignored in the Linux Kernel. Example to send a -notification after 10ms: + * - 0x01 + - address to read data from (lower 7 bits, highest bit currently unused) + - number of bytes to read + - n * 10ms -# i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i +Also needs master mode. This is useful to test if your bus master driver is +handling multi-master correctly. You can trigger the testunit to read bytes +from another device on the bus. If the bus master under test also wants to +access the bus at the same time, the bus will be busy. Example to read 128 +bytes from device 0x50 after 50ms of delay:: -0x03 SMBUS_BLOCK_PROC_CALL (partial command) - DATAL - must be '1', i.e. one further byte will be written - DATAH - number of bytes to be sent back - DELAY - not applicable, partial command! + # i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i -This test will respond to a block process call as defined by the SMBus -specification. The one data byte written specifies how many bytes will be sent -back in the following read transfer. Note that in this read transfer, the -testunit will prefix the length of the bytes to follow. So, if your host bus -driver emulates SMBus calls like the majority does, it needs to support the -I2C_M_RECV_LEN flag of an i2c_msg. This is a good testcase for it. The returned -data consists of the length first, and then of an array of bytes from length-1 -to 0. Here is an example which emulates i2c_smbus_block_process_call() using -i2ctransfer (you need i2c-tools v4.2 or later): +0x02 SMBUS_HOST_NOTIFY +~~~~~~~~~~~~~~~~~~~~~~ -# i2ctransfer -y 0 w3@0x30 0x03 0x01 0x10 r? -0x10 0x0f 0x0e 0x0d 0x0c 0x0b 0x0a 0x09 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00 +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x02 + - low byte of the status word to send + - high byte of the status word to send + - n * 10ms + +Also needs master mode. This test will send an SMBUS_HOST_NOTIFY message to the +host. Note that the status word is currently ignored in the Linux Kernel. +Example to send a notification after 10ms:: + + # i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i + +If the host controller supports HostNotify, this message with debug level +should appear (Linux 6.11 and later):: + + Detected HostNotify from address 0x30 + +0x03 SMBUS_BLOCK_PROC_CALL +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - CMD + - DATAL + - DATAH + - DELAY + + * - 0x03 + - must be '1', i.e. one further byte will be written + - number of bytes to be sent back + - leave out, partial command! + +Partial command. This test will respond to a block process call as defined by +the SMBus specification. The one data byte written specifies how many bytes +will be sent back in the following read transfer. Note that in this read +transfer, the testunit will prefix the length of the bytes to follow. So, if +your host bus driver emulates SMBus calls like the majority does, it needs to +support the I2C_M_RECV_LEN flag of an i2c_msg. This is a good testcase for it. +The returned data consists of the length first, and then of an array of bytes +from length-1 to 0. Here is an example which emulates +i2c_smbus_block_process_call() using i2ctransfer (you need i2c-tools v4.2 or +later):: + + # i2ctransfer -y 0 w3@0x30 0x03 0x01 0x10 r? + 0x10 0x0f 0x0e 0x0d 0x0c 0x0b 0x0a 0x09 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00 diff --git a/Documentation/iio/adis16475.rst b/Documentation/iio/adis16475.rst index 130f9e97cc17..4bf0998be36e 100644 --- a/Documentation/iio/adis16475.rst +++ b/Documentation/iio/adis16475.rst @@ -380,24 +380,5 @@ data is structured. 4. IIO Interfacing Tools ======================== -Linux Kernel Tools ------------------- - -Linux Kernel provides some userspace tools that can be used to retrieve data -from IIO sysfs: - -* lsiio: example application that provides a list of IIO devices and triggers -* iio_event_monitor: example application that reads events from an IIO device - and prints them -* iio_generic_buffer: example application that reads data from buffer -* iio_utils: set of APIs, typically used to access sysfs files. - -LibIIO ------- - -LibIIO is a C/C++ library that provides generic access to IIO devices. The -library abstracts the low-level details of the hardware, and provides a simple -yet complete programming interface that can be used for advanced projects. - -For more information about LibIIO, please see: -https://github.com/analogdevicesinc/libiio +See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO +interfacing tools. diff --git a/Documentation/iio/adis16480.rst b/Documentation/iio/adis16480.rst new file mode 100644 index 000000000000..bc78fa04d958 --- /dev/null +++ b/Documentation/iio/adis16480.rst @@ -0,0 +1,443 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================ +ADIS16480 driver +================ + +This driver supports Analog Device's IMUs on SPI bus. + +1. Supported devices +==================== + +* `ADIS16375 `_ +* `ADIS16480 `_ +* `ADIS16485 `_ +* `ADIS16488 `_ +* `ADIS16490 `_ +* `ADIS16495 `_ +* `ADIS16497 `_ +* `ADIS16545 `_ +* `ADIS16547 `_ + +Each supported device is a complete inertial system that includes a triaxial +gyroscope and a triaxial accelerometer. Each inertial sensor in device combines +with signal conditioning that optimizes dynamic performance. The factory +calibration characterizes each sensor for sensitivity, bias, and alignment. As +a result, each sensor has its own dynamic compensation formulas that provide +accurate sensor measurements. + +2. Device attributes +==================== + +Accelerometer, gyroscope measurements are always provided. Furthermore, the +driver offers the capability to retrieve the delta angle and the delta velocity +measurements computed by the device. + +The delta angle measurements represent a calculation of angular displacement +between each sample update, while the delta velocity measurements represent a +calculation of linear velocity change between each sample update. + +Finally, temperature data are provided which show a coarse measurement of +the temperature inside of the IMU device. This data is most useful for +monitoring relative changes in the thermal environment. + +ADIS16480 and ADIS16488 also provide access to barometric pressure data and +triaxial magnetometer measurements. + +Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``, +where X is the IIO index of the device. Under these folders reside a set of +device files, depending on the characteristics and features of the hardware +device in questions. These files are consistently generalized and documented in +the IIO ABI documentation. + +The following tables show the adis16480 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + +**Available only for ADIS16480 and ADIS16488:** + ++------------------------------------------+---------------------------------------------------------+ +| 3-Axis Magnetometer related device files | Description | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_scale | Scale for the magnetometer channels. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_x_calibbias | Calibration offset for the X-axis magnetometer channel. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_x_filter_low_pass_3db_frequency | Bandwidth for the X-axis magnetometer channel. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_x_raw | Raw X-axis magnetometer channel value. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_y_calibbias | Calibration offset for the Y-axis magnetometer channel. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_y_filter_low_pass_3db_frequency | Bandwidth for the Y-axis magnetometer channel. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_y_raw | Raw Y-axis magnetometer channel value. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_z_calibbias | Calibration offset for the Z-axis magnetometer channel. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_z_filter_low_pass_3db_frequency | Bandwidth for the Z-axis magnetometer channel. | ++------------------------------------------+---------------------------------------------------------+ +| in_magn_z_raw | Raw Z-axis magnetometer channel value. | ++------------------------------------------+---------------------------------------------------------+ + ++------------------------------------------+-----------------------------------------------------+ +| Barometric pressure sensor related files | Description | ++------------------------------------------+-----------------------------------------------------+ +| in_pressure0_calibbias | Calibration offset for barometric pressure channel. | ++------------------------------------------+-----------------------------------------------------+ +| in_pressure0_raw | Raw barometric pressure channel value. | ++------------------------------------------+-----------------------------------------------------+ +| in_pressure0_scale | Scale for the barometric pressure sensor channel. | ++------------------------------------------+-----------------------------------------------------+ + +**Available for all supported devices:** + ++-------------------------------------------+----------------------------------------------------------+ +| 3-Axis Accelerometer related device files | Description | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_scale | Scale for the accelerometer channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_calibscale | Calibration scale for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_filter_low_pass_3db_frequency | Bandwidth for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_raw | Raw X-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_calibscale | Calibration scale for the Y-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_filter_low_pass_3db_frequency | Bandwidth for the Y-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_raw | Raw Y-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_calibbias | Calibration offset for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_calibscale | Calibration scale for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_filter_low_pass_3db_frequency | Bandwidth for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_raw | Raw Z-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_scale | Scale for delta velocity channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_x_raw | Raw X-axis delta velocity channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_y_raw | Raw Y-axis delta velocity channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_z_raw | Raw Z-axis delta velocity channel value. | ++-------------------------------------------+----------------------------------------------------------+ + ++--------------------------------------------+------------------------------------------------------+ +| 3-Axis Gyroscope related device files | Description | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_scale | Scale for the gyroscope channels. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_calibbias | Calibration offset for the X-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_calibscale | Calibration scale for the X-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_filter_low_pass_3db_frequency | Bandwidth for the X-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_raw | Raw X-axis gyroscope channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_calibbias | Calibration offset for the Y-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_calibscale | Calibration scale for the Y-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_filter_low_pass_3db_frequency | Bandwidth for the Y-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_raw | Raw Y-axis gyroscope channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_calibbias | Calibration offset for the Z-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_calibscale | Calibration scale for the Z-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_filter_low_pass_3db_frequency | Bandwidth for the Z-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_raw | Raw Z-axis gyroscope channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_scale | Scale for delta angle channels. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_x_raw | Raw X-axis delta angle channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_y_raw | Raw Y-axis delta angle channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_z_raw | Raw Z-axis delta angle channel value. | ++--------------------------------------------+------------------------------------------------------+ + ++----------------------------------+-------------------------------------------+ +| Temperature sensor related files | Description | ++----------------------------------+-------------------------------------------+ +| in_temp0_raw | Raw temperature channel value. | ++----------------------------------+-------------------------------------------+ +| in_temp0_offset | Offset for the temperature sensor channel.| ++----------------------------------+-------------------------------------------+ +| in_temp0_scale | Scale for the temperature sensor channel. | ++----------------------------------+-------------------------------------------+ + ++-------------------------------+---------------------------------------------------------+ +| Miscellaneous device files | Description | ++-------------------------------+---------------------------------------------------------+ +| name | Name of the IIO device. | ++-------------------------------+---------------------------------------------------------+ +| sampling_frequency | Currently selected sample rate. | ++-------------------------------+---------------------------------------------------------+ + +The following table shows the adis16480 related device debug files, found in the +specific device debug folder path ``/sys/kernel/debug/iio/iio:deviceX``. + ++----------------------+-------------------------------------------------------------------------+ +| Debugfs device files | Description | ++----------------------+-------------------------------------------------------------------------+ +| serial_number | The serial number of the chip in hexadecimal format. | ++----------------------+-------------------------------------------------------------------------+ +| product_id | Chip specific product id (e.g. 16480, 16488, 16545, etc.). | ++----------------------+-------------------------------------------------------------------------+ +| flash_count | The number of flash writes performed on the device. | ++----------------------+-------------------------------------------------------------------------+ +| firmware_revision | String containing the firmware revision in the following format ##.##. | ++----------------------+-------------------------------------------------------------------------+ +| firmware_date | String containing the firmware date in the following format mm-dd-yyyy. | ++----------------------+-------------------------------------------------------------------------+ + +Channels processed values +------------------------- + +A channel value can be read from its _raw attribute. The value returned is the +raw value as reported by the devices. To get the processed value of the channel, +apply the following formula: + +.. code-block:: bash + + processed value = (_raw + _offset) * _scale + +Where _offset and _scale are device attributes. If no _offset attribute is +present, simply assume its value is 0. + +The adis16480 driver offers data for 7 types of channels, the table below shows +the measurement units for the processed value, which are defined by the IIO +framework: + ++--------------------------------------+---------------------------+ +| Channel type | Measurement unit | ++--------------------------------------+---------------------------+ +| Acceleration on X, Y, and Z axis | Meters per Second squared | ++--------------------------------------+---------------------------+ +| Angular velocity on X, Y and Z axis | Radians per second | ++--------------------------------------+---------------------------+ +| Delta velocity on X. Y, and Z axis | Meters per Second | ++--------------------------------------+---------------------------+ +| Delta angle on X, Y, and Z axis | Radians | ++--------------------------------------+---------------------------+ +| Temperature | Millidegrees Celsius | ++--------------------------------------+---------------------------+ +| Magnetic field along X, Y and Z axis | Gauss | ++--------------------------------------+---------------------------+ +| Barometric pressure | kilo Pascal | ++--------------------------------------+---------------------------+ + +Usage examples +-------------- + +Show device name: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat name + adis16545-1 + +Show accelerometer channels value: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_raw + 1376728 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_y_raw + 4487621 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_z_raw + 262773792 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_scale + 0.000000037 + +- X-axis acceleration = in_accel_x_raw * in_accel_scale = 0.050938936 m/s^2 +- Y-axis acceleration = in_accel_y_raw * in_accel_scale = 0.166041977 m/s^2 +- Z-axis acceleration = in_accel_z_raw * in_accel_scale = 9.722630304 m/s^2 + +Show gyroscope channels value: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_x_raw + -1041702 + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_raw + -273013 + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_z_raw + 2745116 + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_scale + 0.000000001 + +- X-axis angular velocity = in_anglvel_x_raw * in_anglvel_scale = −0.001041702 rad/s +- Y-axis angular velocity = in_anglvel_y_raw * in_anglvel_scale = −0.000273013 rad/s +- Z-axis angular velocity = in_anglvel_z_raw * in_anglvel_scale = 0.002745116 rad/s + +Set calibration offset for accelerometer channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 0 + + root:/sys/bus/iio/devices/iio:device0> echo 5000 > in_accel_x_calibbias + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 5000 + +Set calibration offset for gyroscope channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_calibbias + 0 + + root:/sys/bus/iio/devices/iio:device0> echo -5000 > in_anglvel_y_calibbias + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_calibbias + -5000 + +Set sampling frequency: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat sampling_frequency + 4250.000000 + + root:/sys/bus/iio/devices/iio:device0> echo 1000 > sampling_frequency + 1062.500000 + +Set bandwidth for accelerometer channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_filter_low_pass_3db_frequency + 0 + + root:/sys/bus/iio/devices/iio:device0> echo 300 > in_accel_x_filter_low_pass_3db_frequency + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_filter_low_pass_3db_frequency + 300 + +Show serial number: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat serial_number + 0x000c + +Show product id: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat product_id + 16545 + +Show flash count: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat flash_count + 88 + +Show firmware revision: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat firmware_revision + 1.4 + +Show firmware date: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat firmware_date + 09-23-2023 + +3. Device buffers +================= + +This driver supports IIO buffers. + +All devices support retrieving the raw acceleration, gyroscope and temperature +measurements using buffers. + +The following device families also support retrieving the delta velocity, delta +angle and temperature measurements using buffers: + +- ADIS16545 +- ADIS16547 + +However, when retrieving acceleration or gyroscope data using buffers, delta +readings will not be available and vice versa. This is because the device only +allows to read either acceleration and gyroscope data or delta velocity and +delta angle data at a time and switching between these two burst data selection +modes is time consuming. + +Usage examples +-------------- + +Set device trigger in current_trigger, if not already set: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat trigger/current_trigger + + root:/sys/bus/iio/devices/iio:device0> echo adis16545-1-dev0 > trigger/current_trigger + root:/sys/bus/iio/devices/iio:device0> cat trigger/current_trigger + adis16545-1-dev0 + +Select channels for buffer read: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_z_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_temp0_en + +Set the number of samples to be stored in the buffer: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length + +Enable buffer readings: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable + +Obtain buffered data:: + + root:/sys/bus/iio/devices/iio:device0> hexdump -C /dev/iio\:device0 + ... + 00006aa0 09 62 00 00 ff ff fc a4 00 00 01 69 00 03 3c 08 |.b.........i..<.| + 00006ab0 09 61 00 00 00 00 02 96 00 00 02 8f 00 03 37 50 |.a............7P| + 00006ac0 09 61 00 00 00 00 12 3d 00 00 0b 89 00 03 2c 0b |.a.....=......,.| + 00006ad0 09 61 00 00 00 00 1e dc 00 00 16 dd 00 03 25 bf |.a............%.| + 00006ae0 09 61 00 00 00 00 1e e3 00 00 1b bf 00 03 27 0b |.a............'.| + 00006af0 09 61 00 00 00 00 15 50 00 00 19 44 00 03 30 fd |.a.....P...D..0.| + 00006b00 09 61 00 00 00 00 09 0e 00 00 14 41 00 03 3d 7f |.a.........A..=.| + 00006b10 09 61 00 00 ff ff ff f0 00 00 0e bc 00 03 48 d0 |.a............H.| + 00006b20 09 63 00 00 00 00 00 9f 00 00 0f 37 00 03 4c fe |.c.........7..L.| + 00006b30 09 64 00 00 00 00 0b f6 00 00 18 92 00 03 43 22 |.d............C"| + 00006b40 09 64 00 00 00 00 18 df 00 00 22 33 00 03 33 ab |.d........"3..3.| + 00006b50 09 63 00 00 00 00 1e 81 00 00 26 be 00 03 29 60 |.c........&...)`| + 00006b60 09 63 00 00 00 00 1b 13 00 00 22 2f 00 03 23 91 |.c........"/..#.| + ... + +See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered +data is structured. + +4. IIO Interfacing Tools +======================== + +See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO +interfacing tools. diff --git a/Documentation/iio/iio_dmabuf_api.rst b/Documentation/iio/iio_dmabuf_api.rst new file mode 100644 index 000000000000..2836cadbd495 --- /dev/null +++ b/Documentation/iio/iio_dmabuf_api.rst @@ -0,0 +1,54 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================================== +High-speed DMABUF interface for IIO +=================================== + +1. Overview +=========== + +The Industrial I/O subsystem supports access to buffers through a +file-based interface, with read() and write() access calls through the +IIO device's dev node. + +It additionally supports a DMABUF based interface, where the userspace +can attach DMABUF objects (externally created) to an IIO buffer, and +subsequently use them for data transfers. + +A userspace application can then use this interface to share DMABUF +objects between several interfaces, allowing it to transfer data in a +zero-copy fashion, for instance between IIO and the USB stack. + +The userspace application can also memory-map the DMABUF objects, and +access the sample data directly. The advantage of doing this vs. the +read() interface is that it avoids an extra copy of the data between the +kernel and userspace. This is particularly useful for high-speed devices +which produce several megabytes or even gigabytes of data per second. +It does however increase the userspace-kernelspace synchronization +overhead, as the DMA_BUF_SYNC_START and DMA_BUF_SYNC_END IOCTLs have to +be used for data integrity. + +2. User API +=========== + +As part of this interface, three new IOCTLs have been added. These three +IOCTLs have to be performed on the IIO buffer's file descriptor, which +can be obtained using the IIO_BUFFER_GET_FD_IOCTL() ioctl. + + ``IIO_BUFFER_DMABUF_ATTACH_IOCTL(int fd)`` + Attach the DMABUF object, identified by its file descriptor, to the + IIO buffer. Returns zero on success, and a negative errno value on + error. + + ``IIO_BUFFER_DMABUF_DETACH_IOCTL(int fd)`` + Detach the given DMABUF object, identified by its file descriptor, + from the IIO buffer. Returns zero on success, and a negative errno + value on error. + + Note that closing the IIO buffer's file descriptor will + automatically detach all previously attached DMABUF objects. + + ``IIO_BUFFER_DMABUF_ENQUEUE_IOCTL(struct iio_dmabuf *iio_dmabuf)`` + Enqueue a previously attached DMABUF object to the buffer queue. + Enqueued DMABUFs will be read from (if output buffer) or written to + (if input buffer) as long as the buffer is enabled. diff --git a/Documentation/iio/iio_tools.rst b/Documentation/iio/iio_tools.rst new file mode 100644 index 000000000000..cc691c7f6365 --- /dev/null +++ b/Documentation/iio/iio_tools.rst @@ -0,0 +1,27 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================== +IIO Interfacing Tools +===================== + +1. Linux Kernel Tools +===================== + +Linux Kernel provides some userspace tools that can be used to retrieve data +from IIO sysfs: + +* lsiio: example application that provides a list of IIO devices and triggers +* iio_event_monitor: example application that reads events from an IIO device + and prints them +* iio_generic_buffer: example application that reads data from buffer +* iio_utils: set of APIs, typically used to access sysfs files. + +2. LibIIO +========= + +LibIIO is a C/C++ library that provides generic access to IIO devices. The +library abstracts the low-level details of the hardware, and provides a simple +yet complete programming interface that can be used for advanced projects. + +For more information about LibIIO, please see: +https://github.com/analogdevicesinc/libiio diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst index fb6f9d743211..9cb4c50cb20d 100644 --- a/Documentation/iio/index.rst +++ b/Documentation/iio/index.rst @@ -9,6 +9,8 @@ Industrial I/O iio_configfs iio_devbuf + iio_dmabuf_api + iio_tools Industrial I/O Kernel Drivers ============================= @@ -18,5 +20,6 @@ Industrial I/O Kernel Drivers ad7944 adis16475 + adis16480 bno055 ep93xx_adc diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst index 2d0ce9138588..8c5b226d8313 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -21,6 +21,7 @@ fit into other categories. isl29003 lis3lv02d max6875 + mrvl_cn10k_dpi oxsemi-tornado pci-endpoint-test spear-pcie-gadget diff --git a/Documentation/misc-devices/mrvl_cn10k_dpi.rst b/Documentation/misc-devices/mrvl_cn10k_dpi.rst new file mode 100644 index 000000000000..a75e372723d8 --- /dev/null +++ b/Documentation/misc-devices/mrvl_cn10k_dpi.rst @@ -0,0 +1,52 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============================================== +Marvell CN10K DMA packet interface (DPI) driver +=============================================== + +Overview +======== + +DPI is a DMA packet interface hardware block in Marvell's CN10K silicon. +DPI hardware comprises a physical function (PF), its virtual functions, +mailbox logic, and a set of DMA engines & DMA command queues. + +DPI PF function is an administrative function which services the mailbox +requests from its VF functions and provisions DMA engine resources to +it's VF functions. + +mrvl_cn10k_dpi.ko misc driver loads on DPI PF device and services the +mailbox commands submitted by the VF devices and accordingly initializes +the DMA engines and VF device's DMA command queues. Also, driver creates +/dev/mrvl-cn10k-dpi node to set DMA engine and PEM (PCIe interface) port +attributes like fifo length, molr, mps & mrrs. + +DPI PF driver is just an administrative driver to setup its VF device's +queues and provisions the hardware resources, it cannot initiate any +DMA operations. Only VF devices are provisioned with DMA capabilities. + +Driver location +=============== + +drivers/misc/mrvl_cn10k_dpi.c + +Driver IOCTLs +============= + +:c:macro::`DPI_MPS_MRRS_CFG` +ioctl that sets max payload size & max read request size parameters of +a pem port to which DMA engines are wired. + + +:c:macro::`DPI_ENGINE_CFG` +ioctl that sets DMA engine's fifo sizes & max outstanding load request +thresholds. + +User space code example +======================= + +DPI VF devices are probed and accessed from user space applications using +vfio-pci driver. Below is a sample dpi dma application to demonstrate on +how applications use mailbox and ioctl services from DPI PF kernel driver. + +https://github.com/MarvellEmbeddedProcessors/dpi-sample-app diff --git a/Documentation/translations/zh_CN/PCI/pciebus-howto.rst b/Documentation/translations/zh_CN/PCI/pciebus-howto.rst index 65c4301f12cd..c6ffda62af21 100644 --- a/Documentation/translations/zh_CN/PCI/pciebus-howto.rst +++ b/Documentation/translations/zh_CN/PCI/pciebus-howto.rst @@ -124,7 +124,7 @@ pcie_port_service_unregister取代了Linux驱动模型的pci_unregister_driver static struct pcie_port_service_driver root_aerdrv = { .name = (char *)device_name, - .id_table = &service_id[0], + .id_table = service_id, .probe = aerdrv_load, .remove = aerdrv_unload, diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 9224723992fd..e91c0376ee59 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -365,6 +365,7 @@ Code Seq# Include File Comments 0xB6 all linux/fpga-dfl.h 0xB7 all uapi/linux/remoteproc_cdev.h 0xB7 all uapi/linux/nsfs.h > +0xB8 01-02 uapi/misc/mrvl_cn10k_dpi.h Marvell CN10K DPI driver 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h 0xCA 10-2F uapi/misc/ocxl.h diff --git a/MAINTAINERS b/MAINTAINERS index eb69dfaae966..e45b3e150678 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -440,6 +440,16 @@ W: http://wiki.analog.com/AD7142 W: https://ez.analog.com/linux-software-drivers F: drivers/input/misc/ad714x.c +AD738X ADC DRIVER (AD7380/1/2/4) +M: Michael Hennerich +M: Nuno Sá +R: David Lechner +S: Supported +W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml +F: drivers/iio/adc/ad7380.c + AD7877 TOUCHSCREEN DRIVER M: Michael Hennerich S: Supported @@ -1202,7 +1212,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r* F: drivers/iio/adc/ad7091r* ANALOG DEVICES INC AD7192 DRIVER -M: Alexandru Tachici +M: Alisa-Dariana Roman L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers @@ -2400,7 +2410,7 @@ ARM/LPC18XX ARCHITECTURE M: Vladimir Zapolskiy L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt +F: Documentation/devicetree/bindings/i2c/nxp,lpc1788-i2c.yaml F: arch/arm/boot/dts/nxp/lpc/lpc43* F: drivers/i2c/busses/i2c-lpc2k.c F: drivers/memory/pl172.c @@ -3568,6 +3578,13 @@ F: include/linux/cfag12864b.h F: include/uapi/linux/map_to_14segment.h F: include/uapi/linux/map_to_7segment.h +AVAGO APDS9306 AMBIENT LIGHT SENSOR DRIVER +M: Subhajit Ghosh +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/light/avago,apds9300.yaml +F: drivers/iio/light/apds9306.c + AVIA HX711 ANALOG DIGITAL CONVERTER IIO DRIVER M: Andreas Klinger L: linux-iio@vger.kernel.org @@ -11668,6 +11685,7 @@ M: Jean-Baptiste Maneyrol L: linux-iio@vger.kernel.org S: Maintained W: https://invensense.tdk.com/ +F: Documentation/ABI/testing/sysfs-bus-iio-inv_icm42600 F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml F: drivers/iio/imu/inv_icm42600/ @@ -13628,6 +13646,11 @@ S: Supported F: Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml F: drivers/mmc/host/sdhci-xenon* +MARVELL OCTEON CN10K DPI DRIVER +M: Vamsi Attunuru +S: Supported +F: drivers/misc/mrvl_cn10k_dpi.c + MARVELL OCTEON ENDPOINT VIRTIO DATA PATH ACCELERATOR R: schalla@marvell.com R: vattunuru@marvell.com @@ -17440,6 +17463,14 @@ S: Maintained F: Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt F: drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c +PCI DRIVER FOR PLDA PCIE IP +M: Daire McNamara +L: linux-pci@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml +F: drivers/pci/controller/plda/pcie-plda-host.c +F: drivers/pci/controller/plda/pcie-plda.h + PCI DRIVER FOR RENESAS R-CAR M: Marek Vasut M: Yoshihiro Shimoda @@ -17678,7 +17709,7 @@ M: Daire McNamara L: linux-pci@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/pci/microchip* -F: drivers/pci/controller/*microchip* +F: drivers/pci/controller/plda/*microchip* PCIE DRIVER FOR QUALCOMM MSM M: Manivannan Sadhasivam @@ -17708,6 +17739,13 @@ L: linux-pci@vger.kernel.org S: Maintained F: drivers/pci/controller/dwc/*spear* +PCIE DRIVER FOR STARFIVE JH71x0 +M: Kevin Xie +L: linux-pci@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml +F: drivers/pci/controller/plda/pcie-starfive.c + PCIE ENDPOINT DRIVER FOR QUALCOMM M: Manivannan Sadhasivam L: linux-pci@vger.kernel.org @@ -18736,6 +18774,7 @@ QUALCOMM FASTRPC DRIVER M: Srinivas Kandagatla M: Amol Maheshwari L: linux-arm-msm@vger.kernel.org +L: dri-devel@lists.freedesktop.org S: Maintained F: Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml F: drivers/misc/fastrpc.c @@ -19547,7 +19586,7 @@ F: drivers/clk/microchip/clk-mpfs*.c F: drivers/firmware/microchip/mpfs-auto-update.c F: drivers/i2c/busses/i2c-microchip-corei2c.c F: drivers/mailbox/mailbox-mpfs.c -F: drivers/pci/controller/pcie-microchip-host.c +F: drivers/pci/controller/plda/pcie-microchip-host.c F: drivers/pwm/pwm-microchip-core.c F: drivers/reset/reset-mpfs.c F: drivers/rtc/rtc-mpfs.c @@ -20206,6 +20245,14 @@ F: include/linux/wait.h F: include/uapi/linux/sched.h F: kernel/sched/ +SCIOSENSE ENS160 MULTI-GAS SENSOR DRIVER +M: Gustavo Silva +S: Maintained +F: drivers/iio/chemical/ens160_core.c +F: drivers/iio/chemical/ens160_i2c.c +F: drivers/iio/chemical/ens160_spi.c +F: drivers/iio/chemical/ens160.h + SCSI LIBSAS SUBSYSTEM R: John Garry R: Jason Yan @@ -22663,6 +22710,14 @@ M: Robert Richter S: Odd Fixes F: drivers/gpio/gpio-thunderx.c +TI ADS1119 ADC DRIVER +M: Francesco Dolcini +M: João Paulo Gonçalves +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/adc/ti,ads1119.yaml +F: drivers/iio/adc/ti-ads1119.c + TI ADS7924 ADC DRIVER M: Hugo Villeneuve L: linux-iio@vger.kernel.org diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi index d80dd9a3da31..86eb81112232 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi @@ -31,6 +31,30 @@ enable-active-high; }; + /* USB hub supports both USB 2.0 and USB 3.0 root hub */ + usb-hub { + dr_mode = "host"; + #address-cells = <1>; + #size-cells = <0>; + + /* 2.0 hub on port 1 */ + hub_2_0: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + peer-hub = <&hub_3_0>; + vdd-supply = <&usb_pwr_en>; + }; + + /* 3.0 hub on port 4 */ + hub_3_0: hub@2 { + compatible = "usb5e3,620"; + reg = <2>; + peer-hub = <&hub_2_0>; + reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>; + vdd-supply = <&vcc_5v>; + }; + }; + sound { compatible = "amlogic,axg-sound-card"; model = "ODROID-N2"; @@ -234,18 +258,6 @@ "PIN_3", /* GPIOX_17 */ "PIN_5", /* GPIOX_18 */ "PIN_36"; /* GPIOX_19 */ - /* - * WARNING: The USB Hub on the Odroid-N2 needs a reset signal - * to be turned high in order to be detected by the USB Controller - * This signal should be handled by a USB specific power sequence - * in order to reset the Hub when USB bus is powered down. - */ - usb-hub-hog { - gpio-hog; - gpios = ; - output-high; - line-name = "usb-hub-reset"; - }; }; &i2c3 { diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 5ac70759e0ab..0d8339357bad 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -387,12 +387,13 @@ }; uart0: serial@10000000 { - compatible = "snps,dw-apb-uart"; + compatible = "starfive,jh7110-uart", "snps,dw-apb-uart"; reg = <0x0 0x10000000 0x0 0x10000>; clocks = <&syscrg JH7110_SYSCLK_UART0_CORE>, <&syscrg JH7110_SYSCLK_UART0_APB>; clock-names = "baudclk", "apb_pclk"; - resets = <&syscrg JH7110_SYSRST_UART0_APB>; + resets = <&syscrg JH7110_SYSRST_UART0_APB>, + <&syscrg JH7110_SYSRST_UART0_CORE>; interrupts = <32>; reg-io-width = <4>; reg-shift = <2>; @@ -400,12 +401,13 @@ }; uart1: serial@10010000 { - compatible = "snps,dw-apb-uart"; + compatible = "starfive,jh7110-uart", "snps,dw-apb-uart"; reg = <0x0 0x10010000 0x0 0x10000>; clocks = <&syscrg JH7110_SYSCLK_UART1_CORE>, <&syscrg JH7110_SYSCLK_UART1_APB>; clock-names = "baudclk", "apb_pclk"; - resets = <&syscrg JH7110_SYSRST_UART1_APB>; + resets = <&syscrg JH7110_SYSRST_UART1_APB>, + <&syscrg JH7110_SYSRST_UART1_CORE>; interrupts = <33>; reg-io-width = <4>; reg-shift = <2>; @@ -413,12 +415,13 @@ }; uart2: serial@10020000 { - compatible = "snps,dw-apb-uart"; + compatible = "starfive,jh7110-uart", "snps,dw-apb-uart"; reg = <0x0 0x10020000 0x0 0x10000>; clocks = <&syscrg JH7110_SYSCLK_UART2_CORE>, <&syscrg JH7110_SYSCLK_UART2_APB>; clock-names = "baudclk", "apb_pclk"; - resets = <&syscrg JH7110_SYSRST_UART2_APB>; + resets = <&syscrg JH7110_SYSRST_UART2_APB>, + <&syscrg JH7110_SYSRST_UART2_CORE>; interrupts = <34>; reg-io-width = <4>; reg-shift = <2>; @@ -642,12 +645,13 @@ }; uart3: serial@12000000 { - compatible = "snps,dw-apb-uart"; + compatible = "starfive,jh7110-uart", "snps,dw-apb-uart"; reg = <0x0 0x12000000 0x0 0x10000>; clocks = <&syscrg JH7110_SYSCLK_UART3_CORE>, <&syscrg JH7110_SYSCLK_UART3_APB>; clock-names = "baudclk", "apb_pclk"; - resets = <&syscrg JH7110_SYSRST_UART3_APB>; + resets = <&syscrg JH7110_SYSRST_UART3_APB>, + <&syscrg JH7110_SYSRST_UART3_CORE>; interrupts = <45>; reg-io-width = <4>; reg-shift = <2>; @@ -655,12 +659,13 @@ }; uart4: serial@12010000 { - compatible = "snps,dw-apb-uart"; + compatible = "starfive,jh7110-uart", "snps,dw-apb-uart"; reg = <0x0 0x12010000 0x0 0x10000>; clocks = <&syscrg JH7110_SYSCLK_UART4_CORE>, <&syscrg JH7110_SYSCLK_UART4_APB>; clock-names = "baudclk", "apb_pclk"; - resets = <&syscrg JH7110_SYSRST_UART4_APB>; + resets = <&syscrg JH7110_SYSRST_UART4_APB>, + <&syscrg JH7110_SYSRST_UART4_CORE>; interrupts = <46>; reg-io-width = <4>; reg-shift = <2>; @@ -668,12 +673,13 @@ }; uart5: serial@12020000 { - compatible = "snps,dw-apb-uart"; + compatible = "starfive,jh7110-uart", "snps,dw-apb-uart"; reg = <0x0 0x12020000 0x0 0x10000>; clocks = <&syscrg JH7110_SYSCLK_UART5_CORE>, <&syscrg JH7110_SYSCLK_UART5_APB>; clock-names = "baudclk", "apb_pclk"; - resets = <&syscrg JH7110_SYSRST_UART5_APB>; + resets = <&syscrg JH7110_SYSRST_UART5_APB>, + <&syscrg JH7110_SYSRST_UART5_CORE>; interrupts = <47>; reg-io-width = <4>; reg-shift = <2>; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 58b89b8d950e..d0bfb3706801 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -293,11 +293,6 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) } EXPORT_SYMBOL_GPL(acpi_pci_find_root); -struct acpi_handle_node { - struct list_head node; - acpi_handle handle; -}; - /** * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev * @handle: the handle in question @@ -1008,7 +1003,6 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, int node = acpi_get_node(device->handle); struct pci_bus *bus; struct pci_host_bridge *host_bridge; - union acpi_object *obj; info->root = root; info->bridge = device; @@ -1050,17 +1044,6 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, if (!(root->osc_ext_control_set & OSC_CXL_ERROR_REPORTING_CONTROL)) host_bridge->native_cxl_error = 0; - /* - * Evaluate the "PCI Boot Configuration" _DSM Function. If it - * exists and returns 0, we must preserve any PCI resource - * assignments made by firmware for this host bridge. - */ - obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1, - DSM_PCI_PRESERVE_BOOT_CONFIG, NULL, ACPI_TYPE_INTEGER); - if (obj && obj->integer.value == 0) - host_bridge->preserve_config = 1; - ACPI_FREE(obj); - acpi_dev_power_up_children_with_adr(device); pci_scan_child_bus(bus); diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 39ad893e7316..abc8be04ffcc 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -571,9 +571,7 @@ static bool binder_has_work(struct binder_thread *thread, bool do_proc_work) static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread) { return !thread->transaction_stack && - binder_worklist_empty_ilocked(&thread->todo) && - (thread->looper & (BINDER_LOOPER_STATE_ENTERED | - BINDER_LOOPER_STATE_REGISTERED)); + binder_worklist_empty_ilocked(&thread->todo); } static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc, @@ -1218,6 +1216,66 @@ static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc, return NULL; } +/* Find the smallest unused descriptor the "slow way" */ +static u32 slow_desc_lookup_olocked(struct binder_proc *proc) +{ + struct binder_ref *ref; + struct rb_node *n; + u32 desc; + + desc = 1; + for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) { + ref = rb_entry(n, struct binder_ref, rb_node_desc); + if (ref->data.desc > desc) + break; + desc = ref->data.desc + 1; + } + + return desc; +} + +/* + * Find an available reference descriptor ID. The proc->outer_lock might + * be released in the process, in which case -EAGAIN is returned and the + * @desc should be considered invalid. + */ +static int get_ref_desc_olocked(struct binder_proc *proc, + struct binder_node *node, + u32 *desc) +{ + struct dbitmap *dmap = &proc->dmap; + unsigned long *new, bit; + unsigned int nbits; + + /* 0 is reserved for the context manager */ + if (node == proc->context->binder_context_mgr_node) { + *desc = 0; + return 0; + } + + if (!dbitmap_enabled(dmap)) { + *desc = slow_desc_lookup_olocked(proc); + return 0; + } + + if (dbitmap_acquire_first_zero_bit(dmap, &bit) == 0) { + *desc = bit; + return 0; + } + + /* + * The dbitmap is full and needs to grow. The proc->outer_lock + * is briefly released to allocate the new bitmap safely. + */ + nbits = dbitmap_grow_nbits(dmap); + binder_proc_unlock(proc); + new = bitmap_zalloc(nbits, GFP_KERNEL); + binder_proc_lock(proc); + dbitmap_grow(dmap, new, nbits); + + return -EAGAIN; +} + /** * binder_get_ref_for_node_olocked() - get the ref associated with given node * @proc: binder_proc that owns the ref @@ -1241,12 +1299,14 @@ static struct binder_ref *binder_get_ref_for_node_olocked( struct binder_node *node, struct binder_ref *new_ref) { - struct binder_context *context = proc->context; - struct rb_node **p = &proc->refs_by_node.rb_node; - struct rb_node *parent = NULL; struct binder_ref *ref; - struct rb_node *n; + struct rb_node *parent; + struct rb_node **p; + u32 desc; +retry: + p = &proc->refs_by_node.rb_node; + parent = NULL; while (*p) { parent = *p; ref = rb_entry(parent, struct binder_ref, rb_node_node); @@ -1261,6 +1321,10 @@ static struct binder_ref *binder_get_ref_for_node_olocked( if (!new_ref) return NULL; + /* might release the proc->outer_lock */ + if (get_ref_desc_olocked(proc, node, &desc) == -EAGAIN) + goto retry; + binder_stats_created(BINDER_STAT_REF); new_ref->data.debug_id = atomic_inc_return(&binder_last_id); new_ref->proc = proc; @@ -1268,14 +1332,7 @@ static struct binder_ref *binder_get_ref_for_node_olocked( rb_link_node(&new_ref->rb_node_node, parent, p); rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); - new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1; - for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { - ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (ref->data.desc > new_ref->data.desc) - break; - new_ref->data.desc = ref->data.desc + 1; - } - + new_ref->data.desc = desc; p = &proc->refs_by_desc.rb_node; while (*p) { parent = *p; @@ -1304,6 +1361,7 @@ static struct binder_ref *binder_get_ref_for_node_olocked( static void binder_cleanup_ref_olocked(struct binder_ref *ref) { + struct dbitmap *dmap = &ref->proc->dmap; bool delete_node = false; binder_debug(BINDER_DEBUG_INTERNAL_REFS, @@ -1311,6 +1369,8 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref) ref->proc->pid, ref->data.debug_id, ref->data.desc, ref->node->debug_id); + if (dbitmap_enabled(dmap)) + dbitmap_clear_bit(dmap, ref->data.desc); rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); @@ -1471,6 +1531,25 @@ static void binder_free_ref(struct binder_ref *ref) kfree(ref); } +/* shrink descriptor bitmap if needed */ +static void try_shrink_dmap(struct binder_proc *proc) +{ + unsigned long *new; + int nbits; + + binder_proc_lock(proc); + nbits = dbitmap_shrink_nbits(&proc->dmap); + binder_proc_unlock(proc); + + if (!nbits) + return; + + new = bitmap_zalloc(nbits, GFP_KERNEL); + binder_proc_lock(proc); + dbitmap_shrink(&proc->dmap, new, nbits); + binder_proc_unlock(proc); +} + /** * binder_update_ref_for_handle() - inc/dec the ref for given handle * @proc: proc containing the ref @@ -1507,8 +1586,10 @@ static int binder_update_ref_for_handle(struct binder_proc *proc, *rdata = ref->data; binder_proc_unlock(proc); - if (delete_ref) + if (delete_ref) { binder_free_ref(ref); + try_shrink_dmap(proc); + } return ret; err_no_ref: @@ -5122,6 +5203,7 @@ static void binder_free_proc(struct binder_proc *proc) put_task_struct(proc->tsk); put_cred(proc->cred); binder_stats_deleted(BINDER_STAT_PROC); + dbitmap_free(&proc->dmap); kfree(proc); } @@ -5826,6 +5908,8 @@ static int binder_open(struct inode *nodp, struct file *filp) proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (proc == NULL) return -ENOMEM; + + dbitmap_init(&proc->dmap); spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 2e1f261ec5c8..b00961944ab1 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -836,9 +836,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, alloc->buffer = vma->vm_start; - alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE, - sizeof(alloc->pages[0]), - GFP_KERNEL); + alloc->pages = kvcalloc(alloc->buffer_size / PAGE_SIZE, + sizeof(alloc->pages[0]), + GFP_KERNEL); if (alloc->pages == NULL) { ret = -ENOMEM; failure_string = "alloc page array"; @@ -869,7 +869,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, return 0; err_alloc_buf_struct_failed: - kfree(alloc->pages); + kvfree(alloc->pages); alloc->pages = NULL; err_alloc_pages_failed: alloc->buffer = 0; @@ -939,7 +939,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) __free_page(alloc->pages[i].page_ptr); page_count++; } - kfree(alloc->pages); + kvfree(alloc->pages); } spin_unlock(&alloc->lock); if (alloc->mm) diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index ecd6e9f275ae..25e306b696fc 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -14,6 +14,7 @@ #include #include #include "binder_alloc.h" +#include "dbitmap.h" struct binder_context { struct binder_node *binder_context_mgr_node; @@ -395,6 +396,8 @@ enum binder_prio_state { * @freeze_wait: waitqueue of processes waiting for all outstanding * transactions to be processed * (protected by @inner_lock) + * @dmap dbitmap to manage available reference descriptors + * (protected by @outer_lock) * @todo: list of work for this process * (protected by @inner_lock) * @stats: per-process binder statistics @@ -444,7 +447,7 @@ struct binder_proc { bool sync_recv; bool async_recv; wait_queue_head_t freeze_wait; - + struct dbitmap dmap; struct list_head todo; struct binder_stats stats; struct list_head delivered_death; diff --git a/drivers/android/dbitmap.h b/drivers/android/dbitmap.h new file mode 100644 index 000000000000..b8ac7b4764fd --- /dev/null +++ b/drivers/android/dbitmap.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2024 Google LLC + * + * dbitmap - dynamically sized bitmap library. + * + * Used by the binder driver to optimize the allocation of the smallest + * available descriptor ID. Each bit in the bitmap represents the state + * of an ID, with the exception of BIT(0) which is used exclusively to + * reference binder's context manager. + * + * A dbitmap can grow or shrink as needed. This part has been designed + * considering that users might need to briefly release their locks in + * order to allocate memory for the new bitmap. These operations then, + * are verified to determine if the grow or shrink is sill valid. + * + * This library does not provide protection against concurrent access + * by itself. Binder uses the proc->outer_lock for this purpose. + */ + +#ifndef _LINUX_DBITMAP_H +#define _LINUX_DBITMAP_H +#include + +#define NBITS_MIN BITS_PER_TYPE(unsigned long) + +struct dbitmap { + unsigned int nbits; + unsigned long *map; +}; + +static inline int dbitmap_enabled(struct dbitmap *dmap) +{ + return !!dmap->nbits; +} + +static inline void dbitmap_free(struct dbitmap *dmap) +{ + dmap->nbits = 0; + kfree(dmap->map); +} + +/* Returns the nbits that a dbitmap can shrink to, 0 if not possible. */ +static inline unsigned int dbitmap_shrink_nbits(struct dbitmap *dmap) +{ + unsigned int bit; + + if (dmap->nbits <= NBITS_MIN) + return 0; + + /* + * Determine if the bitmap can shrink based on the position of + * its last set bit. If the bit is within the first quarter of + * the bitmap then shrinking is possible. In this case, the + * bitmap should shrink to half its current size. + */ + bit = find_last_bit(dmap->map, dmap->nbits); + if (bit < (dmap->nbits >> 2)) + return dmap->nbits >> 1; + + /* + * Note that find_last_bit() returns dmap->nbits when no bits + * are set. While this is technically not possible here since + * BIT(0) is always set, this check is left for extra safety. + */ + if (bit == dmap->nbits) + return NBITS_MIN; + + return 0; +} + +/* Replace the internal bitmap with a new one of different size */ +static inline void +dbitmap_replace(struct dbitmap *dmap, unsigned long *new, unsigned int nbits) +{ + bitmap_copy(new, dmap->map, min(dmap->nbits, nbits)); + kfree(dmap->map); + dmap->map = new; + dmap->nbits = nbits; +} + +static inline void +dbitmap_shrink(struct dbitmap *dmap, unsigned long *new, unsigned int nbits) +{ + if (!new) + return; + + /* + * Verify that shrinking to @nbits is still possible. The @new + * bitmap might have been allocated without locks, so this call + * could now be outdated. In this case, free @new and move on. + */ + if (!dbitmap_enabled(dmap) || dbitmap_shrink_nbits(dmap) != nbits) { + kfree(new); + return; + } + + dbitmap_replace(dmap, new, nbits); +} + +/* Returns the nbits that a dbitmap can grow to. */ +static inline unsigned int dbitmap_grow_nbits(struct dbitmap *dmap) +{ + return dmap->nbits << 1; +} + +static inline void +dbitmap_grow(struct dbitmap *dmap, unsigned long *new, unsigned int nbits) +{ + /* + * Verify that growing to @nbits is still possible. The @new + * bitmap might have been allocated without locks, so this call + * could now be outdated. In this case, free @new and move on. + */ + if (!dbitmap_enabled(dmap) || nbits <= dmap->nbits) { + kfree(new); + return; + } + + /* + * Check for ENOMEM after confirming the grow operation is still + * required. This ensures we only disable the dbitmap when it's + * necessary. Once the dbitmap is disabled, binder will fallback + * to slow_desc_lookup_olocked(). + */ + if (!new) { + dbitmap_free(dmap); + return; + } + + dbitmap_replace(dmap, new, nbits); +} + +/* + * Finds and sets the first zero bit in the bitmap. Upon success @bit + * is populated with the index and 0 is returned. Otherwise, -ENOSPC + * is returned to indicate that a dbitmap_grow() is needed. + */ +static inline int +dbitmap_acquire_first_zero_bit(struct dbitmap *dmap, unsigned long *bit) +{ + unsigned long n; + + n = find_first_zero_bit(dmap->map, dmap->nbits); + if (n == dmap->nbits) + return -ENOSPC; + + *bit = n; + set_bit(n, dmap->map); + + return 0; +} + +static inline void +dbitmap_clear_bit(struct dbitmap *dmap, unsigned long bit) +{ + /* BIT(0) should always set for the context manager */ + if (bit) + clear_bit(bit, dmap->map); +} + +static inline int dbitmap_init(struct dbitmap *dmap) +{ + dmap->map = bitmap_zalloc(NBITS_MIN, GFP_KERNEL); + if (!dmap->map) { + dmap->nbits = 0; + return -ENOMEM; + } + + dmap->nbits = NBITS_MIN; + /* BIT(0) is reserved for the context manager */ + set_bit(0, dmap->map); + + return 0; +} +#endif diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c index 9a2cb9ca9d1d..93ebf566b54e 100644 --- a/drivers/ata/pata_parport/pata_parport.c +++ b/drivers/ata/pata_parport/pata_parport.c @@ -768,7 +768,6 @@ static struct parport_driver pata_parport_driver = { .name = DRV_NAME, .match_port = pata_parport_attach, .detach = pata_parport_detach, - .devmodel = true, }; static __init int pata_parport_init(void) diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c index 234f9dbe6e30..51587f0fdaae 100644 --- a/drivers/auxdisplay/ks0108.c +++ b/drivers/auxdisplay/ks0108.c @@ -162,7 +162,6 @@ static struct parport_driver ks0108_parport_driver = { .name = "ks0108", .match_port = ks0108_parport_attach, .detach = ks0108_parport_detach, - .devmodel = true, }; module_parport_driver(ks0108_parport_driver); diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index 049ff443e790..a731f28455b4 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -1706,7 +1706,6 @@ static struct parport_driver panel_driver = { .name = "panel", .match_port = panel_attach, .detach = panel_detach, - .devmodel = true, }; module_parport_driver(panel_driver); diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index f8f674adf1d4..4acfac73ca9a 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -90,7 +90,7 @@ static int mhi_ep_send_completion_event(struct mhi_ep_cntrl *mhi_cntrl, struct m struct mhi_ring_element *event; int ret; - event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL | GFP_DMA); + event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL); if (!event) return -ENOMEM; @@ -109,7 +109,7 @@ int mhi_ep_send_state_change_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_stat struct mhi_ring_element *event; int ret; - event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL | GFP_DMA); + event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL); if (!event) return -ENOMEM; @@ -127,7 +127,7 @@ int mhi_ep_send_ee_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_ee_type exec_e struct mhi_ring_element *event; int ret; - event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL | GFP_DMA); + event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL); if (!event) return -ENOMEM; @@ -146,7 +146,7 @@ static int mhi_ep_send_cmd_comp_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_e struct mhi_ring_element *event; int ret; - event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL | GFP_DMA); + event = kmem_cache_zalloc(mhi_cntrl->ev_ring_el_cache, GFP_KERNEL); if (!event) return -ENOMEM; @@ -438,7 +438,7 @@ static int mhi_ep_read_channel(struct mhi_ep_cntrl *mhi_cntrl, read_offset = mhi_chan->tre_size - mhi_chan->tre_bytes_left; write_offset = len - buf_left; - buf_addr = kmem_cache_zalloc(mhi_cntrl->tre_buf_cache, GFP_KERNEL | GFP_DMA); + buf_addr = kmem_cache_zalloc(mhi_cntrl->tre_buf_cache, GFP_KERNEL); if (!buf_addr) return -ENOMEM; @@ -1481,14 +1481,14 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl, mhi_cntrl->ev_ring_el_cache = kmem_cache_create("mhi_ep_event_ring_el", sizeof(struct mhi_ring_element), 0, - SLAB_CACHE_DMA, NULL); + 0, NULL); if (!mhi_cntrl->ev_ring_el_cache) { ret = -ENOMEM; goto err_free_cmd; } mhi_cntrl->tre_buf_cache = kmem_cache_create("mhi_ep_tre_buf", MHI_EP_DEFAULT_MTU, 0, - SLAB_CACHE_DMA, NULL); + 0, NULL); if (!mhi_cntrl->tre_buf_cache) { ret = -ENOMEM; goto err_destroy_ev_ring_el_cache; diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c index 08844ee79654..14a11880bcea 100644 --- a/drivers/bus/mhi/host/pci_generic.c +++ b/drivers/bus/mhi/host/pci_generic.c @@ -399,6 +399,8 @@ static const struct mhi_channel_config mhi_foxconn_sdx55_channels[] = { MHI_CHANNEL_CONFIG_DL(13, "MBIM", 32, 0), MHI_CHANNEL_CONFIG_UL(32, "DUN", 32, 0), MHI_CHANNEL_CONFIG_DL(33, "DUN", 32, 0), + MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0), + MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0), MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0_MBIM", 128, 2), MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0_MBIM", 128, 3), }; @@ -419,13 +421,14 @@ static const struct mhi_controller_config modem_foxconn_sdx55_config = { .event_cfg = mhi_foxconn_sdx55_events, }; -static const struct mhi_pci_dev_info mhi_foxconn_sdx24_info = { - .name = "foxconn-sdx24", - .config = &modem_foxconn_sdx55_config, - .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32, - .mru_default = 32768, - .sideband_wake = false, +static const struct mhi_controller_config modem_foxconn_sdx72_config = { + .max_channels = 128, + .timeout_ms = 20000, + .ready_timeout_ms = 50000, + .num_channels = ARRAY_SIZE(mhi_foxconn_sdx55_channels), + .ch_cfg = mhi_foxconn_sdx55_channels, + .num_events = ARRAY_SIZE(mhi_foxconn_sdx55_events), + .event_cfg = mhi_foxconn_sdx55_events, }; static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = { @@ -439,8 +442,10 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = { .sideband_wake = false, }; -static const struct mhi_pci_dev_info mhi_foxconn_sdx65_info = { - .name = "foxconn-sdx65", +static const struct mhi_pci_dev_info mhi_foxconn_t99w175_info = { + .name = "foxconn-t99w175", + .fw = "qcom/sdx55m/sbl1.mbn", + .edl = "qcom/sdx55m/edl.mbn", .config = &modem_foxconn_sdx55_config, .bar_num = MHI_PCI_DEFAULT_BAR_NUM, .dma_data_width = 32, @@ -448,6 +453,75 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx65_info = { .sideband_wake = false, }; +static const struct mhi_pci_dev_info mhi_foxconn_dw5930e_info = { + .name = "foxconn-dw5930e", + .fw = "qcom/sdx55m/sbl1.mbn", + .edl = "qcom/sdx55m/edl.mbn", + .config = &modem_foxconn_sdx55_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + +static const struct mhi_pci_dev_info mhi_foxconn_t99w368_info = { + .name = "foxconn-t99w368", + .config = &modem_foxconn_sdx55_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + +static const struct mhi_pci_dev_info mhi_foxconn_t99w373_info = { + .name = "foxconn-t99w373", + .config = &modem_foxconn_sdx55_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + +static const struct mhi_pci_dev_info mhi_foxconn_t99w510_info = { + .name = "foxconn-t99w510", + .config = &modem_foxconn_sdx55_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + +static const struct mhi_pci_dev_info mhi_foxconn_dw5932e_info = { + .name = "foxconn-dw5932e", + .config = &modem_foxconn_sdx55_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + +static const struct mhi_pci_dev_info mhi_foxconn_t99w515_info = { + .name = "foxconn-t99w515", + .edl = "fox/sdx72m/edl.mbn", + .edl_trigger = true, + .config = &modem_foxconn_sdx72_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + +static const struct mhi_pci_dev_info mhi_foxconn_dw5934e_info = { + .name = "foxconn-dw5934e", + .edl = "fox/sdx72m/edl.mbn", + .edl_trigger = true, + .config = &modem_foxconn_sdx72_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, +}; + static const struct mhi_channel_config mhi_mv3x_channels[] = { MHI_CHANNEL_CONFIG_UL(0, "LOOPBACK", 64, 0), MHI_CHANNEL_CONFIG_DL(1, "LOOPBACK", 64, 0), @@ -646,40 +720,49 @@ static const struct pci_device_id mhi_pci_id_table[] = { .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info }, /* T99W175 (sdx55), Both for eSIM and Non-eSIM */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0ab), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w175_info }, /* DW5930e (sdx55), With eSIM, It's also T99W175 */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0b0), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5930e_info }, /* DW5930e (sdx55), Non-eSIM, It's also T99W175 */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0b1), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5930e_info }, /* T99W175 (sdx55), Based on Qualcomm new baseline */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0bf), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w175_info }, /* T99W175 (sdx55) */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0c3), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w175_info }, /* T99W368 (sdx65) */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0d8), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx65_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w368_info }, /* T99W373 (sdx62) */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0d9), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx65_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w373_info }, /* T99W510 (sdx24), variant 1 */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f0), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx24_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w510_info }, /* T99W510 (sdx24), variant 2 */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f1), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx24_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w510_info }, /* T99W510 (sdx24), variant 3 */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f2), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx24_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w510_info }, /* DW5932e-eSIM (sdx62), With eSIM */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f5), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx65_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5932e_info }, /* DW5932e (sdx62), Non-eSIM */ { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f9), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx65_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5932e_info }, + /* T99W515 (sdx72) */ + { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe118), + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w515_info }, + /* DW5934e(sdx72), With eSIM */ + { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe11d), + .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5934e_info }, + /* DW5934e(sdx72), Non-eSIM */ + { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe11e), + .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5934e_info }, /* MV31-W (Cinterion) */ { PCI_DEVICE(PCI_VENDOR_ID_THALES, 0x00b3), .driver_data = (kernel_ulong_t) &mhi_mv31_info }, @@ -694,7 +777,7 @@ static const struct pci_device_id mhi_pci_id_table[] = { .driver_data = (kernel_ulong_t) &mhi_mv32_info }, /* T99W175 (sdx55), HP variant */ { PCI_DEVICE(0x03f0, 0x0a6c), - .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info }, + .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w175_info }, { } }; MODULE_DEVICE_TABLE(pci, mhi_pci_id_table); @@ -1003,6 +1086,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mhi_cntrl->runtime_get = mhi_pci_runtime_get; mhi_cntrl->runtime_put = mhi_pci_runtime_put; mhi_cntrl->mru = info->mru_default; + mhi_cntrl->name = info->name; if (info->edl_trigger) mhi_cntrl->edl_trigger = mhi_pci_generic_edl_trigger; diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 84411b13c49f..b8d7115b8c9e 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -726,4 +726,5 @@ MODULE_PARM_DESC(aperture, "\t\tDefault: " DEFAULT_APERTURE_STRING "M"); MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); +MODULE_DESCRIPTION("Apple UniNorth & U3 AGP support"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 70d31aed9011..837109ef6766 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -342,5 +342,6 @@ static void __exit bsr_exit(void) module_init(bsr_init); module_exit(bsr_exit); +MODULE_DESCRIPTION("IBM POWER Barrier Synchronization Register Driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sonny Rao "); diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index bda27e595da1..1c2c8439797c 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -530,5 +530,6 @@ static void __exit dsp56k_cleanup_driver(void) } module_exit(dsp56k_cleanup_driver); +MODULE_DESCRIPTION("Atari DSP56001 Device Driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("dsp56k/bootstrap.bin"); diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 6946c1cad9f6..5a1a73310e97 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -660,4 +660,5 @@ static char dtlk_write_tts(char ch) return 0; } +MODULE_DESCRIPTION("RC Systems DoubleTalk PC speech card driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 2f171d14b9b5..24417a00dfe9 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -1016,7 +1016,6 @@ static struct parport_driver lp_driver = { .name = "lp", .match_port = lp_attach, .detach = lp_detach, - .devmodel = true, }; static int __init lp_init(void) @@ -1123,4 +1122,5 @@ module_init(lp_init_module); module_exit(lp_cleanup_module); MODULE_ALIAS_CHARDEV_MAJOR(LP_MAJOR); +MODULE_DESCRIPTION("Generic parallel printer driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index e9f694b36871..9eff426a9286 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -540,6 +540,7 @@ static void __exit nvram_module_exit(void) module_init(nvram_module_init); module_exit(nvram_module_exit); +MODULE_DESCRIPTION("CMOS/NV-RAM driver for Linux"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(NVRAM_MINOR); MODULE_ALIAS("devname:nvram"); diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 58e9dcc2a308..eaff98dbaa8c 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -839,7 +839,6 @@ static struct parport_driver pp_driver = { .probe = pp_probe, .match_port = pp_attach, .detach = pp_detach, - .devmodel = true, }; static int __init ppdev_init(void) @@ -882,5 +881,6 @@ static void __exit ppdev_cleanup(void) module_init(ppdev_init); module_exit(ppdev_cleanup); +MODULE_DESCRIPTION("Support for user-space parallel port device drivers"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(PP_MAJOR); diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 896a3550fba9..377bebf6c925 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -47,6 +47,7 @@ #include MODULE_AUTHOR("Sebastien Bouchard "); +MODULE_DESCRIPTION("Telecom Clock driver for Intel NetStructure(tm) MPCBL0010"); MODULE_LICENSE("GPL"); /*Hardware Reset of the PLL */ diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 4c806a189ee5..d7f841ab4323 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -228,4 +228,5 @@ static void __exit ttyprintk_exit(void) device_initcall(ttyprintk_init); module_exit(ttyprintk_exit); +MODULE_DESCRIPTION("TTY driver to output user messages via printk"); MODULE_LICENSE("GPL"); diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 497bc05dca4d..d30d22dfe577 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -138,7 +138,7 @@ config TI_ECAP_CAPTURE config TI_EQEP tristate "TI eQEP counter driver" - depends on (SOC_AM33XX || COMPILE_TEST) + depends on SOC_AM33XX || ARCH_K3 || COMPILE_TEST select REGMAP_MMIO help Select this option to enable the Texas Instruments Enhanced Quadrature diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c index aea6622a9b13..200876f3ec04 100644 --- a/drivers/counter/ftm-quaddec.c +++ b/drivers/counter/ftm-quaddec.c @@ -322,6 +322,7 @@ static struct platform_driver ftm_quaddec_driver = { module_platform_driver(ftm_quaddec_driver); +MODULE_DESCRIPTION("Flex Timer Module Quadrature decoder"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kjeld Flarup "); MODULE_AUTHOR("Patrick Havelange "); diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c index 825ae22c3ebc..313b91456f26 100644 --- a/drivers/counter/ti-eqep.c +++ b/drivers/counter/ti-eqep.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,44 @@ #define QEPCTL_UTE BIT(1) #define QEPCTL_WDE BIT(0) +#define QEINT_UTO BIT(11) +#define QEINT_IEL BIT(10) +#define QEINT_SEL BIT(9) +#define QEINT_PCM BIT(8) +#define QEINT_PCR BIT(7) +#define QEINT_PCO BIT(6) +#define QEINT_PCU BIT(5) +#define QEINT_WTO BIT(4) +#define QEINT_QDC BIT(3) +#define QEINT_PHE BIT(2) +#define QEINT_PCE BIT(1) + +#define QFLG_UTO BIT(11) +#define QFLG_IEL BIT(10) +#define QFLG_SEL BIT(9) +#define QFLG_PCM BIT(8) +#define QFLG_PCR BIT(7) +#define QFLG_PCO BIT(6) +#define QFLG_PCU BIT(5) +#define QFLG_WTO BIT(4) +#define QFLG_QDC BIT(3) +#define QFLG_PHE BIT(2) +#define QFLG_PCE BIT(1) +#define QFLG_INT BIT(0) + +#define QCLR_UTO BIT(11) +#define QCLR_IEL BIT(10) +#define QCLR_SEL BIT(9) +#define QCLR_PCM BIT(8) +#define QCLR_PCR BIT(7) +#define QCLR_PCO BIT(6) +#define QCLR_PCU BIT(5) +#define QCLR_WTO BIT(4) +#define QCLR_QDC BIT(3) +#define QCLR_PHE BIT(2) +#define QCLR_PCE BIT(1) +#define QCLR_INT BIT(0) + /* EQEP Inputs */ enum { TI_EQEP_SIGNAL_QEPA, /* QEPA/XCLK */ @@ -83,20 +122,14 @@ enum ti_eqep_count_func { }; struct ti_eqep_cnt { - struct counter_device counter; struct regmap *regmap32; struct regmap *regmap16; }; -static struct ti_eqep_cnt *ti_eqep_count_from_counter(struct counter_device *counter) -{ - return counter_priv(counter); -} - static int ti_eqep_count_read(struct counter_device *counter, struct counter_count *count, u64 *val) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 cnt; regmap_read(priv->regmap32, QPOSCNT, &cnt); @@ -108,7 +141,7 @@ static int ti_eqep_count_read(struct counter_device *counter, static int ti_eqep_count_write(struct counter_device *counter, struct counter_count *count, u64 val) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 max; regmap_read(priv->regmap32, QPOSMAX, &max); @@ -122,7 +155,7 @@ static int ti_eqep_function_read(struct counter_device *counter, struct counter_count *count, enum counter_function *function) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 qdecctl; regmap_read(priv->regmap16, QDECCTL, &qdecctl); @@ -149,7 +182,7 @@ static int ti_eqep_function_write(struct counter_device *counter, struct counter_count *count, enum counter_function function) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); enum ti_eqep_count_func qsrc; switch (function) { @@ -179,7 +212,7 @@ static int ti_eqep_action_read(struct counter_device *counter, struct counter_synapse *synapse, enum counter_synapse_action *action) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); enum counter_function function; u32 qdecctl; int err; @@ -239,19 +272,56 @@ static int ti_eqep_action_read(struct counter_device *counter, } } +static int ti_eqep_events_configure(struct counter_device *counter) +{ + struct ti_eqep_cnt *priv = counter_priv(counter); + struct counter_event_node *event_node; + u32 qeint = 0; + + list_for_each_entry(event_node, &counter->events_list, l) { + switch (event_node->event) { + case COUNTER_EVENT_OVERFLOW: + qeint |= QEINT_PCO; + break; + case COUNTER_EVENT_UNDERFLOW: + qeint |= QEINT_PCU; + break; + } + } + + return regmap_write(priv->regmap16, QEINT, qeint); +} + +static int ti_eqep_watch_validate(struct counter_device *counter, + const struct counter_watch *watch) +{ + switch (watch->event) { + case COUNTER_EVENT_OVERFLOW: + case COUNTER_EVENT_UNDERFLOW: + if (watch->channel != 0) + return -EINVAL; + + return 0; + default: + return -EINVAL; + } +} + static const struct counter_ops ti_eqep_counter_ops = { .count_read = ti_eqep_count_read, .count_write = ti_eqep_count_write, .function_read = ti_eqep_function_read, .function_write = ti_eqep_function_write, .action_read = ti_eqep_action_read, + .events_configure = ti_eqep_events_configure, + .watch_validate = ti_eqep_watch_validate, }; static int ti_eqep_position_ceiling_read(struct counter_device *counter, struct counter_count *count, u64 *ceiling) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 qposmax; regmap_read(priv->regmap32, QPOSMAX, &qposmax); @@ -265,7 +335,7 @@ static int ti_eqep_position_ceiling_write(struct counter_device *counter, struct counter_count *count, u64 ceiling) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); if (ceiling != (u32)ceiling) return -ERANGE; @@ -278,7 +348,7 @@ static int ti_eqep_position_ceiling_write(struct counter_device *counter, static int ti_eqep_position_enable_read(struct counter_device *counter, struct counter_count *count, u8 *enable) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); u32 qepctl; regmap_read(priv->regmap16, QEPCTL, &qepctl); @@ -291,7 +361,7 @@ static int ti_eqep_position_enable_read(struct counter_device *counter, static int ti_eqep_position_enable_write(struct counter_device *counter, struct counter_count *count, u8 enable) { - struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter); + struct ti_eqep_cnt *priv = counter_priv(counter); regmap_write_bits(priv->regmap16, QEPCTL, QEPCTL_PHEN, enable ? -1 : 0); @@ -355,6 +425,25 @@ static struct counter_count ti_eqep_counts[] = { }, }; +static irqreturn_t ti_eqep_irq_handler(int irq, void *dev_id) +{ + struct counter_device *counter = dev_id; + struct ti_eqep_cnt *priv = counter_priv(counter); + u32 qflg; + + regmap_read(priv->regmap16, QFLG, &qflg); + + if (qflg & QFLG_PCO) + counter_push_event(counter, COUNTER_EVENT_OVERFLOW, 0); + + if (qflg & QFLG_PCU) + counter_push_event(counter, COUNTER_EVENT_UNDERFLOW, 0); + + regmap_write(priv->regmap16, QCLR, qflg); + + return IRQ_HANDLED; +} + static const struct regmap_config ti_eqep_regmap32_config = { .name = "32-bit", .reg_bits = 32, @@ -378,7 +467,7 @@ static int ti_eqep_probe(struct platform_device *pdev) struct ti_eqep_cnt *priv; void __iomem *base; struct clk *clk; - int err; + int err, irq; counter = devm_counter_alloc(dev, sizeof(*priv)); if (!counter) @@ -399,6 +488,15 @@ static int ti_eqep_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap16)) return PTR_ERR(priv->regmap16); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + err = devm_request_threaded_irq(dev, irq, NULL, ti_eqep_irq_handler, + IRQF_ONESHOT, dev_name(dev), counter); + if (err < 0) + return dev_err_probe(dev, err, "failed to request IRQ\n"); + counter->name = dev_name(dev); counter->parent = dev; counter->ops = &ti_eqep_counter_ops; @@ -443,6 +541,7 @@ static void ti_eqep_remove(struct platform_device *pdev) static const struct of_device_id ti_eqep_of_match[] = { { .compatible = "ti,am3352-eqep", }, + { .compatible = "ti,am62-eqep", }, { }, }; MODULE_DEVICE_TABLE(of, ti_eqep_of_match); diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index ed3dac546dd6..f5cedf816be1 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -17,6 +17,7 @@ #define DCA_VERSION "1.12.1" MODULE_VERSION(DCA_VERSION); +MODULE_DESCRIPTION("Intel Direct Cache Access (DCA) service module"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index bdb752f11869..36943b0c6d60 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -620,6 +620,45 @@ static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan, return sg; } +static struct dma_async_tx_descriptor * +axi_dmac_prep_peripheral_dma_vec(struct dma_chan *c, const struct dma_vec *vecs, + size_t nb, enum dma_transfer_direction direction, + unsigned long flags) +{ + struct axi_dmac_chan *chan = to_axi_dmac_chan(c); + struct axi_dmac_desc *desc; + unsigned int num_sgs = 0; + struct axi_dmac_sg *dsg; + size_t i; + + if (direction != chan->direction) + return NULL; + + for (i = 0; i < nb; i++) + num_sgs += DIV_ROUND_UP(vecs[i].len, chan->max_length); + + desc = axi_dmac_alloc_desc(chan, num_sgs); + if (!desc) + return NULL; + + dsg = desc->sg; + + for (i = 0; i < nb; i++) { + if (!axi_dmac_check_addr(chan, vecs[i].addr) || + !axi_dmac_check_len(chan, vecs[i].len)) { + kfree(desc); + return NULL; + } + + dsg = axi_dmac_fill_linear_sg(chan, direction, vecs[i].addr, 1, + vecs[i].len, dsg); + } + + desc->cyclic = false; + + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); +} + static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg( struct dma_chan *c, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, @@ -1061,6 +1100,7 @@ static int axi_dmac_probe(struct platform_device *pdev) dma_dev->device_tx_status = dma_cookie_status; dma_dev->device_issue_pending = axi_dmac_issue_pending; dma_dev->device_prep_slave_sg = axi_dmac_prep_slave_sg; + dma_dev->device_prep_peripheral_dma_vec = axi_dmac_prep_peripheral_dma_vec; dma_dev->device_prep_dma_cyclic = axi_dmac_prep_dma_cyclic; dma_dev->device_prep_interleaved_dma = axi_dmac_prep_interleaved; dma_dev->device_terminate_all = axi_dmac_terminate_all; diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index 6b60ca004345..f4de3fea0b2d 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c @@ -75,12 +75,6 @@ static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable) return _alt_fpga2sdram_enable_set(bridge->priv, enable); } -struct prop_map { - char *prop_name; - u32 *prop_value; - u32 prop_max; -}; - static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = { .enable_set = alt_fpga2sdram_enable_set, .enable_show = alt_fpga2sdram_enable_show, diff --git a/drivers/fpga/tests/Kconfig b/drivers/fpga/tests/Kconfig index d4e55204c092..e4a64815f16d 100644 --- a/drivers/fpga/tests/Kconfig +++ b/drivers/fpga/tests/Kconfig @@ -1,6 +1,6 @@ config FPGA_KUNIT_TESTS - bool "KUnit test for the FPGA subsystem" if !KUNIT_ALL_TESTS - depends on FPGA=y && FPGA_REGION=y && FPGA_BRIDGE=y && KUNIT=y && MODULES=n + tristate "KUnit test for the FPGA subsystem" if !KUNIT_ALL_TESTS + depends on FPGA && FPGA_REGION && FPGA_BRIDGE && KUNIT=y default KUNIT_ALL_TESTS help This builds unit tests for the FPGA subsystem diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c index 42c2d8a99509..d4ade9325401 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_main.c +++ b/drivers/gpu/drm/vboxvideo/vbox_main.c @@ -42,12 +42,11 @@ static int vbox_accel_init(struct vbox_private *vbox) /* Take a command buffer for each screen from the end of usable VRAM. */ vbox->available_vram_size -= vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE; - vbox->vbva_buffers = pci_iomap_range(pdev, 0, - vbox->available_vram_size, - vbox->num_crtcs * - VBVA_MIN_BUFFER_SIZE); - if (!vbox->vbva_buffers) - return -ENOMEM; + vbox->vbva_buffers = pcim_iomap_range( + pdev, 0, vbox->available_vram_size, + vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE); + if (IS_ERR(vbox->vbva_buffers)) + return PTR_ERR(vbox->vbva_buffers); for (i = 0; i < vbox->num_crtcs; ++i) { vbva_setup_buffer_context(&vbox->vbva_info[i], @@ -116,11 +115,10 @@ int vbox_hw_init(struct vbox_private *vbox) DRM_INFO("VRAM %08x\n", vbox->full_vram_size); /* Map guest-heap at end of vram */ - vbox->guest_heap = - pci_iomap_range(pdev, 0, GUEST_HEAP_OFFSET(vbox), - GUEST_HEAP_SIZE); - if (!vbox->guest_heap) - return -ENOMEM; + vbox->guest_heap = pcim_iomap_range(pdev, 0, + GUEST_HEAP_OFFSET(vbox), GUEST_HEAP_SIZE); + if (IS_ERR(vbox->guest_heap)) + return PTR_ERR(vbox->guest_heap); /* Create guest-heap mem-pool use 2^4 = 16 byte chunks */ vbox->guest_pool = devm_gen_pool_create(vbox->ddev.dev, 4, -1, diff --git a/drivers/greybus/core.c b/drivers/greybus/core.c index 95c09d4f3a86..33a47e73f0fa 100644 --- a/drivers/greybus/core.c +++ b/drivers/greybus/core.c @@ -375,5 +375,6 @@ static void __exit gb_exit(void) tracepoint_synchronize_unregister(); } module_exit(gb_exit); +MODULE_DESCRIPTION("Greybus core driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/greybus/es2.c b/drivers/greybus/es2.c index 1ee78d0d90b4..69e46b1dff1f 100644 --- a/drivers/greybus/es2.c +++ b/drivers/greybus/es2.c @@ -1456,5 +1456,6 @@ static struct usb_driver es2_ap_driver = { module_usb_driver(es2_ap_driver); +MODULE_DESCRIPTION("Greybus AP USB driver for ES2 controller chips"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c index fab32e1e15f2..e376d4cde5ad 100644 --- a/drivers/hwmon/iio_hwmon.c +++ b/drivers/hwmon/iio_hwmon.c @@ -33,6 +33,17 @@ struct iio_hwmon_state { struct attribute **attrs; }; +static ssize_t iio_hwmon_read_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + struct iio_hwmon_state *state = dev_get_drvdata(dev); + struct iio_channel *chan = &state->channels[sattr->index]; + + return iio_read_channel_label(chan, buf); +} + /* * Assumes that IIO and hwmon operate in the same base units. * This is supposed to be true, but needs verification for @@ -69,12 +80,13 @@ static int iio_hwmon_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct iio_hwmon_state *st; struct sensor_device_attribute *a; - int ret, i; + int ret, i, attr = 0; int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1, power_i = 1; enum iio_chan_type type; struct iio_channel *channels; struct device *hwmon_dev; char *sname; + void *buf; channels = devm_iio_channel_get_all(dev); if (IS_ERR(channels)) { @@ -86,17 +98,18 @@ static int iio_hwmon_probe(struct platform_device *pdev) } st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); - if (st == NULL) + buf = (void *)devm_get_free_pages(dev, GFP_KERNEL, 0); + if (!st || !buf) return -ENOMEM; st->channels = channels; - /* count how many attributes we have */ + /* count how many channels we have */ while (st->channels[st->num_channels].indio_dev) st->num_channels++; st->attrs = devm_kcalloc(dev, - st->num_channels + 1, sizeof(*st->attrs), + 2 * st->num_channels + 1, sizeof(*st->attrs), GFP_KERNEL); if (st->attrs == NULL) return -ENOMEM; @@ -148,9 +161,31 @@ static int iio_hwmon_probe(struct platform_device *pdev) a->dev_attr.show = iio_hwmon_read_val; a->dev_attr.attr.mode = 0444; a->index = i; - st->attrs[i] = &a->dev_attr.attr; + st->attrs[attr++] = &a->dev_attr.attr; + + /* Let's see if we have a label... */ + if (iio_read_channel_label(&st->channels[i], buf) < 0) + continue; + + a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL); + if (a == NULL) + return -ENOMEM; + + sysfs_attr_init(&a->dev_attr.attr); + a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, + "%s%d_label", + prefix, n); + if (!a->dev_attr.attr.name) + return -ENOMEM; + + a->dev_attr.show = iio_hwmon_read_label; + a->dev_attr.attr.mode = 0444; + a->index = i; + st->attrs[attr++] = &a->dev_attr.attr; } + devm_free_pages(dev, (unsigned long)buf); + st->attr_group.attrs = st->attrs; st->groups[0] = &st->attr_group; diff --git a/drivers/hwmon/peci/cputemp.c b/drivers/hwmon/peci/cputemp.c index a812c15948d9..5a682195b98f 100644 --- a/drivers/hwmon/peci/cputemp.c +++ b/drivers/hwmon/peci/cputemp.c @@ -360,10 +360,10 @@ static int init_core_mask(struct peci_cputemp *priv) int ret; /* Get the RESOLVED_CORES register value */ - switch (peci_dev->info.model) { - case INTEL_FAM6_ICELAKE_X: - case INTEL_FAM6_ICELAKE_D: - case INTEL_FAM6_SAPPHIRERAPIDS_X: + switch (peci_dev->info.x86_vfm) { + case INTEL_ICELAKE_X: + case INTEL_ICELAKE_D: + case INTEL_SAPPHIRERAPIDS_X: ret = peci_ep_pci_local_read(peci_dev, 0, reg->bus, reg->dev, reg->func, reg->offset + 4, &data); if (ret) diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 9d550f5697fa..64e171eaad82 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -275,7 +275,7 @@ static int of_get_coresight_platform_data(struct device *dev, */ if (!parent) { /* - * Avoid warnings in of_graph_get_next_endpoint() + * Avoid warnings in for_each_endpoint_of_node() * if the device doesn't have any graph connections */ if (!of_graph_is_present(node)) @@ -286,7 +286,7 @@ static int of_get_coresight_platform_data(struct device *dev, } /* Iterate through each output port to discover topology */ - while ((ep = of_graph_get_next_endpoint(parent, ep))) { + for_each_endpoint_of_node(parent, ep) { /* * Legacy binding mixes input/output ports under the * same parent. So, skip the input ports if we are dealing @@ -297,8 +297,10 @@ static int of_get_coresight_platform_data(struct device *dev, continue; ret = of_coresight_parse_endpoint(dev, ep, pdata); - if (ret) + if (ret) { + of_node_put(ep); return ret; + } } return 0; diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index fc3617642b01..61a46d3bdcc8 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -13,7 +13,7 @@ #include extern struct mutex coresight_mutex; -extern struct device_type coresight_dev_type[]; +extern const struct device_type coresight_dev_type[]; /* * Coresight management registers (0xf00-0xfcc) diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index f9444e2cb1d9..1e67cc7758d7 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -377,7 +377,7 @@ static struct attribute *coresight_source_attrs[] = { }; ATTRIBUTE_GROUPS(coresight_source); -struct device_type coresight_dev_type[] = { +const struct device_type coresight_dev_type[] = { [CORESIGHT_DEV_TYPE_SINK] = { .name = "sink", .groups = coresight_sink_groups, diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index 4f11a739ae4d..b54562f392f3 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "coresight-priv.h" #include "coresight-tmc.h" diff --git a/drivers/hwtracing/intel_th/msu-sink.c b/drivers/hwtracing/intel_th/msu-sink.c index 891b28ea25fe..256ce3260ad9 100644 --- a/drivers/hwtracing/intel_th/msu-sink.c +++ b/drivers/hwtracing/intel_th/msu-sink.c @@ -116,4 +116,5 @@ static const struct msu_buffer sink_mbuf = { module_intel_th_msu_buffer(sink_mbuf); +MODULE_DESCRIPTION("example software sink buffer for Intel TH MSU"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index fe6e8a1bb607..3e32fb882101 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -159,6 +159,7 @@ config I2C_I801 Raptor Lake (PCH) Meteor Lake (SOC and PCH) Birch Stream (SOC) + Arrow Lake (SOC) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -857,7 +858,7 @@ config I2C_MT65XX config I2C_MT7621 tristate "MT7621/MT7628 I2C Controller" - depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || COMPILE_TEST + depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || ARCH_AIROHA || COMPILE_TEST help Say Y here to include support for I2C controller in the MediaTek MT7621/MT7628 SoCs. diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 63897a89bb35..ee4fd66dedb0 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -438,4 +438,5 @@ static struct pci_driver ali1563_pci_driver = { module_pci_driver(ali1563_pci_driver); +MODULE_DESCRIPTION("i2c driver for the ALi 1563 Southbridge"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 956e5020d71e..4761c7208102 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -39,7 +39,7 @@ We make sure that the SMB is enabled. We leave the ACPI alone. This driver controls the SMB Host only. - The SMB Slave controller on the M15X3 is not enabled. + The SMB Target controller on the M15X3 is not enabled. This driver does not use interrupts. */ diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c index 252fbd175fb1..f4dde08a3b92 100644 --- a/drivers/i2c/busses/i2c-altera.c +++ b/drivers/i2c/busses/i2c-altera.c @@ -168,7 +168,7 @@ static void altr_i2c_init(struct altr_i2c_dev *idev) /* SDA Hold Time, 300ns */ writel(3 * clk_mhz / 10, idev->base + ALTR_I2C_SDA_HOLD); - /* Mask all master interrupt bits */ + /* Mask all interrupt bits */ altr_i2c_int_enable(idev, ALTR_I2C_ALL_IRQ, false); } @@ -376,7 +376,7 @@ static u32 altr_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm altr_i2c_algo = { - .master_xfer = altr_i2c_xfer, + .xfer = altr_i2c_xfer, .functionality = altr_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index 8e43f25c117e..902e420e761e 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -81,11 +81,10 @@ static int wait_ack(struct i2c_au1550_data *adap) return 0; } -static int wait_master_done(struct i2c_au1550_data *adap) +static int wait_controller_done(struct i2c_au1550_data *adap) { int i; - /* Wait for Master Done. */ for (i = 0; i < 2 * adap->xfer_timeout; i++) { if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0) return 0; @@ -120,12 +119,12 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q) if (q) addr |= PSC_SMBTXRX_STP; - /* Put byte into fifo, start up master. */ + /* Put byte into fifo, start up controller */ WR(adap, PSC_SMBTXRX, addr); WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS); if (wait_ack(adap)) return -EIO; - return (q) ? wait_master_done(adap) : 0; + return (q) ? wait_controller_done(adap) : 0; } static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out) @@ -175,7 +174,7 @@ static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf, /* The last byte has to indicate transfer done. */ WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP); - if (wait_master_done(adap)) + if (wait_controller_done(adap)) return -EIO; buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff); @@ -204,7 +203,7 @@ static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf, data = buf[i]; data |= PSC_SMBTXRX_STP; WR(adap, PSC_SMBTXRX, data); - if (wait_master_done(adap)) + if (wait_controller_done(adap)) return -EIO; return 0; } @@ -246,8 +245,8 @@ static u32 au1550_func(struct i2c_adapter *adap) } static const struct i2c_algorithm au1550_algo = { - .master_xfer = au1550_xfer, - .functionality = au1550_func, + .xfer = au1550_xfer, + .functionality = au1550_func, }; static void i2c_au1550_setup(struct i2c_au1550_data *priv) diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index a57088ec2b06..eb5c46a8f824 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -85,7 +85,7 @@ #define STD_EXT_CLK_FREQ 13000000UL #define HS_EXT_CLK_FREQ 104000000UL -#define MASTERCODE 0x08 /* Mastercodes are 0000_1xxxb */ +#define CONTROLLER_CODE 0x08 /* Controller codes are 0000_1xxxb */ #define I2C_TIMEOUT 100 /* msecs */ @@ -544,8 +544,8 @@ static int bcm_kona_i2c_switch_to_hs(struct bcm_kona_i2c_dev *dev) { int rc; - /* Send mastercode at standard speed */ - rc = bcm_kona_i2c_write_byte(dev, MASTERCODE, 1); + /* Send controller code at standard speed */ + rc = bcm_kona_i2c_write_byte(dev, CONTROLLER_CODE, 1); if (rc < 0) { pr_err("High speed handshake failed\n"); return rc; @@ -587,7 +587,6 @@ static int bcm_kona_i2c_switch_to_std(struct bcm_kona_i2c_dev *dev) return rc; } -/* Master transfer function */ static int bcm_kona_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num) { @@ -637,7 +636,7 @@ static int bcm_kona_i2c_xfer(struct i2c_adapter *adapter, } } - /* Send slave address */ + /* Send target address */ if (!(pmsg->flags & I2C_M_NOSTART)) { rc = bcm_kona_i2c_do_addr(dev, pmsg); if (rc < 0) { @@ -697,7 +696,7 @@ static uint32_t bcm_kona_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm bcm_algo = { - .master_xfer = bcm_kona_i2c_xfer, + .xfer = bcm_kona_i2c_xfer, .functionality = bcm_kona_i2c_functionality, }; @@ -722,7 +721,7 @@ static int bcm_kona_i2c_assign_bus_speed(struct bcm_kona_i2c_dev *dev) dev->std_cfg = &std_cfg_table[BCM_SPD_1MHZ]; break; case I2C_MAX_HIGH_SPEED_MODE_FREQ: - /* Send mastercode at 100k */ + /* Send controller code at 100k */ dev->std_cfg = &std_cfg_table[BCM_SPD_100K]; dev->hs_cfg = &hs_cfg_table[BCM_SPD_3P4MHZ]; break; diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 3045ba82380d..ae42e37052a8 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * BCM2835 master mode driver + * BCM2835 I2C controller driver */ #include @@ -25,7 +25,7 @@ #define BCM2835_I2C_DEL 0x18 /* * 16-bit field for the number of SCL cycles to wait after rising SCL - * before deciding the slave is not responding. 0 disables the + * before deciding the target is not responding. 0 disables the * timeout detection. */ #define BCM2835_I2C_CLKT 0x1c @@ -223,7 +223,7 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) /* * Repeated Start Condition (Sr) * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it - * talks about reading from a slave with 10 bit address. This is achieved by + * talks about reading from a target with 10 bit address. This is achieved by * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then * issue a read. * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the @@ -390,8 +390,8 @@ static u32 bcm2835_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm bcm2835_i2c_algo = { - .master_xfer = bcm2835_i2c_xfer, - .functionality = bcm2835_i2c_func, + .xfer = bcm2835_i2c_xfer, + .functionality = bcm2835_i2c_func, }; /* diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 38f276c99193..83b85011e377 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -67,7 +67,7 @@ /* BSC block register map structure to cache fields to be written */ struct bsc_regs { - u32 chip_address; /* slave address */ + u32 chip_address; /* target address */ u32 data_in[N_DATA_REGS]; /* tx data buffer*/ u32 cnt_reg; /* rx/tx data length */ u32 ctl_reg; /* control register */ @@ -320,7 +320,7 @@ cmd_out: return rc; } -/* Actual data transfer through the BSC master */ +/* Actual data transfer through the BSC controller */ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev, u8 *buf, unsigned int len, struct i2c_msg *pmsg) @@ -441,7 +441,6 @@ static int brcmstb_i2c_do_addr(struct brcmstb_i2c_dev *dev, return 0; } -/* Master transfer function */ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num) { @@ -473,7 +472,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, brcmstb_set_i2c_start_stop(dev, cond); - /* Send slave address */ + /* Send target address */ if (!(pmsg->flags & I2C_M_NOSTART)) { rc = brcmstb_i2c_do_addr(dev, pmsg); if (rc < 0) { @@ -545,8 +544,8 @@ static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm brcmstb_i2c_algo = { - .master_xfer = brcmstb_i2c_xfer, - .master_xfer_atomic = brcmstb_i2c_xfer_atomic, + .xfer = brcmstb_i2c_xfer, + .xfer_atomic = brcmstb_i2c_xfer_atomic, .functionality = brcmstb_i2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-ccgx-ucsi.c b/drivers/i2c/busses/i2c-ccgx-ucsi.c index 092dc92dea9f..d97233862a6c 100644 --- a/drivers/i2c/busses/i2c-ccgx-ucsi.c +++ b/drivers/i2c/busses/i2c-ccgx-ucsi.c @@ -27,4 +27,5 @@ struct i2c_client *i2c_new_ccgx_ucsi(struct i2c_adapter *adapter, int irq, } EXPORT_SYMBOL_GPL(i2c_new_ccgx_ucsi); +MODULE_DESCRIPTION("Instantiate UCSI device for Cypress CCGx Type-C controller"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 0209933b9a84..52e3000626c5 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Intel CHT Whiskey Cove PMIC I2C Master driver + * Intel CHT Whiskey Cove PMIC I2C controller driver * Copyright (C) 2017 Hans de Goede * * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: @@ -106,7 +106,7 @@ static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) return IRQ_HANDLED; } -static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap) +static u32 cht_wc_i2c_adap_func(struct i2c_adapter *adap) { /* This i2c adapter only supports SMBUS byte transfers */ return I2C_FUNC_SMBUS_BYTE_DATA; @@ -168,7 +168,7 @@ static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, } static const struct i2c_algorithm cht_wc_i2c_adap_algo = { - .functionality = cht_wc_i2c_adap_master_func, + .functionality = cht_wc_i2c_adap_func, .smbus_xfer = cht_wc_i2c_adap_smbus_xfer, }; @@ -554,6 +554,6 @@ static struct platform_driver cht_wc_i2c_adap_driver = { }; module_platform_driver(cht_wc_i2c_adap_driver); -MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver"); +MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C controller driver"); MODULE_AUTHOR("Hans de Goede "); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-cp2615.c b/drivers/i2c/busses/i2c-cp2615.c index cf3747d87034..e7720ea4045e 100644 --- a/drivers/i2c/busses/i2c-cp2615.c +++ b/drivers/i2c/busses/i2c-cp2615.c @@ -60,11 +60,11 @@ enum cp2615_i2c_status { CP2615_CFG_LOCKED = -6, /* read_len or write_len out of range */ CP2615_INVALID_PARAM = -4, - /* I2C slave did not ACK in time */ + /* I2C target did not ACK in time */ CP2615_TIMEOUT, /* I2C bus busy */ CP2615_BUS_BUSY, - /* I2C bus error (ie. device NAK'd the request) */ + /* I2C bus error (ie. target NAK'd the request) */ CP2615_BUS_ERROR, CP2615_SUCCESS }; @@ -211,7 +211,7 @@ out: } static int -cp2615_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +cp2615_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct usb_interface *usbif = adap->algo_data; int i = 0, ret = 0; @@ -250,8 +250,8 @@ cp2615_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm cp2615_i2c_algo = { - .master_xfer = cp2615_i2c_master_xfer, - .functionality = cp2615_i2c_func, + .xfer = cp2615_i2c_xfer, + .functionality = cp2615_i2c_func, }; /* diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 4404b4aac676..4794ec066eb0 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -402,7 +402,7 @@ static u32 cpm_i2c_func(struct i2c_adapter *adap) /* -----exported algorithm data: ------------------------------------- */ static const struct i2c_algorithm cpm_i2c_algo = { - .master_xfer = cpm_i2c_xfer, + .xfer = cpm_i2c_xfer, .functionality = cpm_i2c_func, }; @@ -570,7 +570,7 @@ static int cpm_i2c_setup(struct cpm_i2c *cpm) out_8(&cpm->i2c_reg->i2brg, brg); out_8(&cpm->i2c_reg->i2mod, 0x00); - out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); /* Master mode */ + out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); /* Disable interrupts. */ out_8(&cpm->i2c_reg->i2cmr, 0); diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 2737fd8abd32..ab2688bd4d33 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -235,8 +235,8 @@ static u32 ec_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm ec_i2c_algorithm = { - .master_xfer = ec_i2c_xfer, - .functionality = ec_i2c_functionality, + .xfer = ec_i2c_xfer, + .functionality = ec_i2c_functionality, }; static int ec_i2c_probe(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 7ae611120cfa..c4fb5e9ab506 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -263,7 +263,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) /* compute clock dividers */ i2c_davinci_calc_clk_dividers(dev); - /* Respond at reserved "SMBus Host" slave address" (and zero); + /* Respond at reserved "SMBus Host" target address" (and zero); * we seem to have no option to not respond... */ davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, DAVINCI_I2C_OWN_ADDRESS); @@ -407,8 +407,8 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev) } /* - * Low level master read/write transaction. This function is called - * from i2c_davinci_xfer. + * Low level read/write transaction. This function is called from + * i2c_davinci_xfer. */ static int i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) @@ -428,7 +428,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) if (pdata->bus_delay) udelay(pdata->bus_delay); - /* set the slave address */ + /* set the target address */ davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr); dev->buf = msg->buf; @@ -440,10 +440,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) reinit_completion(&dev->cmd_complete); dev->cmd_err = 0; - /* Take I2C out of reset and configure it as master */ + /* Take I2C out of reset and configure it as controller */ flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; - /* if the slave address is ten bit address, enable XA bit */ if (msg->flags & I2C_M_TEN) flag |= DAVINCI_I2C_MDR_XA; if (!(msg->flags & I2C_M_RD)) @@ -687,7 +686,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) break; case DAVINCI_I2C_IVR_AAS: - dev_dbg(dev->dev, "Address as slave interrupt\n"); + dev_dbg(dev->dev, "Address as target interrupt\n"); break; default: @@ -744,8 +743,8 @@ static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) #endif static const struct i2c_algorithm i2c_davinci_algo = { - .master_xfer = i2c_davinci_xfer, - .functionality = i2c_davinci_func, + .xfer = i2c_davinci_xfer, + .functionality = i2c_davinci_func, }; static const struct of_device_id davinci_i2c_of_match[] = { diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 29aac9c87368..df3dc1e8093e 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -101,7 +101,7 @@ static int bt1_i2c_write(void *context, unsigned int reg, unsigned int val) BT1_I2C_CTL_GO | BT1_I2C_CTL_WR | (reg & BT1_I2C_CTL_ADDR_MASK)); } -static struct regmap_config bt1_i2c_cfg = { +static const struct regmap_config bt1_i2c_cfg = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c index 737604ae11fc..3e6b80e59b90 100644 --- a/drivers/i2c/busses/i2c-digicolor.c +++ b/drivers/i2c/busses/i2c-digicolor.c @@ -281,8 +281,8 @@ static u32 dc_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm dc_i2c_algorithm = { - .master_xfer = dc_i2c_xfer, - .functionality = dc_i2c_func, + .xfer = dc_i2c_xfer, + .functionality = dc_i2c_func, }; static int dc_i2c_probe(struct platform_device *pdev) @@ -372,5 +372,5 @@ static struct platform_driver dc_i2c_driver = { module_platform_driver(dc_i2c_driver); MODULE_AUTHOR("Baruch Siach "); -MODULE_DESCRIPTION("Conexant Digicolor I2C master driver"); +MODULE_DESCRIPTION("Conexant Digicolor I2C controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index b48b7888936f..c02459405b26 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -414,7 +414,7 @@ static u32 diolan_usb_func(struct i2c_adapter *a) } static const struct i2c_algorithm diolan_usb_algorithm = { - .master_xfer = diolan_usb_xfer, + .xfer = diolan_usb_xfer, .functionality = diolan_usb_func, }; diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c index 631109c7a098..11ed055143d3 100644 --- a/drivers/i2c/busses/i2c-dln2.c +++ b/drivers/i2c/busses/i2c-dln2.c @@ -175,7 +175,7 @@ static u32 dln2_i2c_func(struct i2c_adapter *a) } static const struct i2c_algorithm dln2_i2c_usb_algorithm = { - .master_xfer = dln2_i2c_xfer, + .xfer = dln2_i2c_xfer, .functionality = dln2_i2c_func, }; @@ -251,6 +251,6 @@ static struct platform_driver dln2_i2c_driver = { module_platform_driver(dln2_i2c_driver); MODULE_AUTHOR("Laurentiu Palcu "); -MODULE_DESCRIPTION("Driver for the Diolan DLN2 I2C master interface"); +MODULE_DESCRIPTION("Driver for the Diolan DLN2 I2C controller interface"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:dln2-i2c"); diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c index 10332693edf0..ae016a9431da 100644 --- a/drivers/i2c/busses/i2c-fsi.c +++ b/drivers/i2c/busses/i2c-fsi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * FSI-attached I2C master algorithm + * FSI-attached I2C controller algorithm * * Copyright 2018 IBM Corporation * @@ -145,7 +145,7 @@ /* choose timeout length from legacy driver; it's well tested */ #define I2C_ABORT_TIMEOUT msecs_to_jiffies(100) -struct fsi_i2c_master { +struct fsi_i2c_ctrl { struct fsi_device *fsi; u8 fifo_size; struct list_head ports; @@ -155,7 +155,7 @@ struct fsi_i2c_master { struct fsi_i2c_port { struct list_head list; struct i2c_adapter adapter; - struct fsi_i2c_master *master; + struct fsi_i2c_ctrl *ctrl; u16 port; u16 xfrd; }; @@ -183,7 +183,7 @@ static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg, return fsi_device_write(fsi, reg, &data_be, sizeof(data_be)); } -static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c) +static int fsi_i2c_dev_init(struct fsi_i2c_ctrl *i2c) { int rc; u32 mode = I2C_MODE_ENHANCED, extended_status, watermark; @@ -214,7 +214,7 @@ static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c) static int fsi_i2c_set_port(struct fsi_i2c_port *port) { int rc; - struct fsi_device *fsi = port->master->fsi; + struct fsi_device *fsi = port->ctrl->fsi; u32 mode, dummy = 0; rc = fsi_i2c_read_reg(fsi, I2C_FSI_MODE, &mode); @@ -236,7 +236,7 @@ static int fsi_i2c_set_port(struct fsi_i2c_port *port) static int fsi_i2c_start(struct fsi_i2c_port *port, struct i2c_msg *msg, bool stop) { - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; u32 cmd = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR; port->xfrd = 0; @@ -268,7 +268,7 @@ static int fsi_i2c_write_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg, { int write; int rc; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; int bytes_to_write = i2c->fifo_size - fifo_count; int bytes_remaining = msg->len - port->xfrd; @@ -294,7 +294,7 @@ static int fsi_i2c_read_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg, { int read; int rc; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; int bytes_to_read; int xfr_remaining = msg->len - port->xfrd; u32 dummy; @@ -330,7 +330,7 @@ static int fsi_i2c_get_scl(struct i2c_adapter *adap) { u32 stat = 0; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); @@ -341,7 +341,7 @@ static void fsi_i2c_set_scl(struct i2c_adapter *adap, int val) { u32 dummy = 0; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; if (val) fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy); @@ -353,7 +353,7 @@ static int fsi_i2c_get_sda(struct i2c_adapter *adap) { u32 stat = 0; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); @@ -364,7 +364,7 @@ static void fsi_i2c_set_sda(struct i2c_adapter *adap, int val) { u32 dummy = 0; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; if (val) fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SDA, &dummy); @@ -377,7 +377,7 @@ static void fsi_i2c_prepare_recovery(struct i2c_adapter *adap) int rc; u32 mode; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); if (rc) @@ -392,7 +392,7 @@ static void fsi_i2c_unprepare_recovery(struct i2c_adapter *adap) int rc; u32 mode; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); if (rc) @@ -402,7 +402,7 @@ static void fsi_i2c_unprepare_recovery(struct i2c_adapter *adap) fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); } -static int fsi_i2c_reset_bus(struct fsi_i2c_master *i2c, +static int fsi_i2c_reset_bus(struct fsi_i2c_ctrl *i2c, struct fsi_i2c_port *port) { int rc; @@ -435,7 +435,7 @@ static int fsi_i2c_reset_bus(struct fsi_i2c_master *i2c, return fsi_i2c_dev_init(i2c); } -static int fsi_i2c_reset_engine(struct fsi_i2c_master *i2c, u16 port) +static int fsi_i2c_reset_engine(struct fsi_i2c_ctrl *i2c, u16 port) { int rc; u32 mode, dummy = 0; @@ -478,7 +478,7 @@ static int fsi_i2c_abort(struct fsi_i2c_port *port, u32 status) unsigned long start; u32 cmd = I2C_CMD_WITH_STOP; u32 stat; - struct fsi_i2c_master *i2c = port->master; + struct fsi_i2c_ctrl *i2c = port->ctrl; struct fsi_device *fsi = i2c->fsi; rc = fsi_i2c_reset_engine(i2c, port->port); @@ -505,7 +505,7 @@ static int fsi_i2c_abort(struct fsi_i2c_port *port, u32 status) if (rc) return rc; - /* wait until we see command complete in the master */ + /* wait until we see command complete in the controller */ start = jiffies; do { @@ -579,7 +579,7 @@ static int fsi_i2c_wait(struct fsi_i2c_port *port, struct i2c_msg *msg, unsigned long start = jiffies; do { - rc = fsi_i2c_read_reg(port->master->fsi, I2C_FSI_STAT, + rc = fsi_i2c_read_reg(port->ctrl->fsi, I2C_FSI_STAT, &status); if (rc) return rc; @@ -609,10 +609,10 @@ static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int i, rc; unsigned long start_time; struct fsi_i2c_port *port = adap->algo_data; - struct fsi_i2c_master *master = port->master; + struct fsi_i2c_ctrl *ctrl = port->ctrl; struct i2c_msg *msg; - mutex_lock(&master->lock); + mutex_lock(&ctrl->lock); rc = fsi_i2c_set_port(port); if (rc) @@ -633,7 +633,7 @@ static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } unlock: - mutex_unlock(&master->lock); + mutex_unlock(&ctrl->lock); return rc ? : num; } @@ -654,7 +654,7 @@ static struct i2c_bus_recovery_info fsi_i2c_bus_recovery_info = { }; static const struct i2c_algorithm fsi_i2c_algorithm = { - .master_xfer = fsi_i2c_xfer, + .xfer = fsi_i2c_xfer, .functionality = fsi_i2c_functionality, }; @@ -676,7 +676,7 @@ static struct device_node *fsi_i2c_find_port_of_node(struct device_node *fsi, static int fsi_i2c_probe(struct device *dev) { - struct fsi_i2c_master *i2c; + struct fsi_i2c_ctrl *i2c; struct fsi_i2c_port *port; struct device_node *np; u32 port_no, ports, stat; @@ -699,7 +699,7 @@ static int fsi_i2c_probe(struct device *dev) return rc; ports = FIELD_GET(I2C_STAT_MAX_PORT, stat) + 1; - dev_dbg(dev, "I2C master has %d ports\n", ports); + dev_dbg(dev, "I2C controller has %d ports\n", ports); for (port_no = 0; port_no < ports; port_no++) { np = fsi_i2c_find_port_of_node(dev->of_node, port_no); @@ -712,7 +712,7 @@ static int fsi_i2c_probe(struct device *dev) break; } - port->master = i2c; + port->ctrl = i2c; port->port = port_no; port->adapter.owner = THIS_MODULE; @@ -742,7 +742,7 @@ static int fsi_i2c_probe(struct device *dev) static int fsi_i2c_remove(struct device *dev) { - struct fsi_i2c_master *i2c = dev_get_drvdata(dev); + struct fsi_i2c_ctrl *i2c = dev_get_drvdata(dev); struct fsi_i2c_port *port, *tmp; list_for_each_entry_safe(port, tmp, &i2c->ports, list) { @@ -772,5 +772,5 @@ static struct fsi_driver fsi_i2c_driver = { module_fsi_driver(fsi_i2c_driver); MODULE_AUTHOR("Eddie James "); -MODULE_DESCRIPTION("FSI attached I2C master"); +MODULE_DESCRIPTION("FSI attached I2C controller"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 4f1411b1a775..e0bd218e2f14 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -216,8 +216,8 @@ static int fops_lose_arbitration_set(void *data, u64 duration) priv->scl_irq_data = duration; /* - * Interrupt on falling SCL. This ensures that the master under test has - * really started the transfer. Interrupt on falling SDA did only + * Interrupt on falling SCL. This ensures that the controller under test + * has really started the transfer. Interrupt on falling SDA did only * exercise 'bus busy' detection on some HW but not 'arbitration lost'. * Note that the interrupt latency may cause the first bits to be * transmitted correctly. @@ -245,8 +245,8 @@ static int fops_inject_panic_set(void *data, u64 duration) priv->scl_irq_data = duration; /* - * Interrupt on falling SCL. This ensures that the master under test has - * really started the transfer. + * Interrupt on falling SCL. This ensures that the controller under test + * has really started the transfer. */ return i2c_gpio_fi_act_on_scl_irq(priv, inject_panic_irq); } diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index 7922bc917c33..ec1ebacb9aa8 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -331,7 +331,7 @@ static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, /* Ensure we're in a sane state */ highlander_i2c_done(dev); - /* Set slave address */ + /* Set target address */ iowrite16((addr << 1) | read_write, dev->base + SMSMADR); highlander_i2c_command(dev, command, dev->buf_len); diff --git a/drivers/i2c/busses/i2c-hisi.c b/drivers/i2c/busses/i2c-hisi.c index 975c0b1c44de..4b735ad9e193 100644 --- a/drivers/i2c/busses/i2c-hisi.c +++ b/drivers/i2c/busses/i2c-hisi.c @@ -197,8 +197,8 @@ static void hisi_i2c_reset_xfer(struct hisi_i2c_controller *ctlr) * wait for the transfer done. The major transfer process is performed * in the IRQ handler. */ -static int hisi_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) +static int hisi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) { struct hisi_i2c_controller *ctlr = i2c_get_adapdata(adap); DECLARE_COMPLETION_ONSTACK(done); @@ -236,8 +236,8 @@ static u32 hisi_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm hisi_i2c_algo = { - .master_xfer = hisi_i2c_master_xfer, - .functionality = hisi_i2c_functionality, + .xfer = hisi_i2c_xfer, + .functionality = hisi_i2c_functionality, }; static int hisi_i2c_read_rx_fifo(struct hisi_i2c_controller *ctlr) diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index a47b9939fa2c..64cade6ba923 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -200,7 +200,7 @@ static void hix5hd2_read_handle(struct hix5hd2_i2c_priv *priv) /* the last byte don't need send ACK */ writel_relaxed(I2C_READ | I2C_NO_ACK, priv->regs + HIX5I2C_COM); } else if (priv->msg_len > 1) { - /* if i2c master receive data will send ACK */ + /* if i2c controller receive data will send ACK */ writel_relaxed(I2C_READ, priv->regs + HIX5I2C_COM); } else { hix5hd2_rw_handle_stop(priv); @@ -384,8 +384,8 @@ static u32 hix5hd2_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm hix5hd2_i2c_algorithm = { - .master_xfer = hix5hd2_i2c_xfer, - .functionality = hix5hd2_i2c_func, + .xfer = hix5hd2_i2c_xfer, + .functionality = hix5hd2_i2c_func, }; static int hix5hd2_i2c_probe(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index d2d2a6dbe29f..328c0dab6b14 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -80,6 +80,7 @@ * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes * Birch Stream (SOC) 0x5796 32 hard yes yes yes + * Arrow Lake-H (SOC) 0x7722 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -87,7 +88,7 @@ * Block buffer yes * Block process call transaction yes * I2C block read transaction yes (doesn't use the block buffer) - * Slave mode no + * Target mode no * SMBus Host Notify yes * Interrupt processing yes * @@ -237,6 +238,7 @@ #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3 #define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 +#define PCI_DEVICE_ID_INTEL_ARROW_LAKE_H_SMBUS 0x7722 #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22 @@ -1052,6 +1054,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { 0, } }; @@ -1274,10 +1277,10 @@ static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) i2c_new_client_device(&priv->adapter, &info); } -/* Register optional slaves */ -static void i801_probe_optional_slaves(struct i801_priv *priv) +/* Register optional targets */ +static void i801_probe_optional_targets(struct i801_priv *priv) { - /* Only register slaves on main SMBus channel */ + /* Only register targets on main SMBus channel */ if (priv->features & FEATURE_IDF) return; @@ -1304,7 +1307,7 @@ static void i801_probe_optional_slaves(struct i801_priv *priv) } #else static void __init input_apanel_init(void) {} -static void i801_probe_optional_slaves(struct i801_priv *priv) {} +static void i801_probe_optional_targets(struct i801_priv *priv) {} #endif /* CONFIG_X86 && CONFIG_DMI */ #ifdef CONFIG_I2C_I801_MUX @@ -1774,7 +1777,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) /* We ignore errors - multiplexing is optional */ i801_add_mux(priv); - i801_probe_optional_slaves(priv); + i801_probe_optional_targets(priv); pci_set_drvdata(dev, priv); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 7fb87b78923e..82dedb1bb5be 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -136,11 +136,11 @@ static void iic_dev_init(struct ibm_iic_private* dev) DBG("%d: init\n", dev->idx); - /* Clear master address */ + /* Clear remote target address */ out_8(&iic->lmadr, 0); out_8(&iic->hmadr, 0); - /* Clear slave address */ + /* Clear local target address */ out_8(&iic->lsadr, 0); out_8(&iic->hsadr, 0); @@ -337,7 +337,7 @@ static irqreturn_t iic_handler(int irq, void *dev_id) } /* - * Get master transfer result and clear errors if any. + * Get controller transfer result and clear errors if any. * Returns the number of actually transferred bytes or error (<0) */ static int iic_xfer_result(struct ibm_iic_private* dev) @@ -352,7 +352,7 @@ static int iic_xfer_result(struct ibm_iic_private* dev) out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA); - /* Flush master data buffer */ + /* Flush controller data buffer */ out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); /* Is bus free? @@ -401,7 +401,7 @@ static void iic_abort_xfer(struct ibm_iic_private* dev) } /* - * Wait for master transfer to complete. + * Wait for controller transfer to complete. * It puts current process to sleep until we get interrupt or timeout expires. * Returns the number of transferred bytes or error (<0) */ @@ -452,9 +452,6 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){ return ret; } -/* - * Low level master transfer routine - */ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, int combined_xfer) { @@ -511,9 +508,7 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, return ret > 0 ? 0 : ret; } -/* - * Set target slave address for master transfer - */ +/* Set remote target address for transfer */ static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) { volatile struct iic_regs __iomem *iic = dev->vaddr; @@ -546,7 +541,7 @@ static inline int iic_address_neq(const struct i2c_msg* p1, } /* - * Generic master transfer entrypoint. + * Generic transfer entrypoint. * Returns the number of processed messages or error (<0) */ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) @@ -604,11 +599,11 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) } } else { - /* Flush master data buffer (just in case) */ + /* Flush controller data buffer (just in case) */ out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); } - /* Load slave address */ + /* Load target address */ iic_address(dev, &msgs[0]); /* Do real transfer */ @@ -624,8 +619,8 @@ static u32 iic_func(struct i2c_adapter *adap) } static const struct i2c_algorithm iic_algo = { - .master_xfer = iic_xfer, - .functionality = iic_func + .xfer = iic_xfer, + .functionality = iic_func }; /* diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 2e5f0165c3d3..859c14e340e7 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -22,7 +22,7 @@ * - Make it work with IXP46x chips * - Cleanup function names, coding style, etc * - * - writing to slave address causes latchup on iop331. + * - writing to local target address causes latchup on iop331. * fix: driver refuses to address self. */ @@ -234,7 +234,7 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, int status; int rc; - /* avoid writing to my slave address (hangs on 80331), + /* avoid writing to local target address (hangs on 80331), * forbidden in Intel developer manual */ if (msg->addr == MYSAR) { @@ -349,12 +349,9 @@ iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg *pmsg) } } -/* - * master_xfer() - main read/write entry - */ static int -iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, - int num) +iop3xx_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, + int num) { struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; int im = 0; @@ -384,8 +381,8 @@ iop3xx_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm iop3xx_i2c_algo = { - .master_xfer = iop3xx_i2c_master_xfer, - .functionality = iop3xx_i2c_func, + .xfer = iop3xx_i2c_xfer, + .functionality = iop3xx_i2c_func, }; static void diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 416a9968ed28..33dbc19d3848 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -104,7 +104,7 @@ static int sch_transaction(void) result = -EIO; dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " "locked until next hard reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ + /* Clock stops and target is stuck in mid-transmission */ } else if (temp & 0x02) { result = -EIO; dev_err(&sch_adapter.dev, "Error: no response!\n"); diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 7951891d6b97..4aafdfab6305 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -730,8 +730,8 @@ static u32 jz4780_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm jz4780_i2c_algorithm = { - .master_xfer = jz4780_i2c_xfer, - .functionality = jz4780_i2c_functionality, + .xfer = jz4780_i2c_xfer, + .functionality = jz4780_i2c_functionality, }; static const struct ingenic_i2c_config jz4780_i2c_config = { diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index c3a529a73b5b..eb66942e0b7d 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -276,8 +276,8 @@ static u32 kempld_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm kempld_i2c_algorithm = { - .master_xfer = kempld_i2c_xfer, - .functionality = kempld_i2c_func, + .xfer = kempld_i2c_xfer, + .functionality = kempld_i2c_func, }; static const struct i2c_adapter kempld_i2c_adapter = { diff --git a/drivers/i2c/busses/i2c-ljca.c b/drivers/i2c/busses/i2c-ljca.c index b4927622177c..0b70621cf9d3 100644 --- a/drivers/i2c/busses/i2c-ljca.c +++ b/drivers/i2c/busses/i2c-ljca.c @@ -76,7 +76,7 @@ static int ljca_i2c_init(struct ljca_i2c_dev *ljca_i2c, u8 id) return ret < 0 ? ret : 0; } -static int ljca_i2c_start(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr, +static int ljca_i2c_start(struct ljca_i2c_dev *ljca_i2c, u8 target_addr, enum ljca_xfer_type type) { struct ljca_i2c_rw_packet *w_packet = @@ -88,7 +88,7 @@ static int ljca_i2c_start(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr, w_packet->id = ljca_i2c->i2c_info->id; w_packet->len = cpu_to_le16(sizeof(*w_packet->data)); - w_packet->data[0] = (slave_addr << 1) | type; + w_packet->data[0] = (target_addr << 1) | type; ret = ljca_transfer(ljca_i2c->ljca, LJCA_I2C_START, (u8 *)w_packet, struct_size(w_packet, data, 1), (u8 *)r_packet, @@ -107,7 +107,7 @@ static int ljca_i2c_start(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr, return 0; } -static void ljca_i2c_stop(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr) +static void ljca_i2c_stop(struct ljca_i2c_dev *ljca_i2c, u8 target_addr) { struct ljca_i2c_rw_packet *w_packet = (struct ljca_i2c_rw_packet *)ljca_i2c->obuf; @@ -169,16 +169,16 @@ static int ljca_i2c_pure_read(struct ljca_i2c_dev *ljca_i2c, u8 *data, u8 len) return 0; } -static int ljca_i2c_read(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr, u8 *data, +static int ljca_i2c_read(struct ljca_i2c_dev *ljca_i2c, u8 target_addr, u8 *data, u8 len) { int ret; - ret = ljca_i2c_start(ljca_i2c, slave_addr, LJCA_I2C_READ_XFER_TYPE); + ret = ljca_i2c_start(ljca_i2c, target_addr, LJCA_I2C_READ_XFER_TYPE); if (!ret) ret = ljca_i2c_pure_read(ljca_i2c, data, len); - ljca_i2c_stop(ljca_i2c, slave_addr); + ljca_i2c_stop(ljca_i2c, target_addr); return ret; } @@ -213,16 +213,16 @@ static int ljca_i2c_pure_write(struct ljca_i2c_dev *ljca_i2c, u8 *data, u8 len) return 0; } -static int ljca_i2c_write(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr, +static int ljca_i2c_write(struct ljca_i2c_dev *ljca_i2c, u8 target_addr, u8 *data, u8 len) { int ret; - ret = ljca_i2c_start(ljca_i2c, slave_addr, LJCA_I2C_WRITE_XFER_TYPE); + ret = ljca_i2c_start(ljca_i2c, target_addr, LJCA_I2C_WRITE_XFER_TYPE); if (!ret) ret = ljca_i2c_pure_write(ljca_i2c, data, len); - ljca_i2c_stop(ljca_i2c, slave_addr); + ljca_i2c_stop(ljca_i2c, target_addr); return ret; } @@ -266,7 +266,7 @@ static const struct i2c_adapter_quirks ljca_i2c_quirks = { }; static const struct i2c_algorithm ljca_i2c_algo = { - .master_xfer = ljca_i2c_xfer, + .xfer = ljca_i2c_xfer, .functionality = ljca_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index e3660333e91c..9fb33cbf7419 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -50,7 +50,7 @@ /* * 26 possible I2C status codes, but codes applicable only - * to master are listed here and used in this driver + * to controller mode are listed here and used in this driver */ enum { M_BUS_ERROR = 0x00, @@ -157,7 +157,7 @@ static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) break; case MR_ADDR_R_ACK: - /* Receive first byte from slave */ + /* Receive first byte from target */ if (i2c->msg->len == 1) { /* Last byte, return NACK */ writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); @@ -196,7 +196,7 @@ static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) } /* - * One pre-last data input, send NACK to tell the slave that + * One pre-last data input, send NACK to tell the target that * this is going to be the last data byte to be transferred. */ if (i2c->msg_idx >= i2c->msg->len - 2) { @@ -338,8 +338,8 @@ static u32 i2c_lpc2k_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm i2c_lpc2k_algorithm = { - .master_xfer = i2c_lpc2k_xfer, - .functionality = i2c_lpc2k_functionality, + .xfer = i2c_lpc2k_xfer, + .functionality = i2c_lpc2k_functionality, }; static int i2c_lpc2k_probe(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c index ebae6035701d..8821cac3897b 100644 --- a/drivers/i2c/busses/i2c-ls2x.c +++ b/drivers/i2c/busses/i2c-ls2x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Loongson-2K/Loongson LS7A I2C master mode driver + * Loongson-2K/Loongson LS7A I2C controller mode driver * * Copyright (C) 2013 Loongson Technology Corporation Limited. * Copyright (C) 2014-2017 Lemote, Inc. @@ -51,7 +51,7 @@ /* Control Register Bit */ #define LS2X_CTR_EN BIT(7) /* 0: I2c frequency setting 1: Normal */ #define LS2X_CTR_IEN BIT(6) /* Enable i2c interrupt */ -#define LS2X_CTR_MST BIT(5) /* 0: Slave mode 1: Master mode */ +#define LS2X_CTR_MST BIT(5) /* 0: Target mode 1: Controller mode */ #define CTR_FREQ_MASK GENMASK(7, 6) #define CTR_READY_MASK GENMASK(7, 5) @@ -251,8 +251,7 @@ static int ls2x_i2c_xfer_one(struct ls2x_i2c_priv *priv, return ret; } -static int ls2x_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int ls2x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret; struct i2c_msg *msg, *emsg = msgs + num; @@ -273,8 +272,8 @@ static unsigned int ls2x_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm ls2x_i2c_algo = { - .master_xfer = ls2x_i2c_master_xfer, - .functionality = ls2x_i2c_func, + .xfer = ls2x_i2c_xfer, + .functionality = ls2x_i2c_func, }; static int ls2x_i2c_probe(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index 099291a0411d..8223f6d29eb3 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -197,8 +197,8 @@ static int mlxcpld_i2c_check_status(struct mlxcpld_i2c_priv *priv, int *status) if (val & MLXCPLD_LPCI2C_TRANS_END) { if (val & MLXCPLD_LPCI2C_STATUS_NACK) /* - * The slave is unable to accept the data. No such - * slave, command not understood, or unable to accept + * The target is unable to accept the data. No such + * target, command not understood, or unable to accept * any more data. */ *status = MLXCPLD_LPCI2C_NACK_IND; @@ -280,7 +280,7 @@ static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv) } /* - * Wait for master transfer to complete. + * Wait for transfer to complete. * It puts current process to sleep until we get interrupt or timeout expires. * Returns the number of transferred or read bytes or error (<0). */ @@ -315,7 +315,7 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv) /* * Actual read data len will be always the same as * requested len. 0xff (line pull-up) will be returned - * if slave has no data to return. Thus don't read + * if target has no data to return. Thus don't read * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD. Only in case of * SMBus block read transaction data len can be different, * check this case. @@ -375,7 +375,7 @@ static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv) } /* - * Set target slave address with command for master transfer. + * Set target address with command for transfer. * It should be latest executed function before CPLD transaction. */ cmd = (priv->xfer.msg[0].addr << 1) | priv->xfer.cmd; @@ -449,8 +449,8 @@ static u32 mlxcpld_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm mlxcpld_i2c_algo = { - .master_xfer = mlxcpld_i2c_xfer, - .functionality = mlxcpld_i2c_func + .xfer = mlxcpld_i2c_xfer, + .functionality = mlxcpld_i2c_func }; static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = { diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index c4223556b3b8..41d6c8ed163a 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -115,7 +115,7 @@ static inline void writeccr(struct mpc_i2c *i2c, u32 x) writeb(x, i2c->base + MPC_I2C_CR); } -/* Sometimes 9th clock pulse isn't generated, and slave doesn't release +/* Sometimes 9th clock pulse isn't generated, and target doesn't release * the bus, because it wants to send ACK. * Following sequence of enabling/disabling and sending start/stop generates * the 9 pulses, each with a START then ending with STOP, so it's all OK. @@ -759,7 +759,7 @@ static int fsl_i2c_bus_recovery(struct i2c_adapter *adap) } static const struct i2c_algorithm mpc_algo = { - .master_xfer = mpc_xfer, + .xfer = mpc_xfer, .functionality = mpc_functionality, }; diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c index 81d46169bc1f..23d417ff5e71 100644 --- a/drivers/i2c/busses/i2c-mt7621.c +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -117,27 +117,27 @@ static int mtk_i2c_check_ack(struct mtk_i2c *i2c, u32 expected) return ((ack & ack_expected) == ack_expected) ? 0 : -ENXIO; } -static int mtk_i2c_master_start(struct mtk_i2c *i2c) +static int mtk_i2c_start(struct mtk_i2c *i2c) { iowrite32(SM0CTL1_START | SM0CTL1_TRI, i2c->base + REG_SM0CTL1_REG); return mtk_i2c_wait_idle(i2c); } -static int mtk_i2c_master_stop(struct mtk_i2c *i2c) +static int mtk_i2c_stop(struct mtk_i2c *i2c) { iowrite32(SM0CTL1_STOP | SM0CTL1_TRI, i2c->base + REG_SM0CTL1_REG); return mtk_i2c_wait_idle(i2c); } -static int mtk_i2c_master_cmd(struct mtk_i2c *i2c, u32 cmd, int page_len) +static int mtk_i2c_cmd(struct mtk_i2c *i2c, u32 cmd, int page_len) { iowrite32(cmd | SM0CTL1_TRI | SM0CTL1_PGLEN(page_len), i2c->base + REG_SM0CTL1_REG); return mtk_i2c_wait_idle(i2c); } -static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) +static int mtk_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) { struct mtk_i2c *i2c; struct i2c_msg *pmsg; @@ -157,7 +157,7 @@ static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, goto err_timeout; /* start sequence */ - ret = mtk_i2c_master_start(i2c); + ret = mtk_i2c_start(i2c); if (ret) goto err_timeout; @@ -169,14 +169,14 @@ static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, if (pmsg->flags & I2C_M_RD) addr |= 1; iowrite32(addr, i2c->base + REG_SM0D0_REG); - ret = mtk_i2c_master_cmd(i2c, SM0CTL1_WRITE, 2); + ret = mtk_i2c_cmd(i2c, SM0CTL1_WRITE, 2); if (ret) goto err_timeout; } else { /* 7 bits address */ addr = i2c_8bit_addr_from_msg(pmsg); iowrite32(addr, i2c->base + REG_SM0D0_REG); - ret = mtk_i2c_master_cmd(i2c, SM0CTL1_WRITE, 1); + ret = mtk_i2c_cmd(i2c, SM0CTL1_WRITE, 1); if (ret) goto err_timeout; } @@ -202,7 +202,7 @@ static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, cmd = SM0CTL1_WRITE; } - ret = mtk_i2c_master_cmd(i2c, cmd, page_len); + ret = mtk_i2c_cmd(i2c, cmd, page_len); if (ret) goto err_timeout; @@ -222,7 +222,7 @@ static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } } - ret = mtk_i2c_master_stop(i2c); + ret = mtk_i2c_stop(i2c); if (ret) goto err_timeout; @@ -230,7 +230,7 @@ static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, return i; err_ack: - ret = mtk_i2c_master_stop(i2c); + ret = mtk_i2c_stop(i2c); if (ret) goto err_timeout; return -ENXIO; @@ -247,8 +247,8 @@ static u32 mtk_i2c_func(struct i2c_adapter *a) } static const struct i2c_algorithm mtk_i2c_algo = { - .master_xfer = mtk_i2c_master_xfer, - .functionality = mtk_i2c_func, + .xfer = mtk_i2c_xfer, + .functionality = mtk_i2c_func, }; static const struct of_device_id i2c_mtk_dt_ids[] = { diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index dc160cbc3155..29f94efedf60 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -89,8 +89,8 @@ enum { MV64XXX_I2C_STATE_WAITING_FOR_RESTART, MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, + MV64XXX_I2C_STATE_WAITING_FOR_TARGET_ACK, + MV64XXX_I2C_STATE_WAITING_FOR_TARGET_DATA, }; /* Driver actions */ @@ -279,7 +279,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) } else { drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; + MV64XXX_I2C_STATE_WAITING_FOR_TARGET_ACK; drv_data->bytes_left--; } break; @@ -307,7 +307,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA; drv_data->bytes_left--; } - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_TARGET_DATA; if ((drv_data->bytes_left == 1) || drv_data->aborting) drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; @@ -797,8 +797,8 @@ static int mv64xxx_i2c_xfer_atomic(struct i2c_adapter *adap, } static const struct i2c_algorithm mv64xxx_i2c_algo = { - .master_xfer = mv64xxx_i2c_xfer, - .master_xfer_atomic = mv64xxx_i2c_xfer_atomic, + .xfer = mv64xxx_i2c_xfer, + .xfer_atomic = mv64xxx_i2c_xfer_atomic, .functionality = mv64xxx_i2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index 26622d24bb1b..9bcaa29a7191 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -163,8 +163,7 @@ static int gpu_i2c_write(struct gpu_i2c_dev *i2cd, u8 data) return gpu_i2c_check_status(i2cd); } -static int gpu_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int gpu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap); int status, status2; @@ -234,8 +233,8 @@ static u32 gpu_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm gpu_i2c_algorithm = { - .master_xfer = gpu_i2c_master_xfer, - .functionality = gpu_i2c_functionality, + .xfer = gpu_i2c_xfer, + .functionality = gpu_i2c_functionality, }; /* diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 4ad670a80a63..482b37c8a129 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -444,8 +444,8 @@ static u32 ocores_func(struct i2c_adapter *adap) } static struct i2c_algorithm ocores_algorithm = { - .master_xfer = ocores_xfer, - .master_xfer_atomic = ocores_xfer_polling, + .xfer = ocores_xfer, + .xfer_atomic = ocores_xfer_polling, .functionality = ocores_func, }; @@ -682,13 +682,13 @@ static int ocores_i2c_probe(struct platform_device *pdev) } if (irq == -ENXIO) { - ocores_algorithm.master_xfer = ocores_xfer_polling; + ocores_algorithm.xfer = ocores_xfer_polling; } else { if (irq < 0) return irq; } - if (ocores_algorithm.master_xfer != ocores_xfer_polling) { + if (ocores_algorithm.xfer != ocores_xfer_polling) { ret = devm_request_any_context_irq(&pdev->dev, irq, ocores_isr, 0, pdev->name, i2c); diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index 5b7b942141e7..16cc34a0526e 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -221,14 +221,14 @@ static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) case STAT_LOST_ARB_B0: return -EAGAIN; - /* Being addressed as slave, should back off & listen */ + /* Being addressed as local target, should back off & listen */ case STAT_SLAVE_60: case STAT_SLAVE_70: case STAT_GENDATA_ACK: case STAT_GENDATA_NAK: return -EOPNOTSUPP; - /* Core busy as slave */ + /* Core busy as local target */ case STAT_SLAVE_80: case STAT_SLAVE_88: case STAT_SLAVE_A0: @@ -608,7 +608,7 @@ err: } /** - * octeon_i2c_xfer - The driver's master_xfer function + * octeon_i2c_xfer - The driver's xfer function * @adap: Pointer to the i2c_adapter structure * @msgs: Pointer to the messages to be processed * @num: Length of the MSGS array diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h index 7af01864da75..b265e21189a1 100644 --- a/drivers/i2c/busses/i2c-octeon-core.h +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -39,8 +39,8 @@ /* Controller command and status bits */ #define TWSI_CTL_CE 0x80 /* High level controller enable */ #define TWSI_CTL_ENAB 0x40 /* Bus enable */ -#define TWSI_CTL_STA 0x20 /* Master-mode start, HW clears when done */ -#define TWSI_CTL_STP 0x10 /* Master-mode stop, HW clears when done */ +#define TWSI_CTL_STA 0x20 /* Controller-mode start, HW clears when done */ +#define TWSI_CTL_STP 0x10 /* Controller-mode stop, HW clears when done */ #define TWSI_CTL_IFLG 0x08 /* HW event, SW writes 0 to ACK */ #define TWSI_CTL_AAK 0x04 /* Assert ACK */ diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 7d54b3203f71..dc6dff95c68c 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -122,7 +122,7 @@ static u32 octeon_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm octeon_i2c_algo = { - .master_xfer = octeon_i2c_xfer, + .xfer = octeon_i2c_xfer, .functionality = octeon_i2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 30a5ea282a8b..35a3f0a64986 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1534,7 +1534,7 @@ static void omap_i2c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev) +static int omap_i2c_runtime_suspend(struct device *dev) { struct omap_i2c_dev *omap = dev_get_drvdata(dev); @@ -1560,7 +1560,7 @@ static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused omap_i2c_runtime_resume(struct device *dev) +static int omap_i2c_runtime_resume(struct device *dev) { struct omap_i2c_dev *omap = dev_get_drvdata(dev); @@ -1574,11 +1574,33 @@ static int __maybe_unused omap_i2c_runtime_resume(struct device *dev) return 0; } +static int omap_i2c_suspend(struct device *dev) +{ + /* + * If the controller is autosuspended, there is no way to wakeup it once + * runtime pm is disabled (in suspend_late()). + * But a device may need the controller up during suspend_noirq() or + * resume_noirq(). + * Wakeup the controller while runtime pm is enabled, so it is available + * until its suspend_noirq(), and from resume_noirq(). + */ + return pm_runtime_resume_and_get(dev); +} + +static int omap_i2c_resume(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + static const struct dev_pm_ops omap_i2c_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, - omap_i2c_runtime_resume, NULL) + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(omap_i2c_suspend, omap_i2c_resume) + RUNTIME_PM_OPS(omap_i2c_runtime_suspend, + omap_i2c_runtime_resume, NULL) }; static struct platform_driver omap_i2c_driver = { @@ -1586,7 +1608,7 @@ static struct platform_driver omap_i2c_driver = { .remove_new = omap_i2c_remove, .driver = { .name = "omap_i2c", - .pm = &omap_i2c_pm_ops, + .pm = pm_ptr(&omap_i2c_pm_ops), .of_match_table = of_match_ptr(omap_i2c_of_match), }, }; diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c index 17ef87d50f7c..d9dd71cf37fd 100644 --- a/drivers/i2c/busses/i2c-opal.c +++ b/drivers/i2c/busses/i2c-opal.c @@ -70,8 +70,8 @@ exit: return rc; } -static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) +static int i2c_opal_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) { unsigned long opal_id = (unsigned long)adap->algo_data; struct opal_i2c_request req; @@ -179,9 +179,9 @@ static u32 i2c_opal_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm i2c_opal_algo = { - .master_xfer = i2c_opal_master_xfer, - .smbus_xfer = i2c_opal_smbus_xfer, - .functionality = i2c_opal_func, + .xfer = i2c_opal_xfer, + .smbus_xfer = i2c_opal_smbus_xfer, + .functionality = i2c_opal_func, }; /* diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 777f1a0278c7..84a195e35886 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -172,7 +172,7 @@ static void owl_i2c_xfer_data(struct owl_i2c_dev *i2c_dev) i2c_dev->err = 0; - /* Handle NACK from slave */ + /* Handle NACK from target */ fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT); if (fifostat & OWL_I2C_FIFOSTAT_RNB) { i2c_dev->err = -ENXIO; @@ -302,7 +302,7 @@ static int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs, OWL_I2C_CTL_IRQE, !atomic); /* - * Select: FIFO enable, Master mode, Stop enable, Data count enable, + * Select: FIFO enable, controller mode, Stop enable, Data count enable, * Send start bit */ i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE | @@ -314,7 +314,7 @@ static int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs, i2c_cmd |= OWL_I2C_CMD_AS(msgs[0].len + 1) | OWL_I2C_CMD_SAS(1) | OWL_I2C_CMD_RBE; - /* Write slave address */ + /* Write target address */ addr = i2c_8bit_addr_from_msg(&msgs[0]); writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT); @@ -420,9 +420,9 @@ static int owl_i2c_xfer_atomic(struct i2c_adapter *adap, } static const struct i2c_algorithm owl_i2c_algorithm = { - .master_xfer = owl_i2c_xfer, - .master_xfer_atomic = owl_i2c_xfer_atomic, - .functionality = owl_i2c_func, + .xfer = owl_i2c_xfer, + .xfer_atomic = owl_i2c_xfer_atomic, + .functionality = owl_i2c_func, }; static const struct i2c_adapter_quirks owl_i2c_quirks = { diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 0af86a542568..3249bbd5eb43 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -400,7 +400,6 @@ static struct parport_driver i2c_parport_driver = { .name = "i2c-parport", .match_port = i2c_parport_attach, .detach = i2c_parport_detach, - .devmodel = true, }; module_parport_driver(i2c_parport_driver); diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index bd8becbdeeb2..dac694a9d781 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -336,9 +336,9 @@ static u32 pasemi_smb_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm smbus_algorithm = { - .master_xfer = pasemi_i2c_xfer, - .smbus_xfer = pasemi_smb_xfer, - .functionality = pasemi_smb_func, + .xfer = pasemi_i2c_xfer, + .smbus_xfer = pasemi_smb_xfer, + .functionality = pasemi_smb_func, }; int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 6a0392172b2f..84aa18d1003b 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -589,7 +589,7 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter) result = -EIO; dev_dbg(&piix4_adapter->dev, "Bus collision! SMBus may be " "locked until next hard reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ + /* Clock stops and target is stuck in mid-transmission */ } if (temp & 0x04) { diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 8e57ebe595be..b6b03539f626 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -127,13 +127,13 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, } /* - * Generic i2c master transfer entrypoint. This driver only support single + * Generic i2c transfer entrypoint. This driver only supports single * messages (for "lame i2c" transfers). Anything else should use the smbus * entry point */ -static int i2c_powermac_master_xfer( struct i2c_adapter *adap, - struct i2c_msg *msgs, - int num) +static int i2c_powermac_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, + int num) { struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); int rc = 0; @@ -179,9 +179,9 @@ static u32 i2c_powermac_func(struct i2c_adapter * adapter) /* For now, we only handle smbus */ static const struct i2c_algorithm i2c_powermac_algorithm = { - .smbus_xfer = i2c_powermac_smbus_xfer, - .master_xfer = i2c_powermac_master_xfer, - .functionality = i2c_powermac_func, + .smbus_xfer = i2c_powermac_smbus_xfer, + .xfer = i2c_powermac_xfer, + .functionality = i2c_powermac_func, }; static const struct i2c_adapter_quirks i2c_powermac_quirks = { diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c index 08b3229c443d..6b3c6a733368 100644 --- a/drivers/i2c/busses/i2c-pxa-pci.c +++ b/drivers/i2c/busses/i2c-pxa-pci.c @@ -4,7 +4,7 @@ * Author: Sebastian Andrzej Siewior * * The CE4100's I2C device is more or less the same one as found on PXA. - * It does not support slave mode, the register slightly moved. This PCI + * It does not support target mode, the register slightly moved. This PCI * device provides three bars, every contains a single I2C controller. */ #include diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index f495560bd99c..031175113dd4 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1593,6 +1593,7 @@ static void __exit i2c_adap_pxa_exit(void) platform_driver_unregister(&i2c_pxa_driver); } +MODULE_DESCRIPTION("Intel PXA2XX I2C adapter"); MODULE_LICENSE("GPL"); subsys_initcall(i2c_adap_pxa_init); diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index c9b43a3c4bd3..4a2c745751a2 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1985,5 +1985,6 @@ static struct platform_driver qup_i2c_driver = { module_platform_driver(qup_i2c_driver); +MODULE_DESCRIPTION("Qualcomm QUP based I2C controller"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:i2c_qup"); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 185a5d60f101..da4b07c0ed4c 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -191,8 +191,7 @@ static int rcar_i2c_get_scl(struct i2c_adapter *adap) struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); return !!(rcar_i2c_read(priv, ICMCR) & FSCL); - -}; +} static void rcar_i2c_set_scl(struct i2c_adapter *adap, int val) { @@ -204,7 +203,7 @@ static void rcar_i2c_set_scl(struct i2c_adapter *adap, int val) priv->recovery_icmcr &= ~FSCL; rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr); -}; +} static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val) { @@ -216,15 +215,14 @@ static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val) priv->recovery_icmcr &= ~FSDA; rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr); -}; +} static int rcar_i2c_get_bus_free(struct i2c_adapter *adap) { struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); return !(rcar_i2c_read(priv, ICMCR) & FSDA); - -}; +} static struct i2c_bus_recovery_info rcar_i2c_bri = { .get_scl = rcar_i2c_get_scl, @@ -233,6 +231,7 @@ static struct i2c_bus_recovery_info rcar_i2c_bri = { .get_bus_free = rcar_i2c_get_bus_free, .recover_bus = i2c_generic_scl_recovery, }; + static void rcar_i2c_init(struct rcar_i2c_priv *priv) { /* reset master mode */ @@ -553,7 +552,7 @@ static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) u32 irqs_to_clear = MDE; /* FIXME: sometimes, unknown interrupt happened. Do nothing */ - if (!(msr & MDE)) + if (WARN(!(msr & MDE), "spurious irq")) return; if (msr & MAT) diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index f608b1838cad..d6f585cdb7e5 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -12,9 +12,9 @@ * * 1) The main xfer routine kicks off a transmission by putting the start bit * (or repeated start) on the bus and enabling the transmit interrupt (TIE) - * since we need to send the slave address + RW bit in every case. + * since we need to send the target address + RW bit in every case. * - * 2) TIE sends slave address + RW bit and selects how to continue. + * 2) TIE sends target address + RW bit and selects how to continue. * * 3a) Write case: We keep utilizing TIE as long as we have data to send. If we * are done, we switch over to the transmission done interrupt (TEIE) and mark @@ -294,8 +294,8 @@ static u32 riic_func(struct i2c_adapter *adap) } static const struct i2c_algorithm riic_algo = { - .master_xfer = riic_xfer, - .functionality = riic_func, + .xfer = riic_xfer, + .functionality = riic_func, }; static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index beca61700c89..4ef9bad77b85 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -28,8 +28,8 @@ /* Register Map */ #define REG_CON 0x00 /* control register */ #define REG_CLKDIV 0x04 /* clock divisor register */ -#define REG_MRXADDR 0x08 /* slave address for REGISTER_TX */ -#define REG_MRXRADDR 0x0c /* slave register address for REGISTER_TX */ +#define REG_MRXADDR 0x08 /* target address for REGISTER_TX */ +#define REG_MRXRADDR 0x0c /* target register address for REGISTER_TX */ #define REG_MTXCNT 0x10 /* number of bytes to be transmitted */ #define REG_MRXCNT 0x14 /* number of bytes to be received */ #define REG_IEN 0x18 /* interrupt enable */ @@ -68,8 +68,8 @@ enum { /* REG_IEN/REG_IPD bits */ #define REG_INT_BTF BIT(0) /* a byte was transmitted */ #define REG_INT_BRF BIT(1) /* a byte was received */ -#define REG_INT_MBTF BIT(2) /* master data transmit finished */ -#define REG_INT_MBRF BIT(3) /* master data receive finished */ +#define REG_INT_MBTF BIT(2) /* controller data transmit finished */ +#define REG_INT_MBRF BIT(3) /* controller data receive finished */ #define REG_INT_START BIT(4) /* START condition generated */ #define REG_INT_STOP BIT(5) /* STOP condition generated */ #define REG_INT_NAKRCV BIT(6) /* NACK received */ @@ -184,7 +184,7 @@ struct rk3x_i2c_soc_data { * @wait: the waitqueue to wait for i2c transfer * @busy: the condition for the event to wait for * @msg: current i2c message - * @addr: addr of i2c slave device + * @addr: addr of i2c target device * @mode: mode of i2c transfer * @is_last_msg: flag determines whether it is the last msg in this transfer * @state: state of i2c transfer @@ -979,7 +979,7 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) /* * The I2C adapter can issue a small (len < 4) write packet before * reading. This speeds up SMBus-style register reads. - * The MRXADDR/MRXRADDR hold the slave address and the slave register + * The MRXADDR/MRXRADDR hold the target address and the target register * address in this case. */ @@ -1016,7 +1016,7 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) addr |= 1; /* set read bit */ /* - * We have to transmit the slave addr first. Use + * We have to transmit the target addr first. Use * MOD_REGISTER_TX for that purpose. */ i2c->mode = REG_CON_MOD_REGISTER_TX; @@ -1160,9 +1160,9 @@ static u32 rk3x_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm rk3x_i2c_algorithm = { - .master_xfer = rk3x_i2c_xfer, - .master_xfer_atomic = rk3x_i2c_xfer_polling, - .functionality = rk3x_i2c_func, + .xfer = rk3x_i2c_xfer, + .xfer_atomic = rk3x_i2c_xfer_polling, + .functionality = rk3x_i2c_func, }; static const struct rk3x_i2c_soc_data rv1108_soc_data = { diff --git a/drivers/i2c/busses/i2c-robotfuzz-osif.c b/drivers/i2c/busses/i2c-robotfuzz-osif.c index 66dfa211e736..80d45079b763 100644 --- a/drivers/i2c/busses/i2c-robotfuzz-osif.c +++ b/drivers/i2c/busses/i2c-robotfuzz-osif.c @@ -112,8 +112,8 @@ static u32 osif_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm osif_algorithm = { - .master_xfer = osif_xfer, - .functionality = osif_func, + .xfer = osif_xfer, + .functionality = osif_func, }; #define USB_OSIF_VENDOR_ID 0x1964 diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c index b0bfc96b9ede..8380a68538ab 100644 --- a/drivers/i2c/busses/i2c-rzv2m.c +++ b/drivers/i2c/busses/i2c-rzv2m.c @@ -321,8 +321,8 @@ static int rzv2m_i2c_stop_condition(struct rzv2m_i2c_priv *priv) 100, jiffies_to_usecs(priv->adap.timeout)); } -static int rzv2m_i2c_master_xfer_msg(struct rzv2m_i2c_priv *priv, - struct i2c_msg *msg, int stop) +static int rzv2m_i2c_xfer_msg(struct rzv2m_i2c_priv *priv, + struct i2c_msg *msg, int stop) { unsigned int count = 0; int ret, read = !!(msg->flags & I2C_M_RD); @@ -351,8 +351,8 @@ static int rzv2m_i2c_master_xfer_msg(struct rzv2m_i2c_priv *priv, return ret; } -static int rzv2m_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int rzv2m_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) { struct rzv2m_i2c_priv *priv = i2c_get_adapdata(adap); struct device *dev = priv->adap.dev.parent; @@ -370,7 +370,7 @@ static int rzv2m_i2c_master_xfer(struct i2c_adapter *adap, /* I2C main transfer */ for (i = 0; i < num; i++) { - ret = rzv2m_i2c_master_xfer_msg(priv, &msgs[i], i == (num - 1)); + ret = rzv2m_i2c_xfer_msg(priv, &msgs[i], i == (num - 1)); if (ret < 0) goto out; } @@ -408,7 +408,7 @@ static const struct i2c_adapter_quirks rzv2m_i2c_quirks = { }; static struct i2c_algorithm rzv2m_i2c_algo = { - .master_xfer = rzv2m_i2c_master_xfer, + .xfer = rzv2m_i2c_xfer, .functionality = rzv2m_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 32476dc10ad6..ca06fffb8f61 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -257,7 +257,7 @@ static int sis5595_transaction(struct i2c_adapter *adap) if (temp & 0x20) { dev_err(&adap->dev, "Bus collision! SMBus may be locked until " "next hard reset (or not...)\n"); - /* Clock stops and slave is stuck in mid-transmission */ + /* Clock stops and target is stuck in mid-transmission */ result = -EIO; } diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 28c88901d9bc..9c45e75b9187 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -283,8 +283,8 @@ static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap, return i2c_dev->err; } -static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) +static int sprd_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) { struct sprd_i2c *i2c_dev = i2c_adap->algo_data; int im, ret; @@ -314,7 +314,7 @@ static u32 sprd_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm sprd_i2c_algo = { - .master_xfer = sprd_i2c_master_xfer, + .xfer = sprd_i2c_xfer, .functionality = sprd_i2c_func, }; @@ -378,12 +378,12 @@ static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id) i2c_tran = i2c_dev->count; /* - * If we got one ACK from slave when writing data, and we did not + * If we got one ACK from target when writing data, and we did not * finish this transmission (i2c_tran is not zero), then we should * continue to write data. * * For reading data, ack is always true, if i2c_tran is not 0 which - * means we still need to contine to read data from slave. + * means we still need to contine to read data from target. */ if (i2c_tran && ack) { sprd_i2c_data_transfer(i2c_dev); @@ -393,7 +393,7 @@ static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id) i2c_dev->err = 0; /* - * If we did not get one ACK from slave when writing data, we should + * If we did not get one ACK from target when writing data, we should * return -EIO to notify users. */ if (!ack) @@ -422,7 +422,7 @@ static irqreturn_t sprd_i2c_isr(int irq, void *dev_id) i2c_tran = i2c_dev->count; /* - * If we did not get one ACK from slave when writing data, then we + * If we did not get one ACK from target when writing data, then we * should finish this transmission since we got some errors. * * When writing data, if i2c_tran == 0 which means we have writen @@ -653,5 +653,5 @@ static struct platform_driver sprd_i2c_driver = { module_platform_driver(sprd_i2c_driver); -MODULE_DESCRIPTION("Spreadtrum I2C master controller driver"); +MODULE_DESCRIPTION("Spreadtrum I2C controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 5e01fe3dbb63..05b19ede65a0 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2013 STMicroelectronics * - * I2C master mode controller driver, used in STMicroelectronics devices. + * I2C controller driver, used in STMicroelectronics devices. * * Author: Maxime Coquelin */ @@ -150,7 +150,7 @@ struct st_i2c_timings { /** * struct st_i2c_client - client specific data - * @addr: 8-bit slave addr, including r/w bit + * @addr: 8-bit target addr, including r/w bit * @count: number of bytes to be transfered * @xfered: number of bytes already transferred * @buf: data buffer @@ -667,7 +667,7 @@ static int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg, i2c |= SSC_I2C_ACKG; st_i2c_set_bits(i2c_dev->base + SSC_I2C, i2c); - /* Write slave address */ + /* Write target address */ st_i2c_write_tx_fifo(i2c_dev, c->addr); /* Pre-fill Tx fifo with data in case of write */ @@ -766,7 +766,7 @@ static u32 st_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm st_i2c_algo = { - .master_xfer = st_i2c_xfer, + .xfer = st_i2c_xfer, .functionality = st_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index f8b12be6ef55..230fff0c0bf9 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -95,7 +95,7 @@ /** * struct stm32f4_i2c_msg - client specific data - * @addr: 8-bit slave addr, including r/w bit + * @addr: 8-bit target addr, including r/w bit * @count: number of bytes to be transferred * @buf: data buffer * @result: result of the transfer @@ -480,7 +480,7 @@ static void stm32f4_i2c_handle_rx_done(struct stm32f4_i2c_dev *i2c_dev) /** * stm32f4_i2c_handle_rx_addr() - Handle address matched interrupt in case of - * master receiver + * controller receiver * @i2c_dev: Controller's private data */ static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev) @@ -643,7 +643,7 @@ static irqreturn_t stm32f4_i2c_isr_error(int irq, void *data) /* * Acknowledge failure: - * In master transmitter mode a Stop must be generated by software + * In controller transmitter mode a Stop must be generated by software */ if (status & STM32F4_I2C_SR1_AF) { if (!(msg->addr & I2C_M_RD)) { @@ -749,7 +749,7 @@ static u32 stm32f4_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm stm32f4_i2c_algo = { - .master_xfer = stm32f4_i2c_xfer, + .xfer = stm32f4_i2c_xfer, .functionality = stm32f4_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index 85e035e7a1d7..074eade6c4a4 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -10,7 +10,7 @@ * The P2WI controller looks like an SMBus controller which only supports byte * data transfers. But, it differs from standard SMBus protocol on several * aspects: - * - it supports only one slave device, and thus drop the address field + * - it supports only one target device, and thus drop the address field * - it adds a parity bit every 8bits of data * - only one read access is required to read a byte (instead of a write * followed by a read access in standard SMBus protocol) @@ -88,7 +88,7 @@ struct p2wi { void __iomem *regs; struct clk *clk; struct reset_control *rstc; - int slave_addr; + int target_addr; }; static irqreturn_t p2wi_interrupt(int irq, void *dev_id) @@ -121,7 +121,7 @@ static int p2wi_smbus_xfer(struct i2c_adapter *adap, u16 addr, struct p2wi *p2wi = i2c_get_adapdata(adap); unsigned long dlen = P2WI_DLEN_DATA_LENGTH(1); - if (p2wi->slave_addr >= 0 && addr != p2wi->slave_addr) { + if (p2wi->target_addr >= 0 && addr != p2wi->target_addr) { dev_err(&adap->dev, "invalid P2WI address\n"); return -EINVAL; } @@ -188,7 +188,7 @@ static int p2wi_probe(struct platform_device *pdev) unsigned long parent_clk_freq; u32 clk_freq = I2C_MAX_STANDARD_MODE_FREQ; struct p2wi *p2wi; - u32 slave_addr; + u32 target_addr; int clk_div; int irq; int ret; @@ -207,7 +207,7 @@ static int p2wi_probe(struct platform_device *pdev) } if (of_get_child_count(np) > 1) { - dev_err(dev, "P2WI only supports one slave device\n"); + dev_err(dev, "P2WI only supports one target device\n"); return -EINVAL; } @@ -215,24 +215,24 @@ static int p2wi_probe(struct platform_device *pdev) if (!p2wi) return -ENOMEM; - p2wi->slave_addr = -1; + p2wi->target_addr = -1; /* * Authorize a p2wi node without any children to be able to use an * i2c-dev from userpace. - * In this case the slave_addr is set to -1 and won't be checked when + * In this case the target_addr is set to -1 and won't be checked when * launching a P2WI transfer. */ childnp = of_get_next_available_child(np, NULL); if (childnp) { - ret = of_property_read_u32(childnp, "reg", &slave_addr); + ret = of_property_read_u32(childnp, "reg", &target_addr); if (ret) { - dev_err(dev, "invalid slave address on node %pOF\n", + dev_err(dev, "invalid target address on node %pOF\n", childnp); return -EINVAL; } - p2wi->slave_addr = slave_addr; + p2wi->target_addr = target_addr; } p2wi->regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index b0f0120793e1..cb97f72291bc 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Driver for the TAOS evaluation modules - * These devices include an I2C master which can be controlled over the + * These devices include an I2C controller which can be controlled over the * serial port. * * Copyright (C) 2007 Jean Delvare diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c index b0840fa0f53e..dabadbcc6d6a 100644 --- a/drivers/i2c/busses/i2c-tegra-bpmp.c +++ b/drivers/i2c/busses/i2c-tegra-bpmp.c @@ -275,8 +275,8 @@ static u32 tegra_bpmp_i2c_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm tegra_bpmp_i2c_algo = { - .master_xfer = tegra_bpmp_i2c_xfer, - .master_xfer_atomic = tegra_bpmp_i2c_xfer_atomic, + .xfer = tegra_bpmp_i2c_xfer, + .xfer_atomic = tegra_bpmp_i2c_xfer_atomic, .functionality = tegra_bpmp_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c index 32d0e3930b67..143d012fa43e 100644 --- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -72,7 +72,7 @@ static u32 thunderx_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm thunderx_i2c_algo = { - .master_xfer = octeon_i2c_xfer, + .xfer = octeon_i2c_xfer, .functionality = thunderx_i2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index 1bffe36c40ad..0f2ed181b266 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -54,8 +54,6 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) struct i2c_msg *pmsg; int i, ret; - dev_dbg(&adapter->dev, "master xfer %d messages:\n", num); - pstatus = kmalloc(sizeof(*pstatus), GFP_KERNEL); if (!pstatus) return -ENOMEM; @@ -142,8 +140,8 @@ out: /* This is the actual algorithm we define */ static const struct i2c_algorithm usb_algorithm = { - .master_xfer = usb_xfer, - .functionality = usb_func, + .xfer = usb_xfer, + .functionality = usb_func, }; /* ----- end of i2c layer ------------------------------------------------ */ diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 6c3dac2cf568..10a99cd08972 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -12,15 +12,15 @@ #include #define UNIPHIER_FI2C_CR 0x00 /* control register */ -#define UNIPHIER_FI2C_CR_MST BIT(3) /* master mode */ +#define UNIPHIER_FI2C_CR_MST BIT(3) /* controller mode */ #define UNIPHIER_FI2C_CR_STA BIT(2) /* start condition */ #define UNIPHIER_FI2C_CR_STO BIT(1) /* stop condition */ #define UNIPHIER_FI2C_CR_NACK BIT(0) /* do not return ACK */ #define UNIPHIER_FI2C_DTTX 0x04 /* TX FIFO */ -#define UNIPHIER_FI2C_DTTX_CMD BIT(8) /* send command (slave addr) */ +#define UNIPHIER_FI2C_DTTX_CMD BIT(8) /* send command (target addr) */ #define UNIPHIER_FI2C_DTTX_RD BIT(0) /* read transaction */ #define UNIPHIER_FI2C_DTRX 0x04 /* RX FIFO */ -#define UNIPHIER_FI2C_SLAD 0x0c /* slave address */ +#define UNIPHIER_FI2C_SLAD 0x0c /* target address */ #define UNIPHIER_FI2C_CYC 0x10 /* clock cycle control */ #define UNIPHIER_FI2C_LCTL 0x14 /* clock low period control */ #define UNIPHIER_FI2C_SSUT 0x18 /* restart/stop setup time control */ @@ -96,7 +96,7 @@ static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv, int fifo_space = UNIPHIER_FI2C_FIFO_SIZE; /* - * TX-FIFO stores slave address in it for the first access. + * TX-FIFO stores target address in it for the first access. * Decrement the counter. */ if (first) @@ -252,7 +252,7 @@ static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr, /* do not use TX byte counter */ writel(0, priv->membase + UNIPHIER_FI2C_TBC); - /* set slave address */ + /* set target address */ writel(UNIPHIER_FI2C_DTTX_CMD | addr << 1, priv->membase + UNIPHIER_FI2C_DTTX); /* @@ -288,7 +288,7 @@ static void uniphier_fi2c_rx_init(struct uniphier_fi2c_priv *priv, u16 addr) uniphier_fi2c_set_irqs(priv); - /* set slave address with RD bit */ + /* set target address with RD bit */ writel(UNIPHIER_FI2C_DTTX_CMD | UNIPHIER_FI2C_DTTX_RD | addr << 1, priv->membase + UNIPHIER_FI2C_DTTX); } @@ -310,9 +310,8 @@ static void uniphier_fi2c_recover(struct uniphier_fi2c_priv *priv) i2c_recover_bus(&priv->adap); } -static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap, - struct i2c_msg *msg, bool repeat, - bool stop) +static int uniphier_fi2c_xfer_one(struct i2c_adapter *adap, struct i2c_msg *msg, + bool repeat, bool stop) { struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap); bool is_read = msg->flags & I2C_M_RD; @@ -340,7 +339,7 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap, uniphier_fi2c_tx_init(priv, msg->addr, repeat); /* - * For a repeated START condition, writing a slave address to the FIFO + * For a repeated START condition, writing a target address to the FIFO * kicks the controller. So, the UNIPHIER_FI2C_CR register should be * written only for a non-repeated START condition. */ @@ -403,8 +402,7 @@ static int uniphier_fi2c_check_bus_busy(struct i2c_adapter *adap) return 0; } -static int uniphier_fi2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int uniphier_fi2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct i2c_msg *msg, *emsg = msgs + num; bool repeat = false; @@ -418,7 +416,7 @@ static int uniphier_fi2c_master_xfer(struct i2c_adapter *adap, /* Emit STOP if it is the last message or I2C_M_STOP is set. */ bool stop = (msg + 1 == emsg) || (msg->flags & I2C_M_STOP); - ret = uniphier_fi2c_master_xfer_one(adap, msg, repeat, stop); + ret = uniphier_fi2c_xfer_one(adap, msg, repeat, stop); if (ret) return ret; @@ -434,7 +432,7 @@ static u32 uniphier_fi2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm uniphier_fi2c_algo = { - .master_xfer = uniphier_fi2c_master_xfer, + .xfer = uniphier_fi2c_xfer, .functionality = uniphier_fi2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index e1b4c80e0285..ef5753307469 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -17,13 +17,13 @@ #define UNIPHIER_I2C_DTRM_NACK BIT(8) /* do not return ACK */ #define UNIPHIER_I2C_DTRM_RD BIT(0) /* read transaction */ #define UNIPHIER_I2C_DREC 0x04 /* RX register */ -#define UNIPHIER_I2C_DREC_MST BIT(14) /* 1 = master, 0 = slave */ +#define UNIPHIER_I2C_DREC_MST BIT(14) /* 1 = controller, 0 = target */ #define UNIPHIER_I2C_DREC_TX BIT(13) /* 1 = transmit, 0 = receive */ #define UNIPHIER_I2C_DREC_STS BIT(12) /* stop condition detected */ #define UNIPHIER_I2C_DREC_LRB BIT(11) /* no ACK */ #define UNIPHIER_I2C_DREC_LAB BIT(9) /* arbitration lost */ #define UNIPHIER_I2C_DREC_BBN BIT(8) /* bus not busy */ -#define UNIPHIER_I2C_MYAD 0x08 /* slave address */ +#define UNIPHIER_I2C_MYAD 0x08 /* local target address */ #define UNIPHIER_I2C_CLK 0x0c /* clock frequency control */ #define UNIPHIER_I2C_BRST 0x10 /* bus reset */ #define UNIPHIER_I2C_BRST_FOEN BIT(1) /* normal operation */ @@ -152,8 +152,8 @@ static int uniphier_i2c_stop(struct i2c_adapter *adap) UNIPHIER_I2C_DTRM_NACK); } -static int uniphier_i2c_master_xfer_one(struct i2c_adapter *adap, - struct i2c_msg *msg, bool stop) +static int uniphier_i2c_xfer_one(struct i2c_adapter *adap, + struct i2c_msg *msg, bool stop) { bool is_read = msg->flags & I2C_M_RD; bool recovery = false; @@ -211,8 +211,7 @@ static int uniphier_i2c_check_bus_busy(struct i2c_adapter *adap) return 0; } -static int uniphier_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int uniphier_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct i2c_msg *msg, *emsg = msgs + num; int ret; @@ -225,7 +224,7 @@ static int uniphier_i2c_master_xfer(struct i2c_adapter *adap, /* Emit STOP if it is the last message or I2C_M_STOP is set. */ bool stop = (msg + 1 == emsg) || (msg->flags & I2C_M_STOP); - ret = uniphier_i2c_master_xfer_one(adap, msg, stop); + ret = uniphier_i2c_xfer_one(adap, msg, stop); if (ret) return ret; } @@ -239,7 +238,7 @@ static u32 uniphier_i2c_functionality(struct i2c_adapter *adap) } static const struct i2c_algorithm uniphier_i2c_algo = { - .master_xfer = uniphier_i2c_master_xfer, + .xfer = uniphier_i2c_xfer, .functionality = uniphier_i2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c index 162b31306cba..5a53ed95a59b 100644 --- a/drivers/i2c/busses/i2c-viai2c-common.c +++ b/drivers/i2c/busses/i2c-viai2c-common.c @@ -198,6 +198,6 @@ int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat) } EXPORT_SYMBOL_GPL(viai2c_init); -MODULE_DESCRIPTION("Via/Wondermedia/Zhaoxin I2C master-mode bus adapter"); +MODULE_DESCRIPTION("Via/Wondermedia/Zhaoxin I2C controller core"); MODULE_AUTHOR("Tony Prisk "); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-viai2c-wmt.c b/drivers/i2c/busses/i2c-viai2c-wmt.c index 420fd10fe3aa..3415683dab91 100644 --- a/drivers/i2c/busses/i2c-viai2c-wmt.c +++ b/drivers/i2c/busses/i2c-viai2c-wmt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Wondermedia I2C Master Mode Driver + * Wondermedia I2C Controller Driver * * Copyright (C) 2012 Tony Prisk * @@ -35,8 +35,8 @@ static u32 wmt_i2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm wmt_i2c_algo = { - .master_xfer = viai2c_xfer, - .functionality = wmt_i2c_func, + .xfer = viai2c_xfer, + .functionality = wmt_i2c_func, }; static int wmt_i2c_reset_hardware(struct viai2c *i2c) @@ -178,7 +178,7 @@ static struct platform_driver wmt_i2c_driver = { module_platform_driver(wmt_i2c_driver); -MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter"); +MODULE_DESCRIPTION("Wondermedia I2C controller driver"); MODULE_AUTHOR("Tony Prisk "); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids); diff --git a/drivers/i2c/busses/i2c-viai2c-zhaoxin.c b/drivers/i2c/busses/i2c-viai2c-zhaoxin.c index ab3e44e147e9..95dc64902b7c 100644 --- a/drivers/i2c/busses/i2c-viai2c-zhaoxin.c +++ b/drivers/i2c/busses/i2c-viai2c-zhaoxin.c @@ -38,7 +38,7 @@ #define ZXI2C_GOLD_FSTP_400K 0x38 #define ZXI2C_GOLD_FSTP_1M 0x13 #define ZXI2C_GOLD_FSTP_3400K 0x37 -#define ZXI2C_HS_MASTER_CODE (0x08 << 8) +#define ZXI2C_HS_CTRL_CODE (0x08 << 8) #define ZXI2C_FIFO_SIZE 32 @@ -136,7 +136,7 @@ static int viai2c_fifo_irq_xfer(struct viai2c *i2c) return 0; } -static int zxi2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +static int zxi2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { u8 tmp; int ret; @@ -194,8 +194,8 @@ static u32 zxi2c_func(struct i2c_adapter *adap) } static const struct i2c_algorithm zxi2c_algorithm = { - .master_xfer = zxi2c_master_xfer, - .functionality = zxi2c_func, + .xfer = zxi2c_xfer, + .functionality = zxi2c_func, }; static const struct i2c_adapter_quirks zxi2c_quirks = { @@ -250,9 +250,9 @@ static void zxi2c_get_bus_speed(struct viai2c *i2c) i2c->tcr = params[1]; priv->mcr = ioread16(i2c->base + VIAI2C_REG_MCR); - /* for Hs-mode, use 0x80 as master code */ + /* for Hs-mode, use 0x80 as controller code */ if (params[0] == I2C_MAX_HIGH_SPEED_MODE_FREQ) - priv->mcr |= ZXI2C_HS_MASTER_CODE; + priv->mcr |= ZXI2C_HS_CTRL_CODE; dev_info(i2c->dev, "speed mode is %s\n", i2c_freq_mode_string(params[0])); } diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c index 3784b07f5371..2ed4130c0339 100644 --- a/drivers/i2c/busses/i2c-viperboard.c +++ b/drivers/i2c/busses/i2c-viperboard.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Nano River Technologies viperboard i2c master driver + * Nano River Technologies viperboard i2c controller driver * * (C) 2012 by Lemonage GmbH * Author: Lars Poeschel @@ -273,8 +273,6 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs, (struct vprbrd_i2c_addr_msg *)vb->buf; struct vprbrd_i2c_status *smsg = (struct vprbrd_i2c_status *)vb->buf; - dev_dbg(&i2c->dev, "master xfer %d messages:\n", num); - for (i = 0 ; i < num ; i++) { pmsg = &msgs[i]; @@ -345,8 +343,8 @@ static u32 vprbrd_i2c_func(struct i2c_adapter *i2c) /* This is the actual algorithm we define */ static const struct i2c_algorithm vprbrd_algorithm = { - .master_xfer = vprbrd_i2c_xfer, - .functionality = vprbrd_i2c_func, + .xfer = vprbrd_i2c_xfer, + .functionality = vprbrd_i2c_func, }; static const struct i2c_adapter_quirks vprbrd_quirks = { @@ -460,6 +458,6 @@ static void __exit vprbrd_i2c_exit(void) module_exit(vprbrd_i2c_exit); MODULE_AUTHOR("Lars Poeschel "); -MODULE_DESCRIPTION("I2C master driver for Nano River Techs Viperboard"); +MODULE_DESCRIPTION("I2C controller driver for Nano River Techs Viperboard"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:viperboard-i2c"); diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c index c60ae531ba57..52ba1e0845ca 100644 --- a/drivers/i2c/busses/i2c-virtio.c +++ b/drivers/i2c/busses/i2c-virtio.c @@ -183,7 +183,7 @@ static u32 virtio_i2c_func(struct i2c_adapter *adap) } static struct i2c_algorithm virtio_algorithm = { - .master_xfer = virtio_i2c_xfer, + .xfer = virtio_i2c_xfer, .functionality = virtio_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 71391b590ada..19468565120e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -1105,8 +1105,11 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) mutex_lock(&i2c->lock); ret = xiic_busy(i2c); - if (ret) + if (ret) { + dev_err(i2c->adap.dev.parent, + "cannot start a transfer while busy\n"); goto out; + } i2c->tx_msg = msgs; i2c->rx_msg = NULL; @@ -1164,10 +1167,8 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) return err; err = xiic_start_xfer(i2c, msgs, num); - if (err < 0) { - dev_err(adap->dev.parent, "Error xiic_start_xfer\n"); + if (err < 0) goto out; - } err = wait_for_completion_timeout(&i2c->completion, XIIC_XFER_TIMEOUT); mutex_lock(&i2c->lock); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 7e7b15440832..f76b7f4fafc1 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1066,8 +1066,8 @@ EXPORT_SYMBOL(i2c_find_device_by_fwnode); static const struct i2c_device_id dummy_id[] = { - { "dummy", 0 }, - { "smbus_host_notify", 0 }, + { "dummy", }, + { "smbus_host_notify", }, { }, }; @@ -1469,6 +1469,8 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr) if (!adap) return -EINVAL; + dev_dbg(&adap->dev, "Detected HostNotify from address 0x%02x", addr); + irq = irq_find_mapping(adap->host_notify_domain, addr); if (irq <= 0) return -ENXIO; diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 8b7e599f1674..f4fb212b7f39 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -139,6 +139,10 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count, struct i2c_client *client = file->private_data; + /* Adapter must support I2C transfers */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + if (count > 8192) count = 8192; @@ -163,6 +167,10 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf, char *tmp; struct i2c_client *client = file->private_data; + /* Adapter must support I2C transfers */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + if (count > 8192) count = 8192; @@ -238,6 +246,10 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, u8 __user **data_ptrs; int i, res; + /* Adapter must support I2C transfers */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL); if (data_ptrs == NULL) { kfree(msgs); diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c index 23a11e4e9256..4e03b75f9ad7 100644 --- a/drivers/i2c/i2c-slave-testunit.c +++ b/drivers/i2c/i2c-slave-testunit.c @@ -172,7 +172,7 @@ static void i2c_slave_testunit_remove(struct i2c_client *client) } static const struct i2c_device_id i2c_slave_testunit_id[] = { - { "slave-testunit", 0 }, + { "slave-testunit" }, { } }; MODULE_DEVICE_TABLE(i2c, i2c_slave_testunit_id); diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index f809f0ef2004..1cb137b9181d 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -160,7 +160,7 @@ static void smbalert_remove(struct i2c_client *ara) } static const struct i2c_device_id smbalert_ids[] = { - { "smbus_alert", 0 }, + { "smbus_alert" }, { /* LIST END */ } }; MODULE_DEVICE_TABLE(i2c, smbalert_ids); diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index e28694d991fb..8663c8a7c269 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -78,7 +78,7 @@ struct pca9541 { }; static const struct i2c_device_id pca9541_id[] = { - {"pca9541", 0}, + { "pca9541" }, {} }; diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 9c351ffc7bed..661127aed2f9 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -14,6 +14,7 @@ if IIO config IIO_BUFFER bool "Enable buffer support within IIO" + select DMA_SHARED_BUFFER help Provide core support for various buffer based data acquisition methods. diff --git a/drivers/iio/accel/adxl313_spi.c b/drivers/iio/accel/adxl313_spi.c index b7cc15678a2b..6f8d73f6e5a9 100644 --- a/drivers/iio/accel/adxl313_spi.c +++ b/drivers/iio/accel/adxl313_spi.c @@ -72,13 +72,7 @@ static int adxl313_spi_probe(struct spi_device *spi) if (ret) return ret; - /* - * Retrieves device specific data as a pointer to a - * adxl313_chip_info structure - */ - chip_data = device_get_match_data(&spi->dev); - if (!chip_data) - chip_data = (const struct adxl313_chip_info *)spi_get_device_id(spi)->driver_data; + chip_data = spi_get_device_match_data(spi); regmap = devm_regmap_init_spi(spi, &adxl31x_spi_regmap_config[chip_data->type]); diff --git a/drivers/iio/accel/adxl355_spi.c b/drivers/iio/accel/adxl355_spi.c index fc99534d91ff..5153ac815e4b 100644 --- a/drivers/iio/accel/adxl355_spi.c +++ b/drivers/iio/accel/adxl355_spi.c @@ -28,13 +28,9 @@ static int adxl355_spi_probe(struct spi_device *spi) const struct adxl355_chip_info *chip_data; struct regmap *regmap; - chip_data = device_get_match_data(&spi->dev); - if (!chip_data) { - chip_data = (void *)spi_get_device_id(spi)->driver_data; - - if (!chip_data) - return -EINVAL; - } + chip_data = spi_get_device_match_data(spi); + if (!chip_data) + return -EINVAL; regmap = devm_regmap_init_spi(spi, &adxl355_spi_regmap_config); if (IS_ERR(regmap)) { diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2c.c index 62c74bdc0d77..deb82a43ec36 100644 --- a/drivers/iio/accel/adxl367_i2c.c +++ b/drivers/iio/accel/adxl367_i2c.c @@ -61,8 +61,8 @@ static int adxl367_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adxl367_i2c_id[] = { - { "adxl367", 0 }, - { }, + { "adxl367" }, + { } }; MODULE_DEVICE_TABLE(i2c, adxl367_i2c_id); diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index d0690417fd36..3571cfde1c0e 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -42,7 +42,7 @@ static int adxl372_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adxl372_i2c_id[] = { - { "adxl372", 0 }, + { "adxl372" }, {} }; MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c index adf4e3fd2e1d..c1c72f577295 100644 --- a/drivers/iio/accel/bma400_i2c.c +++ b/drivers/iio/accel/bma400_i2c.c @@ -28,7 +28,7 @@ static int bma400_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bma400_i2c_ids[] = { - { "bma400", 0 }, + { "bma400" }, { } }; MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids); diff --git a/drivers/iio/accel/bmi088-accel-core.c b/drivers/iio/accel/bmi088-accel-core.c index 4d989708e6c3..469a1255d93c 100644 --- a/drivers/iio/accel/bmi088-accel-core.c +++ b/drivers/iio/accel/bmi088-accel-core.c @@ -114,11 +114,6 @@ enum bmi088_odr_modes { BMI088_ACCEL_MODE_ODR_1600 = 0xc, }; -struct bmi088_scale_info { - int scale; - u8 reg_range; -}; - struct bmi088_accel_chip_info { const char *name; u8 chip_id; diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c index 8f919920ced5..94f827acdd1c 100644 --- a/drivers/iio/accel/da311.c +++ b/drivers/iio/accel/da311.c @@ -268,7 +268,7 @@ static int da311_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume); static const struct i2c_device_id da311_i2c_id[] = { - {"da311", 0}, + { "da311" }, {} }; MODULE_DEVICE_TABLE(i2c, da311_i2c_id); diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c index 2e719d60fff8..fb14894c66f9 100644 --- a/drivers/iio/accel/dmard06.c +++ b/drivers/iio/accel/dmard06.c @@ -201,9 +201,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard06_pm_ops, dmard06_suspend, dmard06_resume); static const struct i2c_device_id dmard06_id[] = { - { "dmard05", 0 }, - { "dmard06", 0 }, - { "dmard07", 0 }, + { "dmard05" }, + { "dmard06" }, + { "dmard07" }, { } }; MODULE_DEVICE_TABLE(i2c, dmard06_id); diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c index fa98623de579..6644c1fec3e6 100644 --- a/drivers/iio/accel/dmard09.c +++ b/drivers/iio/accel/dmard09.c @@ -125,8 +125,8 @@ static int dmard09_probe(struct i2c_client *client) } static const struct i2c_device_id dmard09_id[] = { - { "dmard09", 0 }, - { }, + { "dmard09" }, + { } }; MODULE_DEVICE_TABLE(i2c, dmard09_id); diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c index 7745b6ffd1ad..35c0eefb741e 100644 --- a/drivers/iio/accel/dmard10.c +++ b/drivers/iio/accel/dmard10.c @@ -231,7 +231,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, dmard10_resume); static const struct i2c_device_id dmard10_i2c_id[] = { - {"dmard10", 0}, + { "dmard10" }, {} }; MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id); diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index 4fbc01bda62e..d25e31613413 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -228,8 +228,8 @@ static int fxls8962af_power_off(struct fxls8962af_data *data) static int fxls8962af_standby(struct fxls8962af_data *data) { - return regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, - FXLS8962AF_SENS_CONFIG1_ACTIVE, 0); + return regmap_clear_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_ACTIVE); } static int fxls8962af_active(struct fxls8962af_data *data) @@ -785,9 +785,8 @@ static int fxls8962af_reset(struct fxls8962af_data *data) unsigned int reg; int ret; - ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, - FXLS8962AF_SENS_CONFIG1_RST, - FXLS8962AF_SENS_CONFIG1_RST); + ret = regmap_set_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_RST); if (ret) return ret; @@ -830,9 +829,8 @@ static int fxls8962af_buffer_postenable(struct iio_dev *indio_dev) fxls8962af_standby(data); /* Enable buffer interrupt */ - ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, - FXLS8962AF_INT_EN_BUF_EN, - FXLS8962AF_INT_EN_BUF_EN); + ret = regmap_set_bits(data->regmap, FXLS8962AF_INT_EN, + FXLS8962AF_INT_EN_BUF_EN); if (ret) return ret; @@ -851,8 +849,8 @@ static int fxls8962af_buffer_predisable(struct iio_dev *indio_dev) fxls8962af_standby(data); /* Disable buffer interrupt */ - ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, - FXLS8962AF_INT_EN_BUF_EN, 0); + ret = regmap_clear_bits(data->regmap, FXLS8962AF_INT_EN, + FXLS8962AF_INT_EN_BUF_EN); if (ret) return ret; diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c index 3bc9ee1f9db3..c4c7e2d4e98a 100644 --- a/drivers/iio/accel/kxsd9-i2c.c +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -43,8 +43,8 @@ static const struct of_device_id kxsd9_of_match[] = { MODULE_DEVICE_TABLE(of, kxsd9_of_match); static const struct i2c_device_id kxsd9_i2c_id[] = { - {"kxsd9", 0}, - { }, + { "kxsd9" }, + { } }; MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id); diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index ba99649fe195..70dfd6e354db 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -370,10 +370,7 @@ static int kxsd9_power_down(struct kxsd9_state *st) * make sure we conserve power even if there are others users on the * regulators. */ - ret = regmap_update_bits(st->map, - KXSD9_REG_CTRL_B, - KXSD9_CTRL_B_ENABLE, - 0); + ret = regmap_clear_bits(st->map, KXSD9_REG_CTRL_B, KXSD9_CTRL_B_ENABLE); if (ret) return ret; diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c index 6b87c2c9945c..caa40a14a631 100644 --- a/drivers/iio/accel/mc3230.c +++ b/drivers/iio/accel/mc3230.c @@ -180,7 +180,7 @@ static int mc3230_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(mc3230_pm_ops, mc3230_suspend, mc3230_resume); static const struct i2c_device_id mc3230_i2c_id[] = { - {"mc3230", 0}, + { "mc3230" }, {} }; MODULE_DEVICE_TABLE(i2c, mc3230_i2c_id); diff --git a/drivers/iio/accel/mma7455_i2c.c b/drivers/iio/accel/mma7455_i2c.c index 14f7850a22f0..36a357c8e9ed 100644 --- a/drivers/iio/accel/mma7455_i2c.c +++ b/drivers/iio/accel/mma7455_i2c.c @@ -32,8 +32,8 @@ static void mma7455_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id mma7455_i2c_ids[] = { - { "mma7455", 0 }, - { "mma7456", 0 }, + { "mma7455" }, + { "mma7456" }, { } }; MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids); diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 260cbceaa151..2894aff80161 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -38,21 +38,6 @@ static const int mma7660_nscale = 467142857; -#define MMA7660_CHANNEL(reg, axis) { \ - .type = IIO_ACCEL, \ - .address = reg, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ -} - -static const struct iio_chan_spec mma7660_channels[] = { - MMA7660_CHANNEL(MMA7660_REG_XOUT, X), - MMA7660_CHANNEL(MMA7660_REG_YOUT, Y), - MMA7660_CHANNEL(MMA7660_REG_ZOUT, Z), -}; - enum mma7660_mode { MMA7660_MODE_STANDBY, MMA7660_MODE_ACTIVE @@ -62,6 +47,21 @@ struct mma7660_data { struct i2c_client *client; struct mutex lock; enum mma7660_mode mode; + struct iio_mount_matrix orientation; +}; + +static const struct iio_mount_matrix * +mma7660_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct mma7660_data *data = iio_priv(indio_dev); + + return &data->orientation; +} + +static const struct iio_chan_spec_ext_info mma7660_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, mma7660_get_mount_matrix), + { } }; static IIO_CONST_ATTR(in_accel_scale_available, MMA7660_SCALE_AVAIL); @@ -75,6 +75,22 @@ static const struct attribute_group mma7660_attribute_group = { .attrs = mma7660_attributes }; +#define MMA7660_CHANNEL(reg, axis) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .ext_info = mma7660_ext_info, \ +} + +static const struct iio_chan_spec mma7660_channels[] = { + MMA7660_CHANNEL(MMA7660_REG_XOUT, X), + MMA7660_CHANNEL(MMA7660_REG_YOUT, Y), + MMA7660_CHANNEL(MMA7660_REG_ZOUT, Z), +}; + static int mma7660_set_mode(struct mma7660_data *data, enum mma7660_mode mode) { @@ -187,6 +203,10 @@ static int mma7660_probe(struct i2c_client *client) mutex_init(&data->lock); data->mode = MMA7660_MODE_STANDBY; + ret = iio_read_mount_matrix(&client->dev, &data->orientation); + if (ret) + return ret; + indio_dev->info = &mma7660_info; indio_dev->name = MMA7660_DRIVER_NAME; indio_dev->modes = INDIO_DIRECT_MODE; @@ -241,7 +261,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, mma7660_resume); static const struct i2c_device_id mma7660_i2c_id[] = { - {"mma7660", 0}, + { "mma7660" }, {} }; MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 083c08f65baf..fa1799b0b0df 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -595,7 +595,7 @@ static const struct acpi_device_id mma9551_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); static const struct i2c_device_id mma9551_id[] = { - {"mma9551", 0}, + { "mma9551" }, {} }; diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 3cbd0fd4e624..86543f34ef17 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -1234,8 +1234,8 @@ static const struct acpi_device_id mma9553_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match); static const struct i2c_device_id mma9553_id[] = { - {"mma9553", 0}, - {}, + { "mma9553" }, + {} }; MODULE_DEVICE_TABLE(i2c, mma9553_id); diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c index b8ddbfd98f11..4cdbf5424a53 100644 --- a/drivers/iio/accel/msa311.c +++ b/drivers/iio/accel/msa311.c @@ -1034,10 +1034,10 @@ static int msa311_chip_init(struct msa311_priv *msa311) "failed to unmap map0/map1 interrupts\n"); /* Disable all axes by default */ - err = regmap_update_bits(msa311->regs, MSA311_ODR_REG, - MSA311_GENMASK(F_X_AXIS_DIS) | - MSA311_GENMASK(F_Y_AXIS_DIS) | - MSA311_GENMASK(F_Z_AXIS_DIS), 0); + err = regmap_clear_bits(msa311->regs, MSA311_ODR_REG, + MSA311_GENMASK(F_X_AXIS_DIS) | + MSA311_GENMASK(F_Y_AXIS_DIS) | + MSA311_GENMASK(F_Z_AXIS_DIS)); if (err) return dev_err_probe(dev, err, "can't enable all axes\n"); diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index e56407b6f204..fc54a2a4693c 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -584,9 +584,9 @@ static const struct of_device_id mxc4005_of_match[] = { MODULE_DEVICE_TABLE(of, mxc4005_of_match); static const struct i2c_device_id mxc4005_id[] = { - {"mxc4005", 0}, - {"mxc6655", 0}, - { }, + { "mxc4005" }, + { "mxc6655" }, + { } }; MODULE_DEVICE_TABLE(i2c, mxc4005_id); diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index ac228128c4f9..a8abda7b2a63 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -172,8 +172,8 @@ static const struct acpi_device_id mxc6255_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match); static const struct i2c_device_id mxc6255_id[] = { - {"mxc6225", 0}, - {"mxc6255", 0}, + { "mxc6225" }, + { "mxc6255" }, { } }; MODULE_DEVICE_TABLE(i2c, mxc6255_id); diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index e7525615712b..2659f536cef6 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -35,6 +35,7 @@ #define LIS3DHH_ACCEL_DEV_NAME "lis3dhh" #define LIS3DE_ACCEL_DEV_NAME "lis3de" #define LIS2DE12_ACCEL_DEV_NAME "lis2de12" +#define LIS2DS12_ACCEL_DEV_NAME "lis2ds12" #define LIS2HH12_ACCEL_DEV_NAME "lis2hh12" #define LIS302DL_ACCEL_DEV_NAME "lis302dl" #define LSM303C_ACCEL_DEV_NAME "lsm303c_accel" diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index d2104e14e255..0e371efbda70 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -925,6 +925,87 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .multi_read_bit = true, .bootime = 2, }, + { + .wai = 0x43, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LIS2DS12_ACCEL_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_16bit_channels, + .odr = { + .addr = 0x20, + .mask = 0xf0, + .odr_avl = { + { .hz = 10, .value = 0x01, }, + { .hz = 50, .value = 0x02, }, + { .hz = 100, .value = 0x03, }, + { .hz = 200, .value = 0x04, }, + { .hz = 400, .value = 0x05, }, + { .hz = 800, .value = 0x06, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0xf0, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x20, + .mask = 0x0c, + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_2G, + .value = 0x00, + .gain = IIO_G_TO_M_S_2(61), + }, + [1] = { + .num = ST_ACCEL_FS_AVL_4G, + .value = 0x02, + .gain = IIO_G_TO_M_S_2(122), + }, + [2] = { + .num = ST_ACCEL_FS_AVL_8G, + .value = 0x03, + .gain = IIO_G_TO_M_S_2(244), + }, + [3] = { + .num = ST_ACCEL_FS_AVL_16G, + .value = 0x01, + .gain = IIO_G_TO_M_S_2(488), + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = 0x01, + }, + .drdy_irq = { + .int1 = { + .addr = 0x23, + .mask = 0x01, + }, + .int2 = { + .addr = 0x24, + .mask = 0x01, + }, + .addr_ihl = 0x22, + .mask_ihl = 0x02, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x01, + }, + }, + .sim = { + .addr = 0x21, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, { .wai = 0x41, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index fd3749871121..329a4d6fb2ec 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -102,6 +102,10 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lis2de12", .data = LIS2DE12_ACCEL_DEV_NAME, }, + { + .compatible = "st,lis2ds12", + .data = LIS2DS12_ACCEL_DEV_NAME, + }, { .compatible = "st,lis2hh12", .data = LIS2HH12_ACCEL_DEV_NAME, @@ -154,6 +158,7 @@ static const struct i2c_device_id st_accel_id_table[] = { { LIS2DW12_ACCEL_DEV_NAME }, { LIS3DE_ACCEL_DEV_NAME }, { LIS2DE12_ACCEL_DEV_NAME }, + { LIS2DS12_ACCEL_DEV_NAME }, { LIS2HH12_ACCEL_DEV_NAME }, { LIS302DL_ACCEL_DEV_NAME }, { LSM303C_ACCEL_DEV_NAME }, diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index f72a24f45322..825adab37105 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -64,6 +64,10 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lis2dh12-accel", .data = LIS2DH12_ACCEL_DEV_NAME, }, + { + .compatible = "st,lis2ds12", + .data = LIS2DS12_ACCEL_DEV_NAME, + }, { .compatible = "st,lis3l02dq", .data = LIS3L02DQ_ACCEL_DEV_NAME, @@ -151,6 +155,7 @@ static const struct spi_device_id st_accel_id_table[] = { { LSM330_ACCEL_DEV_NAME }, { LSM303AGR_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME }, + { LIS2DS12_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME }, { LNG2DM_ACCEL_DEV_NAME }, { H3LIS331DL_ACCEL_DEV_NAME }, diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index ef0ae7672253..b3534d5751b9 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -633,8 +633,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, static const struct i2c_device_id stk8312_i2c_id[] = { /* Deprecated in favour of lowercase form */ - { "STK8312", 0 }, - { "stk8312", 0 }, + { "STK8312" }, + { "stk8312" }, {} }; MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id); diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index 668edc88c89d..6d3c7f444d21 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -525,7 +525,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend, stk8ba50_resume); static const struct i2c_device_id stk8ba50_i2c_id[] = { - {"stk8ba50", 0}, + { "stk8ba50" }, {} }; MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 8db68b80b391..f60fe85a30d5 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -88,12 +88,17 @@ config AD7173 called ad7173. config AD7192 - tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver" + tristate "Analog Devices AD7192 and similar ADC driver" depends on SPI select AD_SIGMA_DELTA help - Say yes here to build support for Analog Devices AD7190, - AD7192, AD7193 or AD7195 SPI analog to digital converters (ADC). + Say yes here to build support for Analog Devices SPI analog to digital + converters (ADC): + - AD7190 + - AD7192 + - AD7193 + - AD7194 + - AD7195 If unsure, say N (but it's safe to say "Y"). To compile this driver as a module, choose M here: the @@ -155,6 +160,22 @@ config AD7298 To compile this driver as a module, choose M here: the module will be called ad7298. +config AD7380 + tristate "Analog Devices AD7380 ADC driver" + depends on SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER + help + AD7380 is a family of simultaneous sampling ADCs that share the same + SPI register map and have similar pinouts. + + Say yes here to build support for Analog Devices AD7380 ADC and + similar chips. + + To compile this driver as a module, choose M here: the module will be + called ad7380. + config AD7476 tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD and TI" depends on SPI @@ -332,6 +353,7 @@ config AD9467 config ADI_AXI_ADC tristate "Analog Devices Generic AXI ADC IP core driver" + depends on MICROBLAZE || NIOS2 || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_INTEL_SOCFPGA || COMPILE_TEST select IIO_BUFFER select IIO_BUFFER_HW_CONSUMER select IIO_BUFFER_DMAENGINE @@ -870,6 +892,18 @@ config MCP3911 This driver can also be built as a module. If so, the module will be called mcp3911. +config MEDIATEK_MT6359_AUXADC + tristate "MediaTek MT6359 PMIC AUXADC driver" + depends on MFD_MT6397 + help + Say yes here to enable support for MediaTek MT6357, MT6358 and + MT6359 PMICs Auxiliary ADC. + This driver provides multiple channels for system monitoring, + such as battery voltage, PMIC temperature, and others. + + This driver can also be built as a module. If so, the module will be + called mt6359-auxadc. + config MEDIATEK_MT6360_ADC tristate "Mediatek MT6360 ADC driver" depends on MFD_MT6360 @@ -1329,6 +1363,18 @@ config TI_ADS1015 This driver can also be built as a module. If so, the module will be called ti-ads1015. +config TI_ADS1119 + tristate "Texas Instruments ADS1119 ADC" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADS1119 + ADC chip. + + This driver can also be built as a module. If so, the module will be + called ti-ads1119. + config TI_ADS7924 tristate "Texas Instruments ADS7924 ADC" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index edb32ce2af02..d370e066544e 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_AD7280) += ad7280a.o obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7292) += ad7292.o obj-$(CONFIG_AD7298) += ad7298.o -obj-$(CONFIG_AD7923) += ad7923.o +obj-$(CONFIG_AD7380) += ad7380.o obj-$(CONFIG_AD7476) += ad7476.o obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o @@ -29,6 +29,7 @@ obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7791) += ad7791.o obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7887) += ad7887.o +obj-$(CONFIG_AD7923) += ad7923.o obj-$(CONFIG_AD7944) += ad7944.o obj-$(CONFIG_AD7949) += ad7949.o obj-$(CONFIG_AD799X) += ad799x.o @@ -79,6 +80,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o obj-$(CONFIG_MCP3564) += mcp3564.o obj-$(CONFIG_MCP3911) += mcp3911.o +obj-$(CONFIG_MEDIATEK_MT6359_AUXADC) += mt6359-auxadc.o obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o @@ -90,42 +92,44 @@ obj-$(CONFIG_NAU7802) += nau7802.o obj-$(CONFIG_NPCM_ADC) += npcm_adc.o obj-$(CONFIG_PAC1934) += pac1934.o obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o +obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o obj-$(CONFIG_QCOM_SPMI_RRADC) += qcom-spmi-rradc.o -obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o -obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o +obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o +obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o -obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o obj-$(CONFIG_RZG2L_ADC) += rzg2l_adc.o obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o +obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o obj-$(CONFIG_SPEAR_ADC) += spear_adc.o -obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o -obj-$(CONFIG_SUN20I_GPADC) += sun20i-gpadc-iio.o obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o -obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o +obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o +obj-$(CONFIG_SUN20I_GPADC) += sun20i-gpadc-iio.o +obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o -obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o obj-$(CONFIG_TI_ADC108S102) += ti-adc108s102.o +obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o obj-$(CONFIG_TI_ADS1100) += ti-ads1100.o +obj-$(CONFIG_TI_ADS1119) += ti-ads1119.o +obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o obj-$(CONFIG_TI_ADS1298) += ti-ads1298.o +obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o obj-$(CONFIG_TI_ADS7924) += ti-ads7924.o obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o -obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o -obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TI_LMP92064) += ti-lmp92064.o obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o @@ -134,7 +138,6 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o obj-$(CONFIG_VF610_ADC) += vf610_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o +obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o -obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o -obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c index aaf1fb0ac447..e134d6497827 100644 --- a/drivers/iio/adc/ad4130.c +++ b/drivers/iio/adc/ad4130.c @@ -1883,8 +1883,8 @@ static int ad4130_setup(struct iio_dev *indio_dev) if (ret) return ret; - ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG, - AD4130_FIFO_CONTROL_HEADER_MASK, 0); + ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG, + AD4130_FIFO_CONTROL_HEADER_MASK); if (ret) return ret; diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index e7b1d517d3de..3beed78496c5 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -555,10 +555,18 @@ static int ad7124_disable_all(struct ad_sigma_delta *sd) return 0; } +static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) +{ + struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); + + return ad7124_spi_write_mask(st, AD7124_CHANNEL(chan), AD7124_CHANNEL_EN_MSK, 0, 2); +} + static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .set_channel = ad7124_set_channel, .append_status = ad7124_append_status, .disable_all = ad7124_disable_all, + .disable_one = ad7124_disable_one, .set_mode = ad7124_set_mode, .has_registers = true, .addr_shift = 0, @@ -582,12 +590,6 @@ static int ad7124_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; - /* After the conversion is performed, disable the channel */ - ret = ad_sd_write_reg(&st->sd, AD7124_CHANNEL(chan->address), 2, - st->channels[chan->address].ain | AD7124_CHANNEL_EN(0)); - if (ret < 0) - return ret; - return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: mutex_lock(&st->cfgs_lock); diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c index b26d4575e256..9544bf7142ad 100644 --- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * AD717x family SPI ADC driver + * AD717x and AD411x family SPI ADC driver * * Supported devices: + * AD4111/AD4112/AD4114/AD4115/AD4116 * AD7172-2/AD7172-4/AD7173-8/AD7175-2 * AD7175-8/AD7176-2/AD7177-2 * @@ -60,11 +61,19 @@ #define AD7173_CH_SETUP_AINPOS_MASK GENMASK(9, 5) #define AD7173_CH_SETUP_AINNEG_MASK GENMASK(4, 0) +#define AD7173_NO_AINS_PER_CHANNEL 2 #define AD7173_CH_ADDRESS(pos, neg) \ (FIELD_PREP(AD7173_CH_SETUP_AINPOS_MASK, pos) | \ FIELD_PREP(AD7173_CH_SETUP_AINNEG_MASK, neg)) #define AD7173_AIN_TEMP_POS 17 #define AD7173_AIN_TEMP_NEG 18 +#define AD7173_AIN_POW_MON_POS 19 +#define AD7173_AIN_POW_MON_NEG 20 +#define AD7173_AIN_REF_POS 21 +#define AD7173_AIN_REF_NEG 22 + +#define AD7173_IS_REF_INPUT(x) ((x) == AD7173_AIN_REF_POS || \ + (x) == AD7173_AIN_REF_NEG) #define AD7172_2_ID 0x00d0 #define AD7175_ID 0x0cd0 @@ -72,6 +81,11 @@ #define AD7175_2_ID 0x0cd0 #define AD7172_4_ID 0x2050 #define AD7173_ID 0x30d0 +#define AD4111_ID AD7173_ID +#define AD4112_ID AD7173_ID +#define AD4114_ID AD7173_ID +#define AD4116_ID 0x34d0 +#define AD4115_ID 0x38d0 #define AD7175_8_ID 0x3cd0 #define AD7177_ID 0x4fd0 #define AD7173_ID_MASK GENMASK(15, 4) @@ -102,6 +116,7 @@ #define AD7173_GPO12_DATA(x) BIT((x) + 0) #define AD7173_GPO23_DATA(x) BIT((x) + 4) +#define AD4111_GPO01_DATA(x) BIT((x) + 6) #define AD7173_GPO_DATA(x) ((x) < 2 ? AD7173_GPO12_DATA(x) : AD7173_GPO23_DATA(x)) #define AD7173_INTERFACE_DATA_STAT BIT(6) @@ -120,34 +135,45 @@ #define AD7173_VOLTAGE_INT_REF_uV 2500000 #define AD7173_TEMP_SENSIIVITY_uV_per_C 477 #define AD7177_ODR_START_VALUE 0x07 +#define AD4111_SHUNT_RESISTOR_OHM 50 +#define AD4111_DIVIDER_RATIO 10 +#define AD4111_CURRENT_CHAN_CUTOFF 16 +#define AD4111_VINCOM_INPUT 0x10 + +/* pin < num_voltage_in is a normal voltage input */ +/* pin >= num_voltage_in_div is a voltage input without a divider */ +#define AD4111_IS_VINCOM_MISMATCH(pin1, pin2) ((pin1) == AD4111_VINCOM_INPUT && \ + (pin2) < st->info->num_voltage_in && \ + (pin2) >= st->info->num_voltage_in_div) #define AD7173_FILTER_ODR0_MASK GENMASK(5, 0) #define AD7173_MAX_CONFIGS 8 -enum ad7173_ids { - ID_AD7172_2, - ID_AD7172_4, - ID_AD7173_8, - ID_AD7175_2, - ID_AD7175_8, - ID_AD7176_2, - ID_AD7177_2, -}; - struct ad7173_device_info { const unsigned int *sinc5_data_rates; unsigned int num_sinc5_data_rates; unsigned int odr_start_value; + /* + * AD4116 has both inputs with a voltage divider and without. + * These inputs cannot be mixed in the channel configuration. + * Does not include the VINCOM input. + */ + unsigned int num_voltage_in_div; unsigned int num_channels; unsigned int num_configs; - unsigned int num_inputs; + unsigned int num_voltage_in; unsigned int clock; unsigned int id; char *name; + bool has_current_inputs; + bool has_vincom_input; bool has_temp; + /* ((AVDD1 − AVSS)/5) */ + bool has_pow_supply_monitoring; bool has_input_buf; bool has_int_ref; bool has_ref2; + bool higher_gpio_bits; u8 num_gpios; }; @@ -189,6 +215,24 @@ struct ad7173_state { #endif }; +static unsigned int ad4115_sinc5_data_rates[] = { + 24845000, 24845000, 20725000, 20725000, /* 0-3 */ + 15564000, 13841000, 10390000, 10390000, /* 4-7 */ + 4994000, 2499000, 1000000, 500000, /* 8-11 */ + 395500, 200000, 100000, 59890, /* 12-15 */ + 49920, 20000, 16660, 10000, /* 16-19 */ + 5000, 2500, 2500, /* 20-22 */ +}; + +static unsigned int ad4116_sinc5_data_rates[] = { + 12422360, 12422360, 12422360, 12422360, /* 0-3 */ + 10362690, 10362690, 7782100, 6290530, /* 4-7 */ + 5194800, 2496900, 1007600, 499900, /* 8-11 */ + 390600, 200300, 100000, 59750, /* 12-15 */ + 49840, 20000, 16650, 10000, /* 16-19 */ + 5000, 2500, 1250, /* 20-22 */ +}; + static const unsigned int ad7173_sinc5_data_rates[] = { 6211000, 6211000, 6211000, 6211000, 6211000, 6211000, 5181000, 4444000, /* 0-7 */ 3115000, 2597000, 1007000, 503800, 381000, 200300, 100500, 59520, /* 8-15 */ @@ -204,108 +248,214 @@ static const unsigned int ad7175_sinc5_data_rates[] = { 5000, /* 20 */ }; -static const struct ad7173_device_info ad7173_device_info[] = { - [ID_AD7172_2] = { - .name = "ad7172-2", - .id = AD7172_2_ID, - .num_inputs = 5, - .num_channels = 4, - .num_configs = 4, - .num_gpios = 2, - .has_temp = true, - .has_input_buf = true, - .has_int_ref = true, - .clock = 2 * HZ_PER_MHZ, - .sinc5_data_rates = ad7173_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), - }, - [ID_AD7172_4] = { - .name = "ad7172-4", - .id = AD7172_4_ID, - .num_inputs = 9, - .num_channels = 8, - .num_configs = 8, - .num_gpios = 4, - .has_temp = false, - .has_input_buf = true, - .has_ref2 = true, - .clock = 2 * HZ_PER_MHZ, - .sinc5_data_rates = ad7173_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), - }, - [ID_AD7173_8] = { - .name = "ad7173-8", - .id = AD7173_ID, - .num_inputs = 17, - .num_channels = 16, - .num_configs = 8, - .num_gpios = 4, - .has_temp = true, - .has_input_buf = true, - .has_int_ref = true, - .has_ref2 = true, - .clock = 2 * HZ_PER_MHZ, - .sinc5_data_rates = ad7173_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), - }, - [ID_AD7175_2] = { - .name = "ad7175-2", - .id = AD7175_2_ID, - .num_inputs = 5, - .num_channels = 4, - .num_configs = 4, - .num_gpios = 2, - .has_temp = true, - .has_input_buf = true, - .has_int_ref = true, - .clock = 16 * HZ_PER_MHZ, - .sinc5_data_rates = ad7175_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), - }, - [ID_AD7175_8] = { - .name = "ad7175-8", - .id = AD7175_8_ID, - .num_inputs = 17, - .num_channels = 16, - .num_configs = 8, - .num_gpios = 4, - .has_temp = true, - .has_input_buf = true, - .has_int_ref = true, - .has_ref2 = true, - .clock = 16 * HZ_PER_MHZ, - .sinc5_data_rates = ad7175_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), - }, - [ID_AD7176_2] = { - .name = "ad7176-2", - .id = AD7176_ID, - .num_inputs = 5, - .num_channels = 4, - .num_configs = 4, - .num_gpios = 2, - .has_temp = false, - .has_input_buf = false, - .has_int_ref = true, - .clock = 16 * HZ_PER_MHZ, - .sinc5_data_rates = ad7175_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), - }, - [ID_AD7177_2] = { - .name = "ad7177-2", - .id = AD7177_ID, - .num_inputs = 5, - .num_channels = 4, - .num_configs = 4, - .num_gpios = 2, - .has_temp = true, - .has_input_buf = true, - .has_int_ref = true, - .clock = 16 * HZ_PER_MHZ, - .odr_start_value = AD7177_ODR_START_VALUE, - .sinc5_data_rates = ad7175_sinc5_data_rates, - .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), - }, +static unsigned int ad4111_current_channel_config[] = { + /* Ain sel: pos neg */ + 0x1E8, /* 15:IIN0+ 8:IIN0− */ + 0x1C9, /* 14:IIN1+ 9:IIN1− */ + 0x1AA, /* 13:IIN2+ 10:IIN2− */ + 0x18B, /* 12:IIN3+ 11:IIN3− */ +}; + +static const struct ad7173_device_info ad4111_device_info = { + .name = "ad4111", + .id = AD4111_ID, + .num_voltage_in_div = 8, + .num_channels = 16, + .num_configs = 8, + .num_voltage_in = 8, + .num_gpios = 2, + .higher_gpio_bits = true, + .has_temp = true, + .has_vincom_input = true, + .has_input_buf = true, + .has_current_inputs = true, + .has_int_ref = true, + .clock = 2 * HZ_PER_MHZ, + .sinc5_data_rates = ad7173_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad4112_device_info = { + .name = "ad4112", + .id = AD4112_ID, + .num_voltage_in_div = 8, + .num_channels = 16, + .num_configs = 8, + .num_voltage_in = 8, + .num_gpios = 2, + .higher_gpio_bits = true, + .has_vincom_input = true, + .has_temp = true, + .has_input_buf = true, + .has_current_inputs = true, + .has_int_ref = true, + .clock = 2 * HZ_PER_MHZ, + .sinc5_data_rates = ad7173_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad4114_device_info = { + .name = "ad4114", + .id = AD4114_ID, + .num_voltage_in_div = 16, + .num_channels = 16, + .num_configs = 8, + .num_voltage_in = 16, + .num_gpios = 4, + .higher_gpio_bits = true, + .has_vincom_input = true, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .clock = 2 * HZ_PER_MHZ, + .sinc5_data_rates = ad7173_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad4115_device_info = { + .name = "ad4115", + .id = AD4115_ID, + .num_voltage_in_div = 16, + .num_channels = 16, + .num_configs = 8, + .num_voltage_in = 16, + .num_gpios = 4, + .higher_gpio_bits = true, + .has_vincom_input = true, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .clock = 8 * HZ_PER_MHZ, + .sinc5_data_rates = ad4115_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad4115_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad4116_device_info = { + .name = "ad4116", + .id = AD4116_ID, + .num_voltage_in_div = 11, + .num_channels = 16, + .num_configs = 8, + .num_voltage_in = 16, + .num_gpios = 4, + .higher_gpio_bits = true, + .has_vincom_input = true, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .clock = 4 * HZ_PER_MHZ, + .sinc5_data_rates = ad4116_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad4116_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7172_2_device_info = { + .name = "ad7172-2", + .id = AD7172_2_ID, + .num_voltage_in = 5, + .num_channels = 4, + .num_configs = 4, + .num_gpios = 2, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .has_pow_supply_monitoring = true, + .clock = 2 * HZ_PER_MHZ, + .sinc5_data_rates = ad7173_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7172_4_device_info = { + .name = "ad7172-4", + .id = AD7172_4_ID, + .num_voltage_in = 9, + .num_channels = 8, + .num_configs = 8, + .num_gpios = 4, + .has_input_buf = true, + .has_ref2 = true, + .has_pow_supply_monitoring = true, + .clock = 2 * HZ_PER_MHZ, + .sinc5_data_rates = ad7173_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7173_8_device_info = { + .name = "ad7173-8", + .id = AD7173_ID, + .num_voltage_in = 17, + .num_channels = 16, + .num_configs = 8, + .num_gpios = 4, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .has_ref2 = true, + .clock = 2 * HZ_PER_MHZ, + .sinc5_data_rates = ad7173_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7175_2_device_info = { + .name = "ad7175-2", + .id = AD7175_2_ID, + .num_voltage_in = 5, + .num_channels = 4, + .num_configs = 4, + .num_gpios = 2, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .has_pow_supply_monitoring = true, + .clock = 16 * HZ_PER_MHZ, + .sinc5_data_rates = ad7175_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7175_8_device_info = { + .name = "ad7175-8", + .id = AD7175_8_ID, + .num_voltage_in = 17, + .num_channels = 16, + .num_configs = 8, + .num_gpios = 4, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .has_ref2 = true, + .has_pow_supply_monitoring = true, + .clock = 16 * HZ_PER_MHZ, + .sinc5_data_rates = ad7175_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7176_2_device_info = { + .name = "ad7176-2", + .id = AD7176_ID, + .num_voltage_in = 5, + .num_channels = 4, + .num_configs = 4, + .num_gpios = 2, + .has_int_ref = true, + .clock = 16 * HZ_PER_MHZ, + .sinc5_data_rates = ad7175_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), +}; + +static const struct ad7173_device_info ad7177_2_device_info = { + .name = "ad7177-2", + .id = AD7177_ID, + .num_voltage_in = 5, + .num_channels = 4, + .num_configs = 4, + .num_gpios = 2, + .has_temp = true, + .has_input_buf = true, + .has_int_ref = true, + .has_pow_supply_monitoring = true, + .clock = 16 * HZ_PER_MHZ, + .odr_start_value = AD7177_ODR_START_VALUE, + .sinc5_data_rates = ad7175_sinc5_data_rates, + .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates), }; static const char *const ad7173_ref_sel_str[] = { @@ -347,6 +497,15 @@ static int ad7173_mask_xlate(struct gpio_regmap *gpio, unsigned int base, return 0; } +static int ad4111_mask_xlate(struct gpio_regmap *gpio, unsigned int base, + unsigned int offset, unsigned int *reg, + unsigned int *mask) +{ + *mask = AD4111_GPO01_DATA(offset); + *reg = base; + return 0; +} + static void ad7173_gpio_disable(void *data) { struct ad7173_state *st = data; @@ -379,7 +538,10 @@ static int ad7173_gpio_init(struct ad7173_state *st) gpio_regmap.regmap = st->reg_gpiocon_regmap; gpio_regmap.ngpio = st->info->num_gpios; gpio_regmap.reg_set_base = AD7173_REG_GPIO; - gpio_regmap.reg_mask_xlate = ad7173_mask_xlate; + if (st->info->higher_gpio_bits) + gpio_regmap.reg_mask_xlate = ad4111_mask_xlate; + else + gpio_regmap.reg_mask_xlate = ad7173_mask_xlate; st->gpio_regmap = devm_gpio_regmap_register(dev, &gpio_regmap); ret = PTR_ERR_OR_ZERO(st->gpio_regmap); @@ -569,10 +731,16 @@ static int ad7173_disable_all(struct ad_sigma_delta *sd) return 0; } +static int ad7173_disable_one(struct ad_sigma_delta *sd, unsigned int chan) +{ + return ad_sd_write_reg(sd, AD7173_REG_CH(chan), 2, 0); +} + static struct ad_sigma_delta_info ad7173_sigma_delta_info = { .set_channel = ad7173_set_channel, .append_status = ad7173_append_status, .disable_all = ad7173_disable_all, + .disable_one = ad7173_disable_one, .set_mode = ad7173_set_mode, .has_registers = true, .addr_shift = 0, @@ -668,25 +836,35 @@ static int ad7173_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; - /* disable channel after single conversion */ - ret = ad_sd_write_reg(&st->sd, AD7173_REG_CH(chan->address), 2, 0); - if (ret < 0) - return ret; - return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - if (chan->type == IIO_TEMP) { + + switch (chan->type) { + case IIO_TEMP: temp = AD7173_VOLTAGE_INT_REF_uV * MILLI; temp /= AD7173_TEMP_SENSIIVITY_uV_per_C; *val = temp; *val2 = chan->scan_type.realbits; - } else { + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_VOLTAGE: *val = ad7173_get_ref_voltage_milli(st, ch->cfg.ref_sel); *val2 = chan->scan_type.realbits - !!(ch->cfg.bipolar); + + if (chan->channel < st->info->num_voltage_in_div) + *val *= AD4111_DIVIDER_RATIO; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CURRENT: + *val = ad7173_get_ref_voltage_milli(st, ch->cfg.ref_sel); + *val /= AD4111_SHUNT_RESISTOR_OHM; + *val2 = chan->scan_type.realbits - ch->cfg.bipolar; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; } - return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: - if (chan->type == IIO_TEMP) { + + switch (chan->type) { + case IIO_TEMP: /* 0 Kelvin -> raw sample */ temp = -ABSOLUTE_ZERO_MILLICELSIUS; temp *= AD7173_TEMP_SENSIIVITY_uV_per_C; @@ -695,10 +873,14 @@ static int ad7173_read_raw(struct iio_dev *indio_dev, AD7173_VOLTAGE_INT_REF_uV * MILLI); *val = -temp; - } else { + return IIO_VAL_INT; + case IIO_VOLTAGE: + case IIO_CURRENT: *val = -BIT(chan->scan_type.realbits - 1); + return IIO_VAL_INT; + default: + return -EINVAL; } - return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: reg = st->channels[chan->address].cfg.odr; @@ -725,6 +907,21 @@ static int ad7173_write_raw(struct iio_dev *indio_dev, return ret; switch (info) { + /* + * This attribute sets the sampling frequency for each channel individually. + * There are no issues for raw or buffered reads of an individual channel. + * + * When multiple channels are enabled in buffered mode, the effective + * sampling rate of a channel is lowered in correlation to the number + * of channels enabled and the sampling rate of the other channels. + * + * Example: 3 channels enabled with rates CH1:6211sps CH2,CH3:10sps + * While the reading of CH1 takes only 0.16ms, the reading of CH2 and CH3 + * will take 100ms each. + * + * This will cause the reading of CH1 to be actually done once every + * 200.16ms, an effective rate of 4.99sps. + */ case IIO_CHAN_INFO_SAMP_FREQ: freq = val * MILLI + val2 / MILLI; for (i = st->info->odr_start_value; i < st->info->num_sinc5_data_rates - 1; i++) @@ -904,14 +1101,110 @@ static int ad7173_register_clk_provider(struct iio_dev *indio_dev) &st->int_clk_hw); } +static int ad4111_validate_current_ain(struct ad7173_state *st, + const unsigned int ain[AD7173_NO_AINS_PER_CHANNEL]) +{ + struct device *dev = &st->sd.spi->dev; + + if (!st->info->has_current_inputs) + return dev_err_probe(dev, -EINVAL, + "Model %s does not support current channels\n", + st->info->name); + + if (ain[0] >= ARRAY_SIZE(ad4111_current_channel_config)) + return dev_err_probe(dev, -EINVAL, + "For current channels single-channel must be <[0-3]>\n"); + + return 0; +} + +static int ad7173_validate_voltage_ain_inputs(struct ad7173_state *st, + unsigned int ain0, unsigned int ain1) +{ + struct device *dev = &st->sd.spi->dev; + bool special_input0, special_input1; + + /* (AVDD1-AVSS)/5 power supply monitoring */ + if (ain0 == AD7173_AIN_POW_MON_POS && ain1 == AD7173_AIN_POW_MON_NEG && + st->info->has_pow_supply_monitoring) + return 0; + + special_input0 = AD7173_IS_REF_INPUT(ain0) || + (ain0 == AD4111_VINCOM_INPUT && st->info->has_vincom_input); + special_input1 = AD7173_IS_REF_INPUT(ain1) || + (ain1 == AD4111_VINCOM_INPUT && st->info->has_vincom_input); + + if ((ain0 >= st->info->num_voltage_in && !special_input0) || + (ain1 >= st->info->num_voltage_in && !special_input1)) { + if (ain0 == AD4111_VINCOM_INPUT || ain1 == AD4111_VINCOM_INPUT) + return dev_err_probe(dev, -EINVAL, + "VINCOM not supported for %s\n", st->info->name); + + return dev_err_probe(dev, -EINVAL, + "Input pin number out of range for pair (%d %d).\n", + ain0, ain1); + } + + if (AD4111_IS_VINCOM_MISMATCH(ain0, ain1) || + AD4111_IS_VINCOM_MISMATCH(ain1, ain0)) + return dev_err_probe(dev, -EINVAL, + "VINCOM must be paired with inputs having divider.\n"); + + if (!special_input0 && !special_input1 && + ((ain0 >= st->info->num_voltage_in_div) != + (ain1 >= st->info->num_voltage_in_div))) + return dev_err_probe(dev, -EINVAL, + "Both inputs must either have a voltage divider or not have: (%d %d).\n", + ain0, ain1); + + return 0; +} + +static int ad7173_validate_reference(struct ad7173_state *st, int ref_sel) +{ + struct device *dev = &st->sd.spi->dev; + int ret; + + if (ref_sel == AD7173_SETUP_REF_SEL_INT_REF && !st->info->has_int_ref) + return dev_err_probe(dev, -EINVAL, + "Internal reference is not available on current model.\n"); + + if (ref_sel == AD7173_SETUP_REF_SEL_EXT_REF2 && !st->info->has_ref2) + return dev_err_probe(dev, -EINVAL, + "External reference 2 is not available on current model.\n"); + + ret = ad7173_get_ref_voltage_milli(st, ref_sel); + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot use reference %u\n", + ref_sel); + + return 0; +} + static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev) { struct ad7173_channel *chans_st_arr, *chan_st_priv; struct ad7173_state *st = iio_priv(indio_dev); struct device *dev = indio_dev->dev.parent; struct iio_chan_spec *chan_arr, *chan; - unsigned int ain[2], chan_index = 0; - int ref_sel, ret; + unsigned int ain[AD7173_NO_AINS_PER_CHANNEL], chan_index = 0; + int ref_sel, ret, num_channels; + + num_channels = device_get_child_node_count(dev); + + if (st->info->has_temp) + num_channels++; + + if (num_channels == 0) + return dev_err_probe(dev, -ENODATA, "No channels specified\n"); + + if (num_channels > st->info->num_channels) + return dev_err_probe(dev, -EINVAL, + "Too many channels specified. Maximum is %d, not including temperature channel if supported.\n", + st->info->num_channels); + + indio_dev->num_channels = num_channels; + st->num_channels = num_channels; chan_arr = devm_kcalloc(dev, sizeof(*indio_dev->channels), st->num_channels, GFP_KERNEL); @@ -941,18 +1234,41 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev) } device_for_each_child_node_scoped(dev, child) { + bool is_current_chan = false; + chan = &chan_arr[chan_index]; + *chan = ad7173_channel_template; chan_st_priv = &chans_st_arr[chan_index]; ret = fwnode_property_read_u32_array(child, "diff-channels", ain, ARRAY_SIZE(ain)); - if (ret) - return ret; + if (ret) { + ret = fwnode_property_read_u32(child, "single-channel", + ain); + if (ret) + return dev_err_probe(dev, ret, + "Channel must define one of diff-channels or single-channel.\n"); - if (ain[0] >= st->info->num_inputs || - ain[1] >= st->info->num_inputs) - return dev_err_probe(dev, -EINVAL, - "Input pin number out of range for pair (%d %d).\n", - ain[0], ain[1]); + is_current_chan = fwnode_property_read_bool(child, "adi,current-channel"); + } else { + chan->differential = true; + } + + if (is_current_chan) { + ret = ad4111_validate_current_ain(st, ain); + if (ret) + return ret; + } else { + if (!chan->differential) { + ret = fwnode_property_read_u32(child, + "common-mode-channel", ain + 1); + if (ret) + return dev_err_probe(dev, ret, + "common-mode-channel must be defined for single-ended channels.\n"); + } + ret = ad7173_validate_voltage_ain_inputs(st, ain[0], ain[1]); + if (ret) + return ret; + } ret = fwnode_property_match_property_string(child, "adi,reference-select", @@ -963,32 +1279,17 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev) else ref_sel = ret; - if (ref_sel == AD7173_SETUP_REF_SEL_INT_REF && - !st->info->has_int_ref) - return dev_err_probe(dev, -EINVAL, - "Internal reference is not available on current model.\n"); - - if (ref_sel == AD7173_SETUP_REF_SEL_EXT_REF2 && !st->info->has_ref2) - return dev_err_probe(dev, -EINVAL, - "External reference 2 is not available on current model.\n"); - - ret = ad7173_get_ref_voltage_milli(st, ref_sel); - if (ret < 0) - return dev_err_probe(dev, ret, - "Cannot use reference %u\n", ref_sel); + ret = ad7173_validate_reference(st, ref_sel); + if (ret) + return ret; if (ref_sel == AD7173_SETUP_REF_SEL_INT_REF) st->adc_mode |= AD7173_ADC_MODE_REF_EN; chan_st_priv->cfg.ref_sel = ref_sel; - *chan = ad7173_channel_template; chan->address = chan_index; chan->scan_index = chan_index; chan->channel = ain[0]; - chan->channel2 = ain[1]; - chan->differential = true; - - chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]); chan_st_priv->chan_reg = chan_index; chan_st_priv->cfg.input_buf = st->info->has_input_buf; chan_st_priv->cfg.odr = 0; @@ -997,6 +1298,17 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev) if (chan_st_priv->cfg.bipolar) chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OFFSET); + if (is_current_chan) { + chan->type = IIO_CURRENT; + chan->differential = false; + chan->channel2 = 0; + chan_st_priv->ain = ad4111_current_channel_config[ain[0]]; + } else { + chan_st_priv->cfg.input_buf = st->info->has_input_buf; + chan->channel2 = ain[1]; + chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]); + } + chan_index++; } return 0; @@ -1006,7 +1318,6 @@ static int ad7173_fw_parse_device_config(struct iio_dev *indio_dev) { struct ad7173_state *st = iio_priv(indio_dev); struct device *dev = indio_dev->dev.parent; - unsigned int num_channels; int ret; st->regulators[0].supply = ad7173_ref_sel_str[AD7173_SETUP_REF_SEL_EXT_REF]; @@ -1065,16 +1376,6 @@ static int ad7173_fw_parse_device_config(struct iio_dev *indio_dev) ad7173_sigma_delta_info.irq_line = ret; - num_channels = device_get_child_node_count(dev); - - if (st->info->has_temp) - num_channels++; - - if (num_channels == 0) - return dev_err_probe(dev, -ENODATA, "No channels specified\n"); - indio_dev->num_channels = num_channels; - st->num_channels = num_channels; - return ad7173_fw_parse_channel_config(indio_dev); } @@ -1134,32 +1435,35 @@ static int ad7173_probe(struct spi_device *spi) } static const struct of_device_id ad7173_of_match[] = { - { .compatible = "adi,ad7172-2", - .data = &ad7173_device_info[ID_AD7172_2]}, - { .compatible = "adi,ad7172-4", - .data = &ad7173_device_info[ID_AD7172_4]}, - { .compatible = "adi,ad7173-8", - .data = &ad7173_device_info[ID_AD7173_8]}, - { .compatible = "adi,ad7175-2", - .data = &ad7173_device_info[ID_AD7175_2]}, - { .compatible = "adi,ad7175-8", - .data = &ad7173_device_info[ID_AD7175_8]}, - { .compatible = "adi,ad7176-2", - .data = &ad7173_device_info[ID_AD7176_2]}, - { .compatible = "adi,ad7177-2", - .data = &ad7173_device_info[ID_AD7177_2]}, + { .compatible = "ad4111", .data = &ad4111_device_info }, + { .compatible = "ad4112", .data = &ad4112_device_info }, + { .compatible = "ad4114", .data = &ad4114_device_info }, + { .compatible = "ad4115", .data = &ad4115_device_info }, + { .compatible = "ad4116", .data = &ad4116_device_info }, + { .compatible = "adi,ad7172-2", .data = &ad7172_2_device_info }, + { .compatible = "adi,ad7172-4", .data = &ad7172_4_device_info }, + { .compatible = "adi,ad7173-8", .data = &ad7173_8_device_info }, + { .compatible = "adi,ad7175-2", .data = &ad7175_2_device_info }, + { .compatible = "adi,ad7175-8", .data = &ad7175_8_device_info }, + { .compatible = "adi,ad7176-2", .data = &ad7176_2_device_info }, + { .compatible = "adi,ad7177-2", .data = &ad7177_2_device_info }, { } }; MODULE_DEVICE_TABLE(of, ad7173_of_match); static const struct spi_device_id ad7173_id_table[] = { - { "ad7172-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7172_2]}, - { "ad7172-4", (kernel_ulong_t)&ad7173_device_info[ID_AD7172_4]}, - { "ad7173-8", (kernel_ulong_t)&ad7173_device_info[ID_AD7173_8]}, - { "ad7175-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7175_2]}, - { "ad7175-8", (kernel_ulong_t)&ad7173_device_info[ID_AD7175_8]}, - { "ad7176-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7176_2]}, - { "ad7177-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7177_2]}, + { "ad4111", (kernel_ulong_t)&ad4111_device_info }, + { "ad4112", (kernel_ulong_t)&ad4112_device_info }, + { "ad4114", (kernel_ulong_t)&ad4114_device_info }, + { "ad4115", (kernel_ulong_t)&ad4115_device_info }, + { "ad4116", (kernel_ulong_t)&ad4116_device_info }, + { "ad7172-2", (kernel_ulong_t)&ad7172_2_device_info }, + { "ad7172-4", (kernel_ulong_t)&ad7172_4_device_info }, + { "ad7173-8", (kernel_ulong_t)&ad7173_8_device_info }, + { "ad7175-2", (kernel_ulong_t)&ad7175_2_device_info }, + { "ad7175-8", (kernel_ulong_t)&ad7175_8_device_info }, + { "ad7176-2", (kernel_ulong_t)&ad7176_2_device_info }, + { "ad7177-2", (kernel_ulong_t)&ad7177_2_device_info }, { } }; MODULE_DEVICE_TABLE(spi, ad7173_id_table); @@ -1177,5 +1481,5 @@ module_spi_driver(ad7173_driver); MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_AUTHOR("Dumitru Ceclan "); -MODULE_DESCRIPTION("Analog Devices AD7172/AD7173/AD7175/AD7176 ADC driver"); +MODULE_DESCRIPTION("Analog Devices AD7173 and similar ADC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 7bcc7e2aa2a2..334ab90991d4 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * AD7190 AD7192 AD7193 AD7195 SPI ADC driver + * AD7192 and similar SPI ADC driver * * Copyright 2011-2015 Analog Devices Inc. */ @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -128,10 +129,24 @@ #define AD7193_CH_AIN8 0x480 /* AIN7 - AINCOM */ #define AD7193_CH_AINCOM 0x600 /* AINCOM - AINCOM */ +#define AD7194_CH_POS(x) (((x) - 1) << 4) +#define AD7194_CH_NEG(x) ((x) - 1) + +/* 10th bit corresponds to CON18(Pseudo) */ +#define AD7194_CH(p) (BIT(10) | AD7194_CH_POS(p)) + +#define AD7194_DIFF_CH(p, n) (AD7194_CH_POS(p) | AD7194_CH_NEG(n)) +#define AD7194_CH_TEMP 0x100 +#define AD7194_CH_BASE_NR 2 +#define AD7194_CH_AIN_START 1 +#define AD7194_CH_AIN_NR 16 +#define AD7194_CH_MAX_NR 272 + /* ID Register Bit Designations (AD7192_REG_ID) */ #define CHIPID_AD7190 0x4 #define CHIPID_AD7192 0x0 #define CHIPID_AD7193 0x2 +#define CHIPID_AD7194 0x3 #define CHIPID_AD7195 0x6 #define AD7192_ID_MASK GENMASK(3, 0) @@ -169,6 +184,7 @@ enum { ID_AD7190, ID_AD7192, ID_AD7193, + ID_AD7194, ID_AD7195, }; @@ -177,19 +193,21 @@ struct ad7192_chip_info { const char *name; const struct iio_chan_spec *channels; u8 num_channels; + const struct ad_sigma_delta_info *sigma_delta_info; const struct iio_info *info; + int (*parse_channels)(struct iio_dev *indio_dev); }; struct ad7192_state { const struct ad7192_chip_info *chip_info; - struct regulator *avdd; - struct regulator *vref; struct clk *mclk; u16 int_vref_mv; + u32 aincom_mv; u32 fclk; u32 mode; u32 conf; u32 scale_avail[8][2]; + u32 filter_freq_avail[4][2]; u32 oversampling_ratio_avail[4]; u8 gpocon; u8 clock_sel; @@ -343,6 +361,18 @@ static const struct ad_sigma_delta_info ad7192_sigma_delta_info = { .irq_flags = IRQF_TRIGGER_FALLING, }; +static const struct ad_sigma_delta_info ad7194_sigma_delta_info = { + .set_channel = ad7192_set_channel, + .append_status = ad7192_append_status, + .disable_all = ad7192_disable_all, + .set_mode = ad7192_set_mode, + .has_registers = true, + .addr_shift = 3, + .read_mask = BIT(6), + .status_ch_mask = GENMASK(3, 0), + .irq_flags = IRQF_TRIGGER_FALLING, +}; + static const struct ad_sd_calib_data ad7192_calib_arr[8] = { {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1}, {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1}, @@ -473,6 +503,16 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev) st->oversampling_ratio_avail[2] = 8; st->oversampling_ratio_avail[3] = 16; + st->filter_freq_avail[0][0] = 600; + st->filter_freq_avail[1][0] = 800; + st->filter_freq_avail[2][0] = 2300; + st->filter_freq_avail[3][0] = 2720; + + st->filter_freq_avail[0][1] = 1000; + st->filter_freq_avail[1][1] = 1000; + st->filter_freq_avail[2][1] = 1000; + st->filter_freq_avail[3][1] = 1000; + return 0; } @@ -586,48 +626,24 @@ static int ad7192_get_f_adc(struct ad7192_state *st) f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode)); } -static void ad7192_get_available_filter_freq(struct ad7192_state *st, - int *freq) +static void ad7192_update_filter_freq_avail(struct ad7192_state *st) { unsigned int fadc; /* Formulas for filter at page 25 of the datasheet */ fadc = ad7192_compute_f_adc(st, false, true); - freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + st->filter_freq_avail[0][0] = DIV_ROUND_CLOSEST(fadc * 240, 1024); fadc = ad7192_compute_f_adc(st, true, true); - freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + st->filter_freq_avail[1][0] = DIV_ROUND_CLOSEST(fadc * 240, 1024); fadc = ad7192_compute_f_adc(st, false, false); - freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024); + st->filter_freq_avail[2][0] = DIV_ROUND_CLOSEST(fadc * 230, 1024); fadc = ad7192_compute_f_adc(st, true, false); - freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024); + st->filter_freq_avail[3][0] = DIV_ROUND_CLOSEST(fadc * 272, 1024); } -static ssize_t ad7192_show_filter_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7192_state *st = iio_priv(indio_dev); - unsigned int freq_avail[4], i; - size_t len = 0; - - ad7192_get_available_filter_freq(st, freq_avail); - - for (i = 0; i < ARRAY_SIZE(freq_avail); i++) - len += sysfs_emit_at(buf, len, "%d.%03d ", freq_avail[i] / 1000, - freq_avail[i] % 1000); - - buf[len - 1] = '\n'; - - return len; -} - -static IIO_DEVICE_ATTR(filter_low_pass_3db_frequency_available, - 0444, ad7192_show_filter_avail, NULL, 0); - static IIO_DEVICE_ATTR(bridge_switch_en, 0644, ad7192_show_bridge_switch, ad7192_set, AD7192_REG_GPOCON); @@ -637,7 +653,6 @@ static IIO_DEVICE_ATTR(ac_excitation_en, 0644, AD7192_REG_CONF); static struct attribute *ad7192_attributes[] = { - &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, NULL }; @@ -647,7 +662,6 @@ static const struct attribute_group ad7192_attribute_group = { }; static struct attribute *ad7195_attributes[] = { - &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, &iio_dev_attr_ac_excitation_en.dev_attr.attr, NULL @@ -665,17 +679,15 @@ static unsigned int ad7192_get_temp_scale(bool unipolar) static int ad7192_set_3db_filter_freq(struct ad7192_state *st, int val, int val2) { - int freq_avail[4], i, ret, freq; + int i, ret, freq; unsigned int diff_new, diff_old; int idx = 0; diff_old = U32_MAX; freq = val * 1000 + val2; - ad7192_get_available_filter_freq(st, freq_avail); - - for (i = 0; i < ARRAY_SIZE(freq_avail); i++) { - diff_new = abs(freq - freq_avail[i]); + for (i = 0; i < ARRAY_SIZE(st->filter_freq_avail); i++) { + diff_new = abs(freq - st->filter_freq_avail[i][0]); if (diff_new < diff_old) { diff_old = diff_new; idx = i; @@ -759,10 +771,24 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, *val = -(1 << (chan->scan_type.realbits - 1)); else *val = 0; + + switch (chan->type) { + case IIO_VOLTAGE: + /* + * Only applies to pseudo-differential inputs. + * AINCOM voltage has to be converted to "raw" units. + */ + if (st->aincom_mv && !chan->differential) + *val += DIV_ROUND_CLOSEST_ULL((u64)st->aincom_mv * NANO, + st->scale_avail[gain][1]); + return IIO_VAL_INT; /* Kelvin to Celsius */ - if (chan->type == IIO_TEMP) + case IIO_TEMP: *val -= 273 * ad7192_get_temp_scale(unipolar); - return IIO_VAL_INT; + return IIO_VAL_INT; + default: + return -EINVAL; + } case IIO_CHAN_INFO_SAMP_FREQ: *val = DIV_ROUND_CLOSEST(ad7192_get_f_adc(st), 1024); return IIO_VAL_INT; @@ -792,10 +818,11 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, if (ret) return ret; + mutex_lock(&st->lock); + switch (mask) { case IIO_CHAN_INFO_SCALE: ret = -EINVAL; - mutex_lock(&st->lock); for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { ret = 0; @@ -809,7 +836,6 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, ad7192_calibrate_all(st); break; } - mutex_unlock(&st->lock); break; case IIO_CHAN_INFO_SAMP_FREQ: if (!val) { @@ -826,13 +852,13 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, st->mode &= ~AD7192_MODE_RATE_MASK; st->mode |= FIELD_PREP(AD7192_MODE_RATE_MASK, div); ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + ad7192_update_filter_freq_avail(st); break; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000); break; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ret = -EINVAL; - mutex_lock(&st->lock); for (i = 0; i < ARRAY_SIZE(st->oversampling_ratio_avail); i++) if (val == st->oversampling_ratio_avail[i]) { ret = 0; @@ -845,12 +871,14 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, 3, st->mode); break; } - mutex_unlock(&st->lock); + ad7192_update_filter_freq_avail(st); break; default: ret = -EINVAL; } + mutex_unlock(&st->lock); + iio_device_release_direct_mode(indio_dev); return ret; @@ -888,6 +916,12 @@ static int ad7192_read_avail(struct iio_dev *indio_dev, /* Values are stored in a 2D matrix */ *length = ARRAY_SIZE(st->scale_avail) * 2; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals = (int *)st->filter_freq_avail; + *type = IIO_VAL_FRACTIONAL; + *length = ARRAY_SIZE(st->filter_freq_avail) * 2; + return IIO_AVAIL_LIST; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *vals = (int *)st->oversampling_ratio_avail; @@ -930,6 +964,14 @@ static const struct iio_info ad7192_info = { .update_scan_mode = ad7192_update_scan_mode, }; +static const struct iio_info ad7194_info = { + .read_raw = ad7192_read_raw, + .write_raw = ad7192_write_raw, + .write_raw_get_fmt = ad7192_write_raw_get_fmt, + .read_avail = ad7192_read_avail, + .validate_trigger = ad_sd_validate_trigger, +}; + static const struct iio_info ad7195_info = { .read_raw = ad7192_read_raw, .write_raw = ad7192_write_raw, @@ -956,7 +998,9 @@ static const struct iio_info ad7195_info = { BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ (_mask_all), \ .info_mask_shared_by_type_available = (_mask_type_av), \ - .info_mask_shared_by_all_available = (_mask_all_av), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ + (_mask_all_av), \ .ext_info = (_ext_info), \ .scan_index = (_si), \ .scan_type = { \ @@ -1019,12 +1063,95 @@ static const struct iio_chan_spec ad7193_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(14), }; +static bool ad7194_validate_ain_channel(struct device *dev, u32 ain) +{ + return in_range(ain, AD7194_CH_AIN_START, AD7194_CH_AIN_NR); +} + +static int ad7194_parse_channels(struct iio_dev *indio_dev) +{ + struct device *dev = indio_dev->dev.parent; + struct iio_chan_spec *ad7194_channels; + const struct iio_chan_spec ad7194_chan = AD7193_CHANNEL(0, 0, 0); + const struct iio_chan_spec ad7194_chan_diff = AD7193_DIFF_CHANNEL(0, 0, 0, 0); + const struct iio_chan_spec ad7194_chan_temp = AD719x_TEMP_CHANNEL(0, 0); + const struct iio_chan_spec ad7194_chan_timestamp = IIO_CHAN_SOFT_TIMESTAMP(0); + unsigned int num_channels, index = 0; + u32 ain[2]; + int ret; + + num_channels = device_get_child_node_count(dev); + if (num_channels > AD7194_CH_MAX_NR) + return dev_err_probe(dev, -EINVAL, "Too many channels: %u\n", + num_channels); + + num_channels += AD7194_CH_BASE_NR; + + ad7194_channels = devm_kcalloc(dev, num_channels, + sizeof(*ad7194_channels), GFP_KERNEL); + if (!ad7194_channels) + return -ENOMEM; + + indio_dev->channels = ad7194_channels; + indio_dev->num_channels = num_channels; + + device_for_each_child_node_scoped(dev, child) { + ret = fwnode_property_read_u32_array(child, "diff-channels", + ain, ARRAY_SIZE(ain)); + if (ret == 0) { + if (!ad7194_validate_ain_channel(dev, ain[0])) + return dev_err_probe(dev, -EINVAL, + "Invalid AIN channel: %u\n", + ain[0]); + + if (!ad7194_validate_ain_channel(dev, ain[1])) + return dev_err_probe(dev, -EINVAL, + "Invalid AIN channel: %u\n", + ain[1]); + + *ad7194_channels = ad7194_chan_diff; + ad7194_channels->scan_index = index++; + ad7194_channels->channel = ain[0]; + ad7194_channels->channel2 = ain[1]; + ad7194_channels->address = AD7194_DIFF_CH(ain[0], ain[1]); + } else { + ret = fwnode_property_read_u32(child, "single-channel", + &ain[0]); + if (ret) + return dev_err_probe(dev, ret, + "Missing channel property\n"); + + if (!ad7194_validate_ain_channel(dev, ain[0])) + return dev_err_probe(dev, -EINVAL, + "Invalid AIN channel: %u\n", + ain[0]); + + *ad7194_channels = ad7194_chan; + ad7194_channels->scan_index = index++; + ad7194_channels->channel = ain[0]; + ad7194_channels->address = AD7194_CH(ain[0]); + } + ad7194_channels++; + } + + *ad7194_channels = ad7194_chan_temp; + ad7194_channels->scan_index = index++; + ad7194_channels->address = AD7194_CH_TEMP; + ad7194_channels++; + + *ad7194_channels = ad7194_chan_timestamp; + ad7194_channels->scan_index = index; + + return 0; +} + static const struct ad7192_chip_info ad7192_chip_info_tbl[] = { [ID_AD7190] = { .chip_id = CHIPID_AD7190, .name = "ad7190", .channels = ad7192_channels, .num_channels = ARRAY_SIZE(ad7192_channels), + .sigma_delta_info = &ad7192_sigma_delta_info, .info = &ad7192_info, }, [ID_AD7192] = { @@ -1032,6 +1159,7 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = { .name = "ad7192", .channels = ad7192_channels, .num_channels = ARRAY_SIZE(ad7192_channels), + .sigma_delta_info = &ad7192_sigma_delta_info, .info = &ad7192_info, }, [ID_AD7193] = { @@ -1039,34 +1167,37 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = { .name = "ad7193", .channels = ad7193_channels, .num_channels = ARRAY_SIZE(ad7193_channels), + .sigma_delta_info = &ad7192_sigma_delta_info, .info = &ad7192_info, }, + [ID_AD7194] = { + .chip_id = CHIPID_AD7194, + .name = "ad7194", + .info = &ad7194_info, + .sigma_delta_info = &ad7194_sigma_delta_info, + .parse_channels = ad7194_parse_channels, + }, [ID_AD7195] = { .chip_id = CHIPID_AD7195, .name = "ad7195", .channels = ad7192_channels, .num_channels = ARRAY_SIZE(ad7192_channels), + .sigma_delta_info = &ad7192_sigma_delta_info, .info = &ad7195_info, }, }; -static void ad7192_reg_disable(void *reg) -{ - regulator_disable(reg); -} - static int ad7192_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct ad7192_state *st; struct iio_dev *indio_dev; - int ret; + int ret, avdd_mv; - if (!spi->irq) { - dev_err(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } + if (!spi->irq) + return dev_err_probe(dev, -ENODEV, "Failed to get IRQ\n"); - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -1074,69 +1205,79 @@ static int ad7192_probe(struct spi_device *spi) mutex_init(&st->lock); - st->avdd = devm_regulator_get(&spi->dev, "avdd"); - if (IS_ERR(st->avdd)) - return PTR_ERR(st->avdd); + /* + * Regulator aincom is optional to maintain compatibility with older DT. + * Newer firmware should provide a zero volt fixed supply if wired to + * ground. + */ + ret = devm_regulator_get_enable_read_voltage(dev, "aincom"); + if (ret < 0 && ret != -ENODEV) + return dev_err_probe(dev, ret, "Failed to get AINCOM voltage\n"); - ret = regulator_enable(st->avdd); - if (ret) { - dev_err(&spi->dev, "Failed to enable specified AVdd supply\n"); + st->aincom_mv = ret == -ENODEV ? 0 : ret / MILLI; + + /* AVDD can optionally be used as reference voltage */ + ret = devm_regulator_get_enable_read_voltage(dev, "avdd"); + if (ret == -ENODEV || ret == -EINVAL) { + int ret2; + + /* + * We get -EINVAL if avdd is a supply with unknown voltage. We + * still need to enable it since it is also a power supply. + */ + ret2 = devm_regulator_get_enable(dev, "avdd"); + if (ret2) + return dev_err_probe(dev, ret2, + "Failed to enable AVDD supply\n"); + } else if (ret < 0) { + return dev_err_probe(dev, ret, "Failed to get AVDD voltage\n"); + } + + avdd_mv = ret == -ENODEV || ret == -EINVAL ? 0 : ret / MILLI; + + ret = devm_regulator_get_enable(dev, "dvdd"); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable specified DVdd supply\n"); + + /* + * This is either REFIN1 or REFIN2 depending on adi,refin2-pins-enable. + * If this supply is not present, fall back to AVDD as reference. + */ + ret = devm_regulator_get_enable_read_voltage(dev, "vref"); + if (ret == -ENODEV) { + if (avdd_mv == 0) + return dev_err_probe(dev, -ENODEV, + "No reference voltage available\n"); + } else if (ret < 0) { return ret; } - ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->avdd); - if (ret) - return ret; - - ret = devm_regulator_get_enable(&spi->dev, "dvdd"); - if (ret) - return dev_err_probe(&spi->dev, ret, "Failed to enable specified DVdd supply\n"); - - st->vref = devm_regulator_get_optional(&spi->dev, "vref"); - if (IS_ERR(st->vref)) { - if (PTR_ERR(st->vref) != -ENODEV) - return PTR_ERR(st->vref); - - ret = regulator_get_voltage(st->avdd); - if (ret < 0) - return dev_err_probe(&spi->dev, ret, - "Device tree error, AVdd voltage undefined\n"); - } else { - ret = regulator_enable(st->vref); - if (ret) { - dev_err(&spi->dev, "Failed to enable specified Vref supply\n"); - return ret; - } - - ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->vref); - if (ret) - return ret; - - ret = regulator_get_voltage(st->vref); - if (ret < 0) - return dev_err_probe(&spi->dev, ret, - "Device tree error, Vref voltage undefined\n"); - } - st->int_vref_mv = ret / 1000; + st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI; st->chip_info = spi_get_device_match_data(spi); indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; indio_dev->info = st->chip_info->info; + if (st->chip_info->parse_channels) { + ret = st->chip_info->parse_channels(indio_dev); + if (ret) + return ret; + } else { + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + } - ret = ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info); + ret = ad_sd_init(&st->sd, indio_dev, spi, st->chip_info->sigma_delta_info); if (ret) return ret; - ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev); if (ret) return ret; st->fclk = AD7192_INT_FREQ_MHZ; - st->mclk = devm_clk_get_optional_enabled(&spi->dev, "mclk"); + st->mclk = devm_clk_get_optional_enabled(dev, "mclk"); if (IS_ERR(st->mclk)) return PTR_ERR(st->mclk); @@ -1145,24 +1286,23 @@ static int ad7192_probe(struct spi_device *spi) if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 || st->clock_sel == AD7192_CLK_EXT_MCLK2) { st->fclk = clk_get_rate(st->mclk); - if (!ad7192_valid_external_frequency(st->fclk)) { - dev_err(&spi->dev, - "External clock frequency out of bounds\n"); - return -EINVAL; - } + if (!ad7192_valid_external_frequency(st->fclk)) + return dev_err_probe(dev, -EINVAL, + "External clock frequency out of bounds\n"); } - ret = ad7192_setup(indio_dev, &spi->dev); + ret = ad7192_setup(indio_dev, dev); if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct of_device_id ad7192_of_match[] = { { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] }, { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] }, { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] }, + { .compatible = "adi,ad7194", .data = &ad7192_chip_info_tbl[ID_AD7194] }, { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] }, {} }; @@ -1172,6 +1312,7 @@ static const struct spi_device_id ad7192_ids[] = { { "ad7190", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7190] }, { "ad7192", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7192] }, { "ad7193", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7193] }, + { "ad7194", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7194] }, { "ad7195", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7195] }, {} }; @@ -1188,6 +1329,6 @@ static struct spi_driver ad7192_driver = { module_spi_driver(ad7192_driver); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7193, AD7195 ADC"); +MODULE_DESCRIPTION("Analog Devices AD7192 and similar ADC"); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 13ea8a1073d2..bdac020045b4 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -23,9 +23,10 @@ #include +#define AD7266_INTERNAL_REF_MV 2500 + struct ad7266_state { struct spi_device *spi; - struct regulator *reg; unsigned long vref_mv; struct spi_transfer single_xfer[3]; @@ -379,11 +380,6 @@ static const char * const ad7266_gpio_labels[] = { "ad0", "ad1", "ad2", }; -static void ad7266_reg_disable(void *reg) -{ - regulator_disable(reg); -} - static int ad7266_probe(struct spi_device *spi) { struct ad7266_platform_data *pdata = spi->dev.platform_data; @@ -398,28 +394,11 @@ static int ad7266_probe(struct spi_device *spi) st = iio_priv(indio_dev); - st->reg = devm_regulator_get_optional(&spi->dev, "vref"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); + if (ret < 0 && ret != -ENODEV) + return ret; - ret = devm_add_action_or_reset(&spi->dev, ad7266_reg_disable, st->reg); - if (ret) - return ret; - - ret = regulator_get_voltage(st->reg); - if (ret < 0) - return ret; - - st->vref_mv = ret / 1000; - } else { - /* Any other error indicates that the regulator does exist */ - if (PTR_ERR(st->reg) != -ENODEV) - return PTR_ERR(st->reg); - /* Use internal reference */ - st->vref_mv = 2500; - } + st->vref_mv = ret == -ENODEV ? AD7266_INTERNAL_REF_MV : ret / 1000; if (pdata) { st->fixed_addr = pdata->fixed_addr; diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c index 14d02b085d3b..b59b2a51623c 100644 --- a/drivers/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -536,7 +536,7 @@ static int ad7291_probe(struct i2c_client *client) } static const struct i2c_device_id ad7291_id[] = { - { "ad7291", 0 }, + { "ad7291" }, {} }; diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c index 6aadd14f459d..ede80f380911 100644 --- a/drivers/iio/adc/ad7292.c +++ b/drivers/iio/adc/ad7292.c @@ -17,6 +17,8 @@ #define ADI_VENDOR_ID 0x0018 +#define AD7292_INTERNAL_REF_MV 1250 + /* AD7292 registers definition */ #define AD7292_REG_VENDOR_ID 0x00 #define AD7292_REG_CONF_BANK 0x05 @@ -79,7 +81,6 @@ static const struct iio_chan_spec ad7292_channels_diff[] = { struct ad7292_state { struct spi_device *spi; - struct regulator *reg; unsigned short vref_mv; __be16 d16 __aligned(IIO_DMA_MINALIGN); @@ -250,13 +251,6 @@ static const struct iio_info ad7292_info = { .read_raw = ad7292_read_raw, }; -static void ad7292_regulator_disable(void *data) -{ - struct ad7292_state *st = data; - - regulator_disable(st->reg); -} - static int ad7292_probe(struct spi_device *spi) { struct ad7292_state *st; @@ -277,29 +271,11 @@ static int ad7292_probe(struct spi_device *spi) return -EINVAL; } - st->reg = devm_regulator_get_optional(&spi->dev, "vref"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) { - dev_err(&spi->dev, - "Failed to enable external vref supply\n"); - return ret; - } + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); + if (ret < 0 && ret != -ENODEV) + return ret; - ret = devm_add_action_or_reset(&spi->dev, - ad7292_regulator_disable, st); - if (ret) - return ret; - - ret = regulator_get_voltage(st->reg); - if (ret < 0) - return ret; - - st->vref_mv = ret / 1000; - } else { - /* Use the internal voltage reference. */ - st->vref_mv = 1250; - } + st->vref_mv = ret == -ENODEV ? AD7292_INTERNAL_REF_MV : ret / 1000; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c new file mode 100644 index 000000000000..7568cd0a2b32 --- /dev/null +++ b/drivers/iio/adc/ad7380.c @@ -0,0 +1,833 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Analog Devices AD738x Simultaneous Sampling SAR ADCs + * + * Copyright 2017 Analog Devices Inc. + * Copyright 2024 BayLibre, SAS + * + * Datasheets of supported parts: + * ad7380/1 : https://www.analog.com/media/en/technical-documentation/data-sheets/AD7380-7381.pdf + * ad7383/4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-7384.pdf + * ad7380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7380-4.pdf + * ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf + * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MAX_NUM_CHANNELS 4 +/* 2.5V internal reference voltage */ +#define AD7380_INTERNAL_REF_MV 2500 + +/* reading and writing registers is more reliable at lower than max speed */ +#define AD7380_REG_WR_SPEED_HZ 10000000 + +#define AD7380_REG_WR BIT(15) +#define AD7380_REG_REGADDR GENMASK(14, 12) +#define AD7380_REG_DATA GENMASK(11, 0) + +#define AD7380_REG_ADDR_NOP 0x0 +#define AD7380_REG_ADDR_CONFIG1 0x1 +#define AD7380_REG_ADDR_CONFIG2 0x2 +#define AD7380_REG_ADDR_ALERT 0x3 +#define AD7380_REG_ADDR_ALERT_LOW_TH 0x4 +#define AD7380_REG_ADDR_ALERT_HIGH_TH 0x5 + +#define AD7380_CONFIG1_OS_MODE BIT(9) +#define AD7380_CONFIG1_OSR GENMASK(8, 6) +#define AD7380_CONFIG1_CRC_W BIT(5) +#define AD7380_CONFIG1_CRC_R BIT(4) +#define AD7380_CONFIG1_ALERTEN BIT(3) +#define AD7380_CONFIG1_RES BIT(2) +#define AD7380_CONFIG1_REFSEL BIT(1) +#define AD7380_CONFIG1_PMODE BIT(0) + +#define AD7380_CONFIG2_SDO2 GENMASK(9, 8) +#define AD7380_CONFIG2_SDO BIT(8) +#define AD7380_CONFIG2_RESET GENMASK(7, 0) + +#define AD7380_CONFIG2_RESET_SOFT 0x3C +#define AD7380_CONFIG2_RESET_HARD 0xFF + +#define AD7380_ALERT_LOW_TH GENMASK(11, 0) +#define AD7380_ALERT_HIGH_TH GENMASK(11, 0) + +#define T_CONVERT_NS 190 /* conversion time */ +#define T_CONVERT_0_NS 10 /* 1st conversion start time (oversampling) */ +#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */ + +struct ad7380_timing_specs { + const unsigned int t_csh_ns; /* CS minimum high time */ +}; + +struct ad7380_chip_info { + const char *name; + const struct iio_chan_spec *channels; + unsigned int num_channels; + const char * const *vcm_supplies; + unsigned int num_vcm_supplies; + const unsigned long *available_scan_masks; + const struct ad7380_timing_specs *timing_specs; +}; + +enum { + AD7380_SCAN_TYPE_NORMAL, + AD7380_SCAN_TYPE_RESOLUTION_BOOST, +}; + +/* Extended scan types for 14-bit chips. */ +static const struct iio_scan_type ad7380_scan_type_14[] = { + [AD7380_SCAN_TYPE_NORMAL] = { + .sign = 's', + .realbits = 14, + .storagebits = 16, + .endianness = IIO_CPU + }, + [AD7380_SCAN_TYPE_RESOLUTION_BOOST] = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU + }, +}; + +/* Extended scan types for 16-bit chips. */ +static const struct iio_scan_type ad7380_scan_type_16[] = { + [AD7380_SCAN_TYPE_NORMAL] = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU + }, + [AD7380_SCAN_TYPE_RESOLUTION_BOOST] = { + .sign = 's', + .realbits = 18, + .storagebits = 32, + .endianness = IIO_CPU + }, +}; + +#define AD7380_CHANNEL(index, bits, diff) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .indexed = 1, \ + .differential = (diff), \ + .channel = (diff) ? (2 * (index)) : (index), \ + .channel2 = (diff) ? (2 * (index) + 1) : 0, \ + .scan_index = (index), \ + .has_ext_scan_type = 1, \ + .ext_scan_type = ad7380_scan_type_##bits, \ + .num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits),\ +} + +#define DEFINE_AD7380_2_CHANNEL(name, bits, diff) \ +static const struct iio_chan_spec name[] = { \ + AD7380_CHANNEL(0, bits, diff), \ + AD7380_CHANNEL(1, bits, diff), \ + IIO_CHAN_SOFT_TIMESTAMP(2), \ +} + +#define DEFINE_AD7380_4_CHANNEL(name, bits, diff) \ +static const struct iio_chan_spec name[] = { \ + AD7380_CHANNEL(0, bits, diff), \ + AD7380_CHANNEL(1, bits, diff), \ + AD7380_CHANNEL(2, bits, diff), \ + AD7380_CHANNEL(3, bits, diff), \ + IIO_CHAN_SOFT_TIMESTAMP(4), \ +} + +/* fully differential */ +DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1); +DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1); +DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1); +DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1); +/* pseudo differential */ +DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0); +DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0); +DEFINE_AD7380_4_CHANNEL(ad7383_4_channels, 16, 0); +DEFINE_AD7380_4_CHANNEL(ad7384_4_channels, 14, 0); + +static const char * const ad7380_2_channel_vcm_supplies[] = { + "aina", "ainb", +}; + +static const char * const ad7380_4_channel_vcm_supplies[] = { + "aina", "ainb", "ainc", "aind", +}; + +/* Since this is simultaneous sampling, we don't allow individual channels. */ +static const unsigned long ad7380_2_channel_scan_masks[] = { + GENMASK(1, 0), + 0 +}; + +static const unsigned long ad7380_4_channel_scan_masks[] = { + GENMASK(3, 0), + 0 +}; + +static const struct ad7380_timing_specs ad7380_timing = { + .t_csh_ns = 10, +}; + +static const struct ad7380_timing_specs ad7380_4_timing = { + .t_csh_ns = 20, +}; + +/* + * Available oversampling ratios. The indices correspond with the bit value + * expected by the chip. The available ratios depend on the averaging mode, + * only normal averaging is supported for now. + */ +static const int ad7380_oversampling_ratios[] = { + 1, 2, 4, 8, 16, 32, +}; + +static const struct ad7380_chip_info ad7380_chip_info = { + .name = "ad7380", + .channels = ad7380_channels, + .num_channels = ARRAY_SIZE(ad7380_channels), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, +}; + +static const struct ad7380_chip_info ad7381_chip_info = { + .name = "ad7381", + .channels = ad7381_channels, + .num_channels = ARRAY_SIZE(ad7381_channels), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, +}; + +static const struct ad7380_chip_info ad7383_chip_info = { + .name = "ad7383", + .channels = ad7383_channels, + .num_channels = ARRAY_SIZE(ad7383_channels), + .vcm_supplies = ad7380_2_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, +}; + +static const struct ad7380_chip_info ad7384_chip_info = { + .name = "ad7384", + .channels = ad7384_channels, + .num_channels = ARRAY_SIZE(ad7384_channels), + .vcm_supplies = ad7380_2_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, +}; + +static const struct ad7380_chip_info ad7380_4_chip_info = { + .name = "ad7380-4", + .channels = ad7380_4_channels, + .num_channels = ARRAY_SIZE(ad7380_4_channels), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +static const struct ad7380_chip_info ad7381_4_chip_info = { + .name = "ad7381-4", + .channels = ad7381_4_channels, + .num_channels = ARRAY_SIZE(ad7381_4_channels), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +static const struct ad7380_chip_info ad7383_4_chip_info = { + .name = "ad7383-4", + .channels = ad7383_4_channels, + .num_channels = ARRAY_SIZE(ad7383_4_channels), + .vcm_supplies = ad7380_4_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +static const struct ad7380_chip_info ad7384_4_chip_info = { + .name = "ad7384-4", + .channels = ad7384_4_channels, + .num_channels = ARRAY_SIZE(ad7384_4_channels), + .vcm_supplies = ad7380_4_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +struct ad7380_state { + const struct ad7380_chip_info *chip_info; + struct spi_device *spi; + struct regmap *regmap; + unsigned int oversampling_ratio; + bool resolution_boost_enabled; + unsigned int vref_mv; + unsigned int vcm_mv[MAX_NUM_CHANNELS]; + /* xfers, message an buffer for reading sample data */ + struct spi_transfer xfer[2]; + struct spi_message msg; + /* + * DMA (thus cache coherency maintenance) requires the transfer buffers + * to live in their own cache lines. + * + * Make the buffer large enough for MAX_NUM_CHANNELS 32-bit samples and + * one 64-bit aligned 64-bit timestamp. + */ + u8 scan_data[ALIGN(MAX_NUM_CHANNELS * sizeof(u32), sizeof(s64)) + + sizeof(s64)] __aligned(IIO_DMA_MINALIGN); + /* buffers for reading/writing registers */ + u16 tx; + u16 rx; +}; + +static int ad7380_regmap_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct ad7380_state *st = context; + struct spi_transfer xfer = { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = 16, + .len = 2, + .tx_buf = &st->tx, + }; + + st->tx = FIELD_PREP(AD7380_REG_WR, 1) | + FIELD_PREP(AD7380_REG_REGADDR, reg) | + FIELD_PREP(AD7380_REG_DATA, val); + + return spi_sync_transfer(st->spi, &xfer, 1); +} + +static int ad7380_regmap_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct ad7380_state *st = context; + struct spi_transfer xfers[] = { + { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = 16, + .len = 2, + .tx_buf = &st->tx, + .cs_change = 1, + .cs_change_delay = { + .value = st->chip_info->timing_specs->t_csh_ns, + .unit = SPI_DELAY_UNIT_NSECS, + }, + }, { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = 16, + .len = 2, + .rx_buf = &st->rx, + }, + }; + int ret; + + st->tx = FIELD_PREP(AD7380_REG_WR, 0) | + FIELD_PREP(AD7380_REG_REGADDR, reg) | + FIELD_PREP(AD7380_REG_DATA, 0); + + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + if (ret < 0) + return ret; + + *val = FIELD_GET(AD7380_REG_DATA, st->rx); + + return 0; +} + +static const struct regmap_config ad7380_regmap_config = { + .reg_bits = 3, + .val_bits = 12, + .reg_read = ad7380_regmap_reg_read, + .reg_write = ad7380_regmap_reg_write, + .max_register = AD7380_REG_ADDR_ALERT_HIGH_TH, + .can_sleep = true, +}; + +static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg, + u32 writeval, u32 *readval) +{ + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + struct ad7380_state *st = iio_priv(indio_dev); + + if (readval) + return regmap_read(st->regmap, reg, readval); + else + return regmap_write(st->regmap, reg, writeval); + } + unreachable(); +} + +/** + * ad7380_update_xfers - update the SPI transfers base on the current scan type + * @st: device instance specific state + * @scan_type: current scan type + */ +static void ad7380_update_xfers(struct ad7380_state *st, + const struct iio_scan_type *scan_type) +{ + /* + * First xfer only triggers conversion and has to be long enough for + * all conversions to complete, which can be multiple conversion in the + * case of oversampling. Technically T_CONVERT_X_NS is lower for some + * chips, but we use the maximum value for simplicity for now. + */ + if (st->oversampling_ratio > 1) + st->xfer[0].delay.value = T_CONVERT_0_NS + T_CONVERT_X_NS * + (st->oversampling_ratio - 1); + else + st->xfer[0].delay.value = T_CONVERT_NS; + + st->xfer[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + /* + * Second xfer reads all channels. Data size depends on if resolution + * boost is enabled or not. + */ + st->xfer[1].bits_per_word = scan_type->realbits; + st->xfer[1].len = BITS_TO_BYTES(scan_type->storagebits) * + (st->chip_info->num_channels - 1); +} + +static int ad7380_triggered_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ad7380_state *st = iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + + /* + * Currently, we always read all channels at the same time. The scan_type + * is the same for all channels, so we just pass the first channel. + */ + scan_type = iio_get_current_scan_type(indio_dev, &indio_dev->channels[0]); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + ad7380_update_xfers(st, scan_type); + + return spi_optimize_message(st->spi, &st->msg); +} + +static int ad7380_triggered_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ad7380_state *st = iio_priv(indio_dev); + + spi_unoptimize_message(&st->msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ad7380_buffer_setup_ops = { + .preenable = ad7380_triggered_buffer_preenable, + .postdisable = ad7380_triggered_buffer_postdisable, +}; + +static irqreturn_t ad7380_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7380_state *st = iio_priv(indio_dev); + int ret; + + ret = spi_sync(st->spi, &st->msg); + if (ret) + goto out; + + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_data, + pf->timestamp); + +out: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ad7380_read_direct(struct ad7380_state *st, unsigned int scan_index, + const struct iio_scan_type *scan_type, int *val) +{ + int ret; + + ad7380_update_xfers(st, scan_type); + + ret = spi_sync(st->spi, &st->msg); + if (ret < 0) + return ret; + + if (scan_type->storagebits > 16) + *val = sign_extend32(*(u32 *)(st->scan_data + 4 * scan_index), + scan_type->realbits - 1); + else + *val = sign_extend32(*(u16 *)(st->scan_data + 2 * scan_index), + scan_type->realbits - 1); + + return IIO_VAL_INT; +} + +static int ad7380_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + struct ad7380_state *st = iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + + scan_type = iio_get_current_scan_type(indio_dev, chan); + + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + switch (info) { + case IIO_CHAN_INFO_RAW: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + return ad7380_read_direct(st, chan->scan_index, + scan_type, val); + } + unreachable(); + case IIO_CHAN_INFO_SCALE: + /* + * According to the datasheet, the LSB size is: + * * (2 × VREF) / 2^N, for differential chips + * * VREF / 2^N, for pseudo-differential chips + * where N is the ADC resolution (i.e realbits) + */ + *val = st->vref_mv; + *val2 = scan_type->realbits - chan->differential; + + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + /* + * According to IIO ABI, offset is applied before scale, + * so offset is: vcm_mv / scale + */ + *val = st->vcm_mv[chan->channel] * (1 << scan_type->realbits) + / st->vref_mv; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = st->oversampling_ratio; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad7380_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *vals = ad7380_oversampling_ratios; + *length = ARRAY_SIZE(ad7380_oversampling_ratios); + *type = IIO_VAL_INT; + + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +/** + * ad7380_osr_to_regval - convert ratio to OSR register value + * @ratio: ratio to check + * + * Check if ratio is present in the list of available ratios and return the + * corresponding value that needs to be written to the register to select that + * ratio. + * + * Returns: register value (0 to 7) or -EINVAL if there is not an exact match + */ +static int ad7380_osr_to_regval(int ratio) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ad7380_oversampling_ratios); i++) { + if (ratio == ad7380_oversampling_ratios[i]) + return i; + } + + return -EINVAL; +} + +static int ad7380_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct ad7380_state *st = iio_priv(indio_dev); + int ret, osr, boost; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + osr = ad7380_osr_to_regval(val); + if (osr < 0) + return osr; + + /* always enable resolution boost when oversampling is enabled */ + boost = osr > 0 ? 1 : 0; + + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = regmap_update_bits(st->regmap, + AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_OSR | AD7380_CONFIG1_RES, + FIELD_PREP(AD7380_CONFIG1_OSR, osr) | + FIELD_PREP(AD7380_CONFIG1_RES, boost)); + + if (ret) + return ret; + + st->oversampling_ratio = val; + st->resolution_boost_enabled = boost; + + /* + * Perform a soft reset. This will flush the oversampling + * block and FIFO but will maintain the content of the + * configurable registers. + */ + return regmap_update_bits(st->regmap, + AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_RESET, + FIELD_PREP(AD7380_CONFIG2_RESET, + AD7380_CONFIG2_RESET_SOFT)); + } + unreachable(); + default: + return -EINVAL; + } +} + +static int ad7380_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad7380_state *st = iio_priv(indio_dev); + + return st->resolution_boost_enabled ? AD7380_SCAN_TYPE_RESOLUTION_BOOST + : AD7380_SCAN_TYPE_NORMAL; +} + +static const struct iio_info ad7380_info = { + .read_raw = &ad7380_read_raw, + .read_avail = &ad7380_read_avail, + .write_raw = &ad7380_write_raw, + .get_current_scan_type = &ad7380_get_current_scan_type, + .debugfs_reg_access = &ad7380_debugfs_reg_access, +}; + +static int ad7380_init(struct ad7380_state *st, struct regulator *vref) +{ + int ret; + + /* perform hard reset */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_RESET, + FIELD_PREP(AD7380_CONFIG2_RESET, + AD7380_CONFIG2_RESET_HARD)); + if (ret < 0) + return ret; + + /* select internal or external reference voltage */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_REFSEL, + FIELD_PREP(AD7380_CONFIG1_REFSEL, + vref ? 1 : 0)); + if (ret < 0) + return ret; + + /* This is the default value after reset. */ + st->oversampling_ratio = 1; + + /* SPI 1-wire mode */ + return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_SDO, + FIELD_PREP(AD7380_CONFIG2_SDO, 1)); +} + +static void ad7380_regulator_disable(void *p) +{ + regulator_disable(p); +} + +static int ad7380_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ad7380_state *st; + struct regulator *vref; + int ret, i; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + st->chip_info = spi_get_device_match_data(spi); + if (!st->chip_info) + return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n"); + + vref = devm_regulator_get_optional(&spi->dev, "refio"); + if (IS_ERR(vref)) { + if (PTR_ERR(vref) != -ENODEV) + return dev_err_probe(&spi->dev, PTR_ERR(vref), + "Failed to get refio regulator\n"); + + vref = NULL; + } + + /* + * If there is no REFIO supply, then it means that we are using + * the internal 2.5V reference, otherwise REFIO is reference voltage. + */ + if (vref) { + ret = regulator_enable(vref); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&spi->dev, + ad7380_regulator_disable, vref); + if (ret) + return ret; + + ret = regulator_get_voltage(vref); + if (ret < 0) + return ret; + + st->vref_mv = ret / 1000; + } else { + st->vref_mv = AD7380_INTERNAL_REF_MV; + } + + if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv)) + return dev_err_probe(&spi->dev, -EINVAL, + "invalid number of VCM supplies\n"); + + /* + * pseudo-differential chips have common mode supplies for the negative + * input pin. + */ + for (i = 0; i < st->chip_info->num_vcm_supplies; i++) { + struct regulator *vcm; + + vcm = devm_regulator_get(&spi->dev, + st->chip_info->vcm_supplies[i]); + if (IS_ERR(vcm)) + return dev_err_probe(&spi->dev, PTR_ERR(vcm), + "Failed to get %s regulator\n", + st->chip_info->vcm_supplies[i]); + + ret = regulator_enable(vcm); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&spi->dev, + ad7380_regulator_disable, vcm); + if (ret) + return ret; + + ret = regulator_get_voltage(vcm); + if (ret < 0) + return ret; + + st->vcm_mv[i] = ret / 1000; + } + + st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), + "failed to allocate register map\n"); + + /* + * Setting up a low latency read for getting sample data. Used for both + * direct read an triggered buffer. Additional fields will be set up in + * ad7380_update_xfers() based on the current state of the driver at the + * time of the read. + */ + + /* toggle CS (no data xfer) to trigger a conversion */ + st->xfer[0].cs_change = 1; + st->xfer[0].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns; + st->xfer[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; + + /* then do a second xfer to read the data */ + st->xfer[1].rx_buf = st->scan_data; + + spi_message_init_with_transfers(&st->msg, st->xfer, ARRAY_SIZE(st->xfer)); + + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->name = st->chip_info->name; + indio_dev->info = &ad7380_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = st->chip_info->available_scan_masks; + + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + iio_pollfunc_store_time, + ad7380_trigger_handler, + &ad7380_buffer_setup_ops); + if (ret) + return ret; + + ret = ad7380_init(st, vref); + if (ret) + return ret; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id ad7380_of_match_table[] = { + { .compatible = "adi,ad7380", .data = &ad7380_chip_info }, + { .compatible = "adi,ad7381", .data = &ad7381_chip_info }, + { .compatible = "adi,ad7383", .data = &ad7383_chip_info }, + { .compatible = "adi,ad7384", .data = &ad7384_chip_info }, + { .compatible = "adi,ad7380-4", .data = &ad7380_4_chip_info }, + { .compatible = "adi,ad7381-4", .data = &ad7381_4_chip_info }, + { .compatible = "adi,ad7383-4", .data = &ad7383_4_chip_info }, + { .compatible = "adi,ad7384-4", .data = &ad7384_4_chip_info }, + { } +}; + +static const struct spi_device_id ad7380_id_table[] = { + { "ad7380", (kernel_ulong_t)&ad7380_chip_info }, + { "ad7381", (kernel_ulong_t)&ad7381_chip_info }, + { "ad7383", (kernel_ulong_t)&ad7383_chip_info }, + { "ad7384", (kernel_ulong_t)&ad7384_chip_info }, + { "ad7380-4", (kernel_ulong_t)&ad7380_4_chip_info }, + { "ad7381-4", (kernel_ulong_t)&ad7381_4_chip_info }, + { "ad7383-4", (kernel_ulong_t)&ad7383_4_chip_info }, + { "ad7384-4", (kernel_ulong_t)&ad7384_4_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad7380_id_table); + +static struct spi_driver ad7380_driver = { + .driver = { + .name = "ad7380", + .of_match_table = ad7380_of_match_table, + }, + .probe = ad7380_probe, + .id_table = ad7380_id_table, +}; +module_spi_driver(ad7380_driver); + +MODULE_AUTHOR("Stefan Popa "); +MODULE_DESCRIPTION("Analog Devices AD738x ADC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 1928d9ae5bcf..3a417595294f 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -174,17 +174,14 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - ret = ad7606_scan_direct(indio_dev, chan->address); - iio_device_release_direct_mode(indio_dev); - - if (ret < 0) - return ret; - *val = (short)ret; - return IIO_VAL_INT; + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = ad7606_scan_direct(indio_dev, chan->address); + if (ret < 0) + return ret; + *val = (short) ret; + return IIO_VAL_INT; + } + unreachable(); case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) ch = chan->address; diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 5f8cb9aaac70..d4ad7e0b515a 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -152,7 +152,6 @@ struct ad7793_chip_info { struct ad7793_state { const struct ad7793_chip_info *chip_info; - struct regulator *reg; u16 int_vref_mv; u16 mode; u16 conf; @@ -769,11 +768,6 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { }, }; -static void ad7793_reg_disable(void *reg) -{ - regulator_disable(reg); -} - static int ad7793_probe(struct spi_device *spi) { const struct ad7793_platform_data *pdata = spi->dev.platform_data; @@ -800,23 +794,11 @@ static int ad7793_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info); if (pdata->refsel != AD7793_REFSEL_INTERNAL) { - st->reg = devm_regulator_get(&spi->dev, "refin"); - if (IS_ERR(st->reg)) - return PTR_ERR(st->reg); - - ret = regulator_enable(st->reg); - if (ret) + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "refin"); + if (ret < 0) return ret; - ret = devm_add_action_or_reset(&spi->dev, ad7793_reg_disable, st->reg); - if (ret) - return ret; - - vref_mv = regulator_get_voltage(st->reg); - if (vref_mv < 0) - return vref_mv; - - vref_mv /= 1000; + vref_mv = ret / 1000; } else { vref_mv = 1170; /* Build-in ref */ } diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index 4602ab5ed2a6..0f36138a7144 100644 --- a/drivers/iio/adc/ad7944.c +++ b/drivers/iio/adc/ad7944.c @@ -134,18 +134,12 @@ AD7944_DEFINE_CHIP_INFO(ad7985, ad7944, 16, 0); /* fully differential */ AD7944_DEFINE_CHIP_INFO(ad7986, ad7986, 18, 1); -static void ad7944_unoptimize_msg(void *msg) -{ - spi_unoptimize_message(msg); -} - static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *adc, const struct iio_chan_spec *chan) { unsigned int t_conv_ns = adc->always_turbo ? adc->timing_spec->turbo_conv_ns : adc->timing_spec->conv_ns; struct spi_transfer *xfers = adc->xfers; - int ret; /* * NB: can get better performance from some SPI controllers if we use @@ -175,11 +169,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * spi_message_init_with_transfers(&adc->msg, xfers, 3); - ret = spi_optimize_message(adc->spi, &adc->msg); - if (ret) - return ret; - - return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg); + return devm_spi_optimize_message(dev, adc->spi, &adc->msg); } static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc, @@ -188,7 +178,6 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc unsigned int t_conv_ns = adc->always_turbo ? adc->timing_spec->turbo_conv_ns : adc->timing_spec->conv_ns; struct spi_transfer *xfers = adc->xfers; - int ret; /* * NB: can get better performance from some SPI controllers if we use @@ -209,11 +198,7 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc spi_message_init_with_transfers(&adc->msg, xfers, 2); - ret = spi_optimize_message(adc->spi, &adc->msg); - if (ret) - return ret; - - return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg); + return devm_spi_optimize_message(dev, adc->spi, &adc->msg); } static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc, @@ -221,7 +206,6 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc u32 n_chain_dev) { struct spi_transfer *xfers = adc->xfers; - int ret; /* * NB: SCLK has to be low before we toggle CS to avoid triggering the @@ -249,17 +233,12 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc spi_message_init_with_transfers(&adc->msg, xfers, 2); - ret = spi_optimize_message(adc->spi, &adc->msg); - if (ret) - return ret; - - return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg); + return devm_spi_optimize_message(dev, adc->spi, &adc->msg); } /** * ad7944_convert_and_acquire - Perform a single conversion and acquisition * @adc: The ADC device structure - * @chan: The channel specification * Return: 0 on success, a negative error code on failure * * Perform a conversion and acquisition of a single sample using the @@ -268,8 +247,7 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc * Upon successful return adc->sample.raw will contain the conversion result * (or adc->chain_mode_buf if the device is using chain mode). */ -static int ad7944_convert_and_acquire(struct ad7944_adc *adc, - const struct iio_chan_spec *chan) +static int ad7944_convert_and_acquire(struct ad7944_adc *adc) { int ret; @@ -291,7 +269,7 @@ static int ad7944_single_conversion(struct ad7944_adc *adc, { int ret; - ret = ad7944_convert_and_acquire(adc, chan); + ret = ad7944_convert_and_acquire(adc); if (ret) return ret; @@ -361,7 +339,7 @@ static irqreturn_t ad7944_trigger_handler(int irq, void *p) struct ad7944_adc *adc = iio_priv(indio_dev); int ret; - ret = ad7944_convert_and_acquire(adc, &indio_dev->channels[0]); + ret = ad7944_convert_and_acquire(adc); if (ret) goto out; @@ -466,23 +444,17 @@ static const char * const ad7944_power_supplies[] = { "avdd", "dvdd", "bvdd", "vio" }; -static void ad7944_ref_disable(void *ref) -{ - regulator_disable(ref); -} - static int ad7944_probe(struct spi_device *spi) { const struct ad7944_chip_info *chip_info; struct device *dev = &spi->dev; struct iio_dev *indio_dev; struct ad7944_adc *adc; - bool have_refin = false; - struct regulator *ref; + bool have_refin; struct iio_chan_spec *chain_chan; unsigned long *chain_scan_masks; u32 n_chain_dev; - int ret; + int ret, ref_mv; indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); if (!indio_dev) @@ -533,47 +505,23 @@ static int ad7944_probe(struct spi_device *spi) * - external reference: REF is connected, REFIN is not connected */ - ref = devm_regulator_get_optional(dev, "ref"); - if (IS_ERR(ref)) { - if (PTR_ERR(ref) != -ENODEV) - return dev_err_probe(dev, PTR_ERR(ref), - "failed to get REF supply\n"); + ret = devm_regulator_get_enable_read_voltage(dev, "ref"); + if (ret < 0 && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get REF voltage\n"); - ref = NULL; - } + ref_mv = ret == -ENODEV ? 0 : ret / 1000; ret = devm_regulator_get_enable_optional(dev, "refin"); - if (ret == 0) - have_refin = true; - else if (ret != -ENODEV) - return dev_err_probe(dev, ret, - "failed to get and enable REFIN supply\n"); + if (ret < 0 && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get REFIN voltage\n"); - if (have_refin && ref) + have_refin = ret != -ENODEV; + + if (have_refin && ref_mv) return dev_err_probe(dev, -EINVAL, "cannot have both refin and ref supplies\n"); - if (ref) { - ret = regulator_enable(ref); - if (ret) - return dev_err_probe(dev, ret, - "failed to enable REF supply\n"); - - ret = devm_add_action_or_reset(dev, ad7944_ref_disable, ref); - if (ret) - return ret; - - ret = regulator_get_voltage(ref); - if (ret < 0) - return dev_err_probe(dev, ret, - "failed to get REF voltage\n"); - - /* external reference */ - adc->ref_mv = ret / 1000; - } else { - /* internal reference */ - adc->ref_mv = AD7944_INTERNAL_REF_MV; - } + adc->ref_mv = ref_mv ?: AD7944_INTERNAL_REF_MV; adc->cnv = devm_gpiod_get_optional(dev, "cnv", GPIOD_OUT_LOW); if (IS_ERR(adc->cnv)) diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 8f5b9c3f6e3d..41c1b519c573 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -107,27 +107,27 @@ #define AD9647_MAX_TEST_POINTS 32 struct ad9467_chip_info { - const char *name; - unsigned int id; - const struct iio_chan_spec *channels; - unsigned int num_channels; - const unsigned int (*scale_table)[2]; - int num_scales; - unsigned long max_rate; - unsigned int default_output_mode; - unsigned int vref_mask; - unsigned int num_lanes; + const char *name; + unsigned int id; + const struct iio_chan_spec *channels; + unsigned int num_channels; + const unsigned int (*scale_table)[2]; + int num_scales; + unsigned long max_rate; + unsigned int default_output_mode; + unsigned int vref_mask; + unsigned int num_lanes; /* data clock output */ - bool has_dco; + bool has_dco; }; struct ad9467_state { - const struct ad9467_chip_info *info; - struct iio_backend *back; - struct spi_device *spi; - struct clk *clk; - unsigned int output_mode; - unsigned int (*scales)[2]; + const struct ad9467_chip_info *info; + struct iio_backend *back; + struct spi_device *spi; + struct clk *clk; + unsigned int output_mode; + unsigned int (*scales)[2]; /* * Times 2 because we may also invert the signal polarity and run the * calibration again. For some reference on the test points (ad9265) see: @@ -138,12 +138,13 @@ struct ad9467_state { * at the io delay control section. */ DECLARE_BITMAP(calib_map, AD9647_MAX_TEST_POINTS * 2); - struct gpio_desc *pwrdown_gpio; + struct gpio_desc *pwrdown_gpio; /* ensure consistent state obtained on multiple related accesses */ - struct mutex lock; + struct mutex lock; + u8 buf[3] __aligned(IIO_DMA_MINALIGN); }; -static int ad9467_spi_read(struct spi_device *spi, unsigned int reg) +static int ad9467_spi_read(struct ad9467_state *st, unsigned int reg) { unsigned char tbuf[2], rbuf[1]; int ret; @@ -151,7 +152,7 @@ static int ad9467_spi_read(struct spi_device *spi, unsigned int reg) tbuf[0] = 0x80 | (reg >> 8); tbuf[1] = reg & 0xFF; - ret = spi_write_then_read(spi, + ret = spi_write_then_read(st->spi, tbuf, ARRAY_SIZE(tbuf), rbuf, ARRAY_SIZE(rbuf)); @@ -161,35 +162,32 @@ static int ad9467_spi_read(struct spi_device *spi, unsigned int reg) return rbuf[0]; } -static int ad9467_spi_write(struct spi_device *spi, unsigned int reg, +static int ad9467_spi_write(struct ad9467_state *st, unsigned int reg, unsigned int val) { - unsigned char buf[3]; + st->buf[0] = reg >> 8; + st->buf[1] = reg & 0xFF; + st->buf[2] = val; - buf[0] = reg >> 8; - buf[1] = reg & 0xFF; - buf[2] = val; - - return spi_write(spi, buf, ARRAY_SIZE(buf)); + return spi_write(st->spi, st->buf, ARRAY_SIZE(st->buf)); } static int ad9467_reg_access(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { struct ad9467_state *st = iio_priv(indio_dev); - struct spi_device *spi = st->spi; int ret; if (!readval) { guard(mutex)(&st->lock); - ret = ad9467_spi_write(spi, reg, writeval); + ret = ad9467_spi_write(st, reg, writeval); if (ret) return ret; - return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, + return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER, AN877_ADC_TRANSFER_SYNC); } - ret = ad9467_spi_read(spi, reg); + ret = ad9467_spi_read(st, reg); if (ret < 0) return ret; *readval = ret; @@ -295,7 +293,7 @@ static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2) unsigned int i, vref_val; int ret; - ret = ad9467_spi_read(st->spi, AN877_ADC_REG_VREF); + ret = ad9467_spi_read(st, AN877_ADC_REG_VREF); if (ret < 0) return ret; @@ -330,31 +328,31 @@ static int ad9467_set_scale(struct ad9467_state *st, int val, int val2) continue; guard(mutex)(&st->lock); - ret = ad9467_spi_write(st->spi, AN877_ADC_REG_VREF, + ret = ad9467_spi_write(st, AN877_ADC_REG_VREF, info->scale_table[i][1]); if (ret < 0) return ret; - return ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER, AN877_ADC_TRANSFER_SYNC); } return -EINVAL; } -static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode) +static int ad9467_outputmode_set(struct ad9467_state *st, unsigned int mode) { int ret; - ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode); + ret = ad9467_spi_write(st, AN877_ADC_REG_OUTPUT_MODE, mode); if (ret < 0) return ret; - return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, + return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER, AN877_ADC_TRANSFER_SYNC); } -static int ad9647_calibrate_prepare(const struct ad9467_state *st) +static int ad9647_calibrate_prepare(struct ad9467_state *st) { struct iio_backend_data_fmt data = { .enable = false, @@ -362,17 +360,17 @@ static int ad9647_calibrate_prepare(const struct ad9467_state *st) unsigned int c; int ret; - ret = ad9467_spi_write(st->spi, AN877_ADC_REG_TEST_IO, + ret = ad9467_spi_write(st, AN877_ADC_REG_TEST_IO, AN877_ADC_TESTMODE_PN9_SEQ); if (ret) return ret; - ret = ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + ret = ad9467_spi_write(st, AN877_ADC_REG_TRANSFER, AN877_ADC_TRANSFER_SYNC); if (ret) return ret; - ret = ad9467_outputmode_set(st->spi, st->info->default_output_mode); + ret = ad9467_outputmode_set(st, st->info->default_output_mode); if (ret) return ret; @@ -390,7 +388,7 @@ static int ad9647_calibrate_prepare(const struct ad9467_state *st) return iio_backend_chan_enable(st->back, 0); } -static int ad9647_calibrate_polarity_set(const struct ad9467_state *st, +static int ad9647_calibrate_polarity_set(struct ad9467_state *st, bool invert) { enum iio_backend_sample_trigger trigger; @@ -401,7 +399,7 @@ static int ad9647_calibrate_polarity_set(const struct ad9467_state *st, if (invert) phase |= AN877_ADC_INVERT_DCO_CLK; - return ad9467_spi_write(st->spi, AN877_ADC_REG_OUTPUT_PHASE, + return ad9467_spi_write(st, AN877_ADC_REG_OUTPUT_PHASE, phase); } @@ -437,19 +435,18 @@ static unsigned int ad9467_find_optimal_point(const unsigned long *calib_map, return cnt; } -static int ad9467_calibrate_apply(const struct ad9467_state *st, - unsigned int val) +static int ad9467_calibrate_apply(struct ad9467_state *st, unsigned int val) { unsigned int lane; int ret; if (st->info->has_dco) { - ret = ad9467_spi_write(st->spi, AN877_ADC_REG_OUTPUT_DELAY, + ret = ad9467_spi_write(st, AN877_ADC_REG_OUTPUT_DELAY, val); if (ret) return ret; - return ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER, AN877_ADC_TRANSFER_SYNC); } @@ -462,7 +459,7 @@ static int ad9467_calibrate_apply(const struct ad9467_state *st, return 0; } -static int ad9647_calibrate_stop(const struct ad9467_state *st) +static int ad9647_calibrate_stop(struct ad9467_state *st) { struct iio_backend_data_fmt data = { .sign_extend = true, @@ -487,16 +484,16 @@ static int ad9647_calibrate_stop(const struct ad9467_state *st) } mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; - ret = ad9467_outputmode_set(st->spi, mode); + ret = ad9467_outputmode_set(st, mode); if (ret) return ret; - ret = ad9467_spi_write(st->spi, AN877_ADC_REG_TEST_IO, + ret = ad9467_spi_write(st, AN877_ADC_REG_TEST_IO, AN877_ADC_TESTMODE_OFF); if (ret) return ret; - return ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER, AN877_ADC_TRANSFER_SYNC); } @@ -846,7 +843,7 @@ static int ad9467_probe(struct spi_device *spi) if (ret) return ret; - id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); + id = ad9467_spi_read(st, AN877_ADC_REG_CHIP_ID); if (id != st->info->id) { dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", id, st->info->id); diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index a2b87f6b7a07..8c062b0d26e3 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -321,6 +321,7 @@ out: sigma_delta->keep_cs_asserted = false; ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); + ad_sigma_delta_disable_one(sigma_delta, chan->address); sigma_delta->bus_locked = false; spi_bus_unlock(sigma_delta->spi->controller); iio_device_release_direct_mode(indio_dev); diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 0cf0d81358fd..21ce7564e83d 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -42,6 +42,9 @@ #define ADI_AXI_ADC_REG_CTRL 0x0044 #define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1) +#define ADI_AXI_ADC_REG_DRP_STATUS 0x0074 +#define ADI_AXI_ADC_DRP_LOCKED BIT(17) + /* ADC Channel controls */ #define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40) @@ -83,14 +86,26 @@ struct adi_axi_adc_state { static int axi_adc_enable(struct iio_backend *back) { struct adi_axi_adc_state *st = iio_backend_get_priv(back); + unsigned int __val; int ret; + guard(mutex)(&st->lock); ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_MMCM_RSTN); if (ret) return ret; - fsleep(10000); + /* + * Make sure the DRP (Dynamic Reconfiguration Port) is locked. Not all + * designs really use it but if they don't we still get the lock bit + * set. So let's do it all the time so the code is generic. + */ + ret = regmap_read_poll_timeout(st->regmap, ADI_AXI_ADC_REG_DRP_STATUS, + __val, __val & ADI_AXI_ADC_DRP_LOCKED, + 100, 1000); + if (ret) + return ret; + return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN); } @@ -99,6 +114,7 @@ static void axi_adc_disable(struct iio_backend *back) { struct adi_axi_adc_state *st = iio_backend_get_priv(back); + guard(mutex)(&st->lock); regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0); } @@ -292,7 +308,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev) st->regmap = devm_regmap_init_mmio(&pdev->dev, base, &axi_adc_regmap_config); if (IS_ERR(st->regmap)) - return PTR_ERR(st->regmap); + return dev_err_probe(&pdev->dev, PTR_ERR(st->regmap), + "failed to init register map\n"); expected_ver = device_get_match_data(&pdev->dev); if (!expected_ver) @@ -300,7 +317,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev) clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) - return PTR_ERR(clk); + return dev_err_probe(&pdev->dev, PTR_ERR(clk), + "failed to get clock\n"); /* * Force disable the core. Up to the frontend to enable us. And we can @@ -328,7 +346,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev) ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st); if (ret) - return ret; + return dev_err_probe(&pdev->dev, ret, + "failed to register iio backend\n"); dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n", ADI_AXI_PCORE_VER_MAJOR(ver), diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 998e8bcc06e1..090416c0d622 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -108,7 +108,6 @@ struct adc_gain { struct aspeed_adc_data { struct device *dev; const struct aspeed_adc_model_data *model_data; - struct regulator *regulator; void __iomem *base; spinlock_t clk_lock; struct clk_hw *fixed_div_clk; @@ -404,13 +403,6 @@ static void aspeed_adc_power_down(void *data) priv_data->base + ASPEED_REG_ENGINE_CONTROL); } -static void aspeed_adc_reg_disable(void *data) -{ - struct regulator *reg = data; - - regulator_disable(reg); -} - static int aspeed_adc_vref_config(struct iio_dev *indio_dev) { struct aspeed_adc_data *data = iio_priv(indio_dev); @@ -423,18 +415,14 @@ static int aspeed_adc_vref_config(struct iio_dev *indio_dev) } adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL); - data->regulator = devm_regulator_get_optional(data->dev, "vref"); - if (!IS_ERR(data->regulator)) { - ret = regulator_enable(data->regulator); - if (ret) - return ret; - ret = devm_add_action_or_reset( - data->dev, aspeed_adc_reg_disable, data->regulator); - if (ret) - return ret; - data->vref_mv = regulator_get_voltage(data->regulator); - /* Conversion from uV to mV */ - data->vref_mv /= 1000; + + ret = devm_regulator_get_enable_read_voltage(data->dev, "vref"); + if (ret < 0 && ret != -ENODEV) + return ret; + + if (ret != -ENODEV) { + data->vref_mv = ret / 1000; + if ((data->vref_mv >= 1550) && (data->vref_mv <= 2700)) writel(adc_engine_control_reg_val | FIELD_PREP( @@ -453,8 +441,6 @@ static int aspeed_adc_vref_config(struct iio_dev *indio_dev) return -EOPNOTSUPP; } } else { - if (PTR_ERR(data->regulator) != -ENODEV) - return PTR_ERR(data->regulator); data->vref_mv = 2500000; of_property_read_u32(data->dev->of_node, "aspeed,int-vref-microvolt", diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c index d6c51b0f48e3..b487e577befb 100644 --- a/drivers/iio/adc/axp20x_adc.c +++ b/drivers/iio/adc/axp20x_adc.c @@ -22,11 +22,19 @@ #include #include +#define AXP192_ADC_EN1_MASK GENMASK(7, 0) +#define AXP192_ADC_EN2_MASK (GENMASK(3, 0) | BIT(7)) + #define AXP20X_ADC_EN1_MASK GENMASK(7, 0) #define AXP20X_ADC_EN2_MASK (GENMASK(3, 2) | BIT(7)) #define AXP22X_ADC_EN1_MASK (GENMASK(7, 5) | BIT(0)) +#define AXP192_GPIO30_IN_RANGE_GPIO0 BIT(0) +#define AXP192_GPIO30_IN_RANGE_GPIO1 BIT(1) +#define AXP192_GPIO30_IN_RANGE_GPIO2 BIT(2) +#define AXP192_GPIO30_IN_RANGE_GPIO3 BIT(3) + #define AXP20X_GPIO10_IN_RANGE_GPIO0 BIT(0) #define AXP20X_GPIO10_IN_RANGE_GPIO1 BIT(1) @@ -71,6 +79,25 @@ struct axp20x_adc_iio { const struct axp_data *data; }; +enum axp192_adc_channel_v { + AXP192_ACIN_V = 0, + AXP192_VBUS_V, + AXP192_TS_IN, + AXP192_GPIO0_V, + AXP192_GPIO1_V, + AXP192_GPIO2_V, + AXP192_GPIO3_V, + AXP192_IPSOUT_V, + AXP192_BATT_V, +}; + +enum axp192_adc_channel_i { + AXP192_ACIN_I = 0, + AXP192_VBUS_I, + AXP192_BATT_CHRG_I, + AXP192_BATT_DISCHRG_I, +}; + enum axp20x_adc_channel_v { AXP20X_ACIN_V = 0, AXP20X_VBUS_V, @@ -158,6 +185,43 @@ static struct iio_map axp22x_maps[] = { * The only exception is for the battery. batt_v will be in_voltage6_raw and * charge current in_current6_raw and discharge current will be in_current7_raw. */ +static const struct iio_chan_spec axp192_adc_channels[] = { + AXP20X_ADC_CHANNEL(AXP192_ACIN_V, "acin_v", IIO_VOLTAGE, + AXP20X_ACIN_V_ADC_H), + AXP20X_ADC_CHANNEL(AXP192_ACIN_I, "acin_i", IIO_CURRENT, + AXP20X_ACIN_I_ADC_H), + AXP20X_ADC_CHANNEL(AXP192_VBUS_V, "vbus_v", IIO_VOLTAGE, + AXP20X_VBUS_V_ADC_H), + AXP20X_ADC_CHANNEL(AXP192_VBUS_I, "vbus_i", IIO_CURRENT, + AXP20X_VBUS_I_ADC_H), + { + .type = IIO_TEMP, + .address = AXP20X_TEMP_ADC_H, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .datasheet_name = "pmic_temp", + }, + AXP20X_ADC_CHANNEL_OFFSET(AXP192_GPIO0_V, "gpio0_v", IIO_VOLTAGE, + AXP20X_GPIO0_V_ADC_H), + AXP20X_ADC_CHANNEL_OFFSET(AXP192_GPIO1_V, "gpio1_v", IIO_VOLTAGE, + AXP20X_GPIO1_V_ADC_H), + AXP20X_ADC_CHANNEL_OFFSET(AXP192_GPIO2_V, "gpio2_v", IIO_VOLTAGE, + AXP192_GPIO2_V_ADC_H), + AXP20X_ADC_CHANNEL_OFFSET(AXP192_GPIO3_V, "gpio3_v", IIO_VOLTAGE, + AXP192_GPIO3_V_ADC_H), + AXP20X_ADC_CHANNEL(AXP192_IPSOUT_V, "ipsout_v", IIO_VOLTAGE, + AXP20X_IPSOUT_V_HIGH_H), + AXP20X_ADC_CHANNEL(AXP192_BATT_V, "batt_v", IIO_VOLTAGE, + AXP20X_BATT_V_H), + AXP20X_ADC_CHANNEL(AXP192_BATT_CHRG_I, "batt_chrg_i", IIO_CURRENT, + AXP20X_BATT_CHRG_I_H), + AXP20X_ADC_CHANNEL(AXP192_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT, + AXP20X_BATT_DISCHRG_I_H), + AXP20X_ADC_CHANNEL(AXP192_TS_IN, "ts_v", IIO_VOLTAGE, + AXP20X_TS_IN_H), +}; + static const struct iio_chan_spec axp20x_adc_channels[] = { AXP20X_ADC_CHANNEL(AXP20X_ACIN_V, "acin_v", IIO_VOLTAGE, AXP20X_ACIN_V_ADC_H), @@ -231,6 +295,27 @@ static const struct iio_chan_spec axp813_adc_channels[] = { AXP288_TS_ADC_H), }; +static int axp192_adc_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) +{ + struct axp20x_adc_iio *info = iio_priv(indio_dev); + int ret, size; + + if (chan->type == IIO_CURRENT && + (chan->channel == AXP192_BATT_CHRG_I || + chan->channel == AXP192_BATT_DISCHRG_I)) + size = 13; + else + size = 12; + + ret = axp20x_read_variable_width(info->regmap, chan->address, size); + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; +} + static int axp20x_adc_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) { @@ -283,6 +368,44 @@ static int axp813_adc_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; } +static int axp192_adc_scale_voltage(int channel, int *val, int *val2) +{ + switch (channel) { + case AXP192_ACIN_V: + case AXP192_VBUS_V: + *val = 1; + *val2 = 700000; + return IIO_VAL_INT_PLUS_MICRO; + + case AXP192_GPIO0_V: + case AXP192_GPIO1_V: + case AXP192_GPIO2_V: + case AXP192_GPIO3_V: + *val = 0; + *val2 = 500000; + return IIO_VAL_INT_PLUS_MICRO; + + case AXP192_BATT_V: + *val = 1; + *val2 = 100000; + return IIO_VAL_INT_PLUS_MICRO; + + case AXP192_IPSOUT_V: + *val = 1; + *val2 = 400000; + return IIO_VAL_INT_PLUS_MICRO; + + case AXP192_TS_IN: + /* 0.8 mV per LSB */ + *val = 0; + *val2 = 800000; + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + static int axp20x_adc_scale_voltage(int channel, int *val, int *val2) { switch (channel) { @@ -386,6 +509,29 @@ static int axp20x_adc_scale_current(int channel, int *val, int *val2) } } +static int axp192_adc_scale(struct iio_chan_spec const *chan, int *val, + int *val2) +{ + switch (chan->type) { + case IIO_VOLTAGE: + return axp192_adc_scale_voltage(chan->channel, val, val2); + + case IIO_CURRENT: + /* + * AXP192 current channels are identical to the AXP20x, + * therefore we can re-use the scaling function. + */ + return axp20x_adc_scale_current(chan->channel, val, val2); + + case IIO_TEMP: + *val = 100; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + static int axp20x_adc_scale(struct iio_chan_spec const *chan, int *val, int *val2) { @@ -445,6 +591,42 @@ static int axp813_adc_scale(struct iio_chan_spec const *chan, int *val, } } +static int axp192_adc_offset_voltage(struct iio_dev *indio_dev, int channel, + int *val) +{ + struct axp20x_adc_iio *info = iio_priv(indio_dev); + unsigned int regval; + int ret; + + ret = regmap_read(info->regmap, AXP192_GPIO30_IN_RANGE, ®val); + if (ret < 0) + return ret; + + switch (channel) { + case AXP192_GPIO0_V: + regval = FIELD_GET(AXP192_GPIO30_IN_RANGE_GPIO0, regval); + break; + + case AXP192_GPIO1_V: + regval = FIELD_GET(AXP192_GPIO30_IN_RANGE_GPIO1, regval); + break; + + case AXP192_GPIO2_V: + regval = FIELD_GET(AXP192_GPIO30_IN_RANGE_GPIO2, regval); + break; + + case AXP192_GPIO3_V: + regval = FIELD_GET(AXP192_GPIO30_IN_RANGE_GPIO3, regval); + break; + + default: + return -EINVAL; + } + + *val = regval ? 700000 : 0; + return IIO_VAL_INT; +} + static int axp20x_adc_offset_voltage(struct iio_dev *indio_dev, int channel, int *val) { @@ -473,6 +655,22 @@ static int axp20x_adc_offset_voltage(struct iio_dev *indio_dev, int channel, return IIO_VAL_INT; } +static int axp192_adc_offset(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) +{ + switch (chan->type) { + case IIO_VOLTAGE: + return axp192_adc_offset_voltage(indio_dev, chan->channel, val); + + case IIO_TEMP: + *val = -1447; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + static int axp20x_adc_offset(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) { @@ -489,6 +687,25 @@ static int axp20x_adc_offset(struct iio_dev *indio_dev, } } +static int axp192_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + return axp192_adc_offset(indio_dev, chan, val); + + case IIO_CHAN_INFO_SCALE: + return axp192_adc_scale(chan, val, val2); + + case IIO_CHAN_INFO_RAW: + return axp192_adc_raw(indio_dev, chan, val); + + default: + return -EINVAL; + } +} + static int axp20x_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -549,6 +766,51 @@ static int axp813_read_raw(struct iio_dev *indio_dev, } } +static int axp192_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, + long mask) +{ + struct axp20x_adc_iio *info = iio_priv(indio_dev); + unsigned int regmask, regval; + + /* + * The AXP192 PMIC allows the user to choose between 0V and 0.7V offsets + * for (independently) GPIO0-3 when in ADC mode. + */ + if (mask != IIO_CHAN_INFO_OFFSET) + return -EINVAL; + + if (val != 0 && val != 700000) + return -EINVAL; + + switch (chan->channel) { + case AXP192_GPIO0_V: + regmask = AXP192_GPIO30_IN_RANGE_GPIO0; + regval = FIELD_PREP(AXP192_GPIO30_IN_RANGE_GPIO0, !!val); + break; + + case AXP192_GPIO1_V: + regmask = AXP192_GPIO30_IN_RANGE_GPIO1; + regval = FIELD_PREP(AXP192_GPIO30_IN_RANGE_GPIO1, !!val); + break; + + case AXP192_GPIO2_V: + regmask = AXP192_GPIO30_IN_RANGE_GPIO2; + regval = FIELD_PREP(AXP192_GPIO30_IN_RANGE_GPIO2, !!val); + break; + + case AXP192_GPIO3_V: + regmask = AXP192_GPIO30_IN_RANGE_GPIO3; + regval = FIELD_PREP(AXP192_GPIO30_IN_RANGE_GPIO3, !!val); + break; + + default: + return -EINVAL; + } + + return regmap_update_bits(info->regmap, AXP192_GPIO30_IN_RANGE, regmask, regval); +} + static int axp20x_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -584,6 +846,11 @@ static int axp20x_write_raw(struct iio_dev *indio_dev, return regmap_update_bits(info->regmap, AXP20X_GPIO10_IN_RANGE, regmask, regval); } +static const struct iio_info axp192_adc_iio_info = { + .read_raw = axp192_read_raw, + .write_raw = axp192_write_raw, +}; + static const struct iio_info axp20x_adc_iio_info = { .read_raw = axp20x_read_raw, .write_raw = axp20x_write_raw, @@ -629,6 +896,16 @@ struct axp_data { struct iio_map *maps; }; +static const struct axp_data axp192_data = { + .iio_info = &axp192_adc_iio_info, + .num_channels = ARRAY_SIZE(axp192_adc_channels), + .channels = axp192_adc_channels, + .adc_en1_mask = AXP192_ADC_EN1_MASK, + .adc_en2_mask = AXP192_ADC_EN2_MASK, + .adc_rate = axp20x_adc_rate, + .maps = axp20x_maps, +}; + static const struct axp_data axp20x_data = { .iio_info = &axp20x_adc_iio_info, .num_channels = ARRAY_SIZE(axp20x_adc_channels), @@ -658,6 +935,7 @@ static const struct axp_data axp813_data = { }; static const struct of_device_id axp20x_adc_of_match[] = { + { .compatible = "x-powers,axp192-adc", .data = (void *)&axp192_data, }, { .compatible = "x-powers,axp209-adc", .data = (void *)&axp20x_data, }, { .compatible = "x-powers,axp221-adc", .data = (void *)&axp22x_data, }, { .compatible = "x-powers,axp813-adc", .data = (void *)&axp813_data, }, @@ -666,6 +944,7 @@ static const struct of_device_id axp20x_adc_of_match[] = { MODULE_DEVICE_TABLE(of, axp20x_adc_of_match); static const struct platform_device_id axp20x_adc_id_match[] = { + { .name = "axp192-adc", .driver_data = (kernel_ulong_t)&axp192_data, }, { .name = "axp20x-adc", .driver_data = (kernel_ulong_t)&axp20x_data, }, { .name = "axp22x-adc", .driver_data = (kernel_ulong_t)&axp22x_data, }, { .name = "axp813-adc", .driver_data = (kernel_ulong_t)&axp813_data, }, @@ -712,9 +991,8 @@ static int axp20x_probe(struct platform_device *pdev) regmap_write(info->regmap, AXP20X_ADC_EN1, info->data->adc_en1_mask); if (info->data->adc_en2_mask) - regmap_update_bits(info->regmap, AXP20X_ADC_EN2, - info->data->adc_en2_mask, - info->data->adc_en2_mask); + regmap_set_bits(info->regmap, AXP20X_ADC_EN2, + info->data->adc_en2_mask); /* Configure ADCs rate */ info->data->adc_rate(info, 100); diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 49fff1cabd0d..f135cf2362df 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -247,8 +247,8 @@ static int axp288_adc_initialize(struct axp288_adc_info *info) return ret; /* Turn on the ADC for all channels except TS, leave TS as is */ - return regmap_update_bits(info->regmap, AXP20X_ADC_EN1, - AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK); + return regmap_set_bits(info->regmap, AXP20X_ADC_EN1, + AXP288_ADC_EN_MASK); } static const struct iio_info axp288_adc_iio_info = { diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index 5bc514bd5ebc..6bc149c51414 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -357,8 +357,8 @@ static int iproc_adc_enable(struct iio_dev *indio_dev) int ret; /* Set i_amux = 3b'000, select channel 0 */ - ret = regmap_update_bits(adc_priv->regmap, IPROC_ANALOG_CONTROL, - IPROC_ADC_CHANNEL_SEL_MASK, 0); + ret = regmap_clear_bits(adc_priv->regmap, IPROC_ANALOG_CONTROL, + IPROC_ADC_CHANNEL_SEL_MASK); if (ret) { dev_err(&indio_dev->dev, "failed to write IPROC_ANALOG_CONTROL %d\n", ret); @@ -543,8 +543,8 @@ static int iproc_adc_probe(struct platform_device *pdev) if (adc_priv->irqno < 0) return adc_priv->irqno; - ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, - IPROC_ADC_AUXIN_SCAN_ENA, 0); + ret = regmap_clear_bits(adc_priv->regmap, IPROC_REGCTL2, + IPROC_ADC_AUXIN_SCAN_ENA); if (ret) { dev_err(&pdev->dev, "failed to write IPROC_REGCTL2 %d\n", ret); return ret; diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c index a4e7c7eff5ac..4cdddc6e36e9 100644 --- a/drivers/iio/adc/berlin2-adc.c +++ b/drivers/iio/adc/berlin2-adc.c @@ -129,8 +129,8 @@ static int berlin2_adc_read(struct iio_dev *indio_dev, int channel) msecs_to_jiffies(1000)); /* Disable the interrupts */ - regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS, - BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0); + regmap_clear_bits(priv->regmap, BERLIN2_SM_ADC_STATUS, + BERLIN2_SM_ADC_STATUS_INT_EN(channel)); if (ret == 0) ret = -ETIMEDOUT; @@ -139,8 +139,8 @@ static int berlin2_adc_read(struct iio_dev *indio_dev, int channel) return ret; } - regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, - BERLIN2_SM_CTRL_ADC_START, 0); + regmap_clear_bits(priv->regmap, BERLIN2_SM_CTRL, + BERLIN2_SM_CTRL_ADC_START); data = priv->data; priv->data_available = false; @@ -180,8 +180,8 @@ static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) msecs_to_jiffies(1000)); /* Disable interrupts */ - regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS, - BERLIN2_SM_TSEN_STATUS_INT_EN, 0); + regmap_clear_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS, + BERLIN2_SM_TSEN_STATUS_INT_EN); if (ret == 0) ret = -ETIMEDOUT; @@ -190,8 +190,8 @@ static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) return ret; } - regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, - BERLIN2_SM_TSEN_CTRL_START, 0); + regmap_clear_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, + BERLIN2_SM_TSEN_CTRL_START); data = priv->data; priv->data_available = false; @@ -284,8 +284,7 @@ static const struct iio_info berlin2_adc_info = { static void berlin2_adc_powerdown(void *regmap) { - regmap_update_bits(regmap, BERLIN2_SM_CTRL, - BERLIN2_SM_CTRL_ADC_POWER, 0); + regmap_clear_bits(regmap, BERLIN2_SM_CTRL, BERLIN2_SM_CTRL_ADC_POWER); } @@ -339,9 +338,8 @@ static int berlin2_adc_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels); /* Power up the ADC */ - regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, - BERLIN2_SM_CTRL_ADC_POWER, - BERLIN2_SM_CTRL_ADC_POWER); + regmap_set_bits(priv->regmap, BERLIN2_SM_CTRL, + BERLIN2_SM_CTRL_ADC_POWER); ret = devm_add_action_or_reset(&pdev->dev, berlin2_adc_powerdown, priv->regmap); diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index b6c4ef70484e..c218acf6c9c6 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -385,9 +385,8 @@ static irqreturn_t cpcap_adc_irq_thread(int irq, void *data) struct cpcap_adc *ddata = iio_priv(indio_dev); int error; - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_DIS, - CPCAP_BIT_ADTRIG_DIS); + error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ADTRIG_DIS); if (error) return IRQ_NONE; @@ -424,23 +423,19 @@ static void cpcap_adc_setup_calibrate(struct cpcap_adc *ddata, if (error) return; - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ATOX_PS_FACTOR | - CPCAP_BIT_ADC_PS_FACTOR1 | - CPCAP_BIT_ADC_PS_FACTOR0, - 0); + error = regmap_clear_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ATOX_PS_FACTOR | + CPCAP_BIT_ADC_PS_FACTOR1 | + CPCAP_BIT_ADC_PS_FACTOR0); if (error) return; - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_DIS, - CPCAP_BIT_ADTRIG_DIS); + error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ADTRIG_DIS); if (error) return; - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ASC, - CPCAP_BIT_ASC); + error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, CPCAP_BIT_ASC); if (error) return; @@ -455,8 +450,8 @@ static void cpcap_adc_setup_calibrate(struct cpcap_adc *ddata, dev_err(ddata->dev, "Timeout waiting for calibration to complete\n"); - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, - CPCAP_BIT_CAL_MODE, 0); + error = regmap_clear_bits(ddata->reg, CPCAP_REG_ADCC1, + CPCAP_BIT_CAL_MODE); if (error) return; } @@ -602,26 +597,23 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, return; if (req->timing == CPCAP_ADC_TIMING_IMM) { - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_DIS, - CPCAP_BIT_ADTRIG_DIS); + error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ADTRIG_DIS); if (error) return; - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ASC, - CPCAP_BIT_ASC); + error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ASC); if (error) return; } else { - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_ONESHOT, - CPCAP_BIT_ADTRIG_ONESHOT); + error = regmap_set_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ADTRIG_ONESHOT); if (error) return; - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_DIS, 0); + error = regmap_clear_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_ADTRIG_DIS); if (error) return; } diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index b680690631db..b3f037510e35 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -87,13 +87,13 @@ static irqreturn_t mx25_gcq_irq(int irq, void *data) regmap_read(priv->regs, MX25_ADCQ_SR, &stats); if (stats & MX25_ADCQ_SR_EOQ) { - regmap_update_bits(priv->regs, MX25_ADCQ_MR, - MX25_ADCQ_MR_EOQ_IRQ, MX25_ADCQ_MR_EOQ_IRQ); + regmap_set_bits(priv->regs, MX25_ADCQ_MR, + MX25_ADCQ_MR_EOQ_IRQ); complete(&priv->completed); } /* Disable conversion queue run */ - regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0); + regmap_clear_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS); /* Acknowledge all possible irqs */ regmap_write(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR | @@ -115,11 +115,10 @@ static int mx25_gcq_get_raw_value(struct device *dev, regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0, MX25_ADCQ_ITEM(0, chan->channel)); - regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ, 0); + regmap_clear_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ); /* Trigger queue for one run */ - regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, - MX25_ADCQ_CR_FQS); + regmap_set_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS); time_left = wait_for_completion_interruptible_timeout( &priv->completed, MX25_GCQ_TIMEOUT); @@ -272,9 +271,8 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, MX25_ADCQ_CFG_REFN_MASK, refp | refn); } - regmap_update_bits(priv->regs, MX25_ADCQ_CR, - MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST, - MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST); + regmap_set_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST); regmap_write(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK | MX25_ADCQ_CR_QSM_FQS); diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index fef97c1d226a..b3372ccff7d5 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -80,7 +80,6 @@ struct hx711_data { struct device *dev; struct gpio_desc *gpiod_pd_sck; struct gpio_desc *gpiod_dout; - struct regulator *reg_avdd; int gain_set; /* gain set on device */ int gain_chan_a; /* gain for channel A */ struct mutex lock; @@ -465,10 +464,8 @@ static int hx711_probe(struct platform_device *pdev) int i; indio_dev = devm_iio_device_alloc(dev, sizeof(struct hx711_data)); - if (!indio_dev) { - dev_err(dev, "failed to allocate IIO device\n"); - return -ENOMEM; - } + if (!indio_dev) + return dev_err_probe(dev, -ENOMEM, "failed to allocate IIO device\n"); hx711_data = iio_priv(indio_dev); hx711_data->dev = dev; @@ -480,28 +477,20 @@ static int hx711_probe(struct platform_device *pdev) * in the driver it is an output */ hx711_data->gpiod_pd_sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); - if (IS_ERR(hx711_data->gpiod_pd_sck)) { - dev_err(dev, "failed to get sck-gpiod: err=%ld\n", - PTR_ERR(hx711_data->gpiod_pd_sck)); - return PTR_ERR(hx711_data->gpiod_pd_sck); - } + if (IS_ERR(hx711_data->gpiod_pd_sck)) + return dev_err_probe(dev, PTR_ERR(hx711_data->gpiod_pd_sck), + "failed to get sck-gpiod\n"); /* * DOUT stands for serial data output of HX711 * for the driver it is an input */ hx711_data->gpiod_dout = devm_gpiod_get(dev, "dout", GPIOD_IN); - if (IS_ERR(hx711_data->gpiod_dout)) { - dev_err(dev, "failed to get dout-gpiod: err=%ld\n", - PTR_ERR(hx711_data->gpiod_dout)); - return PTR_ERR(hx711_data->gpiod_dout); - } + if (IS_ERR(hx711_data->gpiod_dout)) + return dev_err_probe(dev, PTR_ERR(hx711_data->gpiod_dout), + "failed to get dout-gpiod\n"); - hx711_data->reg_avdd = devm_regulator_get(dev, "avdd"); - if (IS_ERR(hx711_data->reg_avdd)) - return PTR_ERR(hx711_data->reg_avdd); - - ret = regulator_enable(hx711_data->reg_avdd); + ret = devm_regulator_get_enable_read_voltage(dev, "avdd"); if (ret < 0) return ret; @@ -517,9 +506,6 @@ static int hx711_probe(struct platform_device *pdev) * approximately to fit into a 32 bit number: * 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV] */ - ret = regulator_get_voltage(hx711_data->reg_avdd); - if (ret < 0) - goto error_regulator; /* we need 10^-9 mV */ ret *= 100; @@ -547,51 +533,24 @@ static int hx711_probe(struct platform_device *pdev) hx711_data->data_ready_delay_ns = 1000000000 / hx711_data->clock_frequency; - platform_set_drvdata(pdev, indio_dev); - indio_dev->name = "hx711"; indio_dev->info = &hx711_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = hx711_chan_spec; indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec); - ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, - hx711_trigger, NULL); - if (ret < 0) { - dev_err(dev, "setup of iio triggered buffer failed\n"); - goto error_regulator; - } + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + hx711_trigger, NULL); + if (ret < 0) + return dev_err_probe(dev, ret, + "setup of iio triggered buffer failed\n"); - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(dev, "Couldn't register the device\n"); - goto error_buffer; - } + ret = devm_iio_device_register(dev, indio_dev); + if (ret < 0) + return dev_err_probe(dev, ret, "Couldn't register the device\n"); return 0; - -error_buffer: - iio_triggered_buffer_cleanup(indio_dev); - -error_regulator: - regulator_disable(hx711_data->reg_avdd); - - return ret; -} - -static void hx711_remove(struct platform_device *pdev) -{ - struct hx711_data *hx711_data; - struct iio_dev *indio_dev; - - indio_dev = platform_get_drvdata(pdev); - hx711_data = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - iio_triggered_buffer_cleanup(indio_dev); - - regulator_disable(hx711_data->reg_avdd); } static const struct of_device_id of_hx711_match[] = { @@ -603,7 +562,6 @@ MODULE_DEVICE_TABLE(of, of_hx711_match); static struct platform_driver hx711_driver = { .probe = hx711_probe, - .remove_new = hx711_remove, .driver = { .name = "hx711-gpio", .of_match_table = of_hx711_match, diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 9e52207352fb..727e390bd979 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -1046,8 +1046,7 @@ static void ina2xx_remove(struct i2c_client *client) iio_device_unregister(indio_dev); /* Powerdown */ - ret = regmap_update_bits(chip->regmap, INA2XX_CONFIG, - INA2XX_MODE_MASK, 0); + ret = regmap_clear_bits(chip->regmap, INA2XX_CONFIG, INA2XX_MODE_MASK); if (ret) dev_warn(&client->dev, "Failed to power down device (%pe)\n", ERR_PTR(ret)); diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c index a7325dbbb99a..af70ca760797 100644 --- a/drivers/iio/adc/ingenic-adc.c +++ b/drivers/iio/adc/ingenic-adc.c @@ -920,4 +920,5 @@ static struct platform_driver ingenic_adc_driver = { .probe = ingenic_adc_probe, }; module_platform_driver(ingenic_adc_driver); +MODULE_DESCRIPTION("ADC driver for the Ingenic JZ47xx SoCs"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c index c7f40ae6e608..0590a126f321 100644 --- a/drivers/iio/adc/intel_mrfld_adc.c +++ b/drivers/iio/adc/intel_mrfld_adc.c @@ -81,8 +81,8 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev, reinit_completion(&adc->completion); - regmap_update_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL, 0); - regmap_update_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC, 0); + regmap_clear_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL); + regmap_clear_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC); ret = regmap_read_poll_timeout(regmap, BCOVE_GPADCREQ, req, !(req & BCOVE_GPADCREQ_BUSY), diff --git a/drivers/iio/adc/ltc2309.c b/drivers/iio/adc/ltc2309.c index 8b3a89c1b840..5f0d947d0615 100644 --- a/drivers/iio/adc/ltc2309.c +++ b/drivers/iio/adc/ltc2309.c @@ -16,6 +16,7 @@ #include #define LTC2309_ADC_RESOLUTION 12 +#define LTC2309_INTERNAL_REF_MV 4096 #define LTC2309_DIN_CH_MASK GENMASK(7, 4) #define LTC2309_DIN_SDN BIT(7) @@ -29,14 +30,12 @@ * struct ltc2309 - internal device data structure * @dev: Device reference * @client: I2C reference - * @vref: External reference source * @lock: Lock to serialize data access * @vref_mv: Internal voltage reference */ struct ltc2309 { struct device *dev; struct i2c_client *client; - struct regulator *vref; struct mutex lock; /* serialize data access */ int vref_mv; }; @@ -104,7 +103,7 @@ static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309, unsigned long address, int *val) { int ret; - u16 buf; + __be16 buf; u8 din; din = FIELD_PREP(LTC2309_DIN_CH_MASK, address & 0x0f) | @@ -157,11 +156,6 @@ static const struct iio_info ltc2309_info = { .read_raw = ltc2309_read_raw, }; -static void ltc2309_regulator_disable(void *regulator) -{ - regulator_disable(regulator); -} - static int ltc2309_probe(struct i2c_client *client) { struct iio_dev *indio_dev; @@ -175,7 +169,6 @@ static int ltc2309_probe(struct i2c_client *client) ltc2309 = iio_priv(indio_dev); ltc2309->dev = &indio_dev->dev; ltc2309->client = client; - ltc2309->vref_mv = 4096; /* Default to the internal ref */ indio_dev->name = "ltc2309"; indio_dev->modes = INDIO_DIRECT_MODE; @@ -183,36 +176,12 @@ static int ltc2309_probe(struct i2c_client *client) indio_dev->num_channels = ARRAY_SIZE(ltc2309_channels); indio_dev->info = <c2309_info; - ltc2309->vref = devm_regulator_get_optional(&client->dev, "vref"); - if (IS_ERR(ltc2309->vref)) { - ret = PTR_ERR(ltc2309->vref); - if (ret == -ENODEV) - ltc2309->vref = NULL; - else - return ret; - } + ret = devm_regulator_get_enable_read_voltage(&client->dev, "vref"); + if (ret < 0 && ret != -ENODEV) + return dev_err_probe(ltc2309->dev, ret, + "failed to get vref voltage\n"); - if (ltc2309->vref) { - ret = regulator_enable(ltc2309->vref); - if (ret) - return dev_err_probe(ltc2309->dev, ret, - "failed to enable vref\n"); - - ret = devm_add_action_or_reset(ltc2309->dev, - ltc2309_regulator_disable, - ltc2309->vref); - if (ret) { - return dev_err_probe(ltc2309->dev, ret, - "failed to add regulator_disable action: %d\n", - ret); - } - - ret = regulator_get_voltage(ltc2309->vref); - if (ret < 0) - return ret; - - ltc2309->vref_mv = ret / 1000; - } + ltc2309->vref_mv = ret == -ENODEV ? LTC2309_INTERNAL_REF_MV : ret / 1000; mutex_init(<c2309->lock); diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c index 859e4314cfa2..060651dd4130 100644 --- a/drivers/iio/adc/ltc2485.c +++ b/drivers/iio/adc/ltc2485.c @@ -124,7 +124,7 @@ static int ltc2485_probe(struct i2c_client *client) } static const struct i2c_device_id ltc2485_id[] = { - { "ltc2485", 0 }, + { "ltc2485" }, { } }; MODULE_DEVICE_TABLE(i2c, ltc2485_id); diff --git a/drivers/iio/adc/max11205.c b/drivers/iio/adc/max11205.c index 65fc32971ba5..9d8bc0b154dd 100644 --- a/drivers/iio/adc/max11205.c +++ b/drivers/iio/adc/max11205.c @@ -116,10 +116,7 @@ static int max11205_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &max11205_sigma_delta_info); - st->chip_info = device_get_match_data(&spi->dev); - if (!st->chip_info) - st->chip_info = - (const struct max11205_chip_info *)spi_get_device_id(spi)->driver_data; + st->chip_info = spi_get_device_match_data(spi); indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 8b5bc96cb9fb..bf4b6dc53fd2 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1561,18 +1561,12 @@ static const struct of_device_id max1363_of_match[] = { }; MODULE_DEVICE_TABLE(of, max1363_of_match); -static void max1363_reg_disable(void *reg) -{ - regulator_disable(reg); -} - static int max1363_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); int ret; struct max1363_state *st; struct iio_dev *indio_dev; - struct regulator *vref; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(struct max1363_state)); @@ -1589,26 +1583,12 @@ static int max1363_probe(struct i2c_client *client) st->chip_info = i2c_get_match_data(client); st->client = client; - st->vref_uv = st->chip_info->int_vref_mv * 1000; - vref = devm_regulator_get_optional(&client->dev, "vref"); - if (!IS_ERR(vref)) { - int vref_uv; + ret = devm_regulator_get_enable_read_voltage(&client->dev, "vref"); + if (ret < 0 && ret != -ENODEV) + return ret; - ret = regulator_enable(vref); - if (ret) - return ret; - ret = devm_add_action_or_reset(&client->dev, max1363_reg_disable, vref); - if (ret) - return ret; - - st->vref = vref; - vref_uv = regulator_get_voltage(vref); - if (vref_uv <= 0) - return -EINVAL; - - st->vref_uv = vref_uv; - } + st->vref_uv = ret == -ENODEV ? st->chip_info->int_vref_mv * 1000 : ret; if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { st->send = i2c_master_send; diff --git a/drivers/iio/adc/mcp3564.c b/drivers/iio/adc/mcp3564.c index e2ae13f1e842..d83bed0e63d2 100644 --- a/drivers/iio/adc/mcp3564.c +++ b/drivers/iio/adc/mcp3564.c @@ -1114,7 +1114,6 @@ static int mcp3564_config(struct iio_dev *indio_dev) { struct mcp3564_state *adc = iio_priv(indio_dev); struct device *dev = &adc->spi->dev; - const struct spi_device_id *dev_id; u8 tmp_reg; u16 tmp_u16; enum mcp3564_ids ids; @@ -1212,11 +1211,6 @@ static int mcp3564_config(struct iio_dev *indio_dev) * try using fallback compatible in device tree to deal with some newer part number. */ adc->chip_info = spi_get_device_match_data(adc->spi); - if (!adc->chip_info) { - dev_id = spi_get_device_id(adc->spi); - adc->chip_info = (const struct mcp3564_chip_info *)dev_id->driver_data; - } - adc->have_vref = adc->chip_info->have_vref; } else { adc->chip_info = &mcp3564_chip_infos_tbl[ids]; diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 13b473d8c6c7..e16b0e28974e 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -546,35 +546,31 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) reinit_completion(&priv->done); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_FIFO_IRQ_EN, - MESON_SAR_ADC_REG0_FIFO_IRQ_EN); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_FIFO_IRQ_EN); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, - MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_SAMPLING_START, - MESON_SAR_ADC_REG0_SAMPLING_START); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_SAMPLING_START); } static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_FIFO_IRQ_EN); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_SAMPLING_STOP, - MESON_SAR_ADC_REG0_SAMPLING_STOP); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_SAMPLING_STOP); /* wait until all modules are stopped */ meson_sar_adc_wait_busy_clear(indio_dev); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); } static int meson_sar_adc_lock(struct iio_dev *indio_dev) @@ -586,9 +582,8 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) if (priv->param->has_bl30_integration) { /* prevent BL30 from using the SAR ADC while we are using it */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY); udelay(1); @@ -614,8 +609,8 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) if (priv->param->has_bl30_integration) /* allow BL30 to use the SAR ADC again */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY); mutex_unlock(&priv->lock); } @@ -869,17 +864,16 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) * disable this bit as seems to be only relevant for Meson6 (based * on the vendor driver), which we don't support at the moment. */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, - MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL); /* disable all channels by default */ regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, - MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, - MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, - MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG3, + MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG3, + MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); /* delay between two samples = (10+1) * 1uS */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, @@ -914,21 +908,17 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, regval); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW, - MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW); /* * set up the input channel muxes in MESON_SAR_ADC_AUX_SW @@ -944,12 +934,10 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); if (priv->temperature_sensor_calibrated) { - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, - MESON_SAR_ADC_DELTA_10_TS_REVE1, - MESON_SAR_ADC_DELTA_10_TS_REVE1); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, - MESON_SAR_ADC_DELTA_10_TS_REVE0, - MESON_SAR_ADC_DELTA_10_TS_REVE0); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, + MESON_SAR_ADC_DELTA_10_TS_REVE1); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, + MESON_SAR_ADC_DELTA_10_TS_REVE0); /* * set bits [3:0] of the TSC (temperature sensor coefficient) @@ -976,10 +964,10 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) regval); } } else { - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, - MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, - MESON_SAR_ADC_DELTA_10_TS_REVE0, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, + MESON_SAR_ADC_DELTA_10_TS_REVE1); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, + MESON_SAR_ADC_DELTA_10_TS_REVE0); } regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, @@ -1062,9 +1050,8 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) meson_sar_adc_set_bandgap(indio_dev, true); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, - MESON_SAR_ADC_REG3_ADC_EN, - MESON_SAR_ADC_REG3_ADC_EN); + regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG3, + MESON_SAR_ADC_REG3_ADC_EN); udelay(5); @@ -1079,8 +1066,8 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) return 0; err_adc_clk: - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, - MESON_SAR_ADC_REG3_ADC_EN, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG3, + MESON_SAR_ADC_REG3_ADC_EN); meson_sar_adc_set_bandgap(indio_dev, false); regulator_disable(priv->vref); err_vref: @@ -1104,8 +1091,8 @@ static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev) clk_disable_unprepare(priv->adc_clk); - regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, - MESON_SAR_ADC_REG3_ADC_EN, 0); + regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG3, + MESON_SAR_ADC_REG3_ADC_EN); meson_sar_adc_set_bandgap(indio_dev, false); diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c index 7c66c2cd5be2..5f672765d4a2 100644 --- a/drivers/iio/adc/mp2629_adc.c +++ b/drivers/iio/adc/mp2629_adc.c @@ -131,9 +131,8 @@ static int mp2629_adc_probe(struct platform_device *pdev) info->dev = dev; platform_set_drvdata(pdev, indio_dev); - ret = regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, - MP2629_ADC_START | MP2629_ADC_CONTINUOUS, - MP2629_ADC_START | MP2629_ADC_CONTINUOUS); + ret = regmap_set_bits(info->regmap, MP2629_REG_ADC_CTRL, + MP2629_ADC_START | MP2629_ADC_CONTINUOUS); if (ret) { dev_err(dev, "adc enable fail: %d\n", ret); return ret; @@ -163,10 +162,9 @@ fail_map_unregister: iio_map_array_unregister(indio_dev); fail_disable: - regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, - MP2629_ADC_CONTINUOUS, 0); - regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, - MP2629_ADC_START, 0); + regmap_clear_bits(info->regmap, MP2629_REG_ADC_CTRL, + MP2629_ADC_CONTINUOUS); + regmap_clear_bits(info->regmap, MP2629_REG_ADC_CTRL, MP2629_ADC_START); return ret; } @@ -180,10 +178,9 @@ static void mp2629_adc_remove(struct platform_device *pdev) iio_map_array_unregister(indio_dev); - regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, - MP2629_ADC_CONTINUOUS, 0); - regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, - MP2629_ADC_START, 0); + regmap_clear_bits(info->regmap, MP2629_REG_ADC_CTRL, + MP2629_ADC_CONTINUOUS); + regmap_clear_bits(info->regmap, MP2629_REG_ADC_CTRL, MP2629_ADC_START); } static const struct of_device_id mp2629_adc_of_match[] = { diff --git a/drivers/iio/adc/mt6359-auxadc.c b/drivers/iio/adc/mt6359-auxadc.c new file mode 100644 index 000000000000..a4970cfb49a5 --- /dev/null +++ b/drivers/iio/adc/mt6359-auxadc.c @@ -0,0 +1,606 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MediaTek MT6359 PMIC AUXADC IIO driver + * + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd + * Author: AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#define AUXADC_AVG_TIME_US 10 +#define AUXADC_POLL_DELAY_US 100 +#define AUXADC_TIMEOUT_US 32000 +#define AUXADC_VOLT_FULL 1800 +#define IMP_STOP_DELAY_US 150 +#define IMP_POLL_DELAY_US 1000 + +/* For PMIC_RG_RESET_VAL and MT6358_IMP0_CLEAR, the bits specific purpose is unknown. */ +#define PMIC_RG_RESET_VAL (BIT(0) | BIT(3)) +#define PMIC_AUXADC_RDY_BIT BIT(15) +#define MT6357_IMP_ADC_NUM 30 +#define MT6358_IMP_ADC_NUM 28 + +#define MT6358_DCM_CK_SW_EN GENMASK(1, 0) +#define MT6358_IMP0_CLEAR (BIT(14) | BIT(7)) +#define MT6358_IMP0_IRQ_RDY BIT(8) +#define MT6358_IMP1_AUTOREPEAT_EN BIT(15) + +#define MT6359_IMP0_CONV_EN BIT(0) +#define MT6359_IMP1_IRQ_RDY BIT(15) + +enum mtk_pmic_auxadc_regs { + PMIC_AUXADC_ADC0, + PMIC_AUXADC_DCM_CON, + PMIC_AUXADC_IMP0, + PMIC_AUXADC_IMP1, + PMIC_AUXADC_IMP3, + PMIC_AUXADC_RQST0, + PMIC_AUXADC_RQST1, + PMIC_HK_TOP_WKEY, + PMIC_HK_TOP_RST_CON0, + PMIC_FGADC_R_CON0, + PMIC_AUXADC_REGS_MAX +}; + +enum mtk_pmic_auxadc_channels { + PMIC_AUXADC_CHAN_BATADC, + PMIC_AUXADC_CHAN_ISENSE, + PMIC_AUXADC_CHAN_VCDT, + PMIC_AUXADC_CHAN_BAT_TEMP, + PMIC_AUXADC_CHAN_BATID, + PMIC_AUXADC_CHAN_CHIP_TEMP, + PMIC_AUXADC_CHAN_VCORE_TEMP, + PMIC_AUXADC_CHAN_VPROC_TEMP, + PMIC_AUXADC_CHAN_VGPU_TEMP, + PMIC_AUXADC_CHAN_ACCDET, + PMIC_AUXADC_CHAN_VDCXO, + PMIC_AUXADC_CHAN_TSX_TEMP, + PMIC_AUXADC_CHAN_HPOFS_CAL, + PMIC_AUXADC_CHAN_DCXO_TEMP, + PMIC_AUXADC_CHAN_VBIF, + PMIC_AUXADC_CHAN_IBAT, + PMIC_AUXADC_CHAN_VBAT, + PMIC_AUXADC_CHAN_MAX +}; + +/** + * struct mt6359_auxadc - Main driver structure + * @dev: Device pointer + * @regmap: Regmap from SoC PMIC Wrapper + * @chip_info: PMIC specific chip info + * @lock: Mutex to serialize AUXADC reading vs configuration + * @timed_out: Signals whether the last read timed out + */ +struct mt6359_auxadc { + struct device *dev; + struct regmap *regmap; + const struct mtk_pmic_auxadc_info *chip_info; + struct mutex lock; + bool timed_out; +}; + +/** + * struct mtk_pmic_auxadc_chan - PMIC AUXADC channel data + * @req_idx: Request register number + * @req_mask: Bitmask to activate a channel + * @num_samples: Number of AUXADC samples for averaging + * @r_ratio: Resistance ratio fractional + */ +struct mtk_pmic_auxadc_chan { + u8 req_idx; + u16 req_mask; + u16 num_samples; + struct u8_fract r_ratio; +}; + +/** + * struct mtk_pmic_auxadc_info - PMIC specific chip info + * @model_name: PMIC model name + * @channels: IIO specification of ADC channels + * @num_channels: Number of ADC channels + * @desc: PMIC AUXADC channel data + * @regs: List of PMIC specific registers + * @sec_unlock_key: Security unlock key for HK_TOP writes + * @imp_adc_num: ADC channel for battery impedance readings + * @read_imp: Callback to read impedance channels + */ +struct mtk_pmic_auxadc_info { + const char *model_name; + const struct iio_chan_spec *channels; + u8 num_channels; + const struct mtk_pmic_auxadc_chan *desc; + const u16 *regs; + u16 sec_unlock_key; + u8 imp_adc_num; + int (*read_imp)(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat); +}; + +#define MTK_PMIC_ADC_CHAN(_ch_idx, _req_idx, _req_bit, _samples, _rnum, _rdiv) \ + [PMIC_AUXADC_CHAN_##_ch_idx] = { \ + .req_idx = _req_idx, \ + .req_mask = BIT(_req_bit), \ + .num_samples = _samples, \ + .r_ratio = { _rnum, _rdiv } \ + } + +#define MTK_PMIC_IIO_CHAN(_model, _name, _ch_idx, _adc_idx, _nbits, _ch_type) \ +{ \ + .type = _ch_type, \ + .channel = _model##_AUXADC_##_ch_idx, \ + .address = _adc_idx, \ + .scan_index = PMIC_AUXADC_CHAN_##_ch_idx, \ + .datasheet_name = __stringify(_name), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = _nbits, \ + .storagebits = 16, \ + .endianness = IIO_CPU \ + }, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) \ +} + +static const struct iio_chan_spec mt6357_auxadc_channels[] = { + MTK_PMIC_IIO_CHAN(MT6357, bat_adc, BATADC, 0, 15, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6357, isense, ISENSE, 1, 12, IIO_CURRENT), + MTK_PMIC_IIO_CHAN(MT6357, cdt_v, VCDT, 2, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6357, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6357, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6357, acc_det, ACCDET, 5, 12, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6357, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE), + MTK_PMIC_IIO_CHAN(MT6357, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6357, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6357, dcxo_temp, DCXO_TEMP, 36, 15, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6357, vcore_temp, VCORE_TEMP, 40, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6357, vproc_temp, VPROC_TEMP, 41, 12, IIO_TEMP), + + /* Battery impedance channels */ + MTK_PMIC_IIO_CHAN(MT6357, batt_v, VBAT, 0, 15, IIO_VOLTAGE), +}; + +static const struct mtk_pmic_auxadc_chan mt6357_auxadc_ch_desc[] = { + MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 3, 1), + MTK_PMIC_ADC_CHAN(ISENSE, PMIC_AUXADC_RQST0, 0, 128, 3, 1), + MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, 8, 1, 1), + MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 1, 1), + MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1), + MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1), + MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1), + MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1), + MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1), + MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 5, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 6, 8, 1, 1), + + /* Battery impedance channels */ + MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 3, 1), +}; + +static const u16 mt6357_auxadc_regs[] = { + [PMIC_HK_TOP_RST_CON0] = 0x0f90, + [PMIC_AUXADC_DCM_CON] = 0x122e, + [PMIC_AUXADC_ADC0] = 0x1088, + [PMIC_AUXADC_IMP0] = 0x119c, + [PMIC_AUXADC_IMP1] = 0x119e, + [PMIC_AUXADC_RQST0] = 0x110e, + [PMIC_AUXADC_RQST1] = 0x1114, +}; + +static const struct iio_chan_spec mt6358_auxadc_channels[] = { + MTK_PMIC_IIO_CHAN(MT6358, bat_adc, BATADC, 0, 15, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6358, cdt_v, VCDT, 2, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, acc_det, ACCDET, 5, 12, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6358, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE), + MTK_PMIC_IIO_CHAN(MT6358, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6358, dcxo_temp, DCXO_TEMP, 10, 15, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, bif_v, VBIF, 11, 12, IIO_VOLTAGE), + MTK_PMIC_IIO_CHAN(MT6358, vcore_temp, VCORE_TEMP, 38, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, vproc_temp, VPROC_TEMP, 39, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6358, vgpu_temp, VGPU_TEMP, 40, 12, IIO_TEMP), + + /* Battery impedance channels */ + MTK_PMIC_IIO_CHAN(MT6358, batt_v, VBAT, 0, 15, IIO_VOLTAGE), +}; + +static const struct mtk_pmic_auxadc_chan mt6358_auxadc_ch_desc[] = { + MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 3, 1), + MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, 8, 1, 1), + MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 2, 1), + MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1), + MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, 8, 3, 2), + MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1), + MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1), + MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1), + MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 2, 1), + MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, 8, 1, 1), + + /* Battery impedance channels */ + MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 7, 2), +}; + +static const u16 mt6358_auxadc_regs[] = { + [PMIC_HK_TOP_RST_CON0] = 0x0f90, + [PMIC_AUXADC_DCM_CON] = 0x1260, + [PMIC_AUXADC_ADC0] = 0x1088, + [PMIC_AUXADC_IMP0] = 0x1208, + [PMIC_AUXADC_IMP1] = 0x120a, + [PMIC_AUXADC_RQST0] = 0x1108, + [PMIC_AUXADC_RQST1] = 0x110a, +}; + +static const struct iio_chan_spec mt6359_auxadc_channels[] = { + MTK_PMIC_IIO_CHAN(MT6359, bat_adc, BATADC, 0, 15, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6359, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6359, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6359, acc_det, ACCDET, 5, 12, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6359, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE), + MTK_PMIC_IIO_CHAN(MT6359, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6359, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE), + MTK_PMIC_IIO_CHAN(MT6359, dcxo_temp, DCXO_TEMP, 10, 15, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6359, bif_v, VBIF, 11, 12, IIO_VOLTAGE), + MTK_PMIC_IIO_CHAN(MT6359, vcore_temp, VCORE_TEMP, 30, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6359, vproc_temp, VPROC_TEMP, 31, 12, IIO_TEMP), + MTK_PMIC_IIO_CHAN(MT6359, vgpu_temp, VGPU_TEMP, 32, 12, IIO_TEMP), + + /* Battery impedance channels */ + MTK_PMIC_IIO_CHAN(MT6359, batt_v, VBAT, 0, 15, IIO_VOLTAGE), + MTK_PMIC_IIO_CHAN(MT6359, batt_i, IBAT, 0, 15, IIO_CURRENT), +}; + +static const struct mtk_pmic_auxadc_chan mt6359_auxadc_ch_desc[] = { + MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 7, 2), + MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 5, 2), + MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1), + MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, 8, 3, 2), + MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1), + MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1), + MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1), + MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 5, 2), + MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, 8, 1, 1), + MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, 8, 1, 1), + + /* Battery impedance channels */ + MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 7, 2), + MTK_PMIC_ADC_CHAN(IBAT, 0, 0, 128, 7, 2), +}; + +static const u16 mt6359_auxadc_regs[] = { + [PMIC_FGADC_R_CON0] = 0x0d88, + [PMIC_HK_TOP_WKEY] = 0x0fb4, + [PMIC_HK_TOP_RST_CON0] = 0x0f90, + [PMIC_AUXADC_RQST0] = 0x1108, + [PMIC_AUXADC_RQST1] = 0x110a, + [PMIC_AUXADC_ADC0] = 0x1088, + [PMIC_AUXADC_IMP0] = 0x1208, + [PMIC_AUXADC_IMP1] = 0x120a, + [PMIC_AUXADC_IMP3] = 0x120e, +}; + +static void mt6358_stop_imp_conv(struct mt6359_auxadc *adc_dev) +{ + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + struct regmap *regmap = adc_dev->regmap; + + regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6358_IMP0_CLEAR); + regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6358_IMP0_CLEAR); + regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP1], MT6358_IMP1_AUTOREPEAT_EN); + regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_DCM_CON], MT6358_DCM_CK_SW_EN); +} + +static int mt6358_start_imp_conv(struct mt6359_auxadc *adc_dev) +{ + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + struct regmap *regmap = adc_dev->regmap; + u32 val; + int ret; + + regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_DCM_CON], MT6358_DCM_CK_SW_EN); + regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP1], MT6358_IMP1_AUTOREPEAT_EN); + + ret = regmap_read_poll_timeout(adc_dev->regmap, cinfo->regs[PMIC_AUXADC_IMP0], + val, val & MT6358_IMP0_IRQ_RDY, + IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US); + if (ret) { + mt6358_stop_imp_conv(adc_dev); + return ret; + } + + return 0; +} + +static int mt6358_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat) +{ + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + struct regmap *regmap = adc_dev->regmap; + u16 reg_adc0 = cinfo->regs[PMIC_AUXADC_ADC0]; + u32 val_v; + int ret; + + ret = mt6358_start_imp_conv(adc_dev); + if (ret) + return ret; + + /* Read the params before stopping */ + regmap_read(regmap, reg_adc0 + (cinfo->imp_adc_num << 1), &val_v); + + mt6358_stop_imp_conv(adc_dev); + + if (vbat) + *vbat = val_v; + if (ibat) + *ibat = 0; + + return 0; +} + +static int mt6359_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat) +{ + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + struct regmap *regmap = adc_dev->regmap; + u32 val, val_v, val_i; + int ret; + + /* Start conversion */ + regmap_write(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6359_IMP0_CONV_EN); + ret = regmap_read_poll_timeout(regmap, cinfo->regs[PMIC_AUXADC_IMP1], + val, val & MT6359_IMP1_IRQ_RDY, + IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US); + + /* Stop conversion regardless of the result */ + regmap_write(regmap, cinfo->regs[PMIC_AUXADC_IMP0], 0); + if (ret) + return ret; + + /* If it succeeded, wait for the registers to be populated */ + fsleep(IMP_STOP_DELAY_US); + + ret = regmap_read(regmap, cinfo->regs[PMIC_AUXADC_IMP3], &val_v); + if (ret) + return ret; + + ret = regmap_read(regmap, cinfo->regs[PMIC_FGADC_R_CON0], &val_i); + if (ret) + return ret; + + if (vbat) + *vbat = val_v; + if (ibat) + *ibat = val_i; + + return 0; +} + +static const struct mtk_pmic_auxadc_info mt6357_chip_info = { + .model_name = "MT6357", + .channels = mt6357_auxadc_channels, + .num_channels = ARRAY_SIZE(mt6357_auxadc_channels), + .desc = mt6357_auxadc_ch_desc, + .regs = mt6357_auxadc_regs, + .imp_adc_num = MT6357_IMP_ADC_NUM, + .read_imp = mt6358_read_imp, +}; + +static const struct mtk_pmic_auxadc_info mt6358_chip_info = { + .model_name = "MT6358", + .channels = mt6358_auxadc_channels, + .num_channels = ARRAY_SIZE(mt6358_auxadc_channels), + .desc = mt6358_auxadc_ch_desc, + .regs = mt6358_auxadc_regs, + .imp_adc_num = MT6358_IMP_ADC_NUM, + .read_imp = mt6358_read_imp, +}; + +static const struct mtk_pmic_auxadc_info mt6359_chip_info = { + .model_name = "MT6359", + .channels = mt6359_auxadc_channels, + .num_channels = ARRAY_SIZE(mt6359_auxadc_channels), + .desc = mt6359_auxadc_ch_desc, + .regs = mt6359_auxadc_regs, + .sec_unlock_key = 0x6359, + .read_imp = mt6359_read_imp, +}; + +static void mt6359_auxadc_reset(struct mt6359_auxadc *adc_dev) +{ + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + struct regmap *regmap = adc_dev->regmap; + + /* Unlock HK_TOP writes */ + if (cinfo->sec_unlock_key) + regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], cinfo->sec_unlock_key); + + /* Assert ADC reset */ + regmap_set_bits(regmap, cinfo->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL); + + /* De-assert ADC reset. No wait required, as pwrap takes care of that for us. */ + regmap_clear_bits(regmap, cinfo->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL); + + /* Lock HK_TOP writes again */ + if (cinfo->sec_unlock_key) + regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], 0); +} + +static int mt6359_auxadc_read_adc(struct mt6359_auxadc *adc_dev, + const struct iio_chan_spec *chan, int *out) +{ + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index]; + struct regmap *regmap = adc_dev->regmap; + u32 val; + int ret; + + /* Request to start sampling for ADC channel */ + ret = regmap_write(regmap, cinfo->regs[desc->req_idx], desc->req_mask); + if (ret) + return ret; + + /* Wait until all samples are averaged */ + fsleep(desc->num_samples * AUXADC_AVG_TIME_US); + + ret = regmap_read_poll_timeout(regmap, + cinfo->regs[PMIC_AUXADC_ADC0] + (chan->address << 1), + val, val & PMIC_AUXADC_RDY_BIT, + AUXADC_POLL_DELAY_US, AUXADC_TIMEOUT_US); + if (ret) + return ret; + + /* Stop sampling */ + regmap_write(regmap, cinfo->regs[desc->req_idx], 0); + + *out = val & GENMASK(chan->scan_type.realbits - 1, 0); + return 0; +} + +static int mt6359_auxadc_read_label(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, char *label) +{ + return sysfs_emit(label, "%s\n", chan->datasheet_name); +} + +static int mt6359_auxadc_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct mt6359_auxadc *adc_dev = iio_priv(indio_dev); + const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info; + const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index]; + int ret; + + if (mask == IIO_CHAN_INFO_SCALE) { + *val = desc->r_ratio.numerator * AUXADC_VOLT_FULL; + + if (desc->r_ratio.denominator > 1) { + *val2 = desc->r_ratio.denominator; + return IIO_VAL_FRACTIONAL; + } + + return IIO_VAL_INT; + } + + scoped_guard(mutex, &adc_dev->lock) { + switch (chan->scan_index) { + case PMIC_AUXADC_CHAN_IBAT: + ret = adc_dev->chip_info->read_imp(adc_dev, NULL, val); + break; + case PMIC_AUXADC_CHAN_VBAT: + ret = adc_dev->chip_info->read_imp(adc_dev, val, NULL); + break; + default: + ret = mt6359_auxadc_read_adc(adc_dev, chan, val); + break; + } + } + + if (ret) { + /* + * If we get more than one timeout, it's possible that the + * AUXADC is stuck: perform a full reset to recover it. + */ + if (ret == -ETIMEDOUT) { + if (adc_dev->timed_out) { + dev_warn(adc_dev->dev, "Resetting stuck ADC!\r\n"); + mt6359_auxadc_reset(adc_dev); + } + adc_dev->timed_out = true; + } + return ret; + } + adc_dev->timed_out = false; + + return IIO_VAL_INT; +} + +static const struct iio_info mt6359_auxadc_iio_info = { + .read_label = mt6359_auxadc_read_label, + .read_raw = mt6359_auxadc_read_raw, +}; + +static int mt6359_auxadc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device *mt6397_mfd_dev = dev->parent; + struct mt6359_auxadc *adc_dev; + struct iio_dev *indio_dev; + struct regmap *regmap; + int ret; + + /* Regmap is from SoC PMIC Wrapper, parent of the mt6397 MFD */ + regmap = dev_get_regmap(mt6397_mfd_dev->parent, NULL); + if (!regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n"); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*adc_dev)); + if (!indio_dev) + return -ENOMEM; + + adc_dev = iio_priv(indio_dev); + adc_dev->regmap = regmap; + adc_dev->dev = dev; + + adc_dev->chip_info = device_get_match_data(dev); + if (!adc_dev->chip_info) + return -EINVAL; + + mutex_init(&adc_dev->lock); + + mt6359_auxadc_reset(adc_dev); + + indio_dev->name = adc_dev->chip_info->model_name; + indio_dev->info = &mt6359_auxadc_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adc_dev->chip_info->channels; + indio_dev->num_channels = adc_dev->chip_info->num_channels; + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, "failed to register iio device\n"); + + return 0; +} + +static const struct of_device_id mt6359_auxadc_of_match[] = { + { .compatible = "mediatek,mt6357-auxadc", .data = &mt6357_chip_info }, + { .compatible = "mediatek,mt6358-auxadc", .data = &mt6358_chip_info }, + { .compatible = "mediatek,mt6359-auxadc", .data = &mt6359_chip_info }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mt6359_auxadc_of_match); + +static struct platform_driver mt6359_auxadc_driver = { + .driver = { + .name = "mt6359-auxadc", + .of_match_table = mt6359_auxadc_of_match, + }, + .probe = mt6359_auxadc_probe, +}; +module_platform_driver(mt6359_auxadc_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_DESCRIPTION("MediaTek MT6359 PMIC AUXADC Driver"); diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index d9e1696df7ae..600151a62f1f 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -532,7 +532,7 @@ static int nau7802_probe(struct i2c_client *client) } static const struct i2c_device_id nau7802_i2c_id[] = { - { "nau7802", 0 }, + { "nau7802" }, { } }; MODULE_DEVICE_TABLE(i2c, nau7802_i2c_id); diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c index 456f12faa348..ae24a27805ab 100644 --- a/drivers/iio/adc/pac1934.c +++ b/drivers/iio/adc/pac1934.c @@ -227,11 +227,6 @@ struct pac1934_features { const char *name; }; -struct samp_rate_mapping { - u16 samp_rate; - u8 shift2value; -}; - static const unsigned int samp_rate_map_tbl[] = { [PAC1934_SAMP_1024SPS] = 1024, [PAC1934_SAMP_256SPS] = 256, diff --git a/drivers/iio/adc/qcom-spmi-rradc.c b/drivers/iio/adc/qcom-spmi-rradc.c index 56a713766954..1402df68dd52 100644 --- a/drivers/iio/adc/qcom-spmi-rradc.c +++ b/drivers/iio/adc/qcom-spmi-rradc.c @@ -358,15 +358,15 @@ static int rradc_enable_continuous_mode(struct rradc_chip *chip) int ret; /* Clear channel log */ - ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_LOG, - RR_ADC_LOG_CLR_CTRL, RR_ADC_LOG_CLR_CTRL); + ret = regmap_set_bits(chip->regmap, chip->base + RR_ADC_LOG, + RR_ADC_LOG_CLR_CTRL); if (ret < 0) { dev_err(chip->dev, "log ctrl update to clear failed:%d\n", ret); return ret; } - ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_LOG, - RR_ADC_LOG_CLR_CTRL, 0); + ret = regmap_clear_bits(chip->regmap, chip->base + RR_ADC_LOG, + RR_ADC_LOG_CLR_CTRL); if (ret < 0) { dev_err(chip->dev, "log ctrl update to not clear failed:%d\n", ret); @@ -374,9 +374,8 @@ static int rradc_enable_continuous_mode(struct rradc_chip *chip) } /* Switch to continuous mode */ - ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_CTL, - RR_ADC_CTL_CONTINUOUS_SEL, - RR_ADC_CTL_CONTINUOUS_SEL); + ret = regmap_set_bits(chip->regmap, chip->base + RR_ADC_CTL, + RR_ADC_CTL_CONTINUOUS_SEL); if (ret < 0) dev_err(chip->dev, "Update to continuous mode failed:%d\n", ret); @@ -389,8 +388,8 @@ static int rradc_disable_continuous_mode(struct rradc_chip *chip) int ret; /* Switch to non continuous mode */ - ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_CTL, - RR_ADC_CTL_CONTINUOUS_SEL, 0); + ret = regmap_clear_bits(chip->regmap, chip->base + RR_ADC_CTL, + RR_ADC_CTL_CONTINUOUS_SEL); if (ret < 0) dev_err(chip->dev, "Update to non-continuous mode failed:%d\n", ret); @@ -434,8 +433,8 @@ static int rradc_read_status_in_cont_mode(struct rradc_chip *chip, return -EINVAL; } - ret = regmap_update_bits(chip->regmap, chip->base + chan->trigger_addr, - chan->trigger_mask, chan->trigger_mask); + ret = regmap_set_bits(chip->regmap, chip->base + chan->trigger_addr, + chan->trigger_mask); if (ret < 0) { dev_err(chip->dev, "Failed to apply trigger for channel '%s' ret=%d\n", @@ -469,8 +468,8 @@ static int rradc_read_status_in_cont_mode(struct rradc_chip *chip, rradc_disable_continuous_mode(chip); disable_trigger: - regmap_update_bits(chip->regmap, chip->base + chan->trigger_addr, - chan->trigger_mask, 0); + regmap_clear_bits(chip->regmap, chip->base + chan->trigger_addr, + chan->trigger_mask); return ret; } @@ -481,17 +480,16 @@ static int rradc_prepare_batt_id_conversion(struct rradc_chip *chip, { int ret; - ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_CTRL, - RR_ADC_BATT_ID_CTRL_CHANNEL_CONV, - RR_ADC_BATT_ID_CTRL_CHANNEL_CONV); + ret = regmap_set_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_CTRL, + RR_ADC_BATT_ID_CTRL_CHANNEL_CONV); if (ret < 0) { dev_err(chip->dev, "Enabling BATT ID channel failed:%d\n", ret); return ret; } - ret = regmap_update_bits(chip->regmap, - chip->base + RR_ADC_BATT_ID_TRIGGER, - RR_ADC_TRIGGER_CTL, RR_ADC_TRIGGER_CTL); + ret = regmap_set_bits(chip->regmap, + chip->base + RR_ADC_BATT_ID_TRIGGER, + RR_ADC_TRIGGER_CTL); if (ret < 0) { dev_err(chip->dev, "BATT_ID trigger set failed:%d\n", ret); goto out_disable_batt_id; @@ -500,12 +498,12 @@ static int rradc_prepare_batt_id_conversion(struct rradc_chip *chip, ret = rradc_read_status_in_cont_mode(chip, chan_address); /* Reset registers back to default values */ - regmap_update_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_TRIGGER, - RR_ADC_TRIGGER_CTL, 0); + regmap_clear_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_TRIGGER, + RR_ADC_TRIGGER_CTL); out_disable_batt_id: - regmap_update_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_CTRL, - RR_ADC_BATT_ID_CTRL_CHANNEL_CONV, 0); + regmap_clear_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_CTRL, + RR_ADC_BATT_ID_CTRL_CHANNEL_CONV); return ret; } @@ -965,9 +963,9 @@ static int rradc_probe(struct platform_device *pdev) if (batt_id_delay >= 0) { batt_id_delay = FIELD_PREP(BATT_ID_SETTLE_MASK, batt_id_delay); - ret = regmap_update_bits(chip->regmap, - chip->base + RR_ADC_BATT_ID_CFG, - batt_id_delay, batt_id_delay); + ret = regmap_set_bits(chip->regmap, + chip->base + RR_ADC_BATT_ID_CFG, + batt_id_delay); if (ret < 0) { dev_err(chip->dev, "BATT_ID settling time config failed:%d\n", diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c index 6bf32907f01d..ce5f3011fe00 100644 --- a/drivers/iio/adc/rn5t618-adc.c +++ b/drivers/iio/adc/rn5t618-adc.c @@ -137,9 +137,8 @@ static int rn5t618_adc_read(struct iio_dev *iio_dev, init_completion(&adc->conv_completion); /* single conversion */ - ret = regmap_update_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, - RN5T618_ADCCNT3_GODONE, - RN5T618_ADCCNT3_GODONE); + ret = regmap_set_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, + RN5T618_ADCCNT3_GODONE); if (ret < 0) return ret; diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index b4a2e057d80f..2535c2c3e60b 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -508,13 +508,13 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, } } - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, - SC27XX_ADC_EN, SC27XX_ADC_EN); + ret = regmap_set_bits(data->regmap, data->base + SC27XX_ADC_CTL, + SC27XX_ADC_EN); if (ret) goto regulator_restore; - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, - SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); + ret = regmap_set_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, + SC27XX_ADC_IRQ_CLR); if (ret) goto disable_adc; @@ -537,8 +537,8 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto disable_adc; - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, - SC27XX_ADC_CHN_RUN, SC27XX_ADC_CHN_RUN); + ret = regmap_set_bits(data->regmap, data->base + SC27XX_ADC_CTL, + SC27XX_ADC_CHN_RUN); if (ret) goto disable_adc; @@ -559,8 +559,8 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, value &= SC27XX_ADC_DATA_MASK; disable_adc: - regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, - SC27XX_ADC_EN, 0); + regmap_clear_bits(data->regmap, data->base + SC27XX_ADC_CTL, + SC27XX_ADC_EN); regulator_restore: if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) { ret_volref = regulator_set_voltage(data->volref, @@ -765,15 +765,14 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data) { int ret; - ret = regmap_update_bits(data->regmap, data->var_data->module_en, - SC27XX_MODULE_ADC_EN, SC27XX_MODULE_ADC_EN); + ret = regmap_set_bits(data->regmap, data->var_data->module_en, + SC27XX_MODULE_ADC_EN); if (ret) return ret; /* Enable ADC work clock and controller clock */ - ret = regmap_update_bits(data->regmap, data->var_data->clk_en, - SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, - SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN); + ret = regmap_set_bits(data->regmap, data->var_data->clk_en, + SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN); if (ret) goto disable_adc; @@ -789,11 +788,11 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data) return 0; disable_clk: - regmap_update_bits(data->regmap, data->var_data->clk_en, - SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); + regmap_clear_bits(data->regmap, data->var_data->clk_en, + SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN); disable_adc: - regmap_update_bits(data->regmap, data->var_data->module_en, - SC27XX_MODULE_ADC_EN, 0); + regmap_clear_bits(data->regmap, data->var_data->module_en, + SC27XX_MODULE_ADC_EN); return ret; } @@ -803,11 +802,11 @@ static void sc27xx_adc_disable(void *_data) struct sc27xx_adc_data *data = _data; /* Disable ADC work clock and controller clock */ - regmap_update_bits(data->regmap, data->var_data->clk_en, - SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); + regmap_clear_bits(data->regmap, data->var_data->clk_en, + SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN); - regmap_update_bits(data->regmap, data->var_data->module_en, - SC27XX_MODULE_ADC_EN, 0); + regmap_clear_bits(data->regmap, data->var_data->module_en, + SC27XX_MODULE_ADC_EN); } static const struct sc27xx_adc_variant_data sc2731_data = { diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 9a47d2c87f05..fabd654245f5 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -759,8 +759,7 @@ static int stm32_dfsdm_start_conv(struct iio_dev *indio_dev, return 0; filter_unconfigure: - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_CFG_MASK, 0); + regmap_clear_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK); stop_channels: stm32_dfsdm_stop_channel(indio_dev); @@ -774,8 +773,7 @@ static void stm32_dfsdm_stop_conv(struct iio_dev *indio_dev) stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id); - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_CFG_MASK, 0); + regmap_clear_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK); stm32_dfsdm_stop_channel(indio_dev); } @@ -951,16 +949,14 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) if (adc->nconv == 1 && !indio_dev->trig) { /* Enable regular DMA transfer*/ - ret = regmap_update_bits(adc->dfsdm->regmap, - DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK, - DFSDM_CR1_RDMAEN_MASK); + ret = regmap_set_bits(adc->dfsdm->regmap, + DFSDM_CR1(adc->fl_id), + DFSDM_CR1_RDMAEN_MASK); } else { /* Enable injected DMA transfer*/ - ret = regmap_update_bits(adc->dfsdm->regmap, - DFSDM_CR1(adc->fl_id), - DFSDM_CR1_JDMAEN_MASK, - DFSDM_CR1_JDMAEN_MASK); + ret = regmap_set_bits(adc->dfsdm->regmap, + DFSDM_CR1(adc->fl_id), + DFSDM_CR1_JDMAEN_MASK); } if (ret < 0) @@ -981,8 +977,8 @@ static void stm32_dfsdm_adc_dma_stop(struct iio_dev *indio_dev) if (!adc->dma_chan) return; - regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK | DFSDM_CR1_JDMAEN_MASK, 0); + regmap_clear_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), + DFSDM_CR1_RDMAEN_MASK | DFSDM_CR1_JDMAEN_MASK); dmaengine_terminate_all(adc->dma_chan); } @@ -1305,9 +1301,8 @@ static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) if (status & DFSDM_ISR_ROVRF_MASK) { if (int_en & DFSDM_CR2_ROVRIE_MASK) dev_warn(&indio_dev->dev, "Overrun detected\n"); - regmap_update_bits(regmap, DFSDM_ICR(adc->fl_id), - DFSDM_ICR_CLRROVRF_MASK, - DFSDM_ICR_CLRROVRF_MASK); + regmap_set_bits(regmap, DFSDM_ICR(adc->fl_id), + DFSDM_ICR_CLRROVRF_MASK); } return IRQ_HANDLED; diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c index 69fcbbc7e418..9758ac801310 100644 --- a/drivers/iio/adc/ti-adc108s102.c +++ b/drivers/iio/adc/ti-adc108s102.c @@ -58,7 +58,6 @@ struct adc108s102_state { struct spi_device *spi; - struct regulator *reg; u32 va_millivolt; /* SPI transfer used by triggered buffer handler*/ struct spi_transfer ring_xfer; @@ -216,11 +215,6 @@ static const struct iio_info adc108s102_info = { .update_scan_mode = &adc108s102_update_scan_mode, }; -static void adc108s102_reg_disable(void *reg) -{ - regulator_disable(reg); -} - static int adc108s102_probe(struct spi_device *spi) { struct adc108s102_state *st; @@ -236,25 +230,9 @@ static int adc108s102_probe(struct spi_device *spi) if (ACPI_COMPANION(&spi->dev)) { st->va_millivolt = ADC108S102_VA_MV_ACPI_DEFAULT; } else { - st->reg = devm_regulator_get(&spi->dev, "vref"); - if (IS_ERR(st->reg)) - return PTR_ERR(st->reg); - - ret = regulator_enable(st->reg); - if (ret < 0) { - dev_err(&spi->dev, "Cannot enable vref regulator\n"); - return ret; - } - ret = devm_add_action_or_reset(&spi->dev, adc108s102_reg_disable, - st->reg); - if (ret) - return ret; - - ret = regulator_get_voltage(st->reg); - if (ret < 0) { - dev_err(&spi->dev, "vref get voltage failed\n"); - return ret; - } + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, "failed get vref voltage\n"); st->va_millivolt = ret / 1000; } diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c index b789891dcf49..f7c78d0dd449 100644 --- a/drivers/iio/adc/ti-adc161s626.c +++ b/drivers/iio/adc/ti-adc161s626.c @@ -137,17 +137,13 @@ static int ti_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - ret = ti_adc_read_measurement(data, chan, val); - iio_device_release_direct_mode(indio_dev); - - if (ret) - return ret; - - return IIO_VAL_INT; + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = ti_adc_read_measurement(data, chan, val); + if (ret) + return ret; + return IIO_VAL_INT; + } + unreachable(); case IIO_CHAN_INFO_SCALE: ret = regulator_get_voltage(data->ref); if (ret < 0) diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c new file mode 100644 index 000000000000..630f5d5f9a60 --- /dev/null +++ b/drivers/iio/adc/ti-ads1119.c @@ -0,0 +1,825 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Texas Instruments ADS1119 ADC driver. + * + * Copyright 2024 Toradex + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ADS1119_CMD_RESET 0x06 +#define ADS1119_CMD_POWERDOWN 0x02 +#define ADS1119_CMD_START_SYNC 0x08 +#define ADS1119_CMD_RDATA 0x10 +#define ADS1119_CMD_RREG_CONFIG 0x20 +#define ADS1119_CMD_RREG_STATUS 0x24 +#define ADS1119_CMD_WREG 0x40 + +#define ADS1119_CMD_RREG(reg) (0x20 | (reg) << 2) + +/* Config register */ +#define ADS1119_REG_CONFIG 0x00 +#define ADS1119_CONFIG_VREF_FIELD BIT(0) +#define ADS1119_CONFIG_CM_FIELD BIT(1) +#define ADS1119_CONFIG_DR_FIELD GENMASK(3, 2) +#define ADS1119_CONFIG_GAIN_FIELD BIT(4) +#define ADS1119_CONFIG_MUX_FIELD GENMASK(7, 5) + +#define ADS1119_VREF_INTERNAL 0 +#define ADS1119_VREF_EXTERNAL 1 +#define ADS1119_VREF_INTERNAL_VAL 2048000 + +#define ADS1119_CM_SINGLE 0 +#define ADS1119_CM_CONTINUOUS 1 + +#define ADS1119_DR_20_SPS 0 +#define ADS1119_DR_90_SPS 1 +#define ADS1119_DR_330_SPS 2 +#define ADS1119_DR_1000_SPS 3 + +#define ADS1119_GAIN_1 0 +#define ADS1119_GAIN_4 1 + +#define ADS1119_MUX_AIN0_AIN1 0 +#define ADS1119_MUX_AIN2_AIN3 1 +#define ADS1119_MUX_AIN1_AIN2 2 +#define ADS1119_MUX_AIN0 3 +#define ADS1119_MUX_AIN1 4 +#define ADS1119_MUX_AIN2 5 +#define ADS1119_MUX_AIN3 6 +#define ADS1119_MUX_SHORTED 7 + +/* Status register */ +#define ADS1119_REG_STATUS 0x01 +#define ADS1119_STATUS_DRDY_FIELD BIT(7) + +#define ADS1119_DEFAULT_GAIN 1 +#define ADS1119_DEFAULT_DATARATE 20 + +#define ADS1119_SUSPEND_DELAY 2000 + +/* Timeout based on the minimum sample rate of 20 SPS (50000us) */ +#define ADS1119_MAX_DRDY_TIMEOUT 85000 + +#define ADS1119_MAX_CHANNELS 7 +#define ADS1119_MAX_SINGLE_CHANNELS 4 + +struct ads1119_channel_config { + int gain; + int datarate; + int mux; +}; + +struct ads1119_state { + struct completion completion; + struct i2c_client *client; + struct gpio_desc *reset_gpio; + struct iio_trigger *trig; + struct ads1119_channel_config *channels_cfg; + unsigned int num_channels_cfg; + unsigned int cached_config; + int vref_uV; +}; + +static const char * const ads1119_power_supplies[] = { + "avdd", "dvdd" +}; + +static const int ads1119_available_datarates[] = { + 20, 90, 330, 1000, +}; + +static const int ads1119_available_gains[] = { + 1, 1, + 1, 4, +}; + +static int ads1119_upd_cfg_reg(struct ads1119_state *st, unsigned int fields, + unsigned int val) +{ + unsigned int config = st->cached_config; + int ret; + + config &= ~fields; + config |= val; + + ret = i2c_smbus_write_byte_data(st->client, ADS1119_CMD_WREG, config); + if (ret) + return ret; + + st->cached_config = config; + + return 0; +} + +static bool ads1119_data_ready(struct ads1119_state *st) +{ + int status; + + status = i2c_smbus_read_byte_data(st->client, ADS1119_CMD_RREG_STATUS); + if (status < 0) + return false; + + return FIELD_GET(ADS1119_STATUS_DRDY_FIELD, status); +} + +static int ads1119_reset(struct ads1119_state *st) +{ + st->cached_config = 0; + + if (!st->reset_gpio) + return i2c_smbus_write_byte(st->client, ADS1119_CMD_RESET); + + gpiod_set_value_cansleep(st->reset_gpio, 1); + udelay(1); + gpiod_set_value_cansleep(st->reset_gpio, 0); + udelay(1); + + return 0; +} + +static int ads1119_set_conv_mode(struct ads1119_state *st, bool continuous) +{ + unsigned int mode; + + if (continuous) + mode = ADS1119_CM_CONTINUOUS; + else + mode = ADS1119_CM_SINGLE; + + return ads1119_upd_cfg_reg(st, ADS1119_CONFIG_CM_FIELD, + FIELD_PREP(ADS1119_CONFIG_CM_FIELD, mode)); +} + +static int ads1119_get_hw_gain(int gain) +{ + if (gain == 4) + return ADS1119_GAIN_4; + else + return ADS1119_GAIN_1; +} + +static int ads1119_get_hw_datarate(int datarate) +{ + switch (datarate) { + case 90: + return ADS1119_DR_90_SPS; + case 330: + return ADS1119_DR_330_SPS; + case 1000: + return ADS1119_DR_1000_SPS; + case 20: + default: + return ADS1119_DR_20_SPS; + } +} + +static int ads1119_configure_channel(struct ads1119_state *st, int mux, + int gain, int datarate) +{ + int ret; + + ret = ads1119_upd_cfg_reg(st, ADS1119_CONFIG_MUX_FIELD, + FIELD_PREP(ADS1119_CONFIG_MUX_FIELD, mux)); + if (ret) + return ret; + + ret = ads1119_upd_cfg_reg(st, ADS1119_CONFIG_GAIN_FIELD, + FIELD_PREP(ADS1119_CONFIG_GAIN_FIELD, + ads1119_get_hw_gain(gain))); + if (ret) + return ret; + + return ads1119_upd_cfg_reg(st, ADS1119_CONFIG_DR_FIELD, + FIELD_PREP(ADS1119_CONFIG_DR_FIELD, + ads1119_get_hw_datarate(datarate))); +} + +static int ads1119_poll_data_ready(struct ads1119_state *st, + struct iio_chan_spec const *chan) +{ + unsigned int datarate = st->channels_cfg[chan->address].datarate; + unsigned long wait_time; + bool data_ready; + + /* Poll 5 times more than the data rate */ + wait_time = DIV_ROUND_CLOSEST(MICRO, 5 * datarate); + + return read_poll_timeout(ads1119_data_ready, data_ready, + data_ready, wait_time, + ADS1119_MAX_DRDY_TIMEOUT, false, st); +} + +static int ads1119_read_data(struct ads1119_state *st, + struct iio_chan_spec const *chan, + unsigned int *val) +{ + unsigned int timeout; + int ret = 0; + + timeout = msecs_to_jiffies(ADS1119_MAX_DRDY_TIMEOUT); + + if (!st->client->irq) { + ret = ads1119_poll_data_ready(st, chan); + if (ret) + return ret; + } else if (!wait_for_completion_timeout(&st->completion, timeout)) { + return -ETIMEDOUT; + } + + ret = i2c_smbus_read_word_swapped(st->client, ADS1119_CMD_RDATA); + if (ret < 0) + return ret; + + *val = ret; + + return 0; +} + +static int ads1119_single_conversion(struct ads1119_state *st, + struct iio_chan_spec const *chan, + int *val, + bool calib_offset) +{ + struct device *dev = &st->client->dev; + int mux = st->channels_cfg[chan->address].mux; + int gain = st->channels_cfg[chan->address].gain; + int datarate = st->channels_cfg[chan->address].datarate; + unsigned int sample; + int ret; + + if (calib_offset) + mux = ADS1119_MUX_SHORTED; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + goto pdown; + + ret = ads1119_configure_channel(st, mux, gain, datarate); + if (ret) + goto pdown; + + ret = i2c_smbus_write_byte(st->client, ADS1119_CMD_START_SYNC); + if (ret) + goto pdown; + + ret = ads1119_read_data(st, chan, &sample); + if (ret) + goto pdown; + + *val = sign_extend32(sample, chan->scan_type.realbits - 1); + ret = IIO_VAL_INT; +pdown: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int ads1119_validate_datarate(struct ads1119_state *st, int datarate) +{ + switch (datarate) { + case 20: + case 90: + case 330: + case 1000: + return datarate; + default: + return -EINVAL; + } +} + +static int ads1119_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *type = IIO_VAL_FRACTIONAL; + *vals = ads1119_available_gains; + *length = ARRAY_SIZE(ads1119_available_gains); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *type = IIO_VAL_INT; + *vals = ads1119_available_datarates; + *length = ARRAY_SIZE(ads1119_available_datarates); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int ads1119_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct ads1119_state *st = iio_priv(indio_dev); + unsigned int index = chan->address; + + if (index >= st->num_channels_cfg) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) + return ads1119_single_conversion(st, chan, val, false); + unreachable(); + case IIO_CHAN_INFO_OFFSET: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) + return ads1119_single_conversion(st, chan, val, true); + unreachable(); + case IIO_CHAN_INFO_SCALE: + *val = st->vref_uV / 1000; + *val /= st->channels_cfg[index].gain; + *val2 = chan->scan_type.realbits - 1; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = st->channels_cfg[index].datarate; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ads1119_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct ads1119_state *st = iio_priv(indio_dev); + unsigned int index = chan->address; + int ret; + + if (index >= st->num_channels_cfg) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = MICRO / ((val * MICRO) + val2); + if (ret != 1 && ret != 4) + return -EINVAL; + + st->channels_cfg[index].gain = ret; + return 0; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = ads1119_validate_datarate(st, val); + if (ret < 0) + return ret; + + st->channels_cfg[index].datarate = ret; + return 0; + default: + return -EINVAL; + } +} + +static int ads1119_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned int reg, unsigned int writeval, + unsigned int *readval) +{ + struct ads1119_state *st = iio_priv(indio_dev); + int ret; + + if (reg > ADS1119_REG_STATUS) + return -EINVAL; + + if (readval) { + ret = i2c_smbus_read_byte_data(st->client, + ADS1119_CMD_RREG(reg)); + if (ret < 0) + return ret; + + *readval = ret; + return 0; + } + + if (reg > ADS1119_REG_CONFIG) + return -EINVAL; + + return i2c_smbus_write_byte_data(st->client, ADS1119_CMD_WREG, + writeval); +} + +static const struct iio_info ads1119_info = { + .read_avail = ads1119_read_avail, + .read_raw = ads1119_read_raw, + .write_raw = ads1119_write_raw, + .debugfs_reg_access = ads1119_debugfs_reg_access, +}; + +static int ads1119_triggered_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ads1119_state *st = iio_priv(indio_dev); + struct device *dev = &st->client->dev; + unsigned int index; + int ret; + + index = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + + ret = ads1119_set_conv_mode(st, true); + if (ret) + return ret; + + ret = ads1119_configure_channel(st, + st->channels_cfg[index].mux, + st->channels_cfg[index].gain, + st->channels_cfg[index].datarate); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + return i2c_smbus_write_byte(st->client, ADS1119_CMD_START_SYNC); +} + +static int ads1119_triggered_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ads1119_state *st = iio_priv(indio_dev); + struct device *dev = &st->client->dev; + int ret; + + ret = ads1119_set_conv_mode(st, false); + if (ret) + return ret; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; +} + +static const struct iio_buffer_setup_ops ads1119_buffer_setup_ops = { + .preenable = ads1119_triggered_buffer_preenable, + .postdisable = ads1119_triggered_buffer_postdisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, +}; + +static const struct iio_trigger_ops ads1119_trigger_ops = { + .validate_device = &iio_trigger_validate_own_device, +}; + +static irqreturn_t ads1119_irq_handler(int irq, void *dev_id) +{ + struct iio_dev *indio_dev = dev_id; + struct ads1119_state *st = iio_priv(indio_dev); + + if (iio_buffer_enabled(indio_dev) && iio_trigger_using_own(indio_dev)) + iio_trigger_poll(indio_dev->trig); + else + complete(&st->completion); + + return IRQ_HANDLED; +} + +static irqreturn_t ads1119_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct ads1119_state *st = iio_priv(indio_dev); + struct { + unsigned int sample; + s64 timestamp __aligned(8); + } scan; + unsigned int index; + int ret; + + if (!iio_trigger_using_own(indio_dev)) { + index = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + + ret = ads1119_poll_data_ready(st, &indio_dev->channels[index]); + if (ret) { + dev_err(&st->client->dev, + "Failed to poll data on trigger (%d)\n", ret); + goto done; + } + } + + ret = i2c_smbus_read_word_swapped(st->client, ADS1119_CMD_RDATA); + if (ret < 0) { + dev_err(&st->client->dev, + "Failed to read data on trigger (%d)\n", ret); + goto done; + } + + scan.sample = ret; + + iio_push_to_buffers_with_timestamp(indio_dev, &scan, + iio_get_time_ns(indio_dev)); +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int ads1119_init(struct ads1119_state *st, bool vref_external) +{ + int ret; + + ret = ads1119_reset(st); + if (ret) + return ret; + + if (vref_external) + return ads1119_upd_cfg_reg(st, + ADS1119_CONFIG_VREF_FIELD, + FIELD_PREP(ADS1119_CONFIG_VREF_FIELD, + ADS1119_VREF_EXTERNAL)); + return 0; +} + +static int ads1119_map_analog_inputs_mux(int ain_pos, int ain_neg, + bool differential) +{ + if (ain_pos >= ADS1119_MAX_SINGLE_CHANNELS) + return -EINVAL; + + if (!differential) + return ADS1119_MUX_AIN0 + ain_pos; + + if (ain_pos == 0 && ain_neg == 1) + return ADS1119_MUX_AIN0_AIN1; + else if (ain_pos == 1 && ain_neg == 2) + return ADS1119_MUX_AIN1_AIN2; + else if (ain_pos == 2 && ain_neg == 3) + return ADS1119_MUX_AIN2_AIN3; + + return -EINVAL; +} + +static int ads1119_alloc_and_config_channels(struct iio_dev *indio_dev) +{ + const struct iio_chan_spec ads1119_channel = + (const struct iio_chan_spec) { + .type = IIO_VOLTAGE, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, + }; + const struct iio_chan_spec ads1119_ts = IIO_CHAN_SOFT_TIMESTAMP(0); + struct ads1119_state *st = iio_priv(indio_dev); + struct iio_chan_spec *iio_channels, *chan; + struct device *dev = &st->client->dev; + unsigned int num_channels, i; + bool differential; + u32 ain[2]; + int ret; + + st->num_channels_cfg = device_get_child_node_count(dev); + if (st->num_channels_cfg > ADS1119_MAX_CHANNELS) + return dev_err_probe(dev, -EINVAL, + "Too many channels %d, max is %d\n", + st->num_channels_cfg, + ADS1119_MAX_CHANNELS); + + st->channels_cfg = devm_kcalloc(dev, st->num_channels_cfg, + sizeof(*st->channels_cfg), GFP_KERNEL); + if (!st->channels_cfg) + return -ENOMEM; + + /* Allocate one more iio channel for the timestamp */ + num_channels = st->num_channels_cfg + 1; + iio_channels = devm_kcalloc(dev, num_channels, sizeof(*iio_channels), + GFP_KERNEL); + if (!iio_channels) + return -ENOMEM; + + i = 0; + + device_for_each_child_node_scoped(dev, child) { + chan = &iio_channels[i]; + + differential = fwnode_property_present(child, "diff-channels"); + if (differential) + ret = fwnode_property_read_u32_array(child, + "diff-channels", + ain, 2); + else + ret = fwnode_property_read_u32(child, "single-channel", + &ain[0]); + + if (ret) + return dev_err_probe(dev, ret, + "Failed to get channel property\n"); + + ret = ads1119_map_analog_inputs_mux(ain[0], ain[1], + differential); + if (ret < 0) + return dev_err_probe(dev, ret, + "Invalid channel value\n"); + + st->channels_cfg[i].mux = ret; + st->channels_cfg[i].gain = ADS1119_DEFAULT_GAIN; + st->channels_cfg[i].datarate = ADS1119_DEFAULT_DATARATE; + + *chan = ads1119_channel; + chan->channel = ain[0]; + chan->address = i; + chan->scan_index = i; + + if (differential) { + chan->channel2 = ain[1]; + chan->differential = 1; + } + + dev_dbg(dev, "channel: index %d, mux %d\n", i, + st->channels_cfg[i].mux); + + i++; + } + + iio_channels[i] = ads1119_ts; + iio_channels[i].address = i; + iio_channels[i].scan_index = i; + + indio_dev->channels = iio_channels; + indio_dev->num_channels = num_channels; + + return 0; +} + +static void ads1119_powerdown(void *data) +{ + struct ads1119_state *st = data; + + i2c_smbus_write_byte(st->client, ADS1119_CMD_POWERDOWN); +} + +static int ads1119_probe(struct i2c_client *client) +{ + struct iio_dev *indio_dev; + struct ads1119_state *st; + struct device *dev = &client->dev; + bool vref_external = true; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return dev_err_probe(dev, -ENOMEM, + "Failed to allocate IIO device\n"); + + st = iio_priv(indio_dev); + st->client = client; + + indio_dev->name = "ads1119"; + indio_dev->info = &ads1119_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + i2c_set_clientdata(client, indio_dev); + + ret = devm_regulator_bulk_get_enable(dev, + ARRAY_SIZE(ads1119_power_supplies), + ads1119_power_supplies); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get and enable supplies\n"); + + st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "vref"); + if (st->vref_uV == -ENODEV) { + vref_external = false; + st->vref_uV = ADS1119_VREF_INTERNAL_VAL; + } else if (st->vref_uV < 0) { + return dev_err_probe(dev, st->vref_uV, "Failed to get vref\n"); + } + + st->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(st->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(st->reset_gpio), + "Failed to get reset gpio\n"); + + ret = ads1119_alloc_and_config_channels(indio_dev); + if (ret) + return ret; + + init_completion(&st->completion); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + ads1119_trigger_handler, + &ads1119_buffer_setup_ops); + if (ret) + return dev_err_probe(dev, ret, "Failed to setup IIO buffer\n"); + + if (client->irq > 0) { + ret = devm_request_threaded_irq(dev, client->irq, + ads1119_irq_handler, + NULL, IRQF_TRIGGER_FALLING, + "ads1119", indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to allocate irq\n"); + + st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, + iio_device_id(indio_dev)); + if (!st->trig) + return dev_err_probe(dev, -ENOMEM, + "Failed to allocate IIO trigger\n"); + + st->trig->ops = &ads1119_trigger_ops; + iio_trigger_set_drvdata(st->trig, indio_dev); + + ret = devm_iio_trigger_register(dev, st->trig); + if (ret) + return dev_err_probe(dev, ret, + "Failed to register IIO trigger\n"); + } + + ret = ads1119_init(st, vref_external); + if (ret) + return dev_err_probe(dev, ret, + "Failed to initialize device\n"); + + pm_runtime_set_autosuspend_delay(dev, ADS1119_SUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_set_active(dev); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable pm runtime\n"); + + ret = devm_add_action_or_reset(dev, ads1119_powerdown, st); + if (ret) + return dev_err_probe(dev, ret, + "Failed to add powerdown action\n"); + + return devm_iio_device_register(dev, indio_dev); +} + +static int ads1119_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ads1119_state *st = iio_priv(indio_dev); + + return i2c_smbus_write_byte(st->client, ADS1119_CMD_POWERDOWN); +} + +/* + * The ADS1119 does not require a resume function because it automatically + * powers on after a reset. + * After a power down command, the ADS1119 can still communicate but turns off + * its analog parts. To resume from power down, the device will power up again + * upon receiving a start/sync command. + */ +static DEFINE_RUNTIME_DEV_PM_OPS(ads1119_pm_ops, ads1119_runtime_suspend, + NULL, NULL); + +static const struct of_device_id __maybe_unused ads1119_of_match[] = { + { .compatible = "ti,ads1119" }, + { } +}; +MODULE_DEVICE_TABLE(of, ads1119_of_match); + +static const struct i2c_device_id ads1119_id[] = { + { "ads1119", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ads1119_id); + +static struct i2c_driver ads1119_driver = { + .driver = { + .name = "ads1119", + .of_match_table = ads1119_of_match, + .pm = pm_ptr(&ads1119_pm_ops), + }, + .probe = ads1119_probe, + .id_table = ads1119_id, +}; +module_i2c_driver(ads1119_driver); + +MODULE_AUTHOR("João Paulo Gonçalves "); +MODULE_DESCRIPTION("Texas Instruments ADS1119 ADC Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/ti-ads131e08.c b/drivers/iio/adc/ti-ads131e08.c index cb04a29b3dba..96dd9366f8ff 100644 --- a/drivers/iio/adc/ti-ads131e08.c +++ b/drivers/iio/adc/ti-ads131e08.c @@ -802,9 +802,7 @@ static int ads131e08_probe(struct spi_device *spi) unsigned long adc_clk_ns; int ret; - info = device_get_match_data(&spi->dev); - if (!info) - info = (void *)spi_get_device_id(spi)->driver_data; + info = spi_get_device_match_data(spi); if (!info) { dev_err(&spi->dev, "failed to get match data\n"); return -ENODEV; diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c index afdbd04778a8..4da78302359b 100644 --- a/drivers/iio/adc/ti-ads7924.c +++ b/drivers/iio/adc/ti-ads7924.c @@ -447,7 +447,7 @@ static int ads7924_probe(struct i2c_client *client) } static const struct i2c_device_id ads7924_id[] = { - { "ads7924", 0 }, + { "ads7924" }, {} }; MODULE_DEVICE_TABLE(i2c, ads7924_id); diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 9440a268a78c..7a79f0cebfbf 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -65,7 +65,6 @@ struct ads8688_state { struct mutex lock; const struct ads8688_chip_info *chip_info; struct spi_device *spi; - struct regulator *reg; unsigned int vref_mv; enum ads8688_range range[8]; union { @@ -423,28 +422,16 @@ static int ads8688_probe(struct spi_device *spi) st = iio_priv(indio_dev); - st->reg = devm_regulator_get_optional(&spi->dev, "vref"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); + if (ret < 0 && ret != -ENODEV) + return ret; - ret = regulator_get_voltage(st->reg); - if (ret < 0) - goto err_regulator_disable; - - st->vref_mv = ret / 1000; - } else { - /* Use internal reference */ - st->vref_mv = ADS8688_VREF_MV; - } + st->vref_mv = ret == -ENODEV ? ADS8688_VREF_MV : ret / 1000; st->chip_info = &ads8688_chip_info_tbl[spi_get_device_id(spi)->driver_data]; spi->mode = SPI_MODE_1; - spi_set_drvdata(spi, indio_dev); - st->spi = spi; indio_dev->name = spi_get_device_id(spi)->name; @@ -457,38 +444,13 @@ static int ads8688_probe(struct spi_device *spi) mutex_init(&st->lock); - ret = iio_triggered_buffer_setup(indio_dev, NULL, ads8688_trigger_handler, NULL); - if (ret < 0) { - dev_err(&spi->dev, "iio triggered buffer setup failed\n"); - goto err_regulator_disable; - } + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + ads8688_trigger_handler, NULL); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "iio triggered buffer setup failed\n"); - ret = iio_device_register(indio_dev); - if (ret) - goto err_buffer_cleanup; - - return 0; - -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - -err_regulator_disable: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); - - return ret; -} - -static void ads8688_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ads8688_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ads8688_id[] = { @@ -511,7 +473,6 @@ static struct spi_driver ads8688_driver = { .of_match_table = ads8688_of_match, }, .probe = ads8688_probe, - .remove = ads8688_remove, .id_table = ads8688_id, }; module_spi_driver(ads8688_driver); diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c index 1bbb51a6683c..edcef8f11522 100644 --- a/drivers/iio/adc/ti-tsc2046.c +++ b/drivers/iio/adc/ti-tsc2046.c @@ -804,12 +804,7 @@ static int tsc2046_adc_probe(struct spi_device *spi) return -EINVAL; } - dcfg = device_get_match_data(dev); - if (!dcfg) { - const struct spi_device_id *id = spi_get_device_id(spi); - - dcfg = (const struct tsc2046_adc_dcfg *)id->driver_data; - } + dcfg = spi_get_device_match_data(spi); if (!dcfg) return -EINVAL; diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c index f52abf759260..f051358d6b50 100644 --- a/drivers/iio/adc/xilinx-ams.c +++ b/drivers/iio/adc/xilinx-ams.c @@ -222,7 +222,7 @@ enum ams_ps_pl_seq { #define PL_SEQ(x) (AMS_PS_SEQ_MAX + (x)) #define AMS_CTRL_SEQ_BASE (AMS_PS_SEQ_MAX * 3) -#define AMS_CHAN_TEMP(_scan_index, _addr) { \ +#define AMS_CHAN_TEMP(_scan_index, _addr, _name) { \ .type = IIO_TEMP, \ .indexed = 1, \ .address = (_addr), \ @@ -232,9 +232,10 @@ enum ams_ps_pl_seq { .event_spec = ams_temp_events, \ .scan_index = _scan_index, \ .num_event_specs = ARRAY_SIZE(ams_temp_events), \ + .datasheet_name = _name, \ } -#define AMS_CHAN_VOLTAGE(_scan_index, _addr, _alarm) { \ +#define AMS_CHAN_VOLTAGE(_scan_index, _addr, _alarm, _name) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .address = (_addr), \ @@ -243,21 +244,24 @@ enum ams_ps_pl_seq { .event_spec = (_alarm) ? ams_voltage_events : NULL, \ .scan_index = _scan_index, \ .num_event_specs = (_alarm) ? ARRAY_SIZE(ams_voltage_events) : 0, \ + .datasheet_name = _name, \ } -#define AMS_PS_CHAN_TEMP(_scan_index, _addr) \ - AMS_CHAN_TEMP(PS_SEQ(_scan_index), _addr) -#define AMS_PS_CHAN_VOLTAGE(_scan_index, _addr) \ - AMS_CHAN_VOLTAGE(PS_SEQ(_scan_index), _addr, true) +#define AMS_PS_CHAN_TEMP(_scan_index, _addr, _name) \ + AMS_CHAN_TEMP(PS_SEQ(_scan_index), _addr, _name) +#define AMS_PS_CHAN_VOLTAGE(_scan_index, _addr, _name) \ + AMS_CHAN_VOLTAGE(PS_SEQ(_scan_index), _addr, true, _name) -#define AMS_PL_CHAN_TEMP(_scan_index, _addr) \ - AMS_CHAN_TEMP(PL_SEQ(_scan_index), _addr) -#define AMS_PL_CHAN_VOLTAGE(_scan_index, _addr, _alarm) \ - AMS_CHAN_VOLTAGE(PL_SEQ(_scan_index), _addr, _alarm) +#define AMS_PL_CHAN_TEMP(_scan_index, _addr, _name) \ + AMS_CHAN_TEMP(PL_SEQ(_scan_index), _addr, _name) +#define AMS_PL_CHAN_VOLTAGE(_scan_index, _addr, _alarm, _name) \ + AMS_CHAN_VOLTAGE(PL_SEQ(_scan_index), _addr, _alarm, _name) #define AMS_PL_AUX_CHAN_VOLTAGE(_auxno) \ - AMS_CHAN_VOLTAGE(PL_SEQ(AMS_SEQ(_auxno)), AMS_REG_VAUX(_auxno), false) -#define AMS_CTRL_CHAN_VOLTAGE(_scan_index, _addr) \ - AMS_CHAN_VOLTAGE(PL_SEQ(AMS_SEQ(AMS_SEQ(_scan_index))), _addr, false) + AMS_CHAN_VOLTAGE(PL_SEQ(AMS_SEQ(_auxno)), AMS_REG_VAUX(_auxno), false, \ + "VAUX" #_auxno) +#define AMS_CTRL_CHAN_VOLTAGE(_scan_index, _addr, _name) \ + AMS_CHAN_VOLTAGE(PL_SEQ(AMS_SEQ(AMS_SEQ(_scan_index))), _addr, false, \ + _name) /** * struct ams - This structure contains necessary state for xilinx-ams to operate @@ -505,6 +509,12 @@ static int ams_init_device(struct ams *ams) return 0; } +static int ams_read_label(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, char *label) +{ + return sysfs_emit(label, "%s\n", chan->datasheet_name); +} + static int ams_enable_single_channel(struct ams *ams, unsigned int offset) { u8 channel_num; @@ -1116,37 +1126,37 @@ static const struct iio_event_spec ams_voltage_events[] = { }; static const struct iio_chan_spec ams_ps_channels[] = { - AMS_PS_CHAN_TEMP(AMS_SEQ_TEMP, AMS_TEMP), - AMS_PS_CHAN_TEMP(AMS_SEQ_TEMP_REMOTE, AMS_TEMP_REMOTE), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY1, AMS_SUPPLY1), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY2, AMS_SUPPLY2), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY3, AMS_SUPPLY3), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY4, AMS_SUPPLY4), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY5, AMS_SUPPLY5), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY6, AMS_SUPPLY6), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY7, AMS_SUPPLY7), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY8, AMS_SUPPLY8), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY9, AMS_SUPPLY9), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY10, AMS_SUPPLY10), - AMS_PS_CHAN_VOLTAGE(AMS_SEQ_VCCAMS, AMS_VCCAMS), + AMS_PS_CHAN_TEMP(AMS_SEQ_TEMP, AMS_TEMP, "Temp_LPD"), + AMS_PS_CHAN_TEMP(AMS_SEQ_TEMP_REMOTE, AMS_TEMP_REMOTE, "Temp_FPD"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY1, AMS_SUPPLY1, "VCC_PSINTLP"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY2, AMS_SUPPLY2, "VCC_PSINTFP"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY3, AMS_SUPPLY3, "VCC_PSAUX"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY4, AMS_SUPPLY4, "VCC_PSDDR"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY5, AMS_SUPPLY5, "VCC_PSIO3"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY6, AMS_SUPPLY6, "VCC_PSIO0"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY7, AMS_SUPPLY7, "VCC_PSIO1"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY8, AMS_SUPPLY8, "VCC_PSIO2"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY9, AMS_SUPPLY9, "PS_MGTRAVCC"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY10, AMS_SUPPLY10, "PS_MGTRAVTT"), + AMS_PS_CHAN_VOLTAGE(AMS_SEQ_VCCAMS, AMS_VCCAMS, "VCC_PSADC"), }; static const struct iio_chan_spec ams_pl_channels[] = { - AMS_PL_CHAN_TEMP(AMS_SEQ_TEMP, AMS_TEMP), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY1, AMS_SUPPLY1, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY2, AMS_SUPPLY2, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VREFP, AMS_VREFP, false), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VREFN, AMS_VREFN, false), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY3, AMS_SUPPLY3, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY4, AMS_SUPPLY4, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY5, AMS_SUPPLY5, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY6, AMS_SUPPLY6, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VCCAMS, AMS_VCCAMS, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VP_VN, AMS_VP_VN, false), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY7, AMS_SUPPLY7, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY8, AMS_SUPPLY8, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY9, AMS_SUPPLY9, true), - AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY10, AMS_SUPPLY10, true), + AMS_PL_CHAN_TEMP(AMS_SEQ_TEMP, AMS_TEMP, "Temp_PL"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY1, AMS_SUPPLY1, true, "VCCINT"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY2, AMS_SUPPLY2, true, "VCCAUX"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VREFP, AMS_VREFP, false, "VREFP"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VREFN, AMS_VREFN, false, "VREFN"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY3, AMS_SUPPLY3, true, "VCCBRAM"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY4, AMS_SUPPLY4, true, "VCC_PSINTLP"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY5, AMS_SUPPLY5, true, "VCC_PSINTFP"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY6, AMS_SUPPLY6, true, "VCC_PSAUX"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VCCAMS, AMS_VCCAMS, true, "VCCAMS"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VP_VN, AMS_VP_VN, false, "VP_VN"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY7, AMS_SUPPLY7, true, "VUser0"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY8, AMS_SUPPLY8, true, "VUser1"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY9, AMS_SUPPLY9, true, "VUser2"), + AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY10, AMS_SUPPLY10, true, "VUser3"), AMS_PL_AUX_CHAN_VOLTAGE(0), AMS_PL_AUX_CHAN_VOLTAGE(1), AMS_PL_AUX_CHAN_VOLTAGE(2), @@ -1166,13 +1176,13 @@ static const struct iio_chan_spec ams_pl_channels[] = { }; static const struct iio_chan_spec ams_ctrl_channels[] = { - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCC_PSPLL, AMS_VCC_PSPLL0), - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCC_PSBATT, AMS_VCC_PSPLL3), - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCINT, AMS_VCCINT), - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCBRAM, AMS_VCCBRAM), - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCAUX, AMS_VCCAUX), - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_PSDDRPLL, AMS_PSDDRPLL), - AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_INTDDR, AMS_PSINTFPDDR), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCC_PSPLL, AMS_VCC_PSPLL0, "VCC_PSPLL"), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCC_PSBATT, AMS_VCC_PSPLL3, "VCC_PSBATT"), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCINT, AMS_VCCINT, "VCCINT"), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCBRAM, AMS_VCCBRAM, "VCCBRAM"), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCAUX, AMS_VCCAUX, "VCCAUX"), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_PSDDRPLL, AMS_PSDDRPLL, "VCC_PSDDR_PLL"), + AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_INTDDR, AMS_PSINTFPDDR, "VCC_PSINTFP_DDR"), }; static int ams_get_ext_chan(struct fwnode_handle *chan_node, @@ -1336,6 +1346,7 @@ static int ams_parse_firmware(struct iio_dev *indio_dev) } static const struct iio_info iio_ams_info = { + .read_label = ams_read_label, .read_raw = &ams_read_raw, .read_event_config = &ams_read_event_config, .write_event_config = &ams_write_event_config, @@ -1434,5 +1445,6 @@ static struct platform_driver ams_driver = { }; module_platform_driver(ams_driver); +MODULE_DESCRIPTION("Xilinx AMS driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Xilinx, Inc."); diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c index cd26a16dc0ff..2410d72da49b 100644 --- a/drivers/iio/addac/ad74413r.c +++ b/drivers/iio/addac/ad74413r.c @@ -1365,16 +1365,9 @@ static int ad74413r_probe(struct spi_device *spi) st->spi = spi; st->dev = &spi->dev; - st->chip_info = device_get_match_data(&spi->dev); - if (!st->chip_info) { - const struct spi_device_id *id = spi_get_device_id(spi); - - if (id) - st->chip_info = - (struct ad74413r_chip_info *)id->driver_data; - if (!st->chip_info) - return -EINVAL; - } + st->chip_info = spi_get_device_match_data(spi); + if (!st->chip_info) + return -EINVAL; mutex_init(&st->lock); init_completion(&st->adc_data_completion); diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index 13b1a858969e..647f417a045e 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -4,6 +4,8 @@ * Author: Lars-Peter Clausen */ +#include +#include #include #include #include @@ -14,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -94,13 +98,18 @@ static void iio_buffer_block_release(struct kref *kref) { struct iio_dma_buffer_block *block = container_of(kref, struct iio_dma_buffer_block, kref); + struct iio_dma_buffer_queue *queue = block->queue; - WARN_ON(block->state != IIO_BLOCK_STATE_DEAD); + WARN_ON(block->fileio && block->state != IIO_BLOCK_STATE_DEAD); - dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size), - block->vaddr, block->phys_addr); + if (block->fileio) { + dma_free_coherent(queue->dev, PAGE_ALIGN(block->size), + block->vaddr, block->phys_addr); + } else { + atomic_dec(&queue->num_dmabufs); + } - iio_buffer_put(&block->queue->buffer); + iio_buffer_put(&queue->buffer); kfree(block); } @@ -163,7 +172,7 @@ static struct iio_dma_buffer_queue *iio_buffer_to_queue(struct iio_buffer *buf) } static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( - struct iio_dma_buffer_queue *queue, size_t size) + struct iio_dma_buffer_queue *queue, size_t size, bool fileio) { struct iio_dma_buffer_block *block; @@ -171,13 +180,16 @@ static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( if (!block) return NULL; - block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size), - &block->phys_addr, GFP_KERNEL); - if (!block->vaddr) { - kfree(block); - return NULL; + if (fileio) { + block->vaddr = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size), + &block->phys_addr, GFP_KERNEL); + if (!block->vaddr) { + kfree(block); + return NULL; + } } + block->fileio = fileio; block->size = size; block->state = IIO_BLOCK_STATE_DONE; block->queue = queue; @@ -186,6 +198,9 @@ static struct iio_dma_buffer_block *iio_dma_buffer_alloc_block( iio_buffer_get(&queue->buffer); + if (!fileio) + atomic_inc(&queue->num_dmabufs); + return block; } @@ -218,13 +233,20 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block) { struct iio_dma_buffer_queue *queue = block->queue; unsigned long flags; + bool cookie; + + cookie = dma_fence_begin_signalling(); spin_lock_irqsave(&queue->list_lock, flags); _iio_dma_buffer_block_done(block); spin_unlock_irqrestore(&queue->list_lock, flags); + if (!block->fileio) + iio_buffer_signal_dmabuf_done(block->fence, 0); + iio_buffer_block_put_atomic(block); iio_dma_buffer_queue_wake(queue); + dma_fence_end_signalling(cookie); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_done); @@ -243,17 +265,27 @@ void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue, { struct iio_dma_buffer_block *block, *_block; unsigned long flags; + bool cookie; + + cookie = dma_fence_begin_signalling(); spin_lock_irqsave(&queue->list_lock, flags); list_for_each_entry_safe(block, _block, list, head) { list_del(&block->head); block->bytes_used = 0; _iio_dma_buffer_block_done(block); + + if (!block->fileio) + iio_buffer_signal_dmabuf_done(block->fence, -EINTR); iio_buffer_block_put_atomic(block); } spin_unlock_irqrestore(&queue->list_lock, flags); + if (queue->fileio.enabled) + queue->fileio.enabled = false; + iio_dma_buffer_queue_wake(queue); + dma_fence_end_signalling(cookie); } EXPORT_SYMBOL_GPL(iio_dma_buffer_block_list_abort); @@ -273,6 +305,16 @@ static bool iio_dma_block_reusable(struct iio_dma_buffer_block *block) } } +static bool iio_dma_buffer_can_use_fileio(struct iio_dma_buffer_queue *queue) +{ + /* + * Note that queue->num_dmabufs cannot increase while the queue is + * locked, it can only decrease, so it does not race against + * iio_dma_buffer_alloc_block(). + */ + return queue->fileio.enabled || !atomic_read(&queue->num_dmabufs); +} + /** * iio_dma_buffer_request_update() - DMA buffer request_update callback * @buffer: The buffer which to request an update @@ -299,6 +341,12 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) mutex_lock(&queue->lock); + queue->fileio.enabled = iio_dma_buffer_can_use_fileio(queue); + + /* If DMABUFs were created, disable fileio interface */ + if (!queue->fileio.enabled) + goto out_unlock; + /* Allocations are page aligned */ if (PAGE_ALIGN(queue->fileio.block_size) == PAGE_ALIGN(size)) try_reuse = true; @@ -339,7 +387,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer) } if (!block) { - block = iio_dma_buffer_alloc_block(queue, size); + block = iio_dma_buffer_alloc_block(queue, size, true); if (!block) { ret = -ENOMEM; goto out_unlock; @@ -412,8 +460,12 @@ static void iio_dma_buffer_submit_block(struct iio_dma_buffer_queue *queue, block->state = IIO_BLOCK_STATE_ACTIVE; iio_buffer_block_get(block); + ret = queue->ops->submit(queue, block); if (ret) { + if (!block->fileio) + iio_buffer_signal_dmabuf_done(block->fence, ret); + /* * This is a bit of a problem and there is not much we can do * other then wait for the buffer to be disabled and re-enabled @@ -646,6 +698,110 @@ size_t iio_dma_buffer_usage(struct iio_buffer *buf) } EXPORT_SYMBOL_GPL(iio_dma_buffer_usage); +struct iio_dma_buffer_block * +iio_dma_buffer_attach_dmabuf(struct iio_buffer *buffer, + struct dma_buf_attachment *attach) +{ + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); + struct iio_dma_buffer_block *block; + + guard(mutex)(&queue->lock); + + /* + * If the buffer is enabled and in fileio mode new blocks can't be + * allocated. + */ + if (queue->fileio.enabled) + return ERR_PTR(-EBUSY); + + block = iio_dma_buffer_alloc_block(queue, attach->dmabuf->size, false); + if (!block) + return ERR_PTR(-ENOMEM); + + /* Free memory that might be in use for fileio mode */ + iio_dma_buffer_fileio_free(queue); + + return block; +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_attach_dmabuf); + +void iio_dma_buffer_detach_dmabuf(struct iio_buffer *buffer, + struct iio_dma_buffer_block *block) +{ + block->state = IIO_BLOCK_STATE_DEAD; + iio_buffer_block_put_atomic(block); +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_detach_dmabuf); + +static int iio_dma_can_enqueue_block(struct iio_dma_buffer_block *block) +{ + struct iio_dma_buffer_queue *queue = block->queue; + + /* If in fileio mode buffers can't be enqueued. */ + if (queue->fileio.enabled) + return -EBUSY; + + switch (block->state) { + case IIO_BLOCK_STATE_QUEUED: + return -EPERM; + case IIO_BLOCK_STATE_ACTIVE: + case IIO_BLOCK_STATE_DEAD: + return -EBUSY; + case IIO_BLOCK_STATE_DONE: + break; + } + + return 0; +} + +int iio_dma_buffer_enqueue_dmabuf(struct iio_buffer *buffer, + struct iio_dma_buffer_block *block, + struct dma_fence *fence, + struct sg_table *sgt, + size_t size, bool cyclic) +{ + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); + bool cookie; + int ret; + + WARN_ON(!mutex_is_locked(&queue->lock)); + + cookie = dma_fence_begin_signalling(); + + ret = iio_dma_can_enqueue_block(block); + if (ret < 0) + goto out_end_signalling; + + block->bytes_used = size; + block->cyclic = cyclic; + block->sg_table = sgt; + block->fence = fence; + + iio_dma_buffer_enqueue(queue, block); + +out_end_signalling: + dma_fence_end_signalling(cookie); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_enqueue_dmabuf); + +void iio_dma_buffer_lock_queue(struct iio_buffer *buffer) +{ + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); + + mutex_lock(&queue->lock); +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_lock_queue); + +void iio_dma_buffer_unlock_queue(struct iio_buffer *buffer) +{ + struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer); + + mutex_unlock(&queue->lock); +} +EXPORT_SYMBOL_GPL(iio_dma_buffer_unlock_queue); + /** * iio_dma_buffer_set_bytes_per_datum() - DMA buffer set_bytes_per_datum callback * @buffer: Buffer to set the bytes-per-datum for diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 918f6f8d65b6..12aa1412dfa0 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -65,25 +65,62 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue, iio_buffer_to_dmaengine_buffer(&queue->buffer); struct dma_async_tx_descriptor *desc; enum dma_transfer_direction dma_dir; + struct scatterlist *sgl; + struct dma_vec *vecs; size_t max_size; dma_cookie_t cookie; + size_t len_total; + unsigned int i; + int nents; max_size = min(block->size, dmaengine_buffer->max_size); max_size = round_down(max_size, dmaengine_buffer->align); - if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) { - block->bytes_used = max_size; + if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) dma_dir = DMA_DEV_TO_MEM; - } else { + else dma_dir = DMA_MEM_TO_DEV; + + if (block->sg_table) { + sgl = block->sg_table->sgl; + nents = sg_nents_for_len(sgl, block->bytes_used); + if (nents < 0) + return nents; + + vecs = kmalloc_array(nents, sizeof(*vecs), GFP_ATOMIC); + if (!vecs) + return -ENOMEM; + + len_total = block->bytes_used; + + for (i = 0; i < nents; i++) { + vecs[i].addr = sg_dma_address(sgl); + vecs[i].len = min(sg_dma_len(sgl), len_total); + len_total -= vecs[i].len; + + sgl = sg_next(sgl); + } + + desc = dmaengine_prep_peripheral_dma_vec(dmaengine_buffer->chan, + vecs, nents, dma_dir, + DMA_PREP_INTERRUPT); + kfree(vecs); + } else { + max_size = min(block->size, dmaengine_buffer->max_size); + max_size = round_down(max_size, dmaengine_buffer->align); + + if (queue->buffer.direction == IIO_BUFFER_DIRECTION_IN) + block->bytes_used = max_size; + + if (!block->bytes_used || block->bytes_used > max_size) + return -EINVAL; + + desc = dmaengine_prep_slave_single(dmaengine_buffer->chan, + block->phys_addr, + block->bytes_used, + dma_dir, + DMA_PREP_INTERRUPT); } - - if (!block->bytes_used || block->bytes_used > max_size) - return -EINVAL; - - desc = dmaengine_prep_slave_single(dmaengine_buffer->chan, - block->phys_addr, block->bytes_used, dma_dir, - DMA_PREP_INTERRUPT); if (!desc) return -ENOMEM; @@ -133,6 +170,13 @@ static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = { .space_available = iio_dma_buffer_usage, .release = iio_dmaengine_buffer_release, + .enqueue_dmabuf = iio_dma_buffer_enqueue_dmabuf, + .attach_dmabuf = iio_dma_buffer_attach_dmabuf, + .detach_dmabuf = iio_dma_buffer_detach_dmabuf, + + .lock_queue = iio_dma_buffer_lock_queue, + .unlock_queue = iio_dma_buffer_unlock_queue, + .modes = INDIO_BUFFER_HARDWARE, .flags = INDIO_BUFFER_FLAG_FIXED_WATERMARK, }; diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c index 05b285f0eb22..38034c8bcc04 100644 --- a/drivers/iio/buffer/kfifo_buf.c +++ b/drivers/iio/buffer/kfifo_buf.c @@ -287,4 +287,5 @@ int devm_iio_kfifo_buffer_setup_ext(struct device *dev, } EXPORT_SYMBOL_GPL(devm_iio_kfifo_buffer_setup_ext); +MODULE_DESCRIPTION("Industrial I/O buffering based on kfifo"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 02649ab81b3c..678a6adb9a75 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -76,6 +76,26 @@ config CCS811 Say Y here to build I2C interface support for the AMS CCS811 VOC (Volatile Organic Compounds) sensor +config ENS160 + tristate "ScioSense ENS160 sensor driver" + depends on (I2C || SPI) + select REGMAP + select ENS160_I2C if I2C + select ENS160_SPI if SPI + help + Say yes here to build support for ScioSense ENS160 multi-gas sensor. + + This driver can also be built as a module. If so, the module for I2C + would be called ens160_i2c and ens160_spi for SPI support. + +config ENS160_I2C + tristate + select REGMAP_I2C + +config ENS160_SPI + tristate + select REGMAP_SPI + config IAQCORE tristate "AMS iAQ-Core VOC sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 2f3dee8bb779..4866db06bdc9 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -11,6 +11,9 @@ obj-$(CONFIG_BME680) += bme680_core.o obj-$(CONFIG_BME680_I2C) += bme680_i2c.o obj-$(CONFIG_BME680_SPI) += bme680_spi.o obj-$(CONFIG_CCS811) += ccs811.o +obj-$(CONFIG_ENS160) += ens160_core.o +obj-$(CONFIG_ENS160_I2C) += ens160_i2c.o +obj-$(CONFIG_ENS160_SPI) += ens160_spi.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_PMS7003) += pms7003.o obj-$(CONFIG_SCD30_CORE) += scd30_core.o diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c index 164facac5db6..10156d794092 100644 --- a/drivers/iio/chemical/ams-iaq-core.c +++ b/drivers/iio/chemical/ams-iaq-core.c @@ -24,7 +24,7 @@ struct ams_iaqcore_reading { u8 status; __be32 resistance; __be16 voc_ppb; -} __attribute__((__packed__)); +} __packed; struct ams_iaqcore_data { struct i2c_client *client; @@ -163,7 +163,7 @@ static int ams_iaqcore_probe(struct i2c_client *client) } static const struct i2c_device_id ams_iaqcore_id[] = { - { "ams-iaq-core", 0 }, + { "ams-iaq-core" }, { } }; MODULE_DEVICE_TABLE(i2c, ams_iaqcore_id); diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c index 1c7076cf91ca..7c4224d75955 100644 --- a/drivers/iio/chemical/bme680_i2c.c +++ b/drivers/iio/chemical/bme680_i2c.c @@ -36,8 +36,8 @@ static int bme680_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bme680_i2c_id[] = { - {"bme680", 0}, - {}, + { "bme680" }, + {} }; MODULE_DEVICE_TABLE(i2c, bme680_i2c_id); diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 87741f155c32..17d1bc518bf2 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -551,7 +551,7 @@ static void ccs811_remove(struct i2c_client *client) } static const struct i2c_device_id ccs811_id[] = { - {"ccs811", 0}, + { "ccs811" }, { } }; MODULE_DEVICE_TABLE(i2c, ccs811_id); diff --git a/drivers/iio/chemical/ens160.h b/drivers/iio/chemical/ens160.h new file mode 100644 index 000000000000..f9f0575ce55d --- /dev/null +++ b/drivers/iio/chemical/ens160.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef ENS160_H_ +#define ENS160_H_ + +int devm_ens160_core_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name); + +extern const struct dev_pm_ops ens160_pm_ops; + +#endif diff --git a/drivers/iio/chemical/ens160_core.c b/drivers/iio/chemical/ens160_core.c new file mode 100644 index 000000000000..c1aa3b498d3b --- /dev/null +++ b/drivers/iio/chemical/ens160_core.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ScioSense ENS160 multi-gas sensor driver + * + * Copyright (c) 2024 Gustavo Silva + * + * Datasheet: + * https://www.sciosense.com/wp-content/uploads/2023/12/ENS160-Datasheet.pdf + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ens160.h" + +#define ENS160_PART_ID 0x160 + +#define ENS160_BOOTING_TIME_MS 10U + +#define ENS160_REG_PART_ID 0x00 + +#define ENS160_REG_OPMODE 0x10 + +#define ENS160_REG_CONFIG 0x11 +#define ENS160_REG_CONFIG_INTEN BIT(0) +#define ENS160_REG_CONFIG_INTDAT BIT(1) +#define ENS160_REG_CONFIG_INT_CFG BIT(5) + +#define ENS160_REG_MODE_DEEP_SLEEP 0x00 +#define ENS160_REG_MODE_IDLE 0x01 +#define ENS160_REG_MODE_STANDARD 0x02 +#define ENS160_REG_MODE_RESET 0xF0 + +#define ENS160_REG_COMMAND 0x12 +#define ENS160_REG_COMMAND_GET_APPVER 0x0E +#define ENS160_REG_COMMAND_CLRGPR 0xCC + +#define ENS160_REG_TEMP_IN 0x13 +#define ENS160_REG_RH_IN 0x15 +#define ENS160_REG_DEVICE_STATUS 0x20 +#define ENS160_REG_DATA_AQI 0x21 +#define ENS160_REG_DATA_TVOC 0x22 +#define ENS160_REG_DATA_ECO2 0x24 +#define ENS160_REG_DATA_T 0x30 +#define ENS160_REG_DATA_RH 0x32 +#define ENS160_REG_GPR_READ4 0x4C + +#define ENS160_STATUS_VALIDITY_FLAG GENMASK(3, 2) + +#define ENS160_STATUS_NORMAL 0x00 + +struct ens160_data { + struct regmap *regmap; + /* Protect reads from the sensor */ + struct mutex mutex; + struct { + __le16 chans[2]; + s64 timestamp __aligned(8); + } scan __aligned(IIO_DMA_MINALIGN); + u8 fw_version[3]; + __le16 buf; +}; + +static const struct iio_chan_spec ens160_channels[] = { + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_VOC, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .address = ENS160_REG_DATA_TVOC, + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + }, + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_CO2, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .address = ENS160_REG_DATA_ECO2, + .scan_index = 1, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static int ens160_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ens160_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + guard(mutex)(&data->mutex); + ret = regmap_bulk_read(data->regmap, chan->address, + &data->buf, sizeof(data->buf)); + if (ret) + return ret; + *val = le16_to_cpu(data->buf); + return IIO_VAL_INT; + } + unreachable(); + case IIO_CHAN_INFO_SCALE: + switch (chan->channel2) { + case IIO_MOD_CO2: + /* The sensor reads CO2 data as ppm */ + *val = 0; + *val2 = 100; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MOD_VOC: + /* The sensor reads VOC data as ppb */ + *val = 0; + *val2 = 100; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int ens160_set_mode(struct ens160_data *data, u8 mode) +{ + int ret; + + ret = regmap_write(data->regmap, ENS160_REG_OPMODE, mode); + if (ret) + return ret; + + msleep(ENS160_BOOTING_TIME_MS); + + return 0; +} + +static void ens160_set_idle(void *data) +{ + ens160_set_mode(data, ENS160_REG_MODE_IDLE); +} + +static int ens160_chip_init(struct ens160_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + unsigned int status; + int ret; + + ret = ens160_set_mode(data, ENS160_REG_MODE_RESET); + if (ret) + return ret; + + ret = regmap_bulk_read(data->regmap, ENS160_REG_PART_ID, &data->buf, + sizeof(data->buf)); + if (ret) + return ret; + + if (le16_to_cpu(data->buf) != ENS160_PART_ID) + return -ENODEV; + + ret = ens160_set_mode(data, ENS160_REG_MODE_IDLE); + if (ret) + return ret; + + ret = regmap_write(data->regmap, ENS160_REG_COMMAND, + ENS160_REG_COMMAND_CLRGPR); + if (ret) + return ret; + + ret = regmap_write(data->regmap, ENS160_REG_COMMAND, + ENS160_REG_COMMAND_GET_APPVER); + if (ret) + return ret; + + ret = regmap_bulk_read(data->regmap, ENS160_REG_GPR_READ4, + data->fw_version, sizeof(data->fw_version)); + if (ret) + return ret; + + dev_info(dev, "firmware version: %u.%u.%u\n", data->fw_version[2], + data->fw_version[1], data->fw_version[0]); + + ret = ens160_set_mode(data, ENS160_REG_MODE_STANDARD); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, ens160_set_idle, data); + if (ret) + return ret; + + ret = regmap_read(data->regmap, ENS160_REG_DEVICE_STATUS, &status); + if (ret) + return ret; + + if (FIELD_GET(ENS160_STATUS_VALIDITY_FLAG, status) + != ENS160_STATUS_NORMAL) + return -EINVAL; + + return 0; +} + +static const struct iio_info ens160_info = { + .read_raw = ens160_read_raw, +}; + +static int ens160_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ens160_data *data = iio_priv(indio_dev); + + return ens160_set_mode(data, ENS160_REG_MODE_DEEP_SLEEP); +} + +static int ens160_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ens160_data *data = iio_priv(indio_dev); + int ret; + + ret = ens160_set_mode(data, ENS160_REG_MODE_IDLE); + if (ret) + return ret; + + return ens160_set_mode(data, ENS160_REG_MODE_STANDARD); +} +EXPORT_NS_SIMPLE_DEV_PM_OPS(ens160_pm_ops, ens160_suspend, ens160_resume, + IIO_ENS160); + +static irqreturn_t ens160_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ens160_data *data = iio_priv(indio_dev); + int ret; + + guard(mutex)(&data->mutex); + + ret = regmap_bulk_read(data->regmap, ENS160_REG_DATA_TVOC, + data->scan.chans, sizeof(data->scan.chans)); + if (ret) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, + pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ens160_set_trigger_state(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct ens160_data *data = iio_priv(indio_dev); + unsigned int int_bits = ENS160_REG_CONFIG_INTEN | + ENS160_REG_CONFIG_INTDAT | + ENS160_REG_CONFIG_INT_CFG; + + if (state) + return regmap_set_bits(data->regmap, ENS160_REG_CONFIG, + int_bits); + else + return regmap_clear_bits(data->regmap, ENS160_REG_CONFIG, + int_bits); +} + +static const struct iio_trigger_ops ens160_trigger_ops = { + .set_trigger_state = ens160_set_trigger_state, + .validate_device = iio_trigger_validate_own_device, +}; + +static int ens160_setup_trigger(struct iio_dev *indio_dev, int irq) +{ + struct device *dev = indio_dev->dev.parent; + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, + iio_device_id(indio_dev)); + if (!trig) + return dev_err_probe(dev, -ENOMEM, + "failed to allocate trigger\n"); + + trig->ops = &ens160_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + ret = devm_iio_trigger_register(dev, trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(trig); + + ret = devm_request_threaded_irq(dev, irq, + iio_trigger_generic_data_rdy_poll, + NULL, + IRQF_ONESHOT, + indio_dev->name, + indio_dev->trig); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + + return 0; +} + +int devm_ens160_core_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name) +{ + struct ens160_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->regmap = regmap; + + indio_dev->name = name; + indio_dev->info = &ens160_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ens160_channels; + indio_dev->num_channels = ARRAY_SIZE(ens160_channels); + + if (irq > 0) { + ret = ens160_setup_trigger(indio_dev, irq); + if (ret) + return dev_err_probe(dev, ret, + "failed to setup trigger\n"); + } + + ret = ens160_chip_init(data); + if (ret) + return dev_err_probe(dev, ret, "chip initialization failed\n"); + + mutex_init(&data->mutex); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ens160_trigger_handler, NULL); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} +EXPORT_SYMBOL_NS(devm_ens160_core_probe, IIO_ENS160); + +MODULE_AUTHOR("Gustavo Silva "); +MODULE_DESCRIPTION("ScioSense ENS160 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/chemical/ens160_i2c.c b/drivers/iio/chemical/ens160_i2c.c new file mode 100644 index 000000000000..57a189a4c257 --- /dev/null +++ b/drivers/iio/chemical/ens160_i2c.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ScioSense ENS160 multi-gas sensor I2C driver + * + * Copyright (c) 2024 Gustavo Silva + * + * 7-Bit I2C slave address is: + * - 0x52 if ADDR pin LOW + * - 0x53 if ADDR pin HIGH + */ + +#include +#include +#include + +#include "ens160.h" + +static const struct regmap_config ens160_regmap_i2c_conf = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int ens160_i2c_probe(struct i2c_client *client) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &ens160_regmap_i2c_conf); + if (IS_ERR(regmap)) + return dev_err_probe(&client->dev, PTR_ERR(regmap), + "Failed to register i2c regmap\n"); + + return devm_ens160_core_probe(&client->dev, regmap, client->irq, + "ens160"); +} + +static const struct i2c_device_id ens160_i2c_id[] = { + { "ens160" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ens160_i2c_id); + +static const struct of_device_id ens160_of_i2c_match[] = { + { .compatible = "sciosense,ens160" }, + { } +}; +MODULE_DEVICE_TABLE(of, ens160_of_i2c_match); + +static struct i2c_driver ens160_i2c_driver = { + .driver = { + .name = "ens160", + .of_match_table = ens160_of_i2c_match, + .pm = pm_sleep_ptr(&ens160_pm_ops), + }, + .probe = ens160_i2c_probe, + .id_table = ens160_i2c_id, +}; +module_i2c_driver(ens160_i2c_driver); + +MODULE_AUTHOR("Gustavo Silva "); +MODULE_DESCRIPTION("ScioSense ENS160 I2C driver"); +MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_ENS160); diff --git a/drivers/iio/chemical/ens160_spi.c b/drivers/iio/chemical/ens160_spi.c new file mode 100644 index 000000000000..10e4f5fd0f45 --- /dev/null +++ b/drivers/iio/chemical/ens160_spi.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ScioSense ENS160 multi-gas sensor SPI driver + * + * Copyright (c) 2024 Gustavo Silva + */ + +#include +#include +#include + +#include "ens160.h" + +#define ENS160_SPI_READ BIT(0) + +static const struct regmap_config ens160_regmap_spi_conf = { + .reg_bits = 8, + .val_bits = 8, + .reg_shift = -1, + .read_flag_mask = ENS160_SPI_READ, +}; + +static int ens160_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &ens160_regmap_spi_conf); + if (IS_ERR(regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(regmap), + "Failed to register spi regmap\n"); + + return devm_ens160_core_probe(&spi->dev, regmap, spi->irq, "ens160"); +} + +static const struct of_device_id ens160_spi_of_match[] = { + { .compatible = "sciosense,ens160" }, + { } +}; +MODULE_DEVICE_TABLE(of, ens160_spi_of_match); + +static const struct spi_device_id ens160_spi_id[] = { + { "ens160" }, + { } +}; +MODULE_DEVICE_TABLE(spi, ens160_spi_id); + +static struct spi_driver ens160_spi_driver = { + .driver = { + .name = "ens160", + .of_match_table = ens160_spi_of_match, + .pm = pm_sleep_ptr(&ens160_pm_ops), + }, + .probe = ens160_spi_probe, + .id_table = ens160_spi_id, +}; +module_spi_driver(ens160_spi_driver); + +MODULE_AUTHOR("Gustavo Silva "); +MODULE_DESCRIPTION("ScioSense ENS160 SPI driver"); +MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_ENS160); diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c index 0c2caf3570db..7190eaede7fb 100644 --- a/drivers/iio/common/scmi_sensors/scmi_iio.c +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c @@ -626,12 +626,10 @@ scmi_alloc_iiodev(struct scmi_device *sdev, SCMI_PROTOCOL_SENSOR, SCMI_EVENT_SENSOR_UPDATE, &sensor->sensor_info->id, &sensor->sensor_update_nb); - if (ret) { - dev_err(&iiodev->dev, - "Error in registering sensor update notifier for sensor %s err %d", - sensor->sensor_info->name, ret); - return ERR_PTR(ret); - } + if (ret) + return dev_err_ptr_probe(&iiodev->dev, ret, + "Error in registering sensor update notifier for sensor %s\n", + sensor->sensor_info->name); scmi_iio_set_timestamp_channel(&iio_channels[i], i); iiodev->channels = iio_channels; @@ -653,10 +651,9 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev) return -ENODEV; sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph); - if (IS_ERR(sensor_ops)) { - dev_err(dev, "SCMI device has no sensor interface\n"); - return PTR_ERR(sensor_ops); - } + if (IS_ERR(sensor_ops)) + return dev_err_probe(dev, PTR_ERR(sensor_ops), + "SCMI device has no sensor interface\n"); nr_sensors = sensor_ops->count_get(ph); if (!nr_sensors) { @@ -667,8 +664,8 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev) for (i = 0; i < nr_sensors; i++) { sensor_info = sensor_ops->info_get(ph, i); if (!sensor_info) { - dev_err(dev, "SCMI sensor %d has missing info\n", i); - return -EINVAL; + return dev_err_probe(dev, -EINVAL, + "SCMI sensor %d has missing info\n", i); } /* This driver only supports 3-axis accel and gyro, skipping other sensors */ @@ -683,29 +680,25 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev) scmi_iio_dev = scmi_alloc_iiodev(sdev, sensor_ops, ph, sensor_info); if (IS_ERR(scmi_iio_dev)) { - dev_err(dev, - "failed to allocate IIO device for sensor %s: %ld\n", - sensor_info->name, PTR_ERR(scmi_iio_dev)); - return PTR_ERR(scmi_iio_dev); + return dev_err_probe(dev, PTR_ERR(scmi_iio_dev), + "failed to allocate IIO device for sensor %s\n", + sensor_info->name); } err = devm_iio_kfifo_buffer_setup(&scmi_iio_dev->dev, scmi_iio_dev, &scmi_iio_buffer_ops); if (err < 0) { - dev_err(dev, - "IIO buffer setup error at sensor %s: %d\n", - sensor_info->name, err); - return err; + return dev_err_probe(dev, err, + "IIO buffer setup error at sensor %s\n", + sensor_info->name); } err = devm_iio_device_register(dev, scmi_iio_dev); - if (err) { - dev_err(dev, - "IIO device registration failed at sensor %s: %d\n", - sensor_info->name, err); - return err; - } + if (err) + return dev_err_probe(dev, err, + "IIO device registration failed at sensor %s\n", + sensor_info->name); } return err; } diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index c77d7bdcc121..c69399ac6657 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -606,10 +606,9 @@ int st_sensors_verify_id(struct iio_dev *indio_dev) } if (sdata->sensor_settings->wai != wai) { - dev_err(&indio_dev->dev, + dev_warn(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n", indio_dev->name, wai); - return -EINVAL; } } diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index ee0d9798d8b4..a2596c2d3de3 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -149,6 +149,7 @@ config AD9739A config ADI_AXI_DAC tristate "Analog Devices Generic AXI DAC IP core driver" + depends on MICROBLAZE || NIOS2 || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_INTEL_SOCFPGA || COMPILE_TEST select IIO_BUFFER select IIO_BUFFER_DMAENGINE select REGMAP_MMIO diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c index 8aa942896b5b..bd37d304ca70 100644 --- a/drivers/iio/dac/ad3552r.c +++ b/drivers/iio/dac/ad3552r.c @@ -117,7 +117,7 @@ #define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3) /* Useful defines */ -#define AD3552R_NUM_CH 2 +#define AD3552R_MAX_CH 2 #define AD3552R_MASK_CH(ch) BIT(ch) #define AD3552R_MASK_ALL_CH GENMASK(1, 0) #define AD3552R_MAX_REG_SIZE 3 @@ -139,8 +139,10 @@ enum ad3552r_ch_vref_select { AD3552R_EXTERNAL_VREF_PIN_INPUT }; -enum ad3542r_id { +enum ad3552r_id { + AD3541R_ID = 0x400b, AD3542R_ID = 0x4009, + AD3551R_ID = 0x400a, AD3552R_ID = 0x4008, }; @@ -261,17 +263,26 @@ struct ad3552r_ch_data { bool range_override; }; +struct ad3552r_model_data { + const char *model_name; + enum ad3552r_id chip_id; + unsigned int num_hw_channels; + const s32 (*ranges_table)[2]; + int num_ranges; + bool requires_output_range; +}; + struct ad3552r_desc { + const struct ad3552r_model_data *model_data; /* Used to look the spi bus for atomic operations where needed */ struct mutex lock; struct gpio_desc *gpio_reset; struct gpio_desc *gpio_ldac; struct spi_device *spi; - struct ad3552r_ch_data ch_data[AD3552R_NUM_CH]; - struct iio_chan_spec channels[AD3552R_NUM_CH + 1]; + struct ad3552r_ch_data ch_data[AD3552R_MAX_CH]; + struct iio_chan_spec channels[AD3552R_MAX_CH + 1]; unsigned long enabled_ch; unsigned int num_ch; - enum ad3542r_id chip_id; }; static const u16 addr_mask_map[][2] = { @@ -528,7 +539,7 @@ static int32_t ad3552r_trigger_hw_ldac(struct gpio_desc *ldac) static int ad3552r_write_all_channels(struct ad3552r_desc *dac, u8 *data) { int err, len; - u8 addr, buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE + 1]; + u8 addr, buff[AD3552R_MAX_CH * AD3552R_MAX_REG_SIZE + 1]; addr = AD3552R_REG_ADDR_CH_INPUT_24B(1); /* CH1 */ @@ -586,7 +597,7 @@ static irqreturn_t ad3552r_trigger_handler(int irq, void *p) struct iio_buffer *buf = indio_dev->buffer; struct ad3552r_desc *dac = iio_priv(indio_dev); /* Maximum size of a scan */ - u8 buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE]; + u8 buff[AD3552R_MAX_CH * AD3552R_MAX_REG_SIZE]; int err; memset(buff, 0, sizeof(buff)); @@ -745,13 +756,8 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) } else { /* Normal range */ idx = dac->ch_data[ch].range; - if (dac->chip_id == AD3542R_ID) { - v_min = ad3542r_ch_ranges[idx][0]; - v_max = ad3542r_ch_ranges[idx][1]; - } else { - v_min = ad3552r_ch_ranges[idx][0]; - v_max = ad3552r_ch_ranges[idx][1]; - } + v_min = dac->model_data->ranges_table[idx][0]; + v_max = dac->model_data->ranges_table[idx][1]; } /* @@ -775,22 +781,14 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) dac->ch_data[ch].offset_dec = div_s64(tmp, span); } -static int ad3552r_find_range(u16 id, s32 *vals) +static int ad3552r_find_range(const struct ad3552r_model_data *model_data, + s32 *vals) { - int i, len; - const s32 (*ranges)[2]; + int i; - if (id == AD3542R_ID) { - len = ARRAY_SIZE(ad3542r_ch_ranges); - ranges = ad3542r_ch_ranges; - } else { - len = ARRAY_SIZE(ad3552r_ch_ranges); - ranges = ad3552r_ch_ranges; - } - - for (i = 0; i < len; i++) - if (vals[0] == ranges[i][0] * 1000 && - vals[1] == ranges[i][1] * 1000) + for (i = 0; i < model_data->num_ranges; i++) + if (vals[0] == model_data->ranges_table[i][0] * 1000 && + vals[1] == model_data->ranges_table[i][1] * 1000) return i; return -EINVAL; @@ -859,15 +857,9 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, return 0; } -static void ad3552r_reg_disable(void *reg) -{ - regulator_disable(reg); -} - static int ad3552r_configure_device(struct ad3552r_desc *dac) { struct device *dev = &dac->spi->dev; - struct regulator *vref; int err, cnt = 0, voltage, delta = 100000; u32 vals[2], val, ch; @@ -876,30 +868,16 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac), "Error getting gpio ldac"); - vref = devm_regulator_get_optional(dev, "vref"); - if (IS_ERR(vref)) { - if (PTR_ERR(vref) != -ENODEV) - return dev_err_probe(dev, PTR_ERR(vref), - "Error getting vref"); + voltage = devm_regulator_get_enable_read_voltage(dev, "vref"); + if (voltage < 0 && voltage != -ENODEV) + return dev_err_probe(dev, voltage, "Error getting vref voltage\n"); + if (voltage == -ENODEV) { if (device_property_read_bool(dev, "adi,vref-out-en")) val = AD3552R_INTERNAL_VREF_PIN_2P5V; else val = AD3552R_INTERNAL_VREF_PIN_FLOATING; } else { - err = regulator_enable(vref); - if (err) { - dev_err(dev, "Failed to enable external vref supply\n"); - return err; - } - - err = devm_add_action_or_reset(dev, ad3552r_reg_disable, vref); - if (err) { - regulator_disable(vref); - return err; - } - - voltage = regulator_get_voltage(vref); if (voltage > 2500000 + delta || voltage < 2500000 - delta) { dev_warn(dev, "vref-supply must be 2.5V"); return -EINVAL; @@ -940,10 +918,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) if (err) return dev_err_probe(dev, err, "mandatory reg property missing\n"); - if (ch >= AD3552R_NUM_CH) + if (ch >= dac->model_data->num_hw_channels) return dev_err_probe(dev, -EINVAL, "reg must be less than %d\n", - AD3552R_NUM_CH); + dac->model_data->num_hw_channels); if (fwnode_property_present(child, "adi,output-range-microvolt")) { err = fwnode_property_read_u32_array(child, @@ -954,7 +932,7 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) return dev_err_probe(dev, err, "adi,output-range-microvolt property could not be parsed\n"); - err = ad3552r_find_range(dac->chip_id, vals); + err = ad3552r_find_range(dac->model_data, vals); if (err < 0) return dev_err_probe(dev, err, "Invalid adi,output-range-microvolt value\n"); @@ -967,9 +945,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) return err; dac->ch_data[ch].range = val; - } else if (dac->chip_id == AD3542R_ID) { + } else if (dac->model_data->requires_output_range) { return dev_err_probe(dev, -EINVAL, - "adi,output-range-microvolt is required for ad3542r\n"); + "adi,output-range-microvolt is required for %s\n", + dac->model_data->model_name); } else { err = ad3552r_configure_custom_gain(dac, child, ch); if (err) @@ -989,7 +968,8 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) } /* Disable unused channels */ - for_each_clear_bit(ch, &dac->enabled_ch, AD3552R_NUM_CH) { + for_each_clear_bit(ch, &dac->enabled_ch, + dac->model_data->num_hw_channels) { err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN, ch, 1); if (err) @@ -1032,7 +1012,7 @@ static int ad3552r_init(struct ad3552r_desc *dac) } id |= val << 8; - if (id != dac->chip_id) { + if (id != dac->model_data->chip_id) { dev_err(&dac->spi->dev, "Product id not matching\n"); return -ENODEV; } @@ -1042,7 +1022,6 @@ static int ad3552r_init(struct ad3552r_desc *dac) static int ad3552r_probe(struct spi_device *spi) { - const struct spi_device_id *id = spi_get_device_id(spi); struct ad3552r_desc *dac; struct iio_dev *indio_dev; int err; @@ -1053,7 +1032,9 @@ static int ad3552r_probe(struct spi_device *spi) dac = iio_priv(indio_dev); dac->spi = spi; - dac->chip_id = id->driver_data; + dac->model_data = spi_get_device_match_data(spi); + if (!dac->model_data) + return -EINVAL; mutex_init(&dac->lock); @@ -1062,10 +1043,7 @@ static int ad3552r_probe(struct spi_device *spi) return err; /* Config triggered buffer device */ - if (dac->chip_id == AD3552R_ID) - indio_dev->name = "ad3552r"; - else - indio_dev->name = "ad3542r"; + indio_dev->name = dac->model_data->model_name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &ad3552r_iio_info; indio_dev->num_channels = dac->num_ch; @@ -1083,16 +1061,68 @@ static int ad3552r_probe(struct spi_device *spi) return devm_iio_device_register(&spi->dev, indio_dev); } +static const struct ad3552r_model_data ad3541r_model_data = { + .model_name = "ad3541r", + .chip_id = AD3541R_ID, + .num_hw_channels = 1, + .ranges_table = ad3542r_ch_ranges, + .num_ranges = ARRAY_SIZE(ad3542r_ch_ranges), + .requires_output_range = true, +}; + +static const struct ad3552r_model_data ad3542r_model_data = { + .model_name = "ad3542r", + .chip_id = AD3542R_ID, + .num_hw_channels = 2, + .ranges_table = ad3542r_ch_ranges, + .num_ranges = ARRAY_SIZE(ad3542r_ch_ranges), + .requires_output_range = true, +}; + +static const struct ad3552r_model_data ad3551r_model_data = { + .model_name = "ad3551r", + .chip_id = AD3551R_ID, + .num_hw_channels = 1, + .ranges_table = ad3552r_ch_ranges, + .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges), + .requires_output_range = false, +}; + +static const struct ad3552r_model_data ad3552r_model_data = { + .model_name = "ad3552r", + .chip_id = AD3552R_ID, + .num_hw_channels = 2, + .ranges_table = ad3552r_ch_ranges, + .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges), + .requires_output_range = false, +}; + static const struct spi_device_id ad3552r_id[] = { - { "ad3542r", AD3542R_ID }, - { "ad3552r", AD3552R_ID }, + { + .name = "ad3541r", + .driver_data = (kernel_ulong_t)&ad3541r_model_data + }, + { + .name = "ad3542r", + .driver_data = (kernel_ulong_t)&ad3542r_model_data + }, + { + .name = "ad3551r", + .driver_data = (kernel_ulong_t)&ad3551r_model_data + }, + { + .name = "ad3552r", + .driver_data = (kernel_ulong_t)&ad3552r_model_data + }, { } }; MODULE_DEVICE_TABLE(spi, ad3552r_id); static const struct of_device_id ad3552r_of_match[] = { - { .compatible = "adi,ad3542r"}, - { .compatible = "adi,ad3552r"}, + { .compatible = "adi,ad3541r", .data = &ad3541r_model_data }, + { .compatible = "adi,ad3542r", .data = &ad3542r_model_data }, + { .compatible = "adi,ad3551r", .data = &ad3551r_model_data }, + { .compatible = "adi,ad3552r", .data = &ad3552r_model_data }, { } }; MODULE_DEVICE_TABLE(of, ad3552r_of_match); diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c index 880d83a014a1..6d56428e623d 100644 --- a/drivers/iio/dac/adi-axi-dac.c +++ b/drivers/iio/dac/adi-axi-dac.c @@ -545,7 +545,8 @@ static int axi_dac_probe(struct platform_device *pdev) clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) - return PTR_ERR(clk); + return dev_err_probe(&pdev->dev, PTR_ERR(clk), + "failed to get clock\n"); base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) @@ -555,7 +556,8 @@ static int axi_dac_probe(struct platform_device *pdev) st->regmap = devm_regmap_init_mmio(&pdev->dev, base, &axi_dac_regmap_config); if (IS_ERR(st->regmap)) - return PTR_ERR(st->regmap); + return dev_err_probe(&pdev->dev, PTR_ERR(st->regmap), + "failed to init register map\n"); /* * Force disable the core. Up to the frontend to enable us. And we can @@ -601,7 +603,8 @@ static int axi_dac_probe(struct platform_device *pdev) mutex_init(&st->lock); ret = devm_iio_backend_register(&pdev->dev, &axi_dac_generic, st); if (ret) - return ret; + return dev_err_probe(&pdev->dev, ret, + "failed to register iio backend\n"); dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n", ADI_AXI_PCORE_VER_MAJOR(ver), diff --git a/drivers/iio/dac/ltc2688.c b/drivers/iio/dac/ltc2688.c index c4b1ba30f935..af50d2a95898 100644 --- a/drivers/iio/dac/ltc2688.c +++ b/drivers/iio/dac/ltc2688.c @@ -860,9 +860,8 @@ static int ltc2688_setup(struct ltc2688_state *st, struct regulator *vref) /* bring device out of reset */ gpiod_set_value_cansleep(gpio, 0); } else { - ret = regmap_update_bits(st->regmap, LTC2688_CMD_CONFIG, - LTC2688_CONFIG_RST, - LTC2688_CONFIG_RST); + ret = regmap_set_bits(st->regmap, LTC2688_CMD_CONFIG, + LTC2688_CONFIG_RST); if (ret) return ret; } diff --git a/drivers/iio/dac/max5522.c b/drivers/iio/dac/max5522.c index 05034a306597..9f72155dcbc7 100644 --- a/drivers/iio/dac/max5522.c +++ b/drivers/iio/dac/max5522.c @@ -132,7 +132,6 @@ static const struct regmap_config max5522_regmap_config = { static int max5522_spi_probe(struct spi_device *spi) { - const struct spi_device_id *id = spi_get_device_id(spi); struct iio_dev *indio_dev; struct max5522_state *state; int ret; @@ -144,13 +143,9 @@ static int max5522_spi_probe(struct spi_device *spi) } state = iio_priv(indio_dev); - state->chip_info = device_get_match_data(&spi->dev); - if (!state->chip_info) { - state->chip_info = - (struct max5522_chip_info *)(id->driver_data); - if (!state->chip_info) - return -EINVAL; - } + state->chip_info = spi_get_device_match_data(spi); + if (!state->chip_info) + return -EINVAL; state->vrefin_reg = devm_regulator_get(&spi->dev, "vrefin"); if (IS_ERR(state->vrefin_reg)) diff --git a/drivers/iio/dac/mcp4728.c b/drivers/iio/dac/mcp4728.c index 5113f67ddc31..c449ca949465 100644 --- a/drivers/iio/dac/mcp4728.c +++ b/drivers/iio/dac/mcp4728.c @@ -591,7 +591,7 @@ static int mcp4728_probe(struct i2c_client *client) } static const struct i2c_device_id mcp4728_id[] = { - { "mcp4728", 0 }, + { "mcp4728" }, {} }; MODULE_DEVICE_TABLE(i2c, mcp4728_id); diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index e150ac729154..2d567073996b 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -200,9 +200,8 @@ static int stm32_dac_core_resume(struct device *dev) if (priv->common.hfsel) { /* restore hfsel (maybe lost under low power state) */ - ret = regmap_update_bits(priv->common.regmap, STM32_DAC_CR, - STM32H7_DAC_CR_HFSEL, - STM32H7_DAC_CR_HFSEL); + ret = regmap_set_bits(priv->common.regmap, STM32_DAC_CR, + STM32H7_DAC_CR_HFSEL); if (ret) return ret; } diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 4abf80f75ef5..e13e64a5164c 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,9 @@ struct adf4350_state { struct gpio_desc *lock_detect_gpiod; struct adf4350_platform_data *pdata; struct clk *clk; + struct clk *clkout; + const char *clk_out_name; + struct clk_hw hw; unsigned long clkin; unsigned long chspc; /* Channel Spacing */ unsigned long fpfd; /* Phase Frequency Detector */ @@ -61,6 +65,8 @@ struct adf4350_state { __be32 val __aligned(IIO_DMA_MINALIGN); }; +#define to_adf4350_state(_hw) container_of(_hw, struct adf4350_state, hw) + static struct adf4350_platform_data default_pdata = { .channel_spacing = 10000, .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS | @@ -381,6 +387,113 @@ static const struct iio_info adf4350_info = { .debugfs_reg_access = &adf4350_reg_access, }; +static void adf4350_clk_del_provider(void *data) +{ + struct adf4350_state *st = data; + + of_clk_del_provider(st->spi->dev.of_node); +} + +static unsigned long adf4350_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct adf4350_state *st = to_adf4350_state(hw); + unsigned long long tmp; + + tmp = (u64)(st->r0_int * st->r1_mod + st->r0_fract) * st->fpfd; + do_div(tmp, st->r1_mod * (1 << st->r4_rf_div_sel)); + + return tmp; +} + +static int adf4350_clk_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct adf4350_state *st = to_adf4350_state(hw); + + if (parent_rate == 0 || parent_rate > ADF4350_MAX_FREQ_REFIN) + return -EINVAL; + + st->clkin = parent_rate; + + return adf4350_set_freq(st, rate); +} + +static int adf4350_clk_prepare(struct clk_hw *hw) +{ + struct adf4350_state *st = to_adf4350_state(hw); + + st->regs[ADF4350_REG2] &= ~ADF4350_REG2_POWER_DOWN_EN; + + return adf4350_sync_config(st); +} + +static void adf4350_clk_unprepare(struct clk_hw *hw) +{ + struct adf4350_state *st = to_adf4350_state(hw); + + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + + adf4350_sync_config(st); +} + +static int adf4350_clk_is_enabled(struct clk_hw *hw) +{ + struct adf4350_state *st = to_adf4350_state(hw); + + return (st->regs[ADF4350_REG2] & ADF4350_REG2_POWER_DOWN_EN); +} + +static const struct clk_ops adf4350_clk_ops = { + .recalc_rate = adf4350_clk_recalc_rate, + .set_rate = adf4350_clk_set_rate, + .prepare = adf4350_clk_prepare, + .unprepare = adf4350_clk_unprepare, + .is_enabled = adf4350_clk_is_enabled, +}; + +static int adf4350_clk_register(struct adf4350_state *st) +{ + struct spi_device *spi = st->spi; + struct clk_init_data init; + struct clk *clk; + const char *parent_name; + int ret; + + if (!device_property_present(&spi->dev, "#clock-cells")) + return 0; + + if (device_property_read_string(&spi->dev, "clock-output-names", &init.name)) { + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", + fwnode_get_name(dev_fwnode(&spi->dev))); + if (!init.name) + return -ENOMEM; + } + + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); + if (!parent_name) + return -EINVAL; + + init.ops = &adf4350_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_PARENT; + + st->hw.init = &init; + clk = devm_clk_register(&spi->dev, &st->hw); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk); + if (ret) + return ret; + + st->clkout = clk; + + return devm_add_action_or_reset(&spi->dev, adf4350_clk_del_provider, st); +} + static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) { struct adf4350_platform_data *pdata; @@ -522,8 +635,6 @@ static int adf4350_probe(struct spi_device *spi) indio_dev->info = &adf4350_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = &adf4350_chan; - indio_dev->num_channels = 1; mutex_init(&st->lock); @@ -551,6 +662,15 @@ static int adf4350_probe(struct spi_device *spi) return ret; } + ret = adf4350_clk_register(st); + if (ret) + return ret; + + if (!st->clkout) { + indio_dev->channels = &adf4350_chan; + indio_dev->num_channels = 1; + } + ret = devm_add_action_or_reset(&spi->dev, adf4350_power_down, indio_dev); if (ret) return dev_err_probe(&spi->dev, ret, diff --git a/drivers/iio/frequency/adrf6780.c b/drivers/iio/frequency/adrf6780.c index b4defb82f37e..3f46032c9275 100644 --- a/drivers/iio/frequency/adrf6780.c +++ b/drivers/iio/frequency/adrf6780.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index c95cf41be34b..da83adc684d0 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -221,13 +221,12 @@ static ssize_t adis16136_read_frequency(struct device *dev, unsigned int freq; int ret; - adis_dev_lock(&adis16136->adis); + adis_dev_auto_lock(&adis16136->adis); ret = __adis16136_get_freq(adis16136, &freq); - adis_dev_unlock(&adis16136->adis); if (ret) return ret; - return sprintf(buf, "%d\n", freq); + return sysfs_emit(buf, "%d\n", freq); } static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, @@ -251,21 +250,17 @@ static int adis16136_set_filter(struct iio_dev *indio_dev, int val) unsigned int freq; int i, ret; - adis_dev_lock(&adis16136->adis); + adis_dev_auto_lock(&adis16136->adis); ret = __adis16136_get_freq(adis16136, &freq); if (ret) - goto out_unlock; + return ret; for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) { if (freq / adis16136_3db_divisors[i] >= val) break; } - ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); -out_unlock: - adis_dev_unlock(&adis16136->adis); - - return ret; + return __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); } static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) @@ -275,23 +270,20 @@ static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) uint16_t val16; int ret; - adis_dev_lock(&adis16136->adis); + adis_dev_auto_lock(&adis16136->adis); ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); if (ret) - goto err_unlock; + return ret; ret = __adis16136_get_freq(adis16136, &freq); if (ret) - goto err_unlock; + return ret; *val = freq / adis16136_3db_divisors[val16 & 0x07]; -err_unlock: - adis_dev_unlock(&adis16136->adis); - - return ret ? ret : IIO_VAL_INT; + return IIO_VAL_INT; } static int adis16136_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 112d635b7dfd..495b64a27061 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -270,7 +270,6 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, { struct adis16260 *adis16260 = iio_priv(indio_dev); struct adis *adis = &adis16260->adis; - int ret; u8 addr; u8 t; @@ -288,7 +287,6 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, addr = adis16260_addresses[chan->scan_index][1]; return adis_write_reg_16(adis, addr, val); case IIO_CHAN_INFO_SAMP_FREQ: - adis_dev_lock(adis); if (spi_get_device_id(adis->spi)->driver_data) t = 256 / val; else @@ -298,15 +296,14 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, t = ADIS16260_SMPL_PRD_DIV_MASK; else if (t > 0) t--; - - if (t >= 0x0A) - adis->spi->max_speed_hz = ADIS16260_SPI_SLOW; - else - adis->spi->max_speed_hz = ADIS16260_SPI_FAST; - ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); - - adis_dev_unlock(adis); - return ret; + adis_dev_auto_scoped_lock(adis) { + if (t >= 0x0A) + adis->spi->max_speed_hz = ADIS16260_SPI_SLOW; + else + adis->spi->max_speed_hz = ADIS16260_SPI_FAST; + return __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); + } + unreachable(); } return -EINVAL; } diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 0e2eb0e98235..10728d5ccae3 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -285,8 +285,8 @@ static int bmg160_chip_init(struct bmg160_data *data) data->slope_thres = val; /* Set default interrupt mode */ - ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1, - BMG160_INT1_BIT_OD, 0); + ret = regmap_clear_bits(data->regmap, BMG160_REG_INT_EN_1, + BMG160_INT1_BIT_OD); if (ret < 0) { dev_err(dev, "Error updating bits in reg_int_en_1\n"); return ret; diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c index 9c8e20c25e96..672d0b720f61 100644 --- a/drivers/iio/gyro/bmg160_i2c.c +++ b/drivers/iio/gyro/bmg160_i2c.c @@ -47,9 +47,9 @@ static const struct acpi_device_id bmg160_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match); static const struct i2c_device_id bmg160_i2c_id[] = { - {"bmg160", 0}, - {"bmi055_gyro", 0}, - {"bmi088_gyro", 0}, + { "bmg160" }, + { "bmi055_gyro" }, + { "bmi088_gyro" }, {} }; diff --git a/drivers/iio/gyro/fxas21002c_i2c.c b/drivers/iio/gyro/fxas21002c_i2c.c index ee7f21b718e2..b1318a1ea41b 100644 --- a/drivers/iio/gyro/fxas21002c_i2c.c +++ b/drivers/iio/gyro/fxas21002c_i2c.c @@ -39,7 +39,7 @@ static void fxas21002c_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id fxas21002c_i2c_id[] = { - { "fxas21002c", 0 }, + { "fxas21002c" }, { } }; MODULE_DEVICE_TABLE(i2c, fxas21002c_i2c_id); diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index 53fb92f0ac7e..cd8a2dae56cd 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -387,7 +387,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(itg3200_pm_ops, itg3200_suspend, itg3200_resume); static const struct i2c_device_id itg3200_id[] = { - { "itg3200", 0 }, + { "itg3200" }, { } }; MODULE_DEVICE_TABLE(i2c, itg3200_id); diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index a791ba3a693a..35af68b41408 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -197,8 +197,8 @@ static int mpu3050_start_sampling(struct mpu3050 *mpu3050) int i; /* Reset */ - ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, - MPU3050_PWR_MGM_RESET, MPU3050_PWR_MGM_RESET); + ret = regmap_set_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_RESET); if (ret) return ret; @@ -513,12 +513,9 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p) "FIFO overflow! Emptying and resetting FIFO\n"); fifo_overflow = true; /* Reset and enable the FIFO */ - ret = regmap_update_bits(mpu3050->map, - MPU3050_USR_CTRL, - MPU3050_USR_CTRL_FIFO_EN | - MPU3050_USR_CTRL_FIFO_RST, - MPU3050_USR_CTRL_FIFO_EN | - MPU3050_USR_CTRL_FIFO_RST); + ret = regmap_set_bits(mpu3050->map, MPU3050_USR_CTRL, + MPU3050_USR_CTRL_FIFO_EN | + MPU3050_USR_CTRL_FIFO_RST); if (ret) { dev_info(mpu3050->dev, "error resetting FIFO\n"); goto out_trigger_unlock; @@ -799,10 +796,8 @@ static int mpu3050_hw_init(struct mpu3050 *mpu3050) u64 otp; /* Reset */ - ret = regmap_update_bits(mpu3050->map, - MPU3050_PWR_MGM, - MPU3050_PWR_MGM_RESET, - MPU3050_PWR_MGM_RESET); + ret = regmap_set_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_RESET); if (ret) return ret; @@ -872,8 +867,8 @@ static int mpu3050_power_up(struct mpu3050 *mpu3050) msleep(200); /* Take device out of sleep mode */ - ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, - MPU3050_PWR_MGM_SLEEP, 0); + ret = regmap_clear_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_SLEEP); if (ret) { regulator_bulk_disable(ARRAY_SIZE(mpu3050->regs), mpu3050->regs); dev_err(mpu3050->dev, "error setting power mode\n"); @@ -895,8 +890,8 @@ static int mpu3050_power_down(struct mpu3050 *mpu3050) * then we would be wasting power unless we go to sleep mode * first. */ - ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM, - MPU3050_PWR_MGM_SLEEP, MPU3050_PWR_MGM_SLEEP); + ret = regmap_set_bits(mpu3050->map, MPU3050_PWR_MGM, + MPU3050_PWR_MGM_SLEEP); if (ret) dev_err(mpu3050->dev, "error putting to sleep\n"); @@ -997,11 +992,9 @@ static int mpu3050_drdy_trigger_set_state(struct iio_trigger *trig, return ret; /* Reset and enable the FIFO */ - ret = regmap_update_bits(mpu3050->map, MPU3050_USR_CTRL, - MPU3050_USR_CTRL_FIFO_EN | - MPU3050_USR_CTRL_FIFO_RST, - MPU3050_USR_CTRL_FIFO_EN | - MPU3050_USR_CTRL_FIFO_RST); + ret = regmap_set_bits(mpu3050->map, MPU3050_USR_CTRL, + MPU3050_USR_CTRL_FIFO_EN | + MPU3050_USR_CTRL_FIFO_RST); if (ret) return ret; diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 1dbe48dae74e..52326dc521ac 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -422,9 +422,8 @@ static int afe4403_suspend(struct device *dev) struct afe4403_data *afe = iio_priv(indio_dev); int ret; - ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, - AFE440X_CONTROL2_PDN_AFE, - AFE440X_CONTROL2_PDN_AFE); + ret = regmap_set_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE); if (ret) return ret; @@ -449,8 +448,8 @@ static int afe4403_resume(struct device *dev) return ret; } - ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, - AFE440X_CONTROL2_PDN_AFE, 0); + ret = regmap_clear_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE); if (ret) return ret; diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index 7768b07ef7a6..7f69baa1ed53 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -430,9 +430,8 @@ static int afe4404_suspend(struct device *dev) struct afe4404_data *afe = iio_priv(indio_dev); int ret; - ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, - AFE440X_CONTROL2_PDN_AFE, - AFE440X_CONTROL2_PDN_AFE); + ret = regmap_set_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE); if (ret) return ret; @@ -457,8 +456,8 @@ static int afe4404_resume(struct device *dev) return ret; } - ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, - AFE440X_CONTROL2_PDN_AFE, 0); + ret = regmap_clear_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE); if (ret) return ret; @@ -582,7 +581,7 @@ static int afe4404_probe(struct i2c_client *client) } static const struct i2c_device_id afe4404_ids[] = { - { "afe4404", 0 }, + { "afe4404" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, afe4404_ids); diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index 6236b4d96137..e08d143a707c 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -363,9 +363,8 @@ static int max30100_get_temp(struct max30100_data *data, int *val) int ret; /* start acquisition */ - ret = regmap_update_bits(data->regmap, MAX30100_REG_MODE_CONFIG, - MAX30100_REG_MODE_CONFIG_TEMP_EN, - MAX30100_REG_MODE_CONFIG_TEMP_EN); + ret = regmap_set_bits(data->regmap, MAX30100_REG_MODE_CONFIG, + MAX30100_REG_MODE_CONFIG_TEMP_EN); if (ret) return ret; @@ -483,7 +482,7 @@ static void max30100_remove(struct i2c_client *client) } static const struct i2c_device_id max30100_id[] = { - { "max30100", 0 }, + { "max30100" }, {} }; MODULE_DEVICE_TABLE(i2c, max30100_id); diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 6616729af5b7..07a343e35a81 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -448,9 +448,8 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en) } /* start acquisition */ - ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG, - MAX30102_REG_TEMP_CONFIG_TEMP_EN, - MAX30102_REG_TEMP_CONFIG_TEMP_EN); + ret = regmap_set_bits(data->regmap, MAX30102_REG_TEMP_CONFIG, + MAX30102_REG_TEMP_CONFIG_TEMP_EN); if (ret) goto out; diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 37a35d1153d5..a56474be5dd2 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -253,7 +253,7 @@ static int am2315_probe(struct i2c_client *client) } static const struct i2c_device_id am2315_i2c_id[] = { - {"am2315", 0}, + { "am2315" }, {} }; MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 202014da2785..9b355380c9bf 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -396,12 +396,12 @@ static int hdc100x_probe(struct i2c_client *client) } static const struct i2c_device_id hdc100x_id[] = { - { "hdc100x", 0 }, - { "hdc1000", 0 }, - { "hdc1008", 0 }, - { "hdc1010", 0 }, - { "hdc1050", 0 }, - { "hdc1080", 0 }, + { "hdc100x" }, + { "hdc1000" }, + { "hdc1008" }, + { "hdc1010" }, + { "hdc1050" }, + { "hdc1080" }, { } }; MODULE_DEVICE_TABLE(i2c, hdc100x_id); diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c index 9465908cc65e..0797ece1fcba 100644 --- a/drivers/iio/humidity/si7005.c +++ b/drivers/iio/humidity/si7005.c @@ -163,8 +163,8 @@ static int si7005_probe(struct i2c_client *client) } static const struct i2c_device_id si7005_id[] = { - { "si7005", 0 }, - { "th02", 0 }, + { "si7005" }, + { "th02" }, { } }; MODULE_DEVICE_TABLE(i2c, si7005_id); diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index fb1006649328..ff2dba50c0a5 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -33,17 +34,38 @@ #define SI7020CMD_TEMP_HOLD 0xE3 /* Software Reset */ #define SI7020CMD_RESET 0xFE +#define SI7020CMD_USR_WRITE 0xE6 +/* "Heater Enabled" bit in the User Register */ +#define SI7020_USR_HEATER_EN BIT(2) +#define SI7020CMD_HEATER_WRITE 0x51 +/* Heater current configuration bits */ +#define SI7020_HEATER_VAL GENMASK(3, 0) + +struct si7020_data { + struct i2c_client *client; + /* Lock for cached register values */ + struct mutex lock; + u8 user_reg; + u8 heater_reg; +}; + +static const int si7020_heater_vals[] = { 0, 1, 0xF }; static int si7020_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - struct i2c_client **client = iio_priv(indio_dev); + struct si7020_data *data = iio_priv(indio_dev); int ret; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = i2c_smbus_read_word_swapped(*client, + if (chan->type == IIO_CURRENT) { + *val = data->heater_reg; + return IIO_VAL_INT; + } + + ret = i2c_smbus_read_word_swapped(data->client, chan->type == IIO_TEMP ? SI7020CMD_TEMP_HOLD : SI7020CMD_RH_HOLD); @@ -96,17 +118,118 @@ static const struct iio_chan_spec si7020_channels[] = { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), + }, + { + .type = IIO_CURRENT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), + .extend_name = "heater", } }; +static int si7020_update_reg(struct si7020_data *data, + u8 *reg, u8 cmd, u8 mask, u8 val) +{ + u8 new = (*reg & ~mask) | val; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, cmd, new); + if (ret) + return ret; + + *reg = new; + + return 0; +} + +static int si7020_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct si7020_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->type != IIO_CURRENT || val2 != 0 || + val < si7020_heater_vals[0] || val > si7020_heater_vals[2]) + return -EINVAL; + + scoped_guard(mutex, &data->lock) + ret = si7020_update_reg(data, &data->heater_reg, + SI7020CMD_HEATER_WRITE, SI7020_HEATER_VAL, val); + return ret; + default: + return -EINVAL; + } +} + +static int si7020_read_available(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, int *length, long mask) +{ + if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_CURRENT) + return -EINVAL; + + *vals = si7020_heater_vals; + *type = IIO_VAL_INT; + + return IIO_AVAIL_RANGE; +} + +static ssize_t si7020_show_heater_en(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct si7020_data *data = iio_priv(indio_dev); + + return sysfs_emit(buf, "%d\n", !!(data->user_reg & SI7020_USR_HEATER_EN)); +} + +static ssize_t si7020_store_heater_en(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct si7020_data *data = iio_priv(indio_dev); + int ret; + bool val; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + scoped_guard(mutex, &data->lock) + ret = si7020_update_reg(data, &data->user_reg, SI7020CMD_USR_WRITE, + SI7020_USR_HEATER_EN, val ? SI7020_USR_HEATER_EN : 0); + + return ret < 0 ? ret : len; +} + +static IIO_DEVICE_ATTR(heater_enable, 0644, + si7020_show_heater_en, si7020_store_heater_en, 0); + +static struct attribute *si7020_attributes[] = { + &iio_dev_attr_heater_enable.dev_attr.attr, + NULL +}; + +static const struct attribute_group si7020_attribute_group = { + .attrs = si7020_attributes, +}; + static const struct iio_info si7020_info = { .read_raw = si7020_read_raw, + .write_raw = si7020_write_raw, + .read_avail = si7020_read_available, + .attrs = &si7020_attribute_group, }; static int si7020_probe(struct i2c_client *client) { struct iio_dev *indio_dev; - struct i2c_client **data; + struct si7020_data *data; int ret; if (!i2c_check_functionality(client->adapter, @@ -126,7 +249,9 @@ static int si7020_probe(struct i2c_client *client) return -ENOMEM; data = iio_priv(indio_dev); - *data = client; + i2c_set_clientdata(client, indio_dev); + data->client = client; + mutex_init(&data->lock); indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; @@ -134,12 +259,16 @@ static int si7020_probe(struct i2c_client *client) indio_dev->channels = si7020_channels; indio_dev->num_channels = ARRAY_SIZE(si7020_channels); + /* All the "reserved" bits in the User Register are 1s by default */ + data->user_reg = 0x3A; + data->heater_reg = 0x0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id si7020_id[] = { - { "si7020", 0 }, - { "th06", 0 }, + { "si7020" }, + { "th06" }, { } }; MODULE_DEVICE_TABLE(i2c, si7020_id); diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 1a38b1915e7a..b7d5f4f0fada 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -34,6 +34,10 @@ void iio_device_ioctl_handler_register(struct iio_dev *indio_dev, struct iio_ioctl_handler *h); void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h); +ssize_t do_iio_read_channel_label(struct iio_dev *indio_dev, + const struct iio_chan_spec *c, + char *buf); + int __iio_add_chan_devattr(const char *postfix, struct iio_chan_spec const *chan, ssize_t (*func)(struct device *dev, diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 52a155ff3250..782fb80e44c2 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -36,8 +36,8 @@ config ADIS16475 select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices ADIS16470, ADIS16475, - ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16505, ADIS16507 inertial - sensors. + ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16501, ADIS16505, + ADIS16507 inertial sensors. To compile this driver as a module, choose M here: the module will be called adis16475. diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 495caf4ce87a..876848b42f69 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -466,17 +466,17 @@ int adis_single_conversion(struct iio_dev *indio_dev, unsigned int uval; int ret; - mutex_lock(&adis->state_lock); + guard(mutex)(&adis->state_lock); ret = __adis_read_reg(adis, chan->address, &uval, chan->scan_type.storagebits / 8); if (ret) - goto err_unlock; + return ret; if (uval & error_mask) { ret = __adis_check_status(adis); if (ret) - goto err_unlock; + return ret; } if (chan->scan_type.sign == 's') @@ -484,10 +484,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, else *val = uval & ((1 << chan->scan_type.realbits) - 1); - ret = IIO_VAL_INT; -err_unlock: - mutex_unlock(&adis->state_lock); - return ret; + return IIO_VAL_INT; } EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB); diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 3eda32e12a53..0bfd6205f5f6 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -497,41 +497,38 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long info) { struct adis16400_state *st = iio_priv(indio_dev); - int ret, sps; + int sps; switch (info) { case IIO_CHAN_INFO_CALIBBIAS: - ret = adis_write_reg_16(&st->adis, - adis16400_addresses[chan->scan_index], val); - return ret; + return adis_write_reg_16(&st->adis, + adis16400_addresses[chan->scan_index], + val); case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* * Need to cache values so we can update if the frequency * changes. */ - adis_dev_lock(&st->adis); - st->filt_int = val; - /* Work out update to current value */ - sps = st->variant->get_freq(st); - if (sps < 0) { - adis_dev_unlock(&st->adis); - return sps; - } + adis_dev_auto_scoped_lock(&st->adis) { + st->filt_int = val; + /* Work out update to current value */ + sps = st->variant->get_freq(st); + if (sps < 0) + return sps; - ret = __adis16400_set_filter(indio_dev, sps, - val * 1000 + val2 / 1000); - adis_dev_unlock(&st->adis); - return ret; + return __adis16400_set_filter(indio_dev, sps, + val * 1000 + val2 / 1000); + } + unreachable(); case IIO_CHAN_INFO_SAMP_FREQ: sps = val * 1000 + val2 / 1000; if (sps <= 0) return -EINVAL; - adis_dev_lock(&st->adis); - ret = st->variant->set_freq(st, sps); - adis_dev_unlock(&st->adis); - return ret; + adis_dev_auto_scoped_lock(&st->adis) + return st->variant->set_freq(st, sps); + unreachable(); default: return -EINVAL; } @@ -596,29 +593,30 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = st->variant->temp_offset; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - adis_dev_lock(&st->adis); - /* Need both the number of taps and the sampling frequency */ - ret = __adis_read_reg_16(&st->adis, - ADIS16400_SENS_AVG, - &val16); - if (ret) { - adis_dev_unlock(&st->adis); - return ret; + adis_dev_auto_scoped_lock(&st->adis) { + /* + * Need both the number of taps and the sampling + * frequency + */ + ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, + &val16); + if (ret) + return ret; + + ret = st->variant->get_freq(st); + if (ret) + return ret; } - ret = st->variant->get_freq(st); - adis_dev_unlock(&st->adis); - if (ret) - return ret; ret /= adis16400_3db_divisors[val16 & 0x07]; *val = ret / 1000; *val2 = (ret % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: - adis_dev_lock(&st->adis); - ret = st->variant->get_freq(st); - adis_dev_unlock(&st->adis); - if (ret) - return ret; + adis_dev_auto_scoped_lock(&st->adis) { + ret = st->variant->get_freq(st); + if (ret) + return ret; + } *val = ret / 1000; *val2 = (ret % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index 060a21c70460..482258ed5a3c 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,8 @@ FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x) #define ADIS16475_SYNC_MODE_MASK GENMASK(4, 2) #define ADIS16475_SYNC_MODE(x) FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x) +#define ADIS16575_SYNC_4KHZ_MASK BIT(11) +#define ADIS16575_SYNC_4KHZ(x) FIELD_PREP(ADIS16575_SYNC_4KHZ_MASK, x) #define ADIS16475_REG_UP_SCALE 0x62 #define ADIS16475_REG_DEC_RATE 0x64 #define ADIS16475_REG_GLOB_CMD 0x68 @@ -65,15 +68,32 @@ #define ADIS16500_BURST32_MASK BIT(9) #define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x) /* number of data elements in burst mode */ -#define ADIS16475_BURST32_MAX_DATA 32 +#define ADIS16475_BURST32_MAX_DATA_NO_TS32 32 +#define ADIS16575_BURST32_DATA_TS32 34 #define ADIS16475_BURST_MAX_DATA 20 #define ADIS16475_MAX_SCAN_DATA 20 /* spi max speed in brust mode */ #define ADIS16475_BURST_MAX_SPEED 1000000 +#define ADIS16575_BURST_MAX_SPEED 8000000 #define ADIS16475_LSB_DEC_MASK 0 #define ADIS16475_LSB_FIR_MASK 1 #define ADIS16500_BURST_DATA_SEL_0_CHN_MASK GENMASK(5, 0) #define ADIS16500_BURST_DATA_SEL_1_CHN_MASK GENMASK(12, 7) +#define ADIS16575_MAX_FIFO_WM 511UL +#define ADIS16475_REG_FIFO_CTRL 0x5A +#define ADIS16575_WM_LVL_MASK GENMASK(15, 4) +#define ADIS16575_WM_LVL(x) FIELD_PREP(ADIS16575_WM_LVL_MASK, x) +#define ADIS16575_WM_POL_MASK BIT(3) +#define ADIS16575_WM_POL(x) FIELD_PREP(ADIS16575_WM_POL_MASK, x) +#define ADIS16575_WM_EN_MASK BIT(2) +#define ADIS16575_WM_EN(x) FIELD_PREP(ADIS16575_WM_EN_MASK, x) +#define ADIS16575_OVERFLOW_MASK BIT(1) +#define ADIS16575_STOP_ENQUEUE FIELD_PREP(ADIS16575_OVERFLOW_MASK, 0) +#define ADIS16575_OVERWRITE_OLDEST FIELD_PREP(ADIS16575_OVERFLOW_MASK, 1) +#define ADIS16575_FIFO_EN_MASK BIT(0) +#define ADIS16575_FIFO_EN(x) FIELD_PREP(ADIS16575_FIFO_EN_MASK, x) +#define ADIS16575_FIFO_FLUSH_CMD BIT(5) +#define ADIS16575_REG_FIFO_CNT 0x3C enum { ADIS16475_SYNC_DIRECT = 1, @@ -95,6 +115,8 @@ struct adis16475_chip_info { const char *name; #define ADIS16475_HAS_BURST32 BIT(0) #define ADIS16475_HAS_BURST_DELTA_DATA BIT(1) +#define ADIS16475_HAS_TIMESTAMP32 BIT(2) +#define ADIS16475_NEEDS_BURST_REQUEST BIT(3) const long flags; u32 num_channels; u32 gyro_max_val; @@ -116,6 +138,7 @@ struct adis16475 { bool burst32; unsigned long lsb_flag; u16 sync_mode; + u16 fifo_watermark; /* Alignment needed for the timestamp */ __be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8); }; @@ -279,30 +302,25 @@ static int adis16475_get_freq(struct adis16475 *st, u32 *freq) u16 dec; u32 sample_rate = st->clk_freq; - adis_dev_lock(&st->adis); + adis_dev_auto_lock(&st->adis); if (st->sync_mode == ADIS16475_SYNC_SCALED) { u16 sync_scale; ret = __adis_read_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, &sync_scale); if (ret) - goto error; + return ret; sample_rate = st->clk_freq * sync_scale; } ret = __adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec); if (ret) - goto error; - - adis_dev_unlock(&st->adis); + return ret; *freq = DIV_ROUND_CLOSEST(sample_rate, dec + 1); return 0; -error: - adis_dev_unlock(&st->adis); - return ret; } static int adis16475_set_freq(struct adis16475 *st, const u32 freq) @@ -310,15 +328,19 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq) u16 dec; int ret; u32 sample_rate = st->clk_freq; + /* The optimal sample rate for the supported IMUs is between int_clk - 100 and int_clk + 100. */ + u32 max_sample_rate = st->info->int_clk * 1000 + 100000; + u32 min_sample_rate = st->info->int_clk * 1000 - 100000; if (!freq) return -EINVAL; - adis_dev_lock(&st->adis); + adis_dev_auto_lock(&st->adis); /* * When using sync scaled mode, the input clock needs to be scaled so that we have - * an IMU sample rate between (optimally) 1900 and 2100. After this, we can use the - * decimation filter to lower the sampling rate in order to get what the user wants. + * an IMU sample rate between (optimally) int_clk - 100 and int_clk + 100. + * After this, we can use the decimation filter to lower the sampling rate in order + * to get what the user wants. * Optimally, the user sample rate is a multiple of both the IMU sample rate and * the input clock. Hence, calculating the sync_scale dynamically gives us better * chances of achieving a perfect/integer value for DEC_RATE. The math here is: @@ -336,28 +358,29 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq) * solution. In this case, we get the highest multiple of the input clock * lower than the IMU max sample rate. */ - if (scaled_rate > 2100000) - scaled_rate = 2100000 / st->clk_freq * st->clk_freq; + if (scaled_rate > max_sample_rate) + scaled_rate = max_sample_rate / st->clk_freq * st->clk_freq; else - scaled_rate = 2100000 / scaled_rate * scaled_rate; + scaled_rate = max_sample_rate / scaled_rate * scaled_rate; /* * This is not an hard requirement but it's not advised to run the IMU - * with a sample rate lower than 1900Hz due to possible undersampling - * issues. However, there are users that might really want to take the risk. - * Hence, we provide a module parameter for them. If set, we allow sample - * rates lower than 1.9KHz. By default, we won't allow this and we just roundup - * the rate to the next multiple of the input clock bigger than 1.9KHz. This - * is done like this as in some cases (when DEC_RATE is 0) might give - * us the closest value to the one desired by the user... + * with a sample rate lower than internal clock frequency, due to possible + * undersampling issues. However, there are users that might really want + * to take the risk. Hence, we provide a module parameter for them. If set, + * we allow sample rates lower than internal clock frequency. + * By default, we won't allow this and we just roundup the rate to the next + * multiple of the input clock. This is done like this as in some cases + * (when DEC_RATE is 0) might give us the closest value to the one desired + * by the user... */ - if (scaled_rate < 1900000 && !low_rate_allow) - scaled_rate = roundup(1900000, st->clk_freq); + if (scaled_rate < min_sample_rate && !low_rate_allow) + scaled_rate = roundup(min_sample_rate, st->clk_freq); sync_scale = scaled_rate / st->clk_freq; ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, sync_scale); if (ret) - goto error; + return ret; sample_rate = scaled_rate; } @@ -372,9 +395,8 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq) ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec); if (ret) - goto error; + return ret; - adis_dev_unlock(&st->adis); /* * If decimation is used, then gyro and accel data will have meaningful * bits on the LSB registers. This info is used on the trigger handler. @@ -382,9 +404,6 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq) assign_bit(ADIS16475_LSB_DEC_MASK, &st->lsb_flag, dec); return 0; -error: - adis_dev_unlock(&st->adis); - return ret; } /* The values are approximated. */ @@ -437,6 +456,118 @@ static int adis16475_set_filter(struct adis16475 *st, const u32 filter) return 0; } +static ssize_t adis16475_get_fifo_enabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct adis16475 *st = iio_priv(indio_dev); + int ret; + u16 val; + + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIFO_CTRL, &val); + if (ret) + return ret; + + return sysfs_emit(buf, "%lu\n", FIELD_GET(ADIS16575_FIFO_EN_MASK, val)); +} + +static ssize_t adis16475_get_fifo_watermark(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct adis16475 *st = iio_priv(indio_dev); + int ret; + u16 val; + + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIFO_CTRL, &val); + if (ret) + return ret; + + return sysfs_emit(buf, "%lu\n", FIELD_GET(ADIS16575_WM_LVL_MASK, val) + 1); +} + +static ssize_t hwfifo_watermark_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "1\n"); +} + +static ssize_t hwfifo_watermark_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%lu\n", ADIS16575_MAX_FIFO_WM); +} + +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); +static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, + adis16475_get_fifo_watermark, NULL, 0); +static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + adis16475_get_fifo_enabled, NULL, 0); + +static const struct iio_dev_attr *adis16475_fifo_attributes[] = { + &iio_dev_attr_hwfifo_watermark_min, + &iio_dev_attr_hwfifo_watermark_max, + &iio_dev_attr_hwfifo_watermark, + &iio_dev_attr_hwfifo_enabled, + NULL +}; + +static int adis16475_buffer_postenable(struct iio_dev *indio_dev) +{ + struct adis16475 *st = iio_priv(indio_dev); + struct adis *adis = &st->adis; + + return adis_update_bits(adis, ADIS16475_REG_FIFO_CTRL, + ADIS16575_FIFO_EN_MASK, (u16)ADIS16575_FIFO_EN(1)); +} + +static int adis16475_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct adis16475 *st = iio_priv(indio_dev); + struct adis *adis = &st->adis; + int ret; + + adis_dev_auto_lock(&st->adis); + + ret = __adis_update_bits(adis, ADIS16475_REG_FIFO_CTRL, + ADIS16575_FIFO_EN_MASK, (u16)ADIS16575_FIFO_EN(0)); + if (ret) + return ret; + + return __adis_write_reg_16(adis, ADIS16475_REG_GLOB_CMD, + ADIS16575_FIFO_FLUSH_CMD); +} + +static const struct iio_buffer_setup_ops adis16475_buffer_ops = { + .postenable = adis16475_buffer_postenable, + .postdisable = adis16475_buffer_postdisable, +}; + +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val) +{ + struct adis16475 *st = iio_priv(indio_dev); + int ret; + u16 wm_lvl; + + adis_dev_auto_lock(&st->adis); + + val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM); + + wm_lvl = ADIS16575_WM_LVL(val - 1); + ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl); + if (ret) + return ret; + + st->fifo_watermark = val; + + return 0; +} + static const u32 adis16475_calib_regs[] = { [ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L, [ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L, @@ -646,6 +777,22 @@ static const struct iio_chan_spec adis16475_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(7) }; +static const struct iio_chan_spec adis16575_channels[] = { + ADIS16475_GYRO_CHANNEL(X), + ADIS16475_GYRO_CHANNEL(Y), + ADIS16475_GYRO_CHANNEL(Z), + ADIS16475_ACCEL_CHANNEL(X), + ADIS16475_ACCEL_CHANNEL(Y), + ADIS16475_ACCEL_CHANNEL(Z), + ADIS16475_TEMP_CHANNEL(), + ADIS16475_DELTANG_CHAN(X), + ADIS16475_DELTANG_CHAN(Y), + ADIS16475_DELTANG_CHAN(Z), + ADIS16475_DELTVEL_CHAN(X), + ADIS16475_DELTVEL_CHAN(Y), + ADIS16475_DELTVEL_CHAN(Z), +}; + enum adis16475_variant { ADIS16470, ADIS16475_1, @@ -661,12 +808,19 @@ enum adis16475_variant { ADIS16467_2, ADIS16467_3, ADIS16500, + ADIS16501, ADIS16505_1, ADIS16505_2, ADIS16505_3, ADIS16507_1, ADIS16507_2, ADIS16507_3, + ADIS16575_2, + ADIS16575_3, + ADIS16576_2, + ADIS16576_3, + ADIS16577_2, + ADIS16577_3, }; enum { @@ -689,32 +843,33 @@ static const char * const adis16475_status_error_msgs[] = { [ADIS16475_DIAG_STAT_CLK] = "Clock error", }; -#define ADIS16475_DATA(_prod_id, _timeouts) \ -{ \ - .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \ - .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \ - .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \ - .prod_id_reg = ADIS16475_REG_PROD_ID, \ - .prod_id = (_prod_id), \ - .self_test_mask = BIT(2), \ - .self_test_reg = ADIS16475_REG_GLOB_CMD, \ - .cs_change_delay = 16, \ - .read_delay = 5, \ - .write_delay = 5, \ - .status_error_msgs = adis16475_status_error_msgs, \ - .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \ - BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \ - BIT(ADIS16475_DIAG_STAT_SPI) | \ - BIT(ADIS16475_DIAG_STAT_STANDBY) | \ - BIT(ADIS16475_DIAG_STAT_SENSOR) | \ - BIT(ADIS16475_DIAG_STAT_MEMORY) | \ - BIT(ADIS16475_DIAG_STAT_CLK), \ - .unmasked_drdy = true, \ - .timeouts = (_timeouts), \ - .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ - .burst_len = ADIS16475_BURST_MAX_DATA, \ - .burst_max_len = ADIS16475_BURST32_MAX_DATA, \ - .burst_max_speed_hz = ADIS16475_BURST_MAX_SPEED \ +#define ADIS16475_DATA(_prod_id, _timeouts, _burst_max_len, _burst_max_speed_hz, _has_fifo) \ +{ \ + .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \ + .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \ + .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \ + .prod_id_reg = ADIS16475_REG_PROD_ID, \ + .prod_id = (_prod_id), \ + .self_test_mask = BIT(2), \ + .self_test_reg = ADIS16475_REG_GLOB_CMD, \ + .cs_change_delay = 16, \ + .read_delay = 5, \ + .write_delay = 5, \ + .status_error_msgs = adis16475_status_error_msgs, \ + .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \ + BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \ + BIT(ADIS16475_DIAG_STAT_SPI) | \ + BIT(ADIS16475_DIAG_STAT_STANDBY) | \ + BIT(ADIS16475_DIAG_STAT_SENSOR) | \ + BIT(ADIS16475_DIAG_STAT_MEMORY) | \ + BIT(ADIS16475_DIAG_STAT_CLK), \ + .unmasked_drdy = true, \ + .has_fifo = _has_fifo, \ + .timeouts = (_timeouts), \ + .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ + .burst_len = ADIS16475_BURST_MAX_DATA, \ + .burst_max_len = _burst_max_len, \ + .burst_max_speed_hz = _burst_max_speed_hz \ } static const struct adis16475_sync adis16475_sync_mode[] = { @@ -724,6 +879,12 @@ static const struct adis16475_sync adis16475_sync_mode[] = { { ADIS16475_SYNC_PULSE, 1000, 2100 }, }; +static const struct adis16475_sync adis16575_sync_mode[] = { + { ADIS16475_SYNC_OUTPUT }, + { ADIS16475_SYNC_DIRECT, 1900, 4100 }, + { ADIS16475_SYNC_SCALED, 1, 400 }, +}; + static const struct adis_timeout adis16475_timeouts = { .reset_ms = 200, .sw_reset_ms = 200, @@ -752,7 +913,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16475_1] = { .name = "adis16475-1", @@ -769,7 +932,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16475_2] = { .name = "adis16475-2", @@ -786,7 +951,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16475_3] = { .name = "adis16475-3", @@ -803,7 +970,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16477_1] = { .name = "adis16477-1", @@ -821,7 +990,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16477_2] = { .name = "adis16477-2", @@ -839,7 +1010,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16477_3] = { .name = "adis16477-3", @@ -857,7 +1030,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16465_1] = { .name = "adis16465-1", @@ -874,7 +1049,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16465_2] = { .name = "adis16465-2", @@ -891,7 +1068,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16465_3] = { .name = "adis16465-3", @@ -908,7 +1087,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16467_1] = { .name = "adis16467-1", @@ -925,7 +1106,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16467_2] = { .name = "adis16467-2", @@ -942,7 +1125,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16467_3] = { .name = "adis16467-3", @@ -959,7 +1144,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { .max_dec = 1999, .sync = adis16475_sync_mode, .num_sync = ARRAY_SIZE(adis16475_sync_mode), - .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), + .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16500] = { .name = "adis16500", @@ -978,7 +1165,30 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), + }, + [ADIS16501] = { + .name = "adis16501", + .num_channels = ARRAY_SIZE(adis16477_channels), + .channels = adis16477_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), + .accel_max_val = 1, + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 125, + .int_clk = 2000, + .max_dec = 1999, + .sync = adis16475_sync_mode, + /* pulse sync not supported */ + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, + .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, + .adis_data = ADIS16475_DATA(16501, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16505_1] = { .name = "adis16505-1", @@ -997,7 +1207,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16505_2] = { .name = "adis16505-2", @@ -1016,7 +1228,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16505_3] = { .name = "adis16505-3", @@ -1035,7 +1249,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16507_1] = { .name = "adis16507-1", @@ -1054,7 +1270,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16507_2] = { .name = "adis16507-2", @@ -1073,7 +1291,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), }, [ADIS16507_3] = { .name = "adis16507-3", @@ -1092,7 +1312,147 @@ static const struct adis16475_chip_info adis16475_chip_info[] = { /* pulse sync not supported */ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA, - .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), + .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts, + ADIS16475_BURST32_MAX_DATA_NO_TS32, + ADIS16475_BURST_MAX_SPEED, false), + }, + [ADIS16575_2] = { + .name = "adis16575-2", + .num_channels = ARRAY_SIZE(adis16575_channels), + .channels = adis16575_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), + .accel_max_val = 8, + .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(450), + .deltvel_max_val = 100, + .int_clk = 4000, + .max_dec = 3999, + .sync = adis16575_sync_mode, + .num_sync = ARRAY_SIZE(adis16575_sync_mode), + .flags = ADIS16475_HAS_BURST32 | + ADIS16475_HAS_BURST_DELTA_DATA | + ADIS16475_NEEDS_BURST_REQUEST | + ADIS16475_HAS_TIMESTAMP32, + .adis_data = ADIS16475_DATA(16575, &adis16475_timeouts, + ADIS16575_BURST32_DATA_TS32, + ADIS16575_BURST_MAX_SPEED, true), + }, + [ADIS16575_3] = { + .name = "adis16575-3", + .num_channels = ARRAY_SIZE(adis16575_channels), + .channels = adis16575_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), + .accel_max_val = 8, + .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(2000), + .deltvel_max_val = 100, + .int_clk = 4000, + .max_dec = 3999, + .sync = adis16575_sync_mode, + .num_sync = ARRAY_SIZE(adis16575_sync_mode), + .flags = ADIS16475_HAS_BURST32 | + ADIS16475_HAS_BURST_DELTA_DATA | + ADIS16475_NEEDS_BURST_REQUEST | + ADIS16475_HAS_TIMESTAMP32, + .adis_data = ADIS16475_DATA(16575, &adis16475_timeouts, + ADIS16575_BURST32_DATA_TS32, + ADIS16575_BURST_MAX_SPEED, true), + }, + [ADIS16576_2] = { + .name = "adis16576-2", + .num_channels = ARRAY_SIZE(adis16575_channels), + .channels = adis16575_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), + .accel_max_val = 40, + .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(450), + .deltvel_max_val = 125, + .int_clk = 4000, + .max_dec = 3999, + .sync = adis16575_sync_mode, + .num_sync = ARRAY_SIZE(adis16575_sync_mode), + .flags = ADIS16475_HAS_BURST32 | + ADIS16475_HAS_BURST_DELTA_DATA | + ADIS16475_NEEDS_BURST_REQUEST | + ADIS16475_HAS_TIMESTAMP32, + .adis_data = ADIS16475_DATA(16576, &adis16475_timeouts, + ADIS16575_BURST32_DATA_TS32, + ADIS16575_BURST_MAX_SPEED, true), + }, + [ADIS16576_3] = { + .name = "adis16576-3", + .num_channels = ARRAY_SIZE(adis16575_channels), + .channels = adis16575_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), + .accel_max_val = 40, + .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(2000), + .deltvel_max_val = 125, + .int_clk = 4000, + .max_dec = 3999, + .sync = adis16575_sync_mode, + .num_sync = ARRAY_SIZE(adis16575_sync_mode), + .flags = ADIS16475_HAS_BURST32 | + ADIS16475_HAS_BURST_DELTA_DATA | + ADIS16475_NEEDS_BURST_REQUEST | + ADIS16475_HAS_TIMESTAMP32, + .adis_data = ADIS16475_DATA(16576, &adis16475_timeouts, + ADIS16575_BURST32_DATA_TS32, + ADIS16575_BURST_MAX_SPEED, true), + }, + [ADIS16577_2] = { + .name = "adis16577-2", + .num_channels = ARRAY_SIZE(adis16575_channels), + .channels = adis16575_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), + .accel_max_val = 40, + .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(450), + .deltvel_max_val = 400, + .int_clk = 4000, + .max_dec = 3999, + .sync = adis16575_sync_mode, + .num_sync = ARRAY_SIZE(adis16575_sync_mode), + .flags = ADIS16475_HAS_BURST32 | + ADIS16475_HAS_BURST_DELTA_DATA | + ADIS16475_NEEDS_BURST_REQUEST | + ADIS16475_HAS_TIMESTAMP32, + .adis_data = ADIS16475_DATA(16577, &adis16475_timeouts, + ADIS16575_BURST32_DATA_TS32, + ADIS16575_BURST_MAX_SPEED, true), + }, + [ADIS16577_3] = { + .name = "adis16577-3", + .num_channels = ARRAY_SIZE(adis16575_channels), + .channels = adis16575_channels, + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), + .accel_max_val = 40, + .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16), + .temp_scale = 100, + .deltang_max_val = IIO_DEGREE_TO_RAD(2000), + .deltvel_max_val = 400, + .int_clk = 4000, + .max_dec = 3999, + .sync = adis16575_sync_mode, + .num_sync = ARRAY_SIZE(adis16575_sync_mode), + .flags = ADIS16475_HAS_BURST32 | + ADIS16475_HAS_BURST_DELTA_DATA | + ADIS16475_NEEDS_BURST_REQUEST | + ADIS16475_HAS_TIMESTAMP32, + .adis_data = ADIS16475_DATA(16577, &adis16475_timeouts, + ADIS16575_BURST32_DATA_TS32, + ADIS16575_BURST_MAX_SPEED, true), }, }; @@ -1128,15 +1488,20 @@ static const struct iio_info adis16475_info = { .debugfs_reg_access = adis_debugfs_reg_access, }; +static const struct iio_info adis16575_info = { + .read_raw = &adis16475_read_raw, + .write_raw = &adis16475_write_raw, + .update_scan_mode = adis16475_update_scan_mode, + .debugfs_reg_access = adis_debugfs_reg_access, + .hwfifo_set_watermark = adis16475_set_watermark, +}; + static bool adis16475_validate_crc(const u8 *buffer, u16 crc, - const bool burst32) + u16 burst_size, u16 start_idx) { int i; - /* extra 6 elements for low gyro and accel */ - const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA : - ADIS16475_BURST_MAX_DATA; - for (i = 0; i < sz - 2; i++) + for (i = start_idx; i < burst_size - 2; i++) crc -= buffer[i]; return crc == 0; @@ -1146,10 +1511,14 @@ static void adis16475_burst32_check(struct adis16475 *st) { int ret; struct adis *adis = &st->adis; + u8 timestamp32 = 0; if (!(st->info->flags & ADIS16475_HAS_BURST32)) return; + if (st->info->flags & ADIS16475_HAS_TIMESTAMP32) + timestamp32 = 1; + if (st->lsb_flag && !st->burst32) { const u16 en = ADIS16500_BURST32(1); @@ -1163,9 +1532,12 @@ static void adis16475_burst32_check(struct adis16475 *st) /* * In 32-bit mode we need extra 2 bytes for all gyro * and accel channels. + * If the device has 32-bit timestamp value we need 2 extra + * bytes for it. */ - adis->burst_extra_len = 6 * sizeof(u16); - adis->xfer[1].len += 6 * sizeof(u16); + adis->burst_extra_len = (6 + timestamp32) * sizeof(u16); + adis->xfer[1].len += (6 + timestamp32) * sizeof(u16); + dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d", adis->xfer[1].len); @@ -1181,15 +1553,14 @@ static void adis16475_burst32_check(struct adis16475 *st) /* Remove the extra bits */ adis->burst_extra_len = 0; - adis->xfer[1].len -= 6 * sizeof(u16); + adis->xfer[1].len -= (6 + timestamp32) * sizeof(u16); dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n", adis->xfer[1].len); } } -static irqreturn_t adis16475_trigger_handler(int irq, void *p) +static int adis16475_push_single_sample(struct iio_poll_func *pf) { - struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16475 *st = iio_priv(indio_dev); struct adis *adis = &st->adis; @@ -1197,20 +1568,29 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p) __be16 *buffer; u16 crc; bool valid; + u8 crc_offset = 9; + u16 burst_size = ADIS16475_BURST_MAX_DATA; + u16 start_idx = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ? 2 : 0; + /* offset until the first element after gyro and accel */ const u8 offset = st->burst32 ? 13 : 7; + if (st->burst32) { + crc_offset = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ? 16 : 15; + burst_size = adis->data->burst_max_len; + } + ret = spi_sync(adis->spi, &adis->msg); if (ret) - goto check_burst32; + return ret; buffer = adis->buffer; - crc = be16_to_cpu(buffer[offset + 2]); - valid = adis16475_validate_crc(adis->buffer, crc, st->burst32); + crc = be16_to_cpu(buffer[crc_offset]); + valid = adis16475_validate_crc(adis->buffer, crc, burst_size, start_idx); if (!valid) { dev_err(&adis->spi->dev, "Invalid crc\n"); - goto check_burst32; + return -EINVAL; } for_each_set_bit(bit, indio_dev->active_scan_mask, @@ -1270,14 +1650,122 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p) } } + /* There might not be a timestamp option for some devices. */ iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp); -check_burst32: + + return 0; +} + +static irqreturn_t adis16475_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adis16475 *st = iio_priv(indio_dev); + + adis16475_push_single_sample(pf); /* * We only check the burst mode at the end of the current capture since * it takes a full data ready cycle for the device to update the burst * array. */ adis16475_burst32_check(st); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/* + * This function updates the first tx byte from the adis message based on the + * given burst request. + */ +static void adis16575_update_msg_for_burst(struct adis *adis, u8 burst_req) +{ + unsigned int burst_max_length; + u8 *tx; + + if (adis->data->burst_max_len) + burst_max_length = adis->data->burst_max_len; + else + burst_max_length = adis->data->burst_len + adis->burst_extra_len; + + tx = adis->buffer + burst_max_length; + tx[0] = ADIS_READ_REG(burst_req); +} + +static int adis16575_custom_burst_read(struct iio_poll_func *pf, u8 burst_req) +{ + struct iio_dev *indio_dev = pf->indio_dev; + struct adis16475 *st = iio_priv(indio_dev); + struct adis *adis = &st->adis; + + adis16575_update_msg_for_burst(adis, burst_req); + + if (burst_req) + return spi_sync(adis->spi, &adis->msg); + + return adis16475_push_single_sample(pf); +} + +/* + * This handler is meant to be used for devices which support burst readings + * from FIFO (namely devices from adis1657x family). + * In order to pop the FIFO the 0x68 0x00 FIFO pop burst request has to be sent. + * If the previous device command was not a FIFO pop burst request, the FIFO pop + * burst request will simply pop the FIFO without returning valid data. + * For the nth consecutive burst request, thedevice will send the data popped + * with the (n-1)th consecutive burst request. + * In order to read the data which was popped previously, without popping the + * FIFO, the 0x00 0x00 burst request has to be sent. + * If after a 0x68 0x00 FIFO pop burst request, there is any other device access + * different from a 0x68 0x00 or a 0x00 0x00 burst request, the FIFO data popped + * previously will be lost. + */ +static irqreturn_t adis16475_trigger_handler_with_fifo(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adis16475 *st = iio_priv(indio_dev); + struct adis *adis = &st->adis; + int ret; + u16 fifo_cnt, i; + + adis_dev_auto_lock(&st->adis); + + ret = __adis_read_reg_16(adis, ADIS16575_REG_FIFO_CNT, &fifo_cnt); + if (ret) + goto unlock; + + /* + * If no sample is available, nothing can be read. This can happen if + * a the used trigger has a higher frequency than the selected sample rate. + */ + if (!fifo_cnt) + goto unlock; + + /* + * First burst request - FIFO pop: popped data will be returned in the + * next burst request. + */ + ret = adis16575_custom_burst_read(pf, adis->data->burst_reg_cmd); + if (ret) + goto unlock; + + for (i = 0; i < fifo_cnt - 1; i++) { + ret = adis16475_push_single_sample(pf); + if (ret) + goto unlock; + } + + /* FIFO read without popping */ + ret = adis16575_custom_burst_read(pf, 0); + +unlock: + /* + * We only check the burst mode at the end of the current capture since + * reading data from registers will impact the FIFO reading. + */ + adis16475_burst32_check(st); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; @@ -1289,8 +1777,18 @@ static int adis16475_config_sync_mode(struct adis16475 *st) struct device *dev = &st->adis.spi->dev; const struct adis16475_sync *sync; u32 sync_mode; + u16 max_sample_rate = st->info->int_clk + 100; u16 val; + /* if available, enable 4khz internal clock */ + if (st->info->int_clk == 4000) { + ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, + ADIS16575_SYNC_4KHZ_MASK, + (u16)ADIS16575_SYNC_4KHZ(1)); + if (ret) + return ret; + } + /* default to internal clk */ st->clk_freq = st->info->int_clk * 1000; @@ -1329,10 +1827,9 @@ static int adis16475_config_sync_mode(struct adis16475 *st) /* * In sync scaled mode, the IMU sample rate is the clk_freq * sync_scale. * Hence, default the IMU sample rate to the highest multiple of the input - * clock lower than the IMU max sample rate. The optimal range is - * 1900-2100 sps... + * clock lower than the IMU max sample rate. */ - up_scale = 2100 / st->clk_freq; + up_scale = max_sample_rate / st->clk_freq; ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, @@ -1370,34 +1867,69 @@ static int adis16475_config_irq_pin(struct adis16475 *st) u8 polarity; struct spi_device *spi = st->adis.spi; - /* - * It is possible to configure the data ready polarity. Furthermore, we - * need to update the adis struct if we want data ready as active low. - */ irq_type = irq_get_trigger_type(spi->irq); - if (irq_type == IRQ_TYPE_EDGE_RISING) { - polarity = 1; - st->adis.irq_flag = IRQF_TRIGGER_RISING; - } else if (irq_type == IRQ_TYPE_EDGE_FALLING) { - polarity = 0; - st->adis.irq_flag = IRQF_TRIGGER_FALLING; - } else { - dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n", - irq_type); - return -EINVAL; - } - val = ADIS16475_MSG_CTRL_DR_POL(polarity); - ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, - ADIS16475_MSG_CTRL_DR_POL_MASK, val); - if (ret) - return ret; - /* - * There is a delay writing to any bits written to the MSC_CTRL - * register. It should not be bigger than 200us, so 250 should be more - * than enough! - */ - usleep_range(250, 260); + if (st->adis.data->has_fifo) { + /* + * It is possible to configure the fifo watermark pin polarity. + * Furthermore, we need to update the adis struct if we want the + * watermark pin active low. + */ + if (irq_type == IRQ_TYPE_LEVEL_HIGH) { + polarity = 1; + st->adis.irq_flag = IRQF_TRIGGER_HIGH; + } else if (irq_type == IRQ_TYPE_LEVEL_LOW) { + polarity = 0; + st->adis.irq_flag = IRQF_TRIGGER_LOW; + } else { + dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n", + irq_type); + return -EINVAL; + } + + /* Configure the watermark pin polarity. */ + val = ADIS16575_WM_POL(polarity); + ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, + ADIS16575_WM_POL_MASK, val); + if (ret) + return ret; + + /* Enable watermark interrupt pin. */ + ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, + ADIS16575_WM_EN_MASK, + (u16)ADIS16575_WM_EN(1)); + if (ret) + return ret; + + } else { + /* + * It is possible to configure the data ready polarity. Furthermore, we + * need to update the adis struct if we want data ready as active low. + */ + if (irq_type == IRQ_TYPE_EDGE_RISING) { + polarity = 1; + st->adis.irq_flag = IRQF_TRIGGER_RISING; + } else if (irq_type == IRQ_TYPE_EDGE_FALLING) { + polarity = 0; + st->adis.irq_flag = IRQF_TRIGGER_FALLING; + } else { + dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n", + irq_type); + return -EINVAL; + } + + val = ADIS16475_MSG_CTRL_DR_POL(polarity); + ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, + ADIS16475_MSG_CTRL_DR_POL_MASK, val); + if (ret) + return ret; + /* + * There is a delay writing to any bits written to the MSC_CTRL + * register. It should not be bigger than 200us, so 250 should be more + * than enough! + */ + usleep_range(250, 260); + } return 0; } @@ -1408,6 +1940,7 @@ static int adis16475_probe(struct spi_device *spi) struct iio_dev *indio_dev; struct adis16475 *st; int ret; + u16 val; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) @@ -1426,7 +1959,10 @@ static int adis16475_probe(struct spi_device *spi) indio_dev->name = st->info->name; indio_dev->channels = st->info->channels; indio_dev->num_channels = st->info->num_channels; - indio_dev->info = &adis16475_info; + if (st->adis.data->has_fifo) + indio_dev->info = &adis16575_info; + else + indio_dev->info = &adis16475_info; indio_dev->modes = INDIO_DIRECT_MODE; ret = __adis_initial_startup(&st->adis); @@ -1441,10 +1977,26 @@ static int adis16475_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, - adis16475_trigger_handler); - if (ret) - return ret; + if (st->adis.data->has_fifo) { + ret = devm_adis_setup_buffer_and_trigger_with_attrs(&st->adis, indio_dev, + adis16475_trigger_handler_with_fifo, + &adis16475_buffer_ops, + adis16475_fifo_attributes); + if (ret) + return ret; + + /* Update overflow behavior to always overwrite the oldest sample. */ + val = ADIS16575_OVERWRITE_OLDEST; + ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, + ADIS16575_OVERFLOW_MASK, val); + if (ret) + return ret; + } else { + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, + adis16475_trigger_handler); + if (ret) + return ret; + } ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) @@ -1484,6 +2036,8 @@ static const struct of_device_id adis16475_of_match[] = { .data = &adis16475_chip_info[ADIS16467_3] }, { .compatible = "adi,adis16500", .data = &adis16475_chip_info[ADIS16500] }, + { .compatible = "adi,adis16501", + .data = &adis16475_chip_info[ADIS16501] }, { .compatible = "adi,adis16505-1", .data = &adis16475_chip_info[ADIS16505_1] }, { .compatible = "adi,adis16505-2", @@ -1496,6 +2050,18 @@ static const struct of_device_id adis16475_of_match[] = { .data = &adis16475_chip_info[ADIS16507_2] }, { .compatible = "adi,adis16507-3", .data = &adis16475_chip_info[ADIS16507_3] }, + { .compatible = "adi,adis16575-2", + .data = &adis16475_chip_info[ADIS16575_2] }, + { .compatible = "adi,adis16575-3", + .data = &adis16475_chip_info[ADIS16575_3] }, + { .compatible = "adi,adis16576-2", + .data = &adis16475_chip_info[ADIS16576_2] }, + { .compatible = "adi,adis16576-3", + .data = &adis16475_chip_info[ADIS16576_3] }, + { .compatible = "adi,adis16577-2", + .data = &adis16475_chip_info[ADIS16577_2] }, + { .compatible = "adi,adis16577-3", + .data = &adis16475_chip_info[ADIS16577_3] }, { }, }; MODULE_DEVICE_TABLE(of, adis16475_of_match); @@ -1515,12 +2081,19 @@ static const struct spi_device_id adis16475_ids[] = { { "adis16467-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_2] }, { "adis16467-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_3] }, { "adis16500", (kernel_ulong_t)&adis16475_chip_info[ADIS16500] }, + { "adis16501", (kernel_ulong_t)&adis16475_chip_info[ADIS16501] }, { "adis16505-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_1] }, { "adis16505-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_2] }, { "adis16505-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_3] }, { "adis16507-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_1] }, { "adis16507-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_2] }, { "adis16507-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_3] }, + { "adis16575-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16575_2] }, + { "adis16575-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16575_3] }, + { "adis16576-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16576_2] }, + { "adis16576-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16576_3] }, + { "adis16577-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16577_2] }, + { "adis16577-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16577_3] }, { } }; MODULE_DEVICE_TABLE(spi, adis16475_ids); diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index b40a55bba30c..c59ef6f7cfd4 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -104,11 +104,10 @@ */ #define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) #define ADIS16495_REG_BURST_CMD ADIS16480_REG(0x00, 0x7C) -#define ADIS16495_BURST_ID 0xA5A5 +#define ADIS16495_GYRO_ACCEL_BURST_ID 0xA5A5 +#define ADIS16545_DELTA_ANG_VEL_BURST_ID 0xC3C3 /* total number of segments in burst */ #define ADIS16495_BURST_MAX_DATA 20 -/* spi max speed in burst mode */ -#define ADIS16495_BURST_MAX_SPEED 6000000 #define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) @@ -134,6 +133,10 @@ #define ADIS16480_SYNC_MODE_MSK BIT(8) #define ADIS16480_SYNC_MODE(x) FIELD_PREP(ADIS16480_SYNC_MODE_MSK, x) +#define ADIS16545_BURST_DATA_SEL_0_CHN_MASK GENMASK(5, 0) +#define ADIS16545_BURST_DATA_SEL_1_CHN_MASK GENMASK(16, 11) +#define ADIS16545_BURST_DATA_SEL_MASK BIT(8) + struct adis16480_chip_info { unsigned int num_channels; const struct iio_chan_spec *channels; @@ -142,11 +145,14 @@ struct adis16480_chip_info { unsigned int accel_max_val; unsigned int accel_max_scale; unsigned int temp_scale; + unsigned int deltang_max_val; + unsigned int deltvel_max_val; unsigned int int_clk; unsigned int max_dec_rate; const unsigned int *filter_freqs; bool has_pps_clk_mode; bool has_sleep_cnt; + bool has_burst_delta_data; const struct adis_data adis_data; }; @@ -170,6 +176,7 @@ struct adis16480 { struct clk *ext_clk; enum adis16480_clock_mode clk_mode; unsigned int clk_freq; + u16 burst_id; /* Alignment needed for the timestamp */ __be16 data[ADIS16495_BURST_MAX_DATA] __aligned(8); }; @@ -338,7 +345,7 @@ static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2) if (t == 0) return -EINVAL; - adis_dev_lock(&st->adis); + adis_dev_auto_lock(&st->adis); /* * When using PPS mode, the input clock needs to be scaled so that we have an IMU * sample rate between (optimally) 4000 and 4250. After this, we can use the @@ -381,7 +388,7 @@ static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2) sync_scale = scaled_rate / st->clk_freq; ret = __adis_write_reg_16(&st->adis, ADIS16495_REG_SYNC_SCALE, sync_scale); if (ret) - goto error; + return ret; sample_rate = scaled_rate; } @@ -393,10 +400,7 @@ static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2) if (t > st->chip_info->max_dec_rate) t = st->chip_info->max_dec_rate; - ret = __adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t); -error: - adis_dev_unlock(&st->adis); - return ret; + return __adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t); } static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2) @@ -406,23 +410,21 @@ static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2) int ret; unsigned int freq, sample_rate = st->clk_freq; - adis_dev_lock(&st->adis); + adis_dev_auto_lock(&st->adis); if (st->clk_mode == ADIS16480_CLK_PPS) { u16 sync_scale; ret = __adis_read_reg_16(&st->adis, ADIS16495_REG_SYNC_SCALE, &sync_scale); if (ret) - goto error; + return ret; sample_rate = st->clk_freq * sync_scale; } ret = __adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t); if (ret) - goto error; - - adis_dev_unlock(&st->adis); + return ret; freq = DIV_ROUND_CLOSEST(sample_rate, (t + 1)); @@ -430,9 +432,6 @@ static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2) *val2 = (freq % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; -error: - adis_dev_unlock(&st->adis); - return ret; } enum { @@ -447,6 +446,12 @@ enum { ADIS16480_SCAN_MAGN_Z, ADIS16480_SCAN_BARO, ADIS16480_SCAN_TEMP, + ADIS16480_SCAN_DELTANG_X, + ADIS16480_SCAN_DELTANG_Y, + ADIS16480_SCAN_DELTANG_Z, + ADIS16480_SCAN_DELTVEL_X, + ADIS16480_SCAN_DELTVEL_Y, + ADIS16480_SCAN_DELTVEL_Z, }; static const unsigned int adis16480_calibbias_regs[] = { @@ -617,11 +622,11 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, offset = ad16480_filter_data[chan->scan_index][1]; enable_mask = BIT(offset + 2); - adis_dev_lock(&st->adis); + adis_dev_auto_lock(&st->adis); ret = __adis_read_reg_16(&st->adis, reg, &val); if (ret) - goto out_unlock; + return ret; if (freq == 0) { val &= ~enable_mask; @@ -643,11 +648,7 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, val |= enable_mask; } - ret = __adis_write_reg_16(&st->adis, reg, val); -out_unlock: - adis_dev_unlock(&st->adis); - - return ret; + return __adis_write_reg_16(&st->adis, reg, val); } static int adis16480_read_raw(struct iio_dev *indio_dev, @@ -690,6 +691,14 @@ static int adis16480_read_raw(struct iio_dev *indio_dev, *val = 131; /* 1310mbar = 131 kPa */ *val2 = 32767 << 16; return IIO_VAL_FRACTIONAL; + case IIO_DELTA_ANGL: + *val = st->chip_info->deltang_max_val; + *val2 = 31; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_DELTA_VELOCITY: + *val = st->chip_info->deltvel_max_val; + *val2 = 31; + return IIO_VAL_FRACTIONAL_LOG2; default: return -EINVAL; } @@ -763,6 +772,24 @@ static int adis16480_write_raw(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_CALIBSCALE), \ 32) +#define ADIS16480_DELTANG_CHANNEL(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _DELTAANG_OUT, ADIS16480_SCAN_DELTANG_ ## _mod, \ + 0, 32) + +#define ADIS16480_DELTANG_CHANNEL_NO_SCAN(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _DELTAANG_OUT, -1, 0, 32) + +#define ADIS16480_DELTVEL_CHANNEL(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _DELTAVEL_OUT, ADIS16480_SCAN_DELTVEL_ ## _mod, \ + 0, 32) + +#define ADIS16480_DELTVEL_CHANNEL_NO_SCAN(_mod) \ + ADIS16480_MOD_CHANNEL(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \ + ADIS16480_REG_ ## _mod ## _DELTAVEL_OUT, -1, 0, 32) + #define ADIS16480_MAGN_CHANNEL(_mod) \ ADIS16480_MOD_CHANNEL(IIO_MAGN, IIO_MOD_ ## _mod, \ ADIS16480_REG_ ## _mod ## _MAGN_OUT, ADIS16480_SCAN_MAGN_ ## _mod, \ @@ -818,7 +845,13 @@ static const struct iio_chan_spec adis16480_channels[] = { ADIS16480_MAGN_CHANNEL(Z), ADIS16480_PRESSURE_CHANNEL(), ADIS16480_TEMP_CHANNEL(), - IIO_CHAN_SOFT_TIMESTAMP(11) + IIO_CHAN_SOFT_TIMESTAMP(11), + ADIS16480_DELTANG_CHANNEL_NO_SCAN(X), + ADIS16480_DELTANG_CHANNEL_NO_SCAN(Y), + ADIS16480_DELTANG_CHANNEL_NO_SCAN(Z), + ADIS16480_DELTVEL_CHANNEL_NO_SCAN(X), + ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Y), + ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Z), }; static const struct iio_chan_spec adis16485_channels[] = { @@ -829,7 +862,30 @@ static const struct iio_chan_spec adis16485_channels[] = { ADIS16480_ACCEL_CHANNEL(Y), ADIS16480_ACCEL_CHANNEL(Z), ADIS16480_TEMP_CHANNEL(), - IIO_CHAN_SOFT_TIMESTAMP(7) + IIO_CHAN_SOFT_TIMESTAMP(7), + ADIS16480_DELTANG_CHANNEL_NO_SCAN(X), + ADIS16480_DELTANG_CHANNEL_NO_SCAN(Y), + ADIS16480_DELTANG_CHANNEL_NO_SCAN(Z), + ADIS16480_DELTVEL_CHANNEL_NO_SCAN(X), + ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Y), + ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Z), +}; + +static const struct iio_chan_spec adis16545_channels[] = { + ADIS16480_GYRO_CHANNEL(X), + ADIS16480_GYRO_CHANNEL(Y), + ADIS16480_GYRO_CHANNEL(Z), + ADIS16480_ACCEL_CHANNEL(X), + ADIS16480_ACCEL_CHANNEL(Y), + ADIS16480_ACCEL_CHANNEL(Z), + ADIS16480_TEMP_CHANNEL(), + ADIS16480_DELTANG_CHANNEL(X), + ADIS16480_DELTANG_CHANNEL(Y), + ADIS16480_DELTANG_CHANNEL(Z), + ADIS16480_DELTVEL_CHANNEL(X), + ADIS16480_DELTVEL_CHANNEL(Y), + ADIS16480_DELTVEL_CHANNEL(Z), + IIO_CHAN_SOFT_TIMESTAMP(17), }; enum adis16480_variant { @@ -844,6 +900,12 @@ enum adis16480_variant { ADIS16497_1, ADIS16497_2, ADIS16497_3, + ADIS16545_1, + ADIS16545_2, + ADIS16545_3, + ADIS16547_1, + ADIS16547_2, + ADIS16547_3 }; #define ADIS16480_DIAG_STAT_XGYRO_FAIL 0 @@ -872,33 +934,33 @@ static const char * const adis16480_status_error_msgs[] = { static int adis16480_enable_irq(struct adis *adis, bool enable); -#define ADIS16480_DATA(_prod_id, _timeouts, _burst_len) \ -{ \ - .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ - .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ - .prod_id_reg = ADIS16480_REG_PROD_ID, \ - .prod_id = (_prod_id), \ - .has_paging = true, \ - .read_delay = 5, \ - .write_delay = 5, \ - .self_test_mask = BIT(1), \ - .self_test_reg = ADIS16480_REG_GLOB_CMD, \ - .status_error_msgs = adis16480_status_error_msgs, \ - .status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) | \ - BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ - .enable_irq = adis16480_enable_irq, \ - .timeouts = (_timeouts), \ - .burst_reg_cmd = ADIS16495_REG_BURST_CMD, \ - .burst_len = (_burst_len), \ - .burst_max_speed_hz = ADIS16495_BURST_MAX_SPEED \ +#define ADIS16480_DATA(_prod_id, _timeouts, _burst_len, _burst_max_speed) \ +{ \ + .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ + .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ + .prod_id_reg = ADIS16480_REG_PROD_ID, \ + .prod_id = (_prod_id), \ + .has_paging = true, \ + .read_delay = 5, \ + .write_delay = 5, \ + .self_test_mask = BIT(1), \ + .self_test_reg = ADIS16480_REG_GLOB_CMD, \ + .status_error_msgs = adis16480_status_error_msgs, \ + .status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ + .enable_irq = adis16480_enable_irq, \ + .timeouts = (_timeouts), \ + .burst_reg_cmd = ADIS16495_REG_BURST_CMD, \ + .burst_len = (_burst_len), \ + .burst_max_speed_hz = _burst_max_speed \ } static const struct adis_timeout adis16485_timeouts = { @@ -925,6 +987,12 @@ static const struct adis_timeout adis16495_1_timeouts = { .self_test_ms = 20, }; +static const struct adis_timeout adis16545_timeouts = { + .reset_ms = 315, + .sw_reset_ms = 270, + .self_test_ms = 35, +}; + static const struct adis16480_chip_info adis16480_chip_info[] = { [ADIS16375] = { .channels = adis16485_channels, @@ -940,11 +1008,13 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(21973 << 16), .accel_max_scale = 18, .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(180), + .deltvel_max_val = 100, .int_clk = 2460000, .max_dec_rate = 2048, .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts, 0), + .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts, 0, 0), }, [ADIS16480] = { .channels = adis16480_channels, @@ -954,11 +1024,13 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(12500 << 16), .accel_max_scale = 10, .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 200, .int_clk = 2460000, .max_dec_rate = 2048, .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts, 0), + .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts, 0, 0), }, [ADIS16485] = { .channels = adis16485_channels, @@ -968,11 +1040,13 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(20000 << 16), .accel_max_scale = 5, .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 50, .int_clk = 2460000, .max_dec_rate = 2048, .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0), + .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0, 0), }, [ADIS16488] = { .channels = adis16480_channels, @@ -982,11 +1056,13 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(22500 << 16), .accel_max_scale = 18, .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 200, .int_clk = 2460000, .max_dec_rate = 2048, .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0), + .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0, 0), }, [ADIS16490] = { .channels = adis16485_channels, @@ -996,11 +1072,13 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(16000 << 16), .accel_max_scale = 8, .temp_scale = 14285, /* 14.285 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 200, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts, 0), + .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts, 0, 0), }, [ADIS16495_1] = { .channels = adis16485_channels, @@ -1010,13 +1088,16 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), .accel_max_scale = 8, .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(360), + .deltvel_max_val = 100, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, /* 20 elements of 16bits */ .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, - ADIS16495_BURST_MAX_DATA * 2), + ADIS16495_BURST_MAX_DATA * 2, + 6000000), }, [ADIS16495_2] = { .channels = adis16485_channels, @@ -1026,13 +1107,16 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), .accel_max_scale = 8, .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 100, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, /* 20 elements of 16bits */ .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, - ADIS16495_BURST_MAX_DATA * 2), + ADIS16495_BURST_MAX_DATA * 2, + 6000000), }, [ADIS16495_3] = { .channels = adis16485_channels, @@ -1042,13 +1126,16 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), .accel_max_scale = 8, .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(2160), + .deltvel_max_val = 100, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, /* 20 elements of 16bits */ .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, - ADIS16495_BURST_MAX_DATA * 2), + ADIS16495_BURST_MAX_DATA * 2, + 6000000), }, [ADIS16497_1] = { .channels = adis16485_channels, @@ -1058,13 +1145,16 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), .accel_max_scale = 40, .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(360), + .deltvel_max_val = 400, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, /* 20 elements of 16bits */ .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, - ADIS16495_BURST_MAX_DATA * 2), + ADIS16495_BURST_MAX_DATA * 2, + 6000000), }, [ADIS16497_2] = { .channels = adis16485_channels, @@ -1074,13 +1164,16 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), .accel_max_scale = 40, .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 400, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, /* 20 elements of 16bits */ .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, - ADIS16495_BURST_MAX_DATA * 2), + ADIS16495_BURST_MAX_DATA * 2, + 6000000), }, [ADIS16497_3] = { .channels = adis16485_channels, @@ -1090,13 +1183,136 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), .accel_max_scale = 40, .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(2160), + .deltvel_max_val = 400, .int_clk = 4250000, .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, /* 20 elements of 16bits */ .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, - ADIS16495_BURST_MAX_DATA * 2), + ADIS16495_BURST_MAX_DATA * 2, + 6000000), + }, + [ADIS16545_1] = { + .channels = adis16545_channels, + .num_channels = ARRAY_SIZE(adis16545_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(125), + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), + .accel_max_scale = 8, + .temp_scale = 7000, /* 7 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(360), + .deltvel_max_val = 100, + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .has_burst_delta_data = true, + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16545, &adis16545_timeouts, + ADIS16495_BURST_MAX_DATA * 2, + 6500000), + }, + [ADIS16545_2] = { + .channels = adis16545_channels, + .num_channels = ARRAY_SIZE(adis16545_channels), + .gyro_max_val = 18000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(450), + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), + .accel_max_scale = 8, + .temp_scale = 7000, /* 7 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 100, + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .has_burst_delta_data = true, + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16545, &adis16545_timeouts, + ADIS16495_BURST_MAX_DATA * 2, + 6500000), + }, + [ADIS16545_3] = { + .channels = adis16545_channels, + .num_channels = ARRAY_SIZE(adis16545_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(2000), + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), + .accel_max_scale = 8, + .temp_scale = 7000, /* 7 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(2160), + .deltvel_max_val = 100, + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .has_burst_delta_data = true, + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16545, &adis16545_timeouts, + ADIS16495_BURST_MAX_DATA * 2, + 6500000), + }, + [ADIS16547_1] = { + .channels = adis16545_channels, + .num_channels = ARRAY_SIZE(adis16545_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(125), + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), + .accel_max_scale = 40, + .temp_scale = 7000, /* 7 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(360), + .deltvel_max_val = 400, + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .has_burst_delta_data = true, + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16547, &adis16545_timeouts, + ADIS16495_BURST_MAX_DATA * 2, + 6500000), + }, + [ADIS16547_2] = { + .channels = adis16545_channels, + .num_channels = ARRAY_SIZE(adis16545_channels), + .gyro_max_val = 18000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(450), + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), + .accel_max_scale = 40, + .temp_scale = 7000, /* 7 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 400, + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .has_burst_delta_data = true, + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16547, &adis16545_timeouts, + ADIS16495_BURST_MAX_DATA * 2, + 6500000), + }, + [ADIS16547_3] = { + .channels = adis16545_channels, + .num_channels = ARRAY_SIZE(adis16545_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(2000), + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), + .accel_max_scale = 40, + .temp_scale = 7000, /* 7 milli degree Celsius */ + .deltang_max_val = IIO_DEGREE_TO_RAD(2160), + .deltvel_max_val = 400, + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .has_burst_delta_data = true, + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16547, &adis16545_timeouts, + ADIS16495_BURST_MAX_DATA * 2, + 6500000), }, }; @@ -1122,41 +1338,38 @@ static irqreturn_t adis16480_trigger_handler(int irq, void *p) struct adis16480 *st = iio_priv(indio_dev); struct adis *adis = &st->adis; struct device *dev = &adis->spi->dev; - int ret, bit, offset, i = 0; + int ret, bit, offset, i = 0, buff_offset = 0; __be16 *buffer; u32 crc; bool valid; - adis_dev_lock(adis); - if (adis->current_page != 0) { - adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); - adis->tx[1] = 0; - ret = spi_write(adis->spi, adis->tx, 2); - if (ret) { - dev_err(dev, "Failed to change device page: %d\n", ret); - adis_dev_unlock(adis); - goto irq_done; + adis_dev_auto_scoped_lock(adis) { + if (adis->current_page != 0) { + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); + adis->tx[1] = 0; + ret = spi_write(adis->spi, adis->tx, 2); + if (ret) { + dev_err(dev, "Failed to change device page: %d\n", ret); + goto irq_done; + } + + adis->current_page = 0; } - adis->current_page = 0; + ret = spi_sync(adis->spi, &adis->msg); + if (ret) { + dev_err(dev, "Failed to read data: %d\n", ret); + goto irq_done; + } } - ret = spi_sync(adis->spi, &adis->msg); - if (ret) { - dev_err(dev, "Failed to read data: %d\n", ret); - adis_dev_unlock(adis); - goto irq_done; - } - - adis_dev_unlock(adis); - /* * After making the burst request, the response can have one or two * 16-bit responses containing the BURST_ID depending on the sclk. If * clk > 3.6MHz, then we will have two BURST_ID in a row. If clk < 3MHZ, * we have only one. To manage that variation, we use the transition from the - * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5. If - * we not find this variation in the first 4 segments, then the data should + * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5/0xC3C3. + * If we not find this variation in the first 4 segments, then the data should * not be valid. */ buffer = adis->buffer; @@ -1164,7 +1377,7 @@ static irqreturn_t adis16480_trigger_handler(int irq, void *p) u16 curr = be16_to_cpu(buffer[offset]); u16 next = be16_to_cpu(buffer[offset + 1]); - if (curr == ADIS16495_BURST_ID && next != ADIS16495_BURST_ID) { + if (curr == st->burst_id && next != st->burst_id) { offset++; break; } @@ -1191,11 +1404,24 @@ static irqreturn_t adis16480_trigger_handler(int irq, void *p) switch (bit) { case ADIS16480_SCAN_TEMP: st->data[i++] = buffer[offset + 1]; + /* + * The temperature channel has 16-bit storage size. + * We need to perform the padding to have the buffer + * elements naturally aligned in case there are any + * 32-bit storage size channels enabled which are added + * in the buffer after the temprature data. In case + * there is no data being added after the temperature + * data, the padding is harmless. + */ + st->data[i++] = 0; break; + case ADIS16480_SCAN_DELTANG_X ... ADIS16480_SCAN_DELTVEL_Z: + buff_offset = ADIS16480_SCAN_DELTANG_X; + fallthrough; case ADIS16480_SCAN_GYRO_X ... ADIS16480_SCAN_ACCEL_Z: /* The lower register data is sequenced first */ - st->data[i++] = buffer[2 * bit + offset + 3]; - st->data[i++] = buffer[2 * bit + offset + 2]; + st->data[i++] = buffer[2 * (bit - buff_offset) + offset + 3]; + st->data[i++] = buffer[2 * (bit - buff_offset) + offset + 2]; break; } } @@ -1207,10 +1433,41 @@ irq_done: return IRQ_HANDLED; } +static const unsigned long adis16545_channel_masks[] = { + ADIS16545_BURST_DATA_SEL_0_CHN_MASK | BIT(ADIS16480_SCAN_TEMP) | BIT(17), + ADIS16545_BURST_DATA_SEL_1_CHN_MASK | BIT(ADIS16480_SCAN_TEMP) | BIT(17), + 0, +}; + +static int adis16480_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + u16 en; + int ret; + struct adis16480 *st = iio_priv(indio_dev); + + if (st->chip_info->has_burst_delta_data) { + if (*scan_mask & ADIS16545_BURST_DATA_SEL_0_CHN_MASK) { + en = FIELD_PREP(ADIS16545_BURST_DATA_SEL_MASK, 0); + st->burst_id = ADIS16495_GYRO_ACCEL_BURST_ID; + } else { + en = FIELD_PREP(ADIS16545_BURST_DATA_SEL_MASK, 1); + st->burst_id = ADIS16545_DELTA_ANG_VEL_BURST_ID; + } + + ret = __adis_update_bits(&st->adis, ADIS16480_REG_CONFIG, + ADIS16545_BURST_DATA_SEL_MASK, en); + if (ret) + return ret; + } + + return adis_update_scan_mode(indio_dev, scan_mask); +} + static const struct iio_info adis16480_info = { .read_raw = &adis16480_read_raw, .write_raw = &adis16480_write_raw, - .update_scan_mode = adis_update_scan_mode, + .update_scan_mode = &adis16480_update_scan_mode, .debugfs_reg_access = adis_debugfs_reg_access, }; @@ -1407,6 +1664,8 @@ static int adis16480_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; + if (st->chip_info->has_burst_delta_data) + indio_dev->available_scan_masks = adis16545_channel_masks; indio_dev->info = &adis16480_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1420,6 +1679,13 @@ static int adis16480_probe(struct spi_device *spi) if (ret) return ret; + /* + * By default, use burst id for gyroscope and accelerometer data. + * This is the only option for devices which do not offer delta angle + * and delta velocity burst readings. + */ + st->burst_id = ADIS16495_GYRO_ACCEL_BURST_ID; + if (st->chip_info->has_sleep_cnt) { ret = devm_add_action_or_reset(dev, adis16480_stop, indio_dev); if (ret) @@ -1493,6 +1759,12 @@ static const struct spi_device_id adis16480_ids[] = { { "adis16497-1", ADIS16497_1 }, { "adis16497-2", ADIS16497_2 }, { "adis16497-3", ADIS16497_3 }, + { "adis16545-1", ADIS16545_1 }, + { "adis16545-2", ADIS16545_2 }, + { "adis16545-3", ADIS16545_3 }, + { "adis16547-1", ADIS16547_1 }, + { "adis16547-2", ADIS16547_2 }, + { "adis16547-3", ADIS16547_3 }, { } }; MODULE_DEVICE_TABLE(spi, adis16480_ids); @@ -1509,6 +1781,12 @@ static const struct of_device_id adis16480_of_match[] = { { .compatible = "adi,adis16497-1" }, { .compatible = "adi,adis16497-2" }, { .compatible = "adi,adis16497-3" }, + { .compatible = "adi,adis16545-1" }, + { .compatible = "adi,adis16545-2" }, + { .compatible = "adi,adis16545-3" }, + { .compatible = "adi,adis16547-1" }, + { .compatible = "adi,adis16547-2" }, + { .compatible = "adi,adis16547-3" }, { }, }; MODULE_DEVICE_TABLE(of, adis16480_of_match); diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 928933027ae3..b7c1cc04492a 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -126,6 +126,26 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, } EXPORT_SYMBOL_NS_GPL(adis_update_scan_mode, IIO_ADISLIB); +static int adis_paging_trigger_handler(struct adis *adis) +{ + int ret; + + guard(mutex)(&adis->state_lock); + if (adis->current_page != 0) { + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); + adis->tx[1] = 0; + ret = spi_write(adis->spi, adis->tx, 2); + if (ret) { + dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); + return ret; + } + + adis->current_page = 0; + } + + return spi_sync(adis->spi, &adis->msg); +} + static irqreturn_t adis_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -133,25 +153,10 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) struct adis *adis = iio_device_get_drvdata(indio_dev); int ret; - if (adis->data->has_paging) { - mutex_lock(&adis->state_lock); - if (adis->current_page != 0) { - adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); - adis->tx[1] = 0; - ret = spi_write(adis->spi, adis->tx, 2); - if (ret) { - dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); - mutex_unlock(&adis->state_lock); - goto irq_done; - } - - adis->current_page = 0; - } - } - - ret = spi_sync(adis->spi, &adis->msg); if (adis->data->has_paging) - mutex_unlock(&adis->state_lock); + ret = adis_paging_trigger_handler(adis); + else + ret = spi_sync(adis->spi, &adis->msg); if (ret) { dev_err(&adis->spi->dev, "Failed to read data: %d", ret); goto irq_done; @@ -175,31 +180,36 @@ static void adis_buffer_cleanup(void *arg) } /** - * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for - * the managed adis device + * devm_adis_setup_buffer_and_trigger_with_attrs() - Sets up buffer and trigger + * for the managed adis device with buffer attributes. * @adis: The adis device * @indio_dev: The IIO device - * @trigger_handler: Optional trigger handler, may be NULL. + * @trigger_handler: Trigger handler: should handle the buffer readings. + * @ops: Optional buffer setup functions, may be NULL. + * @buffer_attrs: Extra buffer attributes. * * Returns 0 on success, a negative error code otherwise. * - * This function sets up the buffer and trigger for a adis devices. If - * 'trigger_handler' is NULL the default trigger handler will be used. The - * default trigger handler will simply read the registers assigned to the - * currently active channels. + * This function sets up the buffer (with buffer setup functions and extra + * buffer attributes) and trigger for a adis devices with buffer attributes. */ int -devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, - irq_handler_t trigger_handler) +devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis, struct iio_dev *indio_dev, + irq_handler_t trigger_handler, + const struct iio_buffer_setup_ops *ops, + const struct iio_dev_attr **buffer_attrs) { int ret; if (!trigger_handler) trigger_handler = adis_trigger_handler; - ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev, - &iio_pollfunc_store_time, - trigger_handler, NULL); + ret = devm_iio_triggered_buffer_setup_ext(&adis->spi->dev, indio_dev, + &iio_pollfunc_store_time, + trigger_handler, + IIO_BUFFER_DIRECTION_IN, + ops, + buffer_attrs); if (ret) return ret; @@ -212,5 +222,4 @@ devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup, adis); } -EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger, IIO_ADISLIB); - +EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger_with_attrs, IIO_ADISLIB); diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c index f890bf842db8..a8740b043cfe 100644 --- a/drivers/iio/imu/adis_trigger.c +++ b/drivers/iio/imu/adis_trigger.c @@ -34,17 +34,24 @@ static int adis_validate_irq_flag(struct adis *adis) if (adis->data->unmasked_drdy) adis->irq_flag |= IRQF_NO_AUTOEN; /* - * Typically this devices have data ready either on the rising edge or - * on the falling edge of the data ready pin. This checks enforces that - * one of those is set in the drivers... It defaults to - * IRQF_TRIGGER_RISING for backward compatibility with devices that - * don't support changing the pin polarity. + * Typically adis devices without FIFO have data ready either on the + * rising edge or on the falling edge of the data ready pin. + * IMU devices with FIFO support have the watermark pin level driven + * either high or low when the FIFO is filled with the desired number + * of samples. + * It defaults to IRQF_TRIGGER_RISING for backward compatibility with + * devices that don't support changing the pin polarity. */ if (direction == IRQF_TRIGGER_NONE) { adis->irq_flag |= IRQF_TRIGGER_RISING; return 0; } else if (direction != IRQF_TRIGGER_RISING && - direction != IRQF_TRIGGER_FALLING) { + direction != IRQF_TRIGGER_FALLING && !adis->data->has_fifo) { + dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n", + adis->irq_flag); + return -EINVAL; + } else if (direction != IRQF_TRIGGER_HIGH && + direction != IRQF_TRIGGER_LOW && adis->data->has_fifo) { dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n", adis->irq_flag); return -EINVAL; @@ -77,11 +84,19 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) if (ret) return ret; - ret = devm_request_irq(&adis->spi->dev, adis->spi->irq, - &iio_trigger_generic_data_rdy_poll, - adis->irq_flag, - indio_dev->name, - adis->trig); + if (adis->data->has_fifo) + ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi->irq, + NULL, + &iio_trigger_generic_data_rdy_poll, + adis->irq_flag | IRQF_ONESHOT, + indio_dev->name, + adis->trig); + else + ret = devm_request_irq(&adis->spi->dev, adis->spi->irq, + &iio_trigger_generic_data_rdy_poll, + adis->irq_flag, + indio_dev->name, + adis->trig); if (ret) return ret; diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index a77f1a8348ff..90aa04d94da5 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -26,6 +26,7 @@ #include "bmi160.h" #define BMI160_REG_CHIP_ID 0x00 +#define BMI120_CHIP_ID_VAL 0xD3 #define BMI160_CHIP_ID_VAL 0xD1 #define BMI160_REG_PMU_STATUS 0x03 @@ -112,6 +113,11 @@ .ext_info = bmi160_ext_info, \ } +static const u8 bmi_chip_ids[] = { + BMI120_CHIP_ID_VAL, + BMI160_CHIP_ID_VAL, +}; + /* scan indexes follow DATA register order */ enum bmi160_scan_axis { BMI160_SCAN_EXT_MAGN_X = 0, @@ -704,6 +710,16 @@ static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq, return bmi160_probe_trigger(indio_dev, irq, irq_type); } +static int bmi160_check_chip_id(const u8 chip_id) +{ + for (int i = 0; i < ARRAY_SIZE(bmi_chip_ids); i++) { + if (chip_id == bmi_chip_ids[i]) + return 0; + } + + return -ENODEV; +} + static int bmi160_chip_init(struct bmi160_data *data, bool use_spi) { int ret; @@ -737,12 +753,10 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi) dev_err(dev, "Error reading chip id\n"); goto disable_regulator; } - if (val != BMI160_CHIP_ID_VAL) { - dev_err(dev, "Wrong chip id, got %x expected %x\n", - val, BMI160_CHIP_ID_VAL); - ret = -ENODEV; - goto disable_regulator; - } + + ret = bmi160_check_chip_id(val); + if (ret) + dev_warn(dev, "Chip id not found: %x\n", val); ret = bmi160_set_mode(data, BMI160_ACCEL, true); if (ret) diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c index a081305254db..3aa5d748f9b6 100644 --- a/drivers/iio/imu/bmi160/bmi160_i2c.c +++ b/drivers/iio/imu/bmi160/bmi160_i2c.c @@ -37,7 +37,8 @@ static int bmi160_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bmi160_i2c_id[] = { - {"bmi160", 0}, + { "bmi120" }, + { "bmi160" }, {} }; MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id); @@ -52,12 +53,14 @@ static const struct acpi_device_id bmi160_acpi_match[] = { * the affected devices are from 2021/2022. */ {"10EC5280", 0}, + {"BMI0120", 0}, {"BMI0160", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match); static const struct of_device_id bmi160_of_match[] = { + { .compatible = "bosch,bmi120" }, { .compatible = "bosch,bmi160" }, { }, }; diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c index 8b573ea99af2..9f40500132f7 100644 --- a/drivers/iio/imu/bmi160/bmi160_spi.c +++ b/drivers/iio/imu/bmi160/bmi160_spi.c @@ -34,18 +34,21 @@ static int bmi160_spi_probe(struct spi_device *spi) } static const struct spi_device_id bmi160_spi_id[] = { + {"bmi120", 0}, {"bmi160", 0}, {} }; MODULE_DEVICE_TABLE(spi, bmi160_spi_id); static const struct acpi_device_id bmi160_acpi_match[] = { + {"BMI0120", 0}, {"BMI0160", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match); static const struct of_device_id bmi160_of_match[] = { + { .compatible = "bosch,bmi120" }, { .compatible = "bosch,bmi160" }, { }, }; diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c index 67d74a1a1b26..d708d1fe3e42 100644 --- a/drivers/iio/imu/bmi323/bmi323_core.c +++ b/drivers/iio/imu/bmi323/bmi323_core.c @@ -2084,9 +2084,11 @@ int bmi323_core_probe(struct device *dev) if (ret) return -EINVAL; - ret = iio_read_mount_matrix(dev, &data->orientation); - if (ret) - return ret; + if (!iio_read_acpi_mount_matrix(dev, &data->orientation, "ROTM")) { + ret = iio_read_mount_matrix(dev, &data->orientation); + if (ret) + return ret; + } indio_dev->name = "bmi323-imu"; indio_dev->info = &bmi323_info; diff --git a/drivers/iio/imu/bno055/bno055_i2c.c b/drivers/iio/imu/bno055/bno055_i2c.c index 6ecd750c6b76..cf3dd62a83ba 100644 --- a/drivers/iio/imu/bno055/bno055_i2c.c +++ b/drivers/iio/imu/bno055/bno055_i2c.c @@ -30,7 +30,7 @@ static int bno055_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id bno055_i2c_id[] = { - {"bno055", 0}, + { "bno055" }, { } }; MODULE_DEVICE_TABLE(i2c, bno055_i2c_id); diff --git a/drivers/iio/imu/fxos8700_i2c.c b/drivers/iio/imu/fxos8700_i2c.c index e99677ad96a2..2cc4a27a4527 100644 --- a/drivers/iio/imu/fxos8700_i2c.c +++ b/drivers/iio/imu/fxos8700_i2c.c @@ -36,7 +36,7 @@ static int fxos8700_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id fxos8700_i2c_id[] = { - {"fxos8700", 0}, + { "fxos8700" }, { } }; MODULE_DEVICE_TABLE(i2c, fxos8700_i2c_id); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index c4ac91f6bafe..3a07e43e4cf1 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -177,11 +177,15 @@ struct inv_icm42600_state { * struct inv_icm42600_sensor_state - sensor state variables * @scales: table of scales. * @scales_len: length (nb of items) of the scales table. + * @power_mode: sensor requested power mode (for common frequencies) + * @filter: sensor filter. * @ts: timestamp module states. */ struct inv_icm42600_sensor_state { const int *scales; size_t scales_len; + enum inv_icm42600_sensor_mode power_mode; + enum inv_icm42600_filter filter; struct inv_sensors_timestamp ts; }; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index 4b2566693614..56ac19814250 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -55,8 +55,108 @@ enum inv_icm42600_accel_scan { INV_ICM42600_ACCEL_SCAN_TIMESTAMP, }; +static const char * const inv_icm42600_accel_power_mode_items[] = { + "low-noise", + "low-power", +}; +static const int inv_icm42600_accel_power_mode_values[] = { + INV_ICM42600_SENSOR_MODE_LOW_NOISE, + INV_ICM42600_SENSOR_MODE_LOW_POWER, +}; +static const int inv_icm42600_accel_filter_values[] = { + INV_ICM42600_FILTER_BW_ODR_DIV_2, + INV_ICM42600_FILTER_AVG_16X, +}; + +static int inv_icm42600_accel_power_mode_set(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int idx) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); + int power_mode, filter; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + if (idx >= ARRAY_SIZE(inv_icm42600_accel_power_mode_values)) + return -EINVAL; + + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + + power_mode = inv_icm42600_accel_power_mode_values[idx]; + filter = inv_icm42600_accel_filter_values[idx]; + + guard(mutex)(&st->lock); + + /* prevent change if power mode is not supported by the ODR */ + switch (power_mode) { + case INV_ICM42600_SENSOR_MODE_LOW_NOISE: + if (st->conf.accel.odr >= INV_ICM42600_ODR_6_25HZ_LP && + st->conf.accel.odr <= INV_ICM42600_ODR_1_5625HZ_LP) + return -EPERM; + break; + case INV_ICM42600_SENSOR_MODE_LOW_POWER: + default: + if (st->conf.accel.odr <= INV_ICM42600_ODR_1KHZ_LN) + return -EPERM; + break; + } + + accel_st->power_mode = power_mode; + accel_st->filter = filter; + + return 0; +} + +static int inv_icm42600_accel_power_mode_get(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); + unsigned int idx; + int power_mode; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + guard(mutex)(&st->lock); + + /* if sensor is on, returns actual power mode and not configured one */ + switch (st->conf.accel.mode) { + case INV_ICM42600_SENSOR_MODE_LOW_POWER: + case INV_ICM42600_SENSOR_MODE_LOW_NOISE: + power_mode = st->conf.accel.mode; + break; + default: + power_mode = accel_st->power_mode; + break; + } + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_power_mode_values); ++idx) { + if (power_mode == inv_icm42600_accel_power_mode_values[idx]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_accel_power_mode_values)) + return -EINVAL; + + return idx; +} + +static const struct iio_enum inv_icm42600_accel_power_mode_enum = { + .items = inv_icm42600_accel_power_mode_items, + .num_items = ARRAY_SIZE(inv_icm42600_accel_power_mode_items), + .set = inv_icm42600_accel_power_mode_set, + .get = inv_icm42600_accel_power_mode_get, +}; + static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix), + IIO_ENUM_AVAILABLE("power_mode", IIO_SHARED_BY_TYPE, + &inv_icm42600_accel_power_mode_enum), + IIO_ENUM("power_mode", IIO_SHARED_BY_TYPE, + &inv_icm42600_accel_power_mode_enum), {}, }; @@ -120,7 +220,8 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev, if (*scan_mask & INV_ICM42600_SCAN_MASK_ACCEL_3AXIS) { /* enable accel sensor */ - conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + conf.mode = accel_st->power_mode; + conf.filter = accel_st->filter; ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_accel); if (ret) goto out_unlock; @@ -140,10 +241,12 @@ out_unlock: return ret; } -static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st, +static int inv_icm42600_accel_read_sensor(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int16_t *val) { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); struct device *dev = regmap_get_device(st->map); struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; unsigned int reg; @@ -171,7 +274,8 @@ static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st, mutex_lock(&st->lock); /* enable accel sensor */ - conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + conf.mode = accel_st->power_mode; + conf.filter = accel_st->filter; ret = inv_icm42600_set_accel_conf(st, &conf, NULL); if (ret) goto exit; @@ -273,6 +377,12 @@ static int inv_icm42600_accel_write_scale(struct iio_dev *indio_dev, /* IIO format int + micro */ static const int inv_icm42600_accel_odr[] = { + /* 1.5625Hz */ + 1, 562500, + /* 3.125Hz */ + 3, 125000, + /* 6.25Hz */ + 6, 250000, /* 12.5Hz */ 12, 500000, /* 25Hz */ @@ -292,6 +402,9 @@ static const int inv_icm42600_accel_odr[] = { }; static const int inv_icm42600_accel_odr_conv[] = { + INV_ICM42600_ODR_1_5625HZ_LP, + INV_ICM42600_ODR_3_125HZ_LP, + INV_ICM42600_ODR_6_25HZ_LP, INV_ICM42600_ODR_12_5HZ, INV_ICM42600_ODR_25HZ, INV_ICM42600_ODR_50HZ, @@ -577,7 +690,7 @@ static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev, ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; - ret = inv_icm42600_accel_read_sensor(st, chan, &data); + ret = inv_icm42600_accel_read_sensor(indio_dev, chan, &data); iio_device_release_direct_mode(indio_dev); if (ret) return ret; @@ -750,6 +863,9 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) accel_st->scales_len = ARRAY_SIZE(inv_icm42600_accel_scale); break; } + /* low-power by default at init */ + accel_st->power_mode = INV_ICM42600_SENSOR_MODE_LOW_POWER; + accel_st->filter = INV_ICM42600_FILTER_AVG_16X; /* * clock period is 32kHz (31250ns) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c index a8cf74c84c3c..aae7c56481a3 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -274,9 +274,8 @@ int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st) /* restore watermark interrupt */ if (restore) { - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, - INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, - INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); + ret = regmap_set_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); if (ret) return ret; } @@ -318,9 +317,8 @@ static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev) } /* set FIFO threshold interrupt */ - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, - INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, - INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); + ret = regmap_set_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); if (ret) goto out_unlock; @@ -375,8 +373,8 @@ static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev) goto out_unlock; /* disable FIFO threshold interrupt */ - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, - INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0); + ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); if (ret) goto out_unlock; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 62fdae530334..c3924cc6190e 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -34,12 +34,56 @@ static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { }, }; +static const struct regmap_range inv_icm42600_regmap_volatile_yes_ranges[] = { + /* Sensor data registers */ + regmap_reg_range(0x001D, 0x002A), + /* INT status, FIFO, APEX data */ + regmap_reg_range(0x002D, 0x0038), + /* Signal path reset */ + regmap_reg_range(0x004B, 0x004B), + /* FIFO lost packets */ + regmap_reg_range(0x006C, 0x006D), + /* Timestamp value */ + regmap_reg_range(0x1062, 0x1064), +}; + +static const struct regmap_range inv_icm42600_regmap_volatile_no_ranges[] = { + regmap_reg_range(0x0000, 0x001C), + regmap_reg_range(0x006E, 0x1061), + regmap_reg_range(0x1065, 0x4FFF), +}; + +static const struct regmap_access_table inv_icm42600_regmap_volatile_accesses[] = { + { + .yes_ranges = inv_icm42600_regmap_volatile_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(inv_icm42600_regmap_volatile_yes_ranges), + .no_ranges = inv_icm42600_regmap_volatile_no_ranges, + .n_no_ranges = ARRAY_SIZE(inv_icm42600_regmap_volatile_no_ranges), + }, +}; + +static const struct regmap_range inv_icm42600_regmap_rd_noinc_no_ranges[] = { + regmap_reg_range(0x0000, INV_ICM42600_REG_FIFO_DATA - 1), + regmap_reg_range(INV_ICM42600_REG_FIFO_DATA + 1, 0x4FFF), +}; + +static const struct regmap_access_table inv_icm42600_regmap_rd_noinc_accesses[] = { + { + .no_ranges = inv_icm42600_regmap_rd_noinc_no_ranges, + .n_no_ranges = ARRAY_SIZE(inv_icm42600_regmap_rd_noinc_no_ranges), + }, +}; + const struct regmap_config inv_icm42600_regmap_config = { + .name = "inv_icm42600", .reg_bits = 8, .val_bits = 8, .max_register = 0x4FFF, .ranges = inv_icm42600_regmap_ranges, .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges), + .volatile_table = inv_icm42600_regmap_volatile_accesses, + .rd_noinc_table = inv_icm42600_regmap_rd_noinc_accesses, + .cache_type = REGCACHE_RBTREE, }; EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, IIO_ICM42600); @@ -248,6 +292,23 @@ int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, if (conf->filter < 0) conf->filter = oldconf->filter; + /* force power mode against ODR when sensor is on */ + switch (conf->mode) { + case INV_ICM42600_SENSOR_MODE_LOW_POWER: + case INV_ICM42600_SENSOR_MODE_LOW_NOISE: + if (conf->odr <= INV_ICM42600_ODR_1KHZ_LN) { + conf->mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + conf->filter = INV_ICM42600_FILTER_BW_ODR_DIV_2; + } else if (conf->odr >= INV_ICM42600_ODR_6_25HZ_LP && + conf->odr <= INV_ICM42600_ODR_1_5625HZ_LP) { + conf->mode = INV_ICM42600_SENSOR_MODE_LOW_POWER; + conf->filter = INV_ICM42600_FILTER_AVG_16X; + } + break; + default: + break; + } + /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) | @@ -435,9 +496,18 @@ static int inv_icm42600_setup(struct inv_icm42600_state *st, return ret; /* sensor data in big-endian (default) */ - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, - INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN, - INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN); + ret = regmap_set_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN); + if (ret) + return ret; + + /* + * Use RC clock for accel low-power to fix glitches when switching + * gyro on/off while accel low-power is on. + */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG1, + INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC, + INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC); if (ret) return ret; @@ -532,8 +602,8 @@ static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, return ret; /* Deassert async reset for proper INT pin operation (cf datasheet) */ - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, - INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0); + ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, + INV_ICM42600_INT_CONFIG1_ASYNC_RESET); if (ret) return ret; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c index 8d33504d770f..ebb31b385881 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -28,8 +28,8 @@ static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st) INV_ICM42600_INTF_CONFIG6_MASK, INV_ICM42600_INTF_CONFIG6_I3C_EN); - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, - INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); + ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, + INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY); if (ret) return ret; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c index cc2bf1799a46..eae5ff7a3cc1 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c @@ -27,8 +27,8 @@ static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st) if (ret) return ret; - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, - INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); + ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, + INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY); if (ret) return ret; diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 7d3e061f3046..d37eca5ef761 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1505,7 +1505,7 @@ static const struct acpi_device_id kmx61_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match); static const struct i2c_device_id kmx61_id[] = { - {"kmx611021", 0}, + { "kmx611021" }, {} }; diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c index 929aff4040ed..efe05be284b6 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -561,11 +561,9 @@ struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name) } fwnode = fwnode_find_reference(dev_fwnode(dev), "io-backends", index); - if (IS_ERR(fwnode)) { - dev_err_probe(dev, PTR_ERR(fwnode), - "Cannot get Firmware reference\n"); - return ERR_CAST(fwnode); - } + if (IS_ERR(fwnode)) + return dev_err_cast_probe(dev, fwnode, + "Cannot get Firmware reference\n"); guard(mutex)(&iio_back_lock); list_for_each_entry(back, &iio_back_list, entry) { diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index cec58a604d73..d6fe105d2f40 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -9,15 +9,20 @@ * - Better memory allocation techniques? * - Alternative access techniques? */ +#include #include #include #include #include #include +#include +#include +#include #include #include #include #include +#include #include #include @@ -29,6 +34,34 @@ #include #include +#define DMABUF_ENQUEUE_TIMEOUT_MS 5000 + +MODULE_IMPORT_NS(DMA_BUF); + +struct iio_dmabuf_priv { + struct list_head entry; + struct kref ref; + + struct iio_buffer *buffer; + struct iio_dma_buffer_block *block; + + u64 context; + + /* Spinlock used for locking the dma_fence */ + spinlock_t lock; + + struct dma_buf_attachment *attach; + struct sg_table *sgt; + enum dma_data_direction dir; + atomic_t seqno; +}; + +struct iio_dma_fence { + struct dma_fence base; + struct iio_dmabuf_priv *priv; + struct work_struct work; +}; + static const char * const iio_endian_prefix[] = { [IIO_BE] = "be", [IIO_LE] = "le", @@ -333,6 +366,8 @@ void iio_buffer_init(struct iio_buffer *buffer) { INIT_LIST_HEAD(&buffer->demux_list); INIT_LIST_HEAD(&buffer->buffer_list); + INIT_LIST_HEAD(&buffer->dmabufs); + mutex_init(&buffer->dmabufs_mutex); init_waitqueue_head(&buffer->pollq); kref_init(&buffer->ref); if (!buffer->watermark) @@ -365,8 +400,16 @@ static ssize_t iio_show_fixed_type(struct device *dev, struct device_attribute *attr, char *buf) { + struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - u8 type = this_attr->c->scan_type.endianness; + const struct iio_scan_type *scan_type; + u8 type; + + scan_type = iio_get_current_scan_type(indio_dev, this_attr->c); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + type = scan_type->endianness; if (type == IIO_CPU) { #ifdef __LITTLE_ENDIAN @@ -375,21 +418,21 @@ static ssize_t iio_show_fixed_type(struct device *dev, type = IIO_BE; #endif } - if (this_attr->c->scan_type.repeat > 1) + if (scan_type->repeat > 1) return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n", iio_endian_prefix[type], - this_attr->c->scan_type.sign, - this_attr->c->scan_type.realbits, - this_attr->c->scan_type.storagebits, - this_attr->c->scan_type.repeat, - this_attr->c->scan_type.shift); + scan_type->sign, + scan_type->realbits, + scan_type->storagebits, + scan_type->repeat, + scan_type->shift); else return sysfs_emit(buf, "%s:%c%d/%d>>%u\n", iio_endian_prefix[type], - this_attr->c->scan_type.sign, - this_attr->c->scan_type.realbits, - this_attr->c->scan_type.storagebits, - this_attr->c->scan_type.shift); + scan_type->sign, + scan_type->realbits, + scan_type->storagebits, + scan_type->shift); } static ssize_t iio_scan_el_show(struct device *dev, @@ -690,20 +733,27 @@ static ssize_t enable_show(struct device *dev, struct device_attribute *attr, return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer)); } -static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, - unsigned int scan_index) +static int iio_storage_bytes_for_si(struct iio_dev *indio_dev, + unsigned int scan_index) { const struct iio_chan_spec *ch; + const struct iio_scan_type *scan_type; unsigned int bytes; ch = iio_find_channel_from_si(indio_dev, scan_index); - bytes = ch->scan_type.storagebits / 8; - if (ch->scan_type.repeat > 1) - bytes *= ch->scan_type.repeat; + scan_type = iio_get_current_scan_type(indio_dev, ch); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + bytes = scan_type->storagebits / 8; + + if (scan_type->repeat > 1) + bytes *= scan_type->repeat; + return bytes; } -static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) +static int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); @@ -721,6 +771,9 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, for_each_set_bit(i, mask, indio_dev->masklength) { length = iio_storage_bytes_for_si(indio_dev, i); + if (length < 0) + return length; + bytes = ALIGN(bytes, length); bytes += length; largest = max(largest, length); @@ -728,6 +781,9 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, if (timestamp) { length = iio_storage_bytes_for_timestamp(indio_dev); + if (length < 0) + return length; + bytes = ALIGN(bytes, length); bytes += length; largest = max(largest, length); @@ -1007,14 +1063,22 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, indio_dev->masklength, in_ind + 1); while (in_ind != out_ind) { - length = iio_storage_bytes_for_si(indio_dev, in_ind); + ret = iio_storage_bytes_for_si(indio_dev, in_ind); + if (ret < 0) + goto error_clear_mux_table; + + length = ret; /* Make sure we are aligned */ in_loc = roundup(in_loc, length) + length; in_ind = find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, in_ind + 1); } - length = iio_storage_bytes_for_si(indio_dev, in_ind); + ret = iio_storage_bytes_for_si(indio_dev, in_ind); + if (ret < 0) + goto error_clear_mux_table; + + length = ret; out_loc = roundup(out_loc, length); in_loc = roundup(in_loc, length); ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); @@ -1025,7 +1089,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, } /* Relies on scan_timestamp being last */ if (buffer->scan_timestamp) { - length = iio_storage_bytes_for_timestamp(indio_dev); + ret = iio_storage_bytes_for_timestamp(indio_dev); + if (ret < 0) + goto error_clear_mux_table; + + length = ret; out_loc = roundup(out_loc, length); in_loc = roundup(in_loc, length); ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); @@ -1493,14 +1561,55 @@ static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev) kfree(iio_dev_opaque->legacy_scan_el_group.attrs); } +static void iio_buffer_dmabuf_release(struct kref *ref) +{ + struct iio_dmabuf_priv *priv = container_of(ref, struct iio_dmabuf_priv, ref); + struct dma_buf_attachment *attach = priv->attach; + struct iio_buffer *buffer = priv->buffer; + struct dma_buf *dmabuf = attach->dmabuf; + + dma_resv_lock(dmabuf->resv, NULL); + dma_buf_unmap_attachment(attach, priv->sgt, priv->dir); + dma_resv_unlock(dmabuf->resv); + + buffer->access->detach_dmabuf(buffer, priv->block); + + dma_buf_detach(attach->dmabuf, attach); + dma_buf_put(dmabuf); + kfree(priv); +} + +static void iio_buffer_dmabuf_get(struct dma_buf_attachment *attach) +{ + struct iio_dmabuf_priv *priv = attach->importer_priv; + + kref_get(&priv->ref); +} + +static void iio_buffer_dmabuf_put(struct dma_buf_attachment *attach) +{ + struct iio_dmabuf_priv *priv = attach->importer_priv; + + kref_put(&priv->ref, iio_buffer_dmabuf_release); +} + static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep) { struct iio_dev_buffer_pair *ib = filep->private_data; struct iio_dev *indio_dev = ib->indio_dev; struct iio_buffer *buffer = ib->buffer; + struct iio_dmabuf_priv *priv, *tmp; wake_up(&buffer->pollq); + guard(mutex)(&buffer->dmabufs_mutex); + + /* Close all attached DMABUFs */ + list_for_each_entry_safe(priv, tmp, &buffer->dmabufs, entry) { + list_del_init(&priv->entry); + iio_buffer_dmabuf_put(priv->attach); + } + kfree(ib); clear_bit(IIO_BUSY_BIT_POS, &buffer->flags); iio_device_put(indio_dev); @@ -1508,11 +1617,393 @@ static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep) return 0; } +static int iio_dma_resv_lock(struct dma_buf *dmabuf, bool nonblock) +{ + if (!nonblock) + return dma_resv_lock_interruptible(dmabuf->resv, NULL); + + if (!dma_resv_trylock(dmabuf->resv)) + return -EBUSY; + + return 0; +} + +static struct dma_buf_attachment * +iio_buffer_find_attachment(struct iio_dev_buffer_pair *ib, + struct dma_buf *dmabuf, bool nonblock) +{ + struct device *dev = ib->indio_dev->dev.parent; + struct iio_buffer *buffer = ib->buffer; + struct dma_buf_attachment *attach = NULL; + struct iio_dmabuf_priv *priv; + + guard(mutex)(&buffer->dmabufs_mutex); + + list_for_each_entry(priv, &buffer->dmabufs, entry) { + if (priv->attach->dev == dev + && priv->attach->dmabuf == dmabuf) { + attach = priv->attach; + break; + } + } + + if (attach) + iio_buffer_dmabuf_get(attach); + + return attach ?: ERR_PTR(-EPERM); +} + +static int iio_buffer_attach_dmabuf(struct iio_dev_buffer_pair *ib, + int __user *user_fd, bool nonblock) +{ + struct iio_dev *indio_dev = ib->indio_dev; + struct iio_buffer *buffer = ib->buffer; + struct dma_buf_attachment *attach; + struct iio_dmabuf_priv *priv, *each; + struct dma_buf *dmabuf; + int err, fd; + + if (!buffer->access->attach_dmabuf + || !buffer->access->detach_dmabuf + || !buffer->access->enqueue_dmabuf) + return -EPERM; + + if (copy_from_user(&fd, user_fd, sizeof(fd))) + return -EFAULT; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + priv->context = dma_fence_context_alloc(1); + + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + err = PTR_ERR(dmabuf); + goto err_free_priv; + } + + attach = dma_buf_attach(dmabuf, indio_dev->dev.parent); + if (IS_ERR(attach)) { + err = PTR_ERR(attach); + goto err_dmabuf_put; + } + + err = iio_dma_resv_lock(dmabuf, nonblock); + if (err) + goto err_dmabuf_detach; + + priv->dir = buffer->direction == IIO_BUFFER_DIRECTION_IN + ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + priv->sgt = dma_buf_map_attachment(attach, priv->dir); + if (IS_ERR(priv->sgt)) { + err = PTR_ERR(priv->sgt); + dev_err(&indio_dev->dev, "Unable to map attachment: %d\n", err); + goto err_resv_unlock; + } + + kref_init(&priv->ref); + priv->buffer = buffer; + priv->attach = attach; + attach->importer_priv = priv; + + priv->block = buffer->access->attach_dmabuf(buffer, attach); + if (IS_ERR(priv->block)) { + err = PTR_ERR(priv->block); + goto err_dmabuf_unmap_attachment; + } + + dma_resv_unlock(dmabuf->resv); + + mutex_lock(&buffer->dmabufs_mutex); + + /* + * Check whether we already have an attachment for this driver/DMABUF + * combo. If we do, refuse to attach. + */ + list_for_each_entry(each, &buffer->dmabufs, entry) { + if (each->attach->dev == indio_dev->dev.parent + && each->attach->dmabuf == dmabuf) { + /* + * We unlocked the reservation object, so going through + * the cleanup code would mean re-locking it first. + * At this stage it is simpler to free the attachment + * using iio_buffer_dma_put(). + */ + mutex_unlock(&buffer->dmabufs_mutex); + iio_buffer_dmabuf_put(attach); + return -EBUSY; + } + } + + /* Otherwise, add the new attachment to our dmabufs list. */ + list_add(&priv->entry, &buffer->dmabufs); + mutex_unlock(&buffer->dmabufs_mutex); + + return 0; + +err_dmabuf_unmap_attachment: + dma_buf_unmap_attachment(attach, priv->sgt, priv->dir); +err_resv_unlock: + dma_resv_unlock(dmabuf->resv); +err_dmabuf_detach: + dma_buf_detach(dmabuf, attach); +err_dmabuf_put: + dma_buf_put(dmabuf); +err_free_priv: + kfree(priv); + + return err; +} + +static int iio_buffer_detach_dmabuf(struct iio_dev_buffer_pair *ib, + int __user *user_req, bool nonblock) +{ + struct iio_buffer *buffer = ib->buffer; + struct iio_dev *indio_dev = ib->indio_dev; + struct iio_dmabuf_priv *priv; + struct dma_buf *dmabuf; + int dmabuf_fd, ret = -EPERM; + + if (copy_from_user(&dmabuf_fd, user_req, sizeof(dmabuf_fd))) + return -EFAULT; + + dmabuf = dma_buf_get(dmabuf_fd); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + + guard(mutex)(&buffer->dmabufs_mutex); + + list_for_each_entry(priv, &buffer->dmabufs, entry) { + if (priv->attach->dev == indio_dev->dev.parent + && priv->attach->dmabuf == dmabuf) { + list_del(&priv->entry); + + /* Unref the reference from iio_buffer_attach_dmabuf() */ + iio_buffer_dmabuf_put(priv->attach); + ret = 0; + break; + } + } + + dma_buf_put(dmabuf); + + return ret; +} + +static const char * +iio_buffer_dma_fence_get_driver_name(struct dma_fence *fence) +{ + return "iio"; +} + +static void iio_buffer_dma_fence_release(struct dma_fence *fence) +{ + struct iio_dma_fence *iio_fence = + container_of(fence, struct iio_dma_fence, base); + + kfree(iio_fence); +} + +static const struct dma_fence_ops iio_buffer_dma_fence_ops = { + .get_driver_name = iio_buffer_dma_fence_get_driver_name, + .get_timeline_name = iio_buffer_dma_fence_get_driver_name, + .release = iio_buffer_dma_fence_release, +}; + +static int iio_buffer_enqueue_dmabuf(struct iio_dev_buffer_pair *ib, + struct iio_dmabuf __user *iio_dmabuf_req, + bool nonblock) +{ + struct iio_buffer *buffer = ib->buffer; + struct iio_dmabuf iio_dmabuf; + struct dma_buf_attachment *attach; + struct iio_dmabuf_priv *priv; + struct iio_dma_fence *fence; + struct dma_buf *dmabuf; + unsigned long timeout; + bool cookie, cyclic, dma_to_ram; + long retl; + u32 seqno; + int ret; + + if (copy_from_user(&iio_dmabuf, iio_dmabuf_req, sizeof(iio_dmabuf))) + return -EFAULT; + + if (iio_dmabuf.flags & ~IIO_BUFFER_DMABUF_SUPPORTED_FLAGS) + return -EINVAL; + + cyclic = iio_dmabuf.flags & IIO_BUFFER_DMABUF_CYCLIC; + + /* Cyclic flag is only supported on output buffers */ + if (cyclic && buffer->direction != IIO_BUFFER_DIRECTION_OUT) + return -EINVAL; + + dmabuf = dma_buf_get(iio_dmabuf.fd); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + + if (!iio_dmabuf.bytes_used || iio_dmabuf.bytes_used > dmabuf->size) { + ret = -EINVAL; + goto err_dmabuf_put; + } + + attach = iio_buffer_find_attachment(ib, dmabuf, nonblock); + if (IS_ERR(attach)) { + ret = PTR_ERR(attach); + goto err_dmabuf_put; + } + + priv = attach->importer_priv; + + fence = kmalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) { + ret = -ENOMEM; + goto err_attachment_put; + } + + fence->priv = priv; + + seqno = atomic_add_return(1, &priv->seqno); + + /* + * The transfers are guaranteed to be processed in the order they are + * enqueued, so we can use a simple incrementing sequence number for + * the dma_fence. + */ + dma_fence_init(&fence->base, &iio_buffer_dma_fence_ops, + &priv->lock, priv->context, seqno); + + ret = iio_dma_resv_lock(dmabuf, nonblock); + if (ret) + goto err_fence_put; + + timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS); + dma_to_ram = buffer->direction == IIO_BUFFER_DIRECTION_IN; + + /* Make sure we don't have writers */ + retl = dma_resv_wait_timeout(dmabuf->resv, + dma_resv_usage_rw(dma_to_ram), + true, timeout); + if (retl == 0) + retl = -EBUSY; + if (retl < 0) { + ret = (int)retl; + goto err_resv_unlock; + } + + if (buffer->access->lock_queue) + buffer->access->lock_queue(buffer); + + ret = dma_resv_reserve_fences(dmabuf->resv, 1); + if (ret) + goto err_queue_unlock; + + dma_resv_add_fence(dmabuf->resv, &fence->base, + dma_to_ram ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ); + dma_resv_unlock(dmabuf->resv); + + cookie = dma_fence_begin_signalling(); + + ret = buffer->access->enqueue_dmabuf(buffer, priv->block, &fence->base, + priv->sgt, iio_dmabuf.bytes_used, + cyclic); + if (ret) { + /* + * DMABUF enqueue failed, but we already added the fence. + * Signal the error through the fence completion mechanism. + */ + iio_buffer_signal_dmabuf_done(&fence->base, ret); + } + + if (buffer->access->unlock_queue) + buffer->access->unlock_queue(buffer); + + dma_fence_end_signalling(cookie); + dma_buf_put(dmabuf); + + return ret; + +err_queue_unlock: + if (buffer->access->unlock_queue) + buffer->access->unlock_queue(buffer); +err_resv_unlock: + dma_resv_unlock(dmabuf->resv); +err_fence_put: + dma_fence_put(&fence->base); +err_attachment_put: + iio_buffer_dmabuf_put(attach); +err_dmabuf_put: + dma_buf_put(dmabuf); + + return ret; +} + +static void iio_buffer_cleanup(struct work_struct *work) +{ + struct iio_dma_fence *fence = + container_of(work, struct iio_dma_fence, work); + struct iio_dmabuf_priv *priv = fence->priv; + struct dma_buf_attachment *attach = priv->attach; + + dma_fence_put(&fence->base); + iio_buffer_dmabuf_put(attach); +} + +void iio_buffer_signal_dmabuf_done(struct dma_fence *fence, int ret) +{ + struct iio_dma_fence *iio_fence = + container_of(fence, struct iio_dma_fence, base); + bool cookie = dma_fence_begin_signalling(); + + /* + * Get a reference to the fence, so that it's not freed as soon as + * it's signaled. + */ + dma_fence_get(fence); + + fence->error = ret; + dma_fence_signal(fence); + dma_fence_end_signalling(cookie); + + /* + * The fence will be unref'd in iio_buffer_cleanup. + * It can't be done here, as the unref functions might try to lock the + * resv object, which can deadlock. + */ + INIT_WORK(&iio_fence->work, iio_buffer_cleanup); + schedule_work(&iio_fence->work); +} +EXPORT_SYMBOL_GPL(iio_buffer_signal_dmabuf_done); + +static long iio_buffer_chrdev_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct iio_dev_buffer_pair *ib = filp->private_data; + void __user *_arg = (void __user *)arg; + bool nonblock = filp->f_flags & O_NONBLOCK; + + switch (cmd) { + case IIO_BUFFER_DMABUF_ATTACH_IOCTL: + return iio_buffer_attach_dmabuf(ib, _arg, nonblock); + case IIO_BUFFER_DMABUF_DETACH_IOCTL: + return iio_buffer_detach_dmabuf(ib, _arg, nonblock); + case IIO_BUFFER_DMABUF_ENQUEUE_IOCTL: + return iio_buffer_enqueue_dmabuf(ib, _arg, nonblock); + default: + return -EINVAL; + } +} + static const struct file_operations iio_buffer_chrdev_fileops = { .owner = THIS_MODULE, .llseek = noop_llseek, .read = iio_buffer_read, .write = iio_buffer_write, + .unlocked_ioctl = iio_buffer_chrdev_ioctl, + .compat_ioctl = compat_ptr_ioctl, .poll = iio_buffer_poll, .release = iio_buffer_chrdev_release, }; @@ -1592,6 +2083,22 @@ static long iio_device_buffer_ioctl(struct iio_dev *indio_dev, struct file *filp } } +static int iio_channel_validate_scan_type(struct device *dev, int ch, + const struct iio_scan_type *scan_type) +{ + /* Verify that sample bits fit into storage */ + if (scan_type->storagebits < scan_type->realbits + scan_type->shift) { + dev_err(dev, + "Channel %d storagebits (%d) < shifted realbits (%d + %d)\n", + ch, scan_type->storagebits, + scan_type->realbits, + scan_type->shift); + return -EINVAL; + } + + return 0; +} + static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, struct iio_dev *indio_dev, int index) @@ -1616,20 +2123,38 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, if (channels) { /* new magic */ for (i = 0; i < indio_dev->num_channels; i++) { + const struct iio_scan_type *scan_type; + if (channels[i].scan_index < 0) continue; - /* Verify that sample bits fit into storage */ - if (channels[i].scan_type.storagebits < - channels[i].scan_type.realbits + - channels[i].scan_type.shift) { - dev_err(&indio_dev->dev, - "Channel %d storagebits (%d) < shifted realbits (%d + %d)\n", - i, channels[i].scan_type.storagebits, - channels[i].scan_type.realbits, - channels[i].scan_type.shift); - ret = -EINVAL; - goto error_cleanup_dynamic; + if (channels[i].has_ext_scan_type) { + int j; + + /* + * get_current_scan_type is required when using + * extended scan types. + */ + if (!indio_dev->info->get_current_scan_type) { + ret = -EINVAL; + goto error_cleanup_dynamic; + } + + for (j = 0; j < channels[i].num_ext_scan_type; j++) { + scan_type = &channels[i].ext_scan_type[j]; + + ret = iio_channel_validate_scan_type( + &indio_dev->dev, i, scan_type); + if (ret) + goto error_cleanup_dynamic; + } + } else { + scan_type = &channels[i].scan_type; + + ret = iio_channel_validate_scan_type( + &indio_dev->dev, i, scan_type); + if (ret) + goto error_cleanup_dynamic; } ret = iio_buffer_add_channel_sysfs(indio_dev, buffer, @@ -1927,6 +2452,7 @@ static void iio_buffer_release(struct kref *ref) { struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref); + mutex_destroy(&buffer->dmabufs_mutex); buffer->access->release(buffer); } diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index fa7cc051b4c4..0f6cda7ffe45 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -727,20 +727,25 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals) } EXPORT_SYMBOL_GPL(iio_format_value); +ssize_t do_iio_read_channel_label(struct iio_dev *indio_dev, + const struct iio_chan_spec *c, + char *buf) +{ + if (indio_dev->info->read_label) + return indio_dev->info->read_label(indio_dev, c, buf); + + if (c->extend_name) + return sysfs_emit(buf, "%s\n", c->extend_name); + + return -EINVAL; +} + static ssize_t iio_read_channel_label(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - if (indio_dev->info->read_label) - return indio_dev->info->read_label(indio_dev, this_attr->c, buf); - - if (this_attr->c->extend_name) - return sysfs_emit(buf, "%s\n", this_attr->c->extend_name); - - return -EINVAL; + return do_iio_read_channel_label(dev_to_iio_dev(dev), + to_iio_dev_attr(attr)->c, buf); } static ssize_t iio_read_channel_info(struct device *dev, @@ -758,9 +763,11 @@ static ssize_t iio_read_channel_info(struct device *dev, INDIO_MAX_RAW_ELEMENTS, vals, &val_len, this_attr->address); - else + else if (indio_dev->info->read_raw) ret = indio_dev->info->read_raw(indio_dev, this_attr->c, &vals[0], &vals[1], this_attr->address); + else + return -EINVAL; if (ret < 0) return ret; @@ -842,6 +849,9 @@ static ssize_t iio_read_channel_info_avail(struct device *dev, int length; int type; + if (!indio_dev->info->read_avail) + return -EINVAL; + ret = indio_dev->info->read_avail(indio_dev, this_attr->c, &vals, &type, &length, this_attr->address); diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 910c1f14abd5..db06501b0e61 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -285,6 +285,9 @@ static ssize_t iio_ev_state_store(struct device *dev, if (ret < 0) return ret; + if (!indio_dev->info->write_event_config) + return -EINVAL; + ret = indio_dev->info->write_event_config(indio_dev, this_attr->c, iio_ev_attr_type(this_attr), iio_ev_attr_dir(this_attr), val); @@ -300,6 +303,9 @@ static ssize_t iio_ev_state_show(struct device *dev, struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int val; + if (!indio_dev->info->read_event_config) + return -EINVAL; + val = indio_dev->info->read_event_config(indio_dev, this_attr->c, iio_ev_attr_type(this_attr), iio_ev_attr_dir(this_attr)); @@ -318,6 +324,9 @@ static ssize_t iio_ev_value_show(struct device *dev, int val, val2, val_arr[2]; int ret; + if (!indio_dev->info->read_event_value) + return -EINVAL; + ret = indio_dev->info->read_event_value(indio_dev, this_attr->c, iio_ev_attr_type(this_attr), iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr), @@ -572,8 +581,8 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) iio_check_for_dynamic_events(indio_dev))) return 0; - ev_int = kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); - if (ev_int == NULL) + ev_int = kzalloc(sizeof(*ev_int), GFP_KERNEL); + if (!ev_int) return -ENOMEM; iio_dev_opaque->event_interface = ev_int; diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c index b51eb6cb766f..59d7615c0f56 100644 --- a/drivers/iio/industrialio-gts-helper.c +++ b/drivers/iio/industrialio-gts-helper.c @@ -362,17 +362,20 @@ static int iio_gts_build_avail_time_table(struct iio_gts *gts) for (i = gts->num_itime - 1; i >= 0; i--) { int new = gts->itime_table[i].time_us; - if (times[idx] < new) { + if (idx == 0 || times[idx - 1] < new) { times[idx++] = new; continue; } - for (j = 0; j <= idx; j++) { + for (j = 0; j < idx; j++) { + if (times[j] == new) + break; if (times[j] > new) { memmove(×[j + 1], ×[j], (idx - j) * sizeof(int)); times[j] = new; idx++; + break; } } } diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 485e6fc44a04..9f484c94bc6e 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -543,6 +543,7 @@ EXPORT_SYMBOL_GPL(devm_iio_channel_get_all); static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, enum iio_chan_info_enum info) { + const struct iio_info *iio_info = chan->indio_dev->info; int unused; int vals[INDIO_MAX_RAW_ELEMENTS]; int ret; @@ -554,15 +555,18 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, if (!iio_channel_has_info(chan->channel, info)) return -EINVAL; - if (chan->indio_dev->info->read_raw_multi) { - ret = chan->indio_dev->info->read_raw_multi(chan->indio_dev, - chan->channel, INDIO_MAX_RAW_ELEMENTS, - vals, &val_len, info); + if (iio_info->read_raw_multi) { + ret = iio_info->read_raw_multi(chan->indio_dev, + chan->channel, + INDIO_MAX_RAW_ELEMENTS, + vals, &val_len, info); *val = vals[0]; *val2 = vals[1]; + } else if (iio_info->read_raw) { + ret = iio_info->read_raw(chan->indio_dev, + chan->channel, val, val2, info); } else { - ret = chan->indio_dev->info->read_raw(chan->indio_dev, - chan->channel, val, val2, info); + return -EINVAL; } return ret; @@ -750,11 +754,15 @@ static int iio_channel_read_avail(struct iio_channel *chan, const int **vals, int *type, int *length, enum iio_chan_info_enum info) { + const struct iio_info *iio_info = chan->indio_dev->info; + if (!iio_channel_has_available(chan->channel, info)) return -EINVAL; - return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel, - vals, type, length, info); + if (iio_info->read_avail) + return iio_info->read_avail(chan->indio_dev, chan->channel, + vals, type, length, info); + return -EINVAL; } int iio_read_avail_channel_attribute(struct iio_channel *chan, @@ -917,8 +925,12 @@ EXPORT_SYMBOL_GPL(iio_get_channel_type); static int iio_channel_write(struct iio_channel *chan, int val, int val2, enum iio_chan_info_enum info) { - return chan->indio_dev->info->write_raw(chan->indio_dev, - chan->channel, val, val2, info); + const struct iio_info *iio_info = chan->indio_dev->info; + + if (iio_info->write_raw) + return iio_info->write_raw(chan->indio_dev, + chan->channel, val, val2, info); + return -EINVAL; } int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, @@ -998,3 +1010,9 @@ ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr, chan->channel, buf, len); } EXPORT_SYMBOL_GPL(iio_write_channel_ext_info); + +ssize_t iio_read_channel_label(struct iio_channel *chan, char *buf) +{ + return do_iio_read_channel_label(chan->indio_dev, chan->channel, buf); +} +EXPORT_SYMBOL_GPL(iio_read_channel_label); diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 9a587d403118..b68dcc1fbaca 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -666,6 +666,17 @@ config VEML6030 To compile this driver as a module, choose M here: the module will be called veml6030. +config VEML6040 + tristate "VEML6040 RGBW light sensor" + select REGMAP_I2C + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML6040 + RGBW light sensor. + + To compile this driver as a module, choose M here: the + module will be called veml6040. + config VEML6070 tristate "VEML6070 UV A light sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index a30f906e91ba..1a071a8e9f8e 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_VCNL4000) += vcnl4000.o obj-$(CONFIG_VCNL4035) += vcnl4035.o obj-$(CONFIG_VEML6030) += veml6030.o +obj-$(CONFIG_VEML6040) += veml6040.o obj-$(CONFIG_VEML6070) += veml6070.o obj-$(CONFIG_VEML6075) += veml6075.o obj-$(CONFIG_VL6180) += vl6180.o diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 5fd775a20176..5169f12c3eba 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -261,7 +261,7 @@ static int adjd_s311_probe(struct i2c_client *client) } static const struct i2c_device_id adjd_s311_id[] = { - { "adjd_s311", 0 }, + { "adjd_s311" }, { } }; MODULE_DEVICE_TABLE(i2c, adjd_s311_id); diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c index aa4a6c78f0aa..2e0170be077a 100644 --- a/drivers/iio/light/adux1020.c +++ b/drivers/iio/light/adux1020.c @@ -539,9 +539,8 @@ static int adux1020_write_event_config(struct iio_dev *indio_dev, * Trigger proximity interrupt when the intensity is above * or below threshold */ - ret = regmap_update_bits(data->regmap, ADUX1020_REG_PROX_TYPE, - ADUX1020_PROX_TYPE, - ADUX1020_PROX_TYPE); + ret = regmap_set_bits(data->regmap, ADUX1020_REG_PROX_TYPE, + ADUX1020_PROX_TYPE); if (ret < 0) goto fail; @@ -748,8 +747,8 @@ static int adux1020_chip_init(struct adux1020_data *data) dev_dbg(&client->dev, "Detected ADUX1020 with chip id: 0x%04x\n", val); - ret = regmap_update_bits(data->regmap, ADUX1020_REG_SW_RESET, - ADUX1020_SW_RESET, ADUX1020_SW_RESET); + ret = regmap_set_bits(data->regmap, ADUX1020_REG_SW_RESET, + ADUX1020_SW_RESET); if (ret < 0) return ret; @@ -764,8 +763,8 @@ static int adux1020_chip_init(struct adux1020_data *data) return ret; /* Use LED_IREF for proximity mode */ - ret = regmap_update_bits(data->regmap, ADUX1020_REG_LED_CURRENT, - ADUX1020_LED_PIREF_EN, 0); + ret = regmap_clear_bits(data->regmap, ADUX1020_REG_LED_CURRENT, + ADUX1020_LED_PIREF_EN); if (ret < 0) return ret; @@ -821,7 +820,7 @@ static int adux1020_probe(struct i2c_client *client) } static const struct i2c_device_id adux1020_id[] = { - { "adux1020", 0 }, + { "adux1020" }, {} }; MODULE_DEVICE_TABLE(i2c, adux1020_id); diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c index 105f379b9b41..497ea3fe3377 100644 --- a/drivers/iio/light/al3320a.c +++ b/drivers/iio/light/al3320a.c @@ -236,7 +236,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend, al3320a_resume); static const struct i2c_device_id al3320a_id[] = { - {"al3320a", 0}, + { "al3320a" }, {} }; MODULE_DEVICE_TABLE(i2c, al3320a_id); diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c index 0f978b30a232..11f2ab4ca261 100644 --- a/drivers/iio/light/apds9300.c +++ b/drivers/iio/light/apds9300.c @@ -493,7 +493,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume); static const struct i2c_device_id apds9300_id[] = { - { APDS9300_DRV_NAME, 0 }, + { APDS9300_DRV_NAME }, { } }; diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index 1065a340b12b..e9e65130b6f9 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1107,7 +1107,7 @@ static const struct dev_pm_ops apds9960_pm_ops = { }; static const struct i2c_device_id apds9960_id[] = { - { "apds9960", 0 }, + { "apds9960" }, {} }; MODULE_DEVICE_TABLE(i2c, apds9960_id); diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c index b84166c5fa06..475f44954f61 100644 --- a/drivers/iio/light/bh1780.c +++ b/drivers/iio/light/bh1780.c @@ -256,8 +256,8 @@ static DEFINE_RUNTIME_DEV_PM_OPS(bh1780_dev_pm_ops, bh1780_runtime_suspend, bh1780_runtime_resume, NULL); static const struct i2c_device_id bh1780_id[] = { - { "bh1780", 0 }, - { }, + { "bh1780" }, + { } }; MODULE_DEVICE_TABLE(i2c, bh1780_id); diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c index d48a70efca69..b6288dd25bbf 100644 --- a/drivers/iio/light/cm3232.c +++ b/drivers/iio/light/cm3232.c @@ -368,7 +368,7 @@ static void cm3232_remove(struct i2c_client *client) } static const struct i2c_device_id cm3232_id[] = { - {"cm3232", 0}, + { "cm3232" }, {} }; diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 35d20207a648..79a64e2ff812 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -250,7 +250,7 @@ static int cm3323_probe(struct i2c_client *client) } static const struct i2c_device_id cm3323_id[] = { - {"cm3323", 0}, + { "cm3323" }, {} }; MODULE_DEVICE_TABLE(i2c, cm3323_id); diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 97e559acba2b..a4a1505534c0 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -713,7 +713,7 @@ static void cm36651_remove(struct i2c_client *client) } static const struct i2c_device_id cm36651_id[] = { - { "cm36651", 0 }, + { "cm36651" }, { } }; diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index fec10d5e037e..7125e011a38a 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -692,8 +692,8 @@ static DEFINE_RUNTIME_DEV_PM_OPS(gp2ap002_dev_pm_ops, gp2ap002_runtime_suspend, gp2ap002_runtime_resume, NULL); static const struct i2c_device_id gp2ap002_id_table[] = { - { "gp2ap002", 0 }, - { }, + { "gp2ap002" }, + { } }; MODULE_DEVICE_TABLE(i2c, gp2ap002_id_table); diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 9f41724819b6..757383456da6 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -237,7 +237,6 @@ enum gp2ap020a00f_thresh_val_id { }; struct gp2ap020a00f_data { - const struct gp2ap020a00f_platform_data *pdata; struct i2c_client *client; struct mutex lock; char *buffer; @@ -1592,7 +1591,7 @@ static void gp2ap020a00f_remove(struct i2c_client *client) } static const struct i2c_device_id gp2ap020a00f_id[] = { - { GP2A_I2C_NAME, 0 }, + { GP2A_I2C_NAME }, { } }; diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c index 004ea890a4b2..6de33feada3a 100644 --- a/drivers/iio/light/iqs621-als.c +++ b/drivers/iio/light/iqs621-als.c @@ -86,8 +86,8 @@ static int iqs621_als_init(struct iqs621_als_private *iqs621_als) if (iqs621_als->prox_en) event_mask |= iqs62x->dev_desc->ir_mask; - return regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, - event_mask, 0); + return regmap_clear_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, + event_mask); } static int iqs621_als_notifier(struct notifier_block *notifier, diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index 43484c18b101..8dfc750e68c0 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -550,9 +550,9 @@ static int isl29018_chip_init(struct isl29018_chip *chip) return -ENODEV; /* Clear brownout bit */ - status = regmap_update_bits(chip->regmap, - ISL29035_REG_DEVICE_ID, - ISL29035_BOUT_MASK, 0); + status = regmap_clear_bits(chip->regmap, + ISL29035_REG_DEVICE_ID, + ISL29035_BOUT_MASK); if (status < 0) return status; } diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index 5694683389be..95bfb3ffa519 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -678,8 +678,8 @@ static DEFINE_RUNTIME_DEV_PM_OPS(isl29028_pm_ops, isl29028_suspend, isl29028_resume, NULL); static const struct i2c_device_id isl29028_id[] = { - {"isl29028", 0}, - {"isl29030", 0}, + { "isl29028" }, + { "isl29030" }, {} }; MODULE_DEVICE_TABLE(i2c, isl29028_id); diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index f1d3356d3369..59329546df58 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -327,7 +327,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume); static const struct i2c_device_id isl29125_id[] = { - { "isl29125", 0 }, + { "isl29125" }, { } }; MODULE_DEVICE_TABLE(i2c, isl29125_id); diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c index 869196746045..e7ba934c8e69 100644 --- a/drivers/iio/light/jsa1212.c +++ b/drivers/iio/light/jsa1212.c @@ -429,7 +429,7 @@ static const struct acpi_device_id jsa1212_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); static const struct i2c_device_id jsa1212_id[] = { - { JSA1212_DRIVER_NAME, 0 }, + { JSA1212_DRIVER_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, jsa1212_id); diff --git a/drivers/iio/light/lv0104cs.c b/drivers/iio/light/lv0104cs.c index a5445d58fddf..916109ec3217 100644 --- a/drivers/iio/light/lv0104cs.c +++ b/drivers/iio/light/lv0104cs.c @@ -510,7 +510,7 @@ static int lv0104cs_probe(struct i2c_client *client) } static const struct i2c_device_id lv0104cs_id[] = { - { "lv0104cs", 0 }, + { "lv0104cs" }, { } }; MODULE_DEVICE_TABLE(i2c, lv0104cs_id); diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 26b464b1b650..b935976871a6 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -598,7 +598,7 @@ static int max44000_probe(struct i2c_client *client) } static const struct i2c_device_id max44000_id[] = { - {"max44000", 0}, + { "max44000" }, { } }; MODULE_DEVICE_TABLE(i2c, max44000_id); diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c index 61ce276e86f7..3b92362675dc 100644 --- a/drivers/iio/light/max44009.c +++ b/drivers/iio/light/max44009.c @@ -534,7 +534,7 @@ static const struct of_device_id max44009_of_match[] = { MODULE_DEVICE_TABLE(of, max44009_of_match); static const struct i2c_device_id max44009_id[] = { - { "max44009", 0 }, + { "max44009" }, { } }; MODULE_DEVICE_TABLE(i2c, max44009_id); diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c index 1574310020e3..596cc48c4c34 100644 --- a/drivers/iio/light/noa1305.c +++ b/drivers/iio/light/noa1305.c @@ -268,7 +268,7 @@ static const struct of_device_id noa1305_of_match[] = { MODULE_DEVICE_TABLE(of, noa1305_of_match); static const struct i2c_device_id noa1305_ids[] = { - { "noa1305", 0 }, + { "noa1305" }, { } }; MODULE_DEVICE_TABLE(i2c, noa1305_ids); diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index cb41e5ee8ec1..887c4b776a86 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -822,7 +822,7 @@ static void opt3001_remove(struct i2c_client *client) } static const struct i2c_device_id opt3001_id[] = { - { "opt3001", 0 }, + { "opt3001" }, { } /* Terminating Entry */ }; MODULE_DEVICE_TABLE(i2c, opt3001_id); diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c index 636432c45651..b920bf82c102 100644 --- a/drivers/iio/light/pa12203001.c +++ b/drivers/iio/light/pa12203001.c @@ -462,7 +462,7 @@ static const struct acpi_device_id pa12203001_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match); static const struct i2c_device_id pa12203001_id[] = { - { "txcpa122", 0 }, + { "txcpa122" }, {} }; diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c index bf3de853a811..4937bf6fa046 100644 --- a/drivers/iio/light/rohm-bu27034.c +++ b/drivers/iio/light/rohm-bu27034.c @@ -223,12 +223,6 @@ struct bu27034_data { } scan; }; -struct bu27034_result { - u16 ch0; - u16 ch1; - u16 ch2; -}; - static const struct regmap_range bu27034_volatile_ranges[] = { { .range_min = BU27034_REG_SYSTEM_CONTROL, diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 40d5732b5e32..78c08e0bd077 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -1109,7 +1109,7 @@ static const struct acpi_device_id rpr0521_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match); static const struct i2c_device_id rpr0521_id[] = { - {"rpr0521", 0}, + { "rpr0521" }, { } }; diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c index ea2c437199c0..eeff6cc792f2 100644 --- a/drivers/iio/light/si1133.c +++ b/drivers/iio/light/si1133.c @@ -1055,7 +1055,7 @@ static int si1133_probe(struct i2c_client *client) } static const struct i2c_device_id si1133_ids[] = { - { "si1133", 0 }, + { "si1133" }, { } }; MODULE_DEVICE_TABLE(i2c, si1133_ids); diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c index d4e17079b2f4..fba3997574bb 100644 --- a/drivers/iio/light/st_uvis25_core.c +++ b/drivers/iio/light/st_uvis25_core.c @@ -330,8 +330,8 @@ static int st_uvis25_suspend(struct device *dev) struct iio_dev *iio_dev = dev_get_drvdata(dev); struct st_uvis25_hw *hw = iio_priv(iio_dev); - return regmap_update_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR, - ST_UVIS25_REG_ODR_MASK, 0); + return regmap_clear_bits(hw->regmap, ST_UVIS25_REG_CTRL1_ADDR, + ST_UVIS25_REG_ODR_MASK); } static int st_uvis25_resume(struct device *dev) diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index 08d471438175..e3470d6743ef 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -37,6 +37,8 @@ #define STK3310_CHIP_ID_VAL 0x13 #define STK3311_CHIP_ID_VAL 0x1D +#define STK3311A_CHIP_ID_VAL 0x15 +#define STK3311S34_CHIP_ID_VAL 0x1E #define STK3311X_CHIP_ID_VAL 0x12 #define STK3335_CHIP_ID_VAL 0x51 #define STK3310_PSINT_EN 0x01 @@ -81,6 +83,15 @@ static const struct reg_field stk3310_reg_field_flag_psint = static const struct reg_field stk3310_reg_field_flag_nf = REG_FIELD(STK3310_REG_FLAG, 0, 0); +static const u8 stk3310_chip_ids[] = { + STK3310_CHIP_ID_VAL, + STK3311A_CHIP_ID_VAL, + STK3311S34_CHIP_ID_VAL, + STK3311X_CHIP_ID_VAL, + STK3311_CHIP_ID_VAL, + STK3335_CHIP_ID_VAL, +}; + /* Estimate maximum proximity values with regard to measurement scale. */ static const int stk3310_ps_max[4] = { STK3310_PS_MAX_VAL / 640, @@ -197,6 +208,16 @@ static const struct attribute_group stk3310_attribute_group = { .attrs = stk3310_attributes }; +static int stk3310_check_chip_id(const u8 chip_id) +{ + for (int i = 0; i < ARRAY_SIZE(stk3310_chip_ids); i++) { + if (chip_id == stk3310_chip_ids[i]) + return 0; + } + + return -ENODEV; +} + static int stk3310_get_index(const int table[][2], int table_size, int val, int val2) { @@ -473,13 +494,9 @@ static int stk3310_init(struct iio_dev *indio_dev) if (ret < 0) return ret; - if (chipid != STK3310_CHIP_ID_VAL && - chipid != STK3311_CHIP_ID_VAL && - chipid != STK3311X_CHIP_ID_VAL && - chipid != STK3335_CHIP_ID_VAL) { - dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); - return -ENODEV; - } + ret = stk3310_check_chip_id(chipid); + if (ret < 0) + dev_warn(&client->dev, "unknown chip id: 0x%x\n", chipid); state = STK3310_STATE_EN_ALS | STK3310_STATE_EN_PS; ret = stk3310_set_state(data, state); @@ -683,9 +700,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend, stk3310_resume); static const struct i2c_device_id stk3310_i2c_id[] = { - {"STK3310", 0}, - {"STK3311", 0}, - {"STK3335", 0}, + { "STK3310" }, + { "STK3311" }, + { "STK3335" }, {} }; MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id); diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index dcdd85b006be..c9566615b964 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -363,7 +363,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tcs3414_pm_ops, tcs3414_suspend, tcs3414_resume); static const struct i2c_device_id tcs3414_id[] = { - { "tcs3414", 0 }, + { "tcs3414" }, { } }; MODULE_DEVICE_TABLE(i2c, tcs3414_id); diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 75fcf2c93717..89384dba83dd 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -599,7 +599,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tcs3472_pm_ops, tcs3472_suspend, tcs3472_resume); static const struct i2c_device_id tcs3472_id[] = { - { "tcs3472", 0 }, + { "tcs3472" }, { } }; MODULE_DEVICE_TABLE(i2c, tcs3472_id); diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c index 4da7d78906d4..a5788c09ad02 100644 --- a/drivers/iio/light/tsl4531.c +++ b/drivers/iio/light/tsl4531.c @@ -227,7 +227,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, tsl4531_resume); static const struct i2c_device_id tsl4531_id[] = { - { "tsl4531", 0 }, + { "tsl4531" }, { } }; MODULE_DEVICE_TABLE(i2c, tsl4531_id); diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 9189a1d4d7e1..de6967ac3b0b 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -955,7 +955,7 @@ static const struct acpi_device_id us5182d_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); static const struct i2c_device_id us5182d_id[] = { - { "usd5182", 0 }, + { "usd5182" }, {} }; diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 56bbefbc0ae6..337a1332c2c6 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -653,7 +653,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4035_pm_ops, vcnl4035_runtime_suspend, vcnl4035_runtime_resume, NULL); static const struct i2c_device_id vcnl4035_id[] = { - { "vcnl4035", 0 }, + { "vcnl4035" }, { } }; MODULE_DEVICE_TABLE(i2c, vcnl4035_id); diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index 043f233d9bdb..2e86d310952e 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -144,8 +144,8 @@ static const struct attribute_group veml6030_event_attr_group = { static int veml6030_als_pwr_on(struct veml6030_data *data) { - return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, - VEML6030_ALS_SD, 0); + return regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF, + VEML6030_ALS_SD); } static int veml6030_als_shut_down(struct veml6030_data *data) @@ -881,7 +881,7 @@ static const struct of_device_id veml6030_of_match[] = { MODULE_DEVICE_TABLE(of, veml6030_of_match); static const struct i2c_device_id veml6030_id[] = { - { "veml6030", 0 }, + { "veml6030" }, { } }; MODULE_DEVICE_TABLE(i2c, veml6030_id); diff --git a/drivers/iio/light/veml6040.c b/drivers/iio/light/veml6040.c new file mode 100644 index 000000000000..216e271001a8 --- /dev/null +++ b/drivers/iio/light/veml6040.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Vishay VEML6040 RGBW light sensor driver + * + * Copyright (C) 2024 Sentec AG + * Author: Arthur Becker + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* VEML6040 Configuration Registers + * + * SD: Shutdown + * AF: Auto / Force Mode (Auto Measurements On:0, Off:1) + * TR: Trigger Measurement (when AF Bit is set) + * IT: Integration Time + */ +#define VEML6040_CONF_REG 0x000 +#define VEML6040_CONF_SD_MSK BIT(0) +#define VEML6040_CONF_AF_MSK BIT(1) +#define VEML6040_CONF_TR_MSK BIT(2) +#define VEML6040_CONF_IT_MSK GENMASK(6, 4) +#define VEML6040_CONF_IT_40_MS 0 +#define VEML6040_CONF_IT_80_MS 1 +#define VEML6040_CONF_IT_160_MS 2 +#define VEML6040_CONF_IT_320_MS 3 +#define VEML6040_CONF_IT_640_MS 4 +#define VEML6040_CONF_IT_1280_MS 5 + +/* VEML6040 Read Only Registers */ +#define VEML6040_REG_R 0x08 +#define VEML6040_REG_G 0x09 +#define VEML6040_REG_B 0x0A +#define VEML6040_REG_W 0x0B + +static const int veml6040_it_ms[] = { 40, 80, 160, 320, 640, 1280 }; + +enum veml6040_chan { + CH_RED, + CH_GREEN, + CH_BLUE, + CH_WHITE, +}; + +struct veml6040_data { + struct i2c_client *client; + struct regmap *regmap; +}; + +static const struct regmap_config veml6040_regmap_config = { + .name = "veml6040_regmap", + .reg_bits = 8, + .val_bits = 16, + .max_register = VEML6040_REG_W, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static int veml6040_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + int ret, reg, it_index; + struct veml6040_data *data = iio_priv(indio_dev); + struct regmap *regmap = data->regmap; + struct device *dev = &data->client->dev; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(regmap, chan->address, ®); + if (ret) { + dev_err(dev, "Data read failed: %d\n", ret); + return ret; + } + *val = reg; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_INT_TIME: + ret = regmap_read(regmap, VEML6040_CONF_REG, ®); + if (ret) { + dev_err(dev, "Data read failed: %d\n", ret); + return ret; + } + it_index = FIELD_GET(VEML6040_CONF_IT_MSK, reg); + if (it_index >= ARRAY_SIZE(veml6040_it_ms)) { + dev_err(dev, "Invalid Integration Time Set"); + return -EINVAL; + } + *val = veml6040_it_ms[it_index]; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int veml6040_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct veml6040_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + for (int i = 0; i < ARRAY_SIZE(veml6040_it_ms); i++) { + if (veml6040_it_ms[i] != val) + continue; + + return regmap_update_bits(data->regmap, + VEML6040_CONF_REG, + VEML6040_CONF_IT_MSK, + FIELD_PREP(VEML6040_CONF_IT_MSK, i)); + } + return -EINVAL; + default: + return -EINVAL; + } +} + +static int veml6040_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(veml6040_it_ms); + *vals = veml6040_it_ms; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + + default: + return -EINVAL; + } +} + +static const struct iio_info veml6040_info = { + .read_raw = veml6040_read_raw, + .write_raw = veml6040_write_raw, + .read_avail = veml6040_read_avail, +}; + +static const struct iio_chan_spec veml6040_channels[] = { + { + .type = IIO_INTENSITY, + .address = VEML6040_REG_R, + .channel = CH_RED, + .channel2 = IIO_MOD_LIGHT_RED, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_type_available = + BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_INTENSITY, + .address = VEML6040_REG_G, + .channel = CH_GREEN, + .channel2 = IIO_MOD_LIGHT_GREEN, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_type_available = + BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_INTENSITY, + .address = VEML6040_REG_B, + .channel = CH_BLUE, + .channel2 = IIO_MOD_LIGHT_BLUE, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_type_available = + BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_INTENSITY, + .address = VEML6040_REG_W, + .channel = CH_WHITE, + .channel2 = IIO_MOD_LIGHT_CLEAR, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_type_available = + BIT(IIO_CHAN_INFO_INT_TIME), + } +}; + +static void veml6040_shutdown_action(void *data) +{ + struct veml6040_data *veml6040_data = data; + + regmap_update_bits(veml6040_data->regmap, VEML6040_CONF_REG, + VEML6040_CONF_SD_MSK, VEML6040_CONF_SD_MSK); +} + +static int veml6040_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct veml6040_data *data; + struct iio_dev *indio_dev; + struct regmap *regmap; + const int init_config = + FIELD_PREP(VEML6040_CONF_IT_MSK, VEML6040_CONF_IT_40_MS) | + FIELD_PREP(VEML6040_CONF_AF_MSK, 0) | + FIELD_PREP(VEML6040_CONF_SD_MSK, 0); + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return dev_err_probe(dev, -EOPNOTSUPP, + "I2C adapter doesn't support plain I2C\n"); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return dev_err_probe(dev, -ENOMEM, + "IIO device allocation failed\n"); + + regmap = devm_regmap_init_i2c(client, &veml6040_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Regmap setup failed\n"); + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + data->regmap = regmap; + + indio_dev->name = "veml6040"; + indio_dev->info = &veml6040_info; + indio_dev->channels = veml6040_channels; + indio_dev->num_channels = ARRAY_SIZE(veml6040_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return ret; + + ret = regmap_write(regmap, VEML6040_CONF_REG, init_config); + if (ret) + return dev_err_probe(dev, ret, + "Could not set initial config\n"); + + ret = devm_add_action_or_reset(dev, veml6040_shutdown_action, data); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct i2c_device_id veml6040_id_table[] = { + {"veml6040"}, + {} +}; +MODULE_DEVICE_TABLE(i2c, veml6040_id_table); + +static const struct of_device_id veml6040_of_match[] = { + {.compatible = "vishay,veml6040"}, + {} +}; +MODULE_DEVICE_TABLE(of, veml6040_of_match); + +static struct i2c_driver veml6040_driver = { + .probe = veml6040_probe, + .id_table = veml6040_id_table, + .driver = { + .name = "veml6040", + .of_match_table = veml6040_of_match, + }, +}; +module_i2c_driver(veml6040_driver); + +MODULE_DESCRIPTION("veml6040 RGBW light sensor driver"); +MODULE_AUTHOR("Arthur Becker "); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index d99bf3ae0fe8..f8321d346d77 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -189,7 +189,7 @@ static void veml6070_remove(struct i2c_client *client) } static const struct i2c_device_id veml6070_id[] = { - { "veml6070", 0 }, + { "veml6070" }, { } }; MODULE_DEVICE_TABLE(i2c, veml6070_id); diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c index dcadf6428a87..a1b2b3c0b4c8 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -527,7 +527,7 @@ static const struct of_device_id vl6180_of_match[] = { MODULE_DEVICE_TABLE(of, vl6180_of_match); static const struct i2c_device_id vl6180_id[] = { - { "vl6180", 0 }, + { "vl6180" }, { } }; MODULE_DEVICE_TABLE(i2c, vl6180_id); diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index d370193a4742..327f94e447af 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -545,7 +545,7 @@ static int zopt2201_probe(struct i2c_client *client) } static const struct i2c_device_id zopt2201_id[] = { - { "zopt2201", 0 }, + { "zopt2201" }, { } }; MODULE_DEVICE_TABLE(i2c, zopt2201_id); diff --git a/drivers/iio/magnetometer/af8133j.c b/drivers/iio/magnetometer/af8133j.c index 742bbdf25f08..d81d89af6283 100644 --- a/drivers/iio/magnetometer/af8133j.c +++ b/drivers/iio/magnetometer/af8133j.c @@ -505,7 +505,7 @@ static const struct of_device_id af8133j_of_match[] = { MODULE_DEVICE_TABLE(of, af8133j_of_match); static const struct i2c_device_id af8133j_id[] = { - { "af8133j", 0 }, + { "af8133j" }, { } }; MODULE_DEVICE_TABLE(i2c, af8133j_id); diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index c74d11943ec7..961b1e0bfb13 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -327,10 +327,7 @@ static int ak8974_trigmeas(struct ak8974 *ak8974) } /* Force a measurement */ - return regmap_update_bits(ak8974->map, - AK8974_CTRL3, - AK8974_CTRL3_FORCE, - AK8974_CTRL3_FORCE); + return regmap_set_bits(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_FORCE); } static int ak8974_await_drdy(struct ak8974 *ak8974) @@ -438,10 +435,7 @@ static int ak8974_selftest(struct ak8974 *ak8974) } /* Trigger self-test */ - ret = regmap_update_bits(ak8974->map, - AK8974_CTRL3, - AK8974_CTRL3_SELFTEST, - AK8974_CTRL3_SELFTEST); + ret = regmap_set_bits(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_SELFTEST); if (ret) { dev_err(dev, "could not write CTRL3\n"); return ret; @@ -1025,10 +1019,10 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ak8974_dev_pm_ops, ak8974_runtime_suspend, ak8974_runtime_resume, NULL); static const struct i2c_device_id ak8974_id[] = { - {"ami305", 0 }, - {"ami306", 0 }, - {"ak8974", 0 }, - {"hscdtd008a", 0 }, + { "ami305" }, + { "ami306" }, + { "ak8974" }, + { "hscdtd008a" }, {} }; MODULE_DEVICE_TABLE(i2c, ak8974_id); diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c index 48d9c698f520..a28d46d59875 100644 --- a/drivers/iio/magnetometer/bmc150_magn_i2c.c +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c @@ -47,9 +47,9 @@ static const struct acpi_device_id bmc150_magn_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); static const struct i2c_device_id bmc150_magn_i2c_id[] = { - {"bmc150_magn", 0}, - {"bmc156_magn", 0}, - {"bmm150_magn", 0}, + { "bmc150_magn" }, + { "bmc156_magn" }, + { "bmm150_magn" }, {} }; MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index deffe3ca9004..5295dc0100e4 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -624,7 +624,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume); static const struct i2c_device_id mag3110_id[] = { - { "mag3110", 0 }, + { "mag3110" }, { } }; MODULE_DEVICE_TABLE(i2c, mag3110_id); diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 6b9f4b056191..dd480a4a5f98 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -186,9 +186,8 @@ static int mmc35240_hw_set(struct mmc35240_data *data, bool set) * Recharge the capacitor at VCAP pin, requested to be issued * before a SET/RESET command. */ - ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, - MMC35240_CTRL0_REFILL_BIT, - MMC35240_CTRL0_REFILL_BIT); + ret = regmap_set_bits(data->regmap, MMC35240_REG_CTRL0, + MMC35240_CTRL0_REFILL_BIT); if (ret < 0) return ret; usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1); @@ -198,8 +197,7 @@ static int mmc35240_hw_set(struct mmc35240_data *data, bool set) else coil_bit = MMC35240_CTRL0_RESET_BIT; - return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, - coil_bit, coil_bit); + return regmap_set_bits(data->regmap, MMC35240_REG_CTRL0, coil_bit); } @@ -563,7 +561,7 @@ static const struct acpi_device_id mmc35240_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); static const struct i2c_device_id mmc35240_id[] = { - {"mmc35240", 0}, + { "mmc35240" }, {} }; MODULE_DEVICE_TABLE(i2c, mmc35240_id); diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c index 218b1ce076c1..4187abe12784 100644 --- a/drivers/iio/magnetometer/tmag5273.c +++ b/drivers/iio/magnetometer/tmag5273.c @@ -118,11 +118,9 @@ struct tmag5273_data { unsigned int version; char name[16]; unsigned int conv_avg; - unsigned int scale; enum tmag5273_scale_index scale_index; unsigned int angle_measurement; struct regmap *map; - struct regulator *vcc; /* * Locks the sensor for exclusive use during a measurement (which diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c index edd8c69f6d2e..2953403bef53 100644 --- a/drivers/iio/multiplexer/iio-mux.c +++ b/drivers/iio/multiplexer/iio-mux.c @@ -30,7 +30,6 @@ struct mux { int cached_state; struct mux_control *control; struct iio_channel *parent; - struct iio_dev *indio_dev; struct iio_chan_spec *chan; struct iio_chan_spec_ext_info *ext_info; struct mux_child *child; diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index bd0f2c3bf2f2..c2c6b2b29867 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -405,8 +405,8 @@ static const struct of_device_id lmp91000_of_match[] = { MODULE_DEVICE_TABLE(of, lmp91000_of_match); static const struct i2c_device_id lmp91000_id[] = { - { "lmp91000", 0 }, - { "lmp91002", 0 }, + { "lmp91000" }, + { "lmp91002" }, {} }; MODULE_DEVICE_TABLE(i2c, lmp91000_id); diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 221fa2c552ae..49081b729618 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -52,7 +53,6 @@ */ enum { AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD }; - enum bmp380_odr { BMP380_ODR_200HZ, BMP380_ODR_100HZ, @@ -181,18 +181,19 @@ static int bmp280_read_calib(struct bmp280_data *data) struct bmp280_calib *calib = &data->calib.bmp280; int ret; - /* Read temperature and pressure calibration values. */ ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, - data->bmp280_cal_buf, sizeof(data->bmp280_cal_buf)); - if (ret < 0) { + data->bmp280_cal_buf, + sizeof(data->bmp280_cal_buf)); + if (ret) { dev_err(data->dev, - "failed to read temperature and pressure calibration parameters\n"); + "failed to read calibration parameters\n"); return ret; } - /* Toss the temperature and pressure calibration data into the entropy pool */ - add_device_randomness(data->bmp280_cal_buf, sizeof(data->bmp280_cal_buf)); + /* Toss calibration data into the entropy pool */ + add_device_randomness(data->bmp280_cal_buf, + sizeof(data->bmp280_cal_buf)); /* Parse temperature calibration values. */ calib->T1 = le16_to_cpu(data->bmp280_cal_buf[T1]); @@ -222,10 +223,8 @@ static int bme280_read_calib(struct bmp280_data *data) /* Load shared calibration params with bmp280 first */ ret = bmp280_read_calib(data); - if (ret < 0) { - dev_err(dev, "failed to read common bmp280 calibration parameters\n"); + if (ret) return ret; - } /* * Read humidity calibration values. @@ -235,47 +234,47 @@ static int bme280_read_calib(struct bmp280_data *data) * Humidity data is only available on BME280. */ - ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &tmp); - if (ret < 0) { + ret = regmap_read(data->regmap, BME280_REG_COMP_H1, &tmp); + if (ret) { dev_err(dev, "failed to read H1 comp value\n"); return ret; } calib->H1 = tmp; - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, + ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H2, &data->le16, sizeof(data->le16)); - if (ret < 0) { + if (ret) { dev_err(dev, "failed to read H2 comp value\n"); return ret; } calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15); - ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp); - if (ret < 0) { + ret = regmap_read(data->regmap, BME280_REG_COMP_H3, &tmp); + if (ret) { dev_err(dev, "failed to read H3 comp value\n"); return ret; } calib->H3 = tmp; - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, + ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H4, &data->be16, sizeof(data->be16)); - if (ret < 0) { + if (ret) { dev_err(dev, "failed to read H4 comp value\n"); return ret; } calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) | (be16_to_cpu(data->be16) & 0xf), 11); - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, + ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H5, &data->le16, sizeof(data->le16)); - if (ret < 0) { + if (ret) { dev_err(dev, "failed to read H5 comp value\n"); return ret; } - calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11); + calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11); - ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp); - if (ret < 0) { + ret = regmap_read(data->regmap, BME280_REG_COMP_H6, &tmp); + if (ret) { dev_err(dev, "failed to read H6 comp value\n"); return ret; } @@ -283,20 +282,43 @@ static int bme280_read_calib(struct bmp280_data *data) return 0; } + +static int bme280_read_humid_adc(struct bmp280_data *data, u16 *adc_humidity) +{ + u16 value_humidity; + int ret; + + ret = regmap_bulk_read(data->regmap, BME280_REG_HUMIDITY_MSB, + &data->be16, sizeof(data->be16)); + if (ret) { + dev_err(data->dev, "failed to read humidity\n"); + return ret; + } + + value_humidity = be16_to_cpu(data->be16); + if (value_humidity == BMP280_HUMIDITY_SKIPPED) { + dev_err(data->dev, "reading humidity skipped\n"); + return -EIO; + } + *adc_humidity = value_humidity; + + return 0; +} + /* * Returns humidity in percent, resolution is 0.01 percent. Output value of * "47445" represents 47445/1024 = 46.333 %RH. * * Taken from BME280 datasheet, Section 4.2.3, "Compensation formula". */ -static u32 bmp280_compensate_humidity(struct bmp280_data *data, - s32 adc_humidity) +static u32 bme280_compensate_humidity(struct bmp280_data *data, + u16 adc_humidity, s32 t_fine) { struct bmp280_calib *calib = &data->calib.bmp280; s32 var; - var = ((s32)data->t_fine) - (s32)76800; - var = ((((adc_humidity << 14) - (calib->H4 << 20) - (calib->H5 * var)) + var = t_fine - (s32)76800; + var = (((((s32)adc_humidity << 14) - (calib->H4 << 20) - (calib->H5 * var)) + (s32)16384) >> 15) * (((((((var * calib->H6) >> 10) * (((var * (s32)calib->H3) >> 11) + (s32)32768)) >> 10) + (s32)2097152) * calib->H2 + 8192) >> 14); @@ -305,7 +327,29 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data, var = clamp_val(var, 0, 419430400); return var >> 12; -}; +} + +static int bmp280_read_temp_adc(struct bmp280_data *data, u32 *adc_temp) +{ + u32 value_temp; + int ret; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, + data->buf, sizeof(data->buf)); + if (ret) { + dev_err(data->dev, "failed to read temperature\n"); + return ret; + } + + value_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf)); + if (value_temp == BMP280_TEMP_SKIPPED) { + dev_err(data->dev, "reading temperature skipped\n"); + return -EIO; + } + *adc_temp = value_temp; + + return 0; +} /* * Returns temperature in DegC, resolution is 0.01 DegC. Output value of @@ -314,20 +358,58 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data, * * Taken from datasheet, Section 3.11.3, "Compensation formula". */ -static s32 bmp280_compensate_temp(struct bmp280_data *data, - s32 adc_temp) +static s32 bmp280_calc_t_fine(struct bmp280_data *data, u32 adc_temp) { struct bmp280_calib *calib = &data->calib.bmp280; s32 var1, var2; - var1 = (((adc_temp >> 3) - ((s32)calib->T1 << 1)) * + var1 = (((((s32)adc_temp) >> 3) - ((s32)calib->T1 << 1)) * ((s32)calib->T2)) >> 11; - var2 = (((((adc_temp >> 4) - ((s32)calib->T1)) * - ((adc_temp >> 4) - ((s32)calib->T1))) >> 12) * - ((s32)calib->T3)) >> 14; - data->t_fine = var1 + var2; + var2 = (((((((s32)adc_temp) >> 4) - ((s32)calib->T1)) * + ((((s32)adc_temp >> 4) - ((s32)calib->T1))) >> 12) * + ((s32)calib->T3))) >> 14; + return var1 + var2; /* t_fine = var1 + var2 */ +} - return (data->t_fine * 5 + 128) >> 8; +static int bmp280_get_t_fine(struct bmp280_data *data, s32 *t_fine) +{ + u32 adc_temp; + int ret; + + ret = bmp280_read_temp_adc(data, &adc_temp); + if (ret) + return ret; + + *t_fine = bmp280_calc_t_fine(data, adc_temp); + + return 0; +} + +static s32 bmp280_compensate_temp(struct bmp280_data *data, u32 adc_temp) +{ + return (bmp280_calc_t_fine(data, adc_temp) * 5 + 128) / 256; +} + +static int bmp280_read_press_adc(struct bmp280_data *data, u32 *adc_press) +{ + u32 value_press; + int ret; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, + data->buf, sizeof(data->buf)); + if (ret) { + dev_err(data->dev, "failed to read pressure\n"); + return ret; + } + + value_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf)); + if (value_press == BMP280_PRESS_SKIPPED) { + dev_err(data->dev, "reading pressure skipped\n"); + return -EIO; + } + *adc_press = value_press; + + return 0; } /* @@ -338,12 +420,12 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, * Taken from datasheet, Section 3.11.3, "Compensation formula". */ static u32 bmp280_compensate_press(struct bmp280_data *data, - s32 adc_press) + u32 adc_press, s32 t_fine) { struct bmp280_calib *calib = &data->calib.bmp280; s64 var1, var2, p; - var1 = ((s64)data->t_fine) - 128000; + var1 = ((s64)t_fine) - 128000; var2 = var1 * var1 * (s64)calib->P6; var2 += (var1 * (s64)calib->P5) << 17; var2 += ((s64)calib->P4) << 35; @@ -354,7 +436,7 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, if (var1 == 0) return 0; - p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125; + p = ((((s64)1048576 - (s32)adc_press) << 31) - var2) * 3125; p = div64_s64(p, var1); var1 = (((s64)calib->P9) * (p >> 13) * (p >> 13)) >> 25; var2 = ((s64)(calib->P8) * p) >> 19; @@ -366,62 +448,35 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, static int bmp280_read_temp(struct bmp280_data *data, int *val, int *val2) { - s32 adc_temp, comp_temp; + s32 comp_temp; + u32 adc_temp; int ret; - ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, - data->buf, sizeof(data->buf)); - if (ret < 0) { - dev_err(data->dev, "failed to read temperature\n"); + ret = bmp280_read_temp_adc(data, &adc_temp); + if (ret) return ret; - } - adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf)); - if (adc_temp == BMP280_TEMP_SKIPPED) { - /* reading was skipped */ - dev_err(data->dev, "reading temperature skipped\n"); - return -EIO; - } comp_temp = bmp280_compensate_temp(data, adc_temp); - /* - * val might be NULL if we're called by the read_press routine, - * who only cares about the carry over t_fine value. - */ - if (val) { - *val = comp_temp * 10; - return IIO_VAL_INT; - } - - return 0; + *val = comp_temp * 10; + return IIO_VAL_INT; } static int bmp280_read_press(struct bmp280_data *data, int *val, int *val2) { - u32 comp_press; - s32 adc_press; + u32 comp_press, adc_press, t_fine; int ret; - /* Read and compensate temperature so we get a reading of t_fine. */ - ret = bmp280_read_temp(data, NULL, NULL); - if (ret < 0) + ret = bmp280_get_t_fine(data, &t_fine); + if (ret) return ret; - ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, - data->buf, sizeof(data->buf)); - if (ret < 0) { - dev_err(data->dev, "failed to read pressure\n"); + ret = bmp280_read_press_adc(data, &adc_press); + if (ret) return ret; - } - adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf)); - if (adc_press == BMP280_PRESS_SKIPPED) { - /* reading was skipped */ - dev_err(data->dev, "reading pressure skipped\n"); - return -EIO; - } - comp_press = bmp280_compensate_press(data, adc_press); + comp_press = bmp280_compensate_press(data, adc_press, t_fine); *val = comp_press; *val2 = 256000; @@ -429,37 +484,80 @@ static int bmp280_read_press(struct bmp280_data *data, return IIO_VAL_FRACTIONAL; } -static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2) +static int bme280_read_humid(struct bmp280_data *data, int *val, int *val2) { u32 comp_humidity; - s32 adc_humidity; + u16 adc_humidity; + s32 t_fine; int ret; - /* Read and compensate temperature so we get a reading of t_fine. */ - ret = bmp280_read_temp(data, NULL, NULL); - if (ret < 0) + ret = bmp280_get_t_fine(data, &t_fine); + if (ret) return ret; - ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, - &data->be16, sizeof(data->be16)); - if (ret < 0) { - dev_err(data->dev, "failed to read humidity\n"); + ret = bme280_read_humid_adc(data, &adc_humidity); + if (ret) return ret; - } - adc_humidity = be16_to_cpu(data->be16); - if (adc_humidity == BMP280_HUMIDITY_SKIPPED) { - /* reading was skipped */ - dev_err(data->dev, "reading humidity skipped\n"); - return -EIO; - } - comp_humidity = bmp280_compensate_humidity(data, adc_humidity); + comp_humidity = bme280_compensate_humidity(data, adc_humidity, t_fine); *val = comp_humidity * 1000 / 1024; return IIO_VAL_INT; } +static int bmp280_read_raw_impl(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct bmp280_data *data = iio_priv(indio_dev); + + guard(mutex)(&data->lock); + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + return data->chip_info->read_humid(data, val, val2); + case IIO_PRESSURE: + return data->chip_info->read_press(data, val, val2); + case IIO_TEMP: + return data->chip_info->read_temp(data, val, val2); + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + *val = 1 << data->oversampling_humid; + return IIO_VAL_INT; + case IIO_PRESSURE: + *val = 1 << data->oversampling_press; + return IIO_VAL_INT; + case IIO_TEMP: + *val = 1 << data->oversampling_temp; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + if (!data->chip_info->sampling_freq_avail) + return -EINVAL; + + *val = data->chip_info->sampling_freq_avail[data->sampling_freq][0]; + *val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1]; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + if (!data->chip_info->iir_filter_coeffs_avail) + return -EINVAL; + + *val = (1 << data->iir_filter_coeff) - 1; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + static int bmp280_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -468,77 +566,15 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, int ret; pm_runtime_get_sync(data->dev); - mutex_lock(&data->lock); - - switch (mask) { - case IIO_CHAN_INFO_PROCESSED: - switch (chan->type) { - case IIO_HUMIDITYRELATIVE: - ret = data->chip_info->read_humid(data, val, val2); - break; - case IIO_PRESSURE: - ret = data->chip_info->read_press(data, val, val2); - break; - case IIO_TEMP: - ret = data->chip_info->read_temp(data, val, val2); - break; - default: - ret = -EINVAL; - break; - } - break; - case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - switch (chan->type) { - case IIO_HUMIDITYRELATIVE: - *val = 1 << data->oversampling_humid; - ret = IIO_VAL_INT; - break; - case IIO_PRESSURE: - *val = 1 << data->oversampling_press; - ret = IIO_VAL_INT; - break; - case IIO_TEMP: - *val = 1 << data->oversampling_temp; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - break; - case IIO_CHAN_INFO_SAMP_FREQ: - if (!data->chip_info->sampling_freq_avail) { - ret = -EINVAL; - break; - } - - *val = data->chip_info->sampling_freq_avail[data->sampling_freq][0]; - *val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1]; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - if (!data->chip_info->iir_filter_coeffs_avail) { - ret = -EINVAL; - break; - } - - *val = (1 << data->iir_filter_coeff) - 1; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - - mutex_unlock(&data->lock); + ret = bmp280_read_raw_impl(indio_dev, chan, val, val2, mask); pm_runtime_mark_last_busy(data->dev); pm_runtime_put_autosuspend(data->dev); return ret; } -static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data, - int val) +static int bme280_write_oversampling_ratio_humid(struct bmp280_data *data, + int val) { const int *avail = data->chip_info->oversampling_humid_avail; const int n = data->chip_info->num_oversampling_humid_avail; @@ -563,7 +599,7 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data, } static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, - int val) + int val) { const int *avail = data->chip_info->oversampling_temp_avail; const int n = data->chip_info->num_oversampling_temp_avail; @@ -588,7 +624,7 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data, } static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data, - int val) + int val) { const int *avail = data->chip_info->oversampling_press_avail; const int n = data->chip_info->num_oversampling_press_avail; @@ -662,12 +698,13 @@ static int bmp280_write_iir_filter_coeffs(struct bmp280_data *data, int val) return -EINVAL; } -static int bmp280_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) +static int bmp280_write_raw_impl(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct bmp280_data *data = iio_priv(indio_dev); - int ret = 0; + + guard(mutex)(&data->lock); /* * Helper functions to update sensor running configuration. @@ -677,45 +714,36 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, */ switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - pm_runtime_get_sync(data->dev); - mutex_lock(&data->lock); switch (chan->type) { case IIO_HUMIDITYRELATIVE: - ret = bmp280_write_oversampling_ratio_humid(data, val); - break; + return bme280_write_oversampling_ratio_humid(data, val); case IIO_PRESSURE: - ret = bmp280_write_oversampling_ratio_press(data, val); - break; + return bmp280_write_oversampling_ratio_press(data, val); case IIO_TEMP: - ret = bmp280_write_oversampling_ratio_temp(data, val); - break; + return bmp280_write_oversampling_ratio_temp(data, val); default: - ret = -EINVAL; - break; + return -EINVAL; } - mutex_unlock(&data->lock); - pm_runtime_mark_last_busy(data->dev); - pm_runtime_put_autosuspend(data->dev); - break; case IIO_CHAN_INFO_SAMP_FREQ: - pm_runtime_get_sync(data->dev); - mutex_lock(&data->lock); - ret = bmp280_write_sampling_frequency(data, val, val2); - mutex_unlock(&data->lock); - pm_runtime_mark_last_busy(data->dev); - pm_runtime_put_autosuspend(data->dev); - break; + return bmp280_write_sampling_frequency(data, val, val2); case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - pm_runtime_get_sync(data->dev); - mutex_lock(&data->lock); - ret = bmp280_write_iir_filter_coeffs(data, val); - mutex_unlock(&data->lock); - pm_runtime_mark_last_busy(data->dev); - pm_runtime_put_autosuspend(data->dev); - break; + return bmp280_write_iir_filter_coeffs(data, val); default: return -EINVAL; } +} + +static int bmp280_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct bmp280_data *data = iio_priv(indio_dev); + int ret; + + pm_runtime_get_sync(data->dev); + ret = bmp280_write_raw_impl(indio_dev, chan, val, val2, mask); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); return ret; } @@ -772,22 +800,20 @@ static int bmp280_chip_config(struct bmp280_data *data) int ret; ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS, - BMP280_OSRS_TEMP_MASK | - BMP280_OSRS_PRESS_MASK | - BMP280_MODE_MASK, - osrs | BMP280_MODE_NORMAL); - if (ret < 0) { - dev_err(data->dev, - "failed to write ctrl_meas register\n"); + BMP280_OSRS_TEMP_MASK | + BMP280_OSRS_PRESS_MASK | + BMP280_MODE_MASK, + osrs | BMP280_MODE_NORMAL); + if (ret) { + dev_err(data->dev, "failed to write ctrl_meas register\n"); return ret; } ret = regmap_update_bits(data->regmap, BMP280_REG_CONFIG, BMP280_FILTER_MASK, BMP280_FILTER_4X); - if (ret < 0) { - dev_err(data->dev, - "failed to write config register\n"); + if (ret) { + dev_err(data->dev, "failed to write config register\n"); return ret; } @@ -833,18 +859,19 @@ EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280); static int bme280_chip_config(struct bmp280_data *data) { - u8 osrs = FIELD_PREP(BMP280_OSRS_HUMIDITY_MASK, data->oversampling_humid + 1); + u8 osrs = FIELD_PREP(BME280_OSRS_HUMIDITY_MASK, data->oversampling_humid + 1); int ret; /* * Oversampling of humidity must be set before oversampling of * temperature/pressure is set to become effective. */ - ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_HUMIDITY, - BMP280_OSRS_HUMIDITY_MASK, osrs); - - if (ret < 0) + ret = regmap_update_bits(data->regmap, BME280_REG_CTRL_HUMIDITY, + BME280_OSRS_HUMIDITY_MASK, osrs); + if (ret) { + dev_err(data->dev, "failed to set humidity oversampling"); return ret; + } return bmp280_chip_config(data); } @@ -870,12 +897,12 @@ const struct bmp280_chip_info bme280_chip_info = { .oversampling_humid_avail = bmp280_oversampling_avail, .num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail), - .oversampling_humid_default = BMP280_OSRS_HUMIDITY_16X - 1, + .oversampling_humid_default = BME280_OSRS_HUMIDITY_16X - 1, .chip_config = bme280_chip_config, .read_temp = bmp280_read_temp, .read_press = bmp280_read_press, - .read_humid = bmp280_read_humid, + .read_humid = bme280_read_humid, .read_calib = bme280_read_calib, }; EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280); @@ -925,16 +952,38 @@ static int bmp380_cmd(struct bmp280_data *data, u8 cmd) return 0; } +static int bmp380_read_temp_adc(struct bmp280_data *data, u32 *adc_temp) +{ + u32 value_temp; + int ret; + + ret = regmap_bulk_read(data->regmap, BMP380_REG_TEMP_XLSB, + data->buf, sizeof(data->buf)); + if (ret) { + dev_err(data->dev, "failed to read temperature\n"); + return ret; + } + + value_temp = get_unaligned_le24(data->buf); + if (value_temp == BMP380_TEMP_SKIPPED) { + dev_err(data->dev, "reading temperature skipped\n"); + return -EIO; + } + *adc_temp = value_temp; + + return 0; +} + /* - * Returns temperature in Celsius degrees, resolution is 0.01º C. Output value of - * "5123" equals 51.2º C. t_fine carries fine temperature as global value. + * Returns temperature in Celsius degrees, resolution is 0.01º C. Output value + * of "5123" equals 51.2º C. t_fine carries fine temperature as global value. * * Taken from datasheet, Section Appendix 9, "Compensation formula" and repo * https://github.com/BoschSensortec/BMP3-Sensor-API. */ -static s32 bmp380_compensate_temp(struct bmp280_data *data, u32 adc_temp) +static s32 bmp380_calc_t_fine(struct bmp280_data *data, u32 adc_temp) { - s64 var1, var2, var3, var4, var5, var6, comp_temp; + s64 var1, var2, var3, var4, var5, var6; struct bmp380_calib *calib = &data->calib.bmp380; var1 = ((s64) adc_temp) - (((s64) calib->T1) << 8); @@ -943,13 +992,57 @@ static s32 bmp380_compensate_temp(struct bmp280_data *data, u32 adc_temp) var4 = var3 * ((s64) calib->T3); var5 = (var2 << 18) + var4; var6 = var5 >> 32; - data->t_fine = (s32) var6; + return (s32)var6; /* t_fine = var6 */ +} + +static int bmp380_get_t_fine(struct bmp280_data *data, s32 *t_fine) +{ + s32 adc_temp; + int ret; + + ret = bmp380_read_temp_adc(data, &adc_temp); + if (ret) + return ret; + + *t_fine = bmp380_calc_t_fine(data, adc_temp); + + return 0; +} + +static int bmp380_compensate_temp(struct bmp280_data *data, u32 adc_temp) +{ + s64 comp_temp; + s32 var6; + + var6 = bmp380_calc_t_fine(data, adc_temp); comp_temp = (var6 * 25) >> 14; comp_temp = clamp_val(comp_temp, BMP380_MIN_TEMP, BMP380_MAX_TEMP); return (s32) comp_temp; } +static int bmp380_read_press_adc(struct bmp280_data *data, u32 *adc_press) +{ + u32 value_press; + int ret; + + ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB, + data->buf, sizeof(data->buf)); + if (ret) { + dev_err(data->dev, "failed to read pressure\n"); + return ret; + } + + value_press = get_unaligned_le24(data->buf); + if (value_press == BMP380_PRESS_SKIPPED) { + dev_err(data->dev, "reading pressure skipped\n"); + return -EIO; + } + *adc_press = value_press; + + return 0; +} + /* * Returns pressure in Pa as an unsigned 32 bit integer in fractional Pascal. * Output value of "9528709" represents 9528709/100 = 95287.09 Pa = 952.8709 hPa. @@ -957,27 +1050,28 @@ static s32 bmp380_compensate_temp(struct bmp280_data *data, u32 adc_temp) * Taken from datasheet, Section 9.3. "Pressure compensation" and repository * https://github.com/BoschSensortec/BMP3-Sensor-API. */ -static u32 bmp380_compensate_press(struct bmp280_data *data, u32 adc_press) +static u32 bmp380_compensate_press(struct bmp280_data *data, + u32 adc_press, s32 t_fine) { s64 var1, var2, var3, var4, var5, var6, offset, sensitivity; struct bmp380_calib *calib = &data->calib.bmp380; u32 comp_press; - var1 = (s64)data->t_fine * (s64)data->t_fine; + var1 = (s64)t_fine * (s64)t_fine; var2 = var1 >> 6; - var3 = (var2 * ((s64) data->t_fine)) >> 8; + var3 = (var2 * ((s64)t_fine)) >> 8; var4 = ((s64)calib->P8 * var3) >> 5; var5 = ((s64)calib->P7 * var1) << 4; - var6 = ((s64)calib->P6 * (s64)data->t_fine) << 22; + var6 = ((s64)calib->P6 * (s64)t_fine) << 22; offset = ((s64)calib->P5 << 47) + var4 + var5 + var6; var2 = ((s64)calib->P4 * var3) >> 5; var4 = ((s64)calib->P3 * var1) << 2; var5 = ((s64)calib->P2 - ((s64)1 << 14)) * - ((s64)data->t_fine << 21); + ((s64)t_fine << 21); sensitivity = (((s64) calib->P1 - ((s64) 1 << 14)) << 46) + var2 + var4 + var5; var1 = (sensitivity >> 24) * (s64)adc_press; - var2 = (s64)calib->P10 * (s64)data->t_fine; + var2 = (s64)calib->P10 * (s64)t_fine; var3 = var2 + ((s64)calib->P9 << 16); var4 = (var3 * (s64)adc_press) >> 13; @@ -1003,60 +1097,32 @@ static int bmp380_read_temp(struct bmp280_data *data, int *val, int *val2) u32 adc_temp; int ret; - ret = regmap_bulk_read(data->regmap, BMP380_REG_TEMP_XLSB, - data->buf, sizeof(data->buf)); - if (ret) { - dev_err(data->dev, "failed to read temperature\n"); + ret = bmp380_read_temp_adc(data, &adc_temp); + if (ret) return ret; - } - adc_temp = get_unaligned_le24(data->buf); - if (adc_temp == BMP380_TEMP_SKIPPED) { - dev_err(data->dev, "reading temperature skipped\n"); - return -EIO; - } comp_temp = bmp380_compensate_temp(data, adc_temp); - /* - * Val might be NULL if we're called by the read_press routine, - * who only cares about the carry over t_fine value. - */ - if (val) { - /* IIO reports temperatures in milli Celsius */ - *val = comp_temp * 10; - return IIO_VAL_INT; - } - - return 0; + *val = comp_temp * 10; + return IIO_VAL_INT; } static int bmp380_read_press(struct bmp280_data *data, int *val, int *val2) { - s32 comp_press; - u32 adc_press; + u32 adc_press, comp_press, t_fine; int ret; - /* Read and compensate for temperature so we get a reading of t_fine */ - ret = bmp380_read_temp(data, NULL, NULL); + ret = bmp380_get_t_fine(data, &t_fine); if (ret) return ret; - ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB, - data->buf, sizeof(data->buf)); - if (ret) { - dev_err(data->dev, "failed to read pressure\n"); + ret = bmp380_read_press_adc(data, &adc_press); + if (ret) return ret; - } - adc_press = get_unaligned_le24(data->buf); - if (adc_press == BMP380_PRESS_SKIPPED) { - dev_err(data->dev, "reading pressure skipped\n"); - return -EIO; - } - comp_press = bmp380_compensate_press(data, adc_press); + comp_press = bmp380_compensate_press(data, adc_press, t_fine); *val = comp_press; - /* Compensated pressure is in cPa (centipascals) */ *val2 = 100000; return IIO_VAL_FRACTIONAL; @@ -1069,15 +1135,17 @@ static int bmp380_read_calib(struct bmp280_data *data) /* Read temperature and pressure calibration data */ ret = regmap_bulk_read(data->regmap, BMP380_REG_CALIB_TEMP_START, - data->bmp380_cal_buf, sizeof(data->bmp380_cal_buf)); + data->bmp380_cal_buf, + sizeof(data->bmp380_cal_buf)); if (ret) { dev_err(data->dev, - "failed to read temperature calibration parameters\n"); + "failed to read calibration parameters\n"); return ret; } /* Toss the temperature calibration data into the entropy pool */ - add_device_randomness(data->bmp380_cal_buf, sizeof(data->bmp380_cal_buf)); + add_device_randomness(data->bmp380_cal_buf, + sizeof(data->bmp380_cal_buf)); /* Parse calibration values */ calib->T1 = get_unaligned_le16(&data->bmp380_cal_buf[BMP380_T1]); @@ -1159,7 +1227,8 @@ static int bmp380_chip_config(struct bmp280_data *data) /* Configure output data rate */ ret = regmap_update_bits_check(data->regmap, BMP380_REG_ODR, - BMP380_ODRS_MASK, data->sampling_freq, &aux); + BMP380_ODRS_MASK, data->sampling_freq, + &aux); if (ret) { dev_err(data->dev, "failed to write ODR selection register\n"); return ret; @@ -1178,12 +1247,13 @@ static int bmp380_chip_config(struct bmp280_data *data) if (change) { /* - * The configurations errors are detected on the fly during a measurement - * cycle. If the sampling frequency is too low, it's faster to reset - * the measurement loop than wait until the next measurement is due. + * The configurations errors are detected on the fly during a + * measurement cycle. If the sampling frequency is too low, it's + * faster to reset the measurement loop than wait until the next + * measurement is due. * - * Resets sensor measurement loop toggling between sleep and normal - * operating modes. + * Resets sensor measurement loop toggling between sleep and + * normal operating modes. */ ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL, BMP380_MODE_MASK, @@ -1201,22 +1271,21 @@ static int bmp380_chip_config(struct bmp280_data *data) return ret; } /* - * Waits for measurement before checking configuration error flag. - * Selected longest measure time indicated in section 3.9.1 - * in the datasheet. + * Waits for measurement before checking configuration error + * flag. Selected longest measure time indicated in + * section 3.9.1 in the datasheet. */ msleep(80); /* Check config error flag */ ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp); if (ret) { - dev_err(data->dev, - "failed to read error register\n"); + dev_err(data->dev, "failed to read error register\n"); return ret; } if (tmp & BMP380_ERR_CONF_MASK) { dev_warn(data->dev, - "sensor flagged configuration as incompatible\n"); + "sensor flagged configuration as incompatible\n"); return -EINVAL; } } @@ -1317,9 +1386,11 @@ static int bmp580_nvm_operation(struct bmp280_data *data, bool is_write) } /* Start NVM operation sequence */ - ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_NVM_OP_SEQ_0); + ret = regmap_write(data->regmap, BMP580_REG_CMD, + BMP580_CMD_NVM_OP_SEQ_0); if (ret) { - dev_err(data->dev, "failed to send nvm operation's first sequence\n"); + dev_err(data->dev, + "failed to send nvm operation's first sequence\n"); return ret; } if (is_write) { @@ -1327,7 +1398,8 @@ static int bmp580_nvm_operation(struct bmp280_data *data, bool is_write) ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_NVM_WRITE_SEQ_1); if (ret) { - dev_err(data->dev, "failed to send nvm write sequence\n"); + dev_err(data->dev, + "failed to send nvm write sequence\n"); return ret; } /* Datasheet says on 4.8.1.2 it takes approximately 10ms */ @@ -1338,17 +1410,14 @@ static int bmp580_nvm_operation(struct bmp280_data *data, bool is_write) ret = regmap_write(data->regmap, BMP580_REG_CMD, BMP580_CMD_NVM_READ_SEQ_1); if (ret) { - dev_err(data->dev, "failed to send nvm read sequence\n"); + dev_err(data->dev, + "failed to send nvm read sequence\n"); return ret; } /* Datasheet says on 4.8.1.1 it takes approximately 200us */ poll = 50; timeout = 400; } - if (ret) { - dev_err(data->dev, "failed to write command sequence\n"); - return -EIO; - } /* Wait until NVM is ready again */ ret = regmap_read_poll_timeout(data->regmap, BMP580_REG_STATUS, reg, @@ -1465,15 +1534,14 @@ static const int bmp580_odr_table[][2] = { static const int bmp580_nvmem_addrs[] = { 0x20, 0x21, 0x22 }; -static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val, - size_t bytes) +static int bmp580_nvmem_read_impl(void *priv, unsigned int offset, void *val, + size_t bytes) { struct bmp280_data *data = priv; u16 *dst = val; int ret, addr; - pm_runtime_get_sync(data->dev); - mutex_lock(&data->lock); + guard(mutex)(&data->lock); /* Set sensor in standby mode */ ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, @@ -1501,8 +1569,8 @@ static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val, if (ret) goto exit; - ret = regmap_bulk_read(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16, - sizeof(data->le16)); + ret = regmap_bulk_read(data->regmap, BMP580_REG_NVM_DATA_LSB, + &data->le16, sizeof(data->le16)); if (ret) { dev_err(data->dev, "error reading nvm data regs\n"); goto exit; @@ -1515,21 +1583,31 @@ static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val, exit: /* Restore chip config */ data->chip_info->chip_config(data); - mutex_unlock(&data->lock); - pm_runtime_mark_last_busy(data->dev); - pm_runtime_put_autosuspend(data->dev); return ret; } -static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, - size_t bytes) +static int bmp580_nvmem_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct bmp280_data *data = priv; + int ret; + + pm_runtime_get_sync(data->dev); + ret = bmp580_nvmem_read_impl(priv, offset, val, bytes); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + + return ret; +} + +static int bmp580_nvmem_write_impl(void *priv, unsigned int offset, void *val, + size_t bytes) { struct bmp280_data *data = priv; u16 *buf = val; int ret, addr; - pm_runtime_get_sync(data->dev); - mutex_lock(&data->lock); + guard(mutex)(&data->lock); /* Set sensor in standby mode */ ret = regmap_update_bits(data->regmap, BMP580_REG_ODR_CONFIG, @@ -1546,7 +1624,8 @@ static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, while (bytes >= sizeof(*buf)) { addr = bmp580_nvmem_addrs[offset / sizeof(*buf)]; - ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, BMP580_NVM_PROG_EN | + ret = regmap_write(data->regmap, BMP580_REG_NVM_ADDR, + BMP580_NVM_PROG_EN | FIELD_PREP(BMP580_NVM_ROW_ADDR_MASK, addr)); if (ret) { dev_err(data->dev, "error writing nvm address\n"); @@ -1554,8 +1633,8 @@ static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, } data->le16 = cpu_to_le16(*buf++); - ret = regmap_bulk_write(data->regmap, BMP580_REG_NVM_DATA_LSB, &data->le16, - sizeof(data->le16)); + ret = regmap_bulk_write(data->regmap, BMP580_REG_NVM_DATA_LSB, + &data->le16, sizeof(data->le16)); if (ret) { dev_err(data->dev, "error writing LSB NVM data regs\n"); goto exit; @@ -1566,8 +1645,8 @@ static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, goto exit; /* Disable programming mode bit */ - ret = regmap_update_bits(data->regmap, BMP580_REG_NVM_ADDR, - BMP580_NVM_PROG_EN, 0); + ret = regmap_clear_bits(data->regmap, BMP580_REG_NVM_ADDR, + BMP580_NVM_PROG_EN); if (ret) { dev_err(data->dev, "error resetting nvm write\n"); goto exit; @@ -1579,9 +1658,20 @@ static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, exit: /* Restore chip config */ data->chip_info->chip_config(data); - mutex_unlock(&data->lock); + return ret; +} + +static int bmp580_nvmem_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct bmp280_data *data = priv; + int ret; + + pm_runtime_get_sync(data->dev); + ret = bmp580_nvmem_write_impl(priv, offset, val, bytes); pm_runtime_mark_last_busy(data->dev); pm_runtime_put_autosuspend(data->dev); + return ret; } @@ -1607,20 +1697,24 @@ static int bmp580_preinit(struct bmp280_data *data) /* Post powerup sequence */ ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, ®); - if (ret) + if (ret) { + dev_err(data->dev, "failed to establish comms with the chip\n"); return ret; + } /* Print warn message if we don't know the chip id */ if (reg != BMP580_CHIP_ID && reg != BMP580_CHIP_ID_ALT) - dev_warn(data->dev, "preinit: unexpected chip_id\n"); + dev_warn(data->dev, "unexpected chip_id\n"); ret = regmap_read(data->regmap, BMP580_REG_STATUS, ®); - if (ret) + if (ret) { + dev_err(data->dev, "failed to read nvm status\n"); return ret; + } /* Check nvm status */ if (!(reg & BMP580_STATUS_NVM_RDY_MASK) || (reg & BMP580_STATUS_NVM_ERR_MASK)) { - dev_err(data->dev, "preinit: nvm error on powerup sequence\n"); + dev_err(data->dev, "nvm error on powerup sequence\n"); return -EIO; } @@ -1655,6 +1749,10 @@ static int bmp580_chip_config(struct bmp280_data *data) BMP580_DSP_COMP_MASK | BMP580_DSP_SHDW_IIR_TEMP_EN | BMP580_DSP_SHDW_IIR_PRESS_EN, reg_val); + if (ret) { + dev_err(data->dev, "failed to change DSP mode settings\n"); + return ret; + } /* Configure oversampling */ reg_val = FIELD_PREP(BMP580_OSR_TEMP_MASK, data->oversampling_temp) | @@ -1662,7 +1760,8 @@ static int bmp580_chip_config(struct bmp280_data *data) BMP580_OSR_PRESS_EN; ret = regmap_update_bits_check(data->regmap, BMP580_REG_OSR_CONFIG, - BMP580_OSR_TEMP_MASK | BMP580_OSR_PRESS_MASK | + BMP580_OSR_TEMP_MASK | + BMP580_OSR_PRESS_MASK | BMP580_OSR_PRESS_EN, reg_val, &aux); if (ret) { @@ -1713,7 +1812,8 @@ static int bmp580_chip_config(struct bmp280_data *data) */ ret = regmap_read(data->regmap, BMP580_REG_EFF_OSR, &tmp); if (ret) { - dev_err(data->dev, "error reading effective OSR register\n"); + dev_err(data->dev, + "error reading effective OSR register\n"); return ret; } if (!(tmp & BMP580_EFF_OSR_VALID_ODR)) { @@ -1763,7 +1863,7 @@ const struct bmp280_chip_info bmp580_chip_info = { }; EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280); -static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) +static int bmp180_wait_for_eoc(struct bmp280_data *data, u8 ctrl_meas) { const int conversion_time_max[] = { 4500, 7500, 13500, 25500 }; unsigned int delay_us; @@ -1774,8 +1874,10 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) reinit_completion(&data->done); ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas); - if (ret) + if (ret) { + dev_err(data->dev, "failed to write crtl_meas register\n"); return ret; + } if (data->use_eoc) { /* @@ -1798,32 +1900,38 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas) } ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl); - if (ret) + if (ret) { + dev_err(data->dev, "failed to read ctrl_meas register\n"); return ret; + } /* The value of this bit reset to "0" after conversion is complete */ - if (ctrl & BMP180_MEAS_SCO) + if (ctrl & BMP180_MEAS_SCO) { + dev_err(data->dev, "conversion didn't complete\n"); return -EIO; + } return 0; } -static int bmp180_read_adc_temp(struct bmp280_data *data, int *val) +static int bmp180_read_temp_adc(struct bmp280_data *data, u32 *adc_temp) { int ret; - ret = bmp180_measure(data, - FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_TEMP) | - BMP180_MEAS_SCO); + ret = bmp180_wait_for_eoc(data, + FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_TEMP) | + BMP180_MEAS_SCO); if (ret) return ret; ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &data->be16, sizeof(data->be16)); - if (ret) + if (ret) { + dev_err(data->dev, "failed to read temperature\n"); return ret; + } - *val = be16_to_cpu(data->be16); + *adc_temp = be16_to_cpu(data->be16); return 0; } @@ -1836,9 +1944,10 @@ static int bmp180_read_calib(struct bmp280_data *data) ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf)); - - if (ret < 0) + if (ret) { + dev_err(data->dev, "failed to read calibration parameters\n"); return ret; + } /* None of the words has the value 0 or 0xFFFF */ for (i = 0; i < ARRAY_SIZE(data->bmp180_cal_buf); i++) { @@ -1848,7 +1957,8 @@ static int bmp180_read_calib(struct bmp280_data *data) } /* Toss the calibration data into the entropy pool */ - add_device_randomness(data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf)); + add_device_randomness(data->bmp180_cal_buf, + sizeof(data->bmp180_cal_buf)); calib->AC1 = be16_to_cpu(data->bmp180_cal_buf[AC1]); calib->AC2 = be16_to_cpu(data->bmp180_cal_buf[AC2]); @@ -1871,59 +1981,72 @@ static int bmp180_read_calib(struct bmp280_data *data) * * Taken from datasheet, Section 3.5, "Calculating pressure and temperature". */ -static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp) + +static s32 bmp180_calc_t_fine(struct bmp280_data *data, u32 adc_temp) { struct bmp180_calib *calib = &data->calib.bmp180; s32 x1, x2; - x1 = ((adc_temp - calib->AC6) * calib->AC5) >> 15; + x1 = ((((s32)adc_temp) - calib->AC6) * calib->AC5) >> 15; x2 = (calib->MC << 11) / (x1 + calib->MD); - data->t_fine = x1 + x2; + return x1 + x2; /* t_fine = x1 + x2; */ +} - return (data->t_fine + 8) >> 4; +static int bmp180_get_t_fine(struct bmp280_data *data, s32 *t_fine) +{ + s32 adc_temp; + int ret; + + ret = bmp180_read_temp_adc(data, &adc_temp); + if (ret) + return ret; + + *t_fine = bmp180_calc_t_fine(data, adc_temp); + + return 0; +} + +static s32 bmp180_compensate_temp(struct bmp280_data *data, u32 adc_temp) +{ + return (bmp180_calc_t_fine(data, adc_temp) + 8) / 16; } static int bmp180_read_temp(struct bmp280_data *data, int *val, int *val2) { - s32 adc_temp, comp_temp; + s32 comp_temp; + u32 adc_temp; int ret; - ret = bmp180_read_adc_temp(data, &adc_temp); + ret = bmp180_read_temp_adc(data, &adc_temp); if (ret) return ret; comp_temp = bmp180_compensate_temp(data, adc_temp); - /* - * val might be NULL if we're called by the read_press routine, - * who only cares about the carry over t_fine value. - */ - if (val) { - *val = comp_temp * 100; - return IIO_VAL_INT; - } - - return 0; + *val = comp_temp * 100; + return IIO_VAL_INT; } -static int bmp180_read_adc_press(struct bmp280_data *data, int *val) +static int bmp180_read_press_adc(struct bmp280_data *data, u32 *adc_press) { u8 oss = data->oversampling_press; int ret; - ret = bmp180_measure(data, - FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_PRESS) | - FIELD_PREP(BMP180_OSRS_PRESS_MASK, oss) | - BMP180_MEAS_SCO); + ret = bmp180_wait_for_eoc(data, + FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_PRESS) | + FIELD_PREP(BMP180_OSRS_PRESS_MASK, oss) | + BMP180_MEAS_SCO); if (ret) return ret; ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, data->buf, sizeof(data->buf)); - if (ret) + if (ret) { + dev_err(data->dev, "failed to read pressure\n"); return ret; + } - *val = get_unaligned_be24(data->buf) >> (8 - oss); + *adc_press = get_unaligned_be24(data->buf) >> (8 - oss); return 0; } @@ -1933,7 +2056,8 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val) * * Taken from datasheet, Section 3.5, "Calculating pressure and temperature". */ -static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) +static u32 bmp180_compensate_press(struct bmp280_data *data, u32 adc_press, + s32 t_fine) { struct bmp180_calib *calib = &data->calib.bmp180; s32 oss = data->oversampling_press; @@ -1941,7 +2065,7 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) s32 b3, b6; u32 b4, b7; - b6 = data->t_fine - 4000; + b6 = t_fine - 4000; x1 = (calib->B2 * (b6 * b6 >> 12)) >> 11; x2 = calib->AC2 * b6 >> 11; x3 = x1 + x2; @@ -1950,7 +2074,7 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) x2 = (calib->B1 * ((b6 * b6) >> 12)) >> 16; x3 = (x1 + x2 + 2) >> 2; b4 = calib->AC4 * (u32)(x3 + 32768) >> 15; - b7 = ((u32)adc_press - b3) * (50000 >> oss); + b7 = (adc_press - b3) * (50000 >> oss); if (b7 < 0x80000000) p = (b7 * 2) / b4; else @@ -1963,23 +2087,21 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press) return p + ((x1 + x2 + 3791) >> 4); } -static int bmp180_read_press(struct bmp280_data *data, - int *val, int *val2) +static int bmp180_read_press(struct bmp280_data *data, int *val, int *val2) { - u32 comp_press; - s32 adc_press; + u32 comp_press, adc_press; + s32 t_fine; int ret; - /* Read and compensate temperature so we get a reading of t_fine. */ - ret = bmp180_read_temp(data, NULL, NULL); + ret = bmp180_get_t_fine(data, &t_fine); if (ret) return ret; - ret = bmp180_read_adc_press(data, &adc_press); + ret = bmp180_read_press_adc(data, &adc_press); if (ret) return ret; - comp_press = bmp180_compensate_press(data, adc_press); + comp_press = bmp180_compensate_press(data, adc_press, t_fine); *val = comp_press; *val2 = 1000; @@ -2154,8 +2276,10 @@ int bmp280_common_probe(struct device *dev, data->regmap = regmap; ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id); - if (ret < 0) + if (ret) { + dev_err(data->dev, "failed to read chip id\n"); return ret; + } for (i = 0; i < data->chip_info->num_chip_id; i++) { if (chip_id == data->chip_info->chip_id[i]) { @@ -2175,7 +2299,7 @@ int bmp280_common_probe(struct device *dev, } ret = data->chip_info->chip_config(data); - if (ret < 0) + if (ret) return ret; dev_set_drvdata(dev, indio_dev); @@ -2188,7 +2312,7 @@ int bmp280_common_probe(struct device *dev, if (data->chip_info->read_calib) { ret = data->chip_info->read_calib(data); - if (ret < 0) + if (ret) return dev_err_probe(data->dev, ret, "failed to read calibration coefficients\n"); } @@ -2241,6 +2365,7 @@ static int bmp280_runtime_resume(struct device *dev) ret = regulator_bulk_enable(BMP280_NUM_SUPPLIES, data->supplies); if (ret) return ret; + usleep_range(data->start_up_time, data->start_up_time + 100); return data->chip_info->chip_config(data); } diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c index 3ee56720428c..fa52839474b1 100644 --- a/drivers/iio/pressure/bmp280-regmap.c +++ b/drivers/iio/pressure/bmp280-regmap.c @@ -45,7 +45,7 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { case BMP280_REG_CONFIG: - case BMP280_REG_CTRL_HUMIDITY: + case BME280_REG_CTRL_HUMIDITY: case BMP280_REG_CTRL_MEAS: case BMP280_REG_RESET: return true; @@ -57,8 +57,8 @@ static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg) static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case BMP280_REG_HUMIDITY_LSB: - case BMP280_REG_HUMIDITY_MSB: + case BME280_REG_HUMIDITY_LSB: + case BME280_REG_HUMIDITY_MSB: case BMP280_REG_TEMP_XLSB: case BMP280_REG_TEMP_LSB: case BMP280_REG_TEMP_MSB: @@ -167,7 +167,7 @@ const struct regmap_config bmp280_regmap_config = { .reg_bits = 8, .val_bits = 8, - .max_register = BMP280_REG_HUMIDITY_LSB, + .max_register = BME280_REG_HUMIDITY_LSB, .cache_type = REGCACHE_RBTREE, .writeable_reg = bmp280_is_writeable_reg, diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index 4e19ea0b4d39..62b4e58104cf 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -13,7 +13,7 @@ #include "bmp280.h" static int bmp280_regmap_spi_write(void *context, const void *data, - size_t count) + size_t count) { struct spi_device *spi = to_spi_device(context); u8 buf[2]; @@ -29,7 +29,7 @@ static int bmp280_regmap_spi_write(void *context, const void *data, } static int bmp280_regmap_spi_read(void *context, const void *reg, - size_t reg_size, void *val, size_t val_size) + size_t reg_size, void *val, size_t val_size) { struct spi_device *spi = to_spi_device(context); diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index 5812a344ed8e..7c30e4d523be 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -192,8 +192,6 @@ #define BMP380_PRESS_SKIPPED 0x800000 /* BMP280 specific registers */ -#define BMP280_REG_HUMIDITY_LSB 0xFE -#define BMP280_REG_HUMIDITY_MSB 0xFD #define BMP280_REG_TEMP_XLSB 0xFC #define BMP280_REG_TEMP_LSB 0xFB #define BMP280_REG_TEMP_MSB 0xFA @@ -207,15 +205,6 @@ #define BMP280_REG_CONFIG 0xF5 #define BMP280_REG_CTRL_MEAS 0xF4 #define BMP280_REG_STATUS 0xF3 -#define BMP280_REG_CTRL_HUMIDITY 0xF2 - -/* Due to non linear mapping, and data sizes we can't do a bulk read */ -#define BMP280_REG_COMP_H1 0xA1 -#define BMP280_REG_COMP_H2 0xE1 -#define BMP280_REG_COMP_H3 0xE3 -#define BMP280_REG_COMP_H4 0xE4 -#define BMP280_REG_COMP_H5 0xE5 -#define BMP280_REG_COMP_H6 0xE7 #define BMP280_REG_COMP_TEMP_START 0x88 #define BMP280_COMP_TEMP_REG_COUNT 6 @@ -223,8 +212,6 @@ #define BMP280_REG_COMP_PRESS_START 0x8E #define BMP280_COMP_PRESS_REG_COUNT 18 -#define BMP280_COMP_H5_MASK GENMASK(15, 4) - #define BMP280_CONTIGUOUS_CALIB_REGS (BMP280_COMP_TEMP_REG_COUNT + \ BMP280_COMP_PRESS_REG_COUNT) @@ -235,14 +222,6 @@ #define BMP280_FILTER_8X 3 #define BMP280_FILTER_16X 4 -#define BMP280_OSRS_HUMIDITY_MASK GENMASK(2, 0) -#define BMP280_OSRS_HUMIDITY_SKIP 0 -#define BMP280_OSRS_HUMIDITY_1X 1 -#define BMP280_OSRS_HUMIDITY_2X 2 -#define BMP280_OSRS_HUMIDITY_4X 3 -#define BMP280_OSRS_HUMIDITY_8X 4 -#define BMP280_OSRS_HUMIDITY_16X 5 - #define BMP280_OSRS_TEMP_MASK GENMASK(7, 5) #define BMP280_OSRS_TEMP_SKIP 0 #define BMP280_OSRS_TEMP_1X 1 @@ -264,6 +243,30 @@ #define BMP280_MODE_FORCED 1 #define BMP280_MODE_NORMAL 3 +/* BME280 specific registers */ +#define BME280_REG_HUMIDITY_LSB 0xFE +#define BME280_REG_HUMIDITY_MSB 0xFD + +#define BME280_REG_CTRL_HUMIDITY 0xF2 + +/* Due to non linear mapping, and data sizes we can't do a bulk read */ +#define BME280_REG_COMP_H1 0xA1 +#define BME280_REG_COMP_H2 0xE1 +#define BME280_REG_COMP_H3 0xE3 +#define BME280_REG_COMP_H4 0xE4 +#define BME280_REG_COMP_H5 0xE5 +#define BME280_REG_COMP_H6 0xE7 + +#define BME280_COMP_H5_MASK GENMASK(15, 4) + +#define BME280_OSRS_HUMIDITY_MASK GENMASK(2, 0) +#define BME280_OSRS_HUMIDITY_SKIP 0 +#define BME280_OSRS_HUMIDITY_1X 1 +#define BME280_OSRS_HUMIDITY_2X 2 +#define BME280_OSRS_HUMIDITY_4X 3 +#define BME280_OSRS_HUMIDITY_8X 4 +#define BME280_OSRS_HUMIDITY_16X 5 + /* BMP180 specific registers */ #define BMP180_REG_OUT_XLSB 0xF8 #define BMP180_REG_OUT_LSB 0xF7 @@ -394,12 +397,6 @@ struct bmp280_data { */ int sampling_freq; - /* - * Carryover value from temperature conversion, used in pressure - * calculation. - */ - s32 t_fine; - /* * DMA (thus cache coherency maintenance) may require the * transfer buffers to live in their own cache lines. @@ -449,12 +446,12 @@ struct bmp280_chip_info { int num_sampling_freq_avail; int sampling_freq_default; - int (*chip_config)(struct bmp280_data *); - int (*read_temp)(struct bmp280_data *, int *, int *); - int (*read_press)(struct bmp280_data *, int *, int *); - int (*read_humid)(struct bmp280_data *, int *, int *); - int (*read_calib)(struct bmp280_data *); - int (*preinit)(struct bmp280_data *); + int (*chip_config)(struct bmp280_data *data); + int (*read_temp)(struct bmp280_data *data, int *val, int *val2); + int (*read_press)(struct bmp280_data *data, int *val, int *val2); + int (*read_humid)(struct bmp280_data *data, int *val, int *val2); + int (*read_calib)(struct bmp280_data *data); + int (*preinit)(struct bmp280_data *data); }; /* Chip infos for each variant */ @@ -473,7 +470,7 @@ extern const struct regmap_config bmp580_regmap_config; /* Probe called from different transports */ int bmp280_common_probe(struct device *dev, struct regmap *regmap, - const struct bmp280_chip_info *, + const struct bmp280_chip_info *chip_info, const char *name, int irq); diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c index 7d882e15e556..c6f44f0f4d2e 100644 --- a/drivers/iio/pressure/dps310.c +++ b/drivers/iio/pressure/dps310.c @@ -887,7 +887,7 @@ static int dps310_probe(struct i2c_client *client) } static const struct i2c_device_id dps310_id[] = { - { DPS310_DEV_NAME, 0 }, + { DPS310_DEV_NAME }, {} }; MODULE_DEVICE_TABLE(i2c, dps310_id); diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index 8bdb279129fa..6f7a16787143 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -266,8 +266,8 @@ static int hp03_probe(struct i2c_client *client) } static const struct i2c_device_id hp03_id[] = { - { "hp03", 0 }, - { }, + { "hp03" }, + { } }; MODULE_DEVICE_TABLE(i2c, hp03_id); diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 2086f3ef338f..3e0bf5d31ad7 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -637,7 +637,7 @@ static const struct of_device_id icp10100_of_match[] = { MODULE_DEVICE_TABLE(of, icp10100_of_match); static const struct i2c_device_id icp10100_id[] = { - { "icp10100", 0 }, + { "icp10100" }, { } }; MODULE_DEVICE_TABLE(i2c, icp10100_id); diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c index fcbdadf4a511..0c51dc02478e 100644 --- a/drivers/iio/pressure/mpl115_i2c.c +++ b/drivers/iio/pressure/mpl115_i2c.c @@ -45,7 +45,7 @@ static int mpl115_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id mpl115_i2c_id[] = { - { "mpl115", 0 }, + { "mpl115" }, { } }; MODULE_DEVICE_TABLE(i2c, mpl115_i2c_id); diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 7aa19584c340..71ded2eee060 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -318,7 +318,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend, mpl3115_resume); static const struct i2c_device_id mpl3115_id[] = { - { "mpl3115", 0 }, + { "mpl3115" }, { } }; MODULE_DEVICE_TABLE(i2c, mpl3115_id); diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c index a6463c06975e..c7cb0fd816d3 100644 --- a/drivers/iio/pressure/t5403.c +++ b/drivers/iio/pressure/t5403.c @@ -251,7 +251,7 @@ static int t5403_probe(struct i2c_client *client) } static const struct i2c_device_id t5403_id[] = { - { "t5403", 0 }, + { "t5403" }, { } }; MODULE_DEVICE_TABLE(i2c, t5403_id); diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c index c7fffbe7c788..4833e525c393 100644 --- a/drivers/iio/pressure/zpa2326_i2c.c +++ b/drivers/iio/pressure/zpa2326_i2c.c @@ -59,8 +59,8 @@ static void zpa2326_remove_i2c(struct i2c_client *client) } static const struct i2c_device_id zpa2326_i2c_ids[] = { - { "zpa2326", 0 }, - { }, + { "zpa2326" }, + { } }; MODULE_DEVICE_TABLE(i2c, zpa2326_i2c_ids); diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index 4982686fb4c3..dc66ca9bba6b 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -989,7 +989,7 @@ static int isl29501_probe(struct i2c_client *client) } static const struct i2c_device_id isl29501_id[] = { - {"isl29501", 0}, + { "isl29501" }, {} }; diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 2913d5e0fe4f..5c959730aecd 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -322,9 +322,9 @@ static void lidar_remove(struct i2c_client *client) } static const struct i2c_device_id lidar_id[] = { - {"lidar-lite-v2", 0}, - {"lidar-lite-v3", 0}, - { }, + { "lidar-lite-v2" }, + { "lidar-lite-v3" }, + { } }; MODULE_DEVICE_TABLE(i2c, lidar_id); diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c index f02e83e3f15f..aff60a3c1a6f 100644 --- a/drivers/iio/proximity/rfd77402.c +++ b/drivers/iio/proximity/rfd77402.c @@ -308,7 +308,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(rfd77402_pm_ops, rfd77402_suspend, rfd77402_resume); static const struct i2c_device_id rfd77402_id[] = { - { "rfd77402", 0 }, + { "rfd77402" }, { } }; MODULE_DEVICE_TABLE(i2c, rfd77402_id); diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c index aa0d14a49d5e..629f83c37d59 100644 --- a/drivers/iio/proximity/sx9324.c +++ b/drivers/iio/proximity/sx9324.c @@ -835,9 +835,8 @@ static int sx9324_init_compensation(struct iio_dev *indio_dev) int ret; /* run the compensation phase on all channels */ - ret = regmap_update_bits(data->regmap, SX9324_REG_STAT2, - SX9324_REG_STAT2_COMPSTAT_MASK, - SX9324_REG_STAT2_COMPSTAT_MASK); + ret = regmap_set_bits(data->regmap, SX9324_REG_STAT2, + SX9324_REG_STAT2_COMPSTAT_MASK); if (ret) return ret; diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c index 75a1c29f14eb..2b90bf45a201 100644 --- a/drivers/iio/proximity/sx9360.c +++ b/drivers/iio/proximity/sx9360.c @@ -672,9 +672,8 @@ static int sx9360_init_compensation(struct iio_dev *indio_dev) int ret; /* run the compensation phase on all channels */ - ret = regmap_update_bits(data->regmap, SX9360_REG_STAT, - SX9360_REG_STAT_COMPSTAT_MASK, - SX9360_REG_STAT_COMPSTAT_MASK); + ret = regmap_set_bits(data->regmap, SX9360_REG_STAT, + SX9360_REG_STAT_COMPSTAT_MASK); if (ret) return ret; diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 550e7d3cd5ee..92630812ece2 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -209,7 +209,7 @@ static int sx9500_inc_users(struct sx9500_data *data, int *counter, /* Bit is already active, nothing to do. */ return 0; - return regmap_update_bits(data->regmap, reg, bitmask, bitmask); + return regmap_set_bits(data->regmap, reg, bitmask); } static int sx9500_dec_users(struct sx9500_data *data, int *counter, @@ -220,7 +220,7 @@ static int sx9500_dec_users(struct sx9500_data *data, int *counter, /* There are more users, do not deactivate. */ return 0; - return regmap_update_bits(data->regmap, reg, bitmask, 0); + return regmap_clear_bits(data->regmap, reg, bitmask); } static int sx9500_inc_chan_users(struct sx9500_data *data, int chan) @@ -795,8 +795,8 @@ static int sx9500_init_compensation(struct iio_dev *indio_dev) int i, ret; unsigned int val; - ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, - SX9500_CHAN_MASK, SX9500_CHAN_MASK); + ret = regmap_set_bits(data->regmap, SX9500_REG_PROX_CTRL0, + SX9500_CHAN_MASK); if (ret < 0) return ret; @@ -815,8 +815,8 @@ static int sx9500_init_compensation(struct iio_dev *indio_dev) } out: - regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, - SX9500_CHAN_MASK, 0); + regmap_clear_bits(data->regmap, SX9500_REG_PROX_CTRL0, + SX9500_CHAN_MASK); return ret; } @@ -1043,8 +1043,8 @@ static const struct of_device_id sx9500_of_match[] = { MODULE_DEVICE_TABLE(of, sx9500_of_match); static const struct i2c_device_id sx9500_id[] = { - {"sx9500", 0}, - { }, + { "sx9500" }, + { } }; MODULE_DEVICE_TABLE(i2c, sx9500_id); diff --git a/drivers/iio/proximity/sx_common.c b/drivers/iio/proximity/sx_common.c index fe07d1444ac3..a95e9814aaf2 100644 --- a/drivers/iio/proximity/sx_common.c +++ b/drivers/iio/proximity/sx_common.c @@ -111,17 +111,16 @@ static int sx_common_enable_irq(struct sx_common_data *data, unsigned int irq) { if (!data->client->irq) return 0; - return regmap_update_bits(data->regmap, data->chip_info->reg_irq_msk, - irq << data->chip_info->irq_msk_offset, - irq << data->chip_info->irq_msk_offset); + return regmap_set_bits(data->regmap, data->chip_info->reg_irq_msk, + irq << data->chip_info->irq_msk_offset); } static int sx_common_disable_irq(struct sx_common_data *data, unsigned int irq) { if (!data->client->irq) return 0; - return regmap_update_bits(data->regmap, data->chip_info->reg_irq_msk, - irq << data->chip_info->irq_msk_offset, 0); + return regmap_clear_bits(data->regmap, data->chip_info->reg_irq_msk, + irq << data->chip_info->irq_msk_offset); } static int sx_common_update_chan_en(struct sx_common_data *data, diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c index 2cea64bea909..8d4f3f849fe2 100644 --- a/drivers/iio/proximity/vl53l0x-i2c.c +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -278,7 +278,7 @@ static int vl53l0x_probe(struct i2c_client *client) } static const struct i2c_device_id vl53l0x_id[] = { - { "vl53l0x", 0 }, + { "vl53l0x" }, { } }; MODULE_DEVICE_TABLE(i2c, vl53l0x_id); diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index 24d19f3c7292..21f2cfc55bf8 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -432,10 +434,9 @@ __ltc2983_custom_sensor_new(struct ltc2983_data *st, const struct fwnode_handle else n_entries = fwnode_property_count_u64(fn, propname); /* n_entries must be an even number */ - if (!n_entries || (n_entries % 2) != 0) { - dev_err(dev, "Number of entries either 0 or not even\n"); - return ERR_PTR(-EINVAL); - } + if (!n_entries || (n_entries % 2) != 0) + return dev_err_ptr_probe(dev, -EINVAL, + "Number of entries either 0 or not even\n"); new_custom = devm_kzalloc(dev, sizeof(*new_custom), GFP_KERNEL); if (!new_custom) @@ -443,19 +444,17 @@ __ltc2983_custom_sensor_new(struct ltc2983_data *st, const struct fwnode_handle new_custom->size = n_entries * n_size; /* check Steinhart size */ - if (is_steinhart && new_custom->size != LTC2983_CUSTOM_STEINHART_SIZE) { - dev_err(dev, "Steinhart sensors size(%zu) must be %u\n", new_custom->size, - LTC2983_CUSTOM_STEINHART_SIZE); - return ERR_PTR(-EINVAL); - } + if (is_steinhart && new_custom->size != LTC2983_CUSTOM_STEINHART_SIZE) + return dev_err_ptr_probe(dev, -EINVAL, + "Steinhart sensors size(%zu) must be %u\n", + new_custom->size, LTC2983_CUSTOM_STEINHART_SIZE); + /* Check space on the table. */ if (st->custom_table_size + new_custom->size > - (LTC2983_CUST_SENS_TBL_END_REG - - LTC2983_CUST_SENS_TBL_START_REG) + 1) { - dev_err(dev, "No space left(%d) for new custom sensor(%zu)", - st->custom_table_size, new_custom->size); - return ERR_PTR(-EINVAL); - } + (LTC2983_CUST_SENS_TBL_END_REG - LTC2983_CUST_SENS_TBL_START_REG) + 1) + return dev_err_ptr_probe(dev, -EINVAL, + "No space left(%d) for new custom sensor(%zu)\n", + st->custom_table_size, new_custom->size); /* allocate the table */ if (is_steinhart) @@ -688,21 +687,19 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data LTC2983_THERMOCOUPLE_OC_CURR(3); break; default: - dev_err(&st->spi->dev, - "Invalid open circuit current:%u", oc_current); - return ERR_PTR(-EINVAL); + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid open circuit current:%u\n", + oc_current); } thermo->sensor_config |= LTC2983_THERMOCOUPLE_OC_CHECK(1); } /* validate channel index */ if (!(thermo->sensor_config & LTC2983_THERMOCOUPLE_DIFF_MASK) && - sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, - "Invalid chann:%d for differential thermocouple", - sensor->chan); - return ERR_PTR(-EINVAL); - } + sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chann:%d for differential thermocouple\n", + sensor->chan); struct fwnode_handle *ref __free(fwnode_handle) = fwnode_find_reference(child, "adi,cold-junction-handle", 0); @@ -710,14 +707,13 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data ref = NULL; } else { ret = fwnode_property_read_u32(ref, "reg", &thermo->cold_junction_chan); - if (ret) { + if (ret) /* * This would be catched later but we can just return * the error right away. */ - dev_err(&st->spi->dev, "Property reg must be given\n"); - return ERR_PTR(ret); - } + return dev_err_ptr_probe(&st->spi->dev, ret, + "Property reg must be given\n"); } /* check custom sensor */ @@ -753,16 +749,14 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, struct fwnode_handle *ref __free(fwnode_handle) = fwnode_find_reference(child, "adi,rsense-handle", 0); - if (IS_ERR(ref)) { - dev_err(dev, "Property adi,rsense-handle missing or invalid"); - return ERR_CAST(ref); - } + if (IS_ERR(ref)) + return dev_err_cast_probe(dev, ref, + "Property adi,rsense-handle missing or invalid\n"); ret = fwnode_property_read_u32(ref, "reg", &rtd->r_sense_chan); - if (ret) { - dev_err(dev, "Property reg must be given\n"); - return ERR_PTR(ret); - } + if (ret) + return dev_err_ptr_probe(dev, ret, + "Property reg must be given\n"); ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires); if (!ret) { @@ -781,19 +775,19 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, rtd->sensor_config = LTC2983_RTD_N_WIRES(3); break; default: - dev_err(dev, "Invalid number of wires:%u\n", n_wires); - return ERR_PTR(-EINVAL); + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid number of wires:%u\n", + n_wires); } } if (fwnode_property_read_bool(child, "adi,rsense-share")) { /* Current rotation is only available with rsense sharing */ if (fwnode_property_read_bool(child, "adi,current-rotate")) { - if (n_wires == 2 || n_wires == 3) { - dev_err(dev, - "Rotation not allowed for 2/3 Wire RTDs"); - return ERR_PTR(-EINVAL); - } + if (n_wires == 2 || n_wires == 3) + return dev_err_ptr_probe(dev, -EINVAL, + "Rotation not allowed for 2/3 Wire RTDs\n"); + rtd->sensor_config |= LTC2983_RTD_C_ROTATE(1); } else { rtd->sensor_config |= LTC2983_RTD_R_SHARE(1); @@ -816,29 +810,22 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, if (((rtd->sensor_config & LTC2983_RTD_KELVIN_R_SENSE_MASK) == LTC2983_RTD_KELVIN_R_SENSE_MASK) && - (rtd->r_sense_chan <= min)) { + (rtd->r_sense_chan <= min)) /* kelvin rsense*/ - dev_err(dev, - "Invalid rsense chann:%d to use in kelvin rsense", - rtd->r_sense_chan); + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid rsense chann:%d to use in kelvin rsense\n", + rtd->r_sense_chan); - return ERR_PTR(-EINVAL); - } - - if (sensor->chan < min || sensor->chan > max) { - dev_err(dev, "Invalid chann:%d for the rtd config", - sensor->chan); - - return ERR_PTR(-EINVAL); - } + if (sensor->chan < min || sensor->chan > max) + return dev_err_ptr_probe(dev, -EINVAL, + "Invalid chann:%d for the rtd config\n", + sensor->chan); } else { /* same as differential case */ - if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, - "Invalid chann:%d for RTD", sensor->chan); - - return ERR_PTR(-EINVAL); - } + if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chann:%d for RTD\n", + sensor->chan); } /* check custom sensor */ @@ -886,10 +873,9 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, rtd->excitation_current = 0x08; break; default: - dev_err(&st->spi->dev, - "Invalid value for excitation current(%u)", - excitation_current); - return ERR_PTR(-EINVAL); + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid value for excitation current(%u)\n", + excitation_current); } } @@ -913,16 +899,14 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s struct fwnode_handle *ref __free(fwnode_handle) = fwnode_find_reference(child, "adi,rsense-handle", 0); - if (IS_ERR(ref)) { - dev_err(dev, "Property adi,rsense-handle missing or invalid"); - return ERR_CAST(ref); - } + if (IS_ERR(ref)) + return dev_err_cast_probe(dev, ref, + "Property adi,rsense-handle missing or invalid\n"); ret = fwnode_property_read_u32(ref, "reg", &thermistor->r_sense_chan); - if (ret) { - dev_err(dev, "rsense channel must be configured...\n"); - return ERR_PTR(ret); - } + if (ret) + return dev_err_ptr_probe(dev, ret, + "rsense channel must be configured...\n"); if (fwnode_property_read_bool(child, "adi,single-ended")) { thermistor->sensor_config = LTC2983_THERMISTOR_SGL(1); @@ -937,12 +921,10 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s } /* validate channel index */ if (!(thermistor->sensor_config & LTC2983_THERMISTOR_DIFF_MASK) && - sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, - "Invalid chann:%d for differential thermistor", - sensor->chan); - return ERR_PTR(-EINVAL); - } + sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chann:%d for differential thermistor\n", + sensor->chan); /* check custom sensor */ if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) { @@ -981,12 +963,10 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s switch (excitation_current) { case 0: /* auto range */ - if (sensor->type >= - LTC2983_SENSOR_THERMISTOR_STEINHART) { - dev_err(&st->spi->dev, - "Auto Range not allowed for custom sensors\n"); - return ERR_PTR(-EINVAL); - } + if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Auto Range not allowed for custom sensors\n"); + thermistor->excitation_current = 0x0c; break; case 250: @@ -1023,10 +1003,9 @@ ltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *s thermistor->excitation_current = 0x0b; break; default: - dev_err(&st->spi->dev, - "Invalid value for excitation current(%u)", - excitation_current); - return ERR_PTR(-EINVAL); + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid value for excitation current(%u)\n", + excitation_current); } } @@ -1056,12 +1035,11 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data * /* validate channel index */ if (!(diode->sensor_config & LTC2983_DIODE_DIFF_MASK) && - sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, - "Invalid chann:%d for differential thermistor", - sensor->chan); - return ERR_PTR(-EINVAL); - } + sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chann:%d for differential thermistor\n", + sensor->chan); + /* set common parameters */ diode->sensor.fault_handler = ltc2983_common_fault_handler; diode->sensor.assign_chan = ltc2983_diode_assign_chan; @@ -1083,10 +1061,9 @@ ltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data * diode->excitation_current = 0x03; break; default: - dev_err(&st->spi->dev, - "Invalid value for excitation current(%u)", - excitation_current); - return ERR_PTR(-EINVAL); + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid value for excitation current(%u)\n", + excitation_current); } } @@ -1111,17 +1088,15 @@ static struct ltc2983_sensor *ltc2983_r_sense_new(struct fwnode_handle *child, return ERR_PTR(-ENOMEM); /* validate channel index */ - if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, "Invalid chann:%d for r_sense", - sensor->chan); - return ERR_PTR(-EINVAL); - } + if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chann:%d for r_sense\n", + sensor->chan); ret = fwnode_property_read_u32(child, "adi,rsense-val-milli-ohms", &temp); - if (ret) { - dev_err(&st->spi->dev, "Property adi,rsense-val-milli-ohms missing\n"); - return ERR_PTR(-EINVAL); - } + if (ret) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Property adi,rsense-val-milli-ohms missing\n"); /* * Times 1000 because we have milli-ohms and __convert_to_raw * expects scales of 1000000 which are used for all other @@ -1149,12 +1124,11 @@ static struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child, if (fwnode_property_read_bool(child, "adi,single-ended")) adc->single_ended = true; - if (!adc->single_ended && - sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, "Invalid chan:%d for differential adc\n", - sensor->chan); - return ERR_PTR(-EINVAL); - } + if (!adc->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chan:%d for differential adc\n", + sensor->chan); + /* set common parameters */ adc->sensor.assign_chan = ltc2983_adc_assign_chan; adc->sensor.fault_handler = ltc2983_common_fault_handler; @@ -1175,12 +1149,10 @@ static struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child, if (fwnode_property_read_bool(child, "adi,single-ended")) temp->single_ended = true; - if (!temp->single_ended && - sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) { - dev_err(&st->spi->dev, "Invalid chan:%d for differential temp\n", - sensor->chan); - return ERR_PTR(-EINVAL); - } + if (!temp->single_ended && sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) + return dev_err_ptr_probe(&st->spi->dev, -EINVAL, + "Invalid chan:%d for differential temp\n", + sensor->chan); temp->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-temp", false, 4096, true); @@ -1296,8 +1268,8 @@ static int ltc2983_reg_access(struct iio_dev *indio_dev, if (readval) return regmap_read(st->regmap, reg, readval); - else - return regmap_write(st->regmap, reg, writeval); + + return regmap_write(st->regmap, reg, writeval); } static irqreturn_t ltc2983_irq_handler(int irq, void *data) @@ -1330,10 +1302,9 @@ static int ltc2983_parse_fw(struct ltc2983_data *st) device_property_read_u32(dev, "adi,filter-notch-freq", &st->filter_notch_freq); st->num_channels = device_get_child_node_count(dev); - if (!st->num_channels) { - dev_err(&st->spi->dev, "At least one channel must be given!"); - return -EINVAL; - } + if (!st->num_channels) + return dev_err_probe(&st->spi->dev, -EINVAL, + "At least one channel must be given!\n"); st->sensors = devm_kcalloc(dev, st->num_channels, sizeof(*st->sensors), GFP_KERNEL); @@ -1438,19 +1409,17 @@ static int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd, time = wait_for_completion_timeout(&st->completion, msecs_to_jiffies(wait_time)); - if (!time) { - dev_err(&st->spi->dev, "EEPROM command timed out\n"); - return -ETIMEDOUT; - } + if (!time) + return dev_err_probe(&st->spi->dev, -ETIMEDOUT, + "EEPROM command timed out\n"); ret = regmap_read(st->regmap, status_reg, &val); if (ret) return ret; - if (val & status_fail_mask) { - dev_err(&st->spi->dev, "EEPROM command failed: 0x%02X\n", val); - return -EINVAL; - } + if (val & status_fail_mask) + return dev_err_probe(&st->spi->dev, -EINVAL, + "EEPROM command failed: 0x%02X\n", val); return 0; } @@ -1464,10 +1433,9 @@ static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) ret = regmap_read_poll_timeout(st->regmap, LTC2983_STATUS_REG, status, LTC2983_STATUS_UP(status) == 1, 25000, 25000 * 10); - if (ret) { - dev_err(&st->spi->dev, "Device startup timed out\n"); - return ret; - } + if (ret) + return dev_err_probe(&st->spi->dev, ret, + "Device startup timed out\n"); ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG, LTC2983_NOTCH_FREQ_MASK, @@ -1583,10 +1551,9 @@ static int ltc2983_probe(struct spi_device *spi) return -ENODEV; st->regmap = devm_regmap_init_spi(spi, <c2983_regmap_config); - if (IS_ERR(st->regmap)) { - dev_err(&spi->dev, "Failed to initialize regmap\n"); - return PTR_ERR(st->regmap); - } + if (IS_ERR(st->regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), + "Failed to initialize regmap\n"); mutex_init(&st->lock); init_completion(&st->completion); @@ -1624,10 +1591,9 @@ static int ltc2983_probe(struct spi_device *spi) ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler, IRQF_TRIGGER_RISING, st->info->name, st); - if (ret) { - dev_err(&spi->dev, "failed to request an irq, %d", ret); - return ret; - } + if (ret) + return dev_err_probe(&spi->dev, ret, + "failed to request an irq\n"); if (st->info->has_eeprom) { ret = ltc2983_eeprom_cmd(st, LTC2983_EEPROM_WRITE_CMD, diff --git a/drivers/iio/temperature/max30208.c b/drivers/iio/temperature/max30208.c index 48be03852cd8..720469f9dc36 100644 --- a/drivers/iio/temperature/max30208.c +++ b/drivers/iio/temperature/max30208.c @@ -34,7 +34,6 @@ struct max30208_data { struct i2c_client *client; - struct iio_dev *indio_dev; struct mutex lock; /* Lock to prevent concurrent reads of temperature readings */ }; diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c index 7a3eef5d5e75..f1bb0976273d 100644 --- a/drivers/iio/temperature/mcp9600.c +++ b/drivers/iio/temperature/mcp9600.c @@ -6,39 +6,123 @@ * Author: */ +#include +#include +#include #include #include #include +#include +#include +#include +#include #include #include +#include #include /* MCP9600 registers */ #define MCP9600_HOT_JUNCTION 0x0 #define MCP9600_COLD_JUNCTION 0x2 +#define MCP9600_STATUS 0x4 +#define MCP9600_STATUS_ALERT(x) BIT(x) +#define MCP9600_ALERT_CFG1 0x8 +#define MCP9600_ALERT_CFG(x) (MCP9600_ALERT_CFG1 + (x - 1)) +#define MCP9600_ALERT_CFG_ENABLE BIT(0) +#define MCP9600_ALERT_CFG_ACTIVE_HIGH BIT(2) +#define MCP9600_ALERT_CFG_FALLING BIT(3) +#define MCP9600_ALERT_CFG_COLD_JUNCTION BIT(4) +#define MCP9600_ALERT_HYSTERESIS1 0xc +#define MCP9600_ALERT_HYSTERESIS(x) (MCP9600_ALERT_HYSTERESIS1 + (x - 1)) +#define MCP9600_ALERT_LIMIT1 0x10 +#define MCP9600_ALERT_LIMIT(x) (MCP9600_ALERT_LIMIT1 + (x - 1)) +#define MCP9600_ALERT_LIMIT_MASK GENMASK(15, 2) #define MCP9600_DEVICE_ID 0x20 /* MCP9600 device id value */ #define MCP9600_DEVICE_ID_MCP9600 0x40 -static const struct iio_chan_spec mcp9600_channels[] = { +#define MCP9600_ALERT_COUNT 4 + +#define MCP9600_MIN_TEMP_HOT_JUNCTION_MICRO -200000000 +#define MCP9600_MAX_TEMP_HOT_JUNCTION_MICRO 1800000000 + +#define MCP9600_MIN_TEMP_COLD_JUNCTION_MICRO -40000000 +#define MCP9600_MAX_TEMP_COLD_JUNCTION_MICRO 125000000 + +enum mcp9600_alert { + MCP9600_ALERT1, + MCP9600_ALERT2, + MCP9600_ALERT3, + MCP9600_ALERT4 +}; + +static const char * const mcp9600_alert_name[MCP9600_ALERT_COUNT] = { + [MCP9600_ALERT1] = "alert1", + [MCP9600_ALERT2] = "alert2", + [MCP9600_ALERT3] = "alert3", + [MCP9600_ALERT4] = "alert4", +}; + +static const struct iio_event_spec mcp9600_events[] = { { - .type = IIO_TEMP, - .address = MCP9600_HOT_JUNCTION, - .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_HYSTERESIS), }, { - .type = IIO_TEMP, - .address = MCP9600_COLD_JUNCTION, - .channel2 = IIO_MOD_TEMP_AMBIENT, - .modified = 1, - .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_HYSTERESIS), }, }; +#define MCP9600_CHANNELS(hj_num_ev, hj_ev_spec_off, cj_num_ev, cj_ev_spec_off) \ + { \ + { \ + .type = IIO_TEMP, \ + .address = MCP9600_HOT_JUNCTION, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .event_spec = &mcp9600_events[hj_ev_spec_off], \ + .num_event_specs = hj_num_ev, \ + }, \ + { \ + .type = IIO_TEMP, \ + .address = MCP9600_COLD_JUNCTION, \ + .channel2 = IIO_MOD_TEMP_AMBIENT, \ + .modified = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .event_spec = &mcp9600_events[cj_ev_spec_off], \ + .num_event_specs = cj_num_ev, \ + }, \ + } + +static const struct iio_chan_spec mcp9600_channels[][2] = { + MCP9600_CHANNELS(0, 0, 0, 0), /* Alerts: - - - - */ + MCP9600_CHANNELS(1, 0, 0, 0), /* Alerts: 1 - - - */ + MCP9600_CHANNELS(1, 1, 0, 0), /* Alerts: - 2 - - */ + MCP9600_CHANNELS(2, 0, 0, 0), /* Alerts: 1 2 - - */ + MCP9600_CHANNELS(0, 0, 1, 0), /* Alerts: - - 3 - */ + MCP9600_CHANNELS(1, 0, 1, 0), /* Alerts: 1 - 3 - */ + MCP9600_CHANNELS(1, 1, 1, 0), /* Alerts: - 2 3 - */ + MCP9600_CHANNELS(2, 0, 1, 0), /* Alerts: 1 2 3 - */ + MCP9600_CHANNELS(0, 0, 1, 1), /* Alerts: - - - 4 */ + MCP9600_CHANNELS(1, 0, 1, 1), /* Alerts: 1 - - 4 */ + MCP9600_CHANNELS(1, 1, 1, 1), /* Alerts: - 2 - 4 */ + MCP9600_CHANNELS(2, 0, 1, 1), /* Alerts: 1 2 - 4 */ + MCP9600_CHANNELS(0, 0, 2, 0), /* Alerts: - - 3 4 */ + MCP9600_CHANNELS(1, 0, 2, 0), /* Alerts: 1 - 3 4 */ + MCP9600_CHANNELS(1, 1, 2, 0), /* Alerts: - 2 3 4 */ + MCP9600_CHANNELS(2, 0, 2, 0), /* Alerts: 1 2 3 4 */ +}; + struct mcp9600_data { struct i2c_client *client; }; @@ -80,15 +164,261 @@ static int mcp9600_read_raw(struct iio_dev *indio_dev, } } +static int mcp9600_get_alert_index(int channel2, enum iio_event_direction dir) +{ + if (channel2 == IIO_MOD_TEMP_AMBIENT) { + if (dir == IIO_EV_DIR_RISING) + return MCP9600_ALERT3; + else + return MCP9600_ALERT4; + } else { + if (dir == IIO_EV_DIR_RISING) + return MCP9600_ALERT1; + else + return MCP9600_ALERT2; + } +} + +static int mcp9600_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct mcp9600_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + int i, ret; + + i = mcp9600_get_alert_index(chan->channel2, dir); + ret = i2c_smbus_read_byte_data(client, MCP9600_ALERT_CFG(i + 1)); + if (ret < 0) + return ret; + + return FIELD_GET(MCP9600_ALERT_CFG_ENABLE, ret); +} + +static int mcp9600_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct mcp9600_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + int i, ret; + + i = mcp9600_get_alert_index(chan->channel2, dir); + ret = i2c_smbus_read_byte_data(client, MCP9600_ALERT_CFG(i + 1)); + if (ret < 0) + return ret; + + if (state) + ret |= MCP9600_ALERT_CFG_ENABLE; + else + ret &= ~MCP9600_ALERT_CFG_ENABLE; + + return i2c_smbus_write_byte_data(client, MCP9600_ALERT_CFG(i + 1), ret); +} + +static int mcp9600_read_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, int *val2) +{ + struct mcp9600_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + s32 ret; + int i; + + i = mcp9600_get_alert_index(chan->channel2, dir); + switch (info) { + case IIO_EV_INFO_VALUE: + ret = i2c_smbus_read_word_swapped(client, MCP9600_ALERT_LIMIT(i + 1)); + if (ret < 0) + return ret; + /* + * Temperature is stored in two’s complement format in + * bits(15:2), LSB is 0.25 degree celsius. + */ + *val = sign_extend32(FIELD_GET(MCP9600_ALERT_LIMIT_MASK, ret), 13); + *val2 = 4; + return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_HYSTERESIS: + ret = i2c_smbus_read_byte_data(client, MCP9600_ALERT_HYSTERESIS(i + 1)); + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int mcp9600_write_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int val, int val2) +{ + struct mcp9600_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + int s_val, i; + s16 thresh; + u8 hyst; + + i = mcp9600_get_alert_index(chan->channel2, dir); + switch (info) { + case IIO_EV_INFO_VALUE: + /* Scale value to include decimal part into calculations */ + s_val = (val < 0) ? ((val * 1000000) - val2) : + ((val * 1000000) + val2); + if (chan->channel2 == IIO_MOD_TEMP_AMBIENT) { + s_val = max(s_val, MCP9600_MIN_TEMP_COLD_JUNCTION_MICRO); + s_val = min(s_val, MCP9600_MAX_TEMP_COLD_JUNCTION_MICRO); + } else { + s_val = max(s_val, MCP9600_MIN_TEMP_HOT_JUNCTION_MICRO); + s_val = min(s_val, MCP9600_MAX_TEMP_HOT_JUNCTION_MICRO); + } + + /* + * Shift length 4 bits = 2(15:2) + 2(0.25 LSB), temperature is + * stored in two’s complement format. + */ + thresh = (s16)(s_val / (1000000 >> 4)); + return i2c_smbus_write_word_swapped(client, + MCP9600_ALERT_LIMIT(i + 1), + thresh); + case IIO_EV_INFO_HYSTERESIS: + hyst = min(abs(val), 255); + return i2c_smbus_write_byte_data(client, + MCP9600_ALERT_HYSTERESIS(i + 1), + hyst); + default: + return -EINVAL; + } +} + static const struct iio_info mcp9600_info = { .read_raw = mcp9600_read_raw, + .read_event_config = mcp9600_read_event_config, + .write_event_config = mcp9600_write_event_config, + .read_event_value = mcp9600_read_thresh, + .write_event_value = mcp9600_write_thresh, }; +static irqreturn_t mcp9600_alert_handler(void *private, + enum mcp9600_alert alert, + enum iio_modifier mod, + enum iio_event_direction dir) +{ + struct iio_dev *indio_dev = private; + struct mcp9600_data *data = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_read_byte_data(data->client, MCP9600_STATUS); + if (ret < 0) + return IRQ_HANDLED; + + if (!(ret & MCP9600_STATUS_ALERT(alert))) + return IRQ_NONE; + + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_TEMP, 0, mod, IIO_EV_TYPE_THRESH, + dir), + iio_get_time_ns(indio_dev)); + + return IRQ_HANDLED; +} + +static irqreturn_t mcp9600_alert1_handler(int irq, void *private) +{ + return mcp9600_alert_handler(private, MCP9600_ALERT1, IIO_NO_MOD, + IIO_EV_DIR_RISING); +} + +static irqreturn_t mcp9600_alert2_handler(int irq, void *private) +{ + return mcp9600_alert_handler(private, MCP9600_ALERT2, IIO_NO_MOD, + IIO_EV_DIR_FALLING); +} + +static irqreturn_t mcp9600_alert3_handler(int irq, void *private) +{ + return mcp9600_alert_handler(private, MCP9600_ALERT3, + IIO_MOD_TEMP_AMBIENT, IIO_EV_DIR_RISING); +} + +static irqreturn_t mcp9600_alert4_handler(int irq, void *private) +{ + return mcp9600_alert_handler(private, MCP9600_ALERT4, + IIO_MOD_TEMP_AMBIENT, IIO_EV_DIR_FALLING); +} + +static irqreturn_t (*mcp9600_alert_handler_func[MCP9600_ALERT_COUNT]) (int, void *) = { + mcp9600_alert1_handler, + mcp9600_alert2_handler, + mcp9600_alert3_handler, + mcp9600_alert4_handler, +}; + +static int mcp9600_probe_alerts(struct iio_dev *indio_dev) +{ + struct mcp9600_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + struct device *dev = &client->dev; + struct fwnode_handle *fwnode = dev_fwnode(dev); + unsigned int irq_type; + int ret, irq, i; + u8 val, ch_sel; + + /* + * alert1: hot junction, rising temperature + * alert2: hot junction, falling temperature + * alert3: cold junction, rising temperature + * alert4: cold junction, falling temperature + */ + ch_sel = 0; + for (i = 0; i < MCP9600_ALERT_COUNT; i++) { + irq = fwnode_irq_get_byname(fwnode, mcp9600_alert_name[i]); + if (irq <= 0) + continue; + + val = 0; + irq_type = irq_get_trigger_type(irq); + if (irq_type == IRQ_TYPE_EDGE_RISING) + val |= MCP9600_ALERT_CFG_ACTIVE_HIGH; + + if (i == MCP9600_ALERT2 || i == MCP9600_ALERT4) + val |= MCP9600_ALERT_CFG_FALLING; + + if (i == MCP9600_ALERT3 || i == MCP9600_ALERT4) + val |= MCP9600_ALERT_CFG_COLD_JUNCTION; + + ret = i2c_smbus_write_byte_data(client, + MCP9600_ALERT_CFG(i + 1), + val); + if (ret < 0) + return ret; + + ret = devm_request_threaded_irq(dev, irq, NULL, + mcp9600_alert_handler_func[i], + IRQF_ONESHOT, "mcp9600", + indio_dev); + if (ret) + return ret; + + ch_sel |= BIT(i); + } + + return ch_sel; +} + static int mcp9600_probe(struct i2c_client *client) { struct iio_dev *indio_dev; struct mcp9600_data *data; - int ret; + int ret, ch_sel; ret = i2c_smbus_read_byte_data(client, MCP9600_DEVICE_ID); if (ret < 0) @@ -104,11 +434,15 @@ static int mcp9600_probe(struct i2c_client *client) data = iio_priv(indio_dev); data->client = client; + ch_sel = mcp9600_probe_alerts(indio_dev); + if (ch_sel < 0) + return ch_sel; + indio_dev->info = &mcp9600_info; indio_dev->name = "mcp9600"; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = mcp9600_channels; - indio_dev->num_channels = ARRAY_SIZE(mcp9600_channels); + indio_dev->channels = mcp9600_channels[ch_sel]; + indio_dev->num_channels = ARRAY_SIZE(mcp9600_channels[ch_sel]); return devm_iio_device_register(&client->dev, indio_dev); } @@ -135,6 +469,7 @@ static struct i2c_driver mcp9600_driver = { }; module_i2c_driver(mcp9600_driver); +MODULE_AUTHOR("Dimitri Fedrau "); MODULE_AUTHOR("Andrew Hepp "); MODULE_DESCRIPTION("Microchip MCP9600 thermocouple EMF converter driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index 8a57be108620..ae4ea587e7f9 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -334,8 +334,8 @@ static int mlx90632_perform_measurement(struct mlx90632_data *data) unsigned int reg_status; int ret; - ret = regmap_update_bits(data->regmap, MLX90632_REG_STATUS, - MLX90632_STAT_DATA_RDY, 0); + ret = regmap_clear_bits(data->regmap, MLX90632_REG_STATUS, + MLX90632_STAT_DATA_RDY); if (ret < 0) return ret; @@ -1279,7 +1279,7 @@ static int mlx90632_probe(struct i2c_client *client) } static const struct i2c_device_id mlx90632_id[] = { - { "mlx90632", 0 }, + { "mlx90632" }, { } }; MODULE_DEVICE_TABLE(i2c, mlx90632_id); diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index 3a3904fe138c..6d8d661f0c82 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -280,7 +280,7 @@ static const struct of_device_id tmp006_of_match[] = { MODULE_DEVICE_TABLE(of, tmp006_of_match); static const struct i2c_device_id tmp006_id[] = { - { "tmp006", 0 }, + { "tmp006" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp006_id); diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index decef6896362..9bdfa9423492 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -563,7 +563,7 @@ static const struct of_device_id tmp007_of_match[] = { MODULE_DEVICE_TABLE(of, tmp007_of_match); static const struct i2c_device_id tmp007_id[] = { - { "tmp007", 0 }, + { "tmp007" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp007_id); diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index 53ef56fbfe1d..9213761c5d18 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -206,7 +206,7 @@ static int tsys01_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tsys01_id[] = { - {"tsys01", 0}, + { "tsys01" }, {} }; MODULE_DEVICE_TABLE(i2c, tsys01_id); diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c index 6191db92ef9a..2b4959d6e467 100644 --- a/drivers/iio/temperature/tsys02d.c +++ b/drivers/iio/temperature/tsys02d.c @@ -168,7 +168,7 @@ static int tsys02d_probe(struct i2c_client *client) } static const struct i2c_device_id tsys02d_id[] = { - {"tsys02d", 0}, + { "tsys02d" }, {} }; MODULE_DEVICE_TABLE(i2c, tsys02d_id); diff --git a/drivers/iio/test/iio-test-gts.c b/drivers/iio/test/iio-test-gts.c index cf7ab773ea0b..5f16a7b5e6d4 100644 --- a/drivers/iio/test/iio-test-gts.c +++ b/drivers/iio/test/iio-test-gts.c @@ -70,6 +70,7 @@ */ static struct iio_gts gts; +/* Keep the gain and time tables unsorted to test the sorting */ static const struct iio_gain_sel_pair gts_test_gains[] = { GAIN_SCALE_GAIN(1, TEST_GSEL_1), GAIN_SCALE_GAIN(4, TEST_GSEL_4), @@ -79,16 +80,17 @@ static const struct iio_gain_sel_pair gts_test_gains[] = { GAIN_SCALE_GAIN(256, TEST_GSEL_256), GAIN_SCALE_GAIN(512, TEST_GSEL_512), GAIN_SCALE_GAIN(1024, TEST_GSEL_1024), - GAIN_SCALE_GAIN(2048, TEST_GSEL_2048), GAIN_SCALE_GAIN(4096, TEST_GSEL_4096), + GAIN_SCALE_GAIN(2048, TEST_GSEL_2048), #define HWGAIN_MAX 4096 }; static const struct iio_itime_sel_mul gts_test_itimes[] = { - GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8), - GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4), GAIN_SCALE_ITIME_US(100 * 1000, TEST_TSEL_100, 2), + GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8), + GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8), GAIN_SCALE_ITIME_US(50 * 1000, TEST_TSEL_50, 1), + GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4), #define TIMEGAIN_MAX 8 }; #define TOTAL_GAIN_MAX (HWGAIN_MAX * TIMEGAIN_MAX) diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index d76444030a28..0684329956d9 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -158,7 +158,7 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, regmap_write(priv->regmap, TIM_PSC, prescaler); regmap_write(priv->regmap, TIM_ARR, prd - 1); - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); + regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE); /* Force master mode to update mode */ if (stm32_timer_is_trgo2_name(trig->name)) @@ -169,10 +169,10 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, 0x2 << TIM_CR2_MMS_SHIFT); /* Make sure that registers are updated */ - regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); + regmap_set_bits(priv->regmap, TIM_EGR, TIM_EGR_UG); /* Enable controller */ - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN); + regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); mutex_unlock(&priv->lock); return 0; @@ -189,19 +189,19 @@ static void stm32_timer_stop(struct stm32_timer_trigger *priv, mutex_lock(&priv->lock); /* Stop timer */ - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); + regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE); + regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); regmap_write(priv->regmap, TIM_PSC, 0); regmap_write(priv->regmap, TIM_ARR, 0); /* Force disable master mode */ if (stm32_timer_is_trgo2_name(trig->name)) - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); + regmap_clear_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2); else - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0); + regmap_clear_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS); /* Make sure that registers are updated */ - regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); + regmap_set_bits(priv->regmap, TIM_EGR, TIM_EGR_UG); if (priv->enabled) { priv->enabled = false; @@ -498,11 +498,9 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, priv->enabled = true; clk_enable(priv->clk); } - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, - TIM_CR1_CEN); + regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); } else { - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, - 0); + regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); if (priv->enabled) { priv->enabled = false; clk_disable(priv->clk); @@ -555,7 +553,7 @@ static int stm32_set_trigger_mode(struct iio_dev *indio_dev, { struct stm32_timer_trigger *priv = iio_priv(indio_dev); - regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, TIM_SMCR_SMS); + regmap_set_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS); return 0; } @@ -683,7 +681,7 @@ static ssize_t stm32_count_set_preset(struct iio_dev *indio_dev, return ret; /* TIMx_ARR register shouldn't be buffered (ARPE=0) */ - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); + regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE); regmap_write(priv->regmap, TIM_ARR, preset); return len; @@ -757,9 +755,9 @@ static void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv) * Master mode selection 2 bits can only be written and read back when * timer supports it. */ - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2); + regmap_set_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2); regmap_read(priv->regmap, TIM_CR2, &val); - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); + regmap_clear_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2); priv->has_trgo2 = !!val; } @@ -820,7 +818,7 @@ static void stm32_timer_trigger_remove(struct platform_device *pdev) /* Check if nobody else use the timer, then disable it */ regmap_read(priv->regmap, TIM_CCER, &val); if (!(val & TIM_CCER_CCXE)) - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); + regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); if (priv->enabled) clk_disable(priv->clk); @@ -841,7 +839,7 @@ static int stm32_timer_trigger_suspend(struct device *dev) regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr); /* Disable the timer */ - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); + regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); clk_disable(priv->clk); } diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 51e0c4954600..a8ce3d140722 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -288,8 +288,8 @@ static void evdev_pass_values(struct evdev_client *client, /* * Pass incoming events to all connected clients. */ -static void evdev_events(struct input_handle *handle, - const struct input_value *vals, unsigned int count) +static unsigned int evdev_events(struct input_handle *handle, + struct input_value *vals, unsigned int count) { struct evdev *evdev = handle->private; struct evdev_client *client; @@ -306,17 +306,8 @@ static void evdev_events(struct input_handle *handle, evdev_pass_values(client, vals, count, ev_time); rcu_read_unlock(); -} -/* - * Pass incoming event to all connected clients. - */ -static void evdev_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) -{ - struct input_value vals[] = { { type, code, value } }; - - evdev_events(handle, vals, 1); + return count; } static int evdev_fasync(int fd, struct file *file, int on) @@ -1418,7 +1409,6 @@ static const struct input_device_id evdev_ids[] = { MODULE_DEVICE_TABLE(input, evdev_ids); static struct input_handler evdev_handler = { - .event = evdev_event, .events = evdev_events, .connect = evdev_connect, .disconnect = evdev_disconnect, diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index 76ce41e58df0..4f4583048f24 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -43,7 +43,7 @@ static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct gameport *port; int error; - emu = kzalloc(sizeof(struct emu), GFP_KERNEL); + emu = kzalloc(sizeof(*emu), GFP_KERNEL); port = gameport_allocate_port(); if (!emu || !port) { printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index e785d36b1926..7ae5009385cc 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -68,7 +68,7 @@ static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id) struct gameport *port; int error; - gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL); + gp = kzalloc(sizeof(*gp), GFP_KERNEL); port = gameport_allocate_port(); if (!gp || !port) { printk(KERN_ERR "fm801-gp: Memory allocation failed\n"); diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index cfcc81c47b50..ad39ac6fa96d 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -372,7 +372,7 @@ static int gameport_queue_event(void *object, struct module *owner, } } - event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); + event = kmalloc(sizeof(*event), GFP_ATOMIC); if (!event) { pr_err("Not enough memory to queue event %d\n", event_type); retval = -ENOMEM; diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 91a8cd346e9b..880e714b49bc 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c @@ -120,7 +120,7 @@ static int ns558_isa_probe(int io) return -EBUSY; } - ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL); + ns558 = kzalloc(sizeof(*ns558), GFP_KERNEL); port = gameport_allocate_port(); if (!ns558 || !port) { printk(KERN_ERR "ns558: Memory allocation failed.\n"); @@ -192,7 +192,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did) if (!request_region(ioport, iolen, "ns558-pnp")) return -EBUSY; - ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL); + ns558 = kzalloc(sizeof(*ns558), GFP_KERNEL); port = gameport_allocate_port(); if (!ns558 || !port) { printk(KERN_ERR "ns558: Memory allocation failed\n"); diff --git a/drivers/input/input.c b/drivers/input/input.c index fd4997ba263c..54c57b267b25 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -99,45 +99,13 @@ static void input_stop_autorepeat(struct input_dev *dev) del_timer(&dev->timer); } -/* - * Pass event first through all filters and then, if event has not been - * filtered out, through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. - */ -static unsigned int input_to_handler(struct input_handle *handle, - struct input_value *vals, unsigned int count) -{ - struct input_handler *handler = handle->handler; - struct input_value *end = vals; - struct input_value *v; - - if (handler->filter) { - for (v = vals; v != vals + count; v++) { - if (handler->filter(handle, v->type, v->code, v->value)) - continue; - if (end != v) - *end = *v; - end++; - } - count = end - vals; - } - - if (!count) - return 0; - - if (handler->events) - handler->events(handle, vals, count); - else if (handler->event) - for (v = vals; v != vals + count; v++) - handler->event(handle, v->type, v->code, v->value); - - return count; -} - /* * Pass values first through all filters and then, if event has not been - * filtered out, through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. + * filtered out, through all open handles. This order is achieved by placing + * filters at the head of the list of handles attached to the device, and + * placing regular handles at the tail of the list. + * + * This function is called with dev->event_lock held and interrupts disabled. */ static void input_pass_values(struct input_dev *dev, struct input_value *vals, unsigned int count) @@ -147,18 +115,16 @@ static void input_pass_values(struct input_dev *dev, lockdep_assert_held(&dev->event_lock); - if (!count) - return; - rcu_read_lock(); handle = rcu_dereference(dev->grab); if (handle) { - count = input_to_handler(handle, vals, count); + count = handle->handler->events(handle, vals, count); } else { list_for_each_entry_rcu(handle, &dev->h_list, d_node) if (handle->open) { - count = input_to_handler(handle, vals, count); + count = handle->handler->events(handle, vals, + count); if (!count) break; } @@ -354,9 +320,6 @@ static void input_event_dispose(struct input_dev *dev, int disposition, if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); - if (!dev->vals) - return; - if (disposition & INPUT_PASS_TO_HANDLERS) { struct input_value *v; @@ -2013,22 +1976,41 @@ struct input_dev *input_allocate_device(void) struct input_dev *dev; dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev) { - dev->dev.type = &input_dev_type; - dev->dev.class = &input_class; - device_initialize(&dev->dev); - mutex_init(&dev->mutex); - spin_lock_init(&dev->event_lock); - timer_setup(&dev->timer, NULL, 0); - INIT_LIST_HEAD(&dev->h_list); - INIT_LIST_HEAD(&dev->node); + if (!dev) + return NULL; - dev_set_name(&dev->dev, "input%lu", - (unsigned long)atomic_inc_return(&input_no)); - - __module_get(THIS_MODULE); + /* + * Start with space for SYN_REPORT + 7 EV_KEY/EV_MSC events + 2 spare, + * see input_estimate_events_per_packet(). We will tune the number + * when we register the device. + */ + dev->max_vals = 10; + dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); + if (!dev->vals) { + kfree(dev); + return NULL; } + mutex_init(&dev->mutex); + spin_lock_init(&dev->event_lock); + timer_setup(&dev->timer, NULL, 0); + INIT_LIST_HEAD(&dev->h_list); + INIT_LIST_HEAD(&dev->node); + + dev->dev.type = &input_dev_type; + dev->dev.class = &input_class; + device_initialize(&dev->dev); + /* + * From this point on we can no longer simply "kfree(dev)", we need + * to use input_free_device() so that device core properly frees its + * resources associated with the input device. + */ + + dev_set_name(&dev->dev, "input%lu", + (unsigned long)atomic_inc_return(&input_no)); + + __module_get(THIS_MODULE); + return dev; } EXPORT_SYMBOL(input_allocate_device); @@ -2368,6 +2350,35 @@ bool input_device_enabled(struct input_dev *dev) } EXPORT_SYMBOL_GPL(input_device_enabled); +static int input_device_tune_vals(struct input_dev *dev) +{ + struct input_value *vals; + unsigned int packet_size; + unsigned int max_vals; + + packet_size = input_estimate_events_per_packet(dev); + if (dev->hint_events_per_packet < packet_size) + dev->hint_events_per_packet = packet_size; + + max_vals = dev->hint_events_per_packet + 2; + if (dev->max_vals >= max_vals) + return 0; + + vals = kcalloc(max_vals, sizeof(*vals), GFP_KERNEL); + if (!vals) + return -ENOMEM; + + spin_lock_irq(&dev->event_lock); + dev->max_vals = max_vals; + swap(dev->vals, vals); + spin_unlock_irq(&dev->event_lock); + + /* Because of swap() above, this frees the old vals memory */ + kfree(vals); + + return 0; +} + /** * input_register_device - register device with input core * @dev: device to be registered @@ -2395,7 +2406,6 @@ int input_register_device(struct input_dev *dev) { struct input_devres *devres = NULL; struct input_handler *handler; - unsigned int packet_size; const char *path; int error; @@ -2423,16 +2433,9 @@ int input_register_device(struct input_dev *dev) /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); - packet_size = input_estimate_events_per_packet(dev); - if (dev->hint_events_per_packet < packet_size) - dev->hint_events_per_packet = packet_size; - - dev->max_vals = dev->hint_events_per_packet + 2; - dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); - if (!dev->vals) { - error = -ENOMEM; + error = input_device_tune_vals(dev); + if (error) goto err_devres_free; - } /* * If delay and period are pre-set by the driver, then autorepeating @@ -2452,7 +2455,7 @@ int input_register_device(struct input_dev *dev) error = device_add(&dev->dev); if (error) - goto err_free_vals; + goto err_devres_free; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %s\n", @@ -2482,9 +2485,6 @@ int input_register_device(struct input_dev *dev) err_device_del: device_del(&dev->dev); -err_free_vals: - kfree(dev->vals); - dev->vals = NULL; err_devres_free: devres_free(devres); return error; @@ -2517,6 +2517,77 @@ void input_unregister_device(struct input_dev *dev) } EXPORT_SYMBOL(input_unregister_device); +static int input_handler_check_methods(const struct input_handler *handler) +{ + int count = 0; + + if (handler->filter) + count++; + if (handler->events) + count++; + if (handler->event) + count++; + + if (count > 1) { + pr_err("%s: only one event processing method can be defined (%s)\n", + __func__, handler->name); + return -EINVAL; + } + + return 0; +} + +/* + * An implementation of input_handler's events() method that simply + * invokes handler->event() method for each event one by one. + */ +static unsigned int input_handler_events_default(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *v; + + for (v = vals; v != vals + count; v++) + handler->event(handle, v->type, v->code, v->value); + + return count; +} + +/* + * An implementation of input_handler's events() method that invokes + * handler->filter() method for each event one by one and removes events + * that were filtered out from the "vals" array. + */ +static unsigned int input_handler_events_filter(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *end = vals; + struct input_value *v; + + for (v = vals; v != vals + count; v++) { + if (handler->filter(handle, v->type, v->code, v->value)) + continue; + if (end != v) + *end = *v; + end++; + } + + return end - vals; +} + +/* + * An implementation of input_handler's events() method that does nothing. + */ +static unsigned int input_handler_events_null(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + return count; +} + /** * input_register_handler - register a new input handler * @handler: handler to be registered @@ -2530,12 +2601,23 @@ int input_register_handler(struct input_handler *handler) struct input_dev *dev; int error; - error = mutex_lock_interruptible(&input_mutex); + error = input_handler_check_methods(handler); if (error) return error; INIT_LIST_HEAD(&handler->h_list); + if (handler->filter) + handler->events = input_handler_events_filter; + else if (handler->event) + handler->events = input_handler_events_default; + else if (!handler->events) + handler->events = input_handler_events_null; + + error = mutex_lock_interruptible(&input_mutex); + if (error) + return error; + list_add_tail(&handler->node, &input_handler_list); list_for_each_entry(dev, &input_dev_list, node) diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index fd1827baf27c..15182f16ed19 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -249,7 +249,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) int i; int err; - a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL); + a3d = kzalloc(sizeof(*a3d), GFP_KERNEL); input_dev = input_allocate_device(); if (!a3d || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c index c0deff5d4282..5f46a7104b52 100644 --- a/drivers/input/joystick/adc-joystick.c +++ b/drivers/input/joystick/adc-joystick.c @@ -15,20 +15,26 @@ struct adc_joystick_axis { u32 code; - s32 range[2]; - s32 fuzz; - s32 flat; + bool inverted; }; struct adc_joystick { struct input_dev *input; struct iio_cb_buffer *buffer; - struct adc_joystick_axis *axes; struct iio_channel *chans; - int num_chans; - bool polled; + unsigned int num_chans; + struct adc_joystick_axis axes[] __counted_by(num_chans); }; +static int adc_joystick_invert(struct input_dev *dev, + unsigned int axis, int val) +{ + int min = input_abs_get_min(dev, axis); + int max = input_abs_get_max(dev, axis); + + return (max + min) - val; +} + static void adc_joystick_poll(struct input_dev *input) { struct adc_joystick *joy = input_get_drvdata(input); @@ -38,6 +44,8 @@ static void adc_joystick_poll(struct input_dev *input) ret = iio_read_channel_raw(&joy->chans[i], &val); if (ret < 0) return; + if (joy->axes[i].inverted) + val = adc_joystick_invert(input, i, val); input_report_abs(input, joy->axes[i].code, val); } input_sync(input); @@ -86,6 +94,8 @@ static int adc_joystick_handle(const void *data, void *private) val = sign_extend32(val, msb); else val &= GENMASK(msb, 0); + if (joy->axes[i].inverted) + val = adc_joystick_invert(joy->input, i, val); input_report_abs(joy->input, joy->axes[i].code, val); } @@ -121,9 +131,11 @@ static void adc_joystick_cleanup(void *data) static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy) { - struct adc_joystick_axis *axes; + struct adc_joystick_axis *axes = joy->axes; struct fwnode_handle *child; - int num_axes, error, i; + s32 range[2], fuzz, flat; + unsigned int num_axes; + int error, i; num_axes = device_get_child_node_count(dev); if (!num_axes) { @@ -137,10 +149,6 @@ static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy) return -EINVAL; } - axes = devm_kmalloc_array(dev, num_axes, sizeof(*axes), GFP_KERNEL); - if (!axes) - return -ENOMEM; - device_for_each_child_node(dev, child) { error = fwnode_property_read_u32(child, "reg", &i); if (error) { @@ -162,23 +170,25 @@ static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy) } error = fwnode_property_read_u32_array(child, "abs-range", - axes[i].range, 2); + range, 2); if (error) { dev_err(dev, "abs-range invalid or missing\n"); goto err_fwnode_put; } - fwnode_property_read_u32(child, "abs-fuzz", &axes[i].fuzz); - fwnode_property_read_u32(child, "abs-flat", &axes[i].flat); + if (range[0] > range[1]) { + dev_dbg(dev, "abs-axis %d inverted\n", i); + axes[i].inverted = true; + swap(range[0], range[1]); + } + + fwnode_property_read_u32(child, "abs-fuzz", &fuzz); + fwnode_property_read_u32(child, "abs-flat", &flat); input_set_abs_params(joy->input, axes[i].code, - axes[i].range[0], axes[i].range[1], - axes[i].fuzz, axes[i].flat); - input_set_capability(joy->input, EV_ABS, axes[i].code); + range[0], range[1], fuzz, flat); } - joy->axes = axes; - return 0; err_fwnode_put: @@ -186,23 +196,50 @@ err_fwnode_put: return error; } + +static int adc_joystick_count_channels(struct device *dev, + const struct iio_channel *chans, + bool polled, + unsigned int *num_chans) +{ + int bits; + int i; + + /* + * Count how many channels we got. NULL terminated. + * Do not check the storage size if using polling. + */ + for (i = 0; chans[i].indio_dev; i++) { + if (polled) + continue; + bits = chans[i].channel->scan_type.storagebits; + if (!bits || bits > 16) { + dev_err(dev, "Unsupported channel storage size\n"); + return -EINVAL; + } + if (bits != chans[0].channel->scan_type.storagebits) { + dev_err(dev, "Channels must have equal storage size\n"); + return -EINVAL; + } + } + + *num_chans = i; + return 0; +} + static int adc_joystick_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct iio_channel *chans; struct adc_joystick *joy; struct input_dev *input; + unsigned int poll_interval = 0; + unsigned int num_chans; int error; - int bits; - int i; - unsigned int poll_interval; - joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL); - if (!joy) - return -ENOMEM; - - joy->chans = devm_iio_channel_get_all(dev); - if (IS_ERR(joy->chans)) { - error = PTR_ERR(joy->chans); + chans = devm_iio_channel_get_all(dev); + error = PTR_ERR_OR_ZERO(chans); + if (error) { if (error != -EPROBE_DEFER) dev_err(dev, "Unable to get IIO channels"); return error; @@ -216,28 +253,19 @@ static int adc_joystick_probe(struct platform_device *pdev) } else if (poll_interval == 0) { dev_err(dev, "Unable to get poll-interval\n"); return -EINVAL; - } else { - joy->polled = true; } - /* - * Count how many channels we got. NULL terminated. - * Do not check the storage size if using polling. - */ - for (i = 0; joy->chans[i].indio_dev; i++) { - if (joy->polled) - continue; - bits = joy->chans[i].channel->scan_type.storagebits; - if (!bits || bits > 16) { - dev_err(dev, "Unsupported channel storage size\n"); - return -EINVAL; - } - if (bits != joy->chans[0].channel->scan_type.storagebits) { - dev_err(dev, "Channels must have equal storage size\n"); - return -EINVAL; - } - } - joy->num_chans = i; + error = adc_joystick_count_channels(dev, chans, poll_interval != 0, + &num_chans); + if (error) + return error; + + joy = devm_kzalloc(dev, struct_size(joy, axes, num_chans), GFP_KERNEL); + if (!joy) + return -ENOMEM; + + joy->chans = chans; + joy->num_chans = num_chans; input = devm_input_allocate_device(dev); if (!input) { @@ -253,7 +281,7 @@ static int adc_joystick_probe(struct platform_device *pdev) if (error) return error; - if (joy->polled) { + if (poll_interval != 0) { input_setup_polling(input, adc_joystick_poll); input_set_poll_interval(input, poll_interval); } else { diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index f1a720be458b..963250de24b7 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -456,7 +456,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) int i; int err; - port = kzalloc(sizeof(struct adi_port), GFP_KERNEL); + port = kzalloc(sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 0c9e172a9818..c709b58d770a 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -582,7 +582,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv int i; int err; - if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL))) + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) return -ENOMEM; err = analog_init_port(gameport, drv, port); diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index 407062bcc84b..49a0dfbbeb49 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -237,7 +237,7 @@ static int as5011_probe(struct i2c_client *client) return -ENODEV; } - as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL); + as5011 = kmalloc(sizeof(*as5011), GFP_KERNEL); input_dev = input_allocate_device(); if (!as5011 || !input_dev) { dev_err(&client->dev, diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 7ff78c9388bd..5a0ea3ad5efa 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -141,7 +141,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) int i, j; int err; - cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL); + cobra = kzalloc(sizeof(*cobra), GFP_KERNEL); if (!cobra) return -ENOMEM; diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 4fba28b1a1e7..6373d7aa739a 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -587,7 +587,7 @@ static void db9_attach(struct parport *pp) return; } - db9 = kzalloc(sizeof(struct db9), GFP_KERNEL); + db9 = kzalloc(sizeof(*db9), GFP_KERNEL); if (!db9) goto err_unreg_pardev; @@ -673,7 +673,6 @@ static struct parport_driver db9_parport_driver = { .name = "db9", .match_port = db9_attach, .detach = db9_detach, - .devmodel = true, }; static int __init db9_init(void) diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 41d5dac05448..2b553e2d838f 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -950,7 +950,7 @@ static void gc_attach(struct parport *pp) return; } - gc = kzalloc(sizeof(struct gc), GFP_KERNEL); + gc = kzalloc(sizeof(*gc), GFP_KERNEL); if (!gc) { pr_err("Not enough memory\n"); goto err_unreg_pardev; @@ -1016,7 +1016,6 @@ static struct parport_driver gc_parport_driver = { .name = "gamecon", .match_port = gc_attach, .detach = gc_detach, - .devmodel = true, }; static int __init gc_init(void) diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index abefbd1484df..e7ff7bdb1a3a 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -222,7 +222,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) unsigned char data[GF2K_LENGTH]; int i, err; - gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL); + gf2k = kzalloc(sizeof(*gf2k), GFP_KERNEL); input_dev = input_allocate_device(); if (!gf2k || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 0e86b269a90e..f339ce2b7a33 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -284,7 +284,8 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) int i, j, t; int err; - if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL))) + grip = kzalloc(sizeof(*grip), GFP_KERNEL); + if (!grip) return -ENOMEM; grip->gameport = gameport; diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 056a89ac2bdf..5eadb5a3ca37 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -632,7 +632,8 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) struct grip_mp *grip; int err; - if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL))) + grip = kzalloc(sizeof(*grip), GFP_KERNEL); + if (!grip) return -ENOMEM; grip->gameport = gameport; diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 205eb6f8b84d..1c5a76f72239 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -163,7 +163,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * int i, t; int err; - guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL); + guillemot = kzalloc(sizeof(*guillemot), GFP_KERNEL); input_dev = input_allocate_device(); if (!guillemot || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 03a9f0829f7e..262f022e5695 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -192,7 +192,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d int i, t; int err; - interact = kzalloc(sizeof(struct interact), GFP_KERNEL); + interact = kzalloc(sizeof(*interact), GFP_KERNEL); input_dev = input_allocate_device(); if (!interact || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index 017ef8c6170b..2eaa25c9c68c 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -132,7 +132,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL); + magellan = kzalloc(sizeof(*magellan), GFP_KERNEL); input_dev = input_allocate_device(); if (!magellan || !input_dev) goto fail1; diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c index 3833ac47b2b8..8b54f9b18e7c 100644 --- a/drivers/input/joystick/maplecontrol.c +++ b/drivers/input/joystick/maplecontrol.c @@ -102,7 +102,7 @@ static int probe_maple_controller(struct device *dev) struct input_dev *idev; unsigned long data = be32_to_cpu(mdev->devinfo.function_data[0]); - pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); + pad = kzalloc(sizeof(*pad), GFP_KERNEL); idev = input_allocate_device(); if (!pad || !idev) { error = -ENOMEM; diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c index 9dbca366613e..b0986d2195d6 100644 --- a/drivers/input/joystick/n64joy.c +++ b/drivers/input/joystick/n64joy.c @@ -246,7 +246,7 @@ static int __init n64joy_probe(struct platform_device *pdev) int err = 0; u32 i, j, found = 0; - priv = kzalloc(sizeof(struct n64joy_priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; mutex_init(&priv->n64joy_mutex); diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 7282301c3ae7..f6e92db4d789 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -577,7 +577,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) comment[0] = 0; - sw = kzalloc(sizeof(struct sw), GFP_KERNEL); + sw = kzalloc(sizeof(*sw), GFP_KERNEL); buf = kmalloc(SW_LENGTH, GFP_KERNEL); idbuf = kmalloc(SW_LENGTH, GFP_KERNEL); if (!sw || !buf || !idbuf) { diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index fa8ec533cd69..49101f1c858b 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -199,7 +199,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) if ((id = serio->id.id) > SPACEBALL_MAX_ID) return -ENODEV; - spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL); + spaceball = kmalloc(sizeof(*spaceball), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceball || !input_dev) goto fail1; diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index dbbc69f17c89..7250d74d62a1 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -147,7 +147,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL); + spaceorb = kzalloc(sizeof(*spaceorb), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceorb || !input_dev) goto fail1; diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index 530de468cb61..1b24ea21aa30 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -118,7 +118,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL); + stinger = kmalloc(sizeof(*stinger), GFP_KERNEL); input_dev = input_allocate_device(); if (!stinger || !input_dev) goto fail1; diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 93562ecc0ca1..514b1026e379 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -348,7 +348,8 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv) int i; int err; - if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL))) + tmdc = kzalloc(sizeof(*tmdc), GFP_KERNEL); + if (!tmdc) return -ENOMEM; tmdc->gameport = gameport; diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index dfb9c684651f..0a78dda3e0ea 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -172,7 +172,7 @@ static void tgfx_attach(struct parport *pp) return; } - tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL); + tgfx = kzalloc(sizeof(*tgfx), GFP_KERNEL); if (!tgfx) { printk(KERN_ERR "turbografx.c: Not enough memory\n"); goto err_unreg_pardev; @@ -274,7 +274,6 @@ static struct parport_driver tgfx_parport_driver = { .name = "turbografx", .match_port = tgfx_attach, .detach = tgfx_detach, - .devmodel = true, }; static int __init tgfx_init(void) diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 9b6792ac27f1..ab99d76e5d8d 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -171,7 +171,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL); + twidjoy = kzalloc(sizeof(*twidjoy), GFP_KERNEL); input_dev = input_allocate_device(); if (!twidjoy || !input_dev) goto fail1; diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 27d95d6cf56e..59eea813f258 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -293,7 +293,6 @@ static struct parport_driver walkera0701_parport_driver = { .name = "walkera0701", .match_port = walkera0701_attach, .detach = walkera0701_detach, - .devmodel = true, }; module_parport_driver(walkera0701_parport_driver); diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index f66bddf145c2..ebeab441e9ec 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -124,7 +124,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL); + warrior = kzalloc(sizeof(*warrior), GFP_KERNEL); input_dev = input_allocate_device(); if (!warrior || !input_dev) goto fail1; diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 2b8370ecf42a..4eda18f4f46e 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -1687,7 +1687,7 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) return 0; - xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); + xpad->led = led = kzalloc(sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; @@ -2023,7 +2023,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id break; } - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); + xpad = kzalloc(sizeof(*xpad), GFP_KERNEL); if (!xpad) return -ENOMEM; diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c index 3f2460e2b095..cc0e2a77ac5e 100644 --- a/drivers/input/joystick/zhenhua.c +++ b/drivers/input/joystick/zhenhua.c @@ -131,7 +131,7 @@ static int zhenhua_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL); + zhenhua = kzalloc(sizeof(*zhenhua), GFP_KERNEL); input_dev = input_allocate_device(); if (!zhenhua || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 7f67f9f2946b..f4f2078cf501 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -1279,7 +1279,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *dev; int err = -ENOMEM; - atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL); + atkbd = kzalloc(sizeof(*atkbd), GFP_KERNEL); dev = input_allocate_device(); if (!atkbd || !dev) goto fail1; diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 52fba9ee7c1d..b21ef9d6ff9d 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -86,7 +86,6 @@ struct cap11xx_priv { struct device *dev; struct input_dev *idev; const struct cap11xx_hw_model *model; - u8 id; struct cap11xx_led *leds; int num_leds; @@ -104,27 +103,10 @@ struct cap11xx_hw_model { u8 product_id; unsigned int num_channels; unsigned int num_leds; - bool no_gain; -}; - -enum { - CAP1106, - CAP1126, - CAP1188, - CAP1203, - CAP1206, - CAP1293, - CAP1298 -}; - -static const struct cap11xx_hw_model cap11xx_devices[] = { - [CAP1106] = { .product_id = 0x55, .num_channels = 6, .num_leds = 0, .no_gain = false }, - [CAP1126] = { .product_id = 0x53, .num_channels = 6, .num_leds = 2, .no_gain = false }, - [CAP1188] = { .product_id = 0x50, .num_channels = 8, .num_leds = 8, .no_gain = false }, - [CAP1203] = { .product_id = 0x6d, .num_channels = 3, .num_leds = 0, .no_gain = true }, - [CAP1206] = { .product_id = 0x67, .num_channels = 6, .num_leds = 0, .no_gain = true }, - [CAP1293] = { .product_id = 0x6f, .num_channels = 3, .num_leds = 0, .no_gain = false }, - [CAP1298] = { .product_id = 0x71, .num_channels = 8, .num_leds = 0, .no_gain = false }, + bool has_gain; + bool has_irq_config; + bool has_sensitivity_control; + bool has_signal_guard; }; static const struct reg_default cap11xx_reg_defaults[] = { @@ -224,7 +206,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) } if (!of_property_read_u32(node, "microchip,sensor-gain", &u32_val)) { - if (priv->model->no_gain) { + if (!priv->model->has_gain) { dev_warn(dev, "This model doesn't support 'sensor-gain'\n"); } else if (is_power_of_2(u32_val) && u32_val <= 8) { @@ -243,9 +225,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) } if (of_property_read_bool(node, "microchip,irq-active-high")) { - if (priv->id == CAP1106 || - priv->id == CAP1126 || - priv->id == CAP1188) { + if (priv->model->has_irq_config) { error = regmap_update_bits(priv->regmap, CAP11XX_REG_CONFIG2, CAP11XX_REG_CONFIG2_ALT_POL, @@ -296,7 +276,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) if (!of_property_read_u32_array(node, "microchip,calib-sensitivity", priv->calib_sensitivities, priv->model->num_channels)) { - if (priv->id == CAP1293 || priv->id == CAP1298) { + if (priv->model->has_sensitivity_control) { for (i = 0; i < priv->model->num_channels; i++) { if (!is_power_of_2(priv->calib_sensitivities[i]) || priv->calib_sensitivities[i] > 4) { @@ -311,7 +291,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) if (error) return error; - if (priv->id == CAP1298) { + if (priv->model->num_channels > 4) { error = cap11xx_write_calib_sens_config_2(priv); if (error) return error; @@ -333,7 +313,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) } if (priv->signal_guard_inputs_mask) { - if (priv->id == CAP1293 || priv->id == CAP1298) { + if (priv->model->has_signal_guard) { error = regmap_write(priv->regmap, CAP11XX_REG_SIGNAL_GUARD_ENABLE, priv->signal_guard_inputs_mask); @@ -508,20 +488,16 @@ static int cap11xx_init_leds(struct device *dev, static int cap11xx_i2c_probe(struct i2c_client *i2c_client) { - const struct i2c_device_id *id = i2c_client_get_device_id(i2c_client); + const struct i2c_device_id *id; + const struct cap11xx_hw_model *cap; struct device *dev = &i2c_client->dev; struct cap11xx_priv *priv; - const struct cap11xx_hw_model *cap; int i, error; unsigned int val, rev; - if (id->driver_data >= ARRAY_SIZE(cap11xx_devices)) { - dev_err(dev, "Invalid device ID %lu\n", id->driver_data); - return -EINVAL; - } - - cap = &cap11xx_devices[id->driver_data]; - if (!cap || !cap->num_channels) { + id = i2c_client_get_device_id(i2c_client); + cap = i2c_get_match_data(i2c_client); + if (!id || !cap || !cap->num_channels) { dev_err(dev, "Invalid device configuration\n"); return -EINVAL; } @@ -566,7 +542,6 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client) id->name, rev); priv->model = cap; - priv->id = id->driver_data; dev_info(dev, "CAP11XX device detected, model %s, revision 0x%02x\n", id->name, rev); @@ -627,27 +602,67 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client) return 0; } +static const struct cap11xx_hw_model cap1106_model = { + .product_id = 0x55, .num_channels = 6, .num_leds = 0, + .has_gain = true, + .has_irq_config = true, +}; + +static const struct cap11xx_hw_model cap1126_model = { + .product_id = 0x53, .num_channels = 6, .num_leds = 2, + .has_gain = true, + .has_irq_config = true, +}; + +static const struct cap11xx_hw_model cap1188_model = { + .product_id = 0x50, .num_channels = 8, .num_leds = 8, + .has_gain = true, + .has_irq_config = true, +}; + +static const struct cap11xx_hw_model cap1203_model = { + .product_id = 0x6d, .num_channels = 3, .num_leds = 0, +}; + +static const struct cap11xx_hw_model cap1206_model = { + .product_id = 0x67, .num_channels = 6, .num_leds = 0, +}; + +static const struct cap11xx_hw_model cap1293_model = { + .product_id = 0x6f, .num_channels = 3, .num_leds = 0, + .has_gain = true, + .has_sensitivity_control = true, + .has_signal_guard = true, +}; + +static const struct cap11xx_hw_model cap1298_model = { + .product_id = 0x71, .num_channels = 8, .num_leds = 0, + .has_gain = true, + .has_sensitivity_control = true, + .has_signal_guard = true, +}; + static const struct of_device_id cap11xx_dt_ids[] = { - { .compatible = "microchip,cap1106", }, - { .compatible = "microchip,cap1126", }, - { .compatible = "microchip,cap1188", }, - { .compatible = "microchip,cap1203", }, - { .compatible = "microchip,cap1206", }, - { .compatible = "microchip,cap1293", }, - { .compatible = "microchip,cap1298", }, - {} + { .compatible = "microchip,cap1106", .data = &cap1106_model }, + { .compatible = "microchip,cap1126", .data = &cap1126_model }, + { .compatible = "microchip,cap1188", .data = &cap1188_model }, + { .compatible = "microchip,cap1203", .data = &cap1203_model }, + { .compatible = "microchip,cap1206", .data = &cap1206_model }, + { .compatible = "microchip,cap1293", .data = &cap1293_model }, + { .compatible = "microchip,cap1298", .data = &cap1298_model }, + { } }; MODULE_DEVICE_TABLE(of, cap11xx_dt_ids); static const struct i2c_device_id cap11xx_i2c_ids[] = { - { "cap1106", CAP1106 }, - { "cap1126", CAP1126 }, - { "cap1188", CAP1188 }, - { "cap1203", CAP1203 }, - { "cap1206", CAP1206 }, - { "cap1293", CAP1293 }, - { "cap1298", CAP1298 }, - {} + { "cap1106", (kernel_ulong_t)&cap1106_model }, + { "cap1126", (kernel_ulong_t)&cap1126_model }, + { "cap1188", (kernel_ulong_t)&cap1188_model }, + { "cap1203", (kernel_ulong_t)&cap1203_model }, + { "cap1206", (kernel_ulong_t)&cap1206_model }, + { "cap1293", (kernel_ulong_t)&cap1293_model }, + { "cap1298", (kernel_ulong_t)&cap1298_model }, + { } }; MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids); diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 047b654b3752..c035216dd27c 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -608,7 +608,7 @@ static int lkkbd_connect(struct serio *serio, struct serio_driver *drv) int i; int err; - lk = kzalloc(sizeof(struct lkkbd), GFP_KERNEL); + lk = kzalloc(sizeof(*lk), GFP_KERNEL); input_dev = input_allocate_device(); if (!lk || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index f866c03b9d0e..4b0f8323c492 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -227,7 +227,7 @@ static int locomokbd_probe(struct locomo_dev *dev) struct input_dev *input_dev; int i, err; - locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL); + locomokbd = kzalloc(sizeof(*locomokbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!locomokbd || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index d08b565be24c..91a1d2958109 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c @@ -154,7 +154,7 @@ static int probe_maple_kbd(struct device *dev) mdev = to_maple_dev(dev); mdrv = to_maple_driver(dev->driver); - kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); + kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); if (!kbd) { error = -ENOMEM; goto fail; diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index df00a119aa9a..71e0a3f830dd 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -68,7 +68,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL); + nkbd = kzalloc(sizeof(*nkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!nkbd || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 16f936db7305..57587541110b 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -171,6 +171,12 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store); +static struct attribute *omap_kp_attrs[] = { + &dev_attr_enable.attr, + NULL +}; +ATTRIBUTE_GROUPS(omap_kp); + static int omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; @@ -214,10 +220,6 @@ static int omap_kp_probe(struct platform_device *pdev) kp_tasklet.data = (unsigned long) omap_kp; tasklet_enable(&kp_tasklet); - ret = device_create_file(&pdev->dev, &dev_attr_enable); - if (ret < 0) - goto err2; - /* setup input device */ input_dev->name = "omap-keypad"; input_dev->phys = "omap-keypad/input0"; @@ -235,12 +237,12 @@ static int omap_kp_probe(struct platform_device *pdev) pdata->rows, pdata->cols, omap_kp->keymap, input_dev); if (ret < 0) - goto err3; + goto err2; ret = input_register_device(omap_kp->input); if (ret < 0) { printk(KERN_ERR "Unable to register omap-keypad input device\n"); - goto err3; + goto err2; } if (pdata->dbounce) @@ -252,17 +254,15 @@ static int omap_kp_probe(struct platform_device *pdev) if (omap_kp->irq >= 0) { if (request_irq(omap_kp->irq, omap_kp_interrupt, 0, "omap-keypad", omap_kp) < 0) - goto err4; + goto err3; } omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); return 0; -err4: +err3: input_unregister_device(omap_kp->input); input_dev = NULL; -err3: - device_remove_file(&pdev->dev, &dev_attr_enable); err2: kfree(omap_kp); input_free_device(input_dev); @@ -293,6 +293,7 @@ static struct platform_driver omap_kp_driver = { .remove_new = omap_kp_remove, .driver = { .name = "omap-keypad", + .dev_groups = omap_kp_groups, }, }; module_platform_driver(omap_kp_driver); diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c index b51dfcd76038..5a2592e6293d 100644 --- a/drivers/input/keyboard/qt1050.c +++ b/drivers/input/keyboard/qt1050.c @@ -208,7 +208,7 @@ static const struct regmap_access_table qt1050_writeable_table = { .n_yes_ranges = ARRAY_SIZE(qt1050_writeable_ranges), }; -static struct regmap_config qt1050_regmap_config = { +static const struct regmap_config qt1050_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = QT1050_RES_CAL, @@ -226,7 +226,12 @@ static bool qt1050_identify(struct qt1050_priv *ts) int err; /* Read Chip ID */ - regmap_read(ts->regmap, QT1050_CHIP_ID, &val); + err = regmap_read(ts->regmap, QT1050_CHIP_ID, &val); + if (err) { + dev_err(&ts->client->dev, "Failed to read chip ID: %d\n", err); + return false; + } + if (val != QT1050_CHIP_ID_VER) { dev_err(&ts->client->dev, "ID %d not supported\n", val); return false; diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index 56e784936059..7ef0b3f4f549 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -72,7 +72,7 @@ static int skbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - skbd = kzalloc(sizeof(struct skbd), GFP_KERNEL); + skbd = kzalloc(sizeof(*skbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!skbd || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index b123a208ef36..72fb46029710 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -263,7 +263,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL); + sunkbd = kzalloc(sizeof(*sunkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!sunkbd || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index c9d7c2481726..befa713268ae 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -70,7 +70,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL); + xtkbd = kmalloc(sizeof(*xtkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!xtkbd || !input_dev) goto fail1; diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index 4fa53423f56c..5d93043bad8e 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c @@ -199,4 +199,5 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, } EXPORT_SYMBOL(matrix_keypad_build_keymap); +MODULE_DESCRIPTION("Helpers for matrix keyboard bindings"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c index 4b0685f96113..6477a41c4bac 100644 --- a/drivers/input/misc/88pm80x_onkey.c +++ b/drivers/input/misc/88pm80x_onkey.c @@ -57,7 +57,7 @@ static int pm80x_onkey_probe(struct platform_device *pdev) struct pm80x_onkey_info *info; int err; - info = kzalloc(sizeof(struct pm80x_onkey_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index d4014e367c77..c05d898898e8 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -98,13 +98,6 @@ static int adxl34x_i2c_probe(struct i2c_client *client) return 0; } -static void adxl34x_i2c_remove(struct i2c_client *client) -{ - struct adxl34x *ac = i2c_get_clientdata(client); - - adxl34x_remove(ac); -} - static const struct i2c_device_id adxl34x_id[] = { { "adxl34x" }, { } @@ -132,11 +125,11 @@ MODULE_DEVICE_TABLE(of, adxl34x_of_id); static struct i2c_driver adxl34x_driver = { .driver = { .name = "adxl34x", + .dev_groups = adxl34x_groups, .pm = pm_sleep_ptr(&adxl34x_pm), .of_match_table = adxl34x_of_id, }, .probe = adxl34x_i2c_probe, - .remove = adxl34x_i2c_remove, .id_table = adxl34x_id, }; diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index f1094a8ccdd5..fd716d861832 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -87,20 +87,13 @@ static int adxl34x_spi_probe(struct spi_device *spi) return 0; } -static void adxl34x_spi_remove(struct spi_device *spi) -{ - struct adxl34x *ac = spi_get_drvdata(spi); - - adxl34x_remove(ac); -} - static struct spi_driver adxl34x_driver = { .driver = { .name = "adxl34x", + .dev_groups = adxl34x_groups, .pm = pm_sleep_ptr(&adxl34x_pm), }, .probe = adxl34x_spi_probe, - .remove = adxl34x_spi_remove, }; module_spi_driver(adxl34x_driver); diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index a3f45e0ee0c7..7cafbf8d5f1a 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -241,7 +241,8 @@ static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) ac->bops->read_block(ac->dev, DATAX0, DATAZ1 - DATAX0 + 1, buf); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); + ac->saved.x = (s16) le16_to_cpu(buf[0]); axis->x = ac->saved.x; @@ -250,7 +251,6 @@ static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) ac->saved.z = (s16) le16_to_cpu(buf[2]); axis->z = ac->saved.z; - mutex_unlock(&ac->mutex); } static void adxl34x_service_ev_fifo(struct adxl34x *ac) @@ -416,15 +416,13 @@ static int adxl34x_suspend(struct device *dev) { struct adxl34x *ac = dev_get_drvdata(dev); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && !ac->disabled && ac->opened) __adxl34x_disable(ac); ac->suspended = true; - mutex_unlock(&ac->mutex); - return 0; } @@ -432,15 +430,13 @@ static int adxl34x_resume(struct device *dev) { struct adxl34x *ac = dev_get_drvdata(dev); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (ac->suspended && !ac->disabled && ac->opened) __adxl34x_enable(ac); ac->suspended = false; - mutex_unlock(&ac->mutex); - return 0; } @@ -464,7 +460,7 @@ static ssize_t adxl34x_disable_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && ac->opened) { if (val) { @@ -478,8 +474,6 @@ static ssize_t adxl34x_disable_store(struct device *dev, ac->disabled = !!val; - mutex_unlock(&ac->mutex); - return count; } @@ -489,16 +483,13 @@ static ssize_t adxl34x_calibrate_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adxl34x *ac = dev_get_drvdata(dev); - ssize_t count; - mutex_lock(&ac->mutex); - count = sprintf(buf, "%d,%d,%d\n", - ac->hwcal.x * 4 + ac->swcal.x, - ac->hwcal.y * 4 + ac->swcal.y, - ac->hwcal.z * 4 + ac->swcal.z); - mutex_unlock(&ac->mutex); + guard(mutex)(&ac->mutex); - return count; + return sprintf(buf, "%d,%d,%d\n", + ac->hwcal.x * 4 + ac->swcal.x, + ac->hwcal.y * 4 + ac->swcal.y, + ac->hwcal.z * 4 + ac->swcal.z); } static ssize_t adxl34x_calibrate_store(struct device *dev, @@ -512,7 +503,8 @@ static ssize_t adxl34x_calibrate_store(struct device *dev, * We use HW calibration and handle the remaining bits in SW. (4mg/LSB) */ - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); + ac->hwcal.x -= (ac->saved.x / 4); ac->swcal.x = ac->saved.x % 4; @@ -525,7 +517,6 @@ static ssize_t adxl34x_calibrate_store(struct device *dev, AC_WRITE(ac, OFSX, (s8) ac->hwcal.x); AC_WRITE(ac, OFSY, (s8) ac->hwcal.y); AC_WRITE(ac, OFSZ, (s8) ac->hwcal.z); - mutex_unlock(&ac->mutex); return count; } @@ -553,15 +544,13 @@ static ssize_t adxl34x_rate_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); ac->pdata.data_rate = RATE(val); AC_WRITE(ac, BW_RATE, ac->pdata.data_rate | (ac->pdata.low_power_mode ? LOW_POWER : 0)); - mutex_unlock(&ac->mutex); - return count; } @@ -588,7 +577,7 @@ static ssize_t adxl34x_autosleep_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (val) ac->pdata.power_mode |= (PCTL_AUTO_SLEEP | PCTL_LINK); @@ -598,8 +587,6 @@ static ssize_t adxl34x_autosleep_store(struct device *dev, if (!ac->disabled && !ac->suspended && ac->opened) AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); - mutex_unlock(&ac->mutex); - return count; } @@ -610,14 +597,11 @@ static ssize_t adxl34x_position_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adxl34x *ac = dev_get_drvdata(dev); - ssize_t count; - mutex_lock(&ac->mutex); - count = sprintf(buf, "(%d, %d, %d)\n", - ac->saved.x, ac->saved.y, ac->saved.z); - mutex_unlock(&ac->mutex); + guard(mutex)(&ac->mutex); - return count; + return sprintf(buf, "(%d, %d, %d)\n", + ac->saved.x, ac->saved.y, ac->saved.z); } static DEVICE_ATTR(position, S_IRUGO, adxl34x_position_show, NULL); @@ -638,9 +622,8 @@ static ssize_t adxl34x_write_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); AC_WRITE(ac, val >> 8, val & 0xFF); - mutex_unlock(&ac->mutex); return count; } @@ -664,19 +647,23 @@ static const struct attribute_group adxl34x_attr_group = { .attrs = adxl34x_attributes, }; +const struct attribute_group *adxl34x_groups[] = { + &adxl34x_attr_group, + NULL +}; +EXPORT_SYMBOL_GPL(adxl34x_groups); + static int adxl34x_input_open(struct input_dev *input) { struct adxl34x *ac = input_get_drvdata(input); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && !ac->disabled) __adxl34x_enable(ac); ac->opened = true; - mutex_unlock(&ac->mutex); - return 0; } @@ -684,14 +671,12 @@ static void adxl34x_input_close(struct input_dev *input) { struct adxl34x *ac = input_get_drvdata(input); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && !ac->disabled) __adxl34x_disable(ac); ac->opened = false; - - mutex_unlock(&ac->mutex); } struct adxl34x *adxl34x_probe(struct device *dev, int irq, @@ -701,21 +686,21 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, struct adxl34x *ac; struct input_dev *input_dev; const struct adxl34x_platform_data *pdata; - int err, range, i; + int error, range, i; int revid; if (!irq) { dev_err(dev, "no IRQ?\n"); - err = -ENODEV; - goto err_out; + return ERR_PTR(-ENODEV); } - ac = kzalloc(sizeof(*ac), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ac || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } + ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); + if (!ac) + return ERR_PTR(-ENOMEM); + + input_dev = devm_input_allocate_device(dev); + if (!input_dev) + return ERR_PTR(-ENOMEM); ac->fifo_delay = fifo_delay_default; @@ -748,14 +733,12 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, break; default: dev_err(dev, "Failed to probe %s\n", input_dev->name); - err = -ENODEV; - goto err_free_mem; + return ERR_PTR(-ENODEV); } snprintf(ac->phys, sizeof(ac->phys), "%s/input0", dev_name(dev)); input_dev->phys = ac->phys; - input_dev->dev.parent = dev; input_dev->id.product = ac->model; input_dev->id.bustype = bops->bustype; input_dev->open = adxl34x_input_open; @@ -763,18 +746,12 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, input_set_drvdata(input_dev, ac); - __set_bit(ac->pdata.ev_type, input_dev->evbit); - if (ac->pdata.ev_type == EV_REL) { - __set_bit(REL_X, input_dev->relbit); - __set_bit(REL_Y, input_dev->relbit); - __set_bit(REL_Z, input_dev->relbit); + input_set_capability(input_dev, EV_REL, REL_X); + input_set_capability(input_dev, EV_REL, REL_Y); + input_set_capability(input_dev, EV_REL, REL_Z); } else { /* EV_ABS */ - __set_bit(ABS_X, input_dev->absbit); - __set_bit(ABS_Y, input_dev->absbit); - __set_bit(ABS_Z, input_dev->absbit); - if (pdata->data_range & FULL_RES) range = ADXL_FULLRES_MAX_VAL; /* Signed 13-bit */ else @@ -785,18 +762,18 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, input_set_abs_params(input_dev, ABS_Z, -range, range, 3, 3); } - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(pdata->ev_code_tap[ADXL_X_AXIS], input_dev->keybit); - __set_bit(pdata->ev_code_tap[ADXL_Y_AXIS], input_dev->keybit); - __set_bit(pdata->ev_code_tap[ADXL_Z_AXIS], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_tap[ADXL_X_AXIS]); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_tap[ADXL_Y_AXIS]); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_tap[ADXL_Z_AXIS]); if (pdata->ev_code_ff) { ac->int_mask = FREE_FALL; - __set_bit(pdata->ev_code_ff, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_ff); } if (pdata->ev_code_act_inactivity) - __set_bit(pdata->ev_code_act_inactivity, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + pdata->ev_code_act_inactivity); ac->int_mask |= ACTIVITY | INACTIVITY; @@ -816,20 +793,16 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, AC_WRITE(ac, POWER_CTL, 0); - err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, - IRQF_ONESHOT, dev_name(dev), ac); - if (err) { + error = devm_request_threaded_irq(dev, ac->irq, NULL, adxl34x_irq, + IRQF_ONESHOT, dev_name(dev), ac); + if (error) { dev_err(dev, "irq %d busy?\n", ac->irq); - goto err_free_mem; + return ERR_PTR(error); } - err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group); - if (err) - goto err_free_irq; - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr; + error = input_register_device(input_dev); + if (error) + return ERR_PTR(error); AC_WRITE(ac, OFSX, pdata->x_axis_offset); ac->hwcal.x = pdata->x_axis_offset; @@ -872,13 +845,13 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++) - __set_bit(pdata->ev_codes_orient_3d[i], - input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + pdata->ev_codes_orient_3d[i]); if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++) - __set_bit(pdata->ev_codes_orient_2d[i], - input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + pdata->ev_codes_orient_2d[i]); } else { ac->pdata.orientation_enable = 0; } @@ -888,29 +861,9 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ac->pdata.power_mode &= (PCTL_AUTO_SLEEP | PCTL_LINK); return ac; - - err_remove_attr: - sysfs_remove_group(&dev->kobj, &adxl34x_attr_group); - err_free_irq: - free_irq(ac->irq, ac); - err_free_mem: - input_free_device(input_dev); - kfree(ac); - err_out: - return ERR_PTR(err); } EXPORT_SYMBOL_GPL(adxl34x_probe); -void adxl34x_remove(struct adxl34x *ac) -{ - sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group); - free_irq(ac->irq, ac); - input_unregister_device(ac->input); - dev_dbg(ac->dev, "unregistered accelerometer\n"); - kfree(ac); -} -EXPORT_SYMBOL_GPL(adxl34x_remove); - EXPORT_GPL_SIMPLE_DEV_PM_OPS(adxl34x_pm, adxl34x_suspend, adxl34x_resume); MODULE_AUTHOR("Michael Hennerich "); diff --git a/drivers/input/misc/adxl34x.h b/drivers/input/misc/adxl34x.h index f9272a2e7a96..718e90c2046d 100644 --- a/drivers/input/misc/adxl34x.h +++ b/drivers/input/misc/adxl34x.h @@ -23,8 +23,8 @@ struct adxl34x_bus_ops { struct adxl34x *adxl34x_probe(struct device *dev, int irq, bool fifo_delay_default, const struct adxl34x_bus_ops *bops); -void adxl34x_remove(struct adxl34x *ac); extern const struct dev_pm_ops adxl34x_pm; +extern const struct attribute_group *adxl34x_groups[]; #endif diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 946bf75aa106..795f69edb4b2 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -204,26 +204,7 @@ struct ati_remote2 { unsigned int mode_mask; }; -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote2_disconnect(struct usb_interface *interface); -static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); -static int ati_remote2_resume(struct usb_interface *interface); -static int ati_remote2_reset_resume(struct usb_interface *interface); -static int ati_remote2_pre_reset(struct usb_interface *interface); -static int ati_remote2_post_reset(struct usb_interface *interface); - -static struct usb_driver ati_remote2_driver = { - .name = "ati_remote2", - .probe = ati_remote2_probe, - .disconnect = ati_remote2_disconnect, - .id_table = ati_remote2_id_table, - .suspend = ati_remote2_suspend, - .resume = ati_remote2_resume, - .reset_resume = ati_remote2_reset_resume, - .pre_reset = ati_remote2_pre_reset, - .post_reset = ati_remote2_post_reset, - .supports_autosuspend = 1, -}; +static struct usb_driver ati_remote2_driver; static int ati_remote2_submit_urbs(struct ati_remote2 *ar2) { @@ -791,10 +772,7 @@ static struct attribute *ati_remote2_attrs[] = { &dev_attr_mode_mask.attr, NULL, }; - -static struct attribute_group ati_remote2_attr_group = { - .attrs = ati_remote2_attrs, -}; +ATTRIBUTE_GROUPS(ati_remote2); static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -861,13 +839,9 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); - r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); - if (r) - goto fail3; - r = ati_remote2_input_init(ar2); if (r) - goto fail4; + goto fail3; usb_set_intfdata(interface, ar2); @@ -875,8 +849,6 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d return 0; - fail4: - sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); fail3: ati_remote2_urb_cleanup(ar2); fail2: @@ -900,8 +872,6 @@ static void ati_remote2_disconnect(struct usb_interface *interface) input_unregister_device(ar2->idev); - sysfs_remove_group(&ar2->udev->dev.kobj, &ati_remote2_attr_group); - ati_remote2_urb_cleanup(ar2); usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); @@ -1032,4 +1002,18 @@ static int ati_remote2_post_reset(struct usb_interface *interface) return r; } +static struct usb_driver ati_remote2_driver = { + .name = "ati_remote2", + .probe = ati_remote2_probe, + .disconnect = ati_remote2_disconnect, + .dev_groups = ati_remote2_groups, + .id_table = ati_remote2_id_table, + .suspend = ati_remote2_suspend, + .resume = ati_remote2_resume, + .reset_resume = ati_remote2_reset_resume, + .pre_reset = ati_remote2_pre_reset, + .post_reset = ati_remote2_post_reset, + .supports_autosuspend = 1, +}; + module_usb_driver(ati_remote2_driver); diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index 1772846708d2..0c68e924a1cc 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -292,7 +292,7 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, goto err_out; } - data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); input_dev = input_allocate_device(); if (!data || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 80d16c92a08b..c086dadb45e3 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -207,8 +207,7 @@ static int ims_pcu_setup_buttons(struct ims_pcu *pcu, input = input_allocate_device(); if (!input) { - dev_err(pcu->dev, - "Not enough memory for input input device\n"); + dev_err(pcu->dev, "Not enough memory for input device\n"); return -ENOMEM; } @@ -287,7 +286,7 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu) struct input_dev *input; int error; - gamepad = kzalloc(sizeof(struct ims_pcu_gamepad), GFP_KERNEL); + gamepad = kzalloc(sizeof(*gamepad), GFP_KERNEL); input = input_allocate_device(); if (!gamepad || !input) { dev_err(pcu->dev, @@ -761,7 +760,7 @@ static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu) struct ims_pcu_flash_fmt { __le32 addr; u8 len; - u8 data[]; + u8 data[] __counted_by(len); }; static unsigned int ims_pcu_count_fw_records(const struct firmware *fw) @@ -928,9 +927,8 @@ static void ims_pcu_process_async_firmware(const struct firmware *fw, goto out; } - mutex_lock(&pcu->cmd_mutex); - ims_pcu_handle_firmware_update(pcu, fw); - mutex_unlock(&pcu->cmd_mutex); + scoped_guard(mutex, &pcu->cmd_mutex) + ims_pcu_handle_firmware_update(pcu, fw); release_firmware(fw); @@ -954,7 +952,7 @@ static int ims_pcu_backlight_set_brightness(struct led_classdev *cdev, __le16 br_val = cpu_to_le16(value); int error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); error = ims_pcu_execute_command(pcu, SET_BRIGHTNESS, &br_val, sizeof(br_val)); @@ -963,8 +961,6 @@ static int ims_pcu_backlight_set_brightness(struct led_classdev *cdev, "Failed to set desired brightness %u, error: %d\n", value, error); - mutex_unlock(&pcu->cmd_mutex); - return error; } @@ -978,7 +974,7 @@ ims_pcu_backlight_get_brightness(struct led_classdev *cdev) int brightness; int error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); error = ims_pcu_execute_query(pcu, GET_BRIGHTNESS); if (error) { @@ -992,8 +988,6 @@ ims_pcu_backlight_get_brightness(struct led_classdev *cdev) get_unaligned_le16(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET]); } - mutex_unlock(&pcu->cmd_mutex); - return brightness; } @@ -1073,24 +1067,23 @@ static ssize_t ims_pcu_attribute_store(struct device *dev, if (data_len > attr->field_length) return -EINVAL; - error = mutex_lock_interruptible(&pcu->cmd_mutex); - if (error) - return error; + scoped_cond_guard(mutex, return -EINTR, &pcu->cmd_mutex) { + memset(field, 0, attr->field_length); + memcpy(field, buf, data_len); - memset(field, 0, attr->field_length); - memcpy(field, buf, data_len); + error = ims_pcu_set_info(pcu); - error = ims_pcu_set_info(pcu); + /* + * Even if update failed, let's fetch the info again as we just + * clobbered one of the fields. + */ + ims_pcu_get_info(pcu); - /* - * Even if update failed, let's fetch the info again as we just - * clobbered one of the fields. - */ - ims_pcu_get_info(pcu); + if (error) + return error; + } - mutex_unlock(&pcu->cmd_mutex); - - return error < 0 ? error : count; + return count; } #define IMS_PCU_ATTR(_field, _mode) \ @@ -1153,7 +1146,6 @@ static ssize_t ims_pcu_update_firmware_store(struct device *dev, { struct usb_interface *intf = to_usb_interface(dev); struct ims_pcu *pcu = usb_get_intfdata(intf); - const struct firmware *fw = NULL; int value; int error; @@ -1164,35 +1156,33 @@ static ssize_t ims_pcu_update_firmware_store(struct device *dev, if (value != 1) return -EINVAL; - error = mutex_lock_interruptible(&pcu->cmd_mutex); - if (error) - return error; - + const struct firmware *fw __free(firmware) = NULL; error = request_ihex_firmware(&fw, IMS_PCU_FIRMWARE_NAME, pcu->dev); if (error) { dev_err(pcu->dev, "Failed to request firmware %s, error: %d\n", IMS_PCU_FIRMWARE_NAME, error); - goto out; + return error; } - /* - * If we are already in bootloader mode we can proceed with - * flashing the firmware. - * - * If we are in application mode, then we need to switch into - * bootloader mode, which will cause the device to disconnect - * and reconnect as different device. - */ - if (pcu->bootloader_mode) - error = ims_pcu_handle_firmware_update(pcu, fw); - else - error = ims_pcu_switch_to_bootloader(pcu); + scoped_cond_guard(mutex_intr, return -EINTR, &pcu->cmd_mutex) { + /* + * If we are already in bootloader mode we can proceed with + * flashing the firmware. + * + * If we are in application mode, then we need to switch into + * bootloader mode, which will cause the device to disconnect + * and reconnect as different device. + */ + if (pcu->bootloader_mode) + error = ims_pcu_handle_firmware_update(pcu, fw); + else + error = ims_pcu_switch_to_bootloader(pcu); - release_firmware(fw); + if (error) + return error; + } -out: - mutex_unlock(&pcu->cmd_mutex); - return error ?: count; + return count; } static DEVICE_ATTR(update_firmware, S_IWUSR, @@ -1302,12 +1292,11 @@ static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev, int error; u8 data; - mutex_lock(&pcu->cmd_mutex); - error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); - mutex_unlock(&pcu->cmd_mutex); - - if (error) - return error; + scoped_guard(mutex, &pcu->cmd_mutex) { + error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); + if (error) + return error; + } return sysfs_emit(buf, "%x\n", data); } @@ -1325,11 +1314,13 @@ static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev, if (error) return error; - mutex_lock(&pcu->cmd_mutex); - error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); - mutex_unlock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); - return error ?: count; + error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); + if (error) + return error; + + return count; } static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR, @@ -1341,13 +1332,10 @@ static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev, { struct usb_interface *intf = to_usb_interface(dev); struct ims_pcu *pcu = usb_get_intfdata(intf); - int error; - mutex_lock(&pcu->cmd_mutex); - error = sysfs_emit(buf, "%x\n", pcu->ofn_reg_addr); - mutex_unlock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); - return error; + return sysfs_emit(buf, "%x\n", pcu->ofn_reg_addr); } static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, @@ -1363,9 +1351,9 @@ static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, if (error) return error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); + pcu->ofn_reg_addr = value; - mutex_unlock(&pcu->cmd_mutex); return count; } @@ -1390,12 +1378,11 @@ static ssize_t ims_pcu_ofn_bit_show(struct device *dev, int error; u8 data; - mutex_lock(&pcu->cmd_mutex); - error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); - mutex_unlock(&pcu->cmd_mutex); - - if (error) - return error; + scoped_guard(mutex, &pcu->cmd_mutex) { + error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); + if (error) + return error; + } return sysfs_emit(buf, "%d\n", !!(data & (1 << attr->nr))); } @@ -1419,21 +1406,22 @@ static ssize_t ims_pcu_ofn_bit_store(struct device *dev, if (value > 1) return -EINVAL; - mutex_lock(&pcu->cmd_mutex); + scoped_guard(mutex, &pcu->cmd_mutex) { + error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); + if (error) + return error; - error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); - if (!error) { if (value) data |= 1U << attr->nr; else data &= ~(1U << attr->nr); error = ims_pcu_write_ofn_config(pcu, attr->addr, data); + if (error) + return error; } - mutex_unlock(&pcu->cmd_mutex); - - return error ?: count; + return count; } #define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr) \ @@ -1466,9 +1454,27 @@ static struct attribute *ims_pcu_ofn_attrs[] = { NULL }; +static umode_t ims_pcu_ofn_is_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + umode_t mode = attr->mode; + + /* + * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor. + */ + if (pcu->bootloader_mode || pcu->device_id == IMS_PCU_PCU_B_DEVICE_ID) + mode = 0; + + return mode; +} + static const struct attribute_group ims_pcu_ofn_attr_group = { - .name = "ofn", - .attrs = ims_pcu_ofn_attrs, + .name = "ofn", + .is_visible = ims_pcu_ofn_is_attr_visible, + .attrs = ims_pcu_ofn_attrs, }; static void ims_pcu_irq(struct urb *urb) @@ -1890,16 +1896,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) /* Device appears to be operable, complete initialization */ pcu->device_no = atomic_inc_return(&device_no); - /* - * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor - */ - if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) { - error = sysfs_create_group(&pcu->dev->kobj, - &ims_pcu_ofn_attr_group); - if (error) - return error; - } - error = ims_pcu_setup_backlight(pcu); if (error) return error; @@ -1936,10 +1932,6 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu) ims_pcu_destroy_gamepad(pcu); ims_pcu_destroy_buttons(pcu); ims_pcu_destroy_backlight(pcu); - - if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) - sysfs_remove_group(&pcu->dev->kobj, - &ims_pcu_ofn_attr_group); } } @@ -1993,7 +1985,7 @@ static int ims_pcu_probe(struct usb_interface *intf, struct ims_pcu *pcu; int error; - pcu = kzalloc(sizeof(struct ims_pcu), GFP_KERNEL); + pcu = kzalloc(sizeof(*pcu), GFP_KERNEL); if (!pcu) return -ENOMEM; @@ -2031,20 +2023,14 @@ static int ims_pcu_probe(struct usb_interface *intf, if (error) goto err_stop_io; - error = sysfs_create_group(&intf->dev.kobj, &ims_pcu_attr_group); - if (error) - goto err_stop_io; - error = pcu->bootloader_mode ? ims_pcu_init_bootloader_mode(pcu) : ims_pcu_init_application_mode(pcu); if (error) - goto err_remove_sysfs; + goto err_stop_io; return 0; -err_remove_sysfs: - sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group); err_stop_io: ims_pcu_stop_io(pcu); err_free_buffers: @@ -2070,8 +2056,6 @@ static void ims_pcu_disconnect(struct usb_interface *intf) if (alt->desc.bInterfaceClass != USB_CLASS_COMM) return; - sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group); - ims_pcu_stop_io(pcu); if (pcu->bootloader_mode) @@ -2130,9 +2114,16 @@ static const struct usb_device_id ims_pcu_id_table[] = { { } }; +static const struct attribute_group *ims_pcu_sysfs_groups[] = { + &ims_pcu_attr_group, + &ims_pcu_ofn_attr_group, + NULL +}; + static struct usb_driver ims_pcu_driver = { .name = "ims_pcu", .id_table = ims_pcu_id_table, + .dev_groups = ims_pcu_sysfs_groups, .probe = ims_pcu_probe, .disconnect = ims_pcu_disconnect, #ifdef CONFIG_PM diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index 8861a67be575..11cac4b7dddc 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -249,7 +249,7 @@ static int max8997_haptic_probe(struct platform_device *pdev) return -EINVAL; } - chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); input_dev = input_allocate_device(); if (!chip || !input_dev) { dev_err(&pdev->dev, "unable to allocate memory\n"); diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index 8a7e9ada5952..f8954a2cab24 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c @@ -49,7 +49,7 @@ static int pcap_keys_probe(struct platform_device *pdev) struct pcap_keys *pcap_keys; struct input_dev *input_dev; - pcap_keys = kmalloc(sizeof(struct pcap_keys), GFP_KERNEL); + pcap_keys = kmalloc(sizeof(*pcap_keys), GFP_KERNEL); if (!pcap_keys) return err; diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index db2ba89adaef..4b039abffc4b 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -320,7 +320,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i 0, interface->desc.bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); - pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL); + pm = kzalloc(sizeof(*pm), GFP_KERNEL); input_dev = input_allocate_device(); if (!pm || !input_dev) goto fail1; diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 0657d785b3cc..39c2882b8e1a 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -128,4 +128,5 @@ static struct platform_driver sgi_buttons_driver = { }; module_platform_driver(sgi_buttons_driver); +MODULE_DESCRIPTION("SGI Indy/O2 volume button interface driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index f6d060377d18..5c5d407fe965 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -620,4 +620,5 @@ static struct platform_driver soc_button_driver = { }; module_platform_driver(soc_button_driver); +MODULE_DESCRIPTION("Windows-compatible SoC Button Array driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index e3ee0638ffba..f85cc289c053 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -1,5 +1,5 @@ -/** - * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver +/* + * TWL4030 Power Button Input Driver * * Copyright (C) 2008-2009 Nokia Corporation * diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index d98212d55108..d23f3225b00f 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -379,7 +379,7 @@ static int uinput_open(struct inode *inode, struct file *file) { struct uinput_device *newdev; - newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL); + newdev = kzalloc(sizeof(*newdev), GFP_KERNEL); if (!newdev) return -ENOMEM; diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 69420781db30..8866bf65d347 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -103,6 +103,8 @@ struct yealink_dev { u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */ int key_code; /* last reported key */ + struct mutex sysfs_mutex; + unsigned int shutdown:1; int stat_ix; @@ -548,8 +550,6 @@ static void input_close(struct input_dev *dev) * sysfs interface ******************************************************************************/ -static DECLARE_RWSEM(sysfs_rwsema); - /* Interface to the 7-segments translation table aka. char set. */ static ssize_t show_map(struct device *dev, struct device_attribute *attr, @@ -580,15 +580,10 @@ static ssize_t store_map(struct device *dev, struct device_attribute *attr, */ static ssize_t show_line(struct device *dev, char *buf, int a, int b) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i; - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); for (i = a; i < b; i++) *buf++ = lcdMap[i].type; @@ -598,7 +593,6 @@ static ssize_t show_line(struct device *dev, char *buf, int a, int b) *buf++ = '\n'; *buf = 0; - up_read(&sysfs_rwsema); return 3 + ((b - a) << 1); } @@ -630,22 +624,16 @@ static ssize_t show_line3(struct device *dev, struct device_attribute *attr, static ssize_t store_line(struct device *dev, const char *buf, size_t count, int el, size_t len) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i; - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); if (len > count) len = count; for (i = 0; i < len; i++) setChar(yld, el++, buf[i]); - up_write(&sysfs_rwsema); return count; } @@ -675,15 +663,10 @@ static ssize_t store_line3(struct device *dev, struct device_attribute *attr, static ssize_t get_icons(struct device *dev, struct device_attribute *attr, char *buf) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i, ret = 1; - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { if (lcdMap[i].type != '.') @@ -692,7 +675,7 @@ static ssize_t get_icons(struct device *dev, struct device_attribute *attr, yld->lcdMap[i] == ' ' ? " " : "on", lcdMap[i].u.p.name); } - up_read(&sysfs_rwsema); + return ret; } @@ -700,15 +683,10 @@ static ssize_t get_icons(struct device *dev, struct device_attribute *attr, static ssize_t set_icon(struct device *dev, const char *buf, size_t count, int chr) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i; - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { if (lcdMap[i].type != '.') @@ -719,7 +697,6 @@ static ssize_t set_icon(struct device *dev, const char *buf, size_t count, } } - up_write(&sysfs_rwsema); return count; } @@ -739,22 +716,16 @@ static ssize_t hide_icon(struct device *dev, struct device_attribute *attr, */ /* Stores raw ringtone data in the phone */ -static ssize_t store_ringtone(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t store_ringtone(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); /* TODO locking with async usb control interface??? */ yealink_set_ringtone(yld, (char *)buf, count); - up_write(&sysfs_rwsema); + return count; } @@ -771,7 +742,7 @@ static DEVICE_ATTR(show_icon , _M220, NULL , show_icon ); static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon ); static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone); -static struct attribute *yld_attributes[] = { +static struct attribute *yld_attrs[] = { &dev_attr_line1.attr, &dev_attr_line2.attr, &dev_attr_line3.attr, @@ -782,10 +753,7 @@ static struct attribute *yld_attributes[] = { &dev_attr_ringtone.attr, NULL }; - -static const struct attribute_group yld_attr_group = { - .attrs = yld_attributes -}; +ATTRIBUTE_GROUPS(yld); /******************************************************************************* * Linux interface and usb initialisation @@ -838,15 +806,10 @@ static int usb_cleanup(struct yealink_dev *yld, int err) static void usb_disconnect(struct usb_interface *intf) { - struct yealink_dev *yld; - - down_write(&sysfs_rwsema); - yld = usb_get_intfdata(intf); - sysfs_remove_group(&intf->dev.kobj, &yld_attr_group); - usb_set_intfdata(intf, NULL); - up_write(&sysfs_rwsema); + struct yealink_dev *yld = usb_get_intfdata(intf); usb_cleanup(yld, 0); + usb_set_intfdata(intf, NULL); } static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -868,12 +831,13 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; - yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); + yld = kzalloc(sizeof(*yld), GFP_KERNEL); if (!yld) return -ENOMEM; yld->udev = udev; yld->intf = intf; + mutex_init(&yld->sysfs_mutex); yld->idev = input_dev = input_allocate_device(); if (!input_dev) @@ -975,8 +939,6 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) store_line3(&intf->dev, NULL, DRIVER_VERSION, sizeof(DRIVER_VERSION)); - /* Register sysfs hooks (don't care about failure) */ - ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group); return 0; } @@ -985,6 +947,7 @@ static struct usb_driver yealink_driver = { .probe = usb_probe, .disconnect = usb_disconnect, .id_table = usb_table, + .dev_groups = yld_groups, }; module_usb_driver(yealink_driver); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index e2c11d9f3868..d5ef5a112d6f 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -3201,7 +3201,7 @@ int alps_detect(struct psmouse *psmouse, bool set_properties) */ psmouse_reset(psmouse); - priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 627048bc6a12..e669f86f1882 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -855,7 +855,7 @@ static int atp_probe(struct usb_interface *iface, } /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct atp), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); input_dev = input_allocate_device(); if (!dev || !input_dev) { dev_err(&iface->dev, "Out of memory\n"); diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index ca150618d32f..10a03a566905 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -904,7 +904,7 @@ static int bcm5974_probe(struct usb_interface *iface, cfg = bcm5974_get_config(udev); /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); input_dev = input_allocate_device(); if (!dev || !input_dev) { dev_err(&iface->dev, "out of memory\n"); diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index d272f1ec27ba..b3c34ebcc4ef 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -32,33 +32,30 @@ static void cypress_set_packet_size(struct psmouse *psmouse, unsigned int n) cytp->pkt_size = n; } -static const unsigned char cytp_rate[] = {10, 20, 40, 60, 100, 200}; -static const unsigned char cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; +static const u8 cytp_rate[] = {10, 20, 40, 60, 100, 200}; +static const u8 cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; -static int cypress_ps2_sendbyte(struct psmouse *psmouse, int value) +static int cypress_ps2_sendbyte(struct psmouse *psmouse, u8 cmd) { struct ps2dev *ps2dev = &psmouse->ps2dev; + int error; - if (ps2_sendbyte(ps2dev, value & 0xff, CYTP_CMD_TIMEOUT) < 0) { + error = ps2_sendbyte(ps2dev, cmd, CYTP_CMD_TIMEOUT); + if (error) { psmouse_dbg(psmouse, - "sending command 0x%02x failed, resp 0x%02x\n", - value & 0xff, ps2dev->nak); - if (ps2dev->nak == CYTP_PS2_RETRY) - return CYTP_PS2_RETRY; - else - return CYTP_PS2_ERROR; + "sending command 0x%02x failed, resp 0x%02x, error %d\n", + cmd, ps2dev->nak, error); + return error; } #ifdef CYTP_DEBUG_VERBOSE - psmouse_dbg(psmouse, "sending command 0x%02x succeeded, resp 0xfa\n", - value & 0xff); + psmouse_dbg(psmouse, "sending command 0x%02x succeeded\n", cmd); #endif return 0; } -static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, - unsigned char data) +static int cypress_ps2_ext_cmd(struct psmouse *psmouse, u8 prefix, u8 nibble) { struct ps2dev *ps2dev = &psmouse->ps2dev; int tries = CYTP_PS2_CMD_TRIES; @@ -72,22 +69,21 @@ static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, * If sending the command fails, send recovery command * to make the device return to the ready state. */ - rc = cypress_ps2_sendbyte(psmouse, cmd & 0xff); - if (rc == CYTP_PS2_RETRY) { + rc = cypress_ps2_sendbyte(psmouse, prefix); + if (rc == -EAGAIN) { rc = cypress_ps2_sendbyte(psmouse, 0x00); - if (rc == CYTP_PS2_RETRY) + if (rc == -EAGAIN) rc = cypress_ps2_sendbyte(psmouse, 0x0a); } - if (rc == CYTP_PS2_ERROR) - continue; - rc = cypress_ps2_sendbyte(psmouse, data); - if (rc == CYTP_PS2_RETRY) - rc = cypress_ps2_sendbyte(psmouse, data); - if (rc == CYTP_PS2_ERROR) - continue; - else - break; + if (!rc) { + rc = cypress_ps2_sendbyte(psmouse, nibble); + if (rc == -EAGAIN) + rc = cypress_ps2_sendbyte(psmouse, nibble); + + if (!rc) + break; + } } while (--tries > 0); ps2_end_command(ps2dev); @@ -96,13 +92,12 @@ static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, } static int cypress_ps2_read_cmd_status(struct psmouse *psmouse, - unsigned char cmd, - unsigned char *param) + u8 cmd, u8 *param) { - int rc; struct ps2dev *ps2dev = &psmouse->ps2dev; enum psmouse_state old_state; int pktsize; + int rc; ps2_begin_command(ps2dev); @@ -113,13 +108,16 @@ static int cypress_ps2_read_cmd_status(struct psmouse *psmouse, pktsize = (cmd == CYTP_CMD_READ_TP_METRICS) ? 8 : 3; memset(param, 0, pktsize); - rc = cypress_ps2_sendbyte(psmouse, 0xe9); - if (rc < 0) + rc = cypress_ps2_sendbyte(psmouse, PSMOUSE_CMD_GETINFO & 0xff); + if (rc) goto out; - wait_event_timeout(ps2dev->wait, - (psmouse->pktcnt >= pktsize), - msecs_to_jiffies(CYTP_CMD_TIMEOUT)); + if (!wait_event_timeout(ps2dev->wait, + psmouse->pktcnt >= pktsize, + msecs_to_jiffies(CYTP_CMD_TIMEOUT))) { + rc = -ETIMEDOUT; + goto out; + } memcpy(param, psmouse->packet, pktsize); @@ -135,8 +133,7 @@ out: return rc; } -static bool cypress_verify_cmd_state(struct psmouse *psmouse, - unsigned char cmd, unsigned char *param) +static bool cypress_verify_cmd_state(struct psmouse *psmouse, u8 cmd, u8* param) { bool rate_match = false; bool resolution_match = false; @@ -166,31 +163,24 @@ static bool cypress_verify_cmd_state(struct psmouse *psmouse, return false; } -static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, - unsigned char *param) +static int cypress_send_ext_cmd(struct psmouse *psmouse, u8 cmd, u8 *param) { + u8 cmd_prefix = PSMOUSE_CMD_SETRES & 0xff; int tries = CYTP_PS2_CMD_TRIES; - int rc; + int error; psmouse_dbg(psmouse, "send extension cmd 0x%02x, [%d %d %d %d]\n", cmd, DECODE_CMD_AA(cmd), DECODE_CMD_BB(cmd), DECODE_CMD_CC(cmd), DECODE_CMD_DD(cmd)); do { - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_DD(cmd)); - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_CC(cmd)); - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_BB(cmd)); - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_AA(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_DD(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_CC(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_BB(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_AA(cmd)); - rc = cypress_ps2_read_cmd_status(psmouse, cmd, param); - if (rc) - continue; - - if (cypress_verify_cmd_state(psmouse, cmd, param)) + error = cypress_ps2_read_cmd_status(psmouse, cmd, param); + if (!error && cypress_verify_cmd_state(psmouse, cmd, param)) return 0; } while (--tries > 0); @@ -200,7 +190,7 @@ static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, int cypress_detect(struct psmouse *psmouse, bool set_properties) { - unsigned char param[3]; + u8 param[3]; if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) return -ENODEV; @@ -220,7 +210,7 @@ int cypress_detect(struct psmouse *psmouse, bool set_properties) static int cypress_read_fw_version(struct psmouse *psmouse) { struct cytp_data *cytp = psmouse->private; - unsigned char param[3]; + u8 param[3]; if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) return -ENODEV; @@ -249,7 +239,7 @@ static int cypress_read_fw_version(struct psmouse *psmouse) static int cypress_read_tp_metrics(struct psmouse *psmouse) { struct cytp_data *cytp = psmouse->private; - unsigned char param[8]; + u8 param[8]; /* set default values for tp metrics. */ cytp->tp_width = CYTP_DEFAULT_WIDTH; @@ -321,15 +311,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) static int cypress_query_hardware(struct psmouse *psmouse) { - int ret; + int error; - ret = cypress_read_fw_version(psmouse); - if (ret) - return ret; + error = cypress_read_fw_version(psmouse); + if (error) + return error; - ret = cypress_read_tp_metrics(psmouse); - if (ret) - return ret; + error = cypress_read_tp_metrics(psmouse); + if (error) + return error; return 0; } @@ -337,10 +327,13 @@ static int cypress_query_hardware(struct psmouse *psmouse) static int cypress_set_absolute_mode(struct psmouse *psmouse) { struct cytp_data *cytp = psmouse->private; - unsigned char param[3]; + u8 param[3]; + int error; - if (cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, param) < 0) - return -1; + error = cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, + param); + if (error) + return error; cytp->mode = (cytp->mode & ~CYTP_BIT_ABS_REL_MASK) | CYTP_BIT_ABS_PRESSURE; @@ -365,7 +358,7 @@ static void cypress_reset(struct psmouse *psmouse) static int cypress_set_input_params(struct input_dev *input, struct cytp_data *cytp) { - int ret; + int error; if (!cytp->tp_res_x || !cytp->tp_res_y) return -EINVAL; @@ -382,10 +375,10 @@ static int cypress_set_input_params(struct input_dev *input, input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cytp->tp_max_abs_y, 0, 0); input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0); - ret = input_mt_init_slots(input, CYTP_MAX_MT_SLOTS, - INPUT_MT_DROP_UNUSED|INPUT_MT_TRACK); - if (ret < 0) - return ret; + error = input_mt_init_slots(input, CYTP_MAX_MT_SLOTS, + INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); + if (error) + return error; __set_bit(INPUT_PROP_SEMI_MT, input->propbit); @@ -414,9 +407,9 @@ static int cypress_set_input_params(struct input_dev *input, return 0; } -static int cypress_get_finger_count(unsigned char header_byte) +static int cypress_get_finger_count(u8 header_byte) { - unsigned char bits6_7; + u8 bits6_7; int finger_count; bits6_7 = header_byte >> 6; @@ -441,10 +434,11 @@ static int cypress_get_finger_count(unsigned char header_byte) static int cypress_parse_packet(struct psmouse *psmouse, - struct cytp_data *cytp, struct cytp_report_data *report_data) + struct cytp_data *cytp, + struct cytp_report_data *report_data) { - unsigned char *packet = psmouse->packet; - unsigned char header_byte = packet[0]; + u8 *packet = psmouse->packet; + u8 header_byte = packet[0]; memset(report_data, 0, sizeof(struct cytp_report_data)); @@ -559,7 +553,7 @@ static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) { int contact_cnt; int index = psmouse->pktcnt - 1; - unsigned char *packet = psmouse->packet; + u8 *packet = psmouse->packet; struct cytp_data *cytp = psmouse->private; if (index < 0 || index > cytp->pkt_size) @@ -612,6 +606,7 @@ static psmouse_ret_t cypress_protocol_handler(struct psmouse *psmouse) static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) { struct cytp_data *cytp = psmouse->private; + u8 rate_param; if (rate >= 80) { psmouse->rate = 80; @@ -621,8 +616,8 @@ static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) cytp->mode &= ~CYTP_BIT_HIGH_RATE; } - ps2_command(&psmouse->ps2dev, (unsigned char *)&psmouse->rate, - PSMOUSE_CMD_SETRATE); + rate_param = (u8)rate; + ps2_command(&psmouse->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE); } static void cypress_disconnect(struct psmouse *psmouse) @@ -635,21 +630,22 @@ static void cypress_disconnect(struct psmouse *psmouse) static int cypress_reconnect(struct psmouse *psmouse) { int tries = CYTP_PS2_CMD_TRIES; - int rc; + int error; do { cypress_reset(psmouse); - rc = cypress_detect(psmouse, false); - } while (rc && (--tries > 0)); + error = cypress_detect(psmouse, false); + } while (error && (--tries > 0)); - if (rc) { + if (error) { psmouse_err(psmouse, "Reconnect: unable to detect trackpad.\n"); - return -1; + return error; } - if (cypress_set_absolute_mode(psmouse)) { + error = cypress_set_absolute_mode(psmouse); + if (error) { psmouse_err(psmouse, "Reconnect: Unable to initialize Cypress absolute mode.\n"); - return -1; + return error; } return 0; @@ -658,8 +654,9 @@ static int cypress_reconnect(struct psmouse *psmouse) int cypress_init(struct psmouse *psmouse) { struct cytp_data *cytp; + int error; - cytp = kzalloc(sizeof(struct cytp_data), GFP_KERNEL); + cytp = kzalloc(sizeof(*cytp), GFP_KERNEL); if (!cytp) return -ENOMEM; @@ -668,17 +665,20 @@ int cypress_init(struct psmouse *psmouse) cypress_reset(psmouse); - if (cypress_query_hardware(psmouse)) { + error = cypress_query_hardware(psmouse); + if (error) { psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); goto err_exit; } - if (cypress_set_absolute_mode(psmouse)) { + error = cypress_set_absolute_mode(psmouse); + if (error) { psmouse_err(psmouse, "init: Unable to initialize Cypress absolute mode.\n"); goto err_exit; } - if (cypress_set_input_params(psmouse->dev, cytp) < 0) { + error = cypress_set_input_params(psmouse->dev, cytp); + if (error) { psmouse_err(psmouse, "init: Unable to set input params.\n"); goto err_exit; } @@ -703,5 +703,5 @@ err_exit: psmouse->private = NULL; kfree(cytp); - return -1; + return error; } diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h index bb4979d06bf9..47d538a49089 100644 --- a/drivers/input/mouse/cypress_ps2.h +++ b/drivers/input/mouse/cypress_ps2.h @@ -72,12 +72,6 @@ #define CYTP_DATA_TIMEOUT 30 #define CYTP_EXT_CMD 0xe8 -#define CYTP_PS2_RETRY 0xfe -#define CYTP_PS2_ERROR 0xfc - -#define CYTP_RESP_RETRY 0x01 -#define CYTP_RESP_ERROR 0xfe - #define CYTP_105001_WIDTH 97 /* Dell XPS 13 */ #define CYTP_105001_HIGH 59 diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index c2aec5c360b3..ce96513b34f6 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1356,6 +1356,8 @@ static int elan_suspend(struct device *dev) } err: + if (ret) + enable_irq(client->irq); mutex_unlock(&data->sysfs_mutex); return ret; } diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c index c74b99077d16..356b99d48544 100644 --- a/drivers/input/mouse/focaltech.c +++ b/drivers/input/mouse/focaltech.c @@ -408,8 +408,7 @@ int focaltech_init(struct psmouse *psmouse) struct focaltech_data *priv; int error; - psmouse->private = priv = kzalloc(sizeof(struct focaltech_data), - GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 3c8310da0b05..6125652e5ad8 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -981,7 +981,7 @@ int hgpk_init(struct psmouse *psmouse) struct hgpk_data *priv; int err; - priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { err = -ENOMEM; goto alloc_fail; diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index bd9955730176..7147dacc404f 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -273,7 +273,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse) struct lifebook_data *priv; int error = -ENOMEM; - priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); dev2 = input_allocate_device(); if (!priv || !dev2) goto err_out; diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index 2de64d6a04d1..baef4be14b54 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c @@ -73,7 +73,7 @@ static int probe_maple_mouse(struct device *dev) struct input_dev *input_dev; struct dc_mouse *mse; - mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); + mse = kzalloc(sizeof(*mse), GFP_KERNEL); if (!mse) { error = -ENOMEM; goto fail; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index a0aac76b1e41..a2c9f7144864 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1591,7 +1591,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_deactivate(parent); } - psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL); + psmouse = kzalloc(sizeof(*psmouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!psmouse || !input_dev) goto err_free; diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 2716d2ba386a..44b136fc29aa 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -1028,7 +1028,7 @@ int fsp_init(struct psmouse *psmouse) "Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n", ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver); - psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 993f90333380..218c8432a13b 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -231,7 +231,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) unsigned char c = serio->id.extra; int err = -ENOMEM; - sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL); + sermouse = kzalloc(sizeof(*sermouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!sermouse || !input_dev) goto fail1; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 7a303a9d6bf7..38191c3b31bf 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -708,7 +708,7 @@ static void synaptics_pt_create(struct psmouse *psmouse) { struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) { psmouse_err(psmouse, "not enough memory for pass-through port\n"); @@ -1563,7 +1563,7 @@ static int synaptics_init_ps2(struct psmouse *psmouse, synaptics_apply_quirks(psmouse, info); - psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 56e9ba396858..a0d707e47d93 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -508,7 +508,7 @@ static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *clien { struct synaptics_i2c *touch; - touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); + touch = kzalloc(sizeof(*touch), GFP_KERNEL); if (!touch) return NULL; diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 8af8e4a15f95..707cd28f4ba6 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -456,7 +456,7 @@ static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL); + mouse = kzalloc(sizeof(*mouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!mouse || !input_dev) goto fail1; diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index c5b634940cfc..611eb9fe2d04 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -100,7 +100,7 @@ static int altera_ps2_probe(struct platform_device *pdev) return error; } - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 496bb7a312d2..de4b3915c37d 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -114,8 +114,8 @@ static int amba_kmi_probe(struct amba_device *dev, if (ret) return ret; - kmi = kzalloc(sizeof(struct amba_kmi_port), GFP_KERNEL); - io = kzalloc(sizeof(struct serio), GFP_KERNEL); + kmi = kzalloc(sizeof(*kmi), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!kmi || !io) { ret = -ENOMEM; goto out; diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c index dbbb10251520..4015e75fcb90 100644 --- a/drivers/input/serio/apbps2.c +++ b/drivers/input/serio/apbps2.c @@ -165,7 +165,7 @@ static int apbps2_of_probe(struct platform_device *ofdev) /* Set reload register to core freq in kHz/10 */ iowrite32be(freq_hz / 10000, &priv->regs->reload); - priv->io = kzalloc(sizeof(struct serio), GFP_KERNEL); + priv->io = kzalloc(sizeof(*priv->io), GFP_KERNEL); if (!priv->io) return -ENOMEM; diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c index 9d8726830140..a9180a005872 100644 --- a/drivers/input/serio/arc_ps2.c +++ b/drivers/input/serio/arc_ps2.c @@ -155,7 +155,7 @@ static int arc_ps2_create_port(struct platform_device *pdev, struct arc_ps2_port *port = &arc_ps2->port[index]; struct serio *io; - io = kzalloc(sizeof(struct serio), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!io) return -ENOMEM; diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index d5c9bb3d0103..6834440b37f6 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -158,7 +158,7 @@ static int __init ct82c710_detect(void) static int ct82c710_probe(struct platform_device *dev) { - ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL); + ct82c710_port = kzalloc(sizeof(*ct82c710_port), GFP_KERNEL); if (!ct82c710_port) return -ENOMEM; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 633c7de49d67..d94c01eb3fc9 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -338,8 +338,8 @@ static int __init gscps2_probe(struct parisc_device *dev) if (dev->id.sversion == 0x96) hpa += GSC_DINO_OFFSET; - ps2port = kzalloc(sizeof(struct gscps2port), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + ps2port = kzalloc(sizeof(*ps2port), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!ps2port || !serio) { ret = -ENOMEM; goto fail_nomem; diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index 31def6ce5157..31d9dacd2fd1 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c @@ -318,8 +318,8 @@ static int hv_kbd_probe(struct hv_device *hv_dev, struct serio *hv_serio; int error; - kbd_dev = kzalloc(sizeof(struct hv_kbd_dev), GFP_KERNEL); - hv_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + kbd_dev = kzalloc(sizeof(*kbd_dev), GFP_KERNEL); + hv_serio = kzalloc(sizeof(*hv_serio), GFP_KERNEL); if (!kbd_dev || !hv_serio) { error = -ENOMEM; goto err_free_mem; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 9fbb8d31575a..e0fb1db653b7 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1329,7 +1329,7 @@ static int i8042_create_kbd_port(void) struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -1359,7 +1359,7 @@ static int i8042_create_aux_port(int idx) int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; struct i8042_port *port = &i8042_ports[port_no]; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c index 5ccfb82759b3..42ac1eb94866 100644 --- a/drivers/input/serio/maceps2.c +++ b/drivers/input/serio/maceps2.c @@ -117,7 +117,7 @@ static struct serio *maceps2_allocate_port(int idx) { struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (serio) { serio->id.type = SERIO_8042; serio->write = maceps2_write; diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c index 240a714f7081..0ad95e880cc2 100644 --- a/drivers/input/serio/olpc_apsp.c +++ b/drivers/input/serio/olpc_apsp.c @@ -188,7 +188,7 @@ static int olpc_apsp_probe(struct platform_device *pdev) return priv->irq; /* KEYBOARD */ - kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + kb_serio = kzalloc(sizeof(*kb_serio), GFP_KERNEL); if (!kb_serio) return -ENOMEM; kb_serio->id.type = SERIO_8042_XL; @@ -203,7 +203,7 @@ static int olpc_apsp_probe(struct platform_device *pdev) serio_register_port(kb_serio); /* TOUCHPAD */ - pad_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + pad_serio = kzalloc(sizeof(*pad_serio), GFP_KERNEL); if (!pad_serio) { error = -ENOMEM; goto err_pad; diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index 0d54895428f5..22fe55490572 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c @@ -165,7 +165,7 @@ static struct serio *parkbd_allocate_serio(void) { struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (serio) { serio->id.type = parkbd_mode; serio->write = parkbd_write; @@ -218,6 +218,5 @@ static struct parport_driver parkbd_parport_driver = { .name = "parkbd", .match_port = parkbd_attach, .detach = parkbd_detach, - .devmodel = true, }; module_parport_driver(parkbd_parport_driver); diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 05878750f2c2..6b9abb2e18c9 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -137,8 +137,8 @@ static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id) if (ret) goto disable; - ps2if = kzalloc(sizeof(struct pcips2_data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + ps2if = kzalloc(sizeof(*ps2if), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!ps2if || !serio) { ret = -ENOMEM; goto release; diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c index c3ff60859a03..0c8b390b8b4f 100644 --- a/drivers/input/serio/ps2-gpio.c +++ b/drivers/input/serio/ps2-gpio.c @@ -404,8 +404,8 @@ static int ps2_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int error; - drvdata = devm_kzalloc(dev, sizeof(struct ps2_gpio_data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!drvdata || !serio) { error = -ENOMEM; goto err_free_serio; diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c index 902e81826fbf..937ecdea491d 100644 --- a/drivers/input/serio/ps2mult.c +++ b/drivers/input/serio/ps2mult.c @@ -127,7 +127,7 @@ static int ps2mult_create_port(struct ps2mult *psm, int i) struct serio *mx_serio = psm->mx_serio; struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 3f81f8749cd5..cd4d5be946a3 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -108,8 +108,8 @@ static int q40kbd_probe(struct platform_device *pdev) struct serio *port; int error; - q40kbd = kzalloc(sizeof(struct q40kbd), GFP_KERNEL); - port = kzalloc(sizeof(struct serio), GFP_KERNEL); + q40kbd = kzalloc(sizeof(*q40kbd), GFP_KERNEL); + port = kzalloc(sizeof(*port), GFP_KERNEL); if (!q40kbd || !port) { error = -ENOMEM; goto err_free_mem; diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 9bbfefd092c0..e236bb7e1014 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -108,7 +108,7 @@ static int rpckbd_probe(struct platform_device *dev) if (tx_irq < 0) return tx_irq; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL); if (!serio || !rpckbd) { kfree(rpckbd); diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 2724c3aa512c..1311caf7dba4 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -256,8 +256,8 @@ static int ps2_probe(struct sa1111_dev *dev) struct serio *serio; int ret; - ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + ps2if = kzalloc(sizeof(*ps2if), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!ps2if || !serio) { ret = -ENOMEM; goto free; diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index a8838b522627..04967494eeb6 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -258,7 +258,7 @@ static int serio_queue_event(void *object, struct module *owner, } } - event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); + event = kmalloc(sizeof(*event), GFP_ATOMIC); if (!event) { pr_err("Not enough memory to queue event %d\n", event_type); retval = -ENOMEM; diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 1e4770094415..0186d1b38f49 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -92,7 +92,7 @@ static int serio_raw_open(struct inode *inode, struct file *file) goto out; } - client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL); + client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) { retval = -ENOMEM; goto out; @@ -293,7 +293,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) struct serio_raw *serio_raw; int err; - serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL); + serio_raw = kzalloc(sizeof(*serio_raw), GFP_KERNEL); if (!serio_raw) { dev_dbg(&serio->dev, "can't allocate memory for a device\n"); return -ENOMEM; diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 1db3f30011c4..5a2b5404ffc2 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -82,7 +82,7 @@ static int serport_ldisc_open(struct tty_struct *tty) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - serport = kzalloc(sizeof(struct serport), GFP_KERNEL); + serport = kzalloc(sizeof(*serport), GFP_KERNEL); if (!serport) return -ENOMEM; @@ -167,7 +167,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, if (test_and_set_bit(SERPORT_BUSY, &serport->flags)) return -EBUSY; - serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serport->serio = serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; diff --git a/drivers/input/serio/sun4i-ps2.c b/drivers/input/serio/sun4i-ps2.c index aec66d9f5176..95cd8aaee65d 100644 --- a/drivers/input/serio/sun4i-ps2.c +++ b/drivers/input/serio/sun4i-ps2.c @@ -213,8 +213,8 @@ static int sun4i_ps2_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int error; - drvdata = kzalloc(sizeof(struct sun4i_ps2data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!drvdata || !serio) { error = -ENOMEM; goto err_free_mem; diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c index 9ab5c45c3a9f..a88e2eee55c3 100644 --- a/drivers/input/serio/userio.c +++ b/drivers/input/serio/userio.c @@ -77,7 +77,7 @@ static int userio_char_open(struct inode *inode, struct file *file) { struct userio_device *userio; - userio = kzalloc(sizeof(struct userio_device), GFP_KERNEL); + userio = kzalloc(sizeof(*userio), GFP_KERNEL); if (!userio) return -ENOMEM; @@ -85,7 +85,7 @@ static int userio_char_open(struct inode *inode, struct file *file) spin_lock_init(&userio->buf_lock); init_waitqueue_head(&userio->waitq); - userio->serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + userio->serio = kzalloc(sizeof(*userio->serio), GFP_KERNEL); if (!userio->serio) { kfree(userio); return -ENOMEM; diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index bb758346a33d..1543267d02ac 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -252,8 +252,8 @@ static int xps2_of_probe(struct platform_device *ofdev) return -ENODEV; } - drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!drvdata || !serio) { error = -ENOMEM; goto failed1; diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index b20e5a1afbcc..0ac16f32b31f 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -129,7 +129,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe); - acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); + acecad = kzalloc(sizeof(*acecad), GFP_KERNEL); input_dev = input_allocate_device(); if (!acecad || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index baabc51547b8..2d176fbab251 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1673,7 +1673,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) */ speeds[0] = programmableDelay; - aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); + aiptek = kzalloc(sizeof(*aiptek), GFP_KERNEL); inputdev = input_allocate_device(); if (!aiptek || !inputdev) { dev_warn(&intf->dev, diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c index 9bc631518b92..42c1e5eaddd5 100644 --- a/drivers/input/tablet/hanwang.c +++ b/drivers/input/tablet/hanwang.c @@ -322,7 +322,7 @@ static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id if (intf->cur_altsetting->desc.bNumEndpoints < 1) return -ENODEV; - hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL); + hanwang = kzalloc(sizeof(*hanwang), GFP_KERNEL); input_dev = input_allocate_device(); if (!hanwang || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index aa577898e952..38d36d25f6f4 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -121,7 +121,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; - kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); + kbtab = kzalloc(sizeof(*kbtab), GFP_KERNEL); input_dev = input_allocate_device(); if (!kbtab || !input_dev) goto fail1; diff --git a/drivers/input/tablet/wacom_serial4.c b/drivers/input/tablet/wacom_serial4.c index 1cedb45ba497..cf7cea77dabc 100644 --- a/drivers/input/tablet/wacom_serial4.c +++ b/drivers/input/tablet/wacom_serial4.c @@ -521,7 +521,7 @@ static int wacom_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); + wacom = kzalloc(sizeof(*wacom), GFP_KERNEL); input_dev = input_allocate_device(); if (!wacom || !input_dev) goto free_device; diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c index 9711ced180b8..e105ce71a920 100644 --- a/drivers/input/tests/input_test.c +++ b/drivers/input/tests/input_test.c @@ -179,4 +179,5 @@ static struct kunit_suite input_test_suite = { kunit_test_suite(input_test_suite); MODULE_AUTHOR("Javier Martinez Canillas "); +MODULE_DESCRIPTION("KUnit test for the input core"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 4d13db13b9e5..4247283c7271 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -138,6 +138,7 @@ struct ads7846 { void *filter_data; int (*get_pendown_state)(void); struct gpio_desc *gpio_pendown; + struct gpio_desc *gpio_hsync; void (*wait_for_sync)(void); }; @@ -634,10 +635,6 @@ ATTRIBUTE_GROUPS(ads784x); /*--------------------------------------------------------------------------*/ -static void null_wait_for_sync(void) -{ -} - static int ads7846_debounce_filter(void *ads, int data_idx, int *val) { struct ads7846 *ts = ads; @@ -790,6 +787,28 @@ static int ads7846_filter(struct ads7846 *ts) return 0; } +static void ads7846_wait_for_hsync(struct ads7846 *ts) +{ + if (ts->wait_for_sync) { + ts->wait_for_sync(); + return; + } + + if (!ts->gpio_hsync) + return; + + /* + * Wait for HSYNC to assert the line should be flagged + * as active low so here we are waiting for it to assert + */ + while (!gpiod_get_value(ts->gpio_hsync)) + cpu_relax(); + + /* Then we wait for it do de-assert */ + while (gpiod_get_value(ts->gpio_hsync)) + cpu_relax(); +} + static void ads7846_read_state(struct ads7846 *ts) { struct ads7846_packet *packet = ts->packet; @@ -800,7 +819,7 @@ static void ads7846_read_state(struct ads7846 *ts) packet->last_cmd_idx = 0; while (true) { - ts->wait_for_sync(); + ads7846_wait_for_hsync(ts); m = &ts->msg[msg_idx]; error = spi_sync(ts->spi, m); @@ -1268,7 +1287,11 @@ static int ads7846_probe(struct spi_device *spi) ts->penirq_recheck_delay_usecs = pdata->penirq_recheck_delay_usecs; - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; + ts->wait_for_sync = pdata->wait_for_sync; + + ts->gpio_hsync = devm_gpiod_get_optional(dev, "ti,hsync", GPIOD_IN); + if (IS_ERR(ts->gpio_hsync)) + return PTR_ERR(ts->gpio_hsync); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 8a606bd441ae..cfc92157701f 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3069,9 +3069,7 @@ static struct attribute *mxt_attrs[] = { NULL }; -static const struct attribute_group mxt_attr_group = { - .attrs = mxt_attrs, -}; +ATTRIBUTE_GROUPS(mxt); static void mxt_start(struct mxt_data *data) { @@ -3348,18 +3346,8 @@ static int mxt_probe(struct i2c_client *client) if (error) goto err_disable_regulators; - error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); - if (error) { - dev_err(&client->dev, "Failure %d creating sysfs group\n", - error); - goto err_free_object; - } - return 0; -err_free_object: - mxt_free_input_device(data); - mxt_free_object_table(data); err_disable_regulators: regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); @@ -3371,7 +3359,6 @@ static void mxt_remove(struct i2c_client *client) struct mxt_data *data = i2c_get_clientdata(client); disable_irq(data->irq); - sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); mxt_free_input_device(data); mxt_free_object_table(data); regulator_bulk_disable(ARRAY_SIZE(data->regulators), @@ -3455,6 +3442,7 @@ MODULE_DEVICE_TABLE(i2c, mxt_id); static struct i2c_driver mxt_driver = { .driver = { .name = "atmel_mxt_ts", + .dev_groups = mxt_groups, .of_match_table = mxt_of_match, .acpi_match_table = ACPI_PTR(mxt_acpi_id), .pm = pm_sleep_ptr(&mxt_pm_ops), diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c index 1f0b6d6f48e2..7e752fb9fad7 100644 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ b/drivers/input/touchscreen/cyttsp_i2c_common.c @@ -81,5 +81,6 @@ int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data); +MODULE_DESCRIPTION("Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c index d71690ce6463..52e0e834e76f 100644 --- a/drivers/input/touchscreen/da9052_tsi.c +++ b/drivers/input/touchscreen/da9052_tsi.c @@ -232,7 +232,7 @@ static int da9052_ts_probe(struct platform_device *pdev) if (!da9052) return -EINVAL; - tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); + tsi = kzalloc(sizeof(*tsi), GFP_KERNEL); input_dev = input_allocate_device(); if (!tsi || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index dc07fca7c5ed..fe626a226b85 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c @@ -110,7 +110,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL); + pdynapro = kzalloc(sizeof(*pdynapro), GFP_KERNEL); input_dev = input_allocate_device(); if (!pdynapro || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 06ec0f2e18ae..42f99e57fbb7 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -1496,6 +1496,7 @@ static const struct of_device_id edt_ft5x06_of_match[] = { { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data }, { .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data }, + { .compatible = "focaltech,ft5426", .data = &edt_ft5506_data }, { .compatible = "focaltech,ft5452", .data = &edt_ft5452_data }, /* Note focaltech vendor prefix for compatibility with ft6236.c */ { .compatible = "focaltech,ft6236", .data = &edt_ft6236_data }, diff --git a/drivers/input/touchscreen/egalax_ts_serial.c b/drivers/input/touchscreen/egalax_ts_serial.c index 375922d3a6d1..07a4aa1c19bb 100644 --- a/drivers/input/touchscreen/egalax_ts_serial.c +++ b/drivers/input/touchscreen/egalax_ts_serial.c @@ -99,7 +99,7 @@ static int egalax_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int error; - egalax = kzalloc(sizeof(struct egalax), GFP_KERNEL); + egalax = kzalloc(sizeof(*egalax), GFP_KERNEL); input_dev = input_allocate_device(); if (!egalax || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c index ab8159e1c99d..46a0611fac82 100644 --- a/drivers/input/touchscreen/ektf2127.c +++ b/drivers/input/touchscreen/ektf2127.c @@ -13,6 +13,7 @@ * Hans de Goede */ +#include #include #include #include @@ -46,6 +47,11 @@ struct ektf2127_ts { struct input_dev *input; struct gpio_desc *power_gpios; struct touchscreen_properties prop; + int status_shift; +}; + +struct ektf2127_i2c_chip_data { + int status_shift; }; static void ektf2127_parse_coordinates(const u8 *buf, unsigned int touch_count, @@ -112,8 +118,8 @@ static void ektf2127_report2_contact(struct ektf2127_ts *ts, int slot, static void ektf2127_report2_event(struct ektf2127_ts *ts, const u8 *buf) { - ektf2127_report2_contact(ts, 0, &buf[1], !!(buf[7] & 2)); - ektf2127_report2_contact(ts, 1, &buf[4], !!(buf[7] & 4)); + ektf2127_report2_contact(ts, 0, &buf[1], !!(buf[7] & BIT(ts->status_shift))); + ektf2127_report2_contact(ts, 1, &buf[4], !!(buf[7] & BIT(ts->status_shift + 1))); input_mt_sync_frame(ts->input); input_sync(ts->input); @@ -247,6 +253,7 @@ static int ektf2127_query_dimension(struct i2c_client *client, bool width) static int ektf2127_probe(struct i2c_client *client) { struct device *dev = &client->dev; + const struct ektf2127_i2c_chip_data *chip_data; struct ektf2127_ts *ts; struct input_dev *input; u8 buf[4]; @@ -303,6 +310,13 @@ static int ektf2127_probe(struct i2c_client *client) return error; ts->input = input; + + chip_data = i2c_get_match_data(client); + if (!chip_data) + return dev_err_probe(&client->dev, -EINVAL, "missing chip data\n"); + + ts->status_shift = chip_data->status_shift; + input_set_drvdata(input, ts); error = devm_request_threaded_irq(dev, client->irq, @@ -325,18 +339,28 @@ static int ektf2127_probe(struct i2c_client *client) return 0; } +static const struct ektf2127_i2c_chip_data ektf2127_data = { + .status_shift = 1, +}; + +static const struct ektf2127_i2c_chip_data ektf2232_data = { + .status_shift = 0, +}; + #ifdef CONFIG_OF static const struct of_device_id ektf2127_of_match[] = { - { .compatible = "elan,ektf2127" }, - { .compatible = "elan,ektf2132" }, + { .compatible = "elan,ektf2127", .data = &ektf2127_data}, + { .compatible = "elan,ektf2132", .data = &ektf2127_data}, + { .compatible = "elan,ektf2232", .data = &ektf2232_data}, {} }; MODULE_DEVICE_TABLE(of, ektf2127_of_match); #endif static const struct i2c_device_id ektf2127_i2c_id[] = { - { "ektf2127" }, - { "ektf2132" }, + { .name = "ektf2127", .driver_data = (long)&ektf2127_data }, + { .name = "ektf2132", .driver_data = (long)&ektf2127_data }, + { .name = "ektf2232", .driver_data = (long)&ektf2232_data }, {} }; MODULE_DEVICE_TABLE(i2c, ektf2127_i2c_id); diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 96173232e53f..eb883db55420 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -307,7 +307,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - elo = kzalloc(sizeof(struct elo), GFP_KERNEL); + elo = kzalloc(sizeof(*elo), GFP_KERNEL); input_dev = input_allocate_device(); if (!elo || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index a4030cc9ff60..2e77cfb63f32 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -53,6 +53,7 @@ enum eeti_dev_id { EETI_EXC3000, EETI_EXC80H60, EETI_EXC80H84, + EETI_EXC81W32, }; static struct eeti_dev_info exc3000_info[] = { @@ -68,6 +69,10 @@ static struct eeti_dev_info exc3000_info[] = { .name = "EETI EXC80H84 Touch Screen", .max_xy = SZ_16K - 1, }, + [EETI_EXC81W32] = { + .name = "EETI EXC81W32 Touch Screen", + .max_xy = SZ_16K - 1, + }, }; struct exc3000_data { @@ -441,6 +446,7 @@ static const struct i2c_device_id exc3000_id[] = { { "exc3000", EETI_EXC3000 }, { "exc80h60", EETI_EXC80H60 }, { "exc80h84", EETI_EXC80H84 }, + { "exc81w32", EETI_EXC81W32 }, { } }; MODULE_DEVICE_TABLE(i2c, exc3000_id); @@ -450,6 +456,7 @@ static const struct of_device_id exc3000_of_match[] = { { .compatible = "eeti,exc3000", .data = &exc3000_info[EETI_EXC3000] }, { .compatible = "eeti,exc80h60", .data = &exc3000_info[EETI_EXC80H60] }, { .compatible = "eeti,exc80h84", .data = &exc3000_info[EETI_EXC80H84] }, + { .compatible = "eeti,exc81w32", .data = &exc3000_info[EETI_EXC81W32] }, { } }; MODULE_DEVICE_TABLE(of, exc3000_of_match); diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c index 60a7246c5157..a32708652d10 100644 --- a/drivers/input/touchscreen/fsl-imx25-tcq.c +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c @@ -38,7 +38,7 @@ struct mx25_tcq_priv { struct device *dev; }; -static struct regmap_config mx25_tcq_regconfig = { +static const struct regmap_config mx25_tcq_regconfig = { .fast_io = true, .max_register = 0x5c, .reg_bits = 32, diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index 3b0b8fccc3f0..1a3e14ea2e08 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c @@ -99,7 +99,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL); + fujitsu = kzalloc(sizeof(*fujitsu), GFP_KERNEL); input_dev = input_allocate_device(); if (!fujitsu || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/goodix_berlin_spi.c b/drivers/input/touchscreen/goodix_berlin_spi.c index 4cc557da048a..82774a412956 100644 --- a/drivers/input/touchscreen/goodix_berlin_spi.c +++ b/drivers/input/touchscreen/goodix_berlin_spi.c @@ -36,13 +36,14 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, struct spi_transfer xfers; struct spi_message spi_msg; const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */ - u8 *buf; int error; if (reg_size != GOODIX_BERLIN_REGISTER_WIDTH) return -EINVAL; - buf = kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size, GFP_KERNEL); + u8 *buf __free(kfree) = + kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size, + GFP_KERNEL); if (!buf) return -ENOMEM; @@ -62,12 +63,12 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, spi_message_add_tail(&xfers, &spi_msg); error = spi_sync(spi, &spi_msg); - if (error < 0) + if (error < 0) { dev_err(&spi->dev, "spi transfer error, %d", error); - else - memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size); + return error; + } - kfree(buf); + memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size); return error; } @@ -79,10 +80,10 @@ static int goodix_berlin_spi_write(void *context, const void *data, struct spi_transfer xfers; struct spi_message spi_msg; const u32 *reg = data; /* reg is stored as native u32 at start of buffer */ - u8 *buf; int error; - buf = kzalloc(GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL); + u8 *buf __free(kfree) = + kzalloc(GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -100,11 +101,12 @@ static int goodix_berlin_spi_write(void *context, const void *data, spi_message_add_tail(&xfers, &spi_msg); error = spi_sync(spi, &spi_msg); - if (error < 0) + if (error < 0) { dev_err(&spi->dev, "spi transfer error, %d", error); + return error; + } - kfree(buf); - return error; + return 0; } static const struct regmap_config goodix_berlin_spi_regmap_conf = { diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 5a5f9da73fa1..dbf92fb02f80 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -97,7 +97,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL); + gunze = kzalloc(sizeof(*gunze), GFP_KERNEL); input_dev = input_allocate_device(); if (!gunze || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index 5c4d877564ee..dc0a2482ddd6 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c @@ -109,7 +109,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL); + phampshire = kzalloc(sizeof(*phampshire), GFP_KERNEL); input_dev = input_allocate_device(); if (!phampshire || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c index bafabd06dabc..9ed3bccde4ac 100644 --- a/drivers/input/touchscreen/himax_hx83112b.c +++ b/drivers/input/touchscreen/himax_hx83112b.c @@ -4,6 +4,9 @@ * * Copyright (C) 2022 Job Noorman * + * HX83100A support + * Copyright (C) 2024 Felix Kaechele + * * This code is based on "Himax Android Driver Sample Code for QCT platform": * * Copyright (C) 2017 Himax Corporation. @@ -20,16 +23,22 @@ #include #include -#define HIMAX_ID_83112B 0x83112b - #define HIMAX_MAX_POINTS 10 -#define HIMAX_REG_CFG_SET_ADDR 0x00 -#define HIMAX_REG_CFG_INIT_READ 0x0c -#define HIMAX_REG_CFG_READ_VALUE 0x08 -#define HIMAX_REG_READ_EVENT 0x30 +#define HIMAX_AHB_ADDR_BYTE_0 0x00 +#define HIMAX_AHB_ADDR_RDATA_BYTE_0 0x08 +#define HIMAX_AHB_ADDR_ACCESS_DIRECTION 0x0c +#define HIMAX_AHB_ADDR_INCR4 0x0d +#define HIMAX_AHB_ADDR_CONTI 0x13 +#define HIMAX_AHB_ADDR_EVENT_STACK 0x30 -#define HIMAX_CFG_PRODUCT_ID 0x900000d0 +#define HIMAX_AHB_CMD_ACCESS_DIRECTION_READ 0x00 +#define HIMAX_AHB_CMD_INCR4 0x10 +#define HIMAX_AHB_CMD_CONTI 0x31 + +#define HIMAX_REG_ADDR_ICID 0x900000d0 + +#define HX83100A_REG_FW_EVENT_STACK 0x90060000 #define HIMAX_INVALID_COORD 0xffff @@ -49,7 +58,16 @@ struct himax_event { static_assert(sizeof(struct himax_event) == 56); +struct himax_ts_data; +struct himax_chip { + u32 id; + int (*check_id)(struct himax_ts_data *ts); + int (*read_events)(struct himax_ts_data *ts, struct himax_event *event, + size_t length); +}; + struct himax_ts_data { + const struct himax_chip *chip; struct gpio_desc *gpiod_rst; struct input_dev *input_dev; struct i2c_client *client; @@ -63,19 +81,60 @@ static const struct regmap_config himax_regmap_config = { .val_format_endian = REGMAP_ENDIAN_LITTLE, }; -static int himax_read_config(struct himax_ts_data *ts, u32 address, u32 *dst) +static int himax_bus_enable_burst(struct himax_ts_data *ts) { int error; - error = regmap_write(ts->regmap, HIMAX_REG_CFG_SET_ADDR, address); + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_CONTI, + HIMAX_AHB_CMD_CONTI); if (error) return error; - error = regmap_write(ts->regmap, HIMAX_REG_CFG_INIT_READ, 0x0); + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_INCR4, + HIMAX_AHB_CMD_INCR4); if (error) return error; - error = regmap_read(ts->regmap, HIMAX_REG_CFG_READ_VALUE, dst); + return 0; +} + +static int himax_bus_read(struct himax_ts_data *ts, u32 address, void *dst, + size_t length) +{ + int error; + + if (length > 4) { + error = himax_bus_enable_burst(ts); + if (error) + return error; + } + + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_BYTE_0, address); + if (error) + return error; + + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_ACCESS_DIRECTION, + HIMAX_AHB_CMD_ACCESS_DIRECTION_READ); + if (error) + return error; + + if (length > 4) + error = regmap_noinc_read(ts->regmap, HIMAX_AHB_ADDR_RDATA_BYTE_0, + dst, length); + else + error = regmap_read(ts->regmap, HIMAX_AHB_ADDR_RDATA_BYTE_0, + dst); + if (error) + return error; + + return 0; +} + +static int himax_read_mcu(struct himax_ts_data *ts, u32 address, u32 *dst) +{ + int error; + + error = himax_bus_read(ts, address, dst, sizeof(dst)); if (error) return error; @@ -101,7 +160,7 @@ static int himax_read_product_id(struct himax_ts_data *ts, u32 *product_id) { int error; - error = himax_read_config(ts, HIMAX_CFG_PRODUCT_ID, product_id); + error = himax_read_mcu(ts, HIMAX_REG_ADDR_ICID, product_id); if (error) return error; @@ -120,15 +179,12 @@ static int himax_check_product_id(struct himax_ts_data *ts) dev_dbg(&ts->client->dev, "Product id: %x\n", product_id); - switch (product_id) { - case HIMAX_ID_83112B: + if (product_id == ts->chip->id) return 0; - default: - dev_err(&ts->client->dev, - "Unknown product id: %x\n", product_id); - return -EINVAL; - } + dev_err(&ts->client->dev, "Unknown product id: %x\n", + product_id); + return -EINVAL; } static int himax_input_register(struct himax_ts_data *ts) @@ -230,13 +286,25 @@ static bool himax_verify_checksum(struct himax_ts_data *ts, return true; } +static int himax_read_events(struct himax_ts_data *ts, + struct himax_event *event, size_t length) +{ + return regmap_raw_read(ts->regmap, HIMAX_AHB_ADDR_EVENT_STACK, event, + length); +} + +static int hx83100a_read_events(struct himax_ts_data *ts, + struct himax_event *event, size_t length) +{ + return himax_bus_read(ts, HX83100A_REG_FW_EVENT_STACK, event, length); +}; + static int himax_handle_input(struct himax_ts_data *ts) { int error; struct himax_event event; - error = regmap_raw_read(ts->regmap, HIMAX_REG_READ_EVENT, &event, - sizeof(event)); + error = ts->chip->read_events(ts, &event, sizeof(event)); if (error) { dev_err(&ts->client->dev, "Failed to read input event: %d\n", error); @@ -282,6 +350,7 @@ static int himax_probe(struct i2c_client *client) i2c_set_clientdata(client, ts); ts->client = client; + ts->chip = i2c_get_match_data(client); ts->regmap = devm_regmap_init_i2c(client, &himax_regmap_config); error = PTR_ERR_OR_ZERO(ts->regmap); @@ -299,9 +368,11 @@ static int himax_probe(struct i2c_client *client) himax_reset(ts); - error = himax_check_product_id(ts); - if (error) - return error; + if (ts->chip->check_id) { + error = himax_check_product_id(ts); + if (error) + return error; + } error = himax_input_register(ts); if (error) @@ -334,15 +405,27 @@ static int himax_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(himax_pm_ops, himax_suspend, himax_resume); +static const struct himax_chip hx83100a_chip = { + .read_events = hx83100a_read_events, +}; + +static const struct himax_chip hx83112b_chip = { + .id = 0x83112b, + .check_id = himax_check_product_id, + .read_events = himax_read_events, +}; + static const struct i2c_device_id himax_ts_id[] = { - { "hx83112b" }, + { "hx83100a", (kernel_ulong_t)&hx83100a_chip }, + { "hx83112b", (kernel_ulong_t)&hx83112b_chip }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, himax_ts_id); #ifdef CONFIG_OF static const struct of_device_id himax_of_match[] = { - { .compatible = "himax,hx83112b" }, + { .compatible = "himax,hx83100a", .data = &hx83100a_chip }, + { .compatible = "himax,hx83112b", .data = &hx83112b_chip }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, himax_of_match); diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 79bdb2b10949..4573844c3395 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -582,14 +582,12 @@ static ssize_t ili210x_calibrate(struct device *dev, } static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate); -static int ili251x_firmware_to_buffer(const struct firmware *fw, - u8 **buf, u16 *ac_end, u16 *df_end) +static const u8 *ili251x_firmware_to_buffer(const struct firmware *fw, + u16 *ac_end, u16 *df_end) { const struct ihex_binrec *rec; u32 fw_addr, fw_last_addr = 0; u16 fw_len; - u8 *fw_buf; - int error; /* * The firmware ihex blob can never be bigger than 64 kiB, so make this @@ -597,9 +595,9 @@ static int ili251x_firmware_to_buffer(const struct firmware *fw, * once, copy them all into this buffer at the right locations, and then * do all operations on this linear buffer. */ - fw_buf = kzalloc(SZ_64K, GFP_KERNEL); + u8* fw_buf __free(kvfree) = kvmalloc(SZ_64K, GFP_KERNEL); if (!fw_buf) - return -ENOMEM; + return ERR_PTR(-ENOMEM); rec = (const struct ihex_binrec *)fw->data; while (rec) { @@ -607,10 +605,8 @@ static int ili251x_firmware_to_buffer(const struct firmware *fw, fw_len = be16_to_cpu(rec->len); /* The last 32 Byte firmware block can be 0xffe0 */ - if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) { - error = -EFBIG; - goto err_big; - } + if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) + return ERR_PTR(-EFBIG); /* Find the last address before DF start address, that is AC end */ if (fw_addr == 0xf000) @@ -623,12 +619,8 @@ static int ili251x_firmware_to_buffer(const struct firmware *fw, /* DF end address is the last address in the firmware blob */ *df_end = fw_addr + fw_len; - *buf = fw_buf; - return 0; -err_big: - kfree(fw_buf); - return error; + return_ptr(fw_buf); } /* Switch mode between Application and BootLoader */ @@ -691,7 +683,7 @@ static int ili251x_firmware_busy(struct i2c_client *client) return 0; } -static int ili251x_firmware_write_to_ic(struct device *dev, u8 *fwbuf, +static int ili251x_firmware_write_to_ic(struct device *dev, const u8 *fwbuf, u16 start, u16 end, u8 dataflash) { struct i2c_client *client = to_i2c_client(dev); @@ -776,47 +768,17 @@ static void ili210x_hardware_reset(struct gpio_desc *reset_gpio) msleep(300); } -static ssize_t ili210x_firmware_update_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int ili210x_do_firmware_update(struct ili210x *priv, + const u8 *fwbuf, u16 ac_end, u16 df_end) { - struct i2c_client *client = to_i2c_client(dev); - struct ili210x *priv = i2c_get_clientdata(client); - const char *fwname = ILI251X_FW_FILENAME; - const struct firmware *fw; - u16 ac_end, df_end; - u8 *fwbuf; + struct i2c_client *client = priv->client; + struct device *dev = &client->dev; int error; int i; - error = request_ihex_firmware(&fw, fwname, dev); - if (error) { - dev_err(dev, "Failed to request firmware %s, error=%d\n", - fwname, error); - return error; - } - - error = ili251x_firmware_to_buffer(fw, &fwbuf, &ac_end, &df_end); - release_firmware(fw); - if (error) - return error; - - /* - * Disable touchscreen IRQ, so that we would not get spurious touch - * interrupt during firmware update, and so that the IRQ handler won't - * trigger and interfere with the firmware update. There is no bit in - * the touch controller to disable the IRQs during update, so we have - * to do it this way here. - */ - disable_irq(client->irq); - - dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname); - - ili210x_hardware_reset(priv->reset_gpio); - error = ili251x_firmware_reset(client); if (error) - goto exit; + return error; /* This may not succeed on first try, so re-try a few times. */ for (i = 0; i < 5; i++) { @@ -826,7 +788,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, } if (error) - goto exit; + return error; dev_dbg(dev, "IC is now in BootLoader mode\n"); @@ -835,7 +797,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, error = ili251x_firmware_write_to_ic(dev, fwbuf, 0xf000, df_end, 1); if (error) { dev_err(dev, "DF firmware update failed, error=%d\n", error); - goto exit; + return error; } dev_dbg(dev, "DataFlash firmware written\n"); @@ -843,7 +805,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, error = ili251x_firmware_write_to_ic(dev, fwbuf, 0x2000, ac_end, 0); if (error) { dev_err(dev, "AC firmware update failed, error=%d\n", error); - goto exit; + return error; } dev_dbg(dev, "Application firmware written\n"); @@ -856,22 +818,61 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, } if (error) - goto exit; + return error; dev_dbg(dev, "IC is now in Application mode\n"); error = ili251x_firmware_update_cached_state(dev); if (error) - goto exit; + return error; - error = count; + return 0; +} -exit: - ili210x_hardware_reset(priv->reset_gpio); - dev_dbg(dev, "Firmware update ended, error=%i\n", error); - enable_irq(client->irq); - kfree(fwbuf); - return error; +static ssize_t ili210x_firmware_update_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ili210x *priv = i2c_get_clientdata(client); + const char *fwname = ILI251X_FW_FILENAME; + u16 ac_end, df_end; + int error; + + const struct firmware *fw __free(firmware) = NULL; + error = request_ihex_firmware(&fw, fwname, dev); + if (error) { + dev_err(dev, "Failed to request firmware %s, error=%d\n", + fwname, error); + return error; + } + + const u8* fwbuf __free(kvfree) = + ili251x_firmware_to_buffer(fw, &ac_end, &df_end); + error = PTR_ERR_OR_ZERO(fwbuf); + if (error) + return error; + + /* + * Disable touchscreen IRQ, so that we would not get spurious touch + * interrupt during firmware update, and so that the IRQ handler won't + * trigger and interfere with the firmware update. There is no bit in + * the touch controller to disable the IRQs during update, so we have + * to do it this way here. + */ + scoped_guard(disable_irq, &client->irq) { + dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname); + + ili210x_hardware_reset(priv->reset_gpio); + + error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end); + + ili210x_hardware_reset(priv->reset_gpio); + + dev_dbg(dev, "Firmware update ended, error=%i\n", error); + } + + return error ?: count; } static DEVICE_ATTR(firmware_update, 0200, NULL, ili210x_firmware_update_store); diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c index 074dd6c342ec..aeabf8d057de 100644 --- a/drivers/input/touchscreen/imagis.c +++ b/drivers/input/touchscreen/imagis.c @@ -12,9 +12,17 @@ #include #include -#define IST3032C_WHOAMI 0x32c +#define IST30XX_REG_STATUS 0x20 +#define IST30XX_REG_CHIPID (0x40000000 | IST3038C_DIRECT_ACCESS) + +#define IST30XX_WHOAMI 0x30003000 +#define IST30XXA_WHOAMI 0x300a300a +#define IST30XXB_WHOAMI 0x300b300b +#define IST3038_WHOAMI 0x30383038 + +#define IST3032C_WHOAMI 0x32c +#define IST3038C_WHOAMI 0x38c -#define IST3038B_REG_STATUS 0x20 #define IST3038B_REG_CHIPID 0x30 #define IST3038B_WHOAMI 0x30380b @@ -25,7 +33,6 @@ #define IST3038C_REG_TOUCH_STATUS (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS) #define IST3038C_REG_TOUCH_COORD (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x8) #define IST3038C_REG_INTR_MESSAGE (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x4) -#define IST3038C_WHOAMI 0x38c #define IST3038C_CHIP_ON_DELAY_MS 60 #define IST3038C_I2C_RETRY_COUNT 3 #define IST3038C_MAX_FINGER_NUM 10 @@ -120,12 +127,12 @@ static irqreturn_t imagis_interrupt(int irq, void *dev_id) for (i = 0; i < finger_count; i++) { if (ts->tdata->protocol_b) - error = imagis_i2c_read_reg(ts, - ts->tdata->touch_coord_cmd, &finger_status); - else error = imagis_i2c_read_reg(ts, ts->tdata->touch_coord_cmd + (i * 4), &finger_status); + else + error = imagis_i2c_read_reg(ts, + ts->tdata->touch_coord_cmd, &finger_status); if (error) { dev_err(&ts->client->dev, "failed to read coordinates for finger %d: %d\n", @@ -394,14 +401,22 @@ static const struct imagis_properties imagis_3032c_data = { .whoami_cmd = IST3038C_REG_CHIPID, .whoami_val = IST3032C_WHOAMI, .touch_keys_supported = true, + .protocol_b = true, +}; + +static const struct imagis_properties imagis_3038_data = { + .interrupt_msg_cmd = IST30XX_REG_STATUS, + .touch_coord_cmd = IST30XX_REG_STATUS, + .whoami_cmd = IST30XX_REG_CHIPID, + .whoami_val = IST3038_WHOAMI, + .touch_keys_supported = true, }; static const struct imagis_properties imagis_3038b_data = { - .interrupt_msg_cmd = IST3038B_REG_STATUS, - .touch_coord_cmd = IST3038B_REG_STATUS, + .interrupt_msg_cmd = IST30XX_REG_STATUS, + .touch_coord_cmd = IST30XX_REG_STATUS, .whoami_cmd = IST3038B_REG_CHIPID, .whoami_val = IST3038B_WHOAMI, - .protocol_b = true, }; static const struct imagis_properties imagis_3038c_data = { @@ -409,11 +424,13 @@ static const struct imagis_properties imagis_3038c_data = { .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, .whoami_cmd = IST3038C_REG_CHIPID, .whoami_val = IST3038C_WHOAMI, + .protocol_b = true, }; #ifdef CONFIG_OF static const struct of_device_id imagis_of_match[] = { { .compatible = "imagis,ist3032c", .data = &imagis_3032c_data }, + { .compatible = "imagis,ist3038", .data = &imagis_3038_data }, { .compatible = "imagis,ist3038b", .data = &imagis_3038b_data }, { .compatible = "imagis,ist3038c", .data = &imagis_3038c_data }, { }, diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index 1d7e4c3966ce..82f7ac62a4f2 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c @@ -114,7 +114,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL); + pinexio = kzalloc(sizeof(*pinexio), GFP_KERNEL); input_dev = input_allocate_device(); if (!pinexio || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 28e449eea318..eefae96a2d40 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -128,7 +128,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL); + mtouch = kzalloc(sizeof(*mtouch), GFP_KERNEL); input_dev = input_allocate_device(); if (!mtouch || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index 12abb3b36128..95adede26703 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -199,7 +199,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) int max_x, max_y; int err; - pm = kzalloc(sizeof(struct pm), GFP_KERNEL); + pm = kzalloc(sizeof(*pm), GFP_KERNEL); input_dev = input_allocate_device(); if (!pm || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c index 06fa3a19d266..0e5cc9fbad17 100644 --- a/drivers/input/touchscreen/rohm_bu21023.c +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -643,12 +643,12 @@ static int rohm_ts_load_firmware(struct i2c_client *client, const char *firmware_name) { struct device *dev = &client->dev; - const struct firmware *fw; s32 status; unsigned int offset, len, xfer_len; unsigned int retry = 0; int error, error2; + const struct firmware *fw __free(firmware) = NULL; error = request_firmware(&fw, firmware_name, dev); if (error) { dev_err(dev, "unable to retrieve firmware %s: %d\n", @@ -722,18 +722,39 @@ static int rohm_ts_load_firmware(struct i2c_client *client, out: error2 = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL); - release_firmware(fw); - return error ? error : error2; } +static int rohm_ts_update_setting(struct rohm_ts_data *ts, + unsigned int setting_bit, bool on) +{ + int error; + + scoped_cond_guard(mutex_intr, return -EINTR, &ts->input->mutex) { + if (on) + ts->setup2 |= setting_bit; + else + ts->setup2 &= ~setting_bit; + + if (ts->initialized) { + error = i2c_smbus_write_byte_data(ts->client, + COMMON_SETUP2, + ts->setup2); + if (error) + return error; + } + } + + return 0; +} + static ssize_t swap_xy_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct rohm_ts_data *ts = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", !!(ts->setup2 & SWAP_XY)); + return sysfs_emit(buf, "%d\n", !!(ts->setup2 & SWAP_XY)); } static ssize_t swap_xy_store(struct device *dev, struct device_attribute *attr, @@ -748,22 +769,8 @@ static ssize_t swap_xy_store(struct device *dev, struct device_attribute *attr, if (error) return error; - error = mutex_lock_interruptible(&ts->input->mutex); - if (error) - return error; - - if (val) - ts->setup2 |= SWAP_XY; - else - ts->setup2 &= ~SWAP_XY; - - if (ts->initialized) - error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2, - ts->setup2); - - mutex_unlock(&ts->input->mutex); - - return error ? error : count; + error = rohm_ts_update_setting(ts, SWAP_XY, val); + return error ?: count; } static ssize_t inv_x_show(struct device *dev, struct device_attribute *attr, @@ -772,7 +779,7 @@ static ssize_t inv_x_show(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct rohm_ts_data *ts = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", !!(ts->setup2 & INV_X)); + return sysfs_emit(buf, "%d\n", !!(ts->setup2 & INV_X)); } static ssize_t inv_x_store(struct device *dev, struct device_attribute *attr, @@ -787,22 +794,8 @@ static ssize_t inv_x_store(struct device *dev, struct device_attribute *attr, if (error) return error; - error = mutex_lock_interruptible(&ts->input->mutex); - if (error) - return error; - - if (val) - ts->setup2 |= INV_X; - else - ts->setup2 &= ~INV_X; - - if (ts->initialized) - error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2, - ts->setup2); - - mutex_unlock(&ts->input->mutex); - - return error ? error : count; + error = rohm_ts_update_setting(ts, INV_X, val); + return error ?: count; } static ssize_t inv_y_show(struct device *dev, struct device_attribute *attr, @@ -811,7 +804,7 @@ static ssize_t inv_y_show(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct rohm_ts_data *ts = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", !!(ts->setup2 & INV_Y)); + return sysfs_emit(buf, "%d\n", !!(ts->setup2 & INV_Y)); } static ssize_t inv_y_store(struct device *dev, struct device_attribute *attr, @@ -826,22 +819,8 @@ static ssize_t inv_y_store(struct device *dev, struct device_attribute *attr, if (error) return error; - error = mutex_lock_interruptible(&ts->input->mutex); - if (error) - return error; - - if (val) - ts->setup2 |= INV_Y; - else - ts->setup2 &= ~INV_Y; - - if (ts->initialized) - error = i2c_smbus_write_byte_data(client, COMMON_SETUP2, - ts->setup2); - - mutex_unlock(&ts->input->mutex); - - return error ? error : count; + error = rohm_ts_update_setting(ts, INV_Y, val); + return error ?: count; } static DEVICE_ATTR_RW(swap_xy); @@ -861,7 +840,7 @@ static int rohm_ts_device_init(struct i2c_client *client, u8 setup2) struct device *dev = &client->dev; int error; - disable_irq(client->irq); + guard(disable_irq)(&client->irq); /* * Wait 200usec for reset @@ -1036,10 +1015,10 @@ static int rohm_ts_device_init(struct i2c_client *client, u8 setup2) /* controller CPU power on */ error = i2c_smbus_write_byte_data(client, SYSTEM, ANALOG_POWER_ON | CPU_POWER_ON); + if (error) + return error; - enable_irq(client->irq); - - return error; + return 0; } static int rohm_ts_power_off(struct i2c_client *client) diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 5f2cf8881e72..8365a2ac6fce 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -672,7 +672,7 @@ static int sur40_probe(struct usb_interface *interface, return -ENODEV; /* Allocate memory for our device state and initialize it. */ - sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL); + sur40 = kzalloc(sizeof(*sur40), GFP_KERNEL); if (!sur40) return -ENOMEM; diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index fb49687da405..c2718350815c 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c @@ -139,7 +139,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - touchit213 = kzalloc(sizeof(struct touchit213), GFP_KERNEL); + touchit213 = kzalloc(sizeof(*touchit213), GFP_KERNEL); input_dev = input_allocate_device(); if (!touchit213 || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 3cd58a13e44f..30ba97bd00a1 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -102,7 +102,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - tr = kzalloc(sizeof(struct tr), GFP_KERNEL); + tr = kzalloc(sizeof(*tr), GFP_KERNEL); input_dev = input_allocate_device(); if (!tr || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index bde3c6ee3c60..fbd72789ea80 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -109,7 +109,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - tw = kzalloc(sizeof(struct tw), GFP_KERNEL); + tw = kzalloc(sizeof(*tw), GFP_KERNEL); input_dev = input_allocate_device(); if (!tw || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 139577021413..9f485cf57a72 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -83,7 +83,7 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int error; - ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL); + ptsc = kzalloc(sizeof(*ptsc), GFP_KERNEL); input_dev = input_allocate_device(); if (!ptsc || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 60354ebc7242..dd6b12c6dc58 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -505,12 +505,14 @@ free: static int mtouch_alloc(struct usbtouch_usb *usbtouch) { + struct mtouch_priv *priv; int ret; - usbtouch->priv = kmalloc(sizeof(struct mtouch_priv), GFP_KERNEL); - if (!usbtouch->priv) + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; + usbtouch->priv = priv; ret = sysfs_create_group(&usbtouch->interface->dev.kobj, &mtouch_attr_group); if (ret) { @@ -924,12 +926,11 @@ static int nexio_alloc(struct usbtouch_usb *usbtouch) struct nexio_priv *priv; int ret = -ENOMEM; - usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); - if (!usbtouch->priv) + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) goto out_buf; - priv = usbtouch->priv; - + usbtouch->priv = priv; priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), GFP_KERNEL); if (!priv->ack_buf) @@ -1661,7 +1662,7 @@ static int usbtouch_probe(struct usb_interface *intf, if (!endpoint) return -ENXIO; - usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); + usbtouch = kzalloc(sizeof(*usbtouch), GFP_KERNEL); input_dev = input_allocate_device(); if (!usbtouch || !input_dev) goto out_free; diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 928c5ee3ac36..ed2ca8a689d5 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -380,30 +380,28 @@ static int w8001_open(struct input_dev *dev) struct w8001 *w8001 = input_get_drvdata(dev); int err; - err = mutex_lock_interruptible(&w8001->mutex); - if (err) - return err; + scoped_guard(mutex_intr, &w8001->mutex) { + if (w8001->open_count == 0) { + err = w8001_command(w8001, W8001_CMD_START, false); + if (err) + return err; + } - if (w8001->open_count++ == 0) { - err = w8001_command(w8001, W8001_CMD_START, false); - if (err) - w8001->open_count--; + w8001->open_count++; + return 0; } - mutex_unlock(&w8001->mutex); - return err; + return -EINTR; } static void w8001_close(struct input_dev *dev) { struct w8001 *w8001 = input_get_drvdata(dev); - mutex_lock(&w8001->mutex); + guard(mutex)(&w8001->mutex); if (--w8001->open_count == 0) w8001_command(w8001, W8001_CMD_STOP, false); - - mutex_unlock(&w8001->mutex); } static int w8001_detect(struct w8001 *w8001) @@ -595,10 +593,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) struct w8001 *w8001; struct input_dev *input_dev_pen; struct input_dev *input_dev_touch; - char basename[64]; + char basename[64] = "Wacom Serial"; int err, err_pen, err_touch; - w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL); + w8001 = kzalloc(sizeof(*w8001), GFP_KERNEL); input_dev_pen = input_allocate_device(); input_dev_touch = input_allocate_device(); if (!w8001 || !input_dev_pen || !input_dev_touch) { @@ -625,8 +623,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) /* For backwards-compatibility we compose the basename based on * capabilities and then just append the tool type */ - strscpy(basename, "Wacom Serial", sizeof(basename)); - err_pen = w8001_setup_pen(w8001, basename, sizeof(basename)); err_touch = w8001_setup_touch(w8001, basename, sizeof(basename)); if (err_pen && err_touch) { @@ -635,8 +631,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) } if (!err_pen) { - strscpy(w8001->pen_name, basename, sizeof(w8001->pen_name)); - strlcat(w8001->pen_name, " Pen", sizeof(w8001->pen_name)); + snprintf(w8001->pen_name, sizeof(w8001->pen_name), + "%s Pen", basename); input_dev_pen->name = w8001->pen_name; w8001_set_devdata(input_dev_pen, w8001, serio); @@ -651,9 +647,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) } if (!err_touch) { - strscpy(w8001->touch_name, basename, sizeof(w8001->touch_name)); - strlcat(w8001->touch_name, " Finger", - sizeof(w8001->touch_name)); + snprintf(w8001->touch_name, sizeof(w8001->touch_name), + "%s Finger", basename); input_dev_touch->name = w8001->touch_name; w8001_set_devdata(input_dev_touch, w8001, serio); diff --git a/drivers/input/vivaldi-fmap.c b/drivers/input/vivaldi-fmap.c index 0d29ec014e2f..978949eba9eb 100644 --- a/drivers/input/vivaldi-fmap.c +++ b/drivers/input/vivaldi-fmap.c @@ -36,4 +36,5 @@ ssize_t vivaldi_function_row_physmap_show(const struct vivaldi_data *data, } EXPORT_SYMBOL_GPL(vivaldi_function_row_physmap_show); +MODULE_DESCRIPTION("Helpers for ChromeOS Vivaldi keyboard function row mapping"); MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig index 5faa8d2aecff..f2e49bd97d31 100644 --- a/drivers/interconnect/Kconfig +++ b/drivers/interconnect/Kconfig @@ -12,6 +12,7 @@ menuconfig INTERCONNECT if INTERCONNECT source "drivers/interconnect/imx/Kconfig" +source "drivers/interconnect/mediatek/Kconfig" source "drivers/interconnect/qcom/Kconfig" source "drivers/interconnect/samsung/Kconfig" diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index d0888babb9a1..b0a9a6753b9d 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -5,6 +5,7 @@ icc-core-objs := core.o bulk.o debugfs-client.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_IMX) += imx/ +obj-$(CONFIG_INTERCONNECT_MTK) += mediatek/ obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ obj-$(CONFIG_INTERCONNECT_SAMSUNG) += samsung/ diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c index 979ed610f704..9511f80cf041 100644 --- a/drivers/interconnect/imx/imx.c +++ b/drivers/interconnect/imx/imx.c @@ -334,4 +334,5 @@ void imx_icc_unregister(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(imx_icc_unregister); +MODULE_DESCRIPTION("Interconnect framework driver for i.MX SoC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/imx/imx8mm.c b/drivers/interconnect/imx/imx8mm.c index 8c40f4182263..a36aaaf106ae 100644 --- a/drivers/interconnect/imx/imx8mm.c +++ b/drivers/interconnect/imx/imx8mm.c @@ -96,5 +96,6 @@ static struct platform_driver imx8mm_icc_driver = { module_platform_driver(imx8mm_icc_driver); MODULE_AUTHOR("Alexandre Bailon "); +MODULE_DESCRIPTION("Interconnect framework driver for i.MX8MM SoC"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:imx8mm-interconnect"); diff --git a/drivers/interconnect/imx/imx8mn.c b/drivers/interconnect/imx/imx8mn.c index fa3d4f97dfa4..2a97c74e875b 100644 --- a/drivers/interconnect/imx/imx8mn.c +++ b/drivers/interconnect/imx/imx8mn.c @@ -86,4 +86,5 @@ static struct platform_driver imx8mn_icc_driver = { module_platform_driver(imx8mn_icc_driver); MODULE_ALIAS("platform:imx8mn-interconnect"); MODULE_AUTHOR("Leonard Crestez "); +MODULE_DESCRIPTION("Interconnect framework driver for i.MX8MN SoC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/imx/imx8mp.c b/drivers/interconnect/imx/imx8mp.c index d218bb47757a..86d4c1517b26 100644 --- a/drivers/interconnect/imx/imx8mp.c +++ b/drivers/interconnect/imx/imx8mp.c @@ -249,5 +249,6 @@ static struct platform_driver imx8mp_icc_driver = { module_platform_driver(imx8mp_icc_driver); MODULE_AUTHOR("Peng Fan "); +MODULE_DESCRIPTION("Interconnect framework driver for i.MX8MP SoC"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:imx8mp-interconnect"); diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c index 8bbd672b346e..f817d24aeefb 100644 --- a/drivers/interconnect/imx/imx8mq.c +++ b/drivers/interconnect/imx/imx8mq.c @@ -97,4 +97,5 @@ static struct platform_driver imx8mq_icc_driver = { module_platform_driver(imx8mq_icc_driver); MODULE_ALIAS("platform:imx8mq-interconnect"); MODULE_AUTHOR("Leonard Crestez "); +MODULE_DESCRIPTION("Interconnect framework driver for i.MX8MQ SoC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/mediatek/Kconfig b/drivers/interconnect/mediatek/Kconfig new file mode 100644 index 000000000000..985c849efac3 --- /dev/null +++ b/drivers/interconnect/mediatek/Kconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config INTERCONNECT_MTK + bool "MediaTek interconnect drivers" + depends on ARCH_MEDIATEK || COMPILE_TEST + help + Support for MediaTek's bus interconnect hardware. + +config INTERCONNECT_MTK_DVFSRC_EMI + tristate "MediaTek DVFSRC EMI interconnect driver" + depends on INTERCONNECT_MTK && MTK_DVFSRC + help + This is a driver for the MediaTek External Memory Interface + interconnect on SoCs equipped with the integrated Dynamic + Voltage Frequency Scaling Resource Collector (DVFSRC) MCU + +config INTERCONNECT_MTK_MT8183 + tristate "MediaTek MT8183 interconnect driver" + depends on INTERCONNECT_MTK_DVFSRC_EMI + help + This is a driver for the MediaTek bus interconnect on MT8183-based + platforms. + +config INTERCONNECT_MTK_MT8195 + tristate "MediaTek MT8195 interconnect driver" + depends on INTERCONNECT_MTK_DVFSRC_EMI + help + This is a driver for the MediaTek bus interconnect on MT8195-based + platforms. diff --git a/drivers/interconnect/mediatek/Makefile b/drivers/interconnect/mediatek/Makefile new file mode 100644 index 000000000000..8e2283a9a5b5 --- /dev/null +++ b/drivers/interconnect/mediatek/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_INTERCONNECT_MTK_DVFSRC_EMI) += icc-emi.o +obj-$(CONFIG_INTERCONNECT_MTK_MT8183) += mt8183.o +obj-$(CONFIG_INTERCONNECT_MTK_MT8195) += mt8195.o diff --git a/drivers/interconnect/mediatek/icc-emi.c b/drivers/interconnect/mediatek/icc-emi.c new file mode 100644 index 000000000000..7da740b5fa8d --- /dev/null +++ b/drivers/interconnect/mediatek/icc-emi.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek External Memory Interface (EMI) Interconnect driver + * + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "icc-emi.h" + +static int mtk_emi_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + struct mtk_icc_node *in = node->data; + + *agg_avg += avg_bw; + *agg_peak = max_t(u32, *agg_peak, peak_bw); + + in->sum_avg = *agg_avg; + in->max_peak = *agg_peak; + + return 0; +} + +static int mtk_emi_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct mtk_icc_node *node = dst->data; + struct device *dev; + int ret; + + if (unlikely(!src->provider)) + return -EINVAL; + + dev = src->provider->dev; + + switch (node->ep) { + case 0: + break; + case 1: + ret = mtk_dvfsrc_send_request(dev, MTK_DVFSRC_CMD_PEAK_BW, node->max_peak); + if (ret) { + dev_err(dev, "Cannot send peak bw request: %d\n", ret); + return ret; + } + + ret = mtk_dvfsrc_send_request(dev, MTK_DVFSRC_CMD_BW, node->sum_avg); + if (ret) { + dev_err(dev, "Cannot send bw request: %d\n", ret); + return ret; + } + break; + case 2: + ret = mtk_dvfsrc_send_request(dev, MTK_DVFSRC_CMD_HRT_BW, node->sum_avg); + if (ret) { + dev_err(dev, "Cannot send HRT bw request: %d\n", ret); + return ret; + } + break; + default: + dev_err(src->provider->dev, "Unknown endpoint %u\n", node->ep); + return -EINVAL; + } + + return 0; +} + +int mtk_emi_icc_probe(struct platform_device *pdev) +{ + const struct mtk_icc_desc *desc; + struct device *dev = &pdev->dev; + struct icc_node *node; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct mtk_icc_node **mnodes; + int i, j, ret; + + desc = of_device_get_match_data(dev); + if (!desc) + return -EINVAL; + + mnodes = desc->nodes; + + provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL); + if (!provider) + return -ENOMEM; + + data = devm_kzalloc(dev, struct_size(data, nodes, desc->num_nodes), GFP_KERNEL); + if (!data) + return -ENOMEM; + + provider->dev = pdev->dev.parent; + provider->set = mtk_emi_icc_set; + provider->aggregate = mtk_emi_icc_aggregate; + provider->xlate = of_icc_xlate_onecell; + INIT_LIST_HEAD(&provider->nodes); + provider->data = data; + + for (i = 0; i < desc->num_nodes; i++) { + if (!mnodes[i]) + continue; + + node = icc_node_create(mnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = mnodes[i]->name; + node->data = mnodes[i]; + icc_node_add(node, provider); + + for (j = 0; j < mnodes[i]->num_links; j++) + icc_link_create(node, mnodes[i]->links[j]); + + data->nodes[i] = node; + } + data->num_nodes = desc->num_nodes; + + ret = icc_provider_register(provider); + if (ret) + goto err; + + platform_set_drvdata(pdev, provider); + + return 0; +err: + icc_nodes_remove(provider); + return ret; +} +EXPORT_SYMBOL_GPL(mtk_emi_icc_probe); + +void mtk_emi_icc_remove(struct platform_device *pdev) +{ + struct icc_provider *provider = platform_get_drvdata(pdev); + + icc_provider_deregister(provider); + icc_nodes_remove(provider); +} +EXPORT_SYMBOL_GPL(mtk_emi_icc_remove); + +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_AUTHOR("Henry Chen "); +MODULE_DESCRIPTION("MediaTek External Memory Interface interconnect driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/mediatek/icc-emi.h b/drivers/interconnect/mediatek/icc-emi.h new file mode 100644 index 000000000000..9512a50db6fa --- /dev/null +++ b/drivers/interconnect/mediatek/icc-emi.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#ifndef __DRIVERS_INTERCONNECT_MEDIATEK_ICC_EMI_H +#define __DRIVERS_INTERCONNECT_MEDIATEK_ICC_EMI_H + +/** + * struct mtk_icc_node - Mediatek EMI Interconnect Node + * @name: The interconnect node name which is shown in debugfs + * @ep: Type of this endpoint + * @id: Unique node identifier + * @sum_avg: Current sum aggregate value of all average bw requests in kBps + * @max_peak: Current max aggregate value of all peak bw requests in kBps + * @num_links: The total number of @links + * @links: Array of @id linked to this node + */ +struct mtk_icc_node { + unsigned char *name; + int ep; + u16 id; + u64 sum_avg; + u64 max_peak; + + u16 num_links; + u16 links[] __counted_by(num_links); +}; + +struct mtk_icc_desc { + struct mtk_icc_node **nodes; + size_t num_nodes; +}; + +int mtk_emi_icc_probe(struct platform_device *pdev); +void mtk_emi_icc_remove(struct platform_device *pdev); + +#endif /* __DRIVERS_INTERCONNECT_MEDIATEK_ICC_EMI_H */ diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c new file mode 100644 index 000000000000..24245085c7a9 --- /dev/null +++ b/drivers/interconnect/mediatek/mt8183.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "icc-emi.h" + +static struct mtk_icc_node ddr_emi = { + .name = "ddr-emi", + .id = SLAVE_DDR_EMI, + .ep = 1, +}; + +static struct mtk_icc_node mcusys = { + .name = "mcusys", + .id = MASTER_MCUSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node gpu = { + .name = "gpu", + .id = MASTER_MFG, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node mmsys = { + .name = "mmsys", + .id = MASTER_MMSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node mm_vpu = { + .name = "mm-vpu", + .id = MASTER_MM_VPU, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_disp = { + .name = "mm-disp", + .id = MASTER_MM_DISP, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_vdec = { + .name = "mm-vdec", + .id = MASTER_MM_VDEC, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_venc = { + .name = "mm-venc", + .id = MASTER_MM_VENC, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_cam = { + .name = "mm-cam", + .id = MASTER_MM_CAM, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_img = { + .name = "mm-img", + .id = MASTER_MM_IMG, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_mdp = { + .name = "mm-mdp", + .id = MASTER_MM_MDP, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node *mt8183_emi_icc_nodes[] = { + [SLAVE_DDR_EMI] = &ddr_emi, + [MASTER_MCUSYS] = &mcusys, + [MASTER_MFG] = &gpu, + [MASTER_MMSYS] = &mmsys, + [MASTER_MM_VPU] = &mm_vpu, + [MASTER_MM_DISP] = &mm_disp, + [MASTER_MM_VDEC] = &mm_vdec, + [MASTER_MM_VENC] = &mm_venc, + [MASTER_MM_CAM] = &mm_cam, + [MASTER_MM_IMG] = &mm_img, + [MASTER_MM_MDP] = &mm_mdp +}; + +static const struct mtk_icc_desc mt8183_emi_icc = { + .nodes = mt8183_emi_icc_nodes, + .num_nodes = ARRAY_SIZE(mt8183_emi_icc_nodes), +}; + +static const struct of_device_id mtk_mt8183_emi_icc_of_match[] = { + { .compatible = "mediatek,mt8183-emi", .data = &mt8183_emi_icc }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mtk_mt8183_emi_icc_of_match); + +static struct platform_driver mtk_emi_icc_mt8183_driver = { + .driver = { + .name = "emi-icc-mt8183", + .of_match_table = mtk_mt8183_emi_icc_of_match, + .sync_state = icc_sync_state, + }, + .probe = mtk_emi_icc_probe, + .remove_new = mtk_emi_icc_remove, + +}; +module_platform_driver(mtk_emi_icc_mt8183_driver); + +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_DESCRIPTION("MediaTek MT8183 EMI ICC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/mediatek/mt8195.c b/drivers/interconnect/mediatek/mt8195.c new file mode 100644 index 000000000000..710e14c5447c --- /dev/null +++ b/drivers/interconnect/mediatek/mt8195.c @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "icc-emi.h" + +static struct mtk_icc_node ddr_emi = { + .name = "ddr-emi", + .id = SLAVE_DDR_EMI, + .ep = 1, +}; + +static struct mtk_icc_node mcusys = { + .name = "mcusys", + .id = MASTER_MCUSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node gpu = { + .name = "gpu", + .id = MASTER_GPUSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node mmsys = { + .name = "mmsys", + .id = MASTER_MMSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node mm_vpu = { + .name = "mm-vpu", + .id = MASTER_MM_VPU, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_disp = { + .name = "mm-disp", + .id = MASTER_MM_DISP, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_vdec = { + .name = "mm-vdec", + .id = MASTER_MM_VDEC, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_venc = { + .name = "mm-venc", + .id = MASTER_MM_VENC, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_cam = { + .name = "mm-cam", + .id = MASTER_MM_CAM, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_img = { + .name = "mm-img", + .id = MASTER_MM_IMG, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node mm_mdp = { + .name = "mm-mdp", + .id = MASTER_MM_MDP, + .ep = 0, + .num_links = 1, + .links = { MASTER_MMSYS } +}; + +static struct mtk_icc_node vpusys = { + .name = "vpusys", + .id = MASTER_VPUSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node vpu_port0 = { + .name = "vpu-port0", + .id = MASTER_VPU_0, + .ep = 0, + .num_links = 1, + .links = { MASTER_VPUSYS } +}; + +static struct mtk_icc_node vpu_port1 = { + .name = "vpu-port1", + .id = MASTER_VPU_1, + .ep = 0, + .num_links = 1, + .links = { MASTER_VPUSYS } +}; + +static struct mtk_icc_node mdlasys = { + .name = "mdlasys", + .id = MASTER_MDLASYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node mdla_port0 = { + .name = "mdla-port0", + .id = MASTER_MDLA_0, + .ep = 0, + .num_links = 1, + .links = { MASTER_MDLASYS } +}; + +static struct mtk_icc_node ufs = { + .name = "ufs", + .id = MASTER_UFS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node pcie0 = { + .name = "pcie0", + .id = MASTER_PCIE_0, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node pcie1 = { + .name = "pcie1", + .id = MASTER_PCIE_1, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node usb = { + .name = "usb", + .id = MASTER_USB, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node wifi = { + .name = "wifi", + .id = MASTER_WIFI, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node bt = { + .name = "bt", + .id = MASTER_BT, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node netsys = { + .name = "netsys", + .id = MASTER_NETSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node dbgif = { + .name = "dbgif", + .id = MASTER_DBGIF, + .ep = 0, + .num_links = 1, + .links = { SLAVE_DDR_EMI } +}; + +static struct mtk_icc_node hrt_ddr_emi = { + .name = "hrt-ddr-emi", + .id = SLAVE_HRT_DDR_EMI, + .ep = 2, +}; + +static struct mtk_icc_node hrt_mmsys = { + .name = "hrt-mmsys", + .id = MASTER_HRT_MMSYS, + .ep = 0, + .num_links = 1, + .links = { SLAVE_HRT_DDR_EMI } +}; + +static struct mtk_icc_node hrt_mm_disp = { + .name = "hrt-mm-disp", + .id = MASTER_HRT_MM_DISP, + .ep = 0, + .num_links = 1, + .links = { MASTER_HRT_MMSYS } +}; + +static struct mtk_icc_node hrt_mm_vdec = { + .name = "hrt-mm-vdec", + .id = MASTER_HRT_MM_VDEC, + .ep = 0, + .num_links = 1, + .links = { MASTER_HRT_MMSYS } +}; + +static struct mtk_icc_node hrt_mm_venc = { + .name = "hrt-mm-venc", + .id = MASTER_HRT_MM_VENC, + .ep = 0, + .num_links = 1, + .links = { MASTER_HRT_MMSYS } +}; + +static struct mtk_icc_node hrt_mm_cam = { + .name = "hrt-mm-cam", + .id = MASTER_HRT_MM_CAM, + .ep = 0, + .num_links = 1, + .links = { MASTER_HRT_MMSYS } +}; + +static struct mtk_icc_node hrt_mm_img = { + .name = "hrt-mm-img", + .id = MASTER_HRT_MM_IMG, + .ep = 0, + .num_links = 1, + .links = { MASTER_HRT_MMSYS } +}; + +static struct mtk_icc_node hrt_mm_mdp = { + .name = "hrt-mm-mdp", + .id = MASTER_HRT_MM_MDP, + .ep = 0, + .num_links = 1, + .links = { MASTER_HRT_MMSYS } +}; + +static struct mtk_icc_node hrt_dbgif = { + .name = "hrt-dbgif", + .id = MASTER_HRT_DBGIF, + .ep = 0, + .num_links = 1, + .links = { SLAVE_HRT_DDR_EMI } +}; + +static struct mtk_icc_node *mt8195_emi_icc_nodes[] = { + [SLAVE_DDR_EMI] = &ddr_emi, + [MASTER_MCUSYS] = &mcusys, + [MASTER_GPUSYS] = &gpu, + [MASTER_MMSYS] = &mmsys, + [MASTER_MM_VPU] = &mm_vpu, + [MASTER_MM_DISP] = &mm_disp, + [MASTER_MM_VDEC] = &mm_vdec, + [MASTER_MM_VENC] = &mm_venc, + [MASTER_MM_CAM] = &mm_cam, + [MASTER_MM_IMG] = &mm_img, + [MASTER_MM_MDP] = &mm_mdp, + [MASTER_VPUSYS] = &vpusys, + [MASTER_VPU_0] = &vpu_port0, + [MASTER_VPU_1] = &vpu_port1, + [MASTER_MDLASYS] = &mdlasys, + [MASTER_MDLA_0] = &mdla_port0, + [MASTER_UFS] = &ufs, + [MASTER_PCIE_0] = &pcie0, + [MASTER_PCIE_1] = &pcie1, + [MASTER_USB] = &usb, + [MASTER_WIFI] = &wifi, + [MASTER_BT] = &bt, + [MASTER_NETSYS] = &netsys, + [MASTER_DBGIF] = &dbgif, + [SLAVE_HRT_DDR_EMI] = &hrt_ddr_emi, + [MASTER_HRT_MMSYS] = &hrt_mmsys, + [MASTER_HRT_MM_DISP] = &hrt_mm_disp, + [MASTER_HRT_MM_VDEC] = &hrt_mm_vdec, + [MASTER_HRT_MM_VENC] = &hrt_mm_venc, + [MASTER_HRT_MM_CAM] = &hrt_mm_cam, + [MASTER_HRT_MM_IMG] = &hrt_mm_img, + [MASTER_HRT_MM_MDP] = &hrt_mm_mdp, + [MASTER_HRT_DBGIF] = &hrt_dbgif +}; + +static struct mtk_icc_desc mt8195_emi_icc = { + .nodes = mt8195_emi_icc_nodes, + .num_nodes = ARRAY_SIZE(mt8195_emi_icc_nodes), +}; + +static const struct of_device_id mtk_mt8195_emi_icc_of_match[] = { + { .compatible = "mediatek,mt8195-emi", .data = &mt8195_emi_icc }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mtk_mt8195_emi_icc_of_match); + +static struct platform_driver mtk_emi_icc_mt8195_driver = { + .driver = { + .name = "emi-icc-mt8195", + .of_match_table = mtk_mt8195_emi_icc_of_match, + .sync_state = icc_sync_state, + }, + .probe = mtk_emi_icc_probe, + .remove_new = mtk_emi_icc_remove, + +}; +module_platform_driver(mtk_emi_icc_mt8195_driver); + +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_DESCRIPTION("MediaTek MT8195 EMI ICC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 1446a839184e..9b84cd8becef 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -35,6 +35,15 @@ config INTERCONNECT_QCOM_MSM8939 This is a driver for the Qualcomm Network-on-Chip on msm8939-based platforms. +config INTERCONNECT_QCOM_MSM8953 + tristate "Qualcomm MSM8953 interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + select INTERCONNECT_QCOM_SMD_RPM + help + This is a driver for the Qualcomm Network-on-Chip on msm8953-based + platforms. + config INTERCONNECT_QCOM_MSM8974 tristate "Qualcomm MSM8974 interconnect driver" depends on INTERCONNECT_QCOM diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index 2ea3113d0a4d..7a7b6a71876f 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -7,6 +7,7 @@ icc-bcm-voter-objs := bcm-voter.o qnoc-msm8909-objs := msm8909.o qnoc-msm8916-objs := msm8916.o qnoc-msm8939-objs := msm8939.o +qnoc-msm8953-objs := msm8953.o qnoc-msm8974-objs := msm8974.o qnoc-msm8996-objs := msm8996.o icc-osm-l3-objs := osm-l3.o @@ -41,6 +42,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8909) += qnoc-msm8909.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o +obj-$(CONFIG_INTERCONNECT_QCOM_MSM8953) += qnoc-msm8953.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o diff --git a/drivers/interconnect/qcom/icc-common.c b/drivers/interconnect/qcom/icc-common.c index 9b9ee113f172..9b8a9c69e0cb 100644 --- a/drivers/interconnect/qcom/icc-common.c +++ b/drivers/interconnect/qcom/icc-common.c @@ -35,4 +35,5 @@ struct icc_node_data *qcom_icc_xlate_extended(const struct of_phandle_args *spec } EXPORT_SYMBOL_GPL(qcom_icc_xlate_extended); +MODULE_DESCRIPTION("Qualcomm interconnect common functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index c1aa265c1f4e..f49a8e0cb03c 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -1,8 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include +#include #include #include #include @@ -14,6 +17,38 @@ #include "icc-common.h" #include "icc-rpmh.h" +/* QNOC QoS */ +#define QOSGEN_MAINCTL_LO(p, qp) (0x8 + (p->port_offsets[qp])) +#define QOS_SLV_URG_MSG_EN_MASK GENMASK(3, 3) +#define QOS_DFLT_PRIO_MASK GENMASK(6, 4) +#define QOS_DISABLE_MASK GENMASK(24, 24) + +/** + * qcom_icc_set_qos - initialize static QoS configurations + * @qp: qcom icc provider to which @node belongs + * @node: qcom icc node to operate on + */ +static void qcom_icc_set_qos(struct qcom_icc_provider *qp, + struct qcom_icc_node *node) +{ + const struct qcom_icc_qosbox *qos = node->qosbox; + int port; + + for (port = 0; port < qos->num_ports; port++) { + regmap_update_bits(qp->regmap, QOSGEN_MAINCTL_LO(qos, port), + QOS_DISABLE_MASK, + FIELD_PREP(QOS_DISABLE_MASK, qos->prio_fwd_disable)); + + regmap_update_bits(qp->regmap, QOSGEN_MAINCTL_LO(qos, port), + QOS_DFLT_PRIO_MASK, + FIELD_PREP(QOS_DFLT_PRIO_MASK, qos->prio)); + + regmap_update_bits(qp->regmap, QOSGEN_MAINCTL_LO(qos, port), + QOS_SLV_URG_MSG_EN_MASK, + FIELD_PREP(QOS_SLV_URG_MSG_EN_MASK, qos->urg_fwd)); + } +} + /** * qcom_icc_pre_aggregate - cleans up stale values from prior icc_set * @node: icc node to operate on @@ -159,6 +194,36 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev) } EXPORT_SYMBOL_GPL(qcom_icc_bcm_init); +/** + * qcom_icc_rpmh_configure_qos - configure QoS parameters + * @qp: qcom icc provider associated with QoS endpoint nodes + * + * Return: 0 on success, or an error code otherwise + */ +static int qcom_icc_rpmh_configure_qos(struct qcom_icc_provider *qp) +{ + struct qcom_icc_node *qnode; + size_t i; + int ret; + + ret = clk_bulk_prepare_enable(qp->num_clks, qp->clks); + if (ret) + return ret; + + for (i = 0; i < qp->num_nodes; i++) { + qnode = qp->nodes[i]; + if (!qnode) + continue; + + if (qnode->qosbox) + qcom_icc_set_qos(qp, qnode); + } + + clk_bulk_disable_unprepare(qp->num_clks, qp->clks); + + return ret; +} + int qcom_icc_rpmh_probe(struct platform_device *pdev) { const struct qcom_icc_desc *desc; @@ -199,7 +264,9 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) qp->dev = dev; qp->bcms = desc->bcms; + qp->nodes = desc->nodes; qp->num_bcms = desc->num_bcms; + qp->num_nodes = desc->num_nodes; qp->voter = of_bcm_voter_get(qp->dev, NULL); if (IS_ERR(qp->voter)) @@ -229,6 +296,32 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) data->nodes[i] = node; } + if (desc->config) { + struct resource *res; + void __iomem *base; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(base)) + goto skip_qos_config; + + qp->regmap = devm_regmap_init_mmio(dev, base, desc->config); + if (IS_ERR(qp->regmap)) { + dev_info(dev, "Skipping QoS, regmap failed; %ld\n", PTR_ERR(qp->regmap)); + goto skip_qos_config; + } + + qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks); + if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_clks_required)) { + dev_info(dev, "Skipping QoS, failed to get clk: %d\n", qp->num_clks); + goto skip_qos_config; + } + + ret = qcom_icc_rpmh_configure_qos(qp); + if (ret) + dev_info(dev, "Failed to program QoS: %d\n", ret); + } + +skip_qos_config: ret = icc_provider_register(provider); if (ret) goto err_remove_nodes; @@ -262,4 +355,5 @@ void qcom_icc_rpmh_remove(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(qcom_icc_rpmh_remove); +MODULE_DESCRIPTION("Qualcomm RPMh interconnect driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index 2de29460e808..14db89850fb3 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -1,12 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__ #define __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__ #include +#include #define to_qcom_provider(_provider) \ container_of(_provider, struct qcom_icc_provider, provider) @@ -18,6 +20,11 @@ * @bcms: list of bcms that maps to the provider * @num_bcms: number of @bcms * @voter: bcm voter targeted by this provider + * @nodes: list of icc nodes that maps to the provider + * @num_nodes: number of @nodes + * @regmap: used for QoS, register access + * @clks : clks required for register access + * @num_clks: number of @clks */ struct qcom_icc_provider { struct icc_provider provider; @@ -25,6 +32,11 @@ struct qcom_icc_provider { struct qcom_icc_bcm * const *bcms; size_t num_bcms; struct bcm_voter *voter; + struct qcom_icc_node * const *nodes; + size_t num_nodes; + struct regmap *regmap; + struct clk_bulk_data *clks; + int num_clks; }; /** @@ -41,6 +53,26 @@ struct bcm_db { u8 reserved; }; +#define MAX_PORTS 2 + +/** + * struct qcom_icc_qosbox - Qualcomm specific QoS config + * @prio: priority value assigned to requests on the node + * @urg_fwd: whether to forward the urgency promotion issued by master + * (endpoint), or discard + * @prio_fwd_disable: whether to forward the priority driven by master, or + * override by @prio + * @num_ports: number of @ports + * @port_offsets: qos register offsets + */ +struct qcom_icc_qosbox { + const u32 prio; + const bool urg_fwd; + const bool prio_fwd_disable; + const u32 num_ports; + const u32 port_offsets[MAX_PORTS]; +}; + #define MAX_LINKS 128 #define MAX_BCMS 64 #define MAX_BCM_PER_NODE 3 @@ -58,6 +90,7 @@ struct bcm_db { * @max_peak: current max aggregate value of all peak bw requests * @bcms: list of bcms associated with this logical node * @num_bcms: num of @bcms + * @qosbox: QoS config data associated with node */ struct qcom_icc_node { const char *name; @@ -70,6 +103,7 @@ struct qcom_icc_node { u64 max_peak[QCOM_ICC_NUM_BUCKETS]; struct qcom_icc_bcm *bcms[MAX_BCM_PER_NODE]; size_t num_bcms; + const struct qcom_icc_qosbox *qosbox; }; /** @@ -114,10 +148,12 @@ struct qcom_icc_fabric { }; struct qcom_icc_desc { + const struct regmap_config *config; struct qcom_icc_node * const *nodes; size_t num_nodes; struct qcom_icc_bcm * const *bcms; size_t num_bcms; + bool qos_clks_required; }; int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, diff --git a/drivers/interconnect/qcom/msm8953.c b/drivers/interconnect/qcom/msm8953.c new file mode 100644 index 000000000000..9e8867c07692 --- /dev/null +++ b/drivers/interconnect/qcom/msm8953.c @@ -0,0 +1,1321 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "icc-rpm.h" + +enum { + MSM8953_MASTER_AMPSS_M0 = 1, + MSM8953_MASTER_GRAPHICS_3D, + MSM8953_SNOC_BIMC_0_MAS, + MSM8953_SNOC_BIMC_2_MAS, + MSM8953_SNOC_BIMC_1_MAS, + MSM8953_MASTER_TCU_0, + MSM8953_SLAVE_EBI_CH0, + MSM8953_BIMC_SNOC_SLV, + MSM8953_MASTER_SPDM, + MSM8953_MASTER_BLSP_1, + MSM8953_MASTER_BLSP_2, + MSM8953_MASTER_USB3, + MSM8953_MASTER_CRYPTO_CORE0, + MSM8953_MASTER_SDCC_1, + MSM8953_MASTER_SDCC_2, + MSM8953_SNOC_PNOC_MAS, + MSM8953_PNOC_M_0, + MSM8953_PNOC_M_1, + MSM8953_PNOC_INT_1, + MSM8953_PNOC_INT_2, + MSM8953_PNOC_SLV_0, + MSM8953_PNOC_SLV_1, + MSM8953_PNOC_SLV_2, + MSM8953_PNOC_SLV_3, + MSM8953_PNOC_SLV_4, + MSM8953_PNOC_SLV_6, + MSM8953_PNOC_SLV_7, + MSM8953_PNOC_SLV_8, + MSM8953_PNOC_SLV_9, + MSM8953_SLAVE_SPDM_WRAPPER, + MSM8953_SLAVE_PDM, + MSM8953_SLAVE_TCSR, + MSM8953_SLAVE_SNOC_CFG, + MSM8953_SLAVE_TLMM, + MSM8953_SLAVE_MESSAGE_RAM, + MSM8953_SLAVE_BLSP_1, + MSM8953_SLAVE_BLSP_2, + MSM8953_SLAVE_PRNG, + MSM8953_SLAVE_CAMERA_CFG, + MSM8953_SLAVE_DISPLAY_CFG, + MSM8953_SLAVE_VENUS_CFG, + MSM8953_SLAVE_GRAPHICS_3D_CFG, + MSM8953_SLAVE_SDCC_1, + MSM8953_SLAVE_SDCC_2, + MSM8953_SLAVE_CRYPTO_0_CFG, + MSM8953_SLAVE_PMIC_ARB, + MSM8953_SLAVE_USB3, + MSM8953_SLAVE_IPA_CFG, + MSM8953_SLAVE_TCU, + MSM8953_PNOC_SNOC_SLV, + MSM8953_MASTER_QDSS_BAM, + MSM8953_BIMC_SNOC_MAS, + MSM8953_PNOC_SNOC_MAS, + MSM8953_MASTER_IPA, + MSM8953_MASTER_QDSS_ETR, + MSM8953_SNOC_QDSS_INT, + MSM8953_SNOC_INT_0, + MSM8953_SNOC_INT_1, + MSM8953_SNOC_INT_2, + MSM8953_SLAVE_APPSS, + MSM8953_SLAVE_WCSS, + MSM8953_SNOC_BIMC_1_SLV, + MSM8953_SLAVE_OCIMEM, + MSM8953_SNOC_PNOC_SLV, + MSM8953_SLAVE_QDSS_STM, + MSM8953_SLAVE_OCMEM_64, + MSM8953_SLAVE_LPASS, + MSM8953_MASTER_JPEG, + MSM8953_MASTER_MDP_PORT0, + MSM8953_MASTER_VIDEO_P0, + MSM8953_MASTER_VFE, + MSM8953_MASTER_VFE1, + MSM8953_MASTER_CPP, + MSM8953_SNOC_BIMC_0_SLV, + MSM8953_SNOC_BIMC_2_SLV, + MSM8953_SLAVE_CATS_128, +}; + +static const u16 mas_apps_proc_links[] = { + MSM8953_SLAVE_EBI_CH0, + MSM8953_BIMC_SNOC_SLV +}; + +static struct qcom_icc_node mas_apps_proc = { + .name = "mas_apps_proc", + .id = MSM8953_MASTER_AMPSS_M0, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 0, + .num_links = ARRAY_SIZE(mas_apps_proc_links), + .links = mas_apps_proc_links, +}; + +static const u16 mas_oxili_links[] = { + MSM8953_SLAVE_EBI_CH0, + MSM8953_BIMC_SNOC_SLV +}; + +static struct qcom_icc_node mas_oxili = { + .name = "mas_oxili", + .id = MSM8953_MASTER_GRAPHICS_3D, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 2, + .num_links = ARRAY_SIZE(mas_oxili_links), + .links = mas_oxili_links, +}; + +static const u16 mas_snoc_bimc_0_links[] = { + MSM8953_SLAVE_EBI_CH0, + MSM8953_BIMC_SNOC_SLV +}; + +static struct qcom_icc_node mas_snoc_bimc_0 = { + .name = "mas_snoc_bimc_0", + .id = MSM8953_SNOC_BIMC_0_MAS, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 3, + .num_links = ARRAY_SIZE(mas_snoc_bimc_0_links), + .links = mas_snoc_bimc_0_links, +}; + +static const u16 mas_snoc_bimc_2_links[] = { + MSM8953_SLAVE_EBI_CH0, + MSM8953_BIMC_SNOC_SLV +}; + +static struct qcom_icc_node mas_snoc_bimc_2 = { + .name = "mas_snoc_bimc_2", + .id = MSM8953_SNOC_BIMC_2_MAS, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 4, + .num_links = ARRAY_SIZE(mas_snoc_bimc_2_links), + .links = mas_snoc_bimc_2_links, +}; + +static const u16 mas_snoc_bimc_1_links[] = { + MSM8953_SLAVE_EBI_CH0 +}; + +static struct qcom_icc_node mas_snoc_bimc_1 = { + .name = "mas_snoc_bimc_1", + .id = MSM8953_SNOC_BIMC_1_MAS, + .buswidth = 8, + .mas_rpm_id = 76, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_snoc_bimc_1_links), + .links = mas_snoc_bimc_1_links, +}; + +static const u16 mas_tcu_0_links[] = { + MSM8953_SLAVE_EBI_CH0, + MSM8953_BIMC_SNOC_SLV +}; + +static struct qcom_icc_node mas_tcu_0 = { + .name = "mas_tcu_0", + .id = MSM8953_MASTER_TCU_0, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 2, + .qos.areq_prio = 2, + .qos.qos_port = 6, + .num_links = ARRAY_SIZE(mas_tcu_0_links), + .links = mas_tcu_0_links, +}; + +static struct qcom_icc_node slv_ebi = { + .name = "slv_ebi", + .id = MSM8953_SLAVE_EBI_CH0, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 0, +}; + +static const u16 slv_bimc_snoc_links[] = { + MSM8953_BIMC_SNOC_MAS +}; + +static struct qcom_icc_node slv_bimc_snoc = { + .name = "slv_bimc_snoc", + .id = MSM8953_BIMC_SNOC_SLV, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 2, + .num_links = ARRAY_SIZE(slv_bimc_snoc_links), + .links = slv_bimc_snoc_links, +}; + +static const u16 mas_spdm_links[] = { + MSM8953_PNOC_M_0 +}; + +static struct qcom_icc_node mas_spdm = { + .name = "mas_spdm", + .id = MSM8953_MASTER_SPDM, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(mas_spdm_links), + .links = mas_spdm_links, +}; + +static const u16 mas_blsp_1_links[] = { + MSM8953_PNOC_M_1 +}; + +static struct qcom_icc_node mas_blsp_1 = { + .name = "mas_blsp_1", + .id = MSM8953_MASTER_BLSP_1, + .buswidth = 4, + .mas_rpm_id = 41, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_blsp_1_links), + .links = mas_blsp_1_links, +}; + +static const u16 mas_blsp_2_links[] = { + MSM8953_PNOC_M_1 +}; + +static struct qcom_icc_node mas_blsp_2 = { + .name = "mas_blsp_2", + .id = MSM8953_MASTER_BLSP_2, + .buswidth = 4, + .mas_rpm_id = 39, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_blsp_2_links), + .links = mas_blsp_2_links, +}; + +static const u16 mas_usb3_links[] = { + MSM8953_PNOC_INT_1 +}; + +static struct qcom_icc_node mas_usb3 = { + .name = "mas_usb3", + .id = MSM8953_MASTER_USB3, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 1, + .qos.areq_prio = 1, + .qos.qos_port = 11, + .num_links = ARRAY_SIZE(mas_usb3_links), + .links = mas_usb3_links, +}; + +static const u16 mas_crypto_links[] = { + MSM8953_PNOC_INT_1 +}; + +static struct qcom_icc_node mas_crypto = { + .name = "mas_crypto", + .id = MSM8953_MASTER_CRYPTO_CORE0, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 1, + .qos.areq_prio = 1, + .qos.qos_port = 0, + .num_links = ARRAY_SIZE(mas_crypto_links), + .links = mas_crypto_links, +}; + +static const u16 mas_sdcc_1_links[] = { + MSM8953_PNOC_INT_1 +}; + +static struct qcom_icc_node mas_sdcc_1 = { + .name = "mas_sdcc_1", + .id = MSM8953_MASTER_SDCC_1, + .buswidth = 8, + .mas_rpm_id = 33, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_sdcc_1_links), + .links = mas_sdcc_1_links, +}; + +static const u16 mas_sdcc_2_links[] = { + MSM8953_PNOC_INT_1 +}; + +static struct qcom_icc_node mas_sdcc_2 = { + .name = "mas_sdcc_2", + .id = MSM8953_MASTER_SDCC_2, + .buswidth = 8, + .mas_rpm_id = 35, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_sdcc_2_links), + .links = mas_sdcc_2_links, +}; + +static const u16 mas_snoc_pcnoc_links[] = { + MSM8953_PNOC_INT_2 +}; + +static struct qcom_icc_node mas_snoc_pcnoc = { + .name = "mas_snoc_pcnoc", + .id = MSM8953_SNOC_PNOC_MAS, + .buswidth = 8, + .mas_rpm_id = 77, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_snoc_pcnoc_links), + .links = mas_snoc_pcnoc_links, +}; + +static const u16 pcnoc_m_0_links[] = { + MSM8953_PNOC_INT_1 +}; + +static struct qcom_icc_node pcnoc_m_0 = { + .name = "pcnoc_m_0", + .id = MSM8953_PNOC_M_0, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 1, + .qos.areq_prio = 1, + .qos.qos_port = 5, + .num_links = ARRAY_SIZE(pcnoc_m_0_links), + .links = pcnoc_m_0_links, +}; + +static const u16 pcnoc_m_1_links[] = { + MSM8953_PNOC_INT_1 +}; + +static struct qcom_icc_node pcnoc_m_1 = { + .name = "pcnoc_m_1", + .id = MSM8953_PNOC_M_1, + .buswidth = 4, + .mas_rpm_id = 88, + .slv_rpm_id = 117, + .num_links = ARRAY_SIZE(pcnoc_m_1_links), + .links = pcnoc_m_1_links, +}; + +static const u16 pcnoc_int_1_links[] = { + MSM8953_PNOC_INT_2, + MSM8953_PNOC_SNOC_SLV +}; + +static struct qcom_icc_node pcnoc_int_1 = { + .name = "pcnoc_int_1", + .id = MSM8953_PNOC_INT_1, + .buswidth = 8, + .mas_rpm_id = 86, + .slv_rpm_id = 115, + .num_links = ARRAY_SIZE(pcnoc_int_1_links), + .links = pcnoc_int_1_links, +}; + +static const u16 pcnoc_int_2_links[] = { + MSM8953_PNOC_SLV_1, + MSM8953_PNOC_SLV_2, + MSM8953_PNOC_SLV_0, + MSM8953_PNOC_SLV_4, + MSM8953_PNOC_SLV_6, + MSM8953_PNOC_SLV_7, + MSM8953_PNOC_SLV_8, + MSM8953_PNOC_SLV_9, + MSM8953_SLAVE_TCU, + MSM8953_SLAVE_GRAPHICS_3D_CFG, + MSM8953_PNOC_SLV_3 +}; + +static struct qcom_icc_node pcnoc_int_2 = { + .name = "pcnoc_int_2", + .id = MSM8953_PNOC_INT_2, + .buswidth = 8, + .mas_rpm_id = 124, + .slv_rpm_id = 184, + .num_links = ARRAY_SIZE(pcnoc_int_2_links), + .links = pcnoc_int_2_links, +}; + +static const u16 pcnoc_s_0_links[] = { + MSM8953_SLAVE_PDM, + MSM8953_SLAVE_SPDM_WRAPPER +}; + +static struct qcom_icc_node pcnoc_s_0 = { + .name = "pcnoc_s_0", + .id = MSM8953_PNOC_SLV_0, + .buswidth = 4, + .mas_rpm_id = 89, + .slv_rpm_id = 118, + .num_links = ARRAY_SIZE(pcnoc_s_0_links), + .links = pcnoc_s_0_links, +}; + +static const u16 pcnoc_s_1_links[] = { + MSM8953_SLAVE_TCSR +}; + +static struct qcom_icc_node pcnoc_s_1 = { + .name = "pcnoc_s_1", + .id = MSM8953_PNOC_SLV_1, + .buswidth = 4, + .mas_rpm_id = 90, + .slv_rpm_id = 119, + .num_links = ARRAY_SIZE(pcnoc_s_1_links), + .links = pcnoc_s_1_links, +}; + +static const u16 pcnoc_s_2_links[] = { + MSM8953_SLAVE_SNOC_CFG +}; + +static struct qcom_icc_node pcnoc_s_2 = { + .name = "pcnoc_s_2", + .id = MSM8953_PNOC_SLV_2, + .buswidth = 4, + .mas_rpm_id = 91, + .slv_rpm_id = 120, + .num_links = ARRAY_SIZE(pcnoc_s_2_links), + .links = pcnoc_s_2_links, +}; + +static const u16 pcnoc_s_3_links[] = { + MSM8953_SLAVE_TLMM, + MSM8953_SLAVE_PRNG, + MSM8953_SLAVE_BLSP_1, + MSM8953_SLAVE_BLSP_2, + MSM8953_SLAVE_MESSAGE_RAM +}; + +static struct qcom_icc_node pcnoc_s_3 = { + .name = "pcnoc_s_3", + .id = MSM8953_PNOC_SLV_3, + .buswidth = 4, + .mas_rpm_id = 92, + .slv_rpm_id = 121, + .num_links = ARRAY_SIZE(pcnoc_s_3_links), + .links = pcnoc_s_3_links, +}; + +static const u16 pcnoc_s_4_links[] = { + MSM8953_SLAVE_CAMERA_CFG, + MSM8953_SLAVE_DISPLAY_CFG, + MSM8953_SLAVE_VENUS_CFG +}; + +static struct qcom_icc_node pcnoc_s_4 = { + .name = "pcnoc_s_4", + .id = MSM8953_PNOC_SLV_4, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(pcnoc_s_4_links), + .links = pcnoc_s_4_links, +}; + +static const u16 pcnoc_s_6_links[] = { + MSM8953_SLAVE_CRYPTO_0_CFG, + MSM8953_SLAVE_SDCC_2, + MSM8953_SLAVE_SDCC_1 +}; + +static struct qcom_icc_node pcnoc_s_6 = { + .name = "pcnoc_s_6", + .id = MSM8953_PNOC_SLV_6, + .buswidth = 4, + .mas_rpm_id = 94, + .slv_rpm_id = 123, + .num_links = ARRAY_SIZE(pcnoc_s_6_links), + .links = pcnoc_s_6_links, +}; + +static const u16 pcnoc_s_7_links[] = { + MSM8953_SLAVE_PMIC_ARB +}; + +static struct qcom_icc_node pcnoc_s_7 = { + .name = "pcnoc_s_7", + .id = MSM8953_PNOC_SLV_7, + .buswidth = 4, + .mas_rpm_id = 95, + .slv_rpm_id = 124, + .num_links = ARRAY_SIZE(pcnoc_s_7_links), + .links = pcnoc_s_7_links, +}; + +static const u16 pcnoc_s_8_links[] = { + MSM8953_SLAVE_USB3 +}; + +static struct qcom_icc_node pcnoc_s_8 = { + .name = "pcnoc_s_8", + .id = MSM8953_PNOC_SLV_8, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(pcnoc_s_8_links), + .links = pcnoc_s_8_links, +}; + +static const u16 pcnoc_s_9_links[] = { + MSM8953_SLAVE_IPA_CFG +}; + +static struct qcom_icc_node pcnoc_s_9 = { + .name = "pcnoc_s_9", + .id = MSM8953_PNOC_SLV_9, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(pcnoc_s_9_links), + .links = pcnoc_s_9_links, +}; + +static struct qcom_icc_node slv_spdm = { + .name = "slv_spdm", + .id = MSM8953_SLAVE_SPDM_WRAPPER, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_pdm = { + .name = "slv_pdm", + .id = MSM8953_SLAVE_PDM, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 41, +}; + +static struct qcom_icc_node slv_tcsr = { + .name = "slv_tcsr", + .id = MSM8953_SLAVE_TCSR, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 50, +}; + +static struct qcom_icc_node slv_snoc_cfg = { + .name = "slv_snoc_cfg", + .id = MSM8953_SLAVE_SNOC_CFG, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 70, +}; + +static struct qcom_icc_node slv_tlmm = { + .name = "slv_tlmm", + .id = MSM8953_SLAVE_TLMM, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 51, +}; + +static struct qcom_icc_node slv_message_ram = { + .name = "slv_message_ram", + .id = MSM8953_SLAVE_MESSAGE_RAM, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 55, +}; + +static struct qcom_icc_node slv_blsp_1 = { + .name = "slv_blsp_1", + .id = MSM8953_SLAVE_BLSP_1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 39, +}; + +static struct qcom_icc_node slv_blsp_2 = { + .name = "slv_blsp_2", + .id = MSM8953_SLAVE_BLSP_2, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 37, +}; + +static struct qcom_icc_node slv_prng = { + .name = "slv_prng", + .id = MSM8953_SLAVE_PRNG, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 44, +}; + +static struct qcom_icc_node slv_camera_ss_cfg = { + .name = "slv_camera_ss_cfg", + .id = MSM8953_SLAVE_CAMERA_CFG, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_disp_ss_cfg = { + .name = "slv_disp_ss_cfg", + .id = MSM8953_SLAVE_DISPLAY_CFG, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_venus_cfg = { + .name = "slv_venus_cfg", + .id = MSM8953_SLAVE_VENUS_CFG, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_gpu_cfg = { + .name = "slv_gpu_cfg", + .id = MSM8953_SLAVE_GRAPHICS_3D_CFG, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_sdcc_1 = { + .name = "slv_sdcc_1", + .id = MSM8953_SLAVE_SDCC_1, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 31, +}; + +static struct qcom_icc_node slv_sdcc_2 = { + .name = "slv_sdcc_2", + .id = MSM8953_SLAVE_SDCC_2, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 33, +}; + +static struct qcom_icc_node slv_crypto_0_cfg = { + .name = "slv_crypto_0_cfg", + .id = MSM8953_SLAVE_CRYPTO_0_CFG, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_pmic_arb = { + .name = "slv_pmic_arb", + .id = MSM8953_SLAVE_PMIC_ARB, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 59, +}; + +static struct qcom_icc_node slv_usb3 = { + .name = "slv_usb3", + .id = MSM8953_SLAVE_USB3, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_ipa_cfg = { + .name = "slv_ipa_cfg", + .id = MSM8953_SLAVE_IPA_CFG, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_tcu = { + .name = "slv_tcu", + .id = MSM8953_SLAVE_TCU, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static const u16 slv_pcnoc_snoc_links[] = { + MSM8953_PNOC_SNOC_MAS +}; + +static struct qcom_icc_node slv_pcnoc_snoc = { + .name = "slv_pcnoc_snoc", + .id = MSM8953_PNOC_SNOC_SLV, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 45, + .num_links = ARRAY_SIZE(slv_pcnoc_snoc_links), + .links = slv_pcnoc_snoc_links, +}; + +static const u16 mas_qdss_bam_links[] = { + MSM8953_SNOC_QDSS_INT +}; + +static struct qcom_icc_node mas_qdss_bam = { + .name = "mas_qdss_bam", + .id = MSM8953_MASTER_QDSS_BAM, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 1, + .qos.areq_prio = 1, + .qos.qos_port = 11, + .num_links = ARRAY_SIZE(mas_qdss_bam_links), + .links = mas_qdss_bam_links, +}; + +static const u16 mas_bimc_snoc_links[] = { + MSM8953_SNOC_INT_0, + MSM8953_SNOC_INT_1, + MSM8953_SNOC_INT_2 +}; + +static struct qcom_icc_node mas_bimc_snoc = { + .name = "mas_bimc_snoc", + .id = MSM8953_BIMC_SNOC_MAS, + .buswidth = 8, + .mas_rpm_id = 21, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_bimc_snoc_links), + .links = mas_bimc_snoc_links, +}; + +static const u16 mas_pcnoc_snoc_links[] = { + MSM8953_SNOC_INT_0, + MSM8953_SNOC_INT_1, + MSM8953_SNOC_BIMC_1_SLV +}; + +static struct qcom_icc_node mas_pcnoc_snoc = { + .name = "mas_pcnoc_snoc", + .id = MSM8953_PNOC_SNOC_MAS, + .buswidth = 8, + .mas_rpm_id = 29, + .slv_rpm_id = -1, + .num_links = ARRAY_SIZE(mas_pcnoc_snoc_links), + .links = mas_pcnoc_snoc_links, +}; + +static const u16 mas_ipa_links[] = { + MSM8953_SNOC_INT_0, + MSM8953_SNOC_INT_1, + MSM8953_SNOC_BIMC_1_SLV +}; + +static struct qcom_icc_node mas_ipa = { + .name = "mas_ipa", + .id = MSM8953_MASTER_IPA, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 14, + .num_links = ARRAY_SIZE(mas_ipa_links), + .links = mas_ipa_links, +}; + +static const u16 mas_qdss_etr_links[] = { + MSM8953_SNOC_QDSS_INT +}; + +static struct qcom_icc_node mas_qdss_etr = { + .name = "mas_qdss_etr", + .id = MSM8953_MASTER_QDSS_ETR, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_FIXED, + .qos.prio_level = 1, + .qos.areq_prio = 1, + .qos.qos_port = 10, + .num_links = ARRAY_SIZE(mas_qdss_etr_links), + .links = mas_qdss_etr_links, +}; + +static const u16 qdss_int_links[] = { + MSM8953_SNOC_INT_1, + MSM8953_SNOC_BIMC_1_SLV +}; + +static struct qcom_icc_node qdss_int = { + .name = "qdss_int", + .id = MSM8953_SNOC_QDSS_INT, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(qdss_int_links), + .links = qdss_int_links, +}; + +static const u16 snoc_int_0_links[] = { + MSM8953_SLAVE_LPASS, + MSM8953_SLAVE_WCSS, + MSM8953_SLAVE_APPSS +}; + +static struct qcom_icc_node snoc_int_0 = { + .name = "snoc_int_0", + .id = MSM8953_SNOC_INT_0, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(snoc_int_0_links), + .links = snoc_int_0_links, +}; + +static const u16 snoc_int_1_links[] = { + MSM8953_SLAVE_QDSS_STM, + MSM8953_SLAVE_OCIMEM, + MSM8953_SNOC_PNOC_SLV +}; + +static struct qcom_icc_node snoc_int_1 = { + .name = "snoc_int_1", + .id = MSM8953_SNOC_INT_1, + .buswidth = 8, + .mas_rpm_id = 100, + .slv_rpm_id = 131, + .num_links = ARRAY_SIZE(snoc_int_1_links), + .links = snoc_int_1_links, +}; + +static const u16 snoc_int_2_links[] = { + MSM8953_SLAVE_CATS_128, + MSM8953_SLAVE_OCMEM_64 +}; + +static struct qcom_icc_node snoc_int_2 = { + .name = "snoc_int_2", + .id = MSM8953_SNOC_INT_2, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(snoc_int_2_links), + .links = snoc_int_2_links, +}; + +static struct qcom_icc_node slv_kpss_ahb = { + .name = "slv_kpss_ahb", + .id = MSM8953_SLAVE_APPSS, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_wcss = { + .name = "slv_wcss", + .id = MSM8953_SLAVE_WCSS, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static const u16 slv_snoc_bimc_1_links[] = { + MSM8953_SNOC_BIMC_1_MAS +}; + +static struct qcom_icc_node slv_snoc_bimc_1 = { + .name = "slv_snoc_bimc_1", + .id = MSM8953_SNOC_BIMC_1_SLV, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 104, + .num_links = ARRAY_SIZE(slv_snoc_bimc_1_links), + .links = slv_snoc_bimc_1_links, +}; + +static struct qcom_icc_node slv_imem = { + .name = "slv_imem", + .id = MSM8953_SLAVE_OCIMEM, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 26, +}; + +static const u16 slv_snoc_pcnoc_links[] = { + MSM8953_SNOC_PNOC_MAS +}; + +static struct qcom_icc_node slv_snoc_pcnoc = { + .name = "slv_snoc_pcnoc", + .id = MSM8953_SNOC_PNOC_SLV, + .buswidth = 8, + .mas_rpm_id = -1, + .slv_rpm_id = 28, + .num_links = ARRAY_SIZE(slv_snoc_pcnoc_links), + .links = slv_snoc_pcnoc_links, +}; + +static struct qcom_icc_node slv_qdss_stm = { + .name = "slv_qdss_stm", + .id = MSM8953_SLAVE_QDSS_STM, + .buswidth = 4, + .mas_rpm_id = -1, + .slv_rpm_id = 30, +}; + +static struct qcom_icc_node slv_cats_1 = { + .name = "slv_cats_1", + .id = MSM8953_SLAVE_OCMEM_64, + .buswidth = 8, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node slv_lpass = { + .name = "slv_lpass", + .id = MSM8953_SLAVE_LPASS, + .buswidth = 4, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static const u16 mas_jpeg_links[] = { + MSM8953_SNOC_BIMC_2_SLV +}; + +static struct qcom_icc_node mas_jpeg = { + .name = "mas_jpeg", + .id = MSM8953_MASTER_JPEG, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 6, + .num_links = ARRAY_SIZE(mas_jpeg_links), + .links = mas_jpeg_links, +}; + +static const u16 mas_mdp_links[] = { + MSM8953_SNOC_BIMC_0_SLV +}; + +static struct qcom_icc_node mas_mdp = { + .name = "mas_mdp", + .id = MSM8953_MASTER_MDP_PORT0, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 7, + .num_links = ARRAY_SIZE(mas_mdp_links), + .links = mas_mdp_links, +}; + +static const u16 mas_venus_links[] = { + MSM8953_SNOC_BIMC_2_SLV +}; + +static struct qcom_icc_node mas_venus = { + .name = "mas_venus", + .id = MSM8953_MASTER_VIDEO_P0, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 8, + .num_links = ARRAY_SIZE(mas_venus_links), + .links = mas_venus_links, +}; + +static const u16 mas_vfe0_links[] = { + MSM8953_SNOC_BIMC_0_SLV +}; + +static struct qcom_icc_node mas_vfe0 = { + .name = "mas_vfe0", + .id = MSM8953_MASTER_VFE, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 9, + .num_links = ARRAY_SIZE(mas_vfe0_links), + .links = mas_vfe0_links, +}; + +static const u16 mas_vfe1_links[] = { + MSM8953_SNOC_BIMC_0_SLV +}; + +static struct qcom_icc_node mas_vfe1 = { + .name = "mas_vfe1", + .id = MSM8953_MASTER_VFE1, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 13, + .num_links = ARRAY_SIZE(mas_vfe1_links), + .links = mas_vfe1_links, +}; + +static const u16 mas_cpp_links[] = { + MSM8953_SNOC_BIMC_2_SLV +}; + +static struct qcom_icc_node mas_cpp = { + .name = "mas_cpp", + .id = MSM8953_MASTER_CPP, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = 12, + .num_links = ARRAY_SIZE(mas_cpp_links), + .links = mas_cpp_links, +}; + +static const u16 slv_snoc_bimc_0_links[] = { + MSM8953_SNOC_BIMC_0_MAS +}; + +static struct qcom_icc_node slv_snoc_bimc_0 = { + .name = "slv_snoc_bimc_0", + .id = MSM8953_SNOC_BIMC_0_SLV, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(slv_snoc_bimc_0_links), + .links = slv_snoc_bimc_0_links, +}; + +static const u16 slv_snoc_bimc_2_links[] = { + MSM8953_SNOC_BIMC_2_MAS +}; + +static struct qcom_icc_node slv_snoc_bimc_2 = { + .name = "slv_snoc_bimc_2", + .id = MSM8953_SNOC_BIMC_2_SLV, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, + .num_links = ARRAY_SIZE(slv_snoc_bimc_2_links), + .links = slv_snoc_bimc_2_links, +}; + +static struct qcom_icc_node slv_cats_0 = { + .name = "slv_cats_0", + .id = MSM8953_SLAVE_CATS_128, + .buswidth = 16, + .qos.ap_owned = true, + .qos.qos_mode = NOC_QOS_MODE_INVALID, + .qos.prio_level = 0, + .qos.areq_prio = 0, + .qos.qos_port = -1, +}; + +static struct qcom_icc_node * const msm8953_bimc_nodes[] = { + [MAS_APPS_PROC] = &mas_apps_proc, + [MAS_OXILI] = &mas_oxili, + [MAS_SNOC_BIMC_0] = &mas_snoc_bimc_0, + [MAS_SNOC_BIMC_2] = &mas_snoc_bimc_2, + [MAS_SNOC_BIMC_1] = &mas_snoc_bimc_1, + [MAS_TCU_0] = &mas_tcu_0, + [SLV_EBI] = &slv_ebi, + [SLV_BIMC_SNOC] = &slv_bimc_snoc, +}; + +static const struct regmap_config msm8953_bimc_regmap_config = { + .fast_io = true, + .max_register = 0x5a000, + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, +}; + +static const struct qcom_icc_desc msm8953_bimc = { + .type = QCOM_ICC_BIMC, + .bus_clk_desc = &bimc_clk, + .nodes = msm8953_bimc_nodes, + .num_nodes = ARRAY_SIZE(msm8953_bimc_nodes), + .qos_offset = 0x8000, + .regmap_cfg = &msm8953_bimc_regmap_config +}; + +static struct qcom_icc_node * const msm8953_pcnoc_nodes[] = { + [MAS_SPDM] = &mas_spdm, + [MAS_BLSP_1] = &mas_blsp_1, + [MAS_BLSP_2] = &mas_blsp_2, + [MAS_USB3] = &mas_usb3, + [MAS_CRYPTO] = &mas_crypto, + [MAS_SDCC_1] = &mas_sdcc_1, + [MAS_SDCC_2] = &mas_sdcc_2, + [MAS_SNOC_PCNOC] = &mas_snoc_pcnoc, + [PCNOC_M_0] = &pcnoc_m_0, + [PCNOC_M_1] = &pcnoc_m_1, + [PCNOC_INT_1] = &pcnoc_int_1, + [PCNOC_INT_2] = &pcnoc_int_2, + [PCNOC_S_0] = &pcnoc_s_0, + [PCNOC_S_1] = &pcnoc_s_1, + [PCNOC_S_2] = &pcnoc_s_2, + [PCNOC_S_3] = &pcnoc_s_3, + [PCNOC_S_4] = &pcnoc_s_4, + [PCNOC_S_6] = &pcnoc_s_6, + [PCNOC_S_7] = &pcnoc_s_7, + [PCNOC_S_8] = &pcnoc_s_8, + [PCNOC_S_9] = &pcnoc_s_9, + [SLV_SPDM] = &slv_spdm, + [SLV_PDM] = &slv_pdm, + [SLV_TCSR] = &slv_tcsr, + [SLV_SNOC_CFG] = &slv_snoc_cfg, + [SLV_TLMM] = &slv_tlmm, + [SLV_MESSAGE_RAM] = &slv_message_ram, + [SLV_BLSP_1] = &slv_blsp_1, + [SLV_BLSP_2] = &slv_blsp_2, + [SLV_PRNG] = &slv_prng, + [SLV_CAMERA_SS_CFG] = &slv_camera_ss_cfg, + [SLV_DISP_SS_CFG] = &slv_disp_ss_cfg, + [SLV_VENUS_CFG] = &slv_venus_cfg, + [SLV_GPU_CFG] = &slv_gpu_cfg, + [SLV_SDCC_1] = &slv_sdcc_1, + [SLV_SDCC_2] = &slv_sdcc_2, + [SLV_CRYPTO_0_CFG] = &slv_crypto_0_cfg, + [SLV_PMIC_ARB] = &slv_pmic_arb, + [SLV_USB3] = &slv_usb3, + [SLV_IPA_CFG] = &slv_ipa_cfg, + [SLV_TCU] = &slv_tcu, + [SLV_PCNOC_SNOC] = &slv_pcnoc_snoc, +}; + +static const char * const msm8953_pcnoc_intf_clocks[] = { + "pcnoc_usb3_axi" +}; + +static const struct regmap_config msm8953_pcnoc_regmap_config = { + .fast_io = true, + .max_register = 0x12080, + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, +}; + +static const struct qcom_icc_desc msm8953_pcnoc = { + .type = QCOM_ICC_NOC, + .bus_clk_desc = &bus_0_clk, + .intf_clocks = msm8953_pcnoc_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(msm8953_pcnoc_intf_clocks), + .nodes = msm8953_pcnoc_nodes, + .num_nodes = ARRAY_SIZE(msm8953_pcnoc_nodes), + .qos_offset = 0x7000, + .regmap_cfg = &msm8953_pcnoc_regmap_config, +}; + +static struct qcom_icc_node * const msm8953_snoc_nodes[] = { + [MAS_QDSS_BAM] = &mas_qdss_bam, + [MAS_BIMC_SNOC] = &mas_bimc_snoc, + [MAS_PCNOC_SNOC] = &mas_pcnoc_snoc, + [MAS_IPA] = &mas_ipa, + [MAS_QDSS_ETR] = &mas_qdss_etr, + [QDSS_INT] = &qdss_int, + [SNOC_INT_0] = &snoc_int_0, + [SNOC_INT_1] = &snoc_int_1, + [SNOC_INT_2] = &snoc_int_2, + [SLV_KPSS_AHB] = &slv_kpss_ahb, + [SLV_WCSS] = &slv_wcss, + [SLV_SNOC_BIMC_1] = &slv_snoc_bimc_1, + [SLV_IMEM] = &slv_imem, + [SLV_SNOC_PCNOC] = &slv_snoc_pcnoc, + [SLV_QDSS_STM] = &slv_qdss_stm, + [SLV_CATS_1] = &slv_cats_1, + [SLV_LPASS] = &slv_lpass, +}; + +static const struct regmap_config msm8953_snoc_regmap_config = { + .fast_io = true, + .max_register = 0x16080, + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, +}; + +static const struct qcom_icc_desc msm8953_snoc = { + .type = QCOM_ICC_NOC, + .bus_clk_desc = &bus_1_clk, + .nodes = msm8953_snoc_nodes, + .num_nodes = ARRAY_SIZE(msm8953_snoc_nodes), + .qos_offset = 0x7000, + .regmap_cfg = &msm8953_snoc_regmap_config, +}; + +static struct qcom_icc_node * const msm8953_snoc_mm_nodes[] = { + [MAS_JPEG] = &mas_jpeg, + [MAS_MDP] = &mas_mdp, + [MAS_VENUS] = &mas_venus, + [MAS_VFE0] = &mas_vfe0, + [MAS_VFE1] = &mas_vfe1, + [MAS_CPP] = &mas_cpp, + [SLV_SNOC_BIMC_0] = &slv_snoc_bimc_0, + [SLV_SNOC_BIMC_2] = &slv_snoc_bimc_2, + [SLV_CATS_0] = &slv_cats_0, +}; + +static const struct qcom_icc_desc msm8953_snoc_mm = { + .type = QCOM_ICC_NOC, + .bus_clk_desc = &bus_2_clk, + .nodes = msm8953_snoc_mm_nodes, + .num_nodes = ARRAY_SIZE(msm8953_snoc_mm_nodes), + .qos_offset = 0x7000, + .regmap_cfg = &msm8953_snoc_regmap_config, +}; + +static const struct of_device_id msm8953_noc_of_match[] = { + { .compatible = "qcom,msm8953-bimc", .data = &msm8953_bimc }, + { .compatible = "qcom,msm8953-pcnoc", .data = &msm8953_pcnoc }, + { .compatible = "qcom,msm8953-snoc", .data = &msm8953_snoc }, + { .compatible = "qcom,msm8953-snoc-mm", .data = &msm8953_snoc_mm }, + { } +}; + +static struct platform_driver msm8953_noc_driver = { + .probe = qnoc_probe, + .remove_new = qnoc_remove, + .driver = { + .name = "qnoc-msm8953", + .of_match_table = msm8953_noc_of_match, + }, +}; + +module_platform_driver(msm8953_noc_driver); +MODULE_DEVICE_TABLE(of, msm8953_noc_of_match); +MODULE_DESCRIPTION("Qualcomm MSM8953 NoC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c index ba4cc08684d6..ccbdc6202c07 100644 --- a/drivers/interconnect/qcom/qcm2290.c +++ b/drivers/interconnect/qcom/qcm2290.c @@ -166,7 +166,7 @@ static struct qcom_icc_node mas_snoc_bimc = { .qos.ap_owned = true, .qos.qos_port = 6, .qos.qos_mode = NOC_QOS_MODE_BYPASS, - .mas_rpm_id = 164, + .mas_rpm_id = 3, .slv_rpm_id = -1, .num_links = ARRAY_SIZE(mas_snoc_bimc_links), .links = mas_snoc_bimc_links, diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c index 7d33694368e8..167971f8e8be 100644 --- a/drivers/interconnect/qcom/sc7280.c +++ b/drivers/interconnect/qcom/sc7280.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. * */ @@ -21,6 +22,12 @@ static struct qcom_icc_node qhm_qspi = { .id = SC7280_MASTER_QSPI_0, .channels = 1, .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x7000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -30,6 +37,12 @@ static struct qcom_icc_node qhm_qup0 = { .id = SC7280_MASTER_QUP_0, .channels = 1, .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x11000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -39,6 +52,12 @@ static struct qcom_icc_node qhm_qup1 = { .id = SC7280_MASTER_QUP_1, .channels = 1, .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x8000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -57,6 +76,12 @@ static struct qcom_icc_node xm_sdc1 = { .id = SC7280_MASTER_SDCC_1, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xc000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -66,6 +91,12 @@ static struct qcom_icc_node xm_sdc2 = { .id = SC7280_MASTER_SDCC_2, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xe000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -75,6 +106,12 @@ static struct qcom_icc_node xm_sdc4 = { .id = SC7280_MASTER_SDCC_4, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x9000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -84,6 +121,12 @@ static struct qcom_icc_node xm_ufs_mem = { .id = SC7280_MASTER_UFS_MEM, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xa000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -102,6 +145,12 @@ static struct qcom_icc_node xm_usb3_0 = { .id = SC7280_MASTER_USB3_0, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xb000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A1NOC_SNOC }, }; @@ -111,6 +160,12 @@ static struct qcom_icc_node qhm_qdss_bam = { .id = SC7280_MASTER_QDSS_BAM, .channels = 1, .buswidth = 4, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x18000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A2NOC_SNOC }, }; @@ -129,6 +184,12 @@ static struct qcom_icc_node qnm_cnoc_datapath = { .id = SC7280_MASTER_CNOC_A2NOC, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1c000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A2NOC_SNOC }, }; @@ -138,6 +199,12 @@ static struct qcom_icc_node qxm_crypto = { .id = SC7280_MASTER_CRYPTO, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x1d000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A2NOC_SNOC }, }; @@ -147,6 +214,12 @@ static struct qcom_icc_node qxm_ipa = { .id = SC7280_MASTER_IPA, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x10000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A2NOC_SNOC }, }; @@ -173,6 +246,12 @@ static struct qcom_icc_node xm_qdss_etr = { .id = SC7280_MASTER_QDSS_ETR, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x15000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_A2NOC_SNOC }, }; @@ -305,6 +384,12 @@ static struct qcom_icc_node alm_gpu_tcu = { .id = SC7280_MASTER_GPU_TCU, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xd7000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 2, .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, }; @@ -314,6 +399,12 @@ static struct qcom_icc_node alm_sys_tcu = { .id = SC7280_MASTER_SYS_TCU, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xd6000 }, + .prio = 6, + .urg_fwd = 0, + }, .num_links = 2, .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, }; @@ -333,6 +424,12 @@ static struct qcom_icc_node qnm_cmpnoc = { .id = SC7280_MASTER_COMPUTE_NOC, .channels = 2, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x21000, 0x61000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 2, .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, }; @@ -353,6 +450,12 @@ static struct qcom_icc_node qnm_gpu = { .id = SC7280_MASTER_GFX3D, .channels = 2, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x22000, 0x62000 }, + .prio = 0, + .urg_fwd = 0, + }, .num_links = 2, .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, }; @@ -362,6 +465,12 @@ static struct qcom_icc_node qnm_mnoc_hf = { .id = SC7280_MASTER_MNOC_HF_MEM_NOC, .channels = 2, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x23000, 0x63000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_LLCC }, }; @@ -371,6 +480,12 @@ static struct qcom_icc_node qnm_mnoc_sf = { .id = SC7280_MASTER_MNOC_SF_MEM_NOC, .channels = 1, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xcf000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 2, .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, }; @@ -389,6 +504,12 @@ static struct qcom_icc_node qnm_snoc_gc = { .id = SC7280_MASTER_SNOC_GC_MEM_NOC, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xd3000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_LLCC }, }; @@ -398,6 +519,12 @@ static struct qcom_icc_node qnm_snoc_sf = { .id = SC7280_MASTER_SNOC_SF_MEM_NOC, .channels = 1, .buswidth = 16, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xd4000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 3, .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC, SC7280_SLAVE_MEM_NOC_PCIE_SNOC }, @@ -437,6 +564,12 @@ static struct qcom_icc_node qnm_video0 = { .id = SC7280_MASTER_VIDEO_P0, .channels = 1, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x14000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, }; @@ -446,6 +579,12 @@ static struct qcom_icc_node qnm_video_cpu = { .id = SC7280_MASTER_VIDEO_PROC, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x15000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, }; @@ -455,6 +594,12 @@ static struct qcom_icc_node qxm_camnoc_hf = { .id = SC7280_MASTER_CAMNOC_HF, .channels = 2, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 2, + .port_offsets = { 0x10000, 0x10180 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_MNOC_HF_MEM_NOC }, }; @@ -464,6 +609,12 @@ static struct qcom_icc_node qxm_camnoc_icp = { .id = SC7280_MASTER_CAMNOC_ICP, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x11000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, }; @@ -473,6 +624,12 @@ static struct qcom_icc_node qxm_camnoc_sf = { .id = SC7280_MASTER_CAMNOC_SF, .channels = 1, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x12000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, }; @@ -482,6 +639,12 @@ static struct qcom_icc_node qxm_mdp0 = { .id = SC7280_MASTER_MDP0, .channels = 1, .buswidth = 32, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x16000 }, + .prio = 0, + .urg_fwd = 1, + }, .num_links = 1, .links = { SC7280_SLAVE_MNOC_HF_MEM_NOC }, }; @@ -536,6 +699,12 @@ static struct qcom_icc_node qxm_pimem = { .id = SC7280_MASTER_PIMEM, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0x8000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_SNOC_GEM_NOC_GC }, }; @@ -545,6 +714,12 @@ static struct qcom_icc_node xm_gic = { .id = SC7280_MASTER_GIC, .channels = 1, .buswidth = 8, + .qosbox = &(const struct qcom_icc_qosbox) { + .num_ports = 1, + .port_offsets = { 0xa000 }, + .prio = 2, + .urg_fwd = 0, + }, .num_links = 1, .links = { SC7280_SLAVE_SNOC_GEM_NOC_GC }, }; @@ -1502,17 +1677,35 @@ static struct qcom_icc_node * const aggre1_noc_nodes[] = { [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, }; +static const struct regmap_config sc7280_aggre1_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1c080, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_aggre1_noc = { + .config = &sc7280_aggre1_noc_regmap_config, .nodes = aggre1_noc_nodes, .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), .bcms = aggre1_noc_bcms, .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), + .qos_clks_required = true, }; static struct qcom_icc_bcm * const aggre2_noc_bcms[] = { &bcm_ce0, }; +static const struct regmap_config sc7280_aggre2_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x2b080, + .fast_io = true, +}; + static struct qcom_icc_node * const aggre2_noc_nodes[] = { [MASTER_QDSS_BAM] = &qhm_qdss_bam, [MASTER_A2NOC_CFG] = &qnm_a2noc_cfg, @@ -1525,10 +1718,12 @@ static struct qcom_icc_node * const aggre2_noc_nodes[] = { }; static const struct qcom_icc_desc sc7280_aggre2_noc = { + .config = &sc7280_aggre2_noc_regmap_config, .nodes = aggre2_noc_nodes, .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), .bcms = aggre2_noc_bcms, .num_bcms = ARRAY_SIZE(aggre2_noc_bcms), + .qos_clks_required = true, }; static struct qcom_icc_bcm * const clk_virt_bcms[] = { @@ -1605,7 +1800,16 @@ static struct qcom_icc_node * const cnoc2_nodes[] = { [SLAVE_SNOC_CFG] = &qns_snoc_cfg, }; +static const struct regmap_config sc7280_cnoc2_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1000, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_cnoc2 = { + .config = &sc7280_cnoc2_regmap_config, .nodes = cnoc2_nodes, .num_nodes = ARRAY_SIZE(cnoc2_nodes), .bcms = cnoc2_bcms, @@ -1637,7 +1841,16 @@ static struct qcom_icc_node * const cnoc3_nodes[] = { [SLAVE_TCU] = &xs_sys_tcu_cfg, }; +static const struct regmap_config sc7280_cnoc3_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1000, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_cnoc3 = { + .config = &sc7280_cnoc3_regmap_config, .nodes = cnoc3_nodes, .num_nodes = ARRAY_SIZE(cnoc3_nodes), .bcms = cnoc3_bcms, @@ -1653,7 +1866,16 @@ static struct qcom_icc_node * const dc_noc_nodes[] = { [SLAVE_GEM_NOC_CFG] = &qns_gemnoc, }; +static const struct regmap_config sc7280_dc_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x5080, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_dc_noc = { + .config = &sc7280_dc_noc_regmap_config, .nodes = dc_noc_nodes, .num_nodes = ARRAY_SIZE(dc_noc_nodes), .bcms = dc_noc_bcms, @@ -1689,7 +1911,16 @@ static struct qcom_icc_node * const gem_noc_nodes[] = { [SLAVE_SERVICE_GEM_NOC] = &srvc_sys_gemnoc, }; +static const struct regmap_config sc7280_gem_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xe2200, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_gem_noc = { + .config = &sc7280_gem_noc_regmap_config, .nodes = gem_noc_nodes, .num_nodes = ARRAY_SIZE(gem_noc_nodes), .bcms = gem_noc_bcms, @@ -1709,7 +1940,16 @@ static struct qcom_icc_node * const lpass_ag_noc_nodes[] = { [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc, }; +static const struct regmap_config sc7280_lpass_ag_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xf080, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_lpass_ag_noc = { + .config = &sc7280_lpass_ag_noc_regmap_config, .nodes = lpass_ag_noc_nodes, .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes), .bcms = lpass_ag_noc_bcms, @@ -1726,7 +1966,16 @@ static struct qcom_icc_node * const mc_virt_nodes[] = { [SLAVE_EBI1] = &ebi, }; +static const struct regmap_config sc7280_mc_virt_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x4, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_mc_virt = { + .config = &sc7280_mc_virt_regmap_config, .nodes = mc_virt_nodes, .num_nodes = ARRAY_SIZE(mc_virt_nodes), .bcms = mc_virt_bcms, @@ -1753,7 +2002,16 @@ static struct qcom_icc_node * const mmss_noc_nodes[] = { [SLAVE_SERVICE_MNOC] = &srvc_mnoc, }; +static const struct regmap_config sc7280_mmss_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1e080, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_mmss_noc = { + .config = &sc7280_mmss_noc_regmap_config, .nodes = mmss_noc_nodes, .num_nodes = ARRAY_SIZE(mmss_noc_nodes), .bcms = mmss_noc_bcms, @@ -1772,7 +2030,16 @@ static struct qcom_icc_node * const nsp_noc_nodes[] = { [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc, }; +static const struct regmap_config sc7280_nsp_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x10000, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_nsp_noc = { + .config = &sc7280_nsp_noc_regmap_config, .nodes = nsp_noc_nodes, .num_nodes = ARRAY_SIZE(nsp_noc_nodes), .bcms = nsp_noc_bcms, @@ -1797,7 +2064,16 @@ static struct qcom_icc_node * const system_noc_nodes[] = { [SLAVE_SERVICE_SNOC] = &srvc_snoc, }; +static const struct regmap_config sc7280_system_noc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x15480, + .fast_io = true, +}; + static const struct qcom_icc_desc sc7280_system_noc = { + .config = &sc7280_system_noc_regmap_config, .nodes = system_noc_nodes, .num_nodes = ARRAY_SIZE(system_noc_nodes), .bcms = system_noc_bcms, diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c index 1ae37e693de0..a5f8ab9a0910 100644 --- a/drivers/mcb/mcb-parse.c +++ b/drivers/mcb/mcb-parse.c @@ -8,11 +8,6 @@ #include "mcb-internal.h" -struct mcb_parse_priv { - phys_addr_t mapbase; - void __iomem *base; -}; - #define for_each_chameleon_cell(dtype, p) \ for ((dtype) = get_next_dtype((p)); \ (dtype) != CHAMELEON_DTYPE_END; \ diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c index 53d9202ff9a7..3b634ea318c7 100644 --- a/drivers/mcb/mcb-pci.c +++ b/drivers/mcb/mcb-pci.c @@ -45,6 +45,14 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) } pci_set_master(pdev); + flags = pci_resource_flags(pdev, 0); + if (flags & IORESOURCE_IO) { + ret = -ENOTSUPP; + dev_err(&pdev->dev, + "IO mapped PCI devices are not supported\n"); + goto out_disable; + } + priv->mapbase = pci_resource_start(pdev, 0); if (!priv->mapbase) { dev_err(&pdev->dev, "No PCI resource\n"); @@ -68,14 +76,6 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_disable; } - flags = pci_resource_flags(pdev, 0); - if (flags & IORESOURCE_IO) { - ret = -ENOTSUPP; - dev_err(&pdev->dev, - "IO mapped PCI devices are not supported\n"); - goto out_disable; - } - pci_set_drvdata(pdev, priv); priv->bus = mcb_alloc_bus(&pdev->dev); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 36be8392a9e2..fd2a0f6d4b67 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -593,6 +593,21 @@ config NSM To compile this driver as a module, choose M here. The module will be called nsm. +config MARVELL_CN10K_DPI + tristate "Octeon CN10K DPI driver" + depends on PCI + depends on ARCH_THUNDER || (COMPILE_TEST && 64BIT) + help + Enables Octeon CN10K DMA packet interface (DPI) driver which + intializes DPI hardware's physical function (PF) device's + global configuration and its virtual function (VFs) resource + configuration to enable DMA transfers. DPI PF device does not + have any data movement functionality, it only serves VF's + resource configuration requests. + + To compile this driver as a module, choose M here: the module + will be called mrvl_cn10k_dpi. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" @@ -610,4 +625,5 @@ source "drivers/misc/cardreader/Kconfig" source "drivers/misc/uacce/Kconfig" source "drivers/misc/pvpanic/Kconfig" source "drivers/misc/mchp_pci1xxxx/Kconfig" +source "drivers/misc/keba/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5a777b13bcdf..f060107cc316 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -69,4 +69,6 @@ obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o 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_UID_SYS_STATS) += uid_sys_stats.o diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c index 693f0e539f37..6db4db975b9a 100644 --- a/drivers/misc/apds9802als.c +++ b/drivers/misc/apds9802als.c @@ -285,7 +285,7 @@ static UNIVERSAL_DEV_PM_OPS(apds9802als_pm_ops, apds9802als_suspend, #endif /* CONFIG_PM */ static const struct i2c_device_id apds9802als_id[] = { - { DRIVER_NAME, 0 }, + { DRIVER_NAME }, { } }; diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index 92b92be91d60..6d4edd69db12 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c @@ -625,15 +625,15 @@ static ssize_t apds990x_lux_show(struct device *dev, struct apds990x_chip *chip = dev_get_drvdata(dev); ssize_t ret; u32 result; - long timeout; + long time_left; if (pm_runtime_suspended(dev)) return -EIO; - timeout = wait_event_interruptible_timeout(chip->wait, - !chip->lux_wait_fresh_res, - msecs_to_jiffies(APDS_TIMEOUT)); - if (!timeout) + time_left = wait_event_interruptible_timeout(chip->wait, + !chip->lux_wait_fresh_res, + msecs_to_jiffies(APDS_TIMEOUT)); + if (!time_left) return -EIO; mutex_lock(&chip->mutex); @@ -1253,7 +1253,7 @@ static int apds990x_runtime_resume(struct device *dev) #endif static const struct i2c_device_id apds990x_id[] = { - {"apds990x", 0 }, + { "apds990x" }, {} }; diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index 1629b62fd052..0c052b05ab6a 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c @@ -680,15 +680,15 @@ static ssize_t bh1770_lux_result_show(struct device *dev, { struct bh1770_chip *chip = dev_get_drvdata(dev); ssize_t ret; - long timeout; + long time_left; if (pm_runtime_suspended(dev)) return -EIO; /* Chip is not enabled at all */ - timeout = wait_event_interruptible_timeout(chip->wait, - !chip->lux_wait_result, - msecs_to_jiffies(BH1770_TIMEOUT)); - if (!timeout) + time_left = wait_event_interruptible_timeout(chip->wait, + !chip->lux_wait_result, + msecs_to_jiffies(BH1770_TIMEOUT)); + if (!time_left) return -EIO; mutex_lock(&chip->mutex); @@ -1361,8 +1361,8 @@ static int bh1770_runtime_resume(struct device *dev) #endif static const struct i2c_device_id bh1770_id[] = { - {"bh1770glc", 0 }, - {"sfh7770", 0 }, + { "bh1770glc" }, + { "sfh7770" }, {} }; diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c index 5f8dcd0e3848..4175df7ef011 100644 --- a/drivers/misc/ds1682.c +++ b/drivers/misc/ds1682.c @@ -271,7 +271,7 @@ static void ds1682_remove(struct i2c_client *client) } static const struct i2c_device_id ds1682_id[] = { - { "ds1682", 0 }, + { "ds1682" }, { } }; MODULE_DEVICE_TABLE(i2c, ds1682_id); diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 4e61ac18cc96..9df12399bda3 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -109,6 +109,8 @@ config EEPROM_IDT_89HPESX config EEPROM_EE1004 tristate "SPD EEPROMs on DDR4 memory modules" depends on I2C && SYSFS + select NVMEM + select NVMEM_SYSFS help Enable this driver to get read support to SPD EEPROMs following the JEDEC EE1004 standard. These are typically found on DDR4 diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 4bd4f32bcdab..ca872e3465ed 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -174,6 +174,10 @@ AT24_CHIP_DATA(at24_data_24mac402, 48 / 8, AT24_FLAG_MAC | AT24_FLAG_READONLY); AT24_CHIP_DATA(at24_data_24mac602, 64 / 8, AT24_FLAG_MAC | AT24_FLAG_READONLY); +AT24_CHIP_DATA(at24_data_24aa025e48, 48 / 8, + AT24_FLAG_READONLY); +AT24_CHIP_DATA(at24_data_24aa025e64, 64 / 8, + AT24_FLAG_READONLY); /* spd is a 24c02 in memory DIMMs */ AT24_CHIP_DATA(at24_data_spd, 2048 / 8, AT24_FLAG_READONLY | AT24_FLAG_IRUGO); @@ -218,6 +222,8 @@ static const struct i2c_device_id at24_ids[] = { { "24cs02", (kernel_ulong_t)&at24_data_24cs02 }, { "24mac402", (kernel_ulong_t)&at24_data_24mac402 }, { "24mac602", (kernel_ulong_t)&at24_data_24mac602 }, + { "24aa025e48", (kernel_ulong_t)&at24_data_24aa025e48 }, + { "24aa025e64", (kernel_ulong_t)&at24_data_24aa025e64 }, { "spd", (kernel_ulong_t)&at24_data_spd }, { "24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio }, { "24c04", (kernel_ulong_t)&at24_data_24c04 }, @@ -270,6 +276,8 @@ static const struct of_device_id __maybe_unused at24_of_match[] = { { .compatible = "atmel,24c1024", .data = &at24_data_24c1024 }, { .compatible = "atmel,24c1025", .data = &at24_data_24c1025 }, { .compatible = "atmel,24c2048", .data = &at24_data_24c2048 }, + { .compatible = "microchip,24aa025e48", .data = &at24_data_24aa025e48 }, + { .compatible = "microchip,24aa025e64", .data = &at24_data_24aa025e64 }, { /* END OF LIST */ }, }; MODULE_DEVICE_TABLE(of, at24_of_match); diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c index f1f766b70965..88888485e6f8 100644 --- a/drivers/misc/eeprom/digsy_mtc_eeprom.c +++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c @@ -14,13 +14,12 @@ * and delete this driver. */ -#include #include #include #include +#include #include #include -#include #define GPIO_EEPROM_CLK 216 #define GPIO_EEPROM_CS 210 @@ -29,22 +28,13 @@ #define GPIO_EEPROM_OE 255 #define EE_SPI_BUS_NUM 1 -static void digsy_mtc_op_prepare(void *p) -{ - /* enable */ - gpio_set_value(GPIO_EEPROM_OE, 0); -} +static const struct property_entry digsy_mtc_spi_properties[] = { + PROPERTY_ENTRY_U32("data-size", 8), + { } +}; -static void digsy_mtc_op_finish(void *p) -{ - /* disable */ - gpio_set_value(GPIO_EEPROM_OE, 1); -} - -struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = { - .flags = EE_ADDR8, - .prepare = digsy_mtc_op_prepare, - .finish = digsy_mtc_op_finish, +static const struct software_node digsy_mtc_spi_node = { + .properties = digsy_mtc_spi_properties, }; static struct spi_gpio_platform_data eeprom_spi_gpio_data = { @@ -70,18 +60,19 @@ static struct gpiod_lookup_table eeprom_spi_gpiod_table = { "miso", GPIO_ACTIVE_HIGH), GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CS, "cs", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_OE, + "select", GPIO_ACTIVE_LOW), { }, }, }; static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = { { - .modalias = "93xx46", + .modalias = "eeprom-93xx46", .max_speed_hz = 1000000, .bus_num = EE_SPI_BUS_NUM, .chip_select = 0, .mode = SPI_MODE_0, - .platform_data = &digsy_mtc_eeprom_data, }, }; @@ -89,15 +80,18 @@ static int __init digsy_mtc_eeprom_devices_init(void) { int ret; - ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH, - "93xx46 EEPROMs OE"); - if (ret) { - pr_err("can't request gpio %d\n", GPIO_EEPROM_OE); - return ret; - } gpiod_add_lookup_table(&eeprom_spi_gpiod_table); spi_register_board_info(digsy_mtc_eeprom_info, ARRAY_SIZE(digsy_mtc_eeprom_info)); - return platform_device_register(&digsy_mtc_eeprom); + + ret = device_add_software_node(&digsy_mtc_eeprom.dev, &digsy_mtc_spi_node); + if (ret) + return ret; + + ret = platform_device_register(&digsy_mtc_eeprom); + if (ret) + device_remove_software_node(&digsy_mtc_eeprom.dev); + + return ret; } device_initcall(digsy_mtc_eeprom_devices_init); diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index 21feebc3044c..d4aeeb2b2169 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -9,12 +9,14 @@ * Copyright (C) 2008 Wolfram Sang, Pengutronix */ +#include #include #include #include #include #include #include +#include /* * DDR4 memory modules use special EEPROMs following the Jedec EE1004 @@ -52,7 +54,7 @@ static struct ee1004_bus_data { } ee1004_bus_data[EE1004_MAX_BUSSES]; static const struct i2c_device_id ee1004_ids[] = { - { "ee1004", 0 }, + { "ee1004" }, { } }; MODULE_DEVICE_TABLE(i2c, ee1004_ids); @@ -144,13 +146,17 @@ static ssize_t ee1004_eeprom_read(struct i2c_client *client, char *buf, return i2c_smbus_read_i2c_block_data_or_emulated(client, offset, count, buf); } -static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static int ee1004_read(void *priv, unsigned int off, void *val, size_t count) { - struct i2c_client *client = kobj_to_i2c_client(kobj); - size_t requested = count; - int ret = 0; + struct i2c_client *client = priv; + char *buf = val; + int ret; + + if (unlikely(!count)) + return count; + + if (off + count > EE1004_EEPROM_SIZE) + return -EINVAL; /* * Read data from chip, protecting against concurrent access to @@ -160,42 +166,52 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, while (count) { ret = ee1004_eeprom_read(client, buf, off, count); - if (ret < 0) - goto out; + if (ret < 0) { + mutex_unlock(&ee1004_bus_lock); + return ret; + } buf += ret; off += ret; count -= ret; } -out: + mutex_unlock(&ee1004_bus_lock); - return ret < 0 ? ret : requested; + return 0; } -static BIN_ATTR_RO(eeprom, EE1004_EEPROM_SIZE); - -static struct bin_attribute *ee1004_attrs[] = { - &bin_attr_eeprom, - NULL -}; - -BIN_ATTRIBUTE_GROUPS(ee1004); - static void ee1004_probe_temp_sensor(struct i2c_client *client) { struct i2c_board_info info = { .type = "jc42" }; - u8 byte14; + unsigned short addr = 0x18 | (client->addr & 7); + unsigned short addr_list[] = { addr, I2C_CLIENT_END }; + u8 data[2]; int ret; /* byte 14, bit 7 is set if temp sensor is present */ - ret = ee1004_eeprom_read(client, &byte14, 14, 1); - if (ret != 1 || !(byte14 & BIT(7))) + ret = ee1004_eeprom_read(client, data, 14, 1); + if (ret != 1) return; - info.addr = 0x18 | (client->addr & 7); - - i2c_new_client_device(client->adapter, &info); + if (!(data[0] & BIT(7))) { + /* + * If the SPD data suggests that there is no temperature + * sensor, it may still be there for SPD revision 1.0. + * See SPD Annex L, Revision 1 and 2, for details. + * Check DIMM type and SPD revision; if it is a DDR4 + * with SPD revision 1.0, check the thermal sensor address + * and instantiate the jc42 driver if a chip is found at + * that address. + * It is not necessary to check if there is a chip at the + * temperature sensor address since i2c_new_scanned_device() + * will do that and return silently if no chip is found. + */ + ret = ee1004_eeprom_read(client, data, 1, 2); + if (ret != 2 || data[0] != 0x10 || data[1] != 0x0c) + return; + } + i2c_new_scanned_device(client->adapter, &info, addr_list, NULL); } static void ee1004_cleanup(int idx, struct ee1004_bus_data *bd) @@ -207,9 +223,36 @@ static void ee1004_cleanup(int idx, struct ee1004_bus_data *bd) } } +static void ee1004_cleanup_bus_data(void *data) +{ + struct ee1004_bus_data *bd = data; + + /* Remove page select clients if this is the last device */ + mutex_lock(&ee1004_bus_lock); + ee1004_cleanup(EE1004_NUM_PAGES, bd); + mutex_unlock(&ee1004_bus_lock); +} + static int ee1004_probe(struct i2c_client *client) { + struct nvmem_config config = { + .dev = &client->dev, + .name = dev_name(&client->dev), + .id = NVMEM_DEVID_NONE, + .owner = THIS_MODULE, + .type = NVMEM_TYPE_EEPROM, + .read_only = true, + .root_only = false, + .reg_read = ee1004_read, + .size = EE1004_EEPROM_SIZE, + .word_size = 1, + .stride = 1, + .priv = client, + .compat = true, + .base_dev = &client->dev, + }; struct ee1004_bus_data *bd; + struct nvmem_device *ndev; int err, cnr = 0; /* Make sure we can operate on this adapter */ @@ -228,6 +271,10 @@ static int ee1004_probe(struct i2c_client *client) "Only %d busses supported", EE1004_MAX_BUSSES); } + err = devm_add_action_or_reset(&client->dev, ee1004_cleanup_bus_data, bd); + if (err < 0) + return err; + i2c_set_clientdata(client, bd); if (++bd->dev_count == 1) { @@ -237,16 +284,18 @@ static int ee1004_probe(struct i2c_client *client) cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); if (IS_ERR(cl)) { - err = PTR_ERR(cl); - goto err_clients; + mutex_unlock(&ee1004_bus_lock); + return PTR_ERR(cl); } bd->set_page[cnr] = cl; } /* Remember current page to avoid unneeded page select */ err = ee1004_get_current_page(bd); - if (err < 0) - goto err_clients; + if (err < 0) { + mutex_unlock(&ee1004_bus_lock); + return err; + } dev_dbg(&client->dev, "Currently selected page: %d\n", err); bd->current_page = err; } @@ -255,27 +304,15 @@ static int ee1004_probe(struct i2c_client *client) mutex_unlock(&ee1004_bus_lock); + ndev = devm_nvmem_register(&client->dev, &config); + if (IS_ERR(ndev)) + return PTR_ERR(ndev); + dev_info(&client->dev, "%u byte EE1004-compliant SPD EEPROM, read-only\n", EE1004_EEPROM_SIZE); return 0; - - err_clients: - ee1004_cleanup(cnr, bd); - mutex_unlock(&ee1004_bus_lock); - - return err; -} - -static void ee1004_remove(struct i2c_client *client) -{ - struct ee1004_bus_data *bd = i2c_get_clientdata(client); - - /* Remove page select clients if this is the last device */ - mutex_lock(&ee1004_bus_lock); - ee1004_cleanup(EE1004_NUM_PAGES, bd); - mutex_unlock(&ee1004_bus_lock); } /*-------------------------------------------------------------------------*/ @@ -283,10 +320,8 @@ static void ee1004_remove(struct i2c_client *client) static struct i2c_driver ee1004_driver = { .driver = { .name = "ee1004", - .dev_groups = ee1004_groups, }, .probe = ee1004_probe, - .remove = ee1004_remove, .id_table = ee1004_ids, }; module_i2c_driver(ee1004_driver); diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 45c8ae0db8f9..e2221be88445 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -5,19 +5,42 @@ * (C) 2011 DENX Software Engineering, Anatolij Gustschin */ +#include +#include #include #include #include -#include +#include #include +#include #include #include -#include -#include +#include #include #include +#include + #include -#include + +struct eeprom_93xx46_platform_data { + unsigned char flags; +#define EE_ADDR8 0x01 /* 8 bit addr. cfg */ +#define EE_ADDR16 0x02 /* 16 bit addr. cfg */ +#define EE_READONLY 0x08 /* forbid writing */ +#define EE_SIZE1K 0x10 /* 1 kb of data, that is a 93xx46 */ +#define EE_SIZE2K 0x20 /* 2 kb of data, that is a 93xx56 */ +#define EE_SIZE4K 0x40 /* 4 kb of data, that is a 93xx66 */ + + unsigned int quirks; +/* Single word read transfers only; no sequential read. */ +#define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) +/* Instructions such as EWEN are (addrlen + 2) in length. */ +#define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) +/* Add extra cycle after address during a read */ +#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2) + + struct gpio_desc *select; +}; #define OP_START 0x4 #define OP_WRITE (OP_START | 0x1) @@ -96,15 +119,14 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, mutex_lock(&edev->lock); - if (edev->pdata->prepare) - edev->pdata->prepare(edev); + gpiod_set_value_cansleep(edev->pdata->select, 1); /* The opcode in front of the address is three bits. */ bits = edev->addrlen + 3; while (count) { struct spi_message m; - struct spi_transfer t[2] = { { 0 } }; + struct spi_transfer t[2] = {}; u16 cmd_addr = OP_READ << edev->addrlen; size_t nbytes = count; @@ -126,25 +148,23 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, bits += 1; } - spi_message_init(&m); - t[0].tx_buf = (char *)&cmd_addr; t[0].len = 2; t[0].bits_per_word = bits; - spi_message_add_tail(&t[0], &m); t[1].rx_buf = buf; t[1].len = count; t[1].bits_per_word = 8; - spi_message_add_tail(&t[1], &m); + + spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t)); err = spi_sync(edev->spi, &m); /* have to wait at least Tcsl ns */ ndelay(250); if (err) { - dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n", - nbytes, (int)off, err); + dev_err(&edev->spi->dev, "read %zu bytes at %u: err. %d\n", + nbytes, off, err); break; } @@ -153,8 +173,7 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, count -= nbytes; } - if (edev->pdata->finish) - edev->pdata->finish(edev); + gpiod_set_value_cansleep(edev->pdata->select, 0); mutex_unlock(&edev->lock); @@ -164,7 +183,7 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) { struct spi_message m; - struct spi_transfer t; + struct spi_transfer t = {}; int bits, ret; u16 cmd_addr; @@ -182,31 +201,27 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) bits += 2; } - dev_dbg(&edev->spi->dev, "ew%s cmd 0x%04x, %d bits\n", - is_on ? "en" : "ds", cmd_addr, bits); - - spi_message_init(&m); - memset(&t, 0, sizeof(t)); + dev_dbg(&edev->spi->dev, "ew %s cmd 0x%04x, %d bits\n", + str_enable_disable(is_on), cmd_addr, bits); t.tx_buf = &cmd_addr; t.len = 2; t.bits_per_word = bits; - spi_message_add_tail(&t, &m); + + spi_message_init_with_transfers(&m, &t, 1); mutex_lock(&edev->lock); - if (edev->pdata->prepare) - edev->pdata->prepare(edev); + gpiod_set_value_cansleep(edev->pdata->select, 1); ret = spi_sync(edev->spi, &m); /* have to wait at least Tcsl ns */ ndelay(250); if (ret) - dev_err(&edev->spi->dev, "erase/write %sable error %d\n", - is_on ? "en" : "dis", ret); + dev_err(&edev->spi->dev, "erase/write %s error %d\n", + str_enable_disable(is_on), ret); - if (edev->pdata->finish) - edev->pdata->finish(edev); + gpiod_set_value_cansleep(edev->pdata->select, 0); mutex_unlock(&edev->lock); return ret; @@ -217,7 +232,7 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, const char *buf, unsigned off) { struct spi_message m; - struct spi_transfer t[2]; + struct spi_transfer t[2] = {}; int bits, data_len, ret; u16 cmd_addr; @@ -239,18 +254,15 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr); - spi_message_init(&m); - memset(t, 0, sizeof(t)); - t[0].tx_buf = (char *)&cmd_addr; t[0].len = 2; t[0].bits_per_word = bits; - spi_message_add_tail(&t[0], &m); t[1].tx_buf = buf; t[1].len = data_len; t[1].bits_per_word = 8; - spi_message_add_tail(&t[1], &m); + + spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t)); ret = spi_sync(edev->spi, &m); /* have to wait program cycle time Twc ms */ @@ -263,7 +275,8 @@ static int eeprom_93xx46_write(void *priv, unsigned int off, { struct eeprom_93xx46_dev *edev = priv; char *buf = val; - int i, ret, step = 1; + int ret, step = 1; + unsigned int i; if (unlikely(off >= edev->size)) return -EFBIG; @@ -285,20 +298,17 @@ static int eeprom_93xx46_write(void *priv, unsigned int off, mutex_lock(&edev->lock); - if (edev->pdata->prepare) - edev->pdata->prepare(edev); + gpiod_set_value_cansleep(edev->pdata->select, 1); for (i = 0; i < count; i += step) { ret = eeprom_93xx46_write_word(edev, &buf[i], off + i); if (ret) { - dev_err(&edev->spi->dev, "write failed at %d: %d\n", - (int)off + i, ret); + dev_err(&edev->spi->dev, "write failed at %u: %d\n", off + i, ret); break; } } - if (edev->pdata->finish) - edev->pdata->finish(edev); + gpiod_set_value_cansleep(edev->pdata->select, 0); mutex_unlock(&edev->lock); @@ -309,9 +319,8 @@ static int eeprom_93xx46_write(void *priv, unsigned int off, static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) { - struct eeprom_93xx46_platform_data *pd = edev->pdata; struct spi_message m; - struct spi_transfer t; + struct spi_transfer t = {}; int bits, ret; u16 cmd_addr; @@ -331,18 +340,15 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) dev_dbg(&edev->spi->dev, "eral cmd 0x%04x, %d bits\n", cmd_addr, bits); - spi_message_init(&m); - memset(&t, 0, sizeof(t)); - t.tx_buf = &cmd_addr; t.len = 2; t.bits_per_word = bits; - spi_message_add_tail(&t, &m); + + spi_message_init_with_transfers(&m, &t, 1); mutex_lock(&edev->lock); - if (edev->pdata->prepare) - edev->pdata->prepare(edev); + gpiod_set_value_cansleep(edev->pdata->select, 1); ret = spi_sync(edev->spi, &m); if (ret) @@ -350,21 +356,23 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) /* have to wait erase cycle time Tec ms */ mdelay(6); - if (pd->finish) - pd->finish(edev); + gpiod_set_value_cansleep(edev->pdata->select, 0); mutex_unlock(&edev->lock); return ret; } -static ssize_t eeprom_93xx46_store_erase(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t erase_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev); - int erase = 0, ret; + bool erase; + int ret; + + ret = kstrtobool(buf, &erase); + if (ret) + return ret; - sscanf(buf, "%d", &erase); if (erase) { ret = eeprom_93xx46_ew(edev, 1); if (ret) @@ -378,21 +386,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev, } return count; } -static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); - -static void select_assert(void *context) -{ - struct eeprom_93xx46_dev *edev = context; - - gpiod_set_value_cansleep(edev->pdata->select, 1); -} - -static void select_deassert(void *context) -{ - struct eeprom_93xx46_dev *edev = context; - - gpiod_set_value_cansleep(edev->pdata->select, 0); -} +static DEVICE_ATTR_WO(erase); static const struct of_device_id eeprom_93xx46_of_table[] = { { .compatible = "eeprom-93xx46", .data = &at93c46_data, }, @@ -422,22 +416,20 @@ static const struct spi_device_id eeprom_93xx46_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, eeprom_93xx46_spi_ids); -static int eeprom_93xx46_probe_dt(struct spi_device *spi) +static int eeprom_93xx46_probe_fw(struct device *dev) { - const struct of_device_id *of_id = - of_match_device(eeprom_93xx46_of_table, &spi->dev); - struct device_node *np = spi->dev.of_node; + const struct eeprom_93xx46_devtype_data *data; struct eeprom_93xx46_platform_data *pd; u32 tmp; int ret; - pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL); + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); if (!pd) return -ENOMEM; - ret = of_property_read_u32(np, "data-size", &tmp); + ret = device_property_read_u32(dev, "data-size", &tmp); if (ret < 0) { - dev_err(&spi->dev, "data-size property not found\n"); + dev_err(dev, "data-size property not found\n"); return ret; } @@ -446,30 +438,25 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) } else if (tmp == 16) { pd->flags |= EE_ADDR16; } else { - dev_err(&spi->dev, "invalid data-size (%d)\n", tmp); + dev_err(dev, "invalid data-size (%d)\n", tmp); return -EINVAL; } - if (of_property_read_bool(np, "read-only")) + if (device_property_read_bool(dev, "read-only")) pd->flags |= EE_READONLY; - pd->select = devm_gpiod_get_optional(&spi->dev, "select", - GPIOD_OUT_LOW); + pd->select = devm_gpiod_get_optional(dev, "select", GPIOD_OUT_LOW); if (IS_ERR(pd->select)) return PTR_ERR(pd->select); + gpiod_set_consumer_name(pd->select, "93xx46 EEPROMs OE"); - pd->prepare = select_assert; - pd->finish = select_deassert; - gpiod_direction_output(pd->select, 0); - - if (of_id->data) { - const struct eeprom_93xx46_devtype_data *data = of_id->data; - + data = spi_get_device_match_data(to_spi_device(dev)); + if (data) { pd->quirks = data->quirks; pd->flags |= data->flags; } - spi->dev.platform_data = pd; + dev->platform_data = pd; return 0; } @@ -478,13 +465,12 @@ static int eeprom_93xx46_probe(struct spi_device *spi) { struct eeprom_93xx46_platform_data *pd; struct eeprom_93xx46_dev *edev; + struct device *dev = &spi->dev; int err; - if (spi->dev.of_node) { - err = eeprom_93xx46_probe_dt(spi); - if (err < 0) - return err; - } + err = eeprom_93xx46_probe_fw(dev); + if (err < 0) + return err; pd = spi->dev.platform_data; if (!pd) { @@ -565,7 +551,7 @@ static void eeprom_93xx46_remove(struct spi_device *spi) static struct spi_driver eeprom_93xx46_driver = { .driver = { .name = "93xx46", - .of_match_table = of_match_ptr(eeprom_93xx46_of_table), + .of_match_table = eeprom_93xx46_of_table, }, .probe = eeprom_93xx46_probe, .remove = eeprom_93xx46_remove, diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c index 327afb866b21..43421fe37d33 100644 --- a/drivers/misc/eeprom/idt_89hpesx.c +++ b/drivers/misc/eeprom/idt_89hpesx.c @@ -1426,58 +1426,58 @@ MODULE_DEVICE_TABLE(i2c, ee_ids); * idt_ids - supported IDT 89HPESx devices */ static const struct i2c_device_id idt_ids[] = { - { "89hpes8nt2", 0 }, - { "89hpes12nt3", 0 }, + { "89hpes8nt2" }, + { "89hpes12nt3" }, - { "89hpes24nt6ag2", 0 }, - { "89hpes32nt8ag2", 0 }, - { "89hpes32nt8bg2", 0 }, - { "89hpes12nt12g2", 0 }, - { "89hpes16nt16g2", 0 }, - { "89hpes24nt24g2", 0 }, - { "89hpes32nt24ag2", 0 }, - { "89hpes32nt24bg2", 0 }, + { "89hpes24nt6ag2" }, + { "89hpes32nt8ag2" }, + { "89hpes32nt8bg2" }, + { "89hpes12nt12g2" }, + { "89hpes16nt16g2" }, + { "89hpes24nt24g2" }, + { "89hpes32nt24ag2" }, + { "89hpes32nt24bg2" }, - { "89hpes12n3", 0 }, - { "89hpes12n3a", 0 }, - { "89hpes24n3", 0 }, - { "89hpes24n3a", 0 }, + { "89hpes12n3" }, + { "89hpes12n3a" }, + { "89hpes24n3" }, + { "89hpes24n3a" }, - { "89hpes32h8", 0 }, - { "89hpes32h8g2", 0 }, - { "89hpes48h12", 0 }, - { "89hpes48h12g2", 0 }, - { "89hpes48h12ag2", 0 }, - { "89hpes16h16", 0 }, - { "89hpes22h16", 0 }, - { "89hpes22h16g2", 0 }, - { "89hpes34h16", 0 }, - { "89hpes34h16g2", 0 }, - { "89hpes64h16", 0 }, - { "89hpes64h16g2", 0 }, - { "89hpes64h16ag2", 0 }, + { "89hpes32h8" }, + { "89hpes32h8g2" }, + { "89hpes48h12" }, + { "89hpes48h12g2" }, + { "89hpes48h12ag2" }, + { "89hpes16h16" }, + { "89hpes22h16" }, + { "89hpes22h16g2" }, + { "89hpes34h16" }, + { "89hpes34h16g2" }, + { "89hpes64h16" }, + { "89hpes64h16g2" }, + { "89hpes64h16ag2" }, - /* { "89hpes3t3", 0 }, // No SMBus-slave iface */ - { "89hpes12t3g2", 0 }, - { "89hpes24t3g2", 0 }, - /* { "89hpes4t4", 0 }, // No SMBus-slave iface */ - { "89hpes16t4", 0 }, - { "89hpes4t4g2", 0 }, - { "89hpes10t4g2", 0 }, - { "89hpes16t4g2", 0 }, - { "89hpes16t4ag2", 0 }, - { "89hpes5t5", 0 }, - { "89hpes6t5", 0 }, - { "89hpes8t5", 0 }, - { "89hpes8t5a", 0 }, - { "89hpes24t6", 0 }, - { "89hpes6t6g2", 0 }, - { "89hpes24t6g2", 0 }, - { "89hpes16t7", 0 }, - { "89hpes32t8", 0 }, - { "89hpes32t8g2", 0 }, - { "89hpes48t12", 0 }, - { "89hpes48t12g2", 0 }, + /* { "89hpes3t3" }, // No SMBus-slave iface */ + { "89hpes12t3g2" }, + { "89hpes24t3g2" }, + /* { "89hpes4t4" }, // No SMBus-slave iface */ + { "89hpes16t4" }, + { "89hpes4t4g2" }, + { "89hpes10t4g2" }, + { "89hpes16t4g2" }, + { "89hpes16t4ag2" }, + { "89hpes5t5" }, + { "89hpes6t5" }, + { "89hpes8t5" }, + { "89hpes8t5a" }, + { "89hpes24t6" }, + { "89hpes6t6g2" }, + { "89hpes24t6g2" }, + { "89hpes16t7" }, + { "89hpes32t8" }, + { "89hpes32t8g2" }, + { "89hpes48t12" }, + { "89hpes48t12g2" }, { /* END OF LIST */ } }; MODULE_DEVICE_TABLE(i2c, idt_ids); diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c index cb6b1efeafe0..6fab2ffa736b 100644 --- a/drivers/misc/eeprom/max6875.c +++ b/drivers/misc/eeprom/max6875.c @@ -183,7 +183,7 @@ static void max6875_remove(struct i2c_client *client) } static const struct i2c_device_id max6875_id[] = { - { "max6875", 0 }, + { "max6875" }, { } }; MODULE_DEVICE_TABLE(i2c, max6875_id); diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index a7a2bcedb37e..5204fda51da3 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -325,7 +325,7 @@ static void fastrpc_free_map(struct kref *ref) err = qcom_scm_assign_mem(map->phys, map->size, &src_perms, &perm, 1); if (err) { - dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d", + dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", map->phys, map->size, err); return; } @@ -816,7 +816,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd, map->attr = attr; err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2); if (err) { - dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", + dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n", map->phys, map->size, err); goto map_err; } @@ -953,7 +953,10 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) ctx->msg_sz = pkt_size; - err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf); + if (ctx->fl->sctx->sid) + err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf); + else + err = fastrpc_remote_heap_alloc(ctx->fl, dev, pkt_size, &ctx->buf); if (err) return err; @@ -1222,7 +1225,7 @@ static bool is_session_rejected(struct fastrpc_user *fl, bool unsigned_pd_reques * that does not support unsigned PD offload */ if (!fl->cctx->unsigned_support || !unsigned_pd_request) { - dev_err(&fl->cctx->rpdev->dev, "Error: Untrusted application trying to offload to signed PD"); + dev_err(&fl->cctx->rpdev->dev, "Error: Untrusted application trying to offload to signed PD\n"); return true; } } @@ -1260,17 +1263,12 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, goto err; } - name = kzalloc(init.namelen, GFP_KERNEL); - if (!name) { - err = -ENOMEM; + name = memdup_user(u64_to_user_ptr(init.name), init.namelen); + if (IS_ERR(name)) { + err = PTR_ERR(name); goto err; } - if (copy_from_user(name, (void __user *)(uintptr_t)init.name, init.namelen)) { - err = -EFAULT; - goto err_name; - } - if (!fl->cctx->remote_heap) { err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, &fl->cctx->remote_heap); @@ -1286,7 +1284,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, &src_perms, fl->cctx->vmperms, fl->cctx->vmcount); if (err) { - dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", + dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n", fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); goto err_map; } @@ -1340,7 +1338,7 @@ err_invoke: (u64)fl->cctx->remote_heap->size, &src_perms, &dst_perms, 1); if (err) - dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d", + dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); } err_map: @@ -2278,6 +2276,8 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) int i, err, domain_id = -1, vmcount; const char *domain; bool secure_dsp; + struct device_node *rmem_node; + struct reserved_mem *rmem; unsigned int vmids[FASTRPC_MAX_VMIDS]; err = of_property_read_string(rdev->of_node, "label", &domain); @@ -2320,6 +2320,23 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } } + rmem_node = of_parse_phandle(rdev->of_node, "memory-region", 0); + if (domain_id == SDSP_DOMAIN_ID && rmem_node) { + u64 src_perms; + + rmem = of_reserved_mem_lookup(rmem_node); + if (!rmem) { + err = -EINVAL; + goto fdev_error; + } + + src_perms = BIT(QCOM_SCM_VMID_HLOS); + + qcom_scm_assign_mem(rmem->base, rmem->size, &src_perms, + data->vmperms, data->vmcount); + + } + secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); data->secure = secure_dsp; @@ -2501,5 +2518,6 @@ static void fastrpc_exit(void) } module_exit(fastrpc_exit); +MODULE_DESCRIPTION("Qualcomm FastRPC"); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c index 759eaeb64307..ff92c6edff6b 100644 --- a/drivers/misc/hmc6352.c +++ b/drivers/misc/hmc6352.c @@ -121,7 +121,7 @@ static void hmc6352_remove(struct i2c_client *client) } static const struct i2c_device_id hmc6352_id[] = { - { "hmc6352", 0 }, + { "hmc6352" }, { } }; diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c index ee6296b98078..4cdb1087838f 100644 --- a/drivers/misc/ics932s401.c +++ b/drivers/misc/ics932s401.c @@ -95,7 +95,7 @@ static int ics932s401_detect(struct i2c_client *client, static void ics932s401_remove(struct i2c_client *client); static const struct i2c_device_id ics932s401_id[] = { - { "ics932s401", 0 }, + { "ics932s401" }, { } }; MODULE_DEVICE_TABLE(i2c, ics932s401_id); diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c index ebf0635aee64..9f26db467a81 100644 --- a/drivers/misc/isl29003.c +++ b/drivers/misc/isl29003.c @@ -449,7 +449,7 @@ static SIMPLE_DEV_PM_OPS(isl29003_pm_ops, isl29003_suspend, isl29003_resume); #endif /* CONFIG_PM_SLEEP */ static const struct i2c_device_id isl29003_id[] = { - { "isl29003", 0 }, + { "isl29003" }, {} }; MODULE_DEVICE_TABLE(i2c, isl29003_id); diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c index c5976fa8c825..1643ba2ff964 100644 --- a/drivers/misc/isl29020.c +++ b/drivers/misc/isl29020.c @@ -177,7 +177,7 @@ static void isl29020_remove(struct i2c_client *client) } static const struct i2c_device_id isl29020_id[] = { - { "isl29020", 0 }, + { "isl29020" }, { } }; diff --git a/drivers/misc/keba/Kconfig b/drivers/misc/keba/Kconfig new file mode 100644 index 000000000000..5fbcbc2252ac --- /dev/null +++ b/drivers/misc/keba/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +config KEBA_CP500 + tristate "KEBA CP500 system FPGA support" + depends on PCI + select AUXILIARY_BUS + help + This driver supports the KEBA CP500 system FPGA, which is used in + KEBA CP500 devices. It registers all sub devices present on the CP500 + system FPGA as separate devices. A driver is needed for each sub + device. + + This driver can also be built as a module. If so, the module will be + called cp500. diff --git a/drivers/misc/keba/Makefile b/drivers/misc/keba/Makefile new file mode 100644 index 000000000000..0a8b846cda7d --- /dev/null +++ b/drivers/misc/keba/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_KEBA_CP500) += cp500.o diff --git a/drivers/misc/keba/cp500.c b/drivers/misc/keba/cp500.c new file mode 100644 index 000000000000..9ba46f0f9392 --- /dev/null +++ b/drivers/misc/keba/cp500.c @@ -0,0 +1,458 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) KEBA Industrial Automation Gmbh 2024 + * + * Driver for KEBA system FPGA + * + * The KEBA system FPGA implements various devices. This driver registers + * auxiliary devices for every device within the FPGA. + */ + +#include +#include +#include +#include +#include + +#define CP500 "cp500" + +#define PCI_VENDOR_ID_KEBA 0xCEBA +#define PCI_DEVICE_ID_KEBA_CP035 0x2706 +#define PCI_DEVICE_ID_KEBA_CP505 0x2703 +#define PCI_DEVICE_ID_KEBA_CP520 0x2696 + +#define CP500_SYS_BAR 0 +#define CP500_ECM_BAR 1 + +/* BAR 0 registers */ +#define CP500_VERSION_REG 0x00 +#define CP500_RECONFIG_REG 0x11 /* upper 8-bits of STARTUP register */ +#define CP500_AXI_REG 0x40 + +/* Bits in BUILD_REG */ +#define CP500_BUILD_TEST 0x8000 /* FPGA test version */ + +/* Bits in RECONFIG_REG */ +#define CP500_RECFG_REQ 0x01 /* reconfigure FPGA on next reset */ + +/* MSIX */ +#define CP500_AXI_MSIX 3 +#define CP500_NUM_MSIX 8 +#define CP500_NUM_MSIX_NO_MMI 2 +#define CP500_NUM_MSIX_NO_AXI 3 + +/* EEPROM */ +#define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom" + +#define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035) +#define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505) +#define CP500_IS_CP520(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP520) + +struct cp500_dev_info { + off_t offset; + size_t size; +}; + +struct cp500_devs { + struct cp500_dev_info startup; + struct cp500_dev_info i2c; +}; + +/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */ +static struct cp500_devs cp035_devices = { + .startup = { 0x0000, SZ_4K }, + .i2c = { 0x4000, SZ_4K }, +}; + +/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */ +static struct cp500_devs cp505_devices = { + .startup = { 0x0000, SZ_4K }, + .i2c = { 0x5000, SZ_4K }, +}; + +/* list of devices within FPGA of CP520 family (CP520, CP530) */ +static struct cp500_devs cp520_devices = { + .startup = { 0x0000, SZ_4K }, + .i2c = { 0x5000, SZ_4K }, +}; + +struct cp500 { + struct pci_dev *pci_dev; + struct cp500_devs *devs; + int msix_num; + struct { + int major; + int minor; + int build; + } version; + + /* system FPGA BAR */ + resource_size_t sys_hwbase; + struct keba_i2c_auxdev *i2c; + + /* ECM EtherCAT BAR */ + resource_size_t ecm_hwbase; + + void __iomem *system_startup_addr; +}; + +/* I2C devices */ +static struct i2c_board_info cp500_i2c_info[] = { + { /* temperature sensor */ + I2C_BOARD_INFO("emc1403", 0x4c), + }, + { /* + * CPU EEPROM + * CP035 family: CPU board + * CP505 family: bridge board + * CP520 family: carrier board + */ + I2C_BOARD_INFO("24c32", 0x50), + .dev_name = CP500_HW_CPU_EEPROM_NAME, + }, + { /* interface board EEPROM */ + I2C_BOARD_INFO("24c32", 0x51), + }, + { /* + * EEPROM (optional) + * CP505 family: CPU board + * CP520 family: MMI board + */ + I2C_BOARD_INFO("24c32", 0x52), + }, + { /* extension module 0 EEPROM (optional) */ + I2C_BOARD_INFO("24c32", 0x53), + }, + { /* extension module 1 EEPROM (optional) */ + I2C_BOARD_INFO("24c32", 0x54), + }, + { /* extension module 2 EEPROM (optional) */ + I2C_BOARD_INFO("24c32", 0x55), + }, + { /* extension module 3 EEPROM (optional) */ + I2C_BOARD_INFO("24c32", 0x56), + } +}; + +static ssize_t cp500_get_fpga_version(struct cp500 *cp500, char *buf, + size_t max_len) +{ + int n; + + if (CP500_IS_CP035(cp500)) + n = scnprintf(buf, max_len, "CP035"); + else if (CP500_IS_CP505(cp500)) + n = scnprintf(buf, max_len, "CP505"); + else + n = scnprintf(buf, max_len, "CP500"); + + n += scnprintf(buf + n, max_len - n, "_FPGA_%d.%02d", + cp500->version.major, cp500->version.minor); + + /* test versions have test bit set */ + if (cp500->version.build & CP500_BUILD_TEST) + n += scnprintf(buf + n, max_len - n, "Test%d", + cp500->version.build & ~CP500_BUILD_TEST); + + n += scnprintf(buf + n, max_len - n, "\n"); + + return n; +} + +static ssize_t version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cp500 *cp500 = dev_get_drvdata(dev); + + return cp500_get_fpga_version(cp500, buf, PAGE_SIZE); +} +static DEVICE_ATTR_RO(version); + +static ssize_t keep_cfg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cp500 *cp500 = dev_get_drvdata(dev); + unsigned long keep_cfg = 1; + + /* + * FPGA configuration stream is kept during reset when RECONFIG bit is + * zero + */ + if (ioread8(cp500->system_startup_addr + CP500_RECONFIG_REG) & + CP500_RECFG_REQ) + keep_cfg = 0; + + return sysfs_emit(buf, "%lu\n", keep_cfg); +} + +static ssize_t keep_cfg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cp500 *cp500 = dev_get_drvdata(dev); + unsigned long keep_cfg; + + if (kstrtoul(buf, 10, &keep_cfg) < 0) + return -EINVAL; + + /* + * In normal operation "keep_cfg" is "1". This means that the FPGA keeps + * its configuration stream during a reset. + * In case of a firmware update of the FPGA, the configuration stream + * needs to be reloaded. This can be done without a powercycle by + * writing a "0" into the "keep_cfg" attribute. After a reset/reboot th + * new configuration stream will be loaded. + */ + if (keep_cfg) + iowrite8(0, cp500->system_startup_addr + CP500_RECONFIG_REG); + else + iowrite8(CP500_RECFG_REQ, + cp500->system_startup_addr + CP500_RECONFIG_REG); + + return count; +} +static DEVICE_ATTR_RW(keep_cfg); + +static struct attribute *attrs[] = { + &dev_attr_version.attr, + &dev_attr_keep_cfg.attr, + NULL +}; +static const struct attribute_group attrs_group = { .attrs = attrs }; + +static void cp500_i2c_release(struct device *dev) +{ + struct keba_i2c_auxdev *i2c = + container_of(dev, struct keba_i2c_auxdev, auxdev.dev); + + kfree(i2c); +} + +static int cp500_register_i2c(struct cp500 *cp500) +{ + int retval; + + cp500->i2c = kzalloc(sizeof(*cp500->i2c), GFP_KERNEL); + if (!cp500->i2c) + return -ENOMEM; + + cp500->i2c->auxdev.name = "i2c"; + cp500->i2c->auxdev.id = 0; + cp500->i2c->auxdev.dev.release = cp500_i2c_release; + cp500->i2c->auxdev.dev.parent = &cp500->pci_dev->dev; + cp500->i2c->io = (struct resource) { + /* I2C register area */ + .start = (resource_size_t) cp500->sys_hwbase + + cp500->devs->i2c.offset, + .end = (resource_size_t) cp500->sys_hwbase + + cp500->devs->i2c.offset + + cp500->devs->i2c.size - 1, + .flags = IORESOURCE_MEM, + }; + cp500->i2c->info_size = ARRAY_SIZE(cp500_i2c_info); + cp500->i2c->info = cp500_i2c_info; + + retval = auxiliary_device_init(&cp500->i2c->auxdev); + if (retval) { + kfree(cp500->i2c); + cp500->i2c = NULL; + + return retval; + } + retval = __auxiliary_device_add(&cp500->i2c->auxdev, "keba"); + if (retval) { + auxiliary_device_uninit(&cp500->i2c->auxdev); + cp500->i2c = NULL; + + return retval; + } + + return 0; +} + +static void cp500_register_auxiliary_devs(struct cp500 *cp500) +{ + struct device *dev = &cp500->pci_dev->dev; + + if (cp500_register_i2c(cp500)) + dev_warn(dev, "Failed to register i2c!\n"); +} + +static void cp500_unregister_dev(struct auxiliary_device *auxdev) +{ + auxiliary_device_delete(auxdev); + auxiliary_device_uninit(auxdev); +} + +static void cp500_unregister_auxiliary_devs(struct cp500 *cp500) +{ + + if (cp500->i2c) { + cp500_unregister_dev(&cp500->i2c->auxdev); + cp500->i2c = NULL; + } +} + +static irqreturn_t cp500_axi_handler(int irq, void *dev) +{ + struct cp500 *cp500 = dev; + u32 axi_address = ioread32(cp500->system_startup_addr + CP500_AXI_REG); + + /* + * FPGA signals AXI response error, print AXI address to indicate which + * IP core was affected + */ + dev_err(&cp500->pci_dev->dev, "AXI response error at 0x%08x\n", + axi_address); + + return IRQ_HANDLED; +} + +static int cp500_enable(struct cp500 *cp500) +{ + int axi_irq = -1; + int ret; + + if (cp500->msix_num > CP500_NUM_MSIX_NO_AXI) { + axi_irq = pci_irq_vector(cp500->pci_dev, CP500_AXI_MSIX); + ret = request_irq(axi_irq, cp500_axi_handler, 0, + CP500, cp500); + if (ret != 0) { + dev_err(&cp500->pci_dev->dev, + "Failed to register AXI response error!\n"); + return ret; + } + } + + return 0; +} + +static void cp500_disable(struct cp500 *cp500) +{ + int axi_irq; + + if (cp500->msix_num > CP500_NUM_MSIX_NO_AXI) { + axi_irq = pci_irq_vector(cp500->pci_dev, CP500_AXI_MSIX); + free_irq(axi_irq, cp500); + } +} + +static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) +{ + struct device *dev = &pci_dev->dev; + struct resource startup; + struct cp500 *cp500; + u32 cp500_vers; + char buf[64]; + int ret; + + cp500 = devm_kzalloc(dev, sizeof(*cp500), GFP_KERNEL); + if (!cp500) + return -ENOMEM; + cp500->pci_dev = pci_dev; + cp500->sys_hwbase = pci_resource_start(pci_dev, CP500_SYS_BAR); + cp500->ecm_hwbase = pci_resource_start(pci_dev, CP500_ECM_BAR); + if (!cp500->sys_hwbase || !cp500->ecm_hwbase) + return -ENODEV; + + if (CP500_IS_CP035(cp500)) + cp500->devs = &cp035_devices; + else if (CP500_IS_CP505(cp500)) + cp500->devs = &cp505_devices; + else if (CP500_IS_CP520(cp500)) + cp500->devs = &cp520_devices; + else + return -ENODEV; + + ret = pci_enable_device(pci_dev); + if (ret) + return ret; + pci_set_master(pci_dev); + + startup = *pci_resource_n(pci_dev, CP500_SYS_BAR); + startup.end = startup.start + cp500->devs->startup.size - 1; + cp500->system_startup_addr = devm_ioremap_resource(&pci_dev->dev, + &startup); + if (IS_ERR(cp500->system_startup_addr)) { + ret = PTR_ERR(cp500->system_startup_addr); + goto out_disable; + } + + cp500->msix_num = pci_alloc_irq_vectors(pci_dev, CP500_NUM_MSIX_NO_MMI, + CP500_NUM_MSIX, PCI_IRQ_MSIX); + if (cp500->msix_num < CP500_NUM_MSIX_NO_MMI) { + dev_err(&pci_dev->dev, + "Hardware does not support enough MSI-X interrupts\n"); + ret = -ENODEV; + goto out_disable; + } + + cp500_vers = ioread32(cp500->system_startup_addr + CP500_VERSION_REG); + cp500->version.major = (cp500_vers & 0xff); + cp500->version.minor = (cp500_vers >> 8) & 0xff; + cp500->version.build = (cp500_vers >> 16) & 0xffff; + cp500_get_fpga_version(cp500, buf, sizeof(buf)); + + dev_info(&pci_dev->dev, "FPGA version %s", buf); + + pci_set_drvdata(pci_dev, cp500); + + ret = sysfs_create_group(&pci_dev->dev.kobj, &attrs_group); + if (ret != 0) + goto out_free_irq; + + ret = cp500_enable(cp500); + if (ret != 0) + goto out_remove_group; + + cp500_register_auxiliary_devs(cp500); + + return 0; + +out_remove_group: + sysfs_remove_group(&pci_dev->dev.kobj, &attrs_group); +out_free_irq: + pci_free_irq_vectors(pci_dev); +out_disable: + pci_clear_master(pci_dev); + pci_disable_device(pci_dev); + + return ret; +} + +static void cp500_remove(struct pci_dev *pci_dev) +{ + struct cp500 *cp500 = pci_get_drvdata(pci_dev); + + cp500_unregister_auxiliary_devs(cp500); + + cp500_disable(cp500); + + sysfs_remove_group(&pci_dev->dev.kobj, &attrs_group); + + pci_set_drvdata(pci_dev, 0); + + pci_free_irq_vectors(pci_dev); + + pci_clear_master(pci_dev); + pci_disable_device(pci_dev); +} + +static struct pci_device_id cp500_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP035) }, + { PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP505) }, + { PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP520) }, + { } +}; +MODULE_DEVICE_TABLE(pci, cp500_ids); + +static struct pci_driver cp500_driver = { + .name = CP500, + .id_table = cp500_ids, + .probe = cp500_probe, + .remove = cp500_remove, +}; +module_pci_driver(cp500_driver); + +MODULE_AUTHOR("Gerhard Engleder "); +MODULE_DESCRIPTION("KEBA CP500 system FPGA driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 2733070acf39..9eebeffcd8fd 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -80,6 +80,8 @@ static void whitelist(struct mei_cl_device *cldev) cldev->do_match = 1; } +#define MKHI_SEND_MAX_TIMEOUT_MSEC 4000 + #define OSTYPE_LINUX 2 struct mei_os_ver { __le16 build; @@ -128,7 +130,7 @@ static int mei_osver(struct mei_cl_device *cldev) os_ver = (struct mei_os_ver *)fwcaps->data; os_ver->os_type = OSTYPE_LINUX; - return __mei_cl_send(cldev->cl, buf, size, 0, mode); + return __mei_cl_send_timeout(cldev->cl, buf, size, 0, mode, MKHI_SEND_MAX_TIMEOUT_MSEC); } #define MKHI_FWVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \ @@ -148,8 +150,8 @@ static int mei_fwver(struct mei_cl_device *cldev) req.hdr.group_id = MKHI_GEN_GROUP_ID; req.hdr.command = MKHI_GEN_GET_FW_VERSION_CMD; - ret = __mei_cl_send(cldev->cl, (u8 *)&req, sizeof(req), 0, - MEI_CL_IO_TX_BLOCKING); + ret = __mei_cl_send_timeout(cldev->cl, (u8 *)&req, sizeof(req), 0, + MEI_CL_IO_TX_BLOCKING, MKHI_SEND_MAX_TIMEOUT_MSEC); if (ret < 0) { dev_info(&cldev->dev, "Could not send ReqFWVersion cmd ret = %d\n", ret); return ret; diff --git a/drivers/misc/mrvl_cn10k_dpi.c b/drivers/misc/mrvl_cn10k_dpi.c new file mode 100644 index 000000000000..7d5433121ff6 --- /dev/null +++ b/drivers/misc/mrvl_cn10k_dpi.c @@ -0,0 +1,676 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon CN10K DPI driver + * + * Copyright (C) 2024 Marvell. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* PCI device IDs */ +#define PCI_DEVID_MRVL_CN10K_DPI_PF 0xA080 +#define PCI_SUBDEVID_MRVL_CN10K_DPI_PF 0xB900 + +/* PCI BAR Number */ +#define PCI_DPI_CFG_BAR 0 + +/* MSI-X interrupts */ +#define DPI_MAX_REQQ_INT 0x20 +#define DPI_MAX_CC_INT 0x40 + +/* MBOX MSI-X interrupt vector index */ +#define DPI_MBOX_PF_VF_INT_IDX 0x75 + +#define DPI_MAX_IRQS (DPI_MBOX_PF_VF_INT_IDX + 1) + +#define DPI_MAX_VFS 0x20 + +#define DPI_MAX_ENG_FIFO_SZ 0x20 +#define DPI_MAX_ENG_MOLR 0x400 + +#define DPI_DMA_IDS_DMA_NPA_PF_FUNC(x) FIELD_PREP(GENMASK_ULL(31, 16), x) +#define DPI_DMA_IDS_INST_STRM(x) FIELD_PREP(GENMASK_ULL(47, 40), x) +#define DPI_DMA_IDS_DMA_STRM(x) FIELD_PREP(GENMASK_ULL(39, 32), x) +#define DPI_DMA_ENG_EN_MOLR(x) FIELD_PREP(GENMASK_ULL(41, 32), x) +#define DPI_EBUS_PORTX_CFG_MPS(x) FIELD_PREP(GENMASK(6, 4), x) +#define DPI_DMA_IDS_DMA_SSO_PF_FUNC(x) FIELD_PREP(GENMASK(15, 0), x) +#define DPI_DMA_IDS2_INST_AURA(x) FIELD_PREP(GENMASK(19, 0), x) +#define DPI_DMA_IBUFF_CSIZE_CSIZE(x) FIELD_PREP(GENMASK(13, 0), x) +#define DPI_EBUS_PORTX_CFG_MRRS(x) FIELD_PREP(GENMASK(2, 0), x) +#define DPI_ENG_BUF_BLKS(x) FIELD_PREP(GENMASK(5, 0), x) +#define DPI_DMA_CONTROL_DMA_ENB GENMASK_ULL(53, 48) + +#define DPI_DMA_CONTROL_O_MODE BIT_ULL(14) +#define DPI_DMA_CONTROL_LDWB BIT_ULL(32) +#define DPI_DMA_CONTROL_WQECSMODE1 BIT_ULL(37) +#define DPI_DMA_CONTROL_ZBWCSEN BIT_ULL(39) +#define DPI_DMA_CONTROL_WQECSOFF(ofst) (((u64)ofst) << 40) +#define DPI_DMA_CONTROL_WQECSDIS BIT_ULL(47) +#define DPI_DMA_CONTROL_PKT_EN BIT_ULL(56) +#define DPI_DMA_IBUFF_CSIZE_NPA_FREE BIT(16) + +#define DPI_CTL_EN BIT_ULL(0) +#define DPI_DMA_CC_INT BIT_ULL(0) +#define DPI_DMA_QRST BIT_ULL(0) + +#define DPI_REQQ_INT_INSTRFLT BIT_ULL(0) +#define DPI_REQQ_INT_RDFLT BIT_ULL(1) +#define DPI_REQQ_INT_WRFLT BIT_ULL(2) +#define DPI_REQQ_INT_CSFLT BIT_ULL(3) +#define DPI_REQQ_INT_INST_DBO BIT_ULL(4) +#define DPI_REQQ_INT_INST_ADDR_NULL BIT_ULL(5) +#define DPI_REQQ_INT_INST_FILL_INVAL BIT_ULL(6) +#define DPI_REQQ_INT_INSTR_PSN BIT_ULL(7) + +#define DPI_REQQ_INT \ + (DPI_REQQ_INT_INSTRFLT | \ + DPI_REQQ_INT_RDFLT | \ + DPI_REQQ_INT_WRFLT | \ + DPI_REQQ_INT_CSFLT | \ + DPI_REQQ_INT_INST_DBO | \ + DPI_REQQ_INT_INST_ADDR_NULL | \ + DPI_REQQ_INT_INST_FILL_INVAL | \ + DPI_REQQ_INT_INSTR_PSN) + +#define DPI_PF_RAS_EBI_DAT_PSN BIT_ULL(0) +#define DPI_PF_RAS_NCB_DAT_PSN BIT_ULL(1) +#define DPI_PF_RAS_NCB_CMD_PSN BIT_ULL(2) + +#define DPI_PF_RAS_INT \ + (DPI_PF_RAS_EBI_DAT_PSN | \ + DPI_PF_RAS_NCB_DAT_PSN | \ + DPI_PF_RAS_NCB_CMD_PSN) + +/* Message fields in word_l of DPI mailbox structure */ +#define DPI_MBOX_VFID(msg) FIELD_GET(GENMASK_ULL(7, 0), msg) +#define DPI_MBOX_CMD(msg) FIELD_GET(GENMASK_ULL(11, 8), msg) +#define DPI_MBOX_CBUF_SIZE(msg) FIELD_GET(GENMASK_ULL(27, 12), msg) +#define DPI_MBOX_CBUF_AURA(msg) FIELD_GET(GENMASK_ULL(47, 28), msg) +#define DPI_MBOX_SSO_PFFUNC(msg) FIELD_GET(GENMASK_ULL(63, 48), msg) + +/* Message fields in word_h of DPI mailbox structure */ +#define DPI_MBOX_NPA_PFFUNC(msg) FIELD_GET(GENMASK_ULL(15, 0), msg) +#define DPI_MBOX_WQES_COMPL(msg) FIELD_GET(GENMASK_ULL(16, 16), msg) +#define DPI_MBOX_WQES_OFFSET(msg) FIELD_GET(GENMASK_ULL(23, 17), msg) + +#define DPI_DMAX_IBUFF_CSIZE(x) (0x0ULL | ((x) << 11)) +#define DPI_DMAX_IDS(x) (0x18ULL | ((x) << 11)) +#define DPI_DMAX_IDS2(x) (0x20ULL | ((x) << 11)) +#define DPI_DMAX_QRST(x) (0x30ULL | ((x) << 11)) + +#define DPI_CTL 0x10010ULL +#define DPI_DMA_CONTROL 0x10018ULL +#define DPI_PF_RAS 0x10308ULL +#define DPI_PF_RAS_ENA_W1C 0x10318ULL +#define DPI_MBOX_VF_PF_INT 0x16300ULL +#define DPI_MBOX_VF_PF_INT_W1S 0x16308ULL +#define DPI_MBOX_VF_PF_INT_ENA_W1C 0x16310ULL +#define DPI_MBOX_VF_PF_INT_ENA_W1S 0x16318ULL + +#define DPI_DMA_ENGX_EN(x) (0x10040ULL | ((x) << 3)) +#define DPI_ENGX_BUF(x) (0x100C0ULL | ((x) << 3)) +#define DPI_EBUS_PORTX_CFG(x) (0x10100ULL | ((x) << 3)) +#define DPI_DMA_CCX_INT(x) (0x11000ULL | ((x) << 3)) +#define DPI_DMA_CCX_INT_ENA_W1C(x) (0x11800ULL | ((x) << 3)) +#define DPI_REQQX_INT(x) (0x12C00ULL | ((x) << 5)) +#define DPI_REQQX_INT_ENA_W1C(x) (0x13800ULL | ((x) << 5)) +#define DPI_MBOX_PF_VF_DATA0(x) (0x16000ULL | ((x) << 4)) +#define DPI_MBOX_PF_VF_DATA1(x) (0x16008ULL | ((x) << 4)) + +#define DPI_WCTL_FIF_THR 0x17008ULL + +#define DPI_EBUS_MAX_PORTS 2 + +#define DPI_EBUS_MRRS_MIN 128 +#define DPI_EBUS_MRRS_MAX 1024 +#define DPI_EBUS_MPS_MIN 128 +#define DPI_EBUS_MPS_MAX 1024 +#define DPI_WCTL_FIFO_THRESHOLD 0x30 + +#define DPI_QUEUE_OPEN 0x1 +#define DPI_QUEUE_CLOSE 0x2 +#define DPI_REG_DUMP 0x3 +#define DPI_GET_REG_CFG 0x4 +#define DPI_QUEUE_OPEN_V2 0x5 + +enum dpi_mbox_rsp_type { + DPI_MBOX_TYPE_CMD, + DPI_MBOX_TYPE_RSP_ACK, + DPI_MBOX_TYPE_RSP_NACK, +}; + +struct dpivf_config { + u32 aura; + u16 csize; + u16 sso_pf_func; + u16 npa_pf_func; +}; + +struct dpipf_vf { + struct dpivf_config vf_config; + bool setup_done; + u8 this_vfid; +}; + +/* DPI device mailbox */ +struct dpi_mbox { + struct work_struct work; + /* lock to serialize mbox requests */ + struct mutex lock; + struct dpipf *pf; + u8 __iomem *pf_vf_data_reg; + u8 __iomem *vf_pf_data_reg; +}; + +struct dpipf { + struct miscdevice miscdev; + void __iomem *reg_base; + struct pci_dev *pdev; + struct dpipf_vf vf[DPI_MAX_VFS]; + /* Mailbox to talk to VFs */ + struct dpi_mbox *mbox[DPI_MAX_VFS]; +}; + +struct dpi_mbox_message { + uint64_t word_l; + uint64_t word_h; +}; + +static inline void dpi_reg_write(struct dpipf *dpi, u64 offset, u64 val) +{ + writeq(val, dpi->reg_base + offset); +} + +static inline u64 dpi_reg_read(struct dpipf *dpi, u64 offset) +{ + return readq(dpi->reg_base + offset); +} + +static void dpi_wqe_cs_offset(struct dpipf *dpi, u8 offset) +{ + u64 reg; + + reg = dpi_reg_read(dpi, DPI_DMA_CONTROL); + reg &= ~DPI_DMA_CONTROL_WQECSDIS; + reg |= DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_WQECSMODE1; + reg |= DPI_DMA_CONTROL_WQECSOFF(offset); + dpi_reg_write(dpi, DPI_DMA_CONTROL, reg); +} + +static int dpi_queue_init(struct dpipf *dpi, struct dpipf_vf *dpivf, u8 vf) +{ + u16 sso_pf_func = dpivf->vf_config.sso_pf_func; + u16 npa_pf_func = dpivf->vf_config.npa_pf_func; + u16 csize = dpivf->vf_config.csize; + u32 aura = dpivf->vf_config.aura; + unsigned long timeout; + u64 reg; + + dpi_reg_write(dpi, DPI_DMAX_QRST(vf), DPI_DMA_QRST); + + /* Wait for a maximum of 3 sec */ + timeout = jiffies + msecs_to_jiffies(3000); + while (!time_after(jiffies, timeout)) { + reg = dpi_reg_read(dpi, DPI_DMAX_QRST(vf)); + if (!(reg & DPI_DMA_QRST)) + break; + + /* Reset would take time for the request cache to drain */ + usleep_range(500, 1000); + } + + if (reg & DPI_DMA_QRST) { + dev_err(&dpi->pdev->dev, "Queue reset failed\n"); + return -EBUSY; + } + + dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), 0); + dpi_reg_write(dpi, DPI_DMAX_IDS(vf), 0); + + reg = DPI_DMA_IBUFF_CSIZE_CSIZE(csize) | DPI_DMA_IBUFF_CSIZE_NPA_FREE; + dpi_reg_write(dpi, DPI_DMAX_IBUFF_CSIZE(vf), reg); + + reg = dpi_reg_read(dpi, DPI_DMAX_IDS2(vf)); + reg |= DPI_DMA_IDS2_INST_AURA(aura); + dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), reg); + + reg = dpi_reg_read(dpi, DPI_DMAX_IDS(vf)); + reg |= DPI_DMA_IDS_DMA_NPA_PF_FUNC(npa_pf_func); + reg |= DPI_DMA_IDS_DMA_SSO_PF_FUNC(sso_pf_func); + reg |= DPI_DMA_IDS_DMA_STRM(vf + 1); + reg |= DPI_DMA_IDS_INST_STRM(vf + 1); + dpi_reg_write(dpi, DPI_DMAX_IDS(vf), reg); + + return 0; +} + +static void dpi_queue_fini(struct dpipf *dpi, u8 vf) +{ + dpi_reg_write(dpi, DPI_DMAX_QRST(vf), DPI_DMA_QRST); + + /* Reset IDS and IDS2 registers */ + dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), 0); + dpi_reg_write(dpi, DPI_DMAX_IDS(vf), 0); +} + +static irqreturn_t dpi_mbox_intr_handler(int irq, void *data) +{ + struct dpipf *dpi = data; + u64 reg; + u32 vf; + + reg = dpi_reg_read(dpi, DPI_MBOX_VF_PF_INT); + if (reg) { + for (vf = 0; vf < pci_num_vf(dpi->pdev); vf++) { + if (reg & BIT_ULL(vf)) + schedule_work(&dpi->mbox[vf]->work); + } + dpi_reg_write(dpi, DPI_MBOX_VF_PF_INT, reg); + } + + return IRQ_HANDLED; +} + +static int queue_config(struct dpipf *dpi, struct dpipf_vf *dpivf, struct dpi_mbox_message *msg) +{ + int ret = 0; + + switch (DPI_MBOX_CMD(msg->word_l)) { + case DPI_QUEUE_OPEN: + case DPI_QUEUE_OPEN_V2: + dpivf->vf_config.aura = DPI_MBOX_CBUF_AURA(msg->word_l); + dpivf->vf_config.csize = DPI_MBOX_CMD(msg->word_l) == DPI_QUEUE_OPEN ? + DPI_MBOX_CBUF_SIZE(msg->word_l) >> 3 : + DPI_MBOX_CBUF_SIZE(msg->word_l); + dpivf->vf_config.sso_pf_func = DPI_MBOX_SSO_PFFUNC(msg->word_l); + dpivf->vf_config.npa_pf_func = DPI_MBOX_NPA_PFFUNC(msg->word_h); + ret = dpi_queue_init(dpi, dpivf, DPI_MBOX_VFID(msg->word_l)); + if (!ret) { + if (DPI_MBOX_WQES_COMPL(msg->word_h)) + dpi_wqe_cs_offset(dpi, DPI_MBOX_WQES_OFFSET(msg->word_h)); + dpivf->setup_done = true; + } + break; + case DPI_QUEUE_CLOSE: + memset(&dpivf->vf_config, 0, sizeof(struct dpivf_config)); + dpi_queue_fini(dpi, DPI_MBOX_VFID(msg->word_l)); + dpivf->setup_done = false; + break; + default: + return -EINVAL; + } + + return ret; +} + +static void dpi_pfvf_mbox_work(struct work_struct *work) +{ + struct dpi_mbox *mbox = container_of(work, struct dpi_mbox, work); + struct dpi_mbox_message msg; + struct dpipf_vf *dpivf; + struct dpipf *dpi; + int vfid, ret; + + dpi = mbox->pf; + memset(&msg, 0, sizeof(msg)); + + mutex_lock(&mbox->lock); + msg.word_l = readq(mbox->vf_pf_data_reg); + if (msg.word_l == (u64)-1) + goto exit; + + vfid = DPI_MBOX_VFID(msg.word_l); + if (vfid >= pci_num_vf(dpi->pdev)) + goto exit; + + dpivf = &dpi->vf[vfid]; + msg.word_h = readq(mbox->pf_vf_data_reg); + + ret = queue_config(dpi, dpivf, &msg); + if (ret < 0) + writeq(DPI_MBOX_TYPE_RSP_NACK, mbox->pf_vf_data_reg); + else + writeq(DPI_MBOX_TYPE_RSP_ACK, mbox->pf_vf_data_reg); +exit: + mutex_unlock(&mbox->lock); +} + +/* Setup registers for a PF mailbox */ +static void dpi_setup_mbox_regs(struct dpipf *dpi, int vf) +{ + struct dpi_mbox *mbox = dpi->mbox[vf]; + + mbox->pf_vf_data_reg = dpi->reg_base + DPI_MBOX_PF_VF_DATA0(vf); + mbox->vf_pf_data_reg = dpi->reg_base + DPI_MBOX_PF_VF_DATA1(vf); +} + +static int dpi_pfvf_mbox_setup(struct dpipf *dpi) +{ + int vf; + + for (vf = 0; vf < DPI_MAX_VFS; vf++) { + dpi->mbox[vf] = devm_kzalloc(&dpi->pdev->dev, sizeof(*dpi->mbox[vf]), GFP_KERNEL); + + if (!dpi->mbox[vf]) + return -ENOMEM; + + mutex_init(&dpi->mbox[vf]->lock); + INIT_WORK(&dpi->mbox[vf]->work, dpi_pfvf_mbox_work); + dpi->mbox[vf]->pf = dpi; + dpi_setup_mbox_regs(dpi, vf); + } + + return 0; +} + +static void dpi_pfvf_mbox_destroy(struct dpipf *dpi) +{ + unsigned int vf; + + for (vf = 0; vf < DPI_MAX_VFS; vf++) { + if (work_pending(&dpi->mbox[vf]->work)) + cancel_work_sync(&dpi->mbox[vf]->work); + + dpi->mbox[vf] = NULL; + } +} + +static void dpi_init(struct dpipf *dpi) +{ + unsigned int engine, port; + u8 mrrs_val, mps_val; + u64 reg; + + for (engine = 0; engine < DPI_MAX_ENGINES; engine++) { + if (engine == 4 || engine == 5) + reg = DPI_ENG_BUF_BLKS(16); + else + reg = DPI_ENG_BUF_BLKS(8); + + dpi_reg_write(dpi, DPI_ENGX_BUF(engine), reg); + } + + reg = DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_PKT_EN | DPI_DMA_CONTROL_LDWB | + DPI_DMA_CONTROL_O_MODE | DPI_DMA_CONTROL_DMA_ENB; + + dpi_reg_write(dpi, DPI_DMA_CONTROL, reg); + dpi_reg_write(dpi, DPI_CTL, DPI_CTL_EN); + + mrrs_val = 2; /* 512B */ + mps_val = 1; /* 256B */ + + for (port = 0; port < DPI_EBUS_MAX_PORTS; port++) { + reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(port)); + reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(7) | DPI_EBUS_PORTX_CFG_MPS(7)); + reg |= DPI_EBUS_PORTX_CFG_MPS(mps_val) | DPI_EBUS_PORTX_CFG_MRRS(mrrs_val); + dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(port), reg); + } + + dpi_reg_write(dpi, DPI_WCTL_FIF_THR, DPI_WCTL_FIFO_THRESHOLD); +} + +static void dpi_fini(struct dpipf *dpi) +{ + unsigned int engine; + + for (engine = 0; engine < DPI_MAX_ENGINES; engine++) + dpi_reg_write(dpi, DPI_ENGX_BUF(engine), 0); + + dpi_reg_write(dpi, DPI_DMA_CONTROL, 0); + dpi_reg_write(dpi, DPI_CTL, 0); +} + +static void dpi_free_irq_vectors(void *pdev) +{ + pci_free_irq_vectors((struct pci_dev *)pdev); +} + +static int dpi_irq_init(struct dpipf *dpi) +{ + struct pci_dev *pdev = dpi->pdev; + struct device *dev = &pdev->dev; + int i, ret; + + /* Clear all RAS interrupts */ + dpi_reg_write(dpi, DPI_PF_RAS, DPI_PF_RAS_INT); + + /* Clear all RAS interrupt enable bits */ + dpi_reg_write(dpi, DPI_PF_RAS_ENA_W1C, DPI_PF_RAS_INT); + + for (i = 0; i < DPI_MAX_REQQ_INT; i++) { + dpi_reg_write(dpi, DPI_REQQX_INT(i), DPI_REQQ_INT); + dpi_reg_write(dpi, DPI_REQQX_INT_ENA_W1C(i), DPI_REQQ_INT); + } + + for (i = 0; i < DPI_MAX_CC_INT; i++) { + dpi_reg_write(dpi, DPI_DMA_CCX_INT(i), DPI_DMA_CC_INT); + dpi_reg_write(dpi, DPI_DMA_CCX_INT_ENA_W1C(i), DPI_DMA_CC_INT); + } + + ret = pci_alloc_irq_vectors(pdev, DPI_MAX_IRQS, DPI_MAX_IRQS, PCI_IRQ_MSIX); + if (ret != DPI_MAX_IRQS) { + dev_err(dev, "DPI: Failed to alloc %d msix irqs\n", DPI_MAX_IRQS); + return ret; + } + + ret = devm_add_action_or_reset(dev, dpi_free_irq_vectors, pdev); + if (ret) { + dev_err(dev, "DPI: Failed to add irq free action\n"); + return ret; + } + + ret = devm_request_irq(dev, pci_irq_vector(pdev, DPI_MBOX_PF_VF_INT_IDX), + dpi_mbox_intr_handler, 0, "dpi-mbox", dpi); + if (ret) { + dev_err(dev, "DPI: request_irq failed for mbox; err=%d\n", ret); + return ret; + } + + dpi_reg_write(dpi, DPI_MBOX_VF_PF_INT_ENA_W1S, GENMASK_ULL(31, 0)); + + return 0; +} + +static int dpi_mps_mrrs_config(struct dpipf *dpi, void __user *arg) +{ + struct dpi_mps_mrrs_cfg cfg; + u8 mrrs_val, mps_val; + u64 reg; + + if (copy_from_user(&cfg, arg, sizeof(struct dpi_mps_mrrs_cfg))) + return -EFAULT; + + if (cfg.max_read_req_sz < DPI_EBUS_MRRS_MIN || cfg.max_read_req_sz > DPI_EBUS_MRRS_MAX || + !is_power_of_2(cfg.max_read_req_sz)) + return -EINVAL; + + if (cfg.max_payload_sz < DPI_EBUS_MPS_MIN || cfg.max_payload_sz > DPI_EBUS_MPS_MAX || + !is_power_of_2(cfg.max_payload_sz)) + return -EINVAL; + + if (cfg.port >= DPI_EBUS_MAX_PORTS) + return -EINVAL; + + /* Make sure reserved fields are set to 0 */ + if (cfg.reserved) + return -EINVAL; + + mrrs_val = fls(cfg.max_read_req_sz >> 8); + mps_val = fls(cfg.max_payload_sz >> 8); + + reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(cfg.port)); + reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(0x7) | DPI_EBUS_PORTX_CFG_MPS(0x7)); + reg |= DPI_EBUS_PORTX_CFG_MPS(mps_val) | DPI_EBUS_PORTX_CFG_MRRS(mrrs_val); + dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(cfg.port), reg); + + return 0; +} + +static int dpi_engine_config(struct dpipf *dpi, void __user *arg) +{ + struct dpi_engine_cfg cfg; + unsigned int engine; + u8 *eng_buf; + u64 reg; + + if (copy_from_user(&cfg, arg, sizeof(struct dpi_engine_cfg))) + return -EFAULT; + + /* Make sure reserved fields are set to 0 */ + if (cfg.reserved) + return -EINVAL; + + eng_buf = (u8 *)&cfg.fifo_mask; + + for (engine = 0; engine < DPI_MAX_ENGINES; engine++) { + if (eng_buf[engine] > DPI_MAX_ENG_FIFO_SZ) + return -EINVAL; + dpi_reg_write(dpi, DPI_ENGX_BUF(engine), eng_buf[engine]); + + if (cfg.update_molr) { + if (cfg.molr[engine] > DPI_MAX_ENG_MOLR) + return -EINVAL; + reg = DPI_DMA_ENG_EN_MOLR(cfg.molr[engine]); + dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), reg); + } else { + /* Make sure unused fields are set to 0 */ + if (cfg.molr[engine]) + return -EINVAL; + } + } + + return 0; +} + +static long dpi_dev_ioctl(struct file *fptr, unsigned int cmd, unsigned long data) +{ + void __user *arg = (void __user *)data; + struct dpipf *dpi; + int ret; + + dpi = container_of(fptr->private_data, struct dpipf, miscdev); + + switch (cmd) { + case DPI_MPS_MRRS_CFG: + ret = dpi_mps_mrrs_config(dpi, arg); + break; + case DPI_ENGINE_CFG: + ret = dpi_engine_config(dpi, arg); + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +static const struct file_operations dpi_device_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = dpi_dev_ioctl, + .compat_ioctl = compat_ptr_ioctl, +}; + +static int dpi_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct device *dev = &pdev->dev; + struct dpipf *dpi; + int ret; + + dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); + if (!dpi) + return -ENOMEM; + + dpi->pdev = pdev; + + ret = pcim_enable_device(pdev); + if (ret) { + dev_err(dev, "DPI: Failed to enable PCI device\n"); + return ret; + } + + ret = pcim_iomap_regions(pdev, BIT(0) | BIT(4), KBUILD_MODNAME); + if (ret) { + dev_err(dev, "DPI: Failed to request MMIO region\n"); + return ret; + } + + dpi->reg_base = pcim_iomap_table(pdev)[PCI_DPI_CFG_BAR]; + + /* Initialize global PF registers */ + dpi_init(dpi); + + /* Setup PF-VF mailbox */ + ret = dpi_pfvf_mbox_setup(dpi); + if (ret) { + dev_err(dev, "DPI: Failed to setup pf-vf mbox\n"); + goto err_dpi_fini; + } + + /* Register interrupts */ + ret = dpi_irq_init(dpi); + if (ret) { + dev_err(dev, "DPI: Failed to initialize irq vectors\n"); + goto err_dpi_mbox_free; + } + + pci_set_drvdata(pdev, dpi); + dpi->miscdev.minor = MISC_DYNAMIC_MINOR; + dpi->miscdev.name = KBUILD_MODNAME; + dpi->miscdev.fops = &dpi_device_fops; + dpi->miscdev.parent = dev; + + ret = misc_register(&dpi->miscdev); + if (ret) { + dev_err(dev, "DPI: Failed to register misc device\n"); + goto err_dpi_mbox_free; + } + + return 0; + +err_dpi_mbox_free: + dpi_pfvf_mbox_destroy(dpi); +err_dpi_fini: + dpi_fini(dpi); + return ret; +} + +static void dpi_remove(struct pci_dev *pdev) +{ + struct dpipf *dpi = pci_get_drvdata(pdev); + + misc_deregister(&dpi->miscdev); + pci_sriov_configure_simple(pdev, 0); + dpi_pfvf_mbox_destroy(dpi); + dpi_fini(dpi); + pci_set_drvdata(pdev, NULL); +} + +static const struct pci_device_id dpi_id_table[] = { + { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_MRVL_CN10K_DPI_PF, + PCI_VENDOR_ID_CAVIUM, PCI_SUBDEVID_MRVL_CN10K_DPI_PF) }, + { 0, } /* end of table */ +}; + +static struct pci_driver dpi_driver = { + .name = KBUILD_MODNAME, + .id_table = dpi_id_table, + .probe = dpi_probe, + .remove = dpi_remove, + .sriov_configure = pci_sriov_configure_simple, +}; + +module_pci_driver(dpi_driver); +MODULE_DEVICE_TABLE(pci, dpi_id_table); +MODULE_AUTHOR("Marvell."); +MODULE_DESCRIPTION("Marvell Octeon CN10K DPI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/open-dice.c b/drivers/misc/open-dice.c index 1e3eb2aa44d9..e6a61e6d9427 100644 --- a/drivers/misc/open-dice.c +++ b/drivers/misc/open-dice.c @@ -201,5 +201,6 @@ static void __exit open_dice_exit(void) module_init(open_dice_init); module_exit(open_dice_exit); +MODULE_DESCRIPTION("Driver for Open Profile for DICE."); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("David Brazdil "); diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index c38a6083f0a7..3aaaf47fa4ee 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -84,6 +85,9 @@ #define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025 #define PCI_DEVICE_ID_RENESAS_R8A779F0 0x0031 +#define PCI_VENDOR_ID_ROCKCHIP 0x1d87 +#define PCI_DEVICE_ID_ROCKCHIP_RK3588 0x3588 + static DEFINE_IDA(pci_endpoint_test_ida); #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ @@ -140,18 +144,6 @@ static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test, writel(value, test->base + offset); } -static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test, - int bar, int offset) -{ - return readl(test->bar[bar] + offset); -} - -static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test, - int bar, u32 offset, u32 value) -{ - writel(value, test->bar[bar] + offset); -} - static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) { struct pci_endpoint_test *test = dev_id; @@ -272,31 +264,60 @@ static const u32 bar_test_pattern[] = { 0xA5A5A5A5, }; +static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test, + enum pci_barno barno, int offset, + void *write_buf, void *read_buf, + int size) +{ + memset(write_buf, bar_test_pattern[barno], size); + memcpy_toio(test->bar[barno] + offset, write_buf, size); + + memcpy_fromio(read_buf, test->bar[barno] + offset, size); + + return memcmp(write_buf, read_buf, size); +} + static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, enum pci_barno barno) { - int j; - u32 val; - int size; + int j, bar_size, buf_size, iters, remain; + void *write_buf __free(kfree) = NULL; + void *read_buf __free(kfree) = NULL; struct pci_dev *pdev = test->pdev; if (!test->bar[barno]) return false; - size = pci_resource_len(pdev, barno); + bar_size = pci_resource_len(pdev, barno); if (barno == test->test_reg_bar) - size = 0x4; + bar_size = 0x4; - for (j = 0; j < size; j += 4) - pci_endpoint_test_bar_writel(test, barno, j, - bar_test_pattern[barno]); + /* + * Allocate a buffer of max size 1MB, and reuse that buffer while + * iterating over the whole BAR size (which might be much larger). + */ + buf_size = min(SZ_1M, bar_size); - for (j = 0; j < size; j += 4) { - val = pci_endpoint_test_bar_readl(test, barno, j); - if (val != bar_test_pattern[barno]) + write_buf = kmalloc(buf_size, GFP_KERNEL); + if (!write_buf) + return false; + + read_buf = kmalloc(buf_size, GFP_KERNEL); + if (!read_buf) + return false; + + iters = bar_size / buf_size; + for (j = 0; j < iters; j++) + if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * j, + write_buf, read_buf, buf_size)) + return false; + + remain = bar_size % buf_size; + if (remain) + if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * iters, + write_buf, read_buf, remain)) return false; - } return true; } @@ -824,11 +845,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, init_completion(&test->irq_raised); mutex_init(&test->mutex); - if ((dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)) != 0) && - dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { - dev_err(dev, "Cannot set DMA mask\n"); - return -EINVAL; - } + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)); err = pci_enable_device(pdev); if (err) { @@ -980,6 +997,15 @@ static const struct pci_endpoint_test_data j721e_data = { .irq_type = IRQ_TYPE_MSI, }; +static const struct pci_endpoint_test_data rk3588_data = { + .alignment = SZ_64K, + .irq_type = IRQ_TYPE_MSI, +}; + +/* + * If the controller's Vendor/Device ID are programmable, you may be able to + * use one of the existing entries for testing instead of adding a new one. + */ static const struct pci_device_id pci_endpoint_test_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x), .driver_data = (kernel_ulong_t)&default_data, @@ -1017,6 +1043,9 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721S2), .driver_data = (kernel_ulong_t)&j721e_data, }, + { PCI_DEVICE(PCI_VENDOR_ID_ROCKCHIP, PCI_DEVICE_ID_ROCKCHIP_RK3588), + .driver_data = (kernel_ulong_t)&rk3588_data, + }, { } }; MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl); diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index c4f963cf96f2..ff172cf4614d 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -198,7 +198,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) { unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0; static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 }; - long timeout; + long time_left; pr_debug("%s", __func__); @@ -208,11 +208,11 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) return -EIO; } - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME)); - if (timeout <= 0) { + if (time_left <= 0) { pr_err(" waiting for ver info- timed out or received signal"); - return timeout ? -ERESTARTSYS : -ETIMEDOUT; + return time_left ? -ERESTARTSYS : -ETIMEDOUT; } reinit_completion(&kim_gdata->kim_rcvd); /* diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 7dd86a9858ab..1d54680d6ed2 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -229,7 +229,7 @@ static int __maybe_unused tifm_7xx1_resume(struct device *dev_d) struct pci_dev *dev = to_pci_dev(dev_d); struct tifm_adapter *fm = pci_get_drvdata(dev); int rc; - unsigned long timeout; + unsigned long time_left; unsigned int good_sockets = 0, bad_sockets = 0; unsigned long flags; /* Maximum number of entries is 4 */ @@ -265,8 +265,8 @@ static int __maybe_unused tifm_7xx1_resume(struct device *dev_d) if (good_sockets) { fm->finish_me = &finish_resume; spin_unlock_irqrestore(&fm->lock, flags); - timeout = wait_for_completion_timeout(&finish_resume, HZ); - dev_dbg(&dev->dev, "wait returned %lu\n", timeout); + time_left = wait_for_completion_timeout(&finish_resume, HZ); + dev_dbg(&dev->dev, "wait returned %lu\n", time_left); writel(TIFM_IRQ_FIFOMASK(good_sockets) | TIFM_IRQ_CARDMASK(good_sockets), fm->addr + FM_CLEAR_INTERRUPT_ENABLE); diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c index a3bc2823143e..2ad4387c9837 100644 --- a/drivers/misc/tsl2550.c +++ b/drivers/misc/tsl2550.c @@ -420,7 +420,7 @@ static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume); #endif /* CONFIG_PM_SLEEP */ static const struct i2c_device_id tsl2550_id[] = { - { "tsl2550", 0 }, + { "tsl2550" }, { } }; MODULE_DEVICE_TABLE(i2c, tsl2550_id); diff --git a/drivers/misc/vcpu_stall_detector.c b/drivers/misc/vcpu_stall_detector.c index e2015c87f03f..41b8c2119e20 100644 --- a/drivers/misc/vcpu_stall_detector.c +++ b/drivers/misc/vcpu_stall_detector.c @@ -32,6 +32,7 @@ struct vcpu_stall_detect_config { u32 clock_freq_hz; u32 stall_timeout_sec; + int ppi_irq; void __iomem *membase; struct platform_device *dev; @@ -77,6 +78,12 @@ vcpu_stall_detect_timer_fn(struct hrtimer *hrtimer) return HRTIMER_RESTART; } +static irqreturn_t vcpu_stall_detector_irq(int irq, void *dev) +{ + panic("vCPU stall detector"); + return IRQ_HANDLED; +} + static int start_stall_detector_cpu(unsigned int cpu) { u32 ticks, ping_timeout_ms; @@ -132,7 +139,7 @@ static int stop_stall_detector_cpu(unsigned int cpu) static int vcpu_stall_detect_probe(struct platform_device *pdev) { - int ret; + int ret, irq; struct resource *r; void __iomem *membase; u32 clock_freq_hz = VCPU_STALL_DEFAULT_CLOCK_HZ; @@ -169,9 +176,22 @@ static int vcpu_stall_detect_probe(struct platform_device *pdev) vcpu_stall_config = (struct vcpu_stall_detect_config) { .membase = membase, .clock_freq_hz = clock_freq_hz, - .stall_timeout_sec = stall_timeout_sec + .stall_timeout_sec = stall_timeout_sec, + .ppi_irq = -1, }; + irq = platform_get_irq_optional(pdev, 0); + if (irq > 0) { + ret = request_percpu_irq(irq, + vcpu_stall_detector_irq, + "vcpu_stall_detector", + vcpu_stall_detectors); + if (ret) + goto err; + + vcpu_stall_config.ppi_irq = irq; + } + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "virt/vcpu_stall_detector:online", start_stall_detector_cpu, @@ -184,6 +204,9 @@ static int vcpu_stall_detect_probe(struct platform_device *pdev) vcpu_stall_config.hp_online = ret; return 0; err: + if (vcpu_stall_config.ppi_irq > 0) + free_percpu_irq(vcpu_stall_config.ppi_irq, + vcpu_stall_detectors); return ret; } @@ -193,6 +216,10 @@ static void vcpu_stall_detect_remove(struct platform_device *pdev) cpuhp_remove_state(vcpu_stall_config.hp_online); + if (vcpu_stall_config.ppi_irq > 0) + free_percpu_irq(vcpu_stall_config.ppi_irq, + vcpu_stall_detectors); + for_each_possible_cpu(cpu) stop_stall_detector_cpu(cpu); } diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 8f50abe739b7..0783fc121bbb 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -2256,6 +2256,9 @@ static int b53_change_mtu(struct dsa_switch *ds, int port, int mtu) if (is5325(dev) || is5365(dev)) return -EOPNOTSUPP; + if (!dsa_is_cpu_port(ds, port)) + return 0; + enable_jumbo = (mtu >= JMS_MIN_SIZE); allow_10_100 = (dev->chip_id == BCM583XX_DEVICE_ID); diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 07c897b13de1..5b4e2ce5470d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3626,7 +3626,8 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) mv88e6xxx_reg_lock(chip); if (chip->info->ops->port_set_jumbo_size) ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu); - else if (chip->info->ops->set_max_frame_size) + else if (chip->info->ops->set_max_frame_size && + dsa_is_cpu_port(ds, port)) ret = chip->info->ops->set_max_frame_size(chip, new_mtu); mv88e6xxx_reg_unlock(chip); diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c index 24a64ec1073e..e7fb7d6d283d 100644 --- a/drivers/net/ethernet/google/gve/gve_tx.c +++ b/drivers/net/ethernet/google/gve/gve_tx.c @@ -158,15 +158,16 @@ static int gve_clean_xdp_done(struct gve_priv *priv, struct gve_tx_ring *tx, u32 to_do) { struct gve_tx_buffer_state *info; - u32 clean_end = tx->done + to_do; u64 pkts = 0, bytes = 0; size_t space_freed = 0; u32 xsk_complete = 0; u32 idx; + int i; - for (; tx->done < clean_end; tx->done++) { + for (i = 0; i < to_do; i++) { idx = tx->done & tx->mask; info = &tx->info[idx]; + tx->done++; if (unlikely(!info->xdp.size)) continue; diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c index 7967a92803c2..16761fde6c6c 100644 --- a/drivers/net/ethernet/mediatek/airoha_eth.c +++ b/drivers/net/ethernet/mediatek/airoha_eth.c @@ -977,7 +977,7 @@ static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable) return 0; error: - for (i--; i >= 0; i++) + for (i--; i >= 0; i--) airoha_set_gdm_port(eth, port_list[i], false); return err; @@ -1585,7 +1585,6 @@ static int airoha_qdma_init_rx_queue(struct airoha_eth *eth, static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) { - enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); struct airoha_eth *eth = q->eth; while (q->queued) { @@ -1593,7 +1592,7 @@ static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) struct page *page = virt_to_head_page(e->buf); dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len, - dir); + page_pool_get_dma_dir(q->page_pool)); page_pool_put_full_page(q->page_pool, page, false); q->tail = (q->tail + 1) % q->ndesc; q->queued--; @@ -2431,9 +2430,11 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, return NETDEV_TX_OK; error_unmap: - for (i--; i >= 0; i++) - dma_unmap_single(dev->dev.parent, q->entry[i].dma_addr, - q->entry[i].dma_len, DMA_TO_DEVICE); + for (i--; i >= 0; i--) { + index = (q->head + i) % q->ndesc; + dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr, + q->entry[index].dma_len, DMA_TO_DEVICE); + } spin_unlock_bh(&q->lock); error: diff --git a/drivers/net/ethernet/meta/Kconfig b/drivers/net/ethernet/meta/Kconfig index d8f5e9f9bb33..86034ea4ba5b 100644 --- a/drivers/net/ethernet/meta/Kconfig +++ b/drivers/net/ethernet/meta/Kconfig @@ -20,6 +20,8 @@ if NET_VENDOR_META config FBNIC tristate "Meta Platforms Host Network Interface" depends on X86_64 || COMPILE_TEST + depends on S390=n + depends on MAX_SKB_FRAGS < 22 depends on PCI_MSI select PHYLINK help diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index ccfc83857c26..9e366f275406 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -1193,7 +1193,6 @@ static int baycom_epp_par_probe(struct pardevice *par_dev) static struct parport_driver baycom_epp_par_driver = { .name = "bce", .probe = baycom_epp_par_probe, - .devmodel = true, }; static void __init baycom_epp_dev_setup(struct net_device *dev) diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index fd7da5bb1fa5..00ebc25d0b22 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -503,7 +503,6 @@ static int baycom_par_probe(struct pardevice *par_dev) static struct parport_driver baycom_par_driver = { .name = "bcp", .probe = baycom_par_probe, - .devmodel = true, }; static int __init init_baycompar(void) diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c index cc7d1113ece0..e39bfaefe8c5 100644 --- a/drivers/net/plip/plip.c +++ b/drivers/net/plip/plip.c @@ -1358,7 +1358,6 @@ static struct parport_driver plip_driver = { .probe = plip_probe, .match_port = plip_attach, .detach = plip_detach, - .devmodel = true, }; static void __exit plip_cleanup_module (void) diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c index f2aef84fc08d..d5a9360323d2 100644 --- a/drivers/net/wwan/mhi_wwan_mbim.c +++ b/drivers/net/wwan/mhi_wwan_mbim.c @@ -42,6 +42,8 @@ #define MHI_MBIM_LINK_HASH_SIZE 8 #define LINK_HASH(session) ((session) % MHI_MBIM_LINK_HASH_SIZE) +#define WDS_BIND_MUX_DATA_PORT_MUX_ID 112 + struct mhi_mbim_link { struct mhi_mbim_context *mbim; struct net_device *ndev; @@ -93,6 +95,15 @@ static struct mhi_mbim_link *mhi_mbim_get_link_rcu(struct mhi_mbim_context *mbim return NULL; } +static int mhi_mbim_get_link_mux_id(struct mhi_controller *cntrl) +{ + if (strcmp(cntrl->name, "foxconn-dw5934e") == 0 || + strcmp(cntrl->name, "foxconn-t99w515") == 0) + return WDS_BIND_MUX_DATA_PORT_MUX_ID; + + return 0; +} + static struct sk_buff *mbim_tx_fixup(struct sk_buff *skb, unsigned int session, u16 tx_seq) { @@ -596,7 +607,7 @@ static int mhi_mbim_probe(struct mhi_device *mhi_dev, const struct mhi_device_id { struct mhi_controller *cntrl = mhi_dev->mhi_cntrl; struct mhi_mbim_context *mbim; - int err; + int err, link_id; mbim = devm_kzalloc(&mhi_dev->dev, sizeof(*mbim), GFP_KERNEL); if (!mbim) @@ -617,8 +628,11 @@ static int mhi_mbim_probe(struct mhi_device *mhi_dev, const struct mhi_device_id /* Number of transfer descriptors determines size of the queue */ mbim->rx_queue_sz = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE); + /* Get the corresponding mux_id from mhi */ + link_id = mhi_mbim_get_link_mux_id(cntrl); + /* Register wwan link ops with MHI controller representing WWAN instance */ - return wwan_register_ops(&cntrl->mhi_dev->dev, &mhi_mbim_wwan_ops, mbim, 0); + return wwan_register_ops(&cntrl->mhi_dev->dev, &mhi_mbim_wwan_ops, mbim, link_id); } static void mhi_mbim_remove(struct mhi_device *mhi_dev) diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c index e0b1e7a616ca..10a8c1080b10 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.c +++ b/drivers/net/wwan/t7xx/t7xx_pci.c @@ -852,6 +852,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev) static const struct pci_device_id t7xx_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x4d75) }, + { PCI_DEVICE(0x14c0, 0x4d75) }, // Dell DW5933e { } }; MODULE_DEVICE_TABLE(pci, t7xx_pci_table); diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c index d6bbcc7b5b90..31946387badf 100644 --- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c @@ -1565,7 +1565,7 @@ static struct class_interface switchtec_interface = { static int __init switchtec_ntb_init(void) { - switchtec_interface.class = switchtec_class; + switchtec_interface.class = &switchtec_class; return class_interface_register(&switchtec_interface); } module_init(switchtec_ntb_init); diff --git a/drivers/nvmem/apple-efuses.c b/drivers/nvmem/apple-efuses.c index d3d49d22338b..1d1bf84a099f 100644 --- a/drivers/nvmem/apple-efuses.c +++ b/drivers/nvmem/apple-efuses.c @@ -78,4 +78,5 @@ static struct platform_driver apple_efuses_driver = { module_platform_driver(apple_efuses_driver); MODULE_AUTHOR("Sven Peter "); +MODULE_DESCRIPTION("Apple SoC eFuse driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c index 5cdf339cfbec..3d8c87835f4d 100644 --- a/drivers/nvmem/brcm_nvram.c +++ b/drivers/nvmem/brcm_nvram.c @@ -253,5 +253,6 @@ static int __init brcm_nvram_init(void) subsys_initcall_sync(brcm_nvram_init); MODULE_AUTHOR("Rafał Miłecki"); +MODULE_DESCRIPTION("Broadcom I/O-mapped NVRAM support driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(of, brcm_nvram_of_match_table); diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index f8dd7eb40fbe..516dfd861b9f 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -179,12 +179,35 @@ static ssize_t type_show(struct device *dev, { struct nvmem_device *nvmem = to_nvmem_device(dev); - return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]); + return sysfs_emit(buf, "%s\n", nvmem_type_str[nvmem->type]); } static DEVICE_ATTR_RO(type); +static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct nvmem_device *nvmem = to_nvmem_device(dev); + + return sysfs_emit(buf, "%d\n", nvmem->read_only); +} + +static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nvmem_device *nvmem = to_nvmem_device(dev); + int ret = kstrtobool(buf, &nvmem->read_only); + + if (ret < 0) + return ret; + + return count; +} + +static DEVICE_ATTR_RW(force_ro); + static struct attribute *nvmem_attrs[] = { + &dev_attr_force_ro.attr, &dev_attr_type.attr, NULL, }; @@ -203,19 +226,12 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj, dev = kobj_to_dev(kobj); nvmem = to_nvmem_device(dev); - /* Stop the user from reading */ - if (pos >= nvmem->size) - return 0; - if (!IS_ALIGNED(pos, nvmem->stride)) return -EINVAL; if (count < nvmem->word_size) return -EINVAL; - if (pos + count > nvmem->size) - count = nvmem->size - pos; - count = round_down(count, nvmem->word_size); if (!nvmem->reg_read) @@ -243,19 +259,12 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj, dev = kobj_to_dev(kobj); nvmem = to_nvmem_device(dev); - /* Stop the user from writing */ - if (pos >= nvmem->size) - return -EFBIG; - if (!IS_ALIGNED(pos, nvmem->stride)) return -EINVAL; if (count < nvmem->word_size) return -EINVAL; - if (pos + count > nvmem->size) - count = nvmem->size - pos; - count = round_down(count, nvmem->word_size); if (!nvmem->reg_write) @@ -299,6 +308,25 @@ static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj, return nvmem_bin_attr_get_umode(nvmem); } +static umode_t nvmem_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct device *dev = kobj_to_dev(kobj); + struct nvmem_device *nvmem = to_nvmem_device(dev); + + /* + * If the device has no .reg_write operation, do not allow + * configuration as read-write. + * If the device is set as read-only by configuration, it + * can be forced into read-write mode using the 'force_ro' + * attribute. + */ + if (attr == &dev_attr_force_ro.attr && !nvmem->reg_write) + return 0; /* Attribute not visible */ + + return attr->mode; +} + static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id, int index); @@ -355,11 +383,7 @@ static const struct attribute_group nvmem_bin_group = { .bin_attrs = nvmem_bin_attributes, .attrs = nvmem_attrs, .is_bin_visible = nvmem_bin_attr_is_visible, -}; - -/* Cell attributes will be dynamically allocated */ -static struct attribute_group nvmem_cells_group = { - .name = "cells", + .is_visible = nvmem_attr_is_visible, }; static const struct attribute_group *nvmem_dev_groups[] = { @@ -367,11 +391,6 @@ static const struct attribute_group *nvmem_dev_groups[] = { NULL, }; -static const struct attribute_group *nvmem_cells_groups[] = { - &nvmem_cells_group, - NULL, -}; - static struct bin_attribute bin_attr_nvmem_eeprom_compat = { .attr = { .name = "eeprom", @@ -428,23 +447,24 @@ static void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem, static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem) { - struct bin_attribute **cells_attrs, *attrs; + struct attribute_group group = { + .name = "cells", + }; struct nvmem_cell_entry *entry; + struct bin_attribute *attrs; unsigned int ncells = 0, i = 0; int ret = 0; mutex_lock(&nvmem_mutex); - if (list_empty(&nvmem->cells) || nvmem->sysfs_cells_populated) { - nvmem_cells_group.bin_attrs = NULL; + if (list_empty(&nvmem->cells) || nvmem->sysfs_cells_populated) goto unlock_mutex; - } /* Allocate an array of attributes with a sentinel */ ncells = list_count_nodes(&nvmem->cells); - cells_attrs = devm_kcalloc(&nvmem->dev, ncells + 1, - sizeof(struct bin_attribute *), GFP_KERNEL); - if (!cells_attrs) { + group.bin_attrs = devm_kcalloc(&nvmem->dev, ncells + 1, + sizeof(struct bin_attribute *), GFP_KERNEL); + if (!group.bin_attrs) { ret = -ENOMEM; goto unlock_mutex; } @@ -471,13 +491,11 @@ static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem) goto unlock_mutex; } - cells_attrs[i] = &attrs[i]; + group.bin_attrs[i] = &attrs[i]; i++; } - nvmem_cells_group.bin_attrs = cells_attrs; - - ret = device_add_groups(&nvmem->dev, nvmem_cells_groups); + ret = device_add_group(&nvmem->dev, &group); if (ret) goto unlock_mutex; diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c index 6c2f80e166e2..d7f9ac99a212 100644 --- a/drivers/nvmem/meson-efuse.c +++ b/drivers/nvmem/meson-efuse.c @@ -48,20 +48,19 @@ static int meson_efuse_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct meson_sm_firmware *fw; - struct device_node *sm_np; struct nvmem_device *nvmem; struct nvmem_config *econfig; struct clk *clk; unsigned int size; + struct device_node *sm_np __free(device_node) = + of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0); - sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0); if (!sm_np) { dev_err(&pdev->dev, "no secure-monitor node\n"); return -ENODEV; } fw = meson_sm_get(sm_np); - of_node_put(sm_np); if (!fw) return -EPROBE_DEFER; diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index 2b40978ddb18..013e67136f3b 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -206,6 +206,7 @@ static int rockchip_rk3399_efuse_read(void *context, unsigned int offset, static struct nvmem_config econfig = { .name = "rockchip-efuse", .add_legacy_fixed_of_cells = true, + .type = NVMEM_TYPE_OTP, .stride = 1, .word_size = 1, .read_only = true, diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c index cb9aa5428350..ebc3f0b24166 100644 --- a/drivers/nvmem/rockchip-otp.c +++ b/drivers/nvmem/rockchip-otp.c @@ -255,6 +255,8 @@ static int rockchip_otp_read(void *context, unsigned int offset, static struct nvmem_config otp_config = { .name = "rockchip-otp", .owner = THIS_MODULE, + .add_legacy_fixed_of_cells = true, + .type = NVMEM_TYPE_OTP, .read_only = true, .stride = 1, .word_size = 1, diff --git a/drivers/nvmem/u-boot-env.c b/drivers/nvmem/u-boot-env.c index befbab156cda..936e39b20b38 100644 --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c @@ -249,5 +249,6 @@ static struct platform_driver u_boot_env_driver = { module_platform_driver(u_boot_env_driver); MODULE_AUTHOR("Rafał Miłecki"); +MODULE_DESCRIPTION("U-Boot environment variables support module"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table); diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c index 6d78ec3a762f..2231dbfd870d 100644 --- a/drivers/parport/daisy.c +++ b/drivers/parport/daisy.c @@ -97,7 +97,6 @@ static int daisy_drv_probe(struct pardevice *par_dev) static struct parport_driver daisy_driver = { .name = "daisy_drv", .probe = daisy_drv_probe, - .devmodel = true, }; /* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains. diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index bd388560ed59..c2e371c50dcf 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -51,12 +51,12 @@ static int do_active_device(struct ctl_table *table, int write, for (dev = port->devices; dev ; dev = dev->next) { if(dev == port->cad) { - len += sprintf(buffer, "%s\n", dev->name); + len += snprintf(buffer, sizeof(buffer), "%s\n", dev->name); } } if(!len) { - len += sprintf(buffer, "%s\n", "none"); + len += snprintf(buffer, sizeof(buffer), "%s\n", "none"); } if (len > *lenp) @@ -87,19 +87,19 @@ static int do_autoprobe(struct ctl_table *table, int write, } if ((str = info->class_name) != NULL) - len += sprintf (buffer + len, "CLASS:%s;\n", str); + len += snprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str); if ((str = info->model) != NULL) - len += sprintf (buffer + len, "MODEL:%s;\n", str); + len += snprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str); if ((str = info->mfr) != NULL) - len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str); + len += snprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str); if ((str = info->description) != NULL) - len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str); + len += snprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str); if ((str = info->cmdset) != NULL) - len += sprintf (buffer + len, "COMMAND SET:%s;\n", str); + len += snprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str); if (len > *lenp) len = *lenp; @@ -117,7 +117,7 @@ static int do_hardware_base_addr(struct ctl_table *table, int write, void *result, size_t *lenp, loff_t *ppos) { struct parport *port = (struct parport *)table->extra1; - char buffer[20]; + char buffer[64]; int len = 0; if (*ppos) { @@ -128,7 +128,7 @@ static int do_hardware_base_addr(struct ctl_table *table, int write, if (write) /* permissions prevent this anyway */ return -EACCES; - len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi); + len += snprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi); if (len > *lenp) len = *lenp; @@ -155,7 +155,7 @@ static int do_hardware_irq(struct ctl_table *table, int write, if (write) /* permissions prevent this anyway */ return -EACCES; - len += sprintf (buffer, "%d\n", port->irq); + len += snprintf (buffer, sizeof(buffer), "%d\n", port->irq); if (len > *lenp) len = *lenp; @@ -182,7 +182,7 @@ static int do_hardware_dma(struct ctl_table *table, int write, if (write) /* permissions prevent this anyway */ return -EACCES; - len += sprintf (buffer, "%d\n", port->dma); + len += snprintf (buffer, sizeof(buffer), "%d\n", port->dma); if (len > *lenp) len = *lenp; @@ -213,7 +213,7 @@ static int do_hardware_modes(struct ctl_table *table, int write, #define printmode(x) \ do { \ if (port->modes & PARPORT_MODE_##x) \ - len += sprintf(buffer + len, "%s%s", f++ ? "," : "", #x); \ + len += snprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \ } while (0) int f = 0; printmode(PCSPP); diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 49c74ded8a53..2d34f783b36e 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -49,8 +49,6 @@ static DEFINE_SPINLOCK(parportlist_lock); static LIST_HEAD(all_ports); static DEFINE_SPINLOCK(full_list_lock); -static LIST_HEAD(drivers); - static DEFINE_MUTEX(registration_lock); /* What you can do to a port that's gone away.. */ @@ -165,10 +163,6 @@ static int driver_check(struct device_driver *dev_drv, void *_port) static void attach_driver_chain(struct parport *port) { /* caller has exclusive registration_lock */ - struct parport_driver *drv; - - list_for_each_entry(drv, &drivers, list) - drv->attach(port); /* * call the driver_check function of the drivers registered in @@ -191,10 +185,7 @@ static int driver_detach(struct device_driver *_drv, void *_port) /* Call detach(port) for each registered driver. */ static void detach_driver_chain(struct parport *port) { - struct parport_driver *drv; /* caller has exclusive registration_lock */ - list_for_each_entry(drv, &drivers, list) - drv->detach(port); /* * call the detach function of the drivers registered in @@ -1219,4 +1210,5 @@ irqreturn_t parport_irq_handler(int irq, void *dev_id) } EXPORT_SYMBOL(parport_irq_handler); +MODULE_DESCRIPTION("Parallel-port resource manager"); MODULE_LICENSE("GPL"); diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 8f3c6c080d88..55c853686051 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -177,10 +177,7 @@ static void pci_clip_resource_to_region(struct pci_bus *bus, static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, unsigned long type_mask, - resource_size_t (*alignf)(void *, - const struct resource *, - resource_size_t, - resource_size_t), + resource_alignf alignf, void *alignf_data, struct pci_bus_region *region) { @@ -251,10 +248,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, unsigned long type_mask, - resource_size_t (*alignf)(void *, - const struct resource *, - resource_size_t, - resource_size_t), + resource_alignf alignf, void *alignf_data) { #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index e534c02ee34f..4d2c188f5835 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -215,14 +215,6 @@ config PCIE_MT7621 help This selects a driver for the MediaTek MT7621 PCIe Controller. -config PCIE_MICROCHIP_HOST - tristate "Microchip AXI PCIe controller" - depends on PCI_MSI && OF - select PCI_HOST_COMMON - help - Say Y here if you want kernel to support the Microchip AXI PCIe - Host Bridge driver. - config PCI_HYPERV_INTERFACE tristate "Microsoft Hyper-V PCI Interface" depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI @@ -356,4 +348,5 @@ config PCIE_XILINX_CPM source "drivers/pci/controller/cadence/Kconfig" source "drivers/pci/controller/dwc/Kconfig" source "drivers/pci/controller/mobiveil/Kconfig" +source "drivers/pci/controller/plda/Kconfig" endmenu diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile index f2b19e6174af..038ccbd9e3ba 100644 --- a/drivers/pci/controller/Makefile +++ b/drivers/pci/controller/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o obj-$(CONFIG_PCIE_MEDIATEK_GEN3) += pcie-mediatek-gen3.o -obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o obj-$(CONFIG_VMD) += vmd.o obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o @@ -44,6 +43,7 @@ obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621.o # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW obj-y += dwc/ obj-y += mobiveil/ +obj-y += plda/ # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 8afacc90c63b..4c38181acffa 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -311,16 +311,30 @@ config PCIE_RCAR_GEN4_EP SoCs. To compile this driver as a module, choose M here: the module will be called pcie-rcar-gen4.ko. This uses the DesignWare core. +config PCIE_ROCKCHIP_DW + bool + config PCIE_ROCKCHIP_DW_HOST - bool "Rockchip DesignWare PCIe controller" - select PCIE_DW - select PCIE_DW_HOST + bool "Rockchip DesignWare PCIe controller (host mode)" depends on PCI_MSI depends on ARCH_ROCKCHIP || COMPILE_TEST depends on OF + select PCIE_DW_HOST + select PCIE_ROCKCHIP_DW help Enables support for the DesignWare PCIe controller in the - Rockchip SoC except RK3399. + Rockchip SoC (except RK3399) to work in host mode. + +config PCIE_ROCKCHIP_DW_EP + bool "Rockchip DesignWare PCIe controller (endpoint mode)" + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on OF + depends on PCI_ENDPOINT + select PCIE_DW_EP + select PCIE_ROCKCHIP_DW + help + Enables support for the DesignWare PCIe controller in the + Rockchip SoC (except RK3399) to work in endpoint mode. config PCI_EXYNOS tristate "Samsung Exynos PCIe controller" diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile index bac103faa523..ec215b3d6191 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o obj-$(CONFIG_PCIE_QCOM_EP) += pcie-qcom-ep.o obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o -obj-$(CONFIG_PCIE_ROCKCHIP_DW_HOST) += pcie-dw-rockchip.o +obj-$(CONFIG_PCIE_ROCKCHIP_DW) += pcie-dw-rockchip.o obj-$(CONFIG_PCIE_INTEL_GW) += pcie-intel-gw.o obj-$(CONFIG_PCIE_KEEMBAY) += pcie-keembay.o obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index d2d17d37d3e0..4fe3b0cb72ec 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -13,11 +13,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -113,9 +113,9 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset, writel(value, pcie->base + offset); } -static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) +static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr) { - return pci_addr & DRA7XX_CPU_TO_BUS_ADDR; + return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR; } static int dra7xx_pcie_link_up(struct dw_pcie *pci) @@ -474,7 +474,7 @@ static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, return ret; } - dw_pcie_ep_init_notify(ep); + pci_epc_init_notify(ep->epc); return 0; } diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c index a33fa98a252e..fa45da28a218 100644 --- a/drivers/pci/controller/dwc/pci-exynos.c +++ b/drivers/pci/controller/dwc/pci-exynos.c @@ -54,43 +54,11 @@ struct exynos_pcie { struct dw_pcie pci; void __iomem *elbi_base; - struct clk *clk; - struct clk *bus_clk; + struct clk_bulk_data *clks; struct phy *phy; struct regulator_bulk_data supplies[2]; }; -static int exynos_pcie_init_clk_resources(struct exynos_pcie *ep) -{ - struct device *dev = ep->pci.dev; - int ret; - - ret = clk_prepare_enable(ep->clk); - if (ret) { - dev_err(dev, "cannot enable pcie rc clock"); - return ret; - } - - ret = clk_prepare_enable(ep->bus_clk); - if (ret) { - dev_err(dev, "cannot enable pcie bus clock"); - goto err_bus_clk; - } - - return 0; - -err_bus_clk: - clk_disable_unprepare(ep->clk); - - return ret; -} - -static void exynos_pcie_deinit_clk_resources(struct exynos_pcie *ep) -{ - clk_disable_unprepare(ep->bus_clk); - clk_disable_unprepare(ep->clk); -} - static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg) { writel(val, base + reg); @@ -332,17 +300,9 @@ static int exynos_pcie_probe(struct platform_device *pdev) if (IS_ERR(ep->elbi_base)) return PTR_ERR(ep->elbi_base); - ep->clk = devm_clk_get(dev, "pcie"); - if (IS_ERR(ep->clk)) { - dev_err(dev, "Failed to get pcie rc clock\n"); - return PTR_ERR(ep->clk); - } - - ep->bus_clk = devm_clk_get(dev, "pcie_bus"); - if (IS_ERR(ep->bus_clk)) { - dev_err(dev, "Failed to get pcie bus clock\n"); - return PTR_ERR(ep->bus_clk); - } + ret = devm_clk_bulk_get_all_enable(dev, &ep->clks); + if (ret < 0) + return ret; ep->supplies[0].supply = "vdd18"; ep->supplies[1].supply = "vdd10"; @@ -351,10 +311,6 @@ static int exynos_pcie_probe(struct platform_device *pdev) if (ret) return ret; - ret = exynos_pcie_init_clk_resources(ep); - if (ret) - return ret; - ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); if (ret) return ret; @@ -369,7 +325,6 @@ static int exynos_pcie_probe(struct platform_device *pdev) fail_probe: phy_exit(ep->phy); - exynos_pcie_deinit_clk_resources(ep); regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); return ret; @@ -383,7 +338,6 @@ static void exynos_pcie_remove(struct platform_device *pdev) exynos_pcie_assert_core_reset(ep); phy_power_off(ep->phy); phy_exit(ep->phy); - exynos_pcie_deinit_clk_resources(ep); regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); } @@ -437,5 +391,6 @@ static struct platform_driver exynos_pcie_driver = { }, }; module_platform_driver(exynos_pcie_driver); +MODULE_DESCRIPTION("Samsung Exynos PCIe host controller driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, exynos_pcie_of_match); diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 917c69edee1d..964d67756eb2 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -11,14 +11,13 @@ #include #include #include -#include +#include #include #include #include #include #include #include -#include #include #include #include @@ -107,8 +106,7 @@ struct imx6_pcie_drvdata { struct imx6_pcie { struct dw_pcie *pci; - int reset_gpio; - bool gpio_active_high; + struct gpio_desc *reset_gpiod; bool link_is_up; struct clk_bulk_data clks[IMX6_PCIE_MAX_CLKS]; struct regmap *iomuxc_gpr; @@ -721,9 +719,7 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) } /* Some boards don't have PCIe reset GPIO. */ - if (gpio_is_valid(imx6_pcie->reset_gpio)) - gpio_set_value_cansleep(imx6_pcie->reset_gpio, - imx6_pcie->gpio_active_high); + gpiod_set_value_cansleep(imx6_pcie->reset_gpiod, 1); } static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) @@ -771,10 +767,9 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) } /* Some boards don't have PCIe reset GPIO. */ - if (gpio_is_valid(imx6_pcie->reset_gpio)) { + if (imx6_pcie->reset_gpiod) { msleep(100); - gpio_set_value_cansleep(imx6_pcie->reset_gpio, - !imx6_pcie->gpio_active_high); + gpiod_set_value_cansleep(imx6_pcie->reset_gpiod, 0); /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ msleep(100); } @@ -1131,7 +1126,7 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie, return ret; } - dw_pcie_ep_init_notify(ep); + pci_epc_init_notify(ep->epc); /* Start LTSSM. */ imx6_pcie_ltssm_enable(dev); @@ -1285,22 +1280,11 @@ static int imx6_pcie_probe(struct platform_device *pdev) return PTR_ERR(pci->dbi_base); /* Fetch GPIOs */ - imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0); - imx6_pcie->gpio_active_high = of_property_read_bool(node, - "reset-gpio-active-high"); - if (gpio_is_valid(imx6_pcie->reset_gpio)) { - ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio, - imx6_pcie->gpio_active_high ? - GPIOF_OUT_INIT_HIGH : - GPIOF_OUT_INIT_LOW, - "PCIe reset"); - if (ret) { - dev_err(dev, "unable to get reset gpio\n"); - return ret; - } - } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { - return imx6_pcie->reset_gpio; - } + imx6_pcie->reset_gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(imx6_pcie->reset_gpiod)) + return dev_err_probe(dev, PTR_ERR(imx6_pcie->reset_gpiod), + "unable to get reset gpio\n"); + gpiod_set_consumer_name(imx6_pcie->reset_gpiod, "PCIe reset"); if (imx6_pcie->drvdata->clks_cnt >= IMX6_PCIE_MAX_CLKS) return dev_err_probe(dev, -ENOMEM, "clks_cnt is too big\n"); diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index d3a7d14ee685..52c6420ae200 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -34,6 +34,11 @@ #define PCIE_DEVICEID_SHIFT 16 /* Application registers */ +#define PID 0x000 +#define RTL GENMASK(15, 11) +#define RTL_SHIFT 11 +#define AM6_PCI_PG1_RTL_VER 0x15 + #define CMD_STATUS 0x004 #define LTSSM_EN_VAL BIT(0) #define OB_XLAT_EN_VAL BIT(1) @@ -104,6 +109,8 @@ #define to_keystone_pcie(x) dev_get_drvdata((x)->dev) +#define PCI_DEVICE_ID_TI_AM654X 0xb00c + struct ks_pcie_of_data { enum dw_pcie_device_mode mode; const struct dw_pcie_host_ops *host_ops; @@ -245,8 +252,68 @@ static struct irq_chip ks_pcie_msi_irq_chip = { .irq_unmask = ks_pcie_msi_unmask, }; +/** + * ks_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask registers + * @ks_pcie: A pointer to the keystone_pcie structure which holds the KeyStone + * PCIe host controller driver information. + * + * Since modification of dbi_cs2 involves different clock domain, read the + * status back to ensure the transition is complete. + */ +static void ks_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie) +{ + u32 val; + + val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); + val |= DBI_CS2; + ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); + + do { + val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); + } while (!(val & DBI_CS2)); +} + +/** + * ks_pcie_clear_dbi_mode() - Disable DBI mode + * @ks_pcie: A pointer to the keystone_pcie structure which holds the KeyStone + * PCIe host controller driver information. + * + * Since modification of dbi_cs2 involves different clock domain, read the + * status back to ensure the transition is complete. + */ +static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie) +{ + u32 val; + + val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); + val &= ~DBI_CS2; + ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); + + do { + val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); + } while (val & DBI_CS2); +} + static int ks_pcie_msi_host_init(struct dw_pcie_rp *pp) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); + + /* Configure and set up BAR0 */ + ks_pcie_set_dbi_mode(ks_pcie); + + /* Enable BAR0 */ + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1); + + ks_pcie_clear_dbi_mode(ks_pcie); + + /* + * For BAR0, just setting bus address for inbound writes (MSI) should + * be sufficient. Use physical address to avoid any conflicts. + */ + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start); + pp->msi_irq_chip = &ks_pcie_msi_irq_chip; return dw_pcie_allocate_domains(pp); } @@ -340,59 +407,22 @@ static const struct irq_domain_ops ks_pcie_intx_irq_domain_ops = { .xlate = irq_domain_xlate_onetwocell, }; -/** - * ks_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask registers - * @ks_pcie: A pointer to the keystone_pcie structure which holds the KeyStone - * PCIe host controller driver information. - * - * Since modification of dbi_cs2 involves different clock domain, read the - * status back to ensure the transition is complete. - */ -static void ks_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie) -{ - u32 val; - - val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); - val |= DBI_CS2; - ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); - - do { - val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); - } while (!(val & DBI_CS2)); -} - -/** - * ks_pcie_clear_dbi_mode() - Disable DBI mode - * @ks_pcie: A pointer to the keystone_pcie structure which holds the KeyStone - * PCIe host controller driver information. - * - * Since modification of dbi_cs2 involves different clock domain, read the - * status back to ensure the transition is complete. - */ -static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie) -{ - u32 val; - - val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); - val &= ~DBI_CS2; - ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); - - do { - val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); - } while (val & DBI_CS2); -} - -static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) +static int ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) { u32 val; u32 num_viewport = ks_pcie->num_viewport; struct dw_pcie *pci = ks_pcie->pci; struct dw_pcie_rp *pp = &pci->pp; - u64 start, end; + struct resource_entry *entry; struct resource *mem; + u64 start, end; int i; - mem = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM)->res; + entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM); + if (!entry) + return -ENODEV; + + mem = entry->res; start = mem->start; end = mem->end; @@ -403,7 +433,7 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) ks_pcie_clear_dbi_mode(ks_pcie); if (ks_pcie->is_am6) - return; + return 0; val = ilog2(OB_WIN_SIZE); ks_pcie_app_writel(ks_pcie, OB_SIZE, val); @@ -420,6 +450,8 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); val |= OB_XLAT_EN_VAL; ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); + + return 0; } static void __iomem *ks_pcie_other_map_bus(struct pci_bus *bus, @@ -445,44 +477,10 @@ static struct pci_ops ks_child_pcie_ops = { .write = pci_generic_config_write, }; -/** - * ks_pcie_v3_65_add_bus() - keystone add_bus post initialization - * @bus: A pointer to the PCI bus structure. - * - * This sets BAR0 to enable inbound access for MSI_IRQ register - */ -static int ks_pcie_v3_65_add_bus(struct pci_bus *bus) -{ - struct dw_pcie_rp *pp = bus->sysdata; - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); - - if (!pci_is_root_bus(bus)) - return 0; - - /* Configure and set up BAR0 */ - ks_pcie_set_dbi_mode(ks_pcie); - - /* Enable BAR0 */ - dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1); - dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1); - - ks_pcie_clear_dbi_mode(ks_pcie); - - /* - * For BAR0, just setting bus address for inbound writes (MSI) should - * be sufficient. Use physical address to avoid any conflicts. - */ - dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start); - - return 0; -} - static struct pci_ops ks_pcie_ops = { .map_bus = dw_pcie_own_conf_map_bus, .read = pci_generic_config_read, .write = pci_generic_config_write, - .add_bus = ks_pcie_v3_65_add_bus, }; /** @@ -525,7 +523,11 @@ static int ks_pcie_start_link(struct dw_pcie *pci) static void ks_pcie_quirk(struct pci_dev *dev) { struct pci_bus *bus = dev->bus; + struct keystone_pcie *ks_pcie; + struct device *bridge_dev; struct pci_dev *bridge; + u32 val; + static const struct pci_device_id rc_pci_devids[] = { { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK), .class = PCI_CLASS_BRIDGE_PCI_NORMAL, .class_mask = ~0, }, @@ -537,6 +539,11 @@ static void ks_pcie_quirk(struct pci_dev *dev) .class = PCI_CLASS_BRIDGE_PCI_NORMAL, .class_mask = ~0, }, { 0, }, }; + static const struct pci_device_id am6_pci_devids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654X), + .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, }, + { 0, }, + }; if (pci_is_root_bus(bus)) bridge = dev; @@ -558,10 +565,36 @@ static void ks_pcie_quirk(struct pci_dev *dev) */ if (pci_match_id(rc_pci_devids, bridge)) { if (pcie_get_readrq(dev) > 256) { - dev_info(&dev->dev, "limiting MRRS to 256\n"); + dev_info(&dev->dev, "limiting MRRS to 256 bytes\n"); pcie_set_readrq(dev, 256); } } + + /* + * Memory transactions fail with PCI controller in AM654 PG1.0 + * when MRRS is set to more than 128 bytes. Force the MRRS to + * 128 bytes in all downstream devices. + */ + if (pci_match_id(am6_pci_devids, bridge)) { + bridge_dev = pci_get_host_bridge_device(dev); + if (!bridge_dev && !bridge_dev->parent) + return; + + ks_pcie = dev_get_drvdata(bridge_dev->parent); + if (!ks_pcie) + return; + + val = ks_pcie_app_readl(ks_pcie, PID); + val &= RTL; + val >>= RTL_SHIFT; + if (val != AM6_PCI_PG1_RTL_VER) + return; + + if (pcie_get_readrq(dev) > 128) { + dev_info(&dev->dev, "limiting MRRS to 128 bytes\n"); + pcie_set_readrq(dev, 128); + } + } } DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk); @@ -814,7 +847,10 @@ static int __init ks_pcie_host_init(struct dw_pcie_rp *pp) return ret; ks_pcie_stop_link(pci); - ks_pcie_setup_rc_app_regs(ks_pcie); + ret = ks_pcie_setup_rc_app_regs(ks_pcie); + if (ret) + return ret; + writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8), pci->dbi_base + PCI_IO_BASE); @@ -1293,7 +1329,7 @@ static int ks_pcie_probe(struct platform_device *pdev) goto err_ep_init; } - dw_pcie_ep_init_notify(&pci->ep); + pci_epc_init_notify(pci->ep.epc); break; default: diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index 7dde6d5fa4d8..a4a800699f89 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -104,7 +104,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id) dev_dbg(pci->dev, "Link up\n"); } else if (val & PEX_PF0_PME_MES_DR_LDD) { dev_dbg(pci->dev, "Link down\n"); - pci_epc_linkdown(pci->ep.epc); + dw_pcie_ep_linkdown(&pci->ep); } else if (val & PEX_PF0_PME_MES_DR_HRD) { dev_dbg(pci->dev, "Hot reset\n"); } @@ -286,7 +286,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) return ret; } - dw_pcie_ep_init_notify(&pci->ep); + pci_epc_init_notify(pci->ep.epc); return ls_pcie_ep_interrupt_init(pcie, pdev); } diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 6477c83262c2..db9482a113e9 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/dwc/pcie-al.c index 6dfdda59f328..643115f74092 100644 --- a/drivers/pci/controller/dwc/pcie-al.c +++ b/drivers/pci/controller/dwc/pcie-al.c @@ -242,18 +242,24 @@ static struct pci_ops al_child_pci_ops = { .write = pci_generic_config_write, }; -static void al_pcie_config_prepare(struct al_pcie *pcie) +static int al_pcie_config_prepare(struct al_pcie *pcie) { struct al_pcie_target_bus_cfg *target_bus_cfg; struct dw_pcie_rp *pp = &pcie->pci->pp; unsigned int ecam_bus_mask; + struct resource_entry *ft; u32 cfg_control_offset; + struct resource *bus; u8 subordinate_bus; u8 secondary_bus; u32 cfg_control; u32 reg; - struct resource *bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS)->res; + ft = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS); + if (!ft) + return -ENODEV; + + bus = ft->res; target_bus_cfg = &pcie->target_bus_cfg; ecam_bus_mask = (pcie->ecam_size >> PCIE_ECAM_BUS_SHIFT) - 1; @@ -287,6 +293,8 @@ static void al_pcie_config_prepare(struct al_pcie *pcie) FIELD_PREP(CFG_CONTROL_SEC_BUS_MASK, secondary_bus); al_pcie_controller_writel(pcie, cfg_control_offset, reg); + + return 0; } static int al_pcie_host_init(struct dw_pcie_rp *pp) @@ -305,7 +313,9 @@ static int al_pcie_host_init(struct dw_pcie_rp *pp) if (rc) return rc; - al_pcie_config_prepare(pcie); + rc = al_pcie_config_prepare(pcie); + if (rc) + return rc; return 0; } diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c index a4630b92489b..f8e7283dacd4 100644 --- a/drivers/pci/controller/dwc/pcie-artpec6.c +++ b/drivers/pci/controller/dwc/pcie-artpec6.c @@ -94,7 +94,7 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u regmap_write(artpec6_pcie->regmap, offset, val); } -static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) +static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr) { struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); struct dw_pcie_rp *pp = &pci->pp; @@ -102,13 +102,13 @@ static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) switch (artpec6_pcie->mode) { case DW_PCIE_RC_TYPE: - return pci_addr - pp->cfg0_base; + return cpu_addr - pp->cfg0_base; case DW_PCIE_EP_TYPE: - return pci_addr - ep->phys_base; + return cpu_addr - ep->phys_base; default: dev_err(pci->dev, "UNKNOWN device type\n"); } - return pci_addr; + return cpu_addr; } static int artpec6_pcie_establish_link(struct dw_pcie *pci) @@ -452,7 +452,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev) return ret; } - dw_pcie_ep_init_notify(&pci->ep); + pci_epc_init_notify(pci->ep.epc); break; default: diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 47391d7d3a73..43ba5c6738df 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -15,30 +15,6 @@ #include #include -/** - * dw_pcie_ep_linkup - Notify EPF drivers about Link Up event - * @ep: DWC EP device - */ -void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) -{ - struct pci_epc *epc = ep->epc; - - pci_epc_linkup(epc); -} -EXPORT_SYMBOL_GPL(dw_pcie_ep_linkup); - -/** - * dw_pcie_ep_init_notify - Notify EPF drivers about EPC initialization complete - * @ep: DWC EP device - */ -void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep) -{ - struct pci_epc *epc = ep->epc; - - pci_epc_init_notify(epc); -} -EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify); - /** * dw_pcie_ep_get_func_from_ep - Get the struct dw_pcie_ep_func corresponding to * the endpoint function @@ -161,7 +137,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type, if (!ep->bar_to_atu[bar]) free_win = find_first_zero_bit(ep->ib_window_map, pci->num_ib_windows); else - free_win = ep->bar_to_atu[bar]; + free_win = ep->bar_to_atu[bar] - 1; if (free_win >= pci->num_ib_windows) { dev_err(pci->dev, "No free inbound window\n"); @@ -175,15 +151,18 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type, return ret; } - ep->bar_to_atu[bar] = free_win; + /* + * Always increment free_win before assignment, since value 0 is used to identify + * unallocated mapping. + */ + ep->bar_to_atu[bar] = free_win + 1; set_bit(free_win, ep->ib_window_map); return 0; } -static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no, - phys_addr_t phys_addr, - u64 pci_addr, size_t size) +static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, + struct dw_pcie_ob_atu_cfg *atu) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); u32 free_win; @@ -195,13 +174,13 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no, return -EINVAL; } - ret = dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM, - phys_addr, pci_addr, size); + atu->index = free_win; + ret = dw_pcie_prog_outbound_atu(pci, atu); if (ret) return ret; set_bit(free_win, ep->ob_window_map); - ep->outbound_addr[free_win] = phys_addr; + ep->outbound_addr[free_win] = atu->cpu_addr; return 0; } @@ -212,7 +191,10 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); enum pci_barno bar = epf_bar->barno; - u32 atu_index = ep->bar_to_atu[bar]; + u32 atu_index = ep->bar_to_atu[bar] - 1; + + if (!ep->bar_to_atu[bar]) + return; __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags); @@ -233,6 +215,13 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int ret, type; u32 reg; + /* + * DWC does not allow BAR pairs to overlap, e.g. you cannot combine BARs + * 1 and 2 to form a 64-bit BAR. + */ + if ((flags & PCI_BASE_ADDRESS_MEM_TYPE_64) && (bar & 1)) + return -EINVAL; + reg = PCI_BASE_ADDRESS_0 + (4 * bar); if (!(flags & PCI_BASE_ADDRESS_SPACE)) @@ -301,8 +290,14 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int ret; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct dw_pcie_ob_atu_cfg atu = { 0 }; - ret = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size); + atu.func_no = func_no; + atu.type = PCIE_ATU_TYPE_MEM; + atu.cpu_addr = addr; + atu.pci_addr = pci_addr; + atu.size = size; + ret = dw_pcie_ep_outbound_atu(ep, &atu); if (ret) { dev_err(pci->dev, "Failed to enable address\n"); return ret; @@ -632,7 +627,6 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep) struct dw_pcie *pci = to_dw_pcie_from_ep(ep); dw_pcie_edma_remove(pci); - ep->epc->init_complete = false; } EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup); @@ -674,6 +668,34 @@ static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap) return 0; } +static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci) +{ + unsigned int offset; + unsigned int nbars; + u32 reg, i; + + offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); + + dw_pcie_dbi_ro_wr_en(pci); + + if (offset) { + reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); + nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> + PCI_REBAR_CTRL_NBAR_SHIFT; + + /* + * PCIe r6.0, sec 7.8.6.2 require us to support at least one + * size in the range from 1 MB to 512 GB. Advertise support + * for 1 MB BAR size only. + */ + for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) + dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0); + } + + dw_pcie_setup(pci); + dw_pcie_dbi_ro_wr_dis(pci); +} + /** * dw_pcie_ep_init_registers - Initialize DWC EP specific registers * @ep: DWC EP device @@ -688,13 +710,11 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep) struct dw_pcie_ep_func *ep_func; struct device *dev = pci->dev; struct pci_epc *epc = ep->epc; - unsigned int offset, ptm_cap_base; - unsigned int nbars; + u32 ptm_cap_base, reg; u8 hdr_type; u8 func_no; - int i, ret; void *addr; - u32 reg; + int ret; hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) & PCI_HEADER_TYPE_MASK; @@ -757,25 +777,8 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep) if (ep->ops->init) ep->ops->init(ep); - offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); ptm_cap_base = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM); - dw_pcie_dbi_ro_wr_en(pci); - - if (offset) { - reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); - nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> - PCI_REBAR_CTRL_NBAR_SHIFT; - - /* - * PCIe r6.0, sec 7.8.6.2 require us to support at least one - * size in the range from 1 MB to 512 GB. Advertise support - * for 1 MB BAR size only. - */ - for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) - dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, BIT(4)); - } - /* * PTM responder capability can be disabled only after disabling * PTM root capability. @@ -792,8 +795,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep) dw_pcie_dbi_ro_wr_dis(pci); } - dw_pcie_setup(pci); - dw_pcie_dbi_ro_wr_dis(pci); + dw_pcie_ep_init_non_sticky_registers(pci); return 0; @@ -804,6 +806,43 @@ err_remove_edma: } EXPORT_SYMBOL_GPL(dw_pcie_ep_init_registers); +/** + * dw_pcie_ep_linkup - Notify EPF drivers about Link Up event + * @ep: DWC EP device + */ +void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) +{ + struct pci_epc *epc = ep->epc; + + pci_epc_linkup(epc); +} +EXPORT_SYMBOL_GPL(dw_pcie_ep_linkup); + +/** + * dw_pcie_ep_linkdown - Notify EPF drivers about Link Down event + * @ep: DWC EP device + * + * Non-sticky registers are also initialized before sending the notification to + * the EPF drivers. This is needed since the registers need to be initialized + * before the link comes back again. + */ +void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct pci_epc *epc = ep->epc; + + /* + * Initialize the non-sticky DWC registers as they would've reset post + * Link Down. This is specifically needed for drivers not supporting + * PERST# as they have no way to reinitialize the registers before the + * link comes back again. + */ + dw_pcie_ep_init_non_sticky_registers(pci); + + pci_epc_linkdown(epc); +} +EXPORT_SYMBOL_GPL(dw_pcie_ep_linkdown); + /** * dw_pcie_ep_init - Initialize the endpoint device * @ep: DWC EP device diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index d4fb5f54acf1..8a1ff5c913d8 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -399,6 +399,32 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp) return 0; } +static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp) +{ + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct resource_entry *win; + struct resource *res; + + win = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM); + if (win) { + res = devm_kzalloc(pci->dev, sizeof(*res), GFP_KERNEL); + if (!res) + return; + + /* + * Allocate MSG TLP region of size 'region_align' at the end of + * the host bridge window. + */ + res->start = win->res->end - pci->region_align + 1; + res->end = win->res->end; + res->name = "msg"; + res->flags = win->res->flags | IORESOURCE_BUSY; + + if (!devm_request_resource(pci->dev, win->res, res)) + pp->msg_res = res; + } +} + int dw_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -485,6 +511,18 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) dw_pcie_iatu_detect(pci); + /* + * Allocate the resource for MSG TLP before programming the iATU + * outbound window in dw_pcie_setup_rc(). Since the allocation depends + * on the value of 'region_align', this has to be done after + * dw_pcie_iatu_detect(). + * + * Glue drivers need to set 'use_atu_msg' before dw_pcie_host_init() to + * make use of the generic MSG TLP implementation. + */ + if (pp->use_atu_msg) + dw_pcie_host_request_msg_tlp_res(pp); + ret = dw_pcie_edma_detect(pci); if (ret) goto err_free_msi; @@ -555,6 +593,7 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus, { struct dw_pcie_rp *pp = bus->sysdata; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct dw_pcie_ob_atu_cfg atu = { 0 }; int type, ret; u32 busdev; @@ -577,8 +616,12 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus, else type = PCIE_ATU_TYPE_CFG1; - ret = dw_pcie_prog_outbound_atu(pci, 0, type, pp->cfg0_base, busdev, - pp->cfg0_size); + atu.type = type; + atu.cpu_addr = pp->cfg0_base; + atu.pci_addr = busdev; + atu.size = pp->cfg0_size; + + ret = dw_pcie_prog_outbound_atu(pci, &atu); if (ret) return NULL; @@ -590,6 +633,7 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn, { struct dw_pcie_rp *pp = bus->sysdata; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct dw_pcie_ob_atu_cfg atu = { 0 }; int ret; ret = pci_generic_config_read(bus, devfn, where, size, val); @@ -597,9 +641,12 @@ static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn, return ret; if (pp->cfg0_io_shared) { - ret = dw_pcie_prog_outbound_atu(pci, 0, PCIE_ATU_TYPE_IO, - pp->io_base, pp->io_bus_addr, - pp->io_size); + atu.type = PCIE_ATU_TYPE_IO; + atu.cpu_addr = pp->io_base; + atu.pci_addr = pp->io_bus_addr; + atu.size = pp->io_size; + + ret = dw_pcie_prog_outbound_atu(pci, &atu); if (ret) return PCIBIOS_SET_FAILED; } @@ -612,6 +659,7 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn, { struct dw_pcie_rp *pp = bus->sysdata; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct dw_pcie_ob_atu_cfg atu = { 0 }; int ret; ret = pci_generic_config_write(bus, devfn, where, size, val); @@ -619,9 +667,12 @@ static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn, return ret; if (pp->cfg0_io_shared) { - ret = dw_pcie_prog_outbound_atu(pci, 0, PCIE_ATU_TYPE_IO, - pp->io_base, pp->io_bus_addr, - pp->io_size); + atu.type = PCIE_ATU_TYPE_IO; + atu.cpu_addr = pp->io_base; + atu.pci_addr = pp->io_bus_addr; + atu.size = pp->io_size; + + ret = dw_pcie_prog_outbound_atu(pci, &atu); if (ret) return PCIBIOS_SET_FAILED; } @@ -656,6 +707,7 @@ static struct pci_ops dw_pcie_ops = { static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct dw_pcie_ob_atu_cfg atu = { 0 }; struct resource_entry *entry; int i, ret; @@ -683,10 +735,19 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) if (pci->num_ob_windows <= ++i) break; - ret = dw_pcie_prog_outbound_atu(pci, i, PCIE_ATU_TYPE_MEM, - entry->res->start, - entry->res->start - entry->offset, - resource_size(entry->res)); + atu.index = i; + atu.type = PCIE_ATU_TYPE_MEM; + atu.cpu_addr = entry->res->start; + atu.pci_addr = entry->res->start - entry->offset; + + /* Adjust iATU size if MSG TLP region was allocated before */ + if (pp->msg_res && pp->msg_res->parent == entry->res) + atu.size = resource_size(entry->res) - + resource_size(pp->msg_res); + else + atu.size = resource_size(entry->res); + + ret = dw_pcie_prog_outbound_atu(pci, &atu); if (ret) { dev_err(pci->dev, "Failed to set MEM range %pr\n", entry->res); @@ -696,10 +757,13 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) if (pp->io_size) { if (pci->num_ob_windows > ++i) { - ret = dw_pcie_prog_outbound_atu(pci, i, PCIE_ATU_TYPE_IO, - pp->io_base, - pp->io_bus_addr, - pp->io_size); + atu.index = i; + atu.type = PCIE_ATU_TYPE_IO; + atu.cpu_addr = pp->io_base; + atu.pci_addr = pp->io_bus_addr; + atu.size = pp->io_size; + + ret = dw_pcie_prog_outbound_atu(pci, &atu); if (ret) { dev_err(pci->dev, "Failed to set IO range %pr\n", entry->res); @@ -714,6 +778,8 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) dev_warn(pci->dev, "Ranges exceed outbound iATU size (%d)\n", pci->num_ob_windows); + pp->msg_atu_index = i; + i = 0; resource_list_for_each_entry(entry, &pp->bridge->dma_ranges) { if (resource_type(entry->res) != IORESOURCE_MEM) @@ -819,11 +885,47 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp) } EXPORT_SYMBOL_GPL(dw_pcie_setup_rc); +static int dw_pcie_pme_turn_off(struct dw_pcie *pci) +{ + struct dw_pcie_ob_atu_cfg atu = { 0 }; + void __iomem *mem; + int ret; + + if (pci->num_ob_windows <= pci->pp.msg_atu_index) + return -ENOSPC; + + if (!pci->pp.msg_res) + return -ENOSPC; + + atu.code = PCIE_MSG_CODE_PME_TURN_OFF; + atu.routing = PCIE_MSG_TYPE_R_BC; + atu.type = PCIE_ATU_TYPE_MSG; + atu.size = resource_size(pci->pp.msg_res); + atu.index = pci->pp.msg_atu_index; + + atu.cpu_addr = pci->pp.msg_res->start; + + ret = dw_pcie_prog_outbound_atu(pci, &atu); + if (ret) + return ret; + + mem = ioremap(atu.cpu_addr, pci->region_align); + if (!mem) + return -ENOMEM; + + /* A dummy write is converted to a Msg TLP */ + writel(0, mem); + + iounmap(mem); + + return 0; +} + int dw_pcie_suspend_noirq(struct dw_pcie *pci) { u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); u32 val; - int ret; + int ret = 0; /* * If L1SS is supported, then do not put the link into L2 as some @@ -835,10 +937,13 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci) if (dw_pcie_get_ltssm(pci) <= DW_PCIE_LTSSM_DETECT_ACT) return 0; - if (!pci->pp.ops->pme_turn_off) - return 0; + if (pci->pp.ops->pme_turn_off) + pci->pp.ops->pme_turn_off(&pci->pp); + else + ret = dw_pcie_pme_turn_off(pci); - pci->pp.ops->pme_turn_off(&pci->pp); + if (ret) + return ret; ret = read_poll_timeout(dw_pcie_get_ltssm, val, val == DW_PCIE_LTSSM_L2_IDLE, PCIE_PME_TO_L2_TIMEOUT_US/10, diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c index 8490c5d6ff9f..771b9d9be077 100644 --- a/drivers/pci/controller/dwc/pcie-designware-plat.c +++ b/drivers/pci/controller/dwc/pcie-designware-plat.c @@ -154,7 +154,7 @@ static int dw_plat_pcie_probe(struct platform_device *pdev) dw_pcie_ep_deinit(&pci->ep); } - dw_pcie_ep_init_notify(&pci->ep); + pci_epc_init_notify(pci->ep.epc); break; default: diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 250cf7f40b85..1b5aba1f0c92 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -465,56 +465,61 @@ static inline u32 dw_pcie_enable_ecrc(u32 val) return val | PCIE_ATU_TD; } -static int __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, - int index, int type, u64 cpu_addr, - u64 pci_addr, u64 size) +int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, + const struct dw_pcie_ob_atu_cfg *atu) { + u64 cpu_addr = atu->cpu_addr; u32 retries, val; u64 limit_addr; if (pci->ops && pci->ops->cpu_addr_fixup) cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr); - limit_addr = cpu_addr + size - 1; + limit_addr = cpu_addr + atu->size - 1; if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) || !IS_ALIGNED(cpu_addr, pci->region_align) || - !IS_ALIGNED(pci_addr, pci->region_align) || !size) { + !IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) { return -EINVAL; } - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LOWER_BASE, + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_BASE, lower_32_bits(cpu_addr)); - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_BASE, + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_BASE, upper_32_bits(cpu_addr)); - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LIMIT, + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LIMIT, lower_32_bits(limit_addr)); if (dw_pcie_ver_is_ge(pci, 460A)) - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_LIMIT, + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_LIMIT, upper_32_bits(limit_addr)); - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LOWER_TARGET, - lower_32_bits(pci_addr)); - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_TARGET, - upper_32_bits(pci_addr)); + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_TARGET, + lower_32_bits(atu->pci_addr)); + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_TARGET, + upper_32_bits(atu->pci_addr)); - val = type | PCIE_ATU_FUNC_NUM(func_no); + val = atu->type | atu->routing | PCIE_ATU_FUNC_NUM(atu->func_no); if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) && dw_pcie_ver_is_ge(pci, 460A)) val |= PCIE_ATU_INCREASE_REGION_SIZE; if (dw_pcie_ver_is(pci, 490A)) val = dw_pcie_enable_ecrc(val); - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_REGION_CTRL1, val); + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL1, val); - dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_REGION_CTRL2, PCIE_ATU_ENABLE); + val = PCIE_ATU_ENABLE; + if (atu->type == PCIE_ATU_TYPE_MSG) { + /* The data-less messages only for now */ + val |= PCIE_ATU_INHIBIT_PAYLOAD | atu->code; + } + dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL2, val); /* * Make sure ATU enable takes effect before any subsequent config * and I/O accesses. */ for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { - val = dw_pcie_readl_atu_ob(pci, index, PCIE_ATU_REGION_CTRL2); + val = dw_pcie_readl_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL2); if (val & PCIE_ATU_ENABLE) return 0; @@ -526,21 +531,6 @@ static int __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, return -ETIMEDOUT; } -int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, - u64 cpu_addr, u64 pci_addr, u64 size) -{ - return __dw_pcie_prog_outbound_atu(pci, 0, index, type, - cpu_addr, pci_addr, size); -} - -int dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, - int type, u64 cpu_addr, u64 pci_addr, - u64 size) -{ - return __dw_pcie_prog_outbound_atu(pci, func_no, index, type, - cpu_addr, pci_addr, size); -} - static inline u32 dw_pcie_readl_atu_ib(struct dw_pcie *pci, u32 index, u32 reg) { return dw_pcie_readl_atu(pci, PCIE_ATU_REGION_DIR_IB, index, reg); @@ -655,7 +645,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) if (dw_pcie_link_up(pci)) break; - usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); + msleep(LINK_WAIT_SLEEP_MS); } if (retries >= LINK_WAIT_MAX_RETRIES) { @@ -880,30 +870,40 @@ static struct dw_edma_plat_ops dw_pcie_edma_ops = { .irq_vector = dw_pcie_edma_irq_vector, }; -static int dw_pcie_edma_find_chip(struct dw_pcie *pci) +static void dw_pcie_edma_init_data(struct dw_pcie *pci) +{ + pci->edma.dev = pci->dev; + + if (!pci->edma.ops) + pci->edma.ops = &dw_pcie_edma_ops; + + pci->edma.flags |= DW_EDMA_CHIP_LOCAL; +} + +static int dw_pcie_edma_find_mf(struct dw_pcie *pci) { u32 val; + /* + * Bail out finding the mapping format if it is already set by the glue + * driver. Also ensure that the edma.reg_base is pointing to a valid + * memory region. + */ + if (pci->edma.mf != EDMA_MF_EDMA_LEGACY) + return pci->edma.reg_base ? 0 : -ENODEV; + /* * Indirect eDMA CSRs access has been completely removed since v5.40a * thus no space is now reserved for the eDMA channels viewport and * former DMA CTRL register is no longer fixed to FFs. - * - * Note that Renesas R-Car S4-8's PCIe controllers for unknown reason - * have zeros in the eDMA CTRL register even though the HW-manual - * explicitly states there must FFs if the unrolled mapping is enabled. - * For such cases the low-level drivers are supposed to manually - * activate the unrolled mapping to bypass the auto-detection procedure. */ - if (dw_pcie_ver_is_ge(pci, 540A) || dw_pcie_cap_is(pci, EDMA_UNROLL)) + if (dw_pcie_ver_is_ge(pci, 540A)) val = 0xFFFFFFFF; else val = dw_pcie_readl_dbi(pci, PCIE_DMA_VIEWPORT_BASE + PCIE_DMA_CTRL); if (val == 0xFFFFFFFF && pci->edma.reg_base) { pci->edma.mf = EDMA_MF_EDMA_UNROLL; - - val = dw_pcie_readl_dma(pci, PCIE_DMA_CTRL); } else if (val != 0xFFFFFFFF) { pci->edma.mf = EDMA_MF_EDMA_LEGACY; @@ -912,15 +912,25 @@ static int dw_pcie_edma_find_chip(struct dw_pcie *pci) return -ENODEV; } - pci->edma.dev = pci->dev; + return 0; +} - if (!pci->edma.ops) - pci->edma.ops = &dw_pcie_edma_ops; +static int dw_pcie_edma_find_channels(struct dw_pcie *pci) +{ + u32 val; - pci->edma.flags |= DW_EDMA_CHIP_LOCAL; + /* + * Autodetect the read/write channels count only for non-HDMA platforms. + * HDMA platforms with native CSR mapping doesn't support autodetect, + * so the glue drivers should've passed the valid count already. If not, + * the below sanity check will catch it. + */ + if (pci->edma.mf != EDMA_MF_HDMA_NATIVE) { + val = dw_pcie_readl_dma(pci, PCIE_DMA_CTRL); - pci->edma.ll_wr_cnt = FIELD_GET(PCIE_DMA_NUM_WR_CHAN, val); - pci->edma.ll_rd_cnt = FIELD_GET(PCIE_DMA_NUM_RD_CHAN, val); + pci->edma.ll_wr_cnt = FIELD_GET(PCIE_DMA_NUM_WR_CHAN, val); + pci->edma.ll_rd_cnt = FIELD_GET(PCIE_DMA_NUM_RD_CHAN, val); + } /* Sanity check the channels count if the mapping was incorrect */ if (!pci->edma.ll_wr_cnt || pci->edma.ll_wr_cnt > EDMA_MAX_WR_CH || @@ -930,6 +940,19 @@ static int dw_pcie_edma_find_chip(struct dw_pcie *pci) return 0; } +static int dw_pcie_edma_find_chip(struct dw_pcie *pci) +{ + int ret; + + dw_pcie_edma_init_data(pci); + + ret = dw_pcie_edma_find_mf(pci); + if (ret) + return ret; + + return dw_pcie_edma_find_channels(pci); +} + static int dw_pcie_edma_irq_verify(struct dw_pcie *pci) { struct platform_device *pdev = to_platform_device(pci->dev); diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index f8e5431a207b..53c4c8f399c8 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -51,9 +51,8 @@ /* DWC PCIe controller capabilities */ #define DW_PCIE_CAP_REQ_RES 0 -#define DW_PCIE_CAP_EDMA_UNROLL 1 -#define DW_PCIE_CAP_IATU_UNROLL 2 -#define DW_PCIE_CAP_CDM_CHECK 3 +#define DW_PCIE_CAP_IATU_UNROLL 1 +#define DW_PCIE_CAP_CDM_CHECK 2 #define dw_pcie_cap_is(_pci, _cap) \ test_bit(DW_PCIE_CAP_ ## _cap, &(_pci)->caps) @@ -63,14 +62,16 @@ /* Parameters for the waiting for link up routine */ #define LINK_WAIT_MAX_RETRIES 10 -#define LINK_WAIT_USLEEP_MIN 90000 -#define LINK_WAIT_USLEEP_MAX 100000 +#define LINK_WAIT_SLEEP_MS 90 /* Parameters for the waiting for iATU enabled routine */ #define LINK_WAIT_MAX_IATU_RETRIES 5 #define LINK_WAIT_IATU 9 /* Synopsys-specific PCIe configuration registers */ +#define PCIE_PORT_FORCE 0x708 +#define PORT_FORCE_DO_DESKEW_FOR_SRIS BIT(23) + #define PCIE_PORT_AFR 0x70C #define PORT_AFR_N_FTS_MASK GENMASK(15, 8) #define PORT_AFR_N_FTS(n) FIELD_PREP(PORT_AFR_N_FTS_MASK, n) @@ -92,6 +93,9 @@ #define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7) #define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf) +#define PCIE_PORT_LANE_SKEW 0x714 +#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0) + #define PCIE_PORT_DEBUG0 0x728 #define PORT_LOGIC_LTSSM_STATE_MASK 0x1f #define PORT_LOGIC_LTSSM_STATE_L0 0x11 @@ -148,11 +152,13 @@ #define PCIE_ATU_TYPE_IO 0x2 #define PCIE_ATU_TYPE_CFG0 0x4 #define PCIE_ATU_TYPE_CFG1 0x5 +#define PCIE_ATU_TYPE_MSG 0x10 #define PCIE_ATU_TD BIT(8) #define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20) #define PCIE_ATU_REGION_CTRL2 0x004 #define PCIE_ATU_ENABLE BIT(31) #define PCIE_ATU_BAR_MODE_ENABLE BIT(30) +#define PCIE_ATU_INHIBIT_PAYLOAD BIT(22) #define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19) #define PCIE_ATU_LOWER_BASE 0x008 #define PCIE_ATU_UPPER_BASE 0x00C @@ -299,6 +305,17 @@ enum dw_pcie_ltssm { DW_PCIE_LTSSM_UNKNOWN = 0xFFFFFFFF, }; +struct dw_pcie_ob_atu_cfg { + int index; + int type; + u8 func_no; + u8 code; + u8 routing; + u64 cpu_addr; + u64 pci_addr; + u64 size; +}; + struct dw_pcie_host_ops { int (*init)(struct dw_pcie_rp *pp); void (*deinit)(struct dw_pcie_rp *pp); @@ -328,6 +345,9 @@ struct dw_pcie_rp { struct pci_host_bridge *bridge; raw_spinlock_t lock; DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); + bool use_atu_msg; + int msg_atu_index; + struct resource *msg_res; }; struct dw_pcie_ep_ops { @@ -433,10 +453,8 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val); int dw_pcie_link_up(struct dw_pcie *pci); void dw_pcie_upconfig_setup(struct dw_pcie *pci); int dw_pcie_wait_for_link(struct dw_pcie *pci); -int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, - u64 cpu_addr, u64 pci_addr, u64 size); -int dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, - int type, u64 cpu_addr, u64 pci_addr, u64 size); +int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, + const struct dw_pcie_ob_atu_cfg *atu); int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type, u64 cpu_addr, u64 pci_addr, u64 size); int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, @@ -668,9 +686,9 @@ static inline void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, #ifdef CONFIG_PCIE_DW_EP void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); +void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep); int dw_pcie_ep_init(struct dw_pcie_ep *ep); int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep); -void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep); void dw_pcie_ep_deinit(struct dw_pcie_ep *ep); void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep); int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 func_no); @@ -688,6 +706,10 @@ static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) { } +static inline void dw_pcie_ep_linkdown(struct dw_pcie_ep *ep) +{ +} + static inline int dw_pcie_ep_init(struct dw_pcie_ep *ep) { return 0; @@ -698,10 +720,6 @@ static inline int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep) return 0; } -static inline void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep) -{ -} - static inline void dw_pcie_ep_deinit(struct dw_pcie_ep *ep) { } diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index d6842141d384..1170e1107508 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -34,10 +34,16 @@ #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) #define PCIE_CLIENT_RC_MODE HIWORD_UPDATE_BIT(0x40) +#define PCIE_CLIENT_EP_MODE HIWORD_UPDATE(0xf0, 0x0) #define PCIE_CLIENT_ENABLE_LTSSM HIWORD_UPDATE_BIT(0xc) +#define PCIE_CLIENT_DISABLE_LTSSM HIWORD_UPDATE(0x0c, 0x8) +#define PCIE_CLIENT_INTR_STATUS_MISC 0x10 +#define PCIE_CLIENT_INTR_MASK_MISC 0x24 #define PCIE_SMLH_LINKUP BIT(16) #define PCIE_RDLH_LINKUP BIT(17) #define PCIE_LINKUP (PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP) +#define PCIE_RDLH_LINK_UP_CHGED BIT(1) +#define PCIE_LINK_REQ_RST_NOT_INT BIT(2) #define PCIE_L0S_ENTRY 0x11 #define PCIE_CLIENT_GENERAL_CONTROL 0x0 #define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8 @@ -49,25 +55,30 @@ #define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0) struct rockchip_pcie { - struct dw_pcie pci; - void __iomem *apb_base; - struct phy *phy; - struct clk_bulk_data *clks; - unsigned int clk_cnt; - struct reset_control *rst; - struct gpio_desc *rst_gpio; - struct regulator *vpcie3v3; - struct irq_domain *irq_domain; + struct dw_pcie pci; + void __iomem *apb_base; + struct phy *phy; + struct clk_bulk_data *clks; + unsigned int clk_cnt; + struct reset_control *rst; + struct gpio_desc *rst_gpio; + struct regulator *vpcie3v3; + struct irq_domain *irq_domain; + const struct rockchip_pcie_of_data *data; }; -static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, - u32 reg) +struct rockchip_pcie_of_data { + enum dw_pcie_device_mode mode; + const struct pci_epc_features *epc_features; +}; + +static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, u32 reg) { return readl_relaxed(rockchip->apb_base + reg); } -static void rockchip_pcie_writel_apb(struct rockchip_pcie *rockchip, - u32 val, u32 reg) +static void rockchip_pcie_writel_apb(struct rockchip_pcie *rockchip, u32 val, + u32 reg) { writel_relaxed(val, rockchip->apb_base + reg); } @@ -144,16 +155,27 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip) return 0; } +static u32 rockchip_pcie_get_ltssm(struct rockchip_pcie *rockchip) +{ + return rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS); +} + static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip) { rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM, PCIE_CLIENT_GENERAL_CONTROL); } +static void rockchip_pcie_disable_ltssm(struct rockchip_pcie *rockchip) +{ + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DISABLE_LTSSM, + PCIE_CLIENT_GENERAL_CONTROL); +} + static int rockchip_pcie_link_up(struct dw_pcie *pci) { struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); - u32 val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS); + u32 val = rockchip_pcie_get_ltssm(rockchip); if ((val & PCIE_LINKUP) == PCIE_LINKUP && (val & PCIE_LTSSM_STATUS_MASK) == PCIE_L0S_ENTRY) @@ -186,12 +208,18 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci) return 0; } +static void rockchip_pcie_stop_link(struct dw_pcie *pci) +{ + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); + + rockchip_pcie_disable_ltssm(rockchip); +} + static int rockchip_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); struct device *dev = rockchip->pci.dev; - u32 val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); int irq, ret; irq = of_irq_get_byname(dev->of_node, "legacy"); @@ -205,12 +233,6 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp) irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler, rockchip); - /* LTSSM enable control mode */ - rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); - - rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, - PCIE_CLIENT_GENERAL_CONTROL); - return 0; } @@ -218,6 +240,82 @@ static const struct dw_pcie_host_ops rockchip_pcie_host_ops = { .init = rockchip_pcie_host_init, }; +static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + enum pci_barno bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) + dw_pcie_ep_reset_bar(pci, bar); +}; + +static int rockchip_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, + unsigned int type, u16 interrupt_num) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + + switch (type) { + case PCI_IRQ_INTX: + return dw_pcie_ep_raise_intx_irq(ep, func_no); + case PCI_IRQ_MSI: + return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); + case PCI_IRQ_MSIX: + return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num); + default: + dev_err(pci->dev, "UNKNOWN IRQ type\n"); + } + + return 0; +} + +static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = { + .linkup_notifier = true, + .msi_capable = true, + .msix_capable = true, + .align = SZ_64K, + .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, +}; + +/* + * BAR4 on rk3588 exposes the ATU Port Logic Structure to the host regardless of + * iATU settings for BAR4. This means that BAR4 cannot be used by an EPF driver, + * so mark it as RESERVED. (rockchip_pcie_ep_init() will disable all BARs by + * default.) If the host could write to BAR4, the iATU settings (for all other + * BARs) would be overwritten, resulting in (all other BARs) no longer working. + */ +static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = { + .linkup_notifier = true, + .msi_capable = true, + .msix_capable = true, + .align = SZ_64K, + .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, + .bar[BAR_4] = { .type = BAR_RESERVED, }, + .bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, +}; + +static const struct pci_epc_features * +rockchip_pcie_get_features(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); + + return rockchip->data->epc_features; +} + +static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = { + .init = rockchip_pcie_ep_init, + .raise_irq = rockchip_pcie_raise_irq, + .get_features = rockchip_pcie_get_features, +}; + static int rockchip_pcie_clk_init(struct rockchip_pcie *rockchip) { struct device *dev = rockchip->pci.dev; @@ -225,11 +323,15 @@ static int rockchip_pcie_clk_init(struct rockchip_pcie *rockchip) ret = devm_clk_bulk_get_all(dev, &rockchip->clks); if (ret < 0) - return ret; + return dev_err_probe(dev, ret, "failed to get clocks\n"); rockchip->clk_cnt = ret; - return clk_bulk_prepare_enable(rockchip->clk_cnt, rockchip->clks); + ret = clk_bulk_prepare_enable(rockchip->clk_cnt, rockchip->clks); + if (ret) + return dev_err_probe(dev, ret, "failed to enable clocks\n"); + + return 0; } static int rockchip_pcie_resource_get(struct platform_device *pdev, @@ -237,12 +339,14 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev, { rockchip->apb_base = devm_platform_ioremap_resource_byname(pdev, "apb"); if (IS_ERR(rockchip->apb_base)) - return PTR_ERR(rockchip->apb_base); + return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->apb_base), + "failed to map apb registers\n"); rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", - GPIOD_OUT_HIGH); + GPIOD_OUT_LOW); if (IS_ERR(rockchip->rst_gpio)) - return PTR_ERR(rockchip->rst_gpio); + return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst_gpio), + "failed to get reset gpio\n"); rockchip->rst = devm_reset_control_array_get_exclusive(&pdev->dev); if (IS_ERR(rockchip->rst)) @@ -282,15 +386,127 @@ static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip) static const struct dw_pcie_ops dw_pcie_ops = { .link_up = rockchip_pcie_link_up, .start_link = rockchip_pcie_start_link, + .stop_link = rockchip_pcie_stop_link, }; +static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg) +{ + struct rockchip_pcie *rockchip = arg; + struct dw_pcie *pci = &rockchip->pci; + struct device *dev = pci->dev; + u32 reg, val; + + reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); + rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); + + dev_dbg(dev, "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n", reg); + dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip)); + + if (reg & PCIE_LINK_REQ_RST_NOT_INT) { + dev_dbg(dev, "hot reset or link-down reset\n"); + dw_pcie_ep_linkdown(&pci->ep); + } + + if (reg & PCIE_RDLH_LINK_UP_CHGED) { + val = rockchip_pcie_get_ltssm(rockchip); + if ((val & PCIE_LINKUP) == PCIE_LINKUP) { + dev_dbg(dev, "link up\n"); + dw_pcie_ep_linkup(&pci->ep); + } + } + + return IRQ_HANDLED; +} + +static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip) +{ + struct dw_pcie_rp *pp; + u32 val; + + if (!IS_ENABLED(CONFIG_PCIE_ROCKCHIP_DW_HOST)) + return -ENODEV; + + /* LTSSM enable control mode */ + val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); + rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); + + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, + PCIE_CLIENT_GENERAL_CONTROL); + + pp = &rockchip->pci.pp; + pp->ops = &rockchip_pcie_host_ops; + + return dw_pcie_host_init(pp); +} + +static int rockchip_pcie_configure_ep(struct platform_device *pdev, + struct rockchip_pcie *rockchip) +{ + struct device *dev = &pdev->dev; + int irq, ret; + u32 val; + + if (!IS_ENABLED(CONFIG_PCIE_ROCKCHIP_DW_EP)) + return -ENODEV; + + irq = platform_get_irq_byname(pdev, "sys"); + if (irq < 0) { + dev_err(dev, "missing sys IRQ resource\n"); + return irq; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, + rockchip_pcie_ep_sys_irq_thread, + IRQF_ONESHOT, "pcie-sys", rockchip); + if (ret) { + dev_err(dev, "failed to request PCIe sys IRQ\n"); + return ret; + } + + /* LTSSM enable control mode */ + val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); + rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); + + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE, + PCIE_CLIENT_GENERAL_CONTROL); + + rockchip->pci.ep.ops = &rockchip_pcie_ep_ops; + rockchip->pci.ep.page_size = SZ_64K; + + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + + ret = dw_pcie_ep_init(&rockchip->pci.ep); + if (ret) { + dev_err(dev, "failed to initialize endpoint\n"); + return ret; + } + + ret = dw_pcie_ep_init_registers(&rockchip->pci.ep); + if (ret) { + dev_err(dev, "failed to initialize DWC endpoint registers\n"); + dw_pcie_ep_deinit(&rockchip->pci.ep); + return ret; + } + + pci_epc_init_notify(rockchip->pci.ep.epc); + + /* unmask DLL up/down indicator and hot reset/link-down reset */ + rockchip_pcie_writel_apb(rockchip, 0x60000, PCIE_CLIENT_INTR_MASK_MISC); + + return ret; +} + static int rockchip_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_pcie *rockchip; - struct dw_pcie_rp *pp; + const struct rockchip_pcie_of_data *data; int ret; + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); if (!rockchip) return -ENOMEM; @@ -299,9 +515,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) rockchip->pci.dev = dev; rockchip->pci.ops = &dw_pcie_ops; - - pp = &rockchip->pci.pp; - pp->ops = &rockchip_pcie_host_ops; + rockchip->data = data; ret = rockchip_pcie_resource_get(pdev, rockchip); if (ret) @@ -320,10 +534,9 @@ static int rockchip_pcie_probe(struct platform_device *pdev) rockchip->vpcie3v3 = NULL; } else { ret = regulator_enable(rockchip->vpcie3v3); - if (ret) { - dev_err(dev, "failed to enable vpcie3v3 regulator\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "failed to enable vpcie3v3 regulator\n"); } ret = rockchip_pcie_phy_init(rockchip); @@ -338,10 +551,26 @@ static int rockchip_pcie_probe(struct platform_device *pdev) if (ret) goto deinit_phy; - ret = dw_pcie_host_init(pp); - if (!ret) - return 0; + switch (data->mode) { + case DW_PCIE_RC_TYPE: + ret = rockchip_pcie_configure_rc(rockchip); + if (ret) + goto deinit_clk; + break; + case DW_PCIE_EP_TYPE: + ret = rockchip_pcie_configure_ep(pdev, rockchip); + if (ret) + goto deinit_clk; + break; + default: + dev_err(dev, "INVALID device type %d\n", data->mode); + ret = -EINVAL; + goto deinit_clk; + } + return 0; + +deinit_clk: clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks); deinit_phy: rockchip_pcie_phy_deinit(rockchip); @@ -352,8 +581,33 @@ disable_regulator: return ret; } +static const struct rockchip_pcie_of_data rockchip_pcie_rc_of_data_rk3568 = { + .mode = DW_PCIE_RC_TYPE, +}; + +static const struct rockchip_pcie_of_data rockchip_pcie_ep_of_data_rk3568 = { + .mode = DW_PCIE_EP_TYPE, + .epc_features = &rockchip_pcie_epc_features_rk3568, +}; + +static const struct rockchip_pcie_of_data rockchip_pcie_ep_of_data_rk3588 = { + .mode = DW_PCIE_EP_TYPE, + .epc_features = &rockchip_pcie_epc_features_rk3588, +}; + static const struct of_device_id rockchip_pcie_of_match[] = { - { .compatible = "rockchip,rk3568-pcie", }, + { + .compatible = "rockchip,rk3568-pcie", + .data = &rockchip_pcie_rc_of_data_rk3568, + }, + { + .compatible = "rockchip,rk3568-pcie-ep", + .data = &rockchip_pcie_ep_of_data_rk3568, + }, + { + .compatible = "rockchip,rk3588-pcie-ep", + .data = &rockchip_pcie_ep_of_data_rk3588, + }, {}, }; diff --git a/drivers/pci/controller/dwc/pcie-keembay.c b/drivers/pci/controller/dwc/pcie-keembay.c index 98bbc83182b4..278205db60a2 100644 --- a/drivers/pci/controller/dwc/pcie-keembay.c +++ b/drivers/pci/controller/dwc/pcie-keembay.c @@ -442,7 +442,7 @@ static int keembay_pcie_probe(struct platform_device *pdev) return ret; } - dw_pcie_ep_init_notify(&pci->ep); + pci_epc_init_notify(pci->ep.epc); break; default: diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c index d5523f302102..0a29136491b8 100644 --- a/drivers/pci/controller/dwc/pcie-kirin.c +++ b/drivers/pci/controller/dwc/pcie-kirin.c @@ -12,12 +12,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -78,16 +76,16 @@ struct kirin_pcie { void *phy_priv; /* only for PCIE_KIRIN_INTERNAL_PHY */ /* DWC PERST# */ - int gpio_id_dwc_perst; + struct gpio_desc *id_dwc_perst_gpio; /* Per-slot PERST# */ int num_slots; - int gpio_id_reset[MAX_PCI_SLOTS]; + struct gpio_desc *id_reset_gpio[MAX_PCI_SLOTS]; const char *reset_names[MAX_PCI_SLOTS]; /* Per-slot clkreq */ int n_gpio_clkreq; - int gpio_id_clkreq[MAX_PCI_SLOTS]; + struct gpio_desc *id_clkreq_gpio[MAX_PCI_SLOTS]; const char *clkreq_names[MAX_PCI_SLOTS]; }; @@ -381,15 +379,20 @@ static int kirin_pcie_get_gpio_enable(struct kirin_pcie *pcie, pcie->n_gpio_clkreq = ret; for (i = 0; i < pcie->n_gpio_clkreq; i++) { - pcie->gpio_id_clkreq[i] = of_get_named_gpio(dev->of_node, - "hisilicon,clken-gpios", i); - if (pcie->gpio_id_clkreq[i] < 0) - return pcie->gpio_id_clkreq[i]; + pcie->id_clkreq_gpio[i] = devm_gpiod_get_index(dev, + "hisilicon,clken", i, + GPIOD_OUT_LOW); + if (IS_ERR(pcie->id_clkreq_gpio[i])) + return dev_err_probe(dev, PTR_ERR(pcie->id_clkreq_gpio[i]), + "unable to get a valid clken gpio\n"); pcie->clkreq_names[i] = devm_kasprintf(dev, GFP_KERNEL, "pcie_clkreq_%d", i); if (!pcie->clkreq_names[i]) return -ENOMEM; + + gpiod_set_consumer_name(pcie->id_clkreq_gpio[i], + pcie->clkreq_names[i]); } return 0; @@ -400,29 +403,33 @@ static int kirin_pcie_parse_port(struct kirin_pcie *pcie, struct device_node *node) { struct device *dev = &pdev->dev; - struct device_node *parent, *child; int ret, slot, i; - for_each_available_child_of_node(node, parent) { - for_each_available_child_of_node(parent, child) { + for_each_available_child_of_node_scoped(node, parent) { + for_each_available_child_of_node_scoped(parent, child) { i = pcie->num_slots; - pcie->gpio_id_reset[i] = of_get_named_gpio(child, - "reset-gpios", 0); - if (pcie->gpio_id_reset[i] < 0) - continue; + pcie->id_reset_gpio[i] = devm_fwnode_gpiod_get_index(dev, + of_fwnode_handle(child), + "reset", 0, GPIOD_OUT_LOW, + NULL); + if (IS_ERR(pcie->id_reset_gpio[i])) { + if (PTR_ERR(pcie->id_reset_gpio[i]) == -ENOENT) + continue; + return dev_err_probe(dev, PTR_ERR(pcie->id_reset_gpio[i]), + "unable to get a valid reset gpio\n"); + } pcie->num_slots++; if (pcie->num_slots > MAX_PCI_SLOTS) { dev_err(dev, "Too many PCI slots!\n"); - ret = -EINVAL; - goto put_node; + return -EINVAL; } ret = of_pci_get_devfn(child); if (ret < 0) { dev_err(dev, "failed to parse devfn: %d\n", ret); - goto put_node; + return ret; } slot = PCI_SLOT(ret); @@ -430,19 +437,15 @@ static int kirin_pcie_parse_port(struct kirin_pcie *pcie, pcie->reset_names[i] = devm_kasprintf(dev, GFP_KERNEL, "pcie_perst_%d", slot); - if (!pcie->reset_names[i]) { - ret = -ENOMEM; - goto put_node; - } + if (!pcie->reset_names[i]) + return -ENOMEM; + + gpiod_set_consumer_name(pcie->id_reset_gpio[i], + pcie->reset_names[i]); } } return 0; - -put_node: - of_node_put(child); - of_node_put(parent); - return ret; } static long kirin_pcie_get_resource(struct kirin_pcie *kirin_pcie, @@ -463,14 +466,11 @@ static long kirin_pcie_get_resource(struct kirin_pcie *kirin_pcie, return PTR_ERR(kirin_pcie->apb); /* pcie internal PERST# gpio */ - kirin_pcie->gpio_id_dwc_perst = of_get_named_gpio(dev->of_node, - "reset-gpios", 0); - if (kirin_pcie->gpio_id_dwc_perst == -EPROBE_DEFER) { - return -EPROBE_DEFER; - } else if (!gpio_is_valid(kirin_pcie->gpio_id_dwc_perst)) { - dev_err(dev, "unable to get a valid gpio pin\n"); - return -ENODEV; - } + kirin_pcie->id_dwc_perst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(kirin_pcie->id_dwc_perst_gpio)) + return dev_err_probe(dev, PTR_ERR(kirin_pcie->id_dwc_perst_gpio), + "unable to get a valid gpio pin\n"); + gpiod_set_consumer_name(kirin_pcie->id_dwc_perst_gpio, "pcie_perst_bridge"); ret = kirin_pcie_get_gpio_enable(kirin_pcie, pdev); if (ret) @@ -553,7 +553,7 @@ static int kirin_pcie_add_bus(struct pci_bus *bus) /* Send PERST# to each slot */ for (i = 0; i < kirin_pcie->num_slots; i++) { - ret = gpio_direction_output(kirin_pcie->gpio_id_reset[i], 1); + ret = gpiod_direction_output_raw(kirin_pcie->id_reset_gpio[i], 1); if (ret) { dev_err(pci->dev, "PERST# %s error: %d\n", kirin_pcie->reset_names[i], ret); @@ -623,44 +623,6 @@ static int kirin_pcie_host_init(struct dw_pcie_rp *pp) return 0; } -static int kirin_pcie_gpio_request(struct kirin_pcie *kirin_pcie, - struct device *dev) -{ - int ret, i; - - for (i = 0; i < kirin_pcie->num_slots; i++) { - if (!gpio_is_valid(kirin_pcie->gpio_id_reset[i])) { - dev_err(dev, "unable to get a valid %s gpio\n", - kirin_pcie->reset_names[i]); - return -ENODEV; - } - - ret = devm_gpio_request(dev, kirin_pcie->gpio_id_reset[i], - kirin_pcie->reset_names[i]); - if (ret) - return ret; - } - - for (i = 0; i < kirin_pcie->n_gpio_clkreq; i++) { - if (!gpio_is_valid(kirin_pcie->gpio_id_clkreq[i])) { - dev_err(dev, "unable to get a valid %s gpio\n", - kirin_pcie->clkreq_names[i]); - return -ENODEV; - } - - ret = devm_gpio_request(dev, kirin_pcie->gpio_id_clkreq[i], - kirin_pcie->clkreq_names[i]); - if (ret) - return ret; - - ret = gpio_direction_output(kirin_pcie->gpio_id_clkreq[i], 0); - if (ret) - return ret; - } - - return 0; -} - static const struct dw_pcie_ops kirin_dw_pcie_ops = { .read_dbi = kirin_pcie_read_dbi, .write_dbi = kirin_pcie_write_dbi, @@ -680,7 +642,7 @@ static int kirin_pcie_power_off(struct kirin_pcie *kirin_pcie) return hi3660_pcie_phy_power_off(kirin_pcie); for (i = 0; i < kirin_pcie->n_gpio_clkreq; i++) - gpio_direction_output(kirin_pcie->gpio_id_clkreq[i], 1); + gpiod_direction_output_raw(kirin_pcie->id_clkreq_gpio[i], 1); phy_power_off(kirin_pcie->phy); phy_exit(kirin_pcie->phy); @@ -707,10 +669,6 @@ static int kirin_pcie_power_on(struct platform_device *pdev, if (IS_ERR(kirin_pcie->phy)) return PTR_ERR(kirin_pcie->phy); - ret = kirin_pcie_gpio_request(kirin_pcie, dev); - if (ret) - return ret; - ret = phy_init(kirin_pcie->phy); if (ret) goto err; @@ -723,11 +681,9 @@ static int kirin_pcie_power_on(struct platform_device *pdev, /* perst assert Endpoint */ usleep_range(REF_2_PERST_MIN, REF_2_PERST_MAX); - if (!gpio_request(kirin_pcie->gpio_id_dwc_perst, "pcie_perst_bridge")) { - ret = gpio_direction_output(kirin_pcie->gpio_id_dwc_perst, 1); - if (ret) - goto err; - } + ret = gpiod_direction_output_raw(kirin_pcie->id_dwc_perst_gpio, 1); + if (ret) + goto err; usleep_range(PERST_2_ACCESS_MIN, PERST_2_ACCESS_MAX); diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index 2fb8c15e7a91..236229f66c80 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -47,6 +47,7 @@ #define PARF_DBI_BASE_ADDR_HI 0x354 #define PARF_SLV_ADDR_SPACE_SIZE 0x358 #define PARF_SLV_ADDR_SPACE_SIZE_HI 0x35c +#define PARF_NO_SNOOP_OVERIDE 0x3d4 #define PARF_ATU_BASE_ADDR 0x634 #define PARF_ATU_BASE_ADDR_HI 0x638 #define PARF_SRIS_MODE 0x644 @@ -86,6 +87,10 @@ #define PARF_DEBUG_INT_CFG_BUS_MASTER_EN BIT(2) #define PARF_DEBUG_INT_RADM_PM_TURNOFF BIT(3) +/* PARF_NO_SNOOP_OVERIDE register fields */ +#define WR_NO_SNOOP_OVERIDE_EN BIT(1) +#define RD_NO_SNOOP_OVERIDE_EN BIT(3) + /* PARF_DEVICE_TYPE register fields */ #define PARF_DEVICE_TYPE_EP 0x0 @@ -149,6 +154,16 @@ enum qcom_pcie_ep_link_status { QCOM_PCIE_EP_LINK_DOWN, }; +/** + * struct qcom_pcie_ep_cfg - Per SoC config struct + * @hdma_support: HDMA support on this SoC + * @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache snooping + */ +struct qcom_pcie_ep_cfg { + bool hdma_support; + bool override_no_snoop; +}; + /** * struct qcom_pcie_ep - Qualcomm PCIe Endpoint Controller * @pci: Designware PCIe controller struct @@ -167,6 +182,7 @@ enum qcom_pcie_ep_link_status { * @num_clks: PCIe clocks count * @perst_en: Flag for PERST enable * @perst_sep_en: Flag for PERST separation enable + * @cfg: PCIe EP config struct * @link_status: PCIe Link status * @global_irq: Qualcomm PCIe specific Global IRQ * @perst_irq: PERST# IRQ @@ -194,6 +210,7 @@ struct qcom_pcie_ep { u32 perst_en; u32 perst_sep_en; + const struct qcom_pcie_ep_cfg *cfg; enum qcom_pcie_ep_link_status link_status; int global_irq; int perst_irq; @@ -482,13 +499,17 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci) val &= ~PARF_MSTR_AXI_CLK_EN; writel_relaxed(val, pcie_ep->parf + PARF_MHI_CLOCK_RESET_CTRL); - dw_pcie_ep_init_notify(&pcie_ep->pci.ep); + pci_epc_init_notify(pcie_ep->pci.ep.epc); /* Enable LTSSM */ val = readl_relaxed(pcie_ep->parf + PARF_LTSSM); val |= BIT(8); writel_relaxed(val, pcie_ep->parf + PARF_LTSSM); + if (pcie_ep->cfg && pcie_ep->cfg->override_no_snoop) + writel_relaxed(WR_NO_SNOOP_OVERIDE_EN | RD_NO_SNOOP_OVERIDE_EN, + pcie_ep->parf + PARF_NO_SNOOP_OVERIDE); + return 0; err_disable_resources: @@ -500,13 +521,8 @@ err_disable_resources: static void qcom_pcie_perst_assert(struct dw_pcie *pci) { struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci); - struct device *dev = pci->dev; - - if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED) { - dev_dbg(dev, "Link is already disabled\n"); - return; - } + pci_epc_deinit_notify(pci->ep.epc); dw_pcie_ep_cleanup(&pci->ep); qcom_pcie_disable_resources(pcie_ep); pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED; @@ -640,12 +656,12 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data) if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) { dev_dbg(dev, "Received Linkdown event\n"); pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN; - pci_epc_linkdown(pci->ep.epc); + dw_pcie_ep_linkdown(&pci->ep); } else if (FIELD_GET(PARF_INT_ALL_BME, status)) { - dev_dbg(dev, "Received BME event. Link is enabled!\n"); + dev_dbg(dev, "Received Bus Master Enable event\n"); pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED; qcom_pcie_ep_icc_update(pcie_ep); - pci_epc_bme_notify(pci->ep.epc); + pci_epc_bus_master_enable_notify(pci->ep.epc); } else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) { dev_dbg(dev, "Received PM Turn-off event! Entering L23\n"); val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL); @@ -816,6 +832,14 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev) pcie_ep->pci.ops = &pci_ops; pcie_ep->pci.ep.ops = &pci_ep_ops; pcie_ep->pci.edma.nr_irqs = 1; + + pcie_ep->cfg = of_device_get_match_data(dev); + if (pcie_ep->cfg && pcie_ep->cfg->hdma_support) { + pcie_ep->pci.edma.ll_wr_cnt = 8; + pcie_ep->pci.edma.ll_rd_cnt = 8; + pcie_ep->pci.edma.mf = EDMA_MF_HDMA_NATIVE; + } + platform_set_drvdata(pdev, pcie_ep); ret = qcom_pcie_ep_get_resources(pdev, pcie_ep); @@ -874,7 +898,13 @@ static void qcom_pcie_ep_remove(struct platform_device *pdev) qcom_pcie_disable_resources(pcie_ep); } +static const struct qcom_pcie_ep_cfg cfg_1_34_0 = { + .hdma_support = true, + .override_no_snoop = true, +}; + static const struct of_device_id qcom_pcie_ep_match[] = { + { .compatible = "qcom,sa8775p-pcie-ep", .data = &cfg_1_34_0}, { .compatible = "qcom,sdx55-pcie-ep", }, { .compatible = "qcom,sm8450-pcie-ep", }, { } diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 14772edcf0d3..0180edf3310e 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -18,10 +18,11 @@ #include #include #include +#include #include #include -#include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include "../../pci.h" #include "pcie-designware.h" @@ -51,6 +53,7 @@ #define PARF_SID_OFFSET 0x234 #define PARF_BDF_TRANSLATE_CFG 0x24c #define PARF_SLV_ADDR_SPACE_SIZE 0x358 +#define PARF_NO_SNOOP_OVERIDE 0x3d4 #define PARF_DEVICE_TYPE 0x1000 #define PARF_BDF_TO_SID_TABLE_N 0x2000 #define PARF_BDF_TO_SID_CFG 0x2c00 @@ -118,6 +121,10 @@ /* PARF_LTSSM register fields */ #define LTSSM_EN BIT(8) +/* PARF_NO_SNOOP_OVERIDE register fields */ +#define WR_NO_SNOOP_OVERIDE_EN BIT(1) +#define RD_NO_SNOOP_OVERIDE_EN BIT(3) + /* PARF_DEVICE_TYPE register fields */ #define DEVICE_TYPE_RC 0x4 @@ -154,58 +161,56 @@ #define QCOM_PCIE_LINK_SPEED_TO_BW(speed) \ Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_link_speed[speed])) -#define QCOM_PCIE_1_0_0_MAX_CLOCKS 4 struct qcom_pcie_resources_1_0_0 { - struct clk_bulk_data clks[QCOM_PCIE_1_0_0_MAX_CLOCKS]; + struct clk_bulk_data *clks; + int num_clks; struct reset_control *core; struct regulator *vdda; }; -#define QCOM_PCIE_2_1_0_MAX_CLOCKS 5 #define QCOM_PCIE_2_1_0_MAX_RESETS 6 #define QCOM_PCIE_2_1_0_MAX_SUPPLY 3 struct qcom_pcie_resources_2_1_0 { - struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS]; + struct clk_bulk_data *clks; + int num_clks; struct reset_control_bulk_data resets[QCOM_PCIE_2_1_0_MAX_RESETS]; int num_resets; struct regulator_bulk_data supplies[QCOM_PCIE_2_1_0_MAX_SUPPLY]; }; -#define QCOM_PCIE_2_3_2_MAX_CLOCKS 4 #define QCOM_PCIE_2_3_2_MAX_SUPPLY 2 struct qcom_pcie_resources_2_3_2 { - struct clk_bulk_data clks[QCOM_PCIE_2_3_2_MAX_CLOCKS]; + struct clk_bulk_data *clks; + int num_clks; struct regulator_bulk_data supplies[QCOM_PCIE_2_3_2_MAX_SUPPLY]; }; -#define QCOM_PCIE_2_3_3_MAX_CLOCKS 5 #define QCOM_PCIE_2_3_3_MAX_RESETS 7 struct qcom_pcie_resources_2_3_3 { - struct clk_bulk_data clks[QCOM_PCIE_2_3_3_MAX_CLOCKS]; + struct clk_bulk_data *clks; + int num_clks; struct reset_control_bulk_data rst[QCOM_PCIE_2_3_3_MAX_RESETS]; }; -#define QCOM_PCIE_2_4_0_MAX_CLOCKS 4 #define QCOM_PCIE_2_4_0_MAX_RESETS 12 struct qcom_pcie_resources_2_4_0 { - struct clk_bulk_data clks[QCOM_PCIE_2_4_0_MAX_CLOCKS]; + struct clk_bulk_data *clks; int num_clks; struct reset_control_bulk_data resets[QCOM_PCIE_2_4_0_MAX_RESETS]; int num_resets; }; -#define QCOM_PCIE_2_7_0_MAX_CLOCKS 15 #define QCOM_PCIE_2_7_0_MAX_SUPPLIES 2 struct qcom_pcie_resources_2_7_0 { - struct clk_bulk_data clks[QCOM_PCIE_2_7_0_MAX_CLOCKS]; + struct clk_bulk_data *clks; int num_clks; struct regulator_bulk_data supplies[QCOM_PCIE_2_7_0_MAX_SUPPLIES]; struct reset_control *rst; }; -#define QCOM_PCIE_2_9_0_MAX_CLOCKS 5 struct qcom_pcie_resources_2_9_0 { - struct clk_bulk_data clks[QCOM_PCIE_2_9_0_MAX_CLOCKS]; + struct clk_bulk_data *clks; + int num_clks; struct reset_control *rst; }; @@ -231,8 +236,15 @@ struct qcom_pcie_ops { int (*config_sid)(struct qcom_pcie *pcie); }; + /** + * struct qcom_pcie_cfg - Per SoC config struct + * @ops: qcom PCIe ops structure + * @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache + * snooping + */ struct qcom_pcie_cfg { const struct qcom_pcie_ops *ops; + bool override_no_snoop; bool no_l0s; }; @@ -245,6 +257,7 @@ struct qcom_pcie { struct phy *phy; struct gpio_desc *reset; struct icc_path *icc_mem; + struct icc_path *icc_cpu; const struct qcom_pcie_cfg *cfg; struct dentry *debugfs; bool suspended; @@ -337,21 +350,11 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) if (ret) return ret; - res->clks[0].id = "iface"; - res->clks[1].id = "core"; - res->clks[2].id = "phy"; - res->clks[3].id = "aux"; - res->clks[4].id = "ref"; - - /* iface, core, phy are required */ - ret = devm_clk_bulk_get(dev, 3, res->clks); - if (ret < 0) - return ret; - - /* aux, ref are optional */ - ret = devm_clk_bulk_get_optional(dev, 2, res->clks + 3); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } res->resets[0].id = "pci"; res->resets[1].id = "axi"; @@ -373,7 +376,7 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; - clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); + clk_bulk_disable_unprepare(res->num_clks, res->clks); reset_control_bulk_assert(res->num_resets, res->resets); writel(1, pcie->parf + PARF_PHY_CTRL); @@ -425,7 +428,7 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie) val &= ~PHY_TEST_PWR_DOWN; writel(val, pcie->parf + PARF_PHY_CTRL); - ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); + ret = clk_bulk_prepare_enable(res->num_clks, res->clks); if (ret) return ret; @@ -476,20 +479,16 @@ static int qcom_pcie_get_resources_1_0_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; - int ret; res->vdda = devm_regulator_get(dev, "vdda"); if (IS_ERR(res->vdda)) return PTR_ERR(res->vdda); - res->clks[0].id = "iface"; - res->clks[1].id = "aux"; - res->clks[2].id = "master_bus"; - res->clks[3].id = "slave_bus"; - - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } res->core = devm_reset_control_get_exclusive(dev, "core"); return PTR_ERR_OR_ZERO(res->core); @@ -500,7 +499,7 @@ static void qcom_pcie_deinit_1_0_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0; reset_control_assert(res->core); - clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); + clk_bulk_disable_unprepare(res->num_clks, res->clks); regulator_disable(res->vdda); } @@ -517,7 +516,7 @@ static int qcom_pcie_init_1_0_0(struct qcom_pcie *pcie) return ret; } - ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); + ret = clk_bulk_prepare_enable(res->num_clks, res->clks); if (ret) { dev_err(dev, "cannot prepare/enable clocks\n"); goto err_assert_reset; @@ -532,7 +531,7 @@ static int qcom_pcie_init_1_0_0(struct qcom_pcie *pcie) return 0; err_disable_clks: - clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); + clk_bulk_disable_unprepare(res->num_clks, res->clks); err_assert_reset: reset_control_assert(res->core); @@ -580,14 +579,11 @@ static int qcom_pcie_get_resources_2_3_2(struct qcom_pcie *pcie) if (ret) return ret; - res->clks[0].id = "aux"; - res->clks[1].id = "cfg"; - res->clks[2].id = "bus_master"; - res->clks[3].id = "bus_slave"; - - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } return 0; } @@ -596,7 +592,7 @@ static void qcom_pcie_deinit_2_3_2(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2; - clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); + clk_bulk_disable_unprepare(res->num_clks, res->clks); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } @@ -613,7 +609,7 @@ static int qcom_pcie_init_2_3_2(struct qcom_pcie *pcie) return ret; } - ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); + ret = clk_bulk_prepare_enable(res->num_clks, res->clks); if (ret) { dev_err(dev, "cannot prepare/enable clocks\n"); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); @@ -661,17 +657,11 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie) bool is_ipq = of_device_is_compatible(dev->of_node, "qcom,pcie-ipq4019"); int ret; - res->clks[0].id = "aux"; - res->clks[1].id = "master_bus"; - res->clks[2].id = "slave_bus"; - res->clks[3].id = "iface"; - - /* qcom,pcie-ipq4019 is defined without "iface" */ - res->num_clks = is_ipq ? 3 : 4; - - ret = devm_clk_bulk_get(dev, res->num_clks, res->clks); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } res->resets[0].id = "axi_m"; res->resets[1].id = "axi_s"; @@ -742,15 +732,11 @@ static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie) struct device *dev = pci->dev; int ret; - res->clks[0].id = "iface"; - res->clks[1].id = "axi_m"; - res->clks[2].id = "axi_s"; - res->clks[3].id = "ahb"; - res->clks[4].id = "aux"; - - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } res->rst[0].id = "axi_m"; res->rst[1].id = "axi_s"; @@ -771,7 +757,7 @@ static void qcom_pcie_deinit_2_3_3(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; - clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); + clk_bulk_disable_unprepare(res->num_clks, res->clks); } static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) @@ -801,7 +787,7 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) */ usleep_range(2000, 2500); - ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); + ret = clk_bulk_prepare_enable(res->num_clks, res->clks); if (ret) { dev_err(dev, "cannot prepare/enable clocks\n"); goto err_assert_resets; @@ -862,8 +848,6 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; - unsigned int num_clks, num_opt_clks; - unsigned int idx; int ret; res->rst = devm_reset_control_array_get_exclusive(dev); @@ -877,36 +861,11 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie) if (ret) return ret; - idx = 0; - res->clks[idx++].id = "aux"; - res->clks[idx++].id = "cfg"; - res->clks[idx++].id = "bus_master"; - res->clks[idx++].id = "bus_slave"; - res->clks[idx++].id = "slave_q2a"; - - num_clks = idx; - - ret = devm_clk_bulk_get(dev, num_clks, res->clks); - if (ret < 0) - return ret; - - res->clks[idx++].id = "tbu"; - res->clks[idx++].id = "ddrss_sf_tbu"; - res->clks[idx++].id = "aggre0"; - res->clks[idx++].id = "aggre1"; - res->clks[idx++].id = "noc_aggr"; - res->clks[idx++].id = "noc_aggr_4"; - res->clks[idx++].id = "noc_aggr_south_sf"; - res->clks[idx++].id = "cnoc_qx"; - res->clks[idx++].id = "sleep"; - res->clks[idx++].id = "cnoc_sf_axi"; - - num_opt_clks = idx - num_clks; - res->num_clks = idx; - - ret = devm_clk_bulk_get_optional(dev, num_opt_clks, res->clks + num_clks); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } return 0; } @@ -986,6 +945,12 @@ err_disable_regulators: static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) { + const struct qcom_pcie_cfg *pcie_cfg = pcie->cfg; + + if (pcie_cfg->override_no_snoop) + writel(WR_NO_SNOOP_OVERIDE_EN | RD_NO_SNOOP_OVERIDE_EN, + pcie->parf + PARF_NO_SNOOP_OVERIDE); + qcom_pcie_clear_aspm_l0s(pcie->pci); qcom_pcie_clear_hpc(pcie->pci); @@ -1101,17 +1066,12 @@ static int qcom_pcie_get_resources_2_9_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; - int ret; - res->clks[0].id = "iface"; - res->clks[1].id = "axi_m"; - res->clks[2].id = "axi_s"; - res->clks[3].id = "axi_bridge"; - res->clks[4].id = "rchng"; - - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); - if (ret < 0) - return ret; + res->num_clks = devm_clk_bulk_get_all(dev, &res->clks); + if (res->num_clks < 0) { + dev_err(dev, "Failed to get clocks\n"); + return res->num_clks; + } res->rst = devm_reset_control_array_get_exclusive(dev); if (IS_ERR(res->rst)) @@ -1124,7 +1084,7 @@ static void qcom_pcie_deinit_2_9_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0; - clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); + clk_bulk_disable_unprepare(res->num_clks, res->clks); } static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie) @@ -1153,7 +1113,7 @@ static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie) usleep_range(2000, 2500); - return clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); + return clk_bulk_prepare_enable(res->num_clks, res->clks); } static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) @@ -1366,6 +1326,11 @@ static const struct qcom_pcie_cfg cfg_1_9_0 = { .ops = &ops_1_9_0, }; +static const struct qcom_pcie_cfg cfg_1_34_0 = { + .ops = &ops_1_9_0, + .override_no_snoop = true, +}; + static const struct qcom_pcie_cfg cfg_2_1_0 = { .ops = &ops_2_1_0, }; @@ -1409,6 +1374,9 @@ static int qcom_pcie_icc_init(struct qcom_pcie *pcie) if (IS_ERR(pcie->icc_mem)) return PTR_ERR(pcie->icc_mem); + pcie->icc_cpu = devm_of_icc_get(pci->dev, "cpu-pcie"); + if (IS_ERR(pcie->icc_cpu)) + return PTR_ERR(pcie->icc_cpu); /* * Some Qualcomm platforms require interconnect bandwidth constraints * to be set before enabling interconnect clocks. @@ -1418,23 +1386,35 @@ static int qcom_pcie_icc_init(struct qcom_pcie *pcie) */ ret = icc_set_bw(pcie->icc_mem, 0, QCOM_PCIE_LINK_SPEED_TO_BW(1)); if (ret) { - dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n", + dev_err(pci->dev, "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n", ret); return ret; } + /* + * Since the CPU-PCIe path is only used for activities like register + * access of the host controller and endpoint Config/BAR space access, + * HW team has recommended to use a minimal bandwidth of 1KBps just to + * keep the path active. + */ + ret = icc_set_bw(pcie->icc_cpu, 0, kBps_to_icc(1)); + if (ret) { + dev_err(pci->dev, "Failed to set bandwidth for CPU-PCIe interconnect path: %d\n", + ret); + icc_set_bw(pcie->icc_mem, 0, 0); + return ret; + } + return 0; } -static void qcom_pcie_icc_update(struct qcom_pcie *pcie) +static void qcom_pcie_icc_opp_update(struct qcom_pcie *pcie) { + u32 offset, status, width, speed; struct dw_pcie *pci = pcie->pci; - u32 offset, status; - int speed, width; - int ret; - - if (!pcie->icc_mem) - return; + unsigned long freq_kbps; + struct dev_pm_opp *opp; + int ret, freq_mbps; offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); status = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA); @@ -1446,10 +1426,28 @@ static void qcom_pcie_icc_update(struct qcom_pcie *pcie) speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, status); width = FIELD_GET(PCI_EXP_LNKSTA_NLW, status); - ret = icc_set_bw(pcie->icc_mem, 0, width * QCOM_PCIE_LINK_SPEED_TO_BW(speed)); - if (ret) { - dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n", - ret); + if (pcie->icc_mem) { + ret = icc_set_bw(pcie->icc_mem, 0, + width * QCOM_PCIE_LINK_SPEED_TO_BW(speed)); + if (ret) { + dev_err(pci->dev, "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n", + ret); + } + } else { + freq_mbps = pcie_dev_speed_mbps(pcie_link_speed[speed]); + if (freq_mbps < 0) + return; + + freq_kbps = freq_mbps * KILO; + opp = dev_pm_opp_find_freq_exact(pci->dev, freq_kbps * width, + true); + if (!IS_ERR(opp)) { + ret = dev_pm_opp_set_opp(pci->dev, opp); + if (ret) + dev_err(pci->dev, "Failed to set OPP for freq (%lu): %d\n", + freq_kbps * width, ret); + dev_pm_opp_put(opp); + } } } @@ -1493,7 +1491,9 @@ static void qcom_pcie_init_debugfs(struct qcom_pcie *pcie) static int qcom_pcie_probe(struct platform_device *pdev) { const struct qcom_pcie_cfg *pcie_cfg; + unsigned long max_freq = ULONG_MAX; struct device *dev = &pdev->dev; + struct dev_pm_opp *opp; struct qcom_pcie *pcie; struct dw_pcie_rp *pp; struct resource *res; @@ -1561,9 +1561,43 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_pm_runtime_put; } - ret = qcom_pcie_icc_init(pcie); - if (ret) + /* OPP table is optional */ + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) { + dev_err_probe(dev, ret, "Failed to add OPP table\n"); goto err_pm_runtime_put; + } + + /* + * Before the PCIe link is initialized, vote for highest OPP in the OPP + * table, so that we are voting for maximum voltage corner for the + * link to come up in maximum supported speed. At the end of the + * probe(), OPP will be updated using qcom_pcie_icc_opp_update(). + */ + if (!ret) { + opp = dev_pm_opp_find_freq_floor(dev, &max_freq); + if (IS_ERR(opp)) { + ret = PTR_ERR(opp); + dev_err_probe(pci->dev, ret, + "Unable to find max freq OPP\n"); + goto err_pm_runtime_put; + } else { + ret = dev_pm_opp_set_opp(dev, opp); + } + + dev_pm_opp_put(opp); + if (ret) { + dev_err_probe(pci->dev, ret, + "Failed to set OPP for freq %lu\n", + max_freq); + goto err_pm_runtime_put; + } + } else { + /* Skip ICC init if OPP is supported as it is handled by OPP */ + ret = qcom_pcie_icc_init(pcie); + if (ret) + goto err_pm_runtime_put; + } ret = pcie->cfg->ops->get_resources(pcie); if (ret) @@ -1583,7 +1617,7 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_phy_exit; } - qcom_pcie_icc_update(pcie); + qcom_pcie_icc_opp_update(pcie); if (pcie->mhi) qcom_pcie_init_debugfs(pcie); @@ -1602,16 +1636,20 @@ err_pm_runtime_put: static int qcom_pcie_suspend_noirq(struct device *dev) { struct qcom_pcie *pcie = dev_get_drvdata(dev); - int ret; + int ret = 0; /* * Set minimum bandwidth required to keep data path functional during * suspend. */ - ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1)); - if (ret) { - dev_err(dev, "Failed to set interconnect bandwidth: %d\n", ret); - return ret; + if (pcie->icc_mem) { + ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1)); + if (ret) { + dev_err(dev, + "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n", + ret); + return ret; + } } /* @@ -1634,7 +1672,21 @@ static int qcom_pcie_suspend_noirq(struct device *dev) pcie->suspended = true; } - return 0; + /* + * Only disable CPU-PCIe interconnect path if the suspend is non-S2RAM. + * Because on some platforms, DBI access can happen very late during the + * S2RAM and a non-active CPU-PCIe interconnect path may lead to NoC + * error. + */ + if (pm_suspend_target_state != PM_SUSPEND_MEM) { + ret = icc_disable(pcie->icc_cpu); + if (ret) + dev_err(dev, "Failed to disable CPU-PCIe interconnect path: %d\n", ret); + + if (!pcie->icc_mem) + dev_pm_opp_set_opp(pcie->pci->dev, NULL); + } + return ret; } static int qcom_pcie_resume_noirq(struct device *dev) @@ -1642,6 +1694,14 @@ static int qcom_pcie_resume_noirq(struct device *dev) struct qcom_pcie *pcie = dev_get_drvdata(dev); int ret; + if (pm_suspend_target_state != PM_SUSPEND_MEM) { + ret = icc_enable(pcie->icc_cpu); + if (ret) { + dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret); + return ret; + } + } + if (pcie->suspended) { ret = qcom_pcie_host_init(&pcie->pci->pp); if (ret) @@ -1650,7 +1710,7 @@ static int qcom_pcie_resume_noirq(struct device *dev) pcie->suspended = false; } - qcom_pcie_icc_update(pcie); + qcom_pcie_icc_opp_update(pcie); return 0; } @@ -1667,7 +1727,7 @@ static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 }, { .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 }, { .compatible = "qcom,pcie-sa8540p", .data = &cfg_sc8280xp }, - { .compatible = "qcom,pcie-sa8775p", .data = &cfg_1_9_0}, + { .compatible = "qcom,pcie-sa8775p", .data = &cfg_1_34_0}, { .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sc8280xp", .data = &cfg_sc8280xp }, diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c index cfeccc2f9ee1..f0f3ebd1a033 100644 --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c @@ -2,11 +2,17 @@ /* * PCIe controller driver for Renesas R-Car Gen4 Series SoCs * Copyright (C) 2022-2023 Renesas Electronics Corporation + * + * The r8a779g0 (R-Car V4H) controller requires a specific firmware to be + * provided, to initialize the PHY. Otherwise, the PCIe controller will not + * work. */ #include +#include #include #include +#include #include #include #include @@ -20,9 +26,10 @@ /* Renesas-specific */ /* PCIe Mode Setting Register 0 */ #define PCIEMSR0 0x0000 -#define BIFUR_MOD_SET_ON BIT(0) +#define APP_SRIS_MODE BIT(6) #define DEVICE_TYPE_EP 0 #define DEVICE_TYPE_RC BIT(4) +#define BIFUR_MOD_SET_ON BIT(0) /* PCIe Interrupt Status 0 */ #define PCIEINTSTS0 0x0084 @@ -37,47 +44,49 @@ #define PCIEDMAINTSTSEN 0x0314 #define PCIEDMAINTSTSEN_INIT GENMASK(15, 0) +/* Port Logic Registers 89 */ +#define PRTLGC89 0x0b70 + +/* Port Logic Registers 90 */ +#define PRTLGC90 0x0b74 + /* PCIe Reset Control Register 1 */ #define PCIERSTCTRL1 0x0014 #define APP_HOLD_PHY_RST BIT(16) #define APP_LTSSM_ENABLE BIT(0) +/* PCIe Power Management Control */ +#define PCIEPWRMNGCTRL 0x0070 +#define APP_CLK_REQ_N BIT(11) +#define APP_CLK_PM_EN BIT(10) + #define RCAR_NUM_SPEED_CHANGE_RETRIES 10 #define RCAR_MAX_LINK_SPEED 4 #define RCAR_GEN4_PCIE_EP_FUNC_DBI_OFFSET 0x1000 #define RCAR_GEN4_PCIE_EP_FUNC_DBI2_OFFSET 0x800 +#define RCAR_GEN4_PCIE_FIRMWARE_NAME "rcar_gen4_pcie.bin" +#define RCAR_GEN4_PCIE_FIRMWARE_BASE_ADDR 0xc000 +MODULE_FIRMWARE(RCAR_GEN4_PCIE_FIRMWARE_NAME); + +struct rcar_gen4_pcie; +struct rcar_gen4_pcie_drvdata { + void (*additional_common_init)(struct rcar_gen4_pcie *rcar); + int (*ltssm_control)(struct rcar_gen4_pcie *rcar, bool enable); + enum dw_pcie_device_mode mode; +}; + struct rcar_gen4_pcie { struct dw_pcie dw; void __iomem *base; + void __iomem *phy_base; struct platform_device *pdev; - enum dw_pcie_device_mode mode; + const struct rcar_gen4_pcie_drvdata *drvdata; }; #define to_rcar_gen4_pcie(_dw) container_of(_dw, struct rcar_gen4_pcie, dw) /* Common */ -static void rcar_gen4_pcie_ltssm_enable(struct rcar_gen4_pcie *rcar, - bool enable) -{ - u32 val; - - val = readl(rcar->base + PCIERSTCTRL1); - if (enable) { - val |= APP_LTSSM_ENABLE; - val &= ~APP_HOLD_PHY_RST; - } else { - /* - * Since the datasheet of R-Car doesn't mention how to assert - * the APP_HOLD_PHY_RST, don't assert it again. Otherwise, - * hang-up issue happened in the dw_edma_core_off() when - * the controller didn't detect a PCI device. - */ - val &= ~APP_LTSSM_ENABLE; - } - writel(val, rcar->base + PCIERSTCTRL1); -} - static int rcar_gen4_pcie_link_up(struct dw_pcie *dw) { struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); @@ -123,9 +132,13 @@ static int rcar_gen4_pcie_speed_change(struct dw_pcie *dw) static int rcar_gen4_pcie_start_link(struct dw_pcie *dw) { struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); - int i, changes; + int i, changes, ret; - rcar_gen4_pcie_ltssm_enable(rcar, true); + if (rcar->drvdata->ltssm_control) { + ret = rcar->drvdata->ltssm_control(rcar, true); + if (ret) + return ret; + } /* * Require direct speed change with retrying here if the link_gen is @@ -137,7 +150,7 @@ static int rcar_gen4_pcie_start_link(struct dw_pcie *dw) * Since dw_pcie_setup_rc() sets it once, PCIe Gen2 will be trained. * So, this needs remaining times for up to PCIe Gen4 if RC mode. */ - if (changes && rcar->mode == DW_PCIE_RC_TYPE) + if (changes && rcar->drvdata->mode == DW_PCIE_RC_TYPE) changes--; for (i = 0; i < changes; i++) { @@ -153,7 +166,8 @@ static void rcar_gen4_pcie_stop_link(struct dw_pcie *dw) { struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); - rcar_gen4_pcie_ltssm_enable(rcar, false); + if (rcar->drvdata->ltssm_control) + rcar->drvdata->ltssm_control(rcar, false); } static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar) @@ -172,9 +186,9 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar) reset_control_assert(dw->core_rsts[DW_PCIE_PWR_RST].rstc); val = readl(rcar->base + PCIEMSR0); - if (rcar->mode == DW_PCIE_RC_TYPE) { + if (rcar->drvdata->mode == DW_PCIE_RC_TYPE) { val |= DEVICE_TYPE_RC; - } else if (rcar->mode == DW_PCIE_EP_TYPE) { + } else if (rcar->drvdata->mode == DW_PCIE_EP_TYPE) { val |= DEVICE_TYPE_EP; } else { ret = -EINVAL; @@ -190,6 +204,9 @@ static int rcar_gen4_pcie_common_init(struct rcar_gen4_pcie *rcar) if (ret) goto err_unprepare; + if (rcar->drvdata->additional_common_init) + rcar->drvdata->additional_common_init(rcar); + return 0; err_unprepare: @@ -231,6 +248,10 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar) static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar) { + rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy"); + if (IS_ERR(rcar->phy_base)) + return PTR_ERR(rcar->phy_base); + /* Renesas-specific registers */ rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app"); @@ -255,7 +276,7 @@ static struct rcar_gen4_pcie *rcar_gen4_pcie_alloc(struct platform_device *pdev) rcar->dw.ops = &dw_pcie_ops; rcar->dw.dev = dev; rcar->pdev = pdev; - dw_pcie_cap_set(&rcar->dw, EDMA_UNROLL); + rcar->dw.edma.mf = EDMA_MF_EDMA_UNROLL; dw_pcie_cap_set(&rcar->dw, REQ_RES); platform_set_drvdata(pdev, rcar); @@ -437,7 +458,7 @@ static int rcar_gen4_add_dw_pcie_ep(struct rcar_gen4_pcie *rcar) rcar_gen4_pcie_ep_deinit(rcar); } - dw_pcie_ep_init_notify(ep); + pci_epc_init_notify(ep->epc); return ret; } @@ -451,9 +472,11 @@ static void rcar_gen4_remove_dw_pcie_ep(struct rcar_gen4_pcie *rcar) /* Common */ static int rcar_gen4_add_dw_pcie(struct rcar_gen4_pcie *rcar) { - rcar->mode = (uintptr_t)of_device_get_match_data(&rcar->pdev->dev); + rcar->drvdata = of_device_get_match_data(&rcar->pdev->dev); + if (!rcar->drvdata) + return -EINVAL; - switch (rcar->mode) { + switch (rcar->drvdata->mode) { case DW_PCIE_RC_TYPE: return rcar_gen4_add_dw_pcie_rp(rcar); case DW_PCIE_EP_TYPE: @@ -494,7 +517,7 @@ err_unprepare: static void rcar_gen4_remove_dw_pcie(struct rcar_gen4_pcie *rcar) { - switch (rcar->mode) { + switch (rcar->drvdata->mode) { case DW_PCIE_RC_TYPE: rcar_gen4_remove_dw_pcie_rp(rcar); break; @@ -514,14 +537,227 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev) rcar_gen4_pcie_unprepare(rcar); } +static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable) +{ + u32 val; + + val = readl(rcar->base + PCIERSTCTRL1); + if (enable) { + val |= APP_LTSSM_ENABLE; + val &= ~APP_HOLD_PHY_RST; + } else { + /* + * Since the datasheet of R-Car doesn't mention how to assert + * the APP_HOLD_PHY_RST, don't assert it again. Otherwise, + * hang-up issue happened in the dw_edma_core_off() when + * the controller didn't detect a PCI device. + */ + val &= ~APP_LTSSM_ENABLE; + } + writel(val, rcar->base + PCIERSTCTRL1); + + return 0; +} + +static void rcar_gen4_pcie_additional_common_init(struct rcar_gen4_pcie *rcar) +{ + struct dw_pcie *dw = &rcar->dw; + u32 val; + + val = dw_pcie_readl_dbi(dw, PCIE_PORT_LANE_SKEW); + val &= ~PORT_LANE_SKEW_INSERT_MASK; + if (dw->num_lanes < 4) + val |= BIT(6); + dw_pcie_writel_dbi(dw, PCIE_PORT_LANE_SKEW, val); + + val = readl(rcar->base + PCIEPWRMNGCTRL); + val |= APP_CLK_REQ_N | APP_CLK_PM_EN; + writel(val, rcar->base + PCIEPWRMNGCTRL); +} + +static void rcar_gen4_pcie_phy_reg_update_bits(struct rcar_gen4_pcie *rcar, + u32 offset, u32 mask, u32 val) +{ + u32 tmp; + + tmp = readl(rcar->phy_base + offset); + tmp &= ~mask; + tmp |= val; + writel(tmp, rcar->phy_base + offset); +} + +/* + * SoC datasheet suggests checking port logic register bits during firmware + * write. If read returns non-zero value, then this function returns -EAGAIN + * indicating that the write needs to be done again. If read returns zero, + * then return 0 to indicate success. + */ +static int rcar_gen4_pcie_reg_test_bit(struct rcar_gen4_pcie *rcar, + u32 offset, u32 mask) +{ + struct dw_pcie *dw = &rcar->dw; + + if (dw_pcie_readl_dbi(dw, offset) & mask) + return -EAGAIN; + + return 0; +} + +static int rcar_gen4_pcie_download_phy_firmware(struct rcar_gen4_pcie *rcar) +{ + /* The check_addr values are magical numbers in the datasheet */ + const u32 check_addr[] = { 0x00101018, 0x00101118, 0x00101021, 0x00101121}; + struct dw_pcie *dw = &rcar->dw; + const struct firmware *fw; + unsigned int i, timeout; + u32 data; + int ret; + + ret = request_firmware(&fw, RCAR_GEN4_PCIE_FIRMWARE_NAME, dw->dev); + if (ret) { + dev_err(dw->dev, "Failed to load firmware (%s): %d\n", + RCAR_GEN4_PCIE_FIRMWARE_NAME, ret); + return ret; + } + + for (i = 0; i < (fw->size / 2); i++) { + data = fw->data[(i * 2) + 1] << 8 | fw->data[i * 2]; + timeout = 100; + do { + dw_pcie_writel_dbi(dw, PRTLGC89, RCAR_GEN4_PCIE_FIRMWARE_BASE_ADDR + i); + dw_pcie_writel_dbi(dw, PRTLGC90, data); + if (!rcar_gen4_pcie_reg_test_bit(rcar, PRTLGC89, BIT(30))) + break; + if (!(--timeout)) { + ret = -ETIMEDOUT; + goto exit; + } + usleep_range(100, 200); + } while (1); + } + + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x0f8, BIT(17), BIT(17)); + + for (i = 0; i < ARRAY_SIZE(check_addr); i++) { + timeout = 100; + do { + dw_pcie_writel_dbi(dw, PRTLGC89, check_addr[i]); + ret = rcar_gen4_pcie_reg_test_bit(rcar, PRTLGC89, BIT(30)); + ret |= rcar_gen4_pcie_reg_test_bit(rcar, PRTLGC90, BIT(0)); + if (!ret) + break; + if (!(--timeout)) { + ret = -ETIMEDOUT; + goto exit; + } + usleep_range(100, 200); + } while (1); + } + +exit: + release_firmware(fw); + + return ret; +} + +static int rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable) +{ + struct dw_pcie *dw = &rcar->dw; + u32 val; + int ret; + + if (!enable) { + val = readl(rcar->base + PCIERSTCTRL1); + val &= ~APP_LTSSM_ENABLE; + writel(val, rcar->base + PCIERSTCTRL1); + + return 0; + } + + val = dw_pcie_readl_dbi(dw, PCIE_PORT_FORCE); + val |= PORT_FORCE_DO_DESKEW_FOR_SRIS; + dw_pcie_writel_dbi(dw, PCIE_PORT_FORCE, val); + + val = readl(rcar->base + PCIEMSR0); + val |= APP_SRIS_MODE; + writel(val, rcar->base + PCIEMSR0); + + /* + * The R-Car Gen4 datasheet doesn't describe the PHY registers' name. + * But, the initialization procedure describes these offsets. So, + * this driver has magical offset numbers. + */ + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x700, BIT(28), 0); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x700, BIT(20), 0); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x700, BIT(12), 0); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x700, BIT(4), 0); + + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(23, 22), BIT(22)); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(18, 16), GENMASK(17, 16)); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(7, 6), BIT(6)); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x148, GENMASK(2, 0), GENMASK(11, 0)); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x1d4, GENMASK(16, 15), GENMASK(16, 15)); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x514, BIT(26), BIT(26)); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x0f8, BIT(16), 0); + rcar_gen4_pcie_phy_reg_update_bits(rcar, 0x0f8, BIT(19), BIT(19)); + + val = readl(rcar->base + PCIERSTCTRL1); + val &= ~APP_HOLD_PHY_RST; + writel(val, rcar->base + PCIERSTCTRL1); + + ret = readl_poll_timeout(rcar->phy_base + 0x0f8, val, !(val & BIT(18)), 100, 10000); + if (ret < 0) + return ret; + + ret = rcar_gen4_pcie_download_phy_firmware(rcar); + if (ret) + return ret; + + val = readl(rcar->base + PCIERSTCTRL1); + val |= APP_LTSSM_ENABLE; + writel(val, rcar->base + PCIERSTCTRL1); + + return 0; +} + +static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie = { + .ltssm_control = r8a779f0_pcie_ltssm_control, + .mode = DW_PCIE_RC_TYPE, +}; + +static struct rcar_gen4_pcie_drvdata drvdata_r8a779f0_pcie_ep = { + .ltssm_control = r8a779f0_pcie_ltssm_control, + .mode = DW_PCIE_EP_TYPE, +}; + +static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie = { + .additional_common_init = rcar_gen4_pcie_additional_common_init, + .ltssm_control = rcar_gen4_pcie_ltssm_control, + .mode = DW_PCIE_RC_TYPE, +}; + +static struct rcar_gen4_pcie_drvdata drvdata_rcar_gen4_pcie_ep = { + .additional_common_init = rcar_gen4_pcie_additional_common_init, + .ltssm_control = rcar_gen4_pcie_ltssm_control, + .mode = DW_PCIE_EP_TYPE, +}; + static const struct of_device_id rcar_gen4_pcie_of_match[] = { + { + .compatible = "renesas,r8a779f0-pcie", + .data = &drvdata_r8a779f0_pcie, + }, + { + .compatible = "renesas,r8a779f0-pcie-ep", + .data = &drvdata_r8a779f0_pcie_ep, + }, { .compatible = "renesas,rcar-gen4-pcie", - .data = (void *)DW_PCIE_RC_TYPE, + .data = &drvdata_rcar_gen4_pcie, }, { .compatible = "renesas,rcar-gen4-pcie-ep", - .data = (void *)DW_PCIE_EP_TYPE, + .data = &drvdata_rcar_gen4_pcie_ep, }, {}, }; diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 93f5433c5c55..4bf7b433417a 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -308,10 +306,6 @@ static inline u32 appl_readl(struct tegra_pcie_dw *pcie, const u32 reg) return readl_relaxed(pcie->appl_base + reg); } -struct tegra_pcie_soc { - enum dw_pcie_device_mode mode; -}; - static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie) { struct dw_pcie *pci = &pcie->pci; @@ -1715,6 +1709,7 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie) if (ret) dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret); + pci_epc_deinit_notify(pcie->pci.ep.epc); dw_pcie_ep_cleanup(&pcie->pci.ep); reset_control_assert(pcie->core_rst); @@ -1903,7 +1898,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie) goto fail_init_complete; } - dw_pcie_ep_init_notify(ep); + pci_epc_init_notify(ep->epc); /* Program the private control to allow sending LTR upstream */ if (pcie->of_data->has_ltr_req_fix) { @@ -2015,6 +2010,7 @@ static const struct pci_epc_features tegra_pcie_epc_features = { .bar[BAR_3] = { .type = BAR_RESERVED, }, .bar[BAR_4] = { .type = BAR_RESERVED, }, .bar[BAR_5] = { .type = BAR_RESERVED, }, + .align = SZ_64K, }; static const struct pci_epc_features* diff --git a/drivers/pci/controller/dwc/pcie-uniphier-ep.c b/drivers/pci/controller/dwc/pcie-uniphier-ep.c index a2b844268e28..d6e73811216e 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier-ep.c +++ b/drivers/pci/controller/dwc/pcie-uniphier-ep.c @@ -410,7 +410,7 @@ static int uniphier_pcie_ep_probe(struct platform_device *pdev) return ret; } - dw_pcie_ep_init_notify(&priv->pci.ep); + pci_epc_init_notify(priv->pci.ep.epc); return 0; } diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c index d7b7350f02dd..5af22bee913b 100644 --- a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c @@ -190,7 +190,7 @@ static void ls_g4_pcie_reset(struct work_struct *work) ls_g4_pcie_enable_interrupt(pcie); } -static struct mobiveil_rp_ops ls_g4_pcie_rp_ops = { +static const struct mobiveil_rp_ops ls_g4_pcie_rp_ops = { .interrupt_init = ls_g4_pcie_interrupt_init, }; diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h index 6082b8afbc31..e63abb887ee3 100644 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h @@ -151,7 +151,7 @@ struct mobiveil_rp_ops { struct mobiveil_root_port { void __iomem *config_axi_slave_base; /* endpoint config base */ struct resource *ob_io_res; - struct mobiveil_rp_ops *ops; + const struct mobiveil_rp_ops *ops; int irq; raw_spinlock_t intx_mask_lock; struct irq_domain *intx_domain; diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 71ecd7ddcc8a..8b3e1a079cf3 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "../pci.h" diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c index 45b71806182d..cf5f59a745b3 100644 --- a/drivers/pci/controller/pci-host-common.c +++ b/drivers/pci/controller/pci-host-common.c @@ -73,10 +73,6 @@ int pci_host_common_probe(struct platform_device *pdev) if (IS_ERR(cfg)) return PTR_ERR(cfg); - /* Do not reassign resources if probe only */ - if (!pci_has_flag(PCI_PROBE_ONLY)) - pci_add_flags(PCI_REASSIGN_ALL_BUS); - bridge->sysdata = cfg; bridge->ops = (struct pci_ops *)&ops->pci_ops; bridge->msi_domain = true; @@ -96,4 +92,5 @@ void pci_host_common_remove(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(pci_host_common_remove); +MODULE_DESCRIPTION("Generic PCI host common driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c index 41cb6a057f6e..5f06f94db7b1 100644 --- a/drivers/pci/controller/pci-host-generic.c +++ b/drivers/pci/controller/pci-host-generic.c @@ -86,4 +86,5 @@ static struct platform_driver gen_pci_driver = { }; module_platform_driver(gen_pci_driver); +MODULE_DESCRIPTION("Generic PCI host controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 5992280e8110..cdd5be16021d 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -1130,8 +1130,8 @@ static void _hv_pcifront_read_config(struct hv_pci_dev *hpdev, int where, PCI_CAPABILITY_LIST) { /* ROM BARs are unimplemented */ *val = 0; - } else if (where >= PCI_INTERRUPT_LINE && where + size <= - PCI_INTERRUPT_PIN) { + } else if ((where >= PCI_INTERRUPT_LINE && where + size <= PCI_INTERRUPT_PIN) || + (where >= PCI_INTERRUPT_PIN && where + size <= PCI_MIN_GNT)) { /* * Interrupt Line and Interrupt PIN are hard-wired to zero * because this front-end only supports message-signaled diff --git a/drivers/pci/controller/pci-loongson.c b/drivers/pci/controller/pci-loongson.c index 8b34ccff073a..bc630ab8a283 100644 --- a/drivers/pci/controller/pci-loongson.c +++ b/drivers/pci/controller/pci-loongson.c @@ -163,6 +163,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_HDMI, loongson_pci_pin_quirk); +static void loongson_pci_msi_quirk(struct pci_dev *dev) +{ + u16 val, class = dev->class >> 8; + + if (class != PCI_CLASS_BRIDGE_HOST) + return; + + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &val); + val |= PCI_MSI_FLAGS_ENABLE; + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, val); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_PCIE_PORT5, loongson_pci_msi_quirk); + static struct loongson_pci *pci_bus_to_loongson_pci(struct pci_bus *bus) { struct pci_config_window *cfg; diff --git a/drivers/pci/controller/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c index 6ad5427490b5..16336a525c16 100644 --- a/drivers/pci/controller/pcie-altera-msi.c +++ b/drivers/pci/controller/pcie-altera-msi.c @@ -290,4 +290,5 @@ static void __exit altera_msi_exit(void) subsys_initcall(altera_msi_init); MODULE_DEVICE_TABLE(of, altera_msi_of_match); module_exit(altera_msi_exit); +MODULE_DESCRIPTION("Altera PCIe MSI support driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index a9536dc4bf96..ef73baefaeb9 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -826,4 +826,5 @@ static struct platform_driver altera_pcie_driver = { MODULE_DEVICE_TABLE(of, altera_pcie_of_match); module_platform_driver(altera_pcie_driver); +MODULE_DESCRIPTION("Altera PCIe host controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c index f7a248393a8f..fefab2758a06 100644 --- a/drivers/pci/controller/pcie-apple.c +++ b/drivers/pci/controller/pcie-apple.c @@ -839,4 +839,5 @@ static struct platform_driver apple_pcie_driver = { }; module_platform_driver(apple_pcie_driver); +MODULE_DESCRIPTION("Apple PCIe host bridge driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index 975b3024fb08..b7e8e24f6a40 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -1091,4 +1091,5 @@ static struct platform_driver mtk_pcie_driver = { }; module_platform_driver(mtk_pcie_driver); +MODULE_DESCRIPTION("MediaTek Gen3 PCIe host controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index 48372013f26d..7fc0d7709b7f 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -1252,4 +1252,5 @@ static struct platform_driver mtk_pcie_driver = { }, }; module_platform_driver(mtk_pcie_driver); +MODULE_DESCRIPTION("MediaTek PCIe host controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c index d97b956e6e57..9b4754a45515 100644 --- a/drivers/pci/controller/pcie-mt7621.c +++ b/drivers/pci/controller/pcie-mt7621.c @@ -549,4 +549,5 @@ static struct platform_driver mt7621_pcie_driver = { }; builtin_platform_driver(mt7621_pcie_driver); +MODULE_DESCRIPTION("MediaTek MT7621 PCIe host controller driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c index 996077ab7cfd..c01efc6ea64f 100644 --- a/drivers/pci/controller/pcie-rcar-host.c +++ b/drivers/pci/controller/pcie-rcar-host.c @@ -78,7 +78,11 @@ static int rcar_pcie_wakeup(struct device *pcie_dev, void __iomem *pcie_base) writel(L1IATN, pcie_base + PMCTLR); ret = readl_poll_timeout_atomic(pcie_base + PMSR, val, val & L1FAEG, 10, 1000); - WARN(ret, "Timeout waiting for L1 link state, ret=%d\n", ret); + if (ret) { + dev_warn_ratelimited(pcie_dev, + "Timeout waiting for L1 link state, ret=%d\n", + ret); + } writel(L1FAEG | PMEL1RX, pcie_base + PMSR); } diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index 300b9dc85ecc..cbec71114825 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -322,8 +322,11 @@ static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip) rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, PCIE_CLIENT_CONFIG); + msleep(PCIE_T_PVPERL_MS); gpiod_set_value_cansleep(rockchip->ep_gpio, 1); + msleep(PCIE_T_RRS_READY_MS); + /* 500ms timeout value should be enough for Gen1/2 training */ err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1, status, PCIE_LINK_UP(status), 20, diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c index 0ef2e622d36e..c07d7129f1c7 100644 --- a/drivers/pci/controller/pcie-rockchip.c +++ b/drivers/pci/controller/pcie-rockchip.c @@ -121,7 +121,7 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) if (rockchip->is_rc) { rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", - GPIOD_OUT_HIGH); + GPIOD_OUT_LOW); if (IS_ERR(rockchip->ep_gpio)) return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio), "failed to get ep GPIO\n"); diff --git a/drivers/pci/controller/plda/Kconfig b/drivers/pci/controller/plda/Kconfig new file mode 100644 index 000000000000..c0e14146d7e4 --- /dev/null +++ b/drivers/pci/controller/plda/Kconfig @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 + +menu "PLDA-based PCIe controllers" + depends on PCI + +config PCIE_PLDA_HOST + bool + +config PCIE_MICROCHIP_HOST + tristate "Microchip AXI PCIe controller" + depends on PCI_MSI && OF + select PCI_HOST_COMMON + select PCIE_PLDA_HOST + help + Say Y here if you want kernel to support the Microchip AXI PCIe + Host Bridge driver. + +config PCIE_STARFIVE_HOST + tristate "StarFive PCIe host controller" + depends on PCI_MSI && OF + depends on ARCH_STARFIVE || COMPILE_TEST + select PCIE_PLDA_HOST + help + Say Y here if you want to support the StarFive PCIe controller in + host mode. StarFive PCIe controller uses PLDA PCIe core. + + If you choose to build this driver as module it will be dynamically + linked and module will be called pcie-starfive.ko. + +endmenu diff --git a/drivers/pci/controller/plda/Makefile b/drivers/pci/controller/plda/Makefile new file mode 100644 index 000000000000..0ac6851bed48 --- /dev/null +++ b/drivers/pci/controller/plda/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o +obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o +obj-$(CONFIG_PCIE_STARFIVE_HOST) += pcie-starfive.o diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c similarity index 54% rename from drivers/pci/controller/pcie-microchip-host.c rename to drivers/pci/controller/plda/pcie-microchip-host.c index 137fb8570ba2..48f60a04b740 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/plda/pcie-microchip-host.c @@ -18,10 +18,8 @@ #include #include -#include "../pci.h" - -/* Number of MSI IRQs */ -#define MC_MAX_NUM_MSI_IRQS 32 +#include "../../pci.h" +#include "pcie-plda.h" /* PCIe Bridge Phy and Controller Phy offsets */ #define MC_PCIE1_BRIDGE_ADDR 0x00008000u @@ -30,84 +28,6 @@ #define MC_PCIE_BRIDGE_ADDR (MC_PCIE1_BRIDGE_ADDR) #define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR) -/* PCIe Bridge Phy Regs */ -#define PCIE_PCI_IRQ_DW0 0xa8 -#define MSIX_CAP_MASK BIT(31) -#define NUM_MSI_MSGS_MASK GENMASK(6, 4) -#define NUM_MSI_MSGS_SHIFT 4 - -#define IMASK_LOCAL 0x180 -#define DMA_END_ENGINE_0_MASK 0x00000000u -#define DMA_END_ENGINE_0_SHIFT 0 -#define DMA_END_ENGINE_1_MASK 0x00000000u -#define DMA_END_ENGINE_1_SHIFT 1 -#define DMA_ERROR_ENGINE_0_MASK 0x00000100u -#define DMA_ERROR_ENGINE_0_SHIFT 8 -#define DMA_ERROR_ENGINE_1_MASK 0x00000200u -#define DMA_ERROR_ENGINE_1_SHIFT 9 -#define A_ATR_EVT_POST_ERR_MASK 0x00010000u -#define A_ATR_EVT_POST_ERR_SHIFT 16 -#define A_ATR_EVT_FETCH_ERR_MASK 0x00020000u -#define A_ATR_EVT_FETCH_ERR_SHIFT 17 -#define A_ATR_EVT_DISCARD_ERR_MASK 0x00040000u -#define A_ATR_EVT_DISCARD_ERR_SHIFT 18 -#define A_ATR_EVT_DOORBELL_MASK 0x00000000u -#define A_ATR_EVT_DOORBELL_SHIFT 19 -#define P_ATR_EVT_POST_ERR_MASK 0x00100000u -#define P_ATR_EVT_POST_ERR_SHIFT 20 -#define P_ATR_EVT_FETCH_ERR_MASK 0x00200000u -#define P_ATR_EVT_FETCH_ERR_SHIFT 21 -#define P_ATR_EVT_DISCARD_ERR_MASK 0x00400000u -#define P_ATR_EVT_DISCARD_ERR_SHIFT 22 -#define P_ATR_EVT_DOORBELL_MASK 0x00000000u -#define P_ATR_EVT_DOORBELL_SHIFT 23 -#define PM_MSI_INT_INTA_MASK 0x01000000u -#define PM_MSI_INT_INTA_SHIFT 24 -#define PM_MSI_INT_INTB_MASK 0x02000000u -#define PM_MSI_INT_INTB_SHIFT 25 -#define PM_MSI_INT_INTC_MASK 0x04000000u -#define PM_MSI_INT_INTC_SHIFT 26 -#define PM_MSI_INT_INTD_MASK 0x08000000u -#define PM_MSI_INT_INTD_SHIFT 27 -#define PM_MSI_INT_INTX_MASK 0x0f000000u -#define PM_MSI_INT_INTX_SHIFT 24 -#define PM_MSI_INT_MSI_MASK 0x10000000u -#define PM_MSI_INT_MSI_SHIFT 28 -#define PM_MSI_INT_AER_EVT_MASK 0x20000000u -#define PM_MSI_INT_AER_EVT_SHIFT 29 -#define PM_MSI_INT_EVENTS_MASK 0x40000000u -#define PM_MSI_INT_EVENTS_SHIFT 30 -#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u -#define PM_MSI_INT_SYS_ERR_SHIFT 31 -#define NUM_LOCAL_EVENTS 15 -#define ISTATUS_LOCAL 0x184 -#define IMASK_HOST 0x188 -#define ISTATUS_HOST 0x18c -#define IMSI_ADDR 0x190 -#define ISTATUS_MSI 0x194 - -/* PCIe Master table init defines */ -#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u -#define ATR0_PCIE_ATR_SIZE 0x25 -#define ATR0_PCIE_ATR_SIZE_SHIFT 1 -#define ATR0_PCIE_WIN0_SRC_ADDR 0x604u -#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u -#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu -#define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u - -/* PCIe AXI slave table init defines */ -#define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u -#define ATR_SIZE_SHIFT 1 -#define ATR_IMPL_ENABLE 1 -#define ATR0_AXI4_SLV0_SRC_ADDR 0x804u -#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u -#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu -#define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u -#define PCIE_TX_RX_INTERFACE 0x00000000u -#define PCIE_CONFIG_INTERFACE 0x00000001u - -#define ATR_ENTRY_SIZE 32 - /* PCIe Controller Phy Regs */ #define SEC_ERROR_EVENT_CNT 0x20 #define DED_ERROR_EVENT_CNT 0x24 @@ -179,20 +99,21 @@ #define EVENT_LOCAL_DMA_END_ENGINE_1 12 #define EVENT_LOCAL_DMA_ERROR_ENGINE_0 13 #define EVENT_LOCAL_DMA_ERROR_ENGINE_1 14 -#define EVENT_LOCAL_A_ATR_EVT_POST_ERR 15 -#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR 16 -#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR 17 -#define EVENT_LOCAL_A_ATR_EVT_DOORBELL 18 -#define EVENT_LOCAL_P_ATR_EVT_POST_ERR 19 -#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR 20 -#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR 21 -#define EVENT_LOCAL_P_ATR_EVT_DOORBELL 22 -#define EVENT_LOCAL_PM_MSI_INT_INTX 23 -#define EVENT_LOCAL_PM_MSI_INT_MSI 24 -#define EVENT_LOCAL_PM_MSI_INT_AER_EVT 25 -#define EVENT_LOCAL_PM_MSI_INT_EVENTS 26 -#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR 27 -#define NUM_EVENTS 28 +#define NUM_MC_EVENTS 15 +#define EVENT_LOCAL_A_ATR_EVT_POST_ERR (NUM_MC_EVENTS + PLDA_AXI_POST_ERR) +#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR (NUM_MC_EVENTS + PLDA_AXI_FETCH_ERR) +#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR (NUM_MC_EVENTS + PLDA_AXI_DISCARD_ERR) +#define EVENT_LOCAL_A_ATR_EVT_DOORBELL (NUM_MC_EVENTS + PLDA_AXI_DOORBELL) +#define EVENT_LOCAL_P_ATR_EVT_POST_ERR (NUM_MC_EVENTS + PLDA_PCIE_POST_ERR) +#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR (NUM_MC_EVENTS + PLDA_PCIE_FETCH_ERR) +#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR (NUM_MC_EVENTS + PLDA_PCIE_DISCARD_ERR) +#define EVENT_LOCAL_P_ATR_EVT_DOORBELL (NUM_MC_EVENTS + PLDA_PCIE_DOORBELL) +#define EVENT_LOCAL_PM_MSI_INT_INTX (NUM_MC_EVENTS + PLDA_INTX) +#define EVENT_LOCAL_PM_MSI_INT_MSI (NUM_MC_EVENTS + PLDA_MSI) +#define EVENT_LOCAL_PM_MSI_INT_AER_EVT (NUM_MC_EVENTS + PLDA_AER_EVENT) +#define EVENT_LOCAL_PM_MSI_INT_EVENTS (NUM_MC_EVENTS + PLDA_MISC_EVENTS) +#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR (NUM_MC_EVENTS + PLDA_SYS_ERR) +#define NUM_EVENTS (NUM_MC_EVENTS + PLDA_INT_EVENT_NUM) #define PCIE_EVENT_CAUSE(x, s) \ [EVENT_PCIE_ ## x] = { __stringify(x), s } @@ -255,22 +176,10 @@ struct event_map { u32 event_bit; }; -struct mc_msi { - struct mutex lock; /* Protect used bitmap */ - struct irq_domain *msi_domain; - struct irq_domain *dev_domain; - u32 num_vectors; - u64 vector_phy; - DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS); -}; struct mc_pcie { + struct plda_pcie_rp plda; void __iomem *axi_base_addr; - struct device *dev; - struct irq_domain *intx_domain; - struct irq_domain *event_domain; - raw_spinlock_t lock; - struct mc_msi msi; }; struct cause { @@ -388,7 +297,7 @@ static struct mc_pcie *port; static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam) { - struct mc_msi *msi = &port->msi; + struct plda_msi *msi = &port->plda.msi; u16 reg; u8 queue_size; @@ -409,246 +318,6 @@ static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam) ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI); } -static void mc_handle_msi(struct irq_desc *desc) -{ - struct mc_pcie *port = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); - struct device *dev = port->dev; - struct mc_msi *msi = &port->msi; - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - unsigned long status; - u32 bit; - int ret; - - chained_irq_enter(chip, desc); - - status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL); - if (status & PM_MSI_INT_MSI_MASK) { - writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL); - status = readl_relaxed(bridge_base_addr + ISTATUS_MSI); - for_each_set_bit(bit, &status, msi->num_vectors) { - ret = generic_handle_domain_irq(msi->dev_domain, bit); - if (ret) - dev_err_ratelimited(dev, "bad MSI IRQ %d\n", - bit); - } - } - - chained_irq_exit(chip, desc); -} - -static void mc_msi_bottom_irq_ack(struct irq_data *data) -{ - struct mc_pcie *port = irq_data_get_irq_chip_data(data); - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - u32 bitpos = data->hwirq; - - writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI); -} - -static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) -{ - struct mc_pcie *port = irq_data_get_irq_chip_data(data); - phys_addr_t addr = port->msi.vector_phy; - - msg->address_lo = lower_32_bits(addr); - msg->address_hi = upper_32_bits(addr); - msg->data = data->hwirq; - - dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n", - (int)data->hwirq, msg->address_hi, msg->address_lo); -} - -static int mc_msi_set_affinity(struct irq_data *irq_data, - const struct cpumask *mask, bool force) -{ - return -EINVAL; -} - -static struct irq_chip mc_msi_bottom_irq_chip = { - .name = "Microchip MSI", - .irq_ack = mc_msi_bottom_irq_ack, - .irq_compose_msi_msg = mc_compose_msi_msg, - .irq_set_affinity = mc_msi_set_affinity, -}; - -static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs, void *args) -{ - struct mc_pcie *port = domain->host_data; - struct mc_msi *msi = &port->msi; - unsigned long bit; - - mutex_lock(&msi->lock); - bit = find_first_zero_bit(msi->used, msi->num_vectors); - if (bit >= msi->num_vectors) { - mutex_unlock(&msi->lock); - return -ENOSPC; - } - - set_bit(bit, msi->used); - - irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip, - domain->host_data, handle_edge_irq, NULL, NULL); - - mutex_unlock(&msi->lock); - - return 0; -} - -static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs) -{ - struct irq_data *d = irq_domain_get_irq_data(domain, virq); - struct mc_pcie *port = irq_data_get_irq_chip_data(d); - struct mc_msi *msi = &port->msi; - - mutex_lock(&msi->lock); - - if (test_bit(d->hwirq, msi->used)) - __clear_bit(d->hwirq, msi->used); - else - dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq); - - mutex_unlock(&msi->lock); -} - -static const struct irq_domain_ops msi_domain_ops = { - .alloc = mc_irq_msi_domain_alloc, - .free = mc_irq_msi_domain_free, -}; - -static struct irq_chip mc_msi_irq_chip = { - .name = "Microchip PCIe MSI", - .irq_ack = irq_chip_ack_parent, - .irq_mask = pci_msi_mask_irq, - .irq_unmask = pci_msi_unmask_irq, -}; - -static struct msi_domain_info mc_msi_domain_info = { - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_PCI_MSIX), - .chip = &mc_msi_irq_chip, -}; - -static int mc_allocate_msi_domains(struct mc_pcie *port) -{ - struct device *dev = port->dev; - struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); - struct mc_msi *msi = &port->msi; - - mutex_init(&port->msi.lock); - - msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors, - &msi_domain_ops, port); - if (!msi->dev_domain) { - dev_err(dev, "failed to create IRQ domain\n"); - return -ENOMEM; - } - - msi->msi_domain = pci_msi_create_irq_domain(fwnode, &mc_msi_domain_info, - msi->dev_domain); - if (!msi->msi_domain) { - dev_err(dev, "failed to create MSI domain\n"); - irq_domain_remove(msi->dev_domain); - return -ENOMEM; - } - - return 0; -} - -static void mc_handle_intx(struct irq_desc *desc) -{ - struct mc_pcie *port = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); - struct device *dev = port->dev; - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - unsigned long status; - u32 bit; - int ret; - - chained_irq_enter(chip, desc); - - status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL); - if (status & PM_MSI_INT_INTX_MASK) { - status &= PM_MSI_INT_INTX_MASK; - status >>= PM_MSI_INT_INTX_SHIFT; - for_each_set_bit(bit, &status, PCI_NUM_INTX) { - ret = generic_handle_domain_irq(port->intx_domain, bit); - if (ret) - dev_err_ratelimited(dev, "bad INTx IRQ %d\n", - bit); - } - } - - chained_irq_exit(chip, desc); -} - -static void mc_ack_intx_irq(struct irq_data *data) -{ - struct mc_pcie *port = irq_data_get_irq_chip_data(data); - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); - - writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL); -} - -static void mc_mask_intx_irq(struct irq_data *data) -{ - struct mc_pcie *port = irq_data_get_irq_chip_data(data); - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - unsigned long flags; - u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); - u32 val; - - raw_spin_lock_irqsave(&port->lock, flags); - val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); - val &= ~mask; - writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); - raw_spin_unlock_irqrestore(&port->lock, flags); -} - -static void mc_unmask_intx_irq(struct irq_data *data) -{ - struct mc_pcie *port = irq_data_get_irq_chip_data(data); - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - unsigned long flags; - u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); - u32 val; - - raw_spin_lock_irqsave(&port->lock, flags); - val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); - val |= mask; - writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); - raw_spin_unlock_irqrestore(&port->lock, flags); -} - -static struct irq_chip mc_intx_irq_chip = { - .name = "Microchip PCIe INTx", - .irq_ack = mc_ack_intx_irq, - .irq_mask = mc_mask_intx_irq, - .irq_unmask = mc_unmask_intx_irq, -}; - -static int mc_pcie_intx_map(struct irq_domain *domain, unsigned int irq, - irq_hw_number_t hwirq) -{ - irq_set_chip_and_handler(irq, &mc_intx_irq_chip, handle_level_irq); - irq_set_chip_data(irq, domain->host_data); - - return 0; -} - -static const struct irq_domain_ops intx_domain_ops = { - .map = mc_pcie_intx_map, -}; - static inline u32 reg_to_event(u32 reg, struct event_map field) { return (reg & field.reg_mask) ? BIT(field.event_bit) : 0; @@ -706,21 +375,22 @@ static u32 local_events(struct mc_pcie *port) return val; } -static u32 get_events(struct mc_pcie *port) +static u32 mc_get_events(struct plda_pcie_rp *port) { + struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda); u32 events = 0; - events |= pcie_events(port); - events |= sec_errors(port); - events |= ded_errors(port); - events |= local_events(port); + events |= pcie_events(mc_port); + events |= sec_errors(mc_port); + events |= ded_errors(mc_port); + events |= local_events(mc_port); return events; } static irqreturn_t mc_event_handler(int irq, void *dev_id) { - struct mc_pcie *port = dev_id; + struct plda_pcie_rp *port = dev_id; struct device *dev = port->dev; struct irq_data *data; @@ -734,31 +404,15 @@ static irqreturn_t mc_event_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static void mc_handle_event(struct irq_desc *desc) -{ - struct mc_pcie *port = irq_desc_get_handler_data(desc); - unsigned long events; - u32 bit; - struct irq_chip *chip = irq_desc_get_chip(desc); - - chained_irq_enter(chip, desc); - - events = get_events(port); - - for_each_set_bit(bit, &events, NUM_EVENTS) - generic_handle_domain_irq(port->event_domain, bit); - - chained_irq_exit(chip, desc); -} - static void mc_ack_event_irq(struct irq_data *data) { - struct mc_pcie *port = irq_data_get_irq_chip_data(data); + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda); u32 event = data->hwirq; void __iomem *addr; u32 mask; - addr = port->axi_base_addr + event_descs[event].base + + addr = mc_port->axi_base_addr + event_descs[event].base + event_descs[event].offset; mask = event_descs[event].mask; mask |= event_descs[event].enb_mask; @@ -768,13 +422,14 @@ static void mc_ack_event_irq(struct irq_data *data) static void mc_mask_event_irq(struct irq_data *data) { - struct mc_pcie *port = irq_data_get_irq_chip_data(data); + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda); u32 event = data->hwirq; void __iomem *addr; u32 mask; u32 val; - addr = port->axi_base_addr + event_descs[event].base + + addr = mc_port->axi_base_addr + event_descs[event].base + event_descs[event].mask_offset; mask = event_descs[event].mask; if (event_descs[event].enb_mask) { @@ -798,13 +453,14 @@ static void mc_mask_event_irq(struct irq_data *data) static void mc_unmask_event_irq(struct irq_data *data) { - struct mc_pcie *port = irq_data_get_irq_chip_data(data); + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda); u32 event = data->hwirq; void __iomem *addr; u32 mask; u32 val; - addr = port->axi_base_addr + event_descs[event].base + + addr = mc_port->axi_base_addr + event_descs[event].base + event_descs[event].mask_offset; mask = event_descs[event].mask; @@ -834,19 +490,6 @@ static struct irq_chip mc_event_irq_chip = { .irq_unmask = mc_unmask_event_irq, }; -static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq, - irq_hw_number_t hwirq) -{ - irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq); - irq_set_chip_data(irq, domain->host_data); - - return 0; -} - -static const struct irq_domain_ops event_domain_ops = { - .map = mc_pcie_event_map, -}; - static inline void mc_pcie_deinit_clk(void *data) { struct clk *clk = data; @@ -892,105 +535,22 @@ static int mc_pcie_init_clks(struct device *dev) return 0; } -static int mc_pcie_init_irq_domains(struct mc_pcie *port) +static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq, + int event) { - struct device *dev = port->dev; - struct device_node *node = dev->of_node; - struct device_node *pcie_intc_node; - - /* Setup INTx */ - pcie_intc_node = of_get_next_child(node, NULL); - if (!pcie_intc_node) { - dev_err(dev, "failed to find PCIe Intc node\n"); - return -EINVAL; - } - - port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS, - &event_domain_ops, port); - if (!port->event_domain) { - dev_err(dev, "failed to get event domain\n"); - of_node_put(pcie_intc_node); - return -ENOMEM; - } - - irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS); - - port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, - &intx_domain_ops, port); - if (!port->intx_domain) { - dev_err(dev, "failed to get an INTx IRQ domain\n"); - of_node_put(pcie_intc_node); - return -ENOMEM; - } - - irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED); - - of_node_put(pcie_intc_node); - raw_spin_lock_init(&port->lock); - - return mc_allocate_msi_domains(port); + return devm_request_irq(plda->dev, event_irq, mc_event_handler, + 0, event_cause[event].sym, plda); } -static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, - phys_addr_t axi_addr, phys_addr_t pci_addr, - size_t size) -{ - u32 atr_sz = ilog2(size) - 1; - u32 val; +static const struct plda_event_ops mc_event_ops = { + .get_events = mc_get_events, +}; - if (index == 0) - val = PCIE_CONFIG_INTERFACE; - else - val = PCIE_TX_RX_INTERFACE; - - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + - ATR0_AXI4_SLV0_TRSL_PARAM); - - val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) | - ATR_IMPL_ENABLE; - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + - ATR0_AXI4_SLV0_SRCADDR_PARAM); - - val = upper_32_bits(axi_addr); - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + - ATR0_AXI4_SLV0_SRC_ADDR); - - val = lower_32_bits(pci_addr); - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + - ATR0_AXI4_SLV0_TRSL_ADDR_LSB); - - val = upper_32_bits(pci_addr); - writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + - ATR0_AXI4_SLV0_TRSL_ADDR_UDW); - - val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); - val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT); - writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); - writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR); -} - -static int mc_pcie_setup_windows(struct platform_device *pdev, - struct mc_pcie *port) -{ - void __iomem *bridge_base_addr = - port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; - struct pci_host_bridge *bridge = platform_get_drvdata(pdev); - struct resource_entry *entry; - u64 pci_addr; - u32 index = 1; - - resource_list_for_each_entry(entry, &bridge->windows) { - if (resource_type(entry->res) == IORESOURCE_MEM) { - pci_addr = entry->res->start - entry->offset; - mc_pcie_setup_window(bridge_base_addr, index, - entry->res->start, pci_addr, - resource_size(entry->res)); - index++; - } - } - - return 0; -} +static const struct plda_event mc_event = { + .request_event_irq = mc_request_event_irq, + .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX, + .msi_event = EVENT_LOCAL_PM_MSI_INT_MSI, +}; static inline void mc_clear_secs(struct mc_pcie *port) { @@ -1052,85 +612,34 @@ static void mc_disable_interrupts(struct mc_pcie *port) writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST); } -static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port) -{ - struct device *dev = &pdev->dev; - int irq; - int i, intx_irq, msi_irq, event_irq; - int ret; - - ret = mc_pcie_init_irq_domains(port); - if (ret) { - dev_err(dev, "failed creating IRQ domains\n"); - return ret; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return -ENODEV; - - for (i = 0; i < NUM_EVENTS; i++) { - event_irq = irq_create_mapping(port->event_domain, i); - if (!event_irq) { - dev_err(dev, "failed to map hwirq %d\n", i); - return -ENXIO; - } - - ret = devm_request_irq(dev, event_irq, mc_event_handler, - 0, event_cause[i].sym, port); - if (ret) { - dev_err(dev, "failed to request IRQ %d\n", event_irq); - return ret; - } - } - - intx_irq = irq_create_mapping(port->event_domain, - EVENT_LOCAL_PM_MSI_INT_INTX); - if (!intx_irq) { - dev_err(dev, "failed to map INTx interrupt\n"); - return -ENXIO; - } - - /* Plug the INTx chained handler */ - irq_set_chained_handler_and_data(intx_irq, mc_handle_intx, port); - - msi_irq = irq_create_mapping(port->event_domain, - EVENT_LOCAL_PM_MSI_INT_MSI); - if (!msi_irq) - return -ENXIO; - - /* Plug the MSI chained handler */ - irq_set_chained_handler_and_data(msi_irq, mc_handle_msi, port); - - /* Plug the main event chained handler */ - irq_set_chained_handler_and_data(irq, mc_handle_event, port); - - return 0; -} - static int mc_platform_init(struct pci_config_window *cfg) { struct device *dev = cfg->parent; struct platform_device *pdev = to_platform_device(dev); + struct pci_host_bridge *bridge = platform_get_drvdata(pdev); void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; int ret; /* Configure address translation table 0 for PCIe config space */ - mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start, - cfg->res.start, - resource_size(&cfg->res)); + plda_pcie_setup_window(bridge_base_addr, 0, cfg->res.start, + cfg->res.start, + resource_size(&cfg->res)); /* Need some fixups in config space */ mc_pcie_enable_msi(port, cfg->win); /* Configure non-config space outbound ranges */ - ret = mc_pcie_setup_windows(pdev, port); + ret = plda_pcie_setup_iomems(bridge, &port->plda); if (ret) return ret; + port->plda.event_ops = &mc_event_ops; + port->plda.event_irq_chip = &mc_event_irq_chip; + port->plda.events_bitmap = GENMASK(NUM_EVENTS - 1, 0); + /* Address translation is up; safe to enable interrupts */ - ret = mc_init_interrupts(pdev, port); + ret = plda_init_interrupts(pdev, &port->plda, &mc_event); if (ret) return ret; @@ -1141,6 +650,7 @@ static int mc_host_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; void __iomem *bridge_base_addr; + struct plda_pcie_rp *plda; int ret; u32 val; @@ -1148,7 +658,8 @@ static int mc_host_probe(struct platform_device *pdev) if (!port) return -ENOMEM; - port->dev = dev; + plda = &port->plda; + plda->dev = dev; port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(port->axi_base_addr)) @@ -1157,6 +668,8 @@ static int mc_host_probe(struct platform_device *pdev) mc_disable_interrupts(port); bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR; + plda->bridge_addr = bridge_base_addr; + plda->num_events = NUM_EVENTS; /* Allow enabling MSI by disabling MSI-X */ val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0); @@ -1168,10 +681,10 @@ static int mc_host_probe(struct platform_device *pdev) val &= NUM_MSI_MSGS_MASK; val >>= NUM_MSI_MSGS_SHIFT; - port->msi.num_vectors = 1 << val; + plda->msi.num_vectors = 1 << val; /* Pick vector address from design */ - port->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR); + plda->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR); ret = mc_pcie_init_clks(dev); if (ret) { diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c new file mode 100644 index 000000000000..a18923d7cea6 --- /dev/null +++ b/drivers/pci/controller/plda/pcie-plda-host.c @@ -0,0 +1,651 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PLDA PCIe XpressRich host controller driver + * + * Copyright (C) 2023 Microchip Co. Ltd + * StarFive Co. Ltd + * + * Author: Daire McNamara + */ + +#include +#include +#include +#include +#include + +#include "pcie-plda.h" + +void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, + int where) +{ + struct plda_pcie_rp *pcie = bus->sysdata; + + return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where); +} +EXPORT_SYMBOL_GPL(plda_pcie_map_bus); + +static void plda_handle_msi(struct irq_desc *desc) +{ + struct plda_pcie_rp *port = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + struct device *dev = port->dev; + struct plda_msi *msi = &port->msi; + void __iomem *bridge_base_addr = port->bridge_addr; + unsigned long status; + u32 bit; + int ret; + + chained_irq_enter(chip, desc); + + status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL); + if (status & PM_MSI_INT_MSI_MASK) { + writel_relaxed(status & PM_MSI_INT_MSI_MASK, + bridge_base_addr + ISTATUS_LOCAL); + status = readl_relaxed(bridge_base_addr + ISTATUS_MSI); + for_each_set_bit(bit, &status, msi->num_vectors) { + ret = generic_handle_domain_irq(msi->dev_domain, bit); + if (ret) + dev_err_ratelimited(dev, "bad MSI IRQ %d\n", + bit); + } + } + + chained_irq_exit(chip, desc); +} + +static void plda_msi_bottom_irq_ack(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + void __iomem *bridge_base_addr = port->bridge_addr; + u32 bitpos = data->hwirq; + + writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI); +} + +static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + phys_addr_t addr = port->msi.vector_phy; + + msg->address_lo = lower_32_bits(addr); + msg->address_hi = upper_32_bits(addr); + msg->data = data->hwirq; + + dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n", + (int)data->hwirq, msg->address_hi, msg->address_lo); +} + +static int plda_msi_set_affinity(struct irq_data *irq_data, + const struct cpumask *mask, bool force) +{ + return -EINVAL; +} + +static struct irq_chip plda_msi_bottom_irq_chip = { + .name = "PLDA MSI", + .irq_ack = plda_msi_bottom_irq_ack, + .irq_compose_msi_msg = plda_compose_msi_msg, + .irq_set_affinity = plda_msi_set_affinity, +}; + +static int plda_irq_msi_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs, + void *args) +{ + struct plda_pcie_rp *port = domain->host_data; + struct plda_msi *msi = &port->msi; + unsigned long bit; + + mutex_lock(&msi->lock); + bit = find_first_zero_bit(msi->used, msi->num_vectors); + if (bit >= msi->num_vectors) { + mutex_unlock(&msi->lock); + return -ENOSPC; + } + + set_bit(bit, msi->used); + + irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip, + domain->host_data, handle_edge_irq, NULL, NULL); + + mutex_unlock(&msi->lock); + + return 0; +} + +static void plda_irq_msi_domain_free(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs) +{ + struct irq_data *d = irq_domain_get_irq_data(domain, virq); + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d); + struct plda_msi *msi = &port->msi; + + mutex_lock(&msi->lock); + + if (test_bit(d->hwirq, msi->used)) + __clear_bit(d->hwirq, msi->used); + else + dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq); + + mutex_unlock(&msi->lock); +} + +static const struct irq_domain_ops msi_domain_ops = { + .alloc = plda_irq_msi_domain_alloc, + .free = plda_irq_msi_domain_free, +}; + +static struct irq_chip plda_msi_irq_chip = { + .name = "PLDA PCIe MSI", + .irq_ack = irq_chip_ack_parent, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, +}; + +static struct msi_domain_info plda_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_PCI_MSIX), + .chip = &plda_msi_irq_chip, +}; + +static int plda_allocate_msi_domains(struct plda_pcie_rp *port) +{ + struct device *dev = port->dev; + struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); + struct plda_msi *msi = &port->msi; + + mutex_init(&port->msi.lock); + + msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors, + &msi_domain_ops, port); + if (!msi->dev_domain) { + dev_err(dev, "failed to create IRQ domain\n"); + return -ENOMEM; + } + + msi->msi_domain = pci_msi_create_irq_domain(fwnode, + &plda_msi_domain_info, + msi->dev_domain); + if (!msi->msi_domain) { + dev_err(dev, "failed to create MSI domain\n"); + irq_domain_remove(msi->dev_domain); + return -ENOMEM; + } + + return 0; +} + +static void plda_handle_intx(struct irq_desc *desc) +{ + struct plda_pcie_rp *port = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + struct device *dev = port->dev; + void __iomem *bridge_base_addr = port->bridge_addr; + unsigned long status; + u32 bit; + int ret; + + chained_irq_enter(chip, desc); + + status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL); + if (status & PM_MSI_INT_INTX_MASK) { + status &= PM_MSI_INT_INTX_MASK; + status >>= PM_MSI_INT_INTX_SHIFT; + for_each_set_bit(bit, &status, PCI_NUM_INTX) { + ret = generic_handle_domain_irq(port->intx_domain, bit); + if (ret) + dev_err_ratelimited(dev, "bad INTx IRQ %d\n", + bit); + } + } + + chained_irq_exit(chip, desc); +} + +static void plda_ack_intx_irq(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + void __iomem *bridge_base_addr = port->bridge_addr; + u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); + + writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL); +} + +static void plda_mask_intx_irq(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + void __iomem *bridge_base_addr = port->bridge_addr; + unsigned long flags; + u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); + u32 val; + + raw_spin_lock_irqsave(&port->lock, flags); + val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); + val &= ~mask; + writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); + raw_spin_unlock_irqrestore(&port->lock, flags); +} + +static void plda_unmask_intx_irq(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + void __iomem *bridge_base_addr = port->bridge_addr; + unsigned long flags; + u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); + u32 val; + + raw_spin_lock_irqsave(&port->lock, flags); + val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); + val |= mask; + writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); + raw_spin_unlock_irqrestore(&port->lock, flags); +} + +static struct irq_chip plda_intx_irq_chip = { + .name = "PLDA PCIe INTx", + .irq_ack = plda_ack_intx_irq, + .irq_mask = plda_mask_intx_irq, + .irq_unmask = plda_unmask_intx_irq, +}; + +static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq); + irq_set_chip_data(irq, domain->host_data); + + return 0; +} + +static const struct irq_domain_ops intx_domain_ops = { + .map = plda_pcie_intx_map, +}; + +static u32 plda_get_events(struct plda_pcie_rp *port) +{ + u32 events, val, origin; + + origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL); + + /* MSI event and sys events */ + val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT; + events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1); + + /* INTx events */ + if (origin & PM_MSI_INT_INTX_MASK) + events |= BIT(PM_MSI_INT_INTX_SHIFT); + + /* remains are same with register */ + events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0); + + return events; +} + +static irqreturn_t plda_event_handler(int irq, void *dev_id) +{ + return IRQ_HANDLED; +} + +static void plda_handle_event(struct irq_desc *desc) +{ + struct plda_pcie_rp *port = irq_desc_get_handler_data(desc); + unsigned long events; + u32 bit; + struct irq_chip *chip = irq_desc_get_chip(desc); + + chained_irq_enter(chip, desc); + + events = port->event_ops->get_events(port); + + events &= port->events_bitmap; + for_each_set_bit(bit, &events, port->num_events) + generic_handle_domain_irq(port->event_domain, bit); + + chained_irq_exit(chip, desc); +} + +static u32 plda_hwirq_to_mask(int hwirq) +{ + u32 mask; + + /* hwirq 23 - 0 are the same with register */ + if (hwirq < EVENT_PM_MSI_INT_INTX) + mask = BIT(hwirq); + else if (hwirq == EVENT_PM_MSI_INT_INTX) + mask = PM_MSI_INT_INTX_MASK; + else + mask = BIT(hwirq + PCI_NUM_INTX - 1); + + return mask; +} + +static void plda_ack_event_irq(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + + writel_relaxed(plda_hwirq_to_mask(data->hwirq), + port->bridge_addr + ISTATUS_LOCAL); +} + +static void plda_mask_event_irq(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + u32 mask, val; + + mask = plda_hwirq_to_mask(data->hwirq); + + raw_spin_lock(&port->lock); + val = readl_relaxed(port->bridge_addr + IMASK_LOCAL); + val &= ~mask; + writel_relaxed(val, port->bridge_addr + IMASK_LOCAL); + raw_spin_unlock(&port->lock); +} + +static void plda_unmask_event_irq(struct irq_data *data) +{ + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); + u32 mask, val; + + mask = plda_hwirq_to_mask(data->hwirq); + + raw_spin_lock(&port->lock); + val = readl_relaxed(port->bridge_addr + IMASK_LOCAL); + val |= mask; + writel_relaxed(val, port->bridge_addr + IMASK_LOCAL); + raw_spin_unlock(&port->lock); +} + +static struct irq_chip plda_event_irq_chip = { + .name = "PLDA PCIe EVENT", + .irq_ack = plda_ack_event_irq, + .irq_mask = plda_mask_event_irq, + .irq_unmask = plda_unmask_event_irq, +}; + +static const struct plda_event_ops plda_event_ops = { + .get_events = plda_get_events, +}; + +static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct plda_pcie_rp *port = (void *)domain->host_data; + + irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq); + irq_set_chip_data(irq, domain->host_data); + + return 0; +} + +static const struct irq_domain_ops plda_event_domain_ops = { + .map = plda_pcie_event_map, +}; + +static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port) +{ + struct device *dev = port->dev; + struct device_node *node = dev->of_node; + struct device_node *pcie_intc_node; + + /* Setup INTx */ + pcie_intc_node = of_get_next_child(node, NULL); + if (!pcie_intc_node) { + dev_err(dev, "failed to find PCIe Intc node\n"); + return -EINVAL; + } + + port->event_domain = irq_domain_add_linear(pcie_intc_node, + port->num_events, + &plda_event_domain_ops, + port); + if (!port->event_domain) { + dev_err(dev, "failed to get event domain\n"); + of_node_put(pcie_intc_node); + return -ENOMEM; + } + + irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS); + + port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, + &intx_domain_ops, port); + if (!port->intx_domain) { + dev_err(dev, "failed to get an INTx IRQ domain\n"); + of_node_put(pcie_intc_node); + return -ENOMEM; + } + + irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED); + + of_node_put(pcie_intc_node); + raw_spin_lock_init(&port->lock); + + return plda_allocate_msi_domains(port); +} + +int plda_init_interrupts(struct platform_device *pdev, + struct plda_pcie_rp *port, + const struct plda_event *event) +{ + struct device *dev = &pdev->dev; + int event_irq, ret; + u32 i; + + if (!port->event_ops) + port->event_ops = &plda_event_ops; + + if (!port->event_irq_chip) + port->event_irq_chip = &plda_event_irq_chip; + + ret = plda_pcie_init_irq_domains(port); + if (ret) { + dev_err(dev, "failed creating IRQ domains\n"); + return ret; + } + + port->irq = platform_get_irq(pdev, 0); + if (port->irq < 0) + return -ENODEV; + + for_each_set_bit(i, &port->events_bitmap, port->num_events) { + event_irq = irq_create_mapping(port->event_domain, i); + if (!event_irq) { + dev_err(dev, "failed to map hwirq %d\n", i); + return -ENXIO; + } + + if (event->request_event_irq) + ret = event->request_event_irq(port, event_irq, i); + else + ret = devm_request_irq(dev, event_irq, + plda_event_handler, + 0, NULL, port); + + if (ret) { + dev_err(dev, "failed to request IRQ %d\n", event_irq); + return ret; + } + } + + port->intx_irq = irq_create_mapping(port->event_domain, + event->intx_event); + if (!port->intx_irq) { + dev_err(dev, "failed to map INTx interrupt\n"); + return -ENXIO; + } + + /* Plug the INTx chained handler */ + irq_set_chained_handler_and_data(port->intx_irq, plda_handle_intx, port); + + port->msi_irq = irq_create_mapping(port->event_domain, + event->msi_event); + if (!port->msi_irq) + return -ENXIO; + + /* Plug the MSI chained handler */ + irq_set_chained_handler_and_data(port->msi_irq, plda_handle_msi, port); + + /* Plug the main event chained handler */ + irq_set_chained_handler_and_data(port->irq, plda_handle_event, port); + + return 0; +} +EXPORT_SYMBOL_GPL(plda_init_interrupts); + +void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, + phys_addr_t axi_addr, phys_addr_t pci_addr, + size_t size) +{ + u32 atr_sz = ilog2(size) - 1; + u32 val; + + if (index == 0) + val = PCIE_CONFIG_INTERFACE; + else + val = PCIE_TX_RX_INTERFACE; + + writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + ATR0_AXI4_SLV0_TRSL_PARAM); + + val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) | + ATR_IMPL_ENABLE; + writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + ATR0_AXI4_SLV0_SRCADDR_PARAM); + + val = upper_32_bits(axi_addr); + writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + ATR0_AXI4_SLV0_SRC_ADDR); + + val = lower_32_bits(pci_addr); + writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + ATR0_AXI4_SLV0_TRSL_ADDR_LSB); + + val = upper_32_bits(pci_addr); + writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + + ATR0_AXI4_SLV0_TRSL_ADDR_UDW); + + val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); + val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT); + writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); + writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR); +} +EXPORT_SYMBOL_GPL(plda_pcie_setup_window); + +int plda_pcie_setup_iomems(struct pci_host_bridge *bridge, + struct plda_pcie_rp *port) +{ + void __iomem *bridge_base_addr = port->bridge_addr; + struct resource_entry *entry; + u64 pci_addr; + u32 index = 1; + + resource_list_for_each_entry(entry, &bridge->windows) { + if (resource_type(entry->res) == IORESOURCE_MEM) { + pci_addr = entry->res->start - entry->offset; + plda_pcie_setup_window(bridge_base_addr, index, + entry->res->start, pci_addr, + resource_size(entry->res)); + index++; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems); + +static void plda_pcie_irq_domain_deinit(struct plda_pcie_rp *pcie) +{ + irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); + irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL); + irq_set_chained_handler_and_data(pcie->intx_irq, NULL, NULL); + + irq_domain_remove(pcie->msi.msi_domain); + irq_domain_remove(pcie->msi.dev_domain); + + irq_domain_remove(pcie->intx_domain); + irq_domain_remove(pcie->event_domain); +} + +int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops, + const struct plda_event *plda_event) +{ + struct device *dev = port->dev; + struct pci_host_bridge *bridge; + struct platform_device *pdev = to_platform_device(dev); + struct resource *cfg_res; + int ret; + + pdev = to_platform_device(dev); + + port->bridge_addr = + devm_platform_ioremap_resource_byname(pdev, "apb"); + + if (IS_ERR(port->bridge_addr)) + return dev_err_probe(dev, PTR_ERR(port->bridge_addr), + "failed to map reg memory\n"); + + cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg"); + if (!cfg_res) + return dev_err_probe(dev, -ENODEV, + "failed to get config memory\n"); + + port->config_base = devm_ioremap_resource(dev, cfg_res); + if (IS_ERR(port->config_base)) + return dev_err_probe(dev, PTR_ERR(port->config_base), + "failed to map config memory\n"); + + bridge = devm_pci_alloc_host_bridge(dev, 0); + if (!bridge) + return dev_err_probe(dev, -ENOMEM, + "failed to alloc bridge\n"); + + if (port->host_ops && port->host_ops->host_init) { + ret = port->host_ops->host_init(port); + if (ret) + return ret; + } + + port->bridge = bridge; + plda_pcie_setup_window(port->bridge_addr, 0, cfg_res->start, 0, + resource_size(cfg_res)); + plda_pcie_setup_iomems(bridge, port); + plda_set_default_msi(&port->msi); + ret = plda_init_interrupts(pdev, port, plda_event); + if (ret) + goto err_host; + + /* Set default bus ops */ + bridge->ops = ops; + bridge->sysdata = port; + + ret = pci_host_probe(bridge); + if (ret < 0) { + dev_err_probe(dev, ret, "failed to probe pci host\n"); + goto err_probe; + } + + return ret; + +err_probe: + plda_pcie_irq_domain_deinit(port); +err_host: + if (port->host_ops && port->host_ops->host_deinit) + port->host_ops->host_deinit(port); + + return ret; +} +EXPORT_SYMBOL_GPL(plda_pcie_host_init); + +void plda_pcie_host_deinit(struct plda_pcie_rp *port) +{ + pci_stop_root_bus(port->bridge->bus); + pci_remove_root_bus(port->bridge->bus); + + plda_pcie_irq_domain_deinit(port); + + if (port->host_ops && port->host_ops->host_deinit) + port->host_ops->host_deinit(port); +} +EXPORT_SYMBOL_GPL(plda_pcie_host_deinit); diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h new file mode 100644 index 000000000000..0e7dc0d8e5ba --- /dev/null +++ b/drivers/pci/controller/plda/pcie-plda.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PLDA PCIe host controller driver + */ + +#ifndef _PCIE_PLDA_H +#define _PCIE_PLDA_H + +/* Number of MSI IRQs */ +#define PLDA_MAX_NUM_MSI_IRQS 32 + +/* PCIe Bridge Phy Regs */ +#define GEN_SETTINGS 0x80 +#define RP_ENABLE 1 +#define PCIE_PCI_IDS_DW1 0x9c +#define IDS_CLASS_CODE_SHIFT 16 +#define REVISION_ID_MASK GENMASK(7, 0) +#define CLASS_CODE_ID_MASK GENMASK(31, 8) +#define PCIE_PCI_IRQ_DW0 0xa8 +#define MSIX_CAP_MASK BIT(31) +#define NUM_MSI_MSGS_MASK GENMASK(6, 4) +#define NUM_MSI_MSGS_SHIFT 4 +#define PCI_MISC 0xb4 +#define PHY_FUNCTION_DIS BIT(15) +#define PCIE_WINROM 0xfc +#define PREF_MEM_WIN_64_SUPPORT BIT(3) + +#define IMASK_LOCAL 0x180 +#define DMA_END_ENGINE_0_MASK 0x00000000u +#define DMA_END_ENGINE_0_SHIFT 0 +#define DMA_END_ENGINE_1_MASK 0x00000000u +#define DMA_END_ENGINE_1_SHIFT 1 +#define DMA_ERROR_ENGINE_0_MASK 0x00000100u +#define DMA_ERROR_ENGINE_0_SHIFT 8 +#define DMA_ERROR_ENGINE_1_MASK 0x00000200u +#define DMA_ERROR_ENGINE_1_SHIFT 9 +#define A_ATR_EVT_POST_ERR_MASK 0x00010000u +#define A_ATR_EVT_POST_ERR_SHIFT 16 +#define A_ATR_EVT_FETCH_ERR_MASK 0x00020000u +#define A_ATR_EVT_FETCH_ERR_SHIFT 17 +#define A_ATR_EVT_DISCARD_ERR_MASK 0x00040000u +#define A_ATR_EVT_DISCARD_ERR_SHIFT 18 +#define A_ATR_EVT_DOORBELL_MASK 0x00000000u +#define A_ATR_EVT_DOORBELL_SHIFT 19 +#define P_ATR_EVT_POST_ERR_MASK 0x00100000u +#define P_ATR_EVT_POST_ERR_SHIFT 20 +#define P_ATR_EVT_FETCH_ERR_MASK 0x00200000u +#define P_ATR_EVT_FETCH_ERR_SHIFT 21 +#define P_ATR_EVT_DISCARD_ERR_MASK 0x00400000u +#define P_ATR_EVT_DISCARD_ERR_SHIFT 22 +#define P_ATR_EVT_DOORBELL_MASK 0x00000000u +#define P_ATR_EVT_DOORBELL_SHIFT 23 +#define PM_MSI_INT_INTA_MASK 0x01000000u +#define PM_MSI_INT_INTA_SHIFT 24 +#define PM_MSI_INT_INTB_MASK 0x02000000u +#define PM_MSI_INT_INTB_SHIFT 25 +#define PM_MSI_INT_INTC_MASK 0x04000000u +#define PM_MSI_INT_INTC_SHIFT 26 +#define PM_MSI_INT_INTD_MASK 0x08000000u +#define PM_MSI_INT_INTD_SHIFT 27 +#define PM_MSI_INT_INTX_MASK 0x0f000000u +#define PM_MSI_INT_INTX_SHIFT 24 +#define PM_MSI_INT_MSI_MASK 0x10000000u +#define PM_MSI_INT_MSI_SHIFT 28 +#define PM_MSI_INT_AER_EVT_MASK 0x20000000u +#define PM_MSI_INT_AER_EVT_SHIFT 29 +#define PM_MSI_INT_EVENTS_MASK 0x40000000u +#define PM_MSI_INT_EVENTS_SHIFT 30 +#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u +#define PM_MSI_INT_SYS_ERR_SHIFT 31 +#define SYS_AND_MSI_MASK GENMASK(31, 28) +#define NUM_LOCAL_EVENTS 15 +#define ISTATUS_LOCAL 0x184 +#define IMASK_HOST 0x188 +#define ISTATUS_HOST 0x18c +#define IMSI_ADDR 0x190 +#define ISTATUS_MSI 0x194 +#define PMSG_SUPPORT_RX 0x3f0 +#define PMSG_LTR_SUPPORT BIT(2) + +/* PCIe Master table init defines */ +#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u +#define ATR0_PCIE_ATR_SIZE 0x25 +#define ATR0_PCIE_ATR_SIZE_SHIFT 1 +#define ATR0_PCIE_WIN0_SRC_ADDR 0x604u +#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u +#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu +#define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u + +/* PCIe AXI slave table init defines */ +#define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u +#define ATR_SIZE_SHIFT 1 +#define ATR_IMPL_ENABLE 1 +#define ATR0_AXI4_SLV0_SRC_ADDR 0x804u +#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u +#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu +#define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u +#define PCIE_TX_RX_INTERFACE 0x00000000u +#define PCIE_CONFIG_INTERFACE 0x00000001u + +#define CONFIG_SPACE_ADDR_OFFSET 0x1000u + +#define ATR_ENTRY_SIZE 32 + +enum plda_int_event { + PLDA_AXI_POST_ERR, + PLDA_AXI_FETCH_ERR, + PLDA_AXI_DISCARD_ERR, + PLDA_AXI_DOORBELL, + PLDA_PCIE_POST_ERR, + PLDA_PCIE_FETCH_ERR, + PLDA_PCIE_DISCARD_ERR, + PLDA_PCIE_DOORBELL, + PLDA_INTX, + PLDA_MSI, + PLDA_AER_EVENT, + PLDA_MISC_EVENTS, + PLDA_SYS_ERR, + PLDA_INT_EVENT_NUM +}; + +#define PLDA_NUM_DMA_EVENTS 16 + +#define EVENT_PM_MSI_INT_INTX (PLDA_NUM_DMA_EVENTS + PLDA_INTX) +#define EVENT_PM_MSI_INT_MSI (PLDA_NUM_DMA_EVENTS + PLDA_MSI) +#define PLDA_MAX_EVENT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM) + +/* + * PLDA interrupt register + * + * 31 27 23 15 7 0 + * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+ + * |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end | + * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+ + * event bit + * 0-7 (0-7) DMA interrupt end : reserved for vendor implement + * 8-15 (8-15) DMA error : reserved for vendor implement + * 16 (16) AXI post error (PLDA_AXI_POST_ERR) + * 17 (17) AXI fetch error (PLDA_AXI_FETCH_ERR) + * 18 (18) AXI discard error (PLDA_AXI_DISCARD_ERR) + * 19 (19) AXI doorbell (PLDA_PCIE_DOORBELL) + * 20 (20) PCIe post error (PLDA_PCIE_POST_ERR) + * 21 (21) PCIe fetch error (PLDA_PCIE_FETCH_ERR) + * 22 (22) PCIe discard error (PLDA_PCIE_DISCARD_ERR) + * 23 (23) PCIe doorbell (PLDA_PCIE_DOORBELL) + * 24 (27-24) INTx interruts (PLDA_INTX) + * 25 (28): MSI interrupt (PLDA_MSI) + * 26 (29): AER event (PLDA_AER_EVENT) + * 27 (30): PM/LTR/Hotplug (PLDA_MISC_EVENTS) + * 28 (31): System error (PLDA_SYS_ERR) + */ + +struct plda_pcie_rp; + +struct plda_event_ops { + u32 (*get_events)(struct plda_pcie_rp *pcie); +}; + +struct plda_pcie_host_ops { + int (*host_init)(struct plda_pcie_rp *pcie); + void (*host_deinit)(struct plda_pcie_rp *pcie); +}; + +struct plda_msi { + struct mutex lock; /* Protect used bitmap */ + struct irq_domain *msi_domain; + struct irq_domain *dev_domain; + u32 num_vectors; + u64 vector_phy; + DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS); +}; + +struct plda_pcie_rp { + struct device *dev; + struct pci_host_bridge *bridge; + struct irq_domain *intx_domain; + struct irq_domain *event_domain; + raw_spinlock_t lock; + struct plda_msi msi; + const struct plda_event_ops *event_ops; + const struct irq_chip *event_irq_chip; + const struct plda_pcie_host_ops *host_ops; + void __iomem *bridge_addr; + void __iomem *config_base; + unsigned long events_bitmap; + int irq; + int msi_irq; + int intx_irq; + int num_events; +}; + +struct plda_event { + int (*request_event_irq)(struct plda_pcie_rp *pcie, + int event_irq, int event); + int intx_event; + int msi_event; +}; + +void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, + int where); +int plda_init_interrupts(struct platform_device *pdev, + struct plda_pcie_rp *port, + const struct plda_event *event); +void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, + phys_addr_t axi_addr, phys_addr_t pci_addr, + size_t size); +int plda_pcie_setup_iomems(struct pci_host_bridge *bridge, + struct plda_pcie_rp *port); +int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops, + const struct plda_event *plda_event); +void plda_pcie_host_deinit(struct plda_pcie_rp *pcie); + +static inline void plda_set_default_msi(struct plda_msi *msi) +{ + msi->vector_phy = IMSI_ADDR; + msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS; +} + +static inline void plda_pcie_enable_root_port(struct plda_pcie_rp *plda) +{ + u32 value; + + value = readl_relaxed(plda->bridge_addr + GEN_SETTINGS); + value |= RP_ENABLE; + writel_relaxed(value, plda->bridge_addr + GEN_SETTINGS); +} + +static inline void plda_pcie_set_standard_class(struct plda_pcie_rp *plda) +{ + u32 value; + + /* set class code and reserve revision id */ + value = readl_relaxed(plda->bridge_addr + PCIE_PCI_IDS_DW1); + value &= REVISION_ID_MASK; + value |= (PCI_CLASS_BRIDGE_PCI << IDS_CLASS_CODE_SHIFT); + writel_relaxed(value, plda->bridge_addr + PCIE_PCI_IDS_DW1); +} + +static inline void plda_pcie_set_pref_win_64bit(struct plda_pcie_rp *plda) +{ + u32 value; + + value = readl_relaxed(plda->bridge_addr + PCIE_WINROM); + value |= PREF_MEM_WIN_64_SUPPORT; + writel_relaxed(value, plda->bridge_addr + PCIE_WINROM); +} + +static inline void plda_pcie_disable_ltr(struct plda_pcie_rp *plda) +{ + u32 value; + + value = readl_relaxed(plda->bridge_addr + PMSG_SUPPORT_RX); + value &= ~PMSG_LTR_SUPPORT; + writel_relaxed(value, plda->bridge_addr + PMSG_SUPPORT_RX); +} + +static inline void plda_pcie_disable_func(struct plda_pcie_rp *plda) +{ + u32 value; + + value = readl_relaxed(plda->bridge_addr + PCI_MISC); + value |= PHY_FUNCTION_DIS; + writel_relaxed(value, plda->bridge_addr + PCI_MISC); +} + +static inline void plda_pcie_write_rc_bar(struct plda_pcie_rp *plda, u64 val) +{ + void __iomem *addr = plda->bridge_addr + CONFIG_SPACE_ADDR_OFFSET; + + writel_relaxed(lower_32_bits(val), addr + PCI_BASE_ADDRESS_0); + writel_relaxed(upper_32_bits(val), addr + PCI_BASE_ADDRESS_1); +} +#endif /* _PCIE_PLDA_H */ diff --git a/drivers/pci/controller/plda/pcie-starfive.c b/drivers/pci/controller/plda/pcie-starfive.c new file mode 100644 index 000000000000..c9933ecf6833 --- /dev/null +++ b/drivers/pci/controller/plda/pcie-starfive.c @@ -0,0 +1,488 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * PCIe host controller driver for StarFive JH7110 Soc. + * + * Copyright (C) 2023 StarFive Technology Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../pci.h" + +#include "pcie-plda.h" + +#define PCIE_FUNC_NUM 4 + +/* system control */ +#define STG_SYSCON_PCIE0_BASE 0x48 +#define STG_SYSCON_PCIE1_BASE 0x1f8 + +#define STG_SYSCON_AR_OFFSET 0x78 +#define STG_SYSCON_AXI4_SLVL_AR_MASK GENMASK(22, 8) +#define STG_SYSCON_AXI4_SLVL_PHY_AR(x) FIELD_PREP(GENMASK(20, 17), x) +#define STG_SYSCON_AW_OFFSET 0x7c +#define STG_SYSCON_AXI4_SLVL_AW_MASK GENMASK(14, 0) +#define STG_SYSCON_AXI4_SLVL_PHY_AW(x) FIELD_PREP(GENMASK(12, 9), x) +#define STG_SYSCON_CLKREQ BIT(22) +#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18) +#define STG_SYSCON_RP_NEP_OFFSET 0xe8 +#define STG_SYSCON_K_RP_NEP BIT(8) +#define STG_SYSCON_LNKSTA_OFFSET 0x170 +#define DATA_LINK_ACTIVE BIT(5) + +/* Parameters for the waiting for link up routine */ +#define LINK_WAIT_MAX_RETRIES 10 +#define LINK_WAIT_USLEEP_MIN 90000 +#define LINK_WAIT_USLEEP_MAX 100000 + +struct starfive_jh7110_pcie { + struct plda_pcie_rp plda; + struct reset_control *resets; + struct clk_bulk_data *clks; + struct regmap *reg_syscon; + struct gpio_desc *power_gpio; + struct gpio_desc *reset_gpio; + struct phy *phy; + + unsigned int stg_pcie_base; + int num_clks; +}; + +/* + * JH7110 PCIe port BAR0/1 can be configured as 64-bit prefetchable memory + * space. PCIe read and write requests targeting BAR0/1 are routed to so called + * 'Bridge Configuration space' in PLDA IP datasheet, which contains the bridge + * internal registers, such as interrupt, DMA and ATU registers... + * JH7110 can access the Bridge Configuration space by local bus, and don`t + * want the bridge internal registers accessed by the DMA from EP devices. + * Thus, they are unimplemented and should be hidden here. + */ +static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn, + int offset) +{ + if (pci_is_root_bus(bus) && !devfn && + (offset == PCI_BASE_ADDRESS_0 || offset == PCI_BASE_ADDRESS_1)) + return true; + + return false; +} + +static int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + if (starfive_pcie_hide_rc_bar(bus, devfn, where)) + return PCIBIOS_SUCCESSFUL; + + return pci_generic_config_write(bus, devfn, where, size, value); +} + +static int starfive_pcie_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + if (starfive_pcie_hide_rc_bar(bus, devfn, where)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + return pci_generic_config_read(bus, devfn, where, size, value); +} + +static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie, + struct device *dev) +{ + int domain_nr; + + pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks); + if (pcie->num_clks < 0) + return dev_err_probe(dev, pcie->num_clks, + "failed to get pcie clocks\n"); + + pcie->resets = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(pcie->resets)) + return dev_err_probe(dev, PTR_ERR(pcie->resets), + "failed to get pcie resets"); + + pcie->reg_syscon = + syscon_regmap_lookup_by_phandle(dev->of_node, + "starfive,stg-syscon"); + + if (IS_ERR(pcie->reg_syscon)) + return dev_err_probe(dev, PTR_ERR(pcie->reg_syscon), + "failed to parse starfive,stg-syscon\n"); + + pcie->phy = devm_phy_optional_get(dev, NULL); + if (IS_ERR(pcie->phy)) + return dev_err_probe(dev, PTR_ERR(pcie->phy), + "failed to get pcie phy\n"); + + /* + * The PCIe domain numbers are set to be static in JH7110 DTS. + * As the STG system controller defines different bases in PCIe RP0 & + * RP1, we use them to identify which controller is doing the hardware + * initialization. + */ + domain_nr = of_get_pci_domain_nr(dev->of_node); + + if (domain_nr < 0 || domain_nr > 1) + return dev_err_probe(dev, -ENODEV, + "failed to get valid pcie domain\n"); + + if (domain_nr == 0) + pcie->stg_pcie_base = STG_SYSCON_PCIE0_BASE; + else + pcie->stg_pcie_base = STG_SYSCON_PCIE1_BASE; + + pcie->reset_gpio = devm_gpiod_get_optional(dev, "perst", + GPIOD_OUT_HIGH); + if (IS_ERR(pcie->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(pcie->reset_gpio), + "failed to get perst-gpio\n"); + + pcie->power_gpio = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(pcie->power_gpio)) + return dev_err_probe(dev, PTR_ERR(pcie->power_gpio), + "failed to get power-gpio\n"); + + return 0; +} + +static struct pci_ops starfive_pcie_ops = { + .map_bus = plda_pcie_map_bus, + .read = starfive_pcie_config_read, + .write = starfive_pcie_config_write, +}; + +static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie) +{ + struct device *dev = pcie->plda.dev; + int ret; + + ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); + if (ret) + return dev_err_probe(dev, ret, "failed to enable clocks\n"); + + ret = reset_control_deassert(pcie->resets); + if (ret) { + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); + dev_err_probe(dev, ret, "failed to deassert resets\n"); + } + + return ret; +} + +static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie) +{ + reset_control_assert(pcie->resets); + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); +} + +static bool starfive_pcie_link_up(struct plda_pcie_rp *plda) +{ + struct starfive_jh7110_pcie *pcie = + container_of(plda, struct starfive_jh7110_pcie, plda); + int ret; + u32 stg_reg_val; + + ret = regmap_read(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_LNKSTA_OFFSET, + &stg_reg_val); + if (ret) { + dev_err(pcie->plda.dev, "failed to read link status\n"); + return false; + } + + return !!(stg_reg_val & DATA_LINK_ACTIVE); +} + +static int starfive_pcie_host_wait_for_link(struct starfive_jh7110_pcie *pcie) +{ + int retries; + + /* Check if the link is up or not */ + for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { + if (starfive_pcie_link_up(&pcie->plda)) { + dev_info(pcie->plda.dev, "port link up\n"); + return 0; + } + usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); + } + + return -ETIMEDOUT; +} + +static int starfive_pcie_enable_phy(struct device *dev, + struct starfive_jh7110_pcie *pcie) +{ + int ret; + + if (!pcie->phy) + return 0; + + ret = phy_init(pcie->phy); + if (ret) + return dev_err_probe(dev, ret, + "failed to initialize pcie phy\n"); + + ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE); + if (ret) { + dev_err_probe(dev, ret, "failed to set pcie mode\n"); + goto err_phy_on; + } + + ret = phy_power_on(pcie->phy); + if (ret) { + dev_err_probe(dev, ret, "failed to power on pcie phy\n"); + goto err_phy_on; + } + + return 0; + +err_phy_on: + phy_exit(pcie->phy); + return ret; +} + +static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie) +{ + phy_power_off(pcie->phy); + phy_exit(pcie->phy); +} + +static void starfive_pcie_host_deinit(struct plda_pcie_rp *plda) +{ + struct starfive_jh7110_pcie *pcie = + container_of(plda, struct starfive_jh7110_pcie, plda); + + starfive_pcie_clk_rst_deinit(pcie); + if (pcie->power_gpio) + gpiod_set_value_cansleep(pcie->power_gpio, 0); + starfive_pcie_disable_phy(pcie); +} + +static int starfive_pcie_host_init(struct plda_pcie_rp *plda) +{ + struct starfive_jh7110_pcie *pcie = + container_of(plda, struct starfive_jh7110_pcie, plda); + struct device *dev = plda->dev; + int ret; + int i; + + ret = starfive_pcie_enable_phy(dev, pcie); + if (ret) + return ret; + + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_RP_NEP_OFFSET, + STG_SYSCON_K_RP_NEP, STG_SYSCON_K_RP_NEP); + + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, + STG_SYSCON_CKREF_SRC_MASK, + FIELD_PREP(STG_SYSCON_CKREF_SRC_MASK, 2)); + + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, + STG_SYSCON_CLKREQ, STG_SYSCON_CLKREQ); + + ret = starfive_pcie_clk_rst_init(pcie); + if (ret) + return ret; + + if (pcie->power_gpio) + gpiod_set_value_cansleep(pcie->power_gpio, 1); + + if (pcie->reset_gpio) + gpiod_set_value_cansleep(pcie->reset_gpio, 1); + + /* Disable physical functions except #0 */ + for (i = 1; i < PCIE_FUNC_NUM; i++) { + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET, + STG_SYSCON_AXI4_SLVL_AR_MASK, + STG_SYSCON_AXI4_SLVL_PHY_AR(i)); + + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, + STG_SYSCON_AXI4_SLVL_AW_MASK, + STG_SYSCON_AXI4_SLVL_PHY_AW(i)); + + plda_pcie_disable_func(plda); + } + + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET, + STG_SYSCON_AXI4_SLVL_AR_MASK, 0); + regmap_update_bits(pcie->reg_syscon, + pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, + STG_SYSCON_AXI4_SLVL_AW_MASK, 0); + + plda_pcie_enable_root_port(plda); + plda_pcie_write_rc_bar(plda, 0); + + /* PCIe PCI Standard Configuration Identification Settings. */ + plda_pcie_set_standard_class(plda); + + /* + * The LTR message receiving is enabled by the register "PCIe Message + * Reception" as default, but the forward id & addr are uninitialized. + * If we do not disable LTR message forwarding here, or set a legal + * forwarding address, the kernel will get stuck. + * To workaround, disable the LTR message forwarding here before using + * this feature. + */ + plda_pcie_disable_ltr(plda); + + /* + * Enable the prefetchable memory window 64-bit addressing in JH7110. + * The 64-bits prefetchable address translation configurations in ATU + * can be work after enable the register setting below. + */ + plda_pcie_set_pref_win_64bit(plda); + + /* + * Ensure that PERST has been asserted for at least 100 ms, + * the sleep value is T_PVPERL from PCIe CEM spec r2.0 (Table 2-4) + */ + msleep(100); + if (pcie->reset_gpio) + gpiod_set_value_cansleep(pcie->reset_gpio, 0); + + /* + * With a Downstream Port (<=5GT/s), software must wait a minimum + * of 100ms following exit from a conventional reset before + * sending a configuration request to the device. + */ + msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS); + + if (starfive_pcie_host_wait_for_link(pcie)) + dev_info(dev, "port link down\n"); + + return 0; +} + +static const struct plda_pcie_host_ops sf_host_ops = { + .host_init = starfive_pcie_host_init, + .host_deinit = starfive_pcie_host_deinit, +}; + +static const struct plda_event stf_pcie_event = { + .intx_event = EVENT_PM_MSI_INT_INTX, + .msi_event = EVENT_PM_MSI_INT_MSI +}; + +static int starfive_pcie_probe(struct platform_device *pdev) +{ + struct starfive_jh7110_pcie *pcie; + struct device *dev = &pdev->dev; + struct plda_pcie_rp *plda; + int ret; + + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + + plda = &pcie->plda; + plda->dev = dev; + + ret = starfive_pcie_parse_dt(pcie, dev); + if (ret) + return ret; + + plda->host_ops = &sf_host_ops; + plda->num_events = PLDA_MAX_EVENT_NUM; + /* mask doorbell event */ + plda->events_bitmap = GENMASK(PLDA_INT_EVENT_NUM - 1, 0) + & ~BIT(PLDA_AXI_DOORBELL) + & ~BIT(PLDA_PCIE_DOORBELL); + plda->events_bitmap <<= PLDA_NUM_DMA_EVENTS; + ret = plda_pcie_host_init(&pcie->plda, &starfive_pcie_ops, + &stf_pcie_event); + if (ret) + return ret; + + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + platform_set_drvdata(pdev, pcie); + + return 0; +} + +static void starfive_pcie_remove(struct platform_device *pdev) +{ + struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev); + + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + plda_pcie_host_deinit(&pcie->plda); + platform_set_drvdata(pdev, NULL); +} + +static int starfive_pcie_suspend_noirq(struct device *dev) +{ + struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); + starfive_pcie_disable_phy(pcie); + + return 0; +} + +static int starfive_pcie_resume_noirq(struct device *dev) +{ + struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev); + int ret; + + ret = starfive_pcie_enable_phy(dev, pcie); + if (ret) + return ret; + + ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + starfive_pcie_disable_phy(pcie); + return ret; + } + + return 0; +} + +static const struct dev_pm_ops starfive_pcie_pm_ops = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(starfive_pcie_suspend_noirq, + starfive_pcie_resume_noirq) +}; + +static const struct of_device_id starfive_pcie_of_match[] = { + { .compatible = "starfive,jh7110-pcie", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, starfive_pcie_of_match); + +static struct platform_driver starfive_pcie_driver = { + .driver = { + .name = "pcie-starfive", + .of_match_table = of_match_ptr(starfive_pcie_of_match), + .pm = pm_sleep_ptr(&starfive_pcie_pm_ops), + }, + .probe = starfive_pcie_probe, + .remove_new = starfive_pcie_remove, +}; +module_platform_driver(starfive_pcie_driver); + +MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 87b7856f375a..a726de0af011 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -925,6 +925,9 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) dev_set_msi_domain(&vmd->bus->dev, dev_get_msi_domain(&vmd->dev->dev)); + WARN(sysfs_create_link(&vmd->dev->dev.kobj, &vmd->bus->dev.kobj, + "domain"), "Can't create symlink to domain\n"); + vmd_acpi_begin(); pci_scan_child_bus(vmd->bus); @@ -964,9 +967,6 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) pci_bus_add_devices(vmd->bus); vmd_acpi_end(); - - WARN(sysfs_create_link(&vmd->dev->dev.kobj, &vmd->bus->dev.kobj, - "domain"), "Can't create symlink to domain\n"); return 0; } @@ -1042,8 +1042,8 @@ static void vmd_remove(struct pci_dev *dev) { struct vmd_dev *vmd = pci_get_drvdata(dev); - sysfs_remove_link(&vmd->dev->dev.kobj, "domain"); pci_stop_root_bus(vmd->bus); + sysfs_remove_link(&vmd->dev->dev.kobj, "domain"); pci_remove_root_bus(vmd->bus); vmd_cleanup_srcu(vmd); vmd_detach_resources(vmd); @@ -1128,5 +1128,6 @@ static struct pci_driver vmd_drv = { module_pci_driver(vmd_drv); MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Volume Management Device driver"); MODULE_LICENSE("GPL v2"); MODULE_VERSION("0.6"); diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c index 2c562b9eaf80..3780a9f9ec00 100644 --- a/drivers/pci/devres.c +++ b/drivers/pci/devres.c @@ -4,14 +4,249 @@ #include "pci.h" /* - * PCI iomap devres + * On the state of PCI's devres implementation: + * + * The older devres API for PCI has two significant problems: + * + * 1. It is very strongly tied to the statically allocated mapping table in + * struct pcim_iomap_devres below. This is mostly solved in the sense of the + * pcim_ functions in this file providing things like ranged mapping by + * bypassing this table, whereas the functions that were present in the old + * API still enter the mapping addresses into the table for users of the old + * API. + * + * 2. The region-request-functions in pci.c do become managed IF the device has + * been enabled with pcim_enable_device() instead of pci_enable_device(). + * This resulted in the API becoming inconsistent: Some functions have an + * obviously managed counter-part (e.g., pci_iomap() <-> pcim_iomap()), + * whereas some don't and are never managed, while others don't and are + * _sometimes_ managed (e.g. pci_request_region()). + * + * Consequently, in the new API, region requests performed by the pcim_ + * functions are automatically cleaned up through the devres callback + * pcim_addr_resource_release(). + * + * Users of pcim_enable_device() + pci_*region*() are redirected in + * pci.c to the managed functions here in this file. This isn't exactly + * perfect, but the only alternative way would be to port ALL drivers + * using said combination to pcim_ functions. + * + * TODO: + * Remove the legacy table entirely once all calls to pcim_iomap_table() in + * the kernel have been removed. */ -#define PCIM_IOMAP_MAX PCI_STD_NUM_BARS +/* + * Legacy struct storing addresses to whole mapped BARs. + */ struct pcim_iomap_devres { - void __iomem *table[PCIM_IOMAP_MAX]; + void __iomem *table[PCI_STD_NUM_BARS]; }; +/* Used to restore the old INTx state on driver detach. */ +struct pcim_intx_devres { + int orig_intx; +}; + +enum pcim_addr_devres_type { + /* Default initializer. */ + PCIM_ADDR_DEVRES_TYPE_INVALID, + + /* A requested region spanning an entire BAR. */ + PCIM_ADDR_DEVRES_TYPE_REGION, + + /* + * A requested region spanning an entire BAR, and a mapping for + * the entire BAR. + */ + PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING, + + /* + * A mapping within a BAR, either spanning the whole BAR or just a + * range. Without a requested region. + */ + PCIM_ADDR_DEVRES_TYPE_MAPPING, +}; + +/* + * This struct envelops IO or MEM addresses, i.e., mappings and region + * requests, because those are very frequently requested and released + * together. + */ +struct pcim_addr_devres { + enum pcim_addr_devres_type type; + void __iomem *baseaddr; + unsigned long offset; + unsigned long len; + int bar; +}; + +static inline void pcim_addr_devres_clear(struct pcim_addr_devres *res) +{ + memset(res, 0, sizeof(*res)); + res->bar = -1; +} + +/* + * The following functions, __pcim_*_region*, exist as counterparts to the + * versions from pci.c - which, unfortunately, can be in "hybrid mode", i.e., + * sometimes managed, sometimes not. + * + * To separate the APIs cleanly, we define our own, simplified versions here. + */ + +/** + * __pcim_request_region_range - Request a ranged region + * @pdev: PCI device the region belongs to + * @bar: BAR the range is within + * @offset: offset from the BAR's start address + * @maxlen: length in bytes, beginning at @offset + * @name: name associated with the request + * @req_flags: flags for the request, e.g., for kernel-exclusive requests + * + * Returns: 0 on success, a negative error code on failure. + * + * Request a range within a device's PCI BAR. Sanity check the input. + */ +static int __pcim_request_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, + unsigned long maxlen, + const char *name, int req_flags) +{ + resource_size_t start = pci_resource_start(pdev, bar); + resource_size_t len = pci_resource_len(pdev, bar); + unsigned long dev_flags = pci_resource_flags(pdev, bar); + + if (start == 0 || len == 0) /* Unused BAR. */ + return 0; + if (len <= offset) + return -EINVAL; + + start += offset; + len -= offset; + + if (len > maxlen && maxlen != 0) + len = maxlen; + + if (dev_flags & IORESOURCE_IO) { + if (!request_region(start, len, name)) + return -EBUSY; + } else if (dev_flags & IORESOURCE_MEM) { + if (!__request_mem_region(start, len, name, req_flags)) + return -EBUSY; + } else { + /* That's not a device we can request anything on. */ + return -ENODEV; + } + + return 0; +} + +static void __pcim_release_region_range(struct pci_dev *pdev, int bar, + unsigned long offset, + unsigned long maxlen) +{ + resource_size_t start = pci_resource_start(pdev, bar); + resource_size_t len = pci_resource_len(pdev, bar); + unsigned long flags = pci_resource_flags(pdev, bar); + + if (len <= offset || start == 0) + return; + + if (len == 0 || maxlen == 0) /* This an unused BAR. Do nothing. */ + return; + + start += offset; + len -= offset; + + if (len > maxlen) + len = maxlen; + + if (flags & IORESOURCE_IO) + release_region(start, len); + else if (flags & IORESOURCE_MEM) + release_mem_region(start, len); +} + +static int __pcim_request_region(struct pci_dev *pdev, int bar, + const char *name, int flags) +{ + unsigned long offset = 0; + unsigned long len = pci_resource_len(pdev, bar); + + return __pcim_request_region_range(pdev, bar, offset, len, name, flags); +} + +static void __pcim_release_region(struct pci_dev *pdev, int bar) +{ + unsigned long offset = 0; + unsigned long len = pci_resource_len(pdev, bar); + + __pcim_release_region_range(pdev, bar, offset, len); +} + +static void pcim_addr_resource_release(struct device *dev, void *resource_raw) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pcim_addr_devres *res = resource_raw; + + switch (res->type) { + case PCIM_ADDR_DEVRES_TYPE_REGION: + __pcim_release_region(pdev, res->bar); + break; + case PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING: + pci_iounmap(pdev, res->baseaddr); + __pcim_release_region(pdev, res->bar); + break; + case PCIM_ADDR_DEVRES_TYPE_MAPPING: + pci_iounmap(pdev, res->baseaddr); + break; + default: + break; + } +} + +static struct pcim_addr_devres *pcim_addr_devres_alloc(struct pci_dev *pdev) +{ + struct pcim_addr_devres *res; + + res = devres_alloc_node(pcim_addr_resource_release, sizeof(*res), + GFP_KERNEL, dev_to_node(&pdev->dev)); + if (res) + pcim_addr_devres_clear(res); + return res; +} + +/* Just for consistency and readability. */ +static inline void pcim_addr_devres_free(struct pcim_addr_devres *res) +{ + devres_free(res); +} + +/* + * Used by devres to identify a pcim_addr_devres. + */ +static int pcim_addr_resources_match(struct device *dev, + void *a_raw, void *b_raw) +{ + struct pcim_addr_devres *a, *b; + + a = a_raw; + b = b_raw; + + if (a->type != b->type) + return 0; + + switch (a->type) { + case PCIM_ADDR_DEVRES_TYPE_REGION: + case PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING: + return a->bar == b->bar; + case PCIM_ADDR_DEVRES_TYPE_MAPPING: + return a->baseaddr == b->baseaddr; + default: + return 0; + } +} static void devm_pci_unmap_iospace(struct device *dev, void *ptr) { @@ -92,8 +327,8 @@ EXPORT_SYMBOL(devm_pci_remap_cfgspace); * * All operations are managed and will be undone on driver detach. * - * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code - * on failure. Usage example:: + * Returns a pointer to the remapped memory or an IOMEM_ERR_PTR() encoded error + * code on failure. Usage example:: * * res = platform_get_resource(pdev, IORESOURCE_MEM, 0); * base = devm_pci_remap_cfg_resource(&pdev->dev, res); @@ -140,96 +375,147 @@ void __iomem *devm_pci_remap_cfg_resource(struct device *dev, } EXPORT_SYMBOL(devm_pci_remap_cfg_resource); +static void __pcim_clear_mwi(void *pdev_raw) +{ + struct pci_dev *pdev = pdev_raw; + + pci_clear_mwi(pdev); +} + /** * pcim_set_mwi - a device-managed pci_set_mwi() - * @dev: the PCI device for which MWI is enabled + * @pdev: the PCI device for which MWI is enabled * * Managed pci_set_mwi(). * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ -int pcim_set_mwi(struct pci_dev *dev) +int pcim_set_mwi(struct pci_dev *pdev) { - struct pci_devres *dr; + int ret; - dr = find_pci_dr(dev); - if (!dr) - return -ENOMEM; + ret = devm_add_action(&pdev->dev, __pcim_clear_mwi, pdev); + if (ret != 0) + return ret; - dr->mwi = 1; - return pci_set_mwi(dev); + ret = pci_set_mwi(pdev); + if (ret != 0) + devm_remove_action(&pdev->dev, __pcim_clear_mwi, pdev); + + return ret; } EXPORT_SYMBOL(pcim_set_mwi); - -static void pcim_release(struct device *gendev, void *res) +static inline bool mask_contains_bar(int mask, int bar) { - struct pci_dev *dev = to_pci_dev(gendev); - struct pci_devres *this = res; - int i; - - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - if (this->region_mask & (1 << i)) - pci_release_region(dev, i); - - if (this->mwi) - pci_clear_mwi(dev); - - if (this->restore_intx) - pci_intx(dev, this->orig_intx); - - if (this->enabled && !this->pinned) - pci_disable_device(dev); + return mask & BIT(bar); } /* - * TODO: After the last four callers in pci.c are ported, find_pci_dr() - * needs to be made static again. + * This is a copy of pci_intx() used to bypass the problem of recursive + * function calls due to the hybrid nature of pci_intx(). */ -struct pci_devres *find_pci_dr(struct pci_dev *pdev) +static void __pcim_intx(struct pci_dev *pdev, int enable) { - if (pci_is_managed(pdev)) - return devres_find(&pdev->dev, pcim_release, NULL, NULL); - return NULL; + u16 pci_command, new; + + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + + if (enable) + new = pci_command & ~PCI_COMMAND_INTX_DISABLE; + else + new = pci_command | PCI_COMMAND_INTX_DISABLE; + + if (new != pci_command) + pci_write_config_word(pdev, PCI_COMMAND, new); } -static struct pci_devres *get_pci_dr(struct pci_dev *pdev) +static void pcim_intx_restore(struct device *dev, void *data) { - struct pci_devres *dr, *new_dr; + struct pci_dev *pdev = to_pci_dev(dev); + struct pcim_intx_devres *res = data; - dr = devres_find(&pdev->dev, pcim_release, NULL, NULL); - if (dr) - return dr; + __pcim_intx(pdev, res->orig_intx); +} - new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL); - if (!new_dr) - return NULL; - return devres_get(&pdev->dev, new_dr, NULL, NULL); +static struct pcim_intx_devres *get_or_create_intx_devres(struct device *dev) +{ + struct pcim_intx_devres *res; + + res = devres_find(dev, pcim_intx_restore, NULL, NULL); + if (res) + return res; + + res = devres_alloc(pcim_intx_restore, sizeof(*res), GFP_KERNEL); + if (res) + devres_add(dev, res); + + return res; +} + +/** + * pcim_intx - managed pci_intx() + * @pdev: the PCI device to operate on + * @enable: boolean: whether to enable or disable PCI INTx + * + * Returns: 0 on success, -ENOMEM on error. + * + * Enable/disable PCI INTx for device @pdev. + * Restore the original state on driver detach. + */ +int pcim_intx(struct pci_dev *pdev, int enable) +{ + struct pcim_intx_devres *res; + + res = get_or_create_intx_devres(&pdev->dev); + if (!res) + return -ENOMEM; + + res->orig_intx = !enable; + __pcim_intx(pdev, enable); + + return 0; +} + +static void pcim_disable_device(void *pdev_raw) +{ + struct pci_dev *pdev = pdev_raw; + + if (!pdev->pinned) + pci_disable_device(pdev); } /** * pcim_enable_device - Managed pci_enable_device() * @pdev: PCI device to be initialized * - * Managed pci_enable_device(). + * Returns: 0 on success, negative error code on failure. + * + * Managed pci_enable_device(). Device will automatically be disabled on + * driver detach. */ int pcim_enable_device(struct pci_dev *pdev) { - struct pci_devres *dr; - int rc; + int ret; - dr = get_pci_dr(pdev); - if (unlikely(!dr)) - return -ENOMEM; - if (dr->enabled) - return 0; + ret = devm_add_action(&pdev->dev, pcim_disable_device, pdev); + if (ret != 0) + return ret; - rc = pci_enable_device(pdev); - if (!rc) { - pdev->is_managed = 1; - dr->enabled = 1; + /* + * We prefer removing the action in case of an error over + * devm_add_action_or_reset() because the latter could theoretically be + * disturbed by users having pinned the device too soon. + */ + ret = pci_enable_device(pdev); + if (ret != 0) { + devm_remove_action(&pdev->dev, pcim_disable_device, pdev); + return ret; } - return rc; + + pdev->is_managed = true; + + return ret; } EXPORT_SYMBOL(pcim_enable_device); @@ -237,36 +523,32 @@ EXPORT_SYMBOL(pcim_enable_device); * pcim_pin_device - Pin managed PCI device * @pdev: PCI device to pin * - * Pin managed PCI device @pdev. Pinned device won't be disabled on - * driver detach. @pdev must have been enabled with - * pcim_enable_device(). + * Pin managed PCI device @pdev. Pinned device won't be disabled on driver + * detach. @pdev must have been enabled with pcim_enable_device(). */ void pcim_pin_device(struct pci_dev *pdev) { - struct pci_devres *dr; - - dr = find_pci_dr(pdev); - WARN_ON(!dr || !dr->enabled); - if (dr) - dr->pinned = 1; + pdev->pinned = true; } EXPORT_SYMBOL(pcim_pin_device); static void pcim_iomap_release(struct device *gendev, void *res) { - struct pci_dev *dev = to_pci_dev(gendev); - struct pcim_iomap_devres *this = res; - int i; - - for (i = 0; i < PCIM_IOMAP_MAX; i++) - if (this->table[i]) - pci_iounmap(dev, this->table[i]); + /* + * Do nothing. This is legacy code. + * + * Cleanup of the mappings is now done directly through the callbacks + * registered when creating them. + */ } /** - * pcim_iomap_table - access iomap allocation table + * pcim_iomap_table - access iomap allocation table (DEPRECATED) * @pdev: PCI device to access iomap table for * + * Returns: + * Const pointer to array of __iomem pointers on success, NULL on failure. + * * Access iomap allocation table for @dev. If iomap table doesn't * exist and @pdev is managed, it will be allocated. All iomaps * recorded in the iomap table are automatically unmapped on driver @@ -275,6 +557,11 @@ static void pcim_iomap_release(struct device *gendev, void *res) * This function might sleep when the table is first allocated but can * be safely called without context and guaranteed to succeed once * allocated. + * + * This function is DEPRECATED. Do not use it in new code. Instead, obtain a + * mapping's address directly from one of the pcim_* mapping functions. For + * example: + * void __iomem \*mappy = pcim_iomap(pdev, bar, length); */ void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) { @@ -293,27 +580,114 @@ void __iomem * const *pcim_iomap_table(struct pci_dev *pdev) } EXPORT_SYMBOL(pcim_iomap_table); +/* + * Fill the legacy mapping-table, so that drivers using the old API can + * still get a BAR's mapping address through pcim_iomap_table(). + */ +static int pcim_add_mapping_to_legacy_table(struct pci_dev *pdev, + void __iomem *mapping, int bar) +{ + void __iomem **legacy_iomap_table; + + if (bar >= PCI_STD_NUM_BARS) + return -EINVAL; + + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + return -ENOMEM; + + /* The legacy mechanism doesn't allow for duplicate mappings. */ + WARN_ON(legacy_iomap_table[bar]); + + legacy_iomap_table[bar] = mapping; + + return 0; +} + +/* + * Remove a mapping. The table only contains whole-BAR mappings, so this will + * never interfere with ranged mappings. + */ +static void pcim_remove_mapping_from_legacy_table(struct pci_dev *pdev, + void __iomem *addr) +{ + int bar; + void __iomem **legacy_iomap_table; + + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + return; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (legacy_iomap_table[bar] == addr) { + legacy_iomap_table[bar] = NULL; + return; + } + } +} + +/* + * The same as pcim_remove_mapping_from_legacy_table(), but identifies the + * mapping by its BAR index. + */ +static void pcim_remove_bar_from_legacy_table(struct pci_dev *pdev, int bar) +{ + void __iomem **legacy_iomap_table; + + if (bar >= PCI_STD_NUM_BARS) + return; + + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + if (!legacy_iomap_table) + return; + + legacy_iomap_table[bar] = NULL; +} + /** * pcim_iomap - Managed pcim_iomap() * @pdev: PCI device to iomap for * @bar: BAR to iomap * @maxlen: Maximum length of iomap * - * Managed pci_iomap(). Map is automatically unmapped on driver - * detach. + * Returns: __iomem pointer on success, NULL on failure. + * + * Managed pci_iomap(). Map is automatically unmapped on driver detach. If + * desired, unmap manually only with pcim_iounmap(). + * + * This SHOULD only be used once per BAR. + * + * NOTE: + * Contrary to the other pcim_* functions, this function does not return an + * IOMEM_ERR_PTR() on failure, but a simple NULL. This is done for backwards + * compatibility. */ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) { - void __iomem **tbl; + void __iomem *mapping; + struct pcim_addr_devres *res; - BUG_ON(bar >= PCIM_IOMAP_MAX); - - tbl = (void __iomem **)pcim_iomap_table(pdev); - if (!tbl || tbl[bar]) /* duplicate mappings not allowed */ + res = pcim_addr_devres_alloc(pdev); + if (!res) return NULL; + res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING; - tbl[bar] = pci_iomap(pdev, bar, maxlen); - return tbl[bar]; + mapping = pci_iomap(pdev, bar, maxlen); + if (!mapping) + goto err_iomap; + res->baseaddr = mapping; + + if (pcim_add_mapping_to_legacy_table(pdev, mapping, bar) != 0) + goto err_table; + + devres_add(&pdev->dev, res); + return mapping; + +err_table: + pci_iounmap(pdev, mapping); +err_iomap: + pcim_addr_devres_free(res); + return NULL; } EXPORT_SYMBOL(pcim_iomap); @@ -322,102 +696,314 @@ EXPORT_SYMBOL(pcim_iomap); * @pdev: PCI device to iounmap for * @addr: Address to unmap * - * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap(). + * Managed pci_iounmap(). @addr must have been mapped using a pcim_* mapping + * function. */ void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) { - void __iomem **tbl; - int i; + struct pcim_addr_devres res_searched; - pci_iounmap(pdev, addr); + pcim_addr_devres_clear(&res_searched); + res_searched.type = PCIM_ADDR_DEVRES_TYPE_MAPPING; + res_searched.baseaddr = addr; - tbl = (void __iomem **)pcim_iomap_table(pdev); - BUG_ON(!tbl); + if (devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched) != 0) { + /* Doesn't exist. User passed nonsense. */ + return; + } - for (i = 0; i < PCIM_IOMAP_MAX; i++) - if (tbl[i] == addr) { - tbl[i] = NULL; - return; - } - WARN_ON(1); + pcim_remove_mapping_from_legacy_table(pdev, addr); } EXPORT_SYMBOL(pcim_iounmap); +/** + * pcim_iomap_region - Request and iomap a PCI BAR + * @pdev: PCI device to map IO resources for + * @bar: Index of a BAR to map + * @name: Name associated with the request + * + * Returns: __iomem pointer on success, an IOMEM_ERR_PTR on failure. + * + * Mapping and region will get automatically released on driver detach. If + * desired, release manually only with pcim_iounmap_region(). + */ +static void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar, + const char *name) +{ + int ret; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return IOMEM_ERR_PTR(-ENOMEM); + + res->type = PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING; + res->bar = bar; + + ret = __pcim_request_region(pdev, bar, name, 0); + if (ret != 0) + goto err_region; + + res->baseaddr = pci_iomap(pdev, bar, 0); + if (!res->baseaddr) { + ret = -EINVAL; + goto err_iomap; + } + + devres_add(&pdev->dev, res); + return res->baseaddr; + +err_iomap: + __pcim_release_region(pdev, bar); +err_region: + pcim_addr_devres_free(res); + + return IOMEM_ERR_PTR(ret); +} + +/** + * pcim_iounmap_region - Unmap and release a PCI BAR + * @pdev: PCI device to operate on + * @bar: Index of BAR to unmap and release + * + * Unmap a BAR and release its region manually. Only pass BARs that were + * previously mapped by pcim_iomap_region(). + */ +static void pcim_iounmap_region(struct pci_dev *pdev, int bar) +{ + struct pcim_addr_devres res_searched; + + pcim_addr_devres_clear(&res_searched); + res_searched.type = PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING; + res_searched.bar = bar; + + devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched); +} + /** * pcim_iomap_regions - Request and iomap PCI BARs * @pdev: PCI device to map IO resources for * @mask: Mask of BARs to request and iomap - * @name: Name used when requesting regions + * @name: Name associated with the requests + * + * Returns: 0 on success, negative error code on failure. * * Request and iomap regions specified by @mask. */ int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name) { - void __iomem * const *iomap; - int i, rc; + int ret; + int bar; + void __iomem *mapping; - iomap = pcim_iomap_table(pdev); - if (!iomap) - return -ENOMEM; - - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - unsigned long len; - - if (!(mask & (1 << i))) + for (bar = 0; bar < DEVICE_COUNT_RESOURCE; bar++) { + if (!mask_contains_bar(mask, bar)) continue; - rc = -EINVAL; - len = pci_resource_len(pdev, i); - if (!len) - goto err_inval; - - rc = pci_request_region(pdev, i, name); - if (rc) - goto err_inval; - - rc = -ENOMEM; - if (!pcim_iomap(pdev, i, 0)) - goto err_region; + mapping = pcim_iomap_region(pdev, bar, name); + if (IS_ERR(mapping)) { + ret = PTR_ERR(mapping); + goto err; + } + ret = pcim_add_mapping_to_legacy_table(pdev, mapping, bar); + if (ret != 0) + goto err; } return 0; - err_region: - pci_release_region(pdev, i); - err_inval: - while (--i >= 0) { - if (!(mask & (1 << i))) - continue; - pcim_iounmap(pdev, iomap[i]); - pci_release_region(pdev, i); +err: + while (--bar >= 0) { + pcim_iounmap_region(pdev, bar); + pcim_remove_bar_from_legacy_table(pdev, bar); } - return rc; + return ret; } EXPORT_SYMBOL(pcim_iomap_regions); +static int _pcim_request_region(struct pci_dev *pdev, int bar, const char *name, + int request_flags) +{ + int ret; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return -ENOMEM; + res->type = PCIM_ADDR_DEVRES_TYPE_REGION; + res->bar = bar; + + ret = __pcim_request_region(pdev, bar, name, request_flags); + if (ret != 0) { + pcim_addr_devres_free(res); + return ret; + } + + devres_add(&pdev->dev, res); + return 0; +} + +/** + * pcim_request_region - Request a PCI BAR + * @pdev: PCI device to requestion region for + * @bar: Index of BAR to request + * @name: Name associated with the request + * + * Returns: 0 on success, a negative error code on failure. + * + * Request region specified by @bar. + * + * The region will automatically be released on driver detach. If desired, + * release manually only with pcim_release_region(). + */ +int pcim_request_region(struct pci_dev *pdev, int bar, const char *name) +{ + return _pcim_request_region(pdev, bar, name, 0); +} + +/** + * pcim_request_region_exclusive - Request a PCI BAR exclusively + * @pdev: PCI device to requestion region for + * @bar: Index of BAR to request + * @name: Name associated with the request + * + * Returns: 0 on success, a negative error code on failure. + * + * Request region specified by @bar exclusively. + * + * The region will automatically be released on driver detach. If desired, + * release manually only with pcim_release_region(). + */ +int pcim_request_region_exclusive(struct pci_dev *pdev, int bar, const char *name) +{ + return _pcim_request_region(pdev, bar, name, IORESOURCE_EXCLUSIVE); +} + +/** + * pcim_release_region - Release a PCI BAR + * @pdev: PCI device to operate on + * @bar: Index of BAR to release + * + * Release a region manually that was previously requested by + * pcim_request_region(). + */ +void pcim_release_region(struct pci_dev *pdev, int bar) +{ + struct pcim_addr_devres res_searched; + + pcim_addr_devres_clear(&res_searched); + res_searched.type = PCIM_ADDR_DEVRES_TYPE_REGION; + res_searched.bar = bar; + + devres_release(&pdev->dev, pcim_addr_resource_release, + pcim_addr_resources_match, &res_searched); +} + + +/** + * pcim_release_all_regions - Release all regions of a PCI-device + * @pdev: the PCI device + * + * Release all regions previously requested through pcim_request_region() + * or pcim_request_all_regions(). + * + * Can be called from any context, i.e., not necessarily as a counterpart to + * pcim_request_all_regions(). + */ +static void pcim_release_all_regions(struct pci_dev *pdev) +{ + int bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) + pcim_release_region(pdev, bar); +} + +/** + * pcim_request_all_regions - Request all regions + * @pdev: PCI device to map IO resources for + * @name: name associated with the request + * + * Returns: 0 on success, negative error code on failure. + * + * Requested regions will automatically be released at driver detach. If + * desired, release individual regions with pcim_release_region() or all of + * them at once with pcim_release_all_regions(). + */ +static int pcim_request_all_regions(struct pci_dev *pdev, const char *name) +{ + int ret; + int bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + ret = pcim_request_region(pdev, bar, name); + if (ret != 0) + goto err; + } + + return 0; + +err: + pcim_release_all_regions(pdev); + + return ret; +} + /** * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones + * (DEPRECATED) * @pdev: PCI device to map IO resources for * @mask: Mask of BARs to iomap - * @name: Name used when requesting regions + * @name: Name associated with the requests + * + * Returns: 0 on success, negative error code on failure. * * Request all PCI BARs and iomap regions specified by @mask. + * + * To release these resources manually, call pcim_release_region() for the + * regions and pcim_iounmap() for the mappings. + * + * This function is DEPRECATED. Don't use it in new code. Instead, use one + * of the pcim_* region request functions in combination with a pcim_* + * mapping function. */ int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, const char *name) { - int request_mask = ((1 << 6) - 1) & ~mask; - int rc; + int bar; + int ret; + void __iomem **legacy_iomap_table; - rc = pci_request_selected_regions(pdev, request_mask, name); - if (rc) - return rc; + ret = pcim_request_all_regions(pdev, name); + if (ret != 0) + return ret; - rc = pcim_iomap_regions(pdev, mask, name); - if (rc) - pci_release_selected_regions(pdev, request_mask); - return rc; + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (!mask_contains_bar(mask, bar)) + continue; + if (!pcim_iomap(pdev, bar, 0)) + goto err; + } + + return 0; + +err: + /* + * If bar is larger than 0, then pcim_iomap() above has most likely + * failed because of -EINVAL. If it is equal 0, most likely the table + * couldn't be created, indicating -ENOMEM. + */ + ret = bar > 0 ? -EINVAL : -ENOMEM; + legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev); + + while (--bar >= 0) + pcim_iounmap(pdev, legacy_iomap_table[bar]); + + pcim_release_all_regions(pdev); + + return ret; } EXPORT_SYMBOL(pcim_iomap_regions_request_all); @@ -430,19 +1016,58 @@ EXPORT_SYMBOL(pcim_iomap_regions_request_all); */ void pcim_iounmap_regions(struct pci_dev *pdev, int mask) { - void __iomem * const *iomap; int i; - iomap = pcim_iomap_table(pdev); - if (!iomap) - return; - - for (i = 0; i < PCIM_IOMAP_MAX; i++) { - if (!(mask & (1 << i))) + for (i = 0; i < PCI_STD_NUM_BARS; i++) { + if (!mask_contains_bar(mask, i)) continue; - pcim_iounmap(pdev, iomap[i]); - pci_release_region(pdev, i); + pcim_iounmap_region(pdev, i); + pcim_remove_bar_from_legacy_table(pdev, i); } } EXPORT_SYMBOL(pcim_iounmap_regions); + +/** + * pcim_iomap_range - Create a ranged __iomap mapping within a PCI BAR + * @pdev: PCI device to map IO resources for + * @bar: Index of the BAR + * @offset: Offset from the begin of the BAR + * @len: Length in bytes for the mapping + * + * Returns: __iomem pointer on success, an IOMEM_ERR_PTR on failure. + * + * Creates a new IO-Mapping within the specified @bar, ranging from @offset to + * @offset + @len. + * + * The mapping will automatically get unmapped on driver detach. If desired, + * release manually only with pcim_iounmap(). + */ +void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len) +{ + void __iomem *mapping; + struct pcim_addr_devres *res; + + res = pcim_addr_devres_alloc(pdev); + if (!res) + return IOMEM_ERR_PTR(-ENOMEM); + + mapping = pci_iomap_range(pdev, bar, offset, len); + if (!mapping) { + pcim_addr_devres_free(res); + return IOMEM_ERR_PTR(-EINVAL); + } + + res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING; + res->baseaddr = mapping; + + /* + * Ranged mappings don't get added to the legacy-table, since the table + * only ever keeps track of whole BARs. + */ + + devres_add(&pdev->dev, res); + return mapping; +} +EXPORT_SYMBOL(pcim_iomap_range); diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c index 2c54d80107cf..7d070b1def11 100644 --- a/drivers/pci/endpoint/functions/pci-epf-mhi.c +++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c @@ -137,6 +137,7 @@ static const struct pci_epf_mhi_ep_info sa8775p_info = { .epf_flags = PCI_BASE_ADDRESS_MEM_TYPE_32, .msi_count = 32, .mru = 0x8000, + .flags = MHI_EPF_USE_DMA, }; struct pci_epf_mhi { @@ -716,7 +717,7 @@ static void pci_epf_mhi_dma_deinit(struct pci_epf_mhi *epf_mhi) epf_mhi->dma_chan_rx = NULL; } -static int pci_epf_mhi_core_init(struct pci_epf *epf) +static int pci_epf_mhi_epc_init(struct pci_epf *epf) { struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); const struct pci_epf_mhi_ep_info *info = epf_mhi->info; @@ -753,9 +754,35 @@ static int pci_epf_mhi_core_init(struct pci_epf *epf) if (!epf_mhi->epc_features) return -ENODATA; + if (info->flags & MHI_EPF_USE_DMA) { + ret = pci_epf_mhi_dma_init(epf_mhi); + if (ret) { + dev_err(dev, "Failed to initialize DMA: %d\n", ret); + return ret; + } + } + return 0; } +static void pci_epf_mhi_epc_deinit(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num]; + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct pci_epc *epc = epf->epc; + + if (mhi_cntrl->mhi_dev) { + mhi_ep_power_down(mhi_cntrl); + if (info->flags & MHI_EPF_USE_DMA) + pci_epf_mhi_dma_deinit(epf_mhi); + mhi_ep_unregister_controller(mhi_cntrl); + } + + pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar); +} + static int pci_epf_mhi_link_up(struct pci_epf *epf) { struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); @@ -765,14 +792,6 @@ static int pci_epf_mhi_link_up(struct pci_epf *epf) struct device *dev = &epf->dev; int ret; - if (info->flags & MHI_EPF_USE_DMA) { - ret = pci_epf_mhi_dma_init(epf_mhi); - if (ret) { - dev_err(dev, "Failed to initialize DMA: %d\n", ret); - return ret; - } - } - mhi_cntrl->mmio = epf_mhi->mmio; mhi_cntrl->irq = epf_mhi->irq; mhi_cntrl->mru = info->mru; @@ -819,7 +838,7 @@ static int pci_epf_mhi_link_down(struct pci_epf *epf) return 0; } -static int pci_epf_mhi_bme(struct pci_epf *epf) +static int pci_epf_mhi_bus_master_enable(struct pci_epf *epf) { struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); const struct pci_epf_mhi_ep_info *info = epf_mhi->info; @@ -882,8 +901,8 @@ static void pci_epf_mhi_unbind(struct pci_epf *epf) /* * Forcefully power down the MHI EP stack. Only way to bring the MHI EP - * stack back to working state after successive bind is by getting BME - * from host. + * stack back to working state after successive bind is by getting Bus + * Master Enable event from host. */ if (mhi_cntrl->mhi_dev) { mhi_ep_power_down(mhi_cntrl); @@ -897,10 +916,11 @@ static void pci_epf_mhi_unbind(struct pci_epf *epf) } static const struct pci_epc_event_ops pci_epf_mhi_event_ops = { - .core_init = pci_epf_mhi_core_init, + .epc_init = pci_epf_mhi_epc_init, + .epc_deinit = pci_epf_mhi_epc_deinit, .link_up = pci_epf_mhi_link_up, .link_down = pci_epf_mhi_link_down, - .bme = pci_epf_mhi_bme, + .bus_master_enable = pci_epf_mhi_bus_master_enable, }; static int pci_epf_mhi_probe(struct pci_epf *epf, diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 977fb79c1567..7c2ed6eae53a 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -686,25 +686,6 @@ reset_handler: msecs_to_jiffies(1)); } -static void pci_epf_test_unbind(struct pci_epf *epf) -{ - struct pci_epf_test *epf_test = epf_get_drvdata(epf); - struct pci_epc *epc = epf->epc; - int bar; - - cancel_delayed_work(&epf_test->cmd_handler); - pci_epf_test_clean_dma_chan(epf_test); - for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { - if (!epf_test->reg[bar]) - continue; - - pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, - &epf->bar[bar]); - pci_epf_free_space(epf, epf_test->reg[bar], bar, - PRIMARY_INTERFACE); - } -} - static int pci_epf_test_set_bar(struct pci_epf *epf) { int bar, ret; @@ -731,23 +712,36 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) return 0; } -static int pci_epf_test_core_init(struct pci_epf *epf) +static void pci_epf_test_clear_bar(struct pci_epf *epf) +{ + struct pci_epf_test *epf_test = epf_get_drvdata(epf); + struct pci_epc *epc = epf->epc; + int bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (!epf_test->reg[bar]) + continue; + + pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, + &epf->bar[bar]); + } +} + +static int pci_epf_test_epc_init(struct pci_epf *epf) { struct pci_epf_test *epf_test = epf_get_drvdata(epf); struct pci_epf_header *header = epf->header; - const struct pci_epc_features *epc_features; + const struct pci_epc_features *epc_features = epf_test->epc_features; struct pci_epc *epc = epf->epc; struct device *dev = &epf->dev; bool linkup_notifier = false; - bool msix_capable = false; - bool msi_capable = true; int ret; - epc_features = pci_epc_get_features(epc, epf->func_no, epf->vfunc_no); - if (epc_features) { - msix_capable = epc_features->msix_capable; - msi_capable = epc_features->msi_capable; - } + epf_test->dma_supported = true; + + ret = pci_epf_test_init_dma_chan(epf_test); + if (ret) + epf_test->dma_supported = false; if (epf->vfunc_no <= 1) { ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no, header); @@ -761,7 +755,7 @@ static int pci_epf_test_core_init(struct pci_epf *epf) if (ret) return ret; - if (msi_capable) { + if (epc_features->msi_capable) { ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no, epf->msi_interrupts); if (ret) { @@ -770,7 +764,7 @@ static int pci_epf_test_core_init(struct pci_epf *epf) } } - if (msix_capable) { + if (epc_features->msix_capable) { ret = pci_epc_set_msix(epc, epf->func_no, epf->vfunc_no, epf->msix_interrupts, epf_test->test_reg_bar, @@ -788,6 +782,15 @@ static int pci_epf_test_core_init(struct pci_epf *epf) return 0; } +static void pci_epf_test_epc_deinit(struct pci_epf *epf) +{ + struct pci_epf_test *epf_test = epf_get_drvdata(epf); + + cancel_delayed_work(&epf_test->cmd_handler); + pci_epf_test_clean_dma_chan(epf_test); + pci_epf_test_clear_bar(epf); +} + static int pci_epf_test_link_up(struct pci_epf *epf) { struct pci_epf_test *epf_test = epf_get_drvdata(epf); @@ -798,9 +801,20 @@ static int pci_epf_test_link_up(struct pci_epf *epf) return 0; } +static int pci_epf_test_link_down(struct pci_epf *epf) +{ + struct pci_epf_test *epf_test = epf_get_drvdata(epf); + + cancel_delayed_work_sync(&epf_test->cmd_handler); + + return 0; +} + static const struct pci_epc_event_ops pci_epf_test_event_ops = { - .core_init = pci_epf_test_core_init, + .epc_init = pci_epf_test_epc_init, + .epc_deinit = pci_epf_test_epc_deinit, .link_up = pci_epf_test_link_up, + .link_down = pci_epf_test_link_down, }; static int pci_epf_test_alloc_space(struct pci_epf *epf) @@ -810,19 +824,15 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) size_t msix_table_size = 0; size_t test_reg_bar_size; size_t pba_size = 0; - bool msix_capable; void *base; enum pci_barno test_reg_bar = epf_test->test_reg_bar; enum pci_barno bar; - const struct pci_epc_features *epc_features; + const struct pci_epc_features *epc_features = epf_test->epc_features; size_t test_reg_size; - epc_features = epf_test->epc_features; - test_reg_bar_size = ALIGN(sizeof(struct pci_epf_test_reg), 128); - msix_capable = epc_features->msix_capable; - if (msix_capable) { + if (epc_features->msix_capable) { msix_table_size = PCI_MSIX_ENTRY_SIZE * epf->msix_interrupts; epf_test->msix_table_offset = test_reg_bar_size; /* Align to QWORD or 8 Bytes */ @@ -857,6 +867,20 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) return 0; } +static void pci_epf_test_free_space(struct pci_epf *epf) +{ + struct pci_epf_test *epf_test = epf_get_drvdata(epf); + int bar; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (!epf_test->reg[bar]) + continue; + + pci_epf_free_space(epf, epf_test->reg[bar], bar, + PRIMARY_INTERFACE); + } +} + static int pci_epf_test_bind(struct pci_epf *epf) { int ret; @@ -885,15 +909,22 @@ static int pci_epf_test_bind(struct pci_epf *epf) if (ret) return ret; - epf_test->dma_supported = true; - - ret = pci_epf_test_init_dma_chan(epf_test); - if (ret) - epf_test->dma_supported = false; - return 0; } +static void pci_epf_test_unbind(struct pci_epf *epf) +{ + struct pci_epf_test *epf_test = epf_get_drvdata(epf); + struct pci_epc *epc = epf->epc; + + cancel_delayed_work(&epf_test->cmd_handler); + if (epc->init_complete) { + pci_epf_test_clean_dma_chan(epf_test); + pci_epf_test_clear_bar(epf); + } + pci_epf_test_free_space(epf); +} + static const struct pci_epf_device_id pci_epf_test_ids[] = { { .name = "pci_epf_test", diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c index 8e779eecd62d..874cb097b093 100644 --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c @@ -799,8 +799,9 @@ err_config_interrupt: */ static void epf_ntb_epc_cleanup(struct epf_ntb *ntb) { - epf_ntb_db_bar_clear(ntb); epf_ntb_mw_bar_clear(ntb, ntb->num_mws); + epf_ntb_db_bar_clear(ntb); + epf_ntb_config_sspad_bar_clear(ntb); } #define EPF_NTB_R(_name) \ @@ -1018,8 +1019,10 @@ static int vpci_scan_bus(void *sysdata) struct epf_ntb *ndev = sysdata; vpci_bus = pci_scan_bus(ndev->vbus_number, &vpci_ops, sysdata); - if (vpci_bus) - pr_err("create pci bus\n"); + if (!vpci_bus) { + pr_err("create pci bus failed\n"); + return -EINVAL; + } pci_bus_add_devices(vpci_bus); @@ -1335,13 +1338,19 @@ static int epf_ntb_bind(struct pci_epf *epf) ret = pci_register_driver(&vntb_pci_driver); if (ret) { dev_err(dev, "failure register vntb pci driver\n"); - goto err_bar_alloc; + goto err_epc_cleanup; } - vpci_scan_bus(ntb); + ret = vpci_scan_bus(ntb); + if (ret) + goto err_unregister; return 0; +err_unregister: + pci_unregister_driver(&vntb_pci_driver); +err_epc_cleanup: + epf_ntb_epc_cleanup(ntb); err_bar_alloc: epf_ntb_config_spad_bar_free(ntb); diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index 3b21e28f9b59..d712c7a866d2 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -23,7 +23,6 @@ struct pci_epf_group { struct config_group group; struct config_group primary_epc_group; struct config_group secondary_epc_group; - struct config_group *type_group; struct delayed_work cfs_work; struct pci_epf *epf; int index; diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 47d27ec7439d..84309dfe0c68 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -14,7 +14,9 @@ #include #include -static struct class *pci_epc_class; +static const struct class pci_epc_class = { + .name = "pci_epc", +}; static void devm_pci_epc_release(struct device *dev, void *res) { @@ -60,7 +62,7 @@ struct pci_epc *pci_epc_get(const char *epc_name) struct device *dev; struct class_dev_iter iter; - class_dev_iter_init(&iter, pci_epc_class, NULL, NULL); + class_dev_iter_init(&iter, &pci_epc_class, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) { if (strcmp(epc_name, dev_name(dev))) continue; @@ -727,9 +729,9 @@ void pci_epc_linkdown(struct pci_epc *epc) EXPORT_SYMBOL_GPL(pci_epc_linkdown); /** - * pci_epc_init_notify() - Notify the EPF device that EPC device's core - * initialization is completed. - * @epc: the EPC device whose core initialization is completed + * pci_epc_init_notify() - Notify the EPF device that EPC device initialization + * is completed. + * @epc: the EPC device whose initialization is completed * * Invoke to Notify the EPF device that the EPC device's initialization * is completed. @@ -744,8 +746,8 @@ void pci_epc_init_notify(struct pci_epc *epc) mutex_lock(&epc->list_lock); list_for_each_entry(epf, &epc->pci_epf, list) { mutex_lock(&epf->lock); - if (epf->event_ops && epf->event_ops->core_init) - epf->event_ops->core_init(epf); + if (epf->event_ops && epf->event_ops->epc_init) + epf->event_ops->epc_init(epf); mutex_unlock(&epf->lock); } epc->init_complete = true; @@ -756,7 +758,7 @@ EXPORT_SYMBOL_GPL(pci_epc_init_notify); /** * pci_epc_notify_pending_init() - Notify the pending EPC device initialization * complete to the EPF device - * @epc: the EPC device whose core initialization is pending to be notified + * @epc: the EPC device whose initialization is pending to be notified * @epf: the EPF device to be notified * * Invoke to notify the pending EPC device initialization complete to the EPF @@ -767,22 +769,20 @@ void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf) { if (epc->init_complete) { mutex_lock(&epf->lock); - if (epf->event_ops && epf->event_ops->core_init) - epf->event_ops->core_init(epf); + if (epf->event_ops && epf->event_ops->epc_init) + epf->event_ops->epc_init(epf); mutex_unlock(&epf->lock); } } EXPORT_SYMBOL_GPL(pci_epc_notify_pending_init); /** - * pci_epc_bme_notify() - Notify the EPF device that the EPC device has received - * the BME event from the Root complex - * @epc: the EPC device that received the BME event + * pci_epc_deinit_notify() - Notify the EPF device about EPC deinitialization + * @epc: the EPC device whose deinitialization is completed * - * Invoke to Notify the EPF device that the EPC device has received the Bus - * Master Enable (BME) event from the Root complex + * Invoke to notify the EPF device that the EPC deinitialization is completed. */ -void pci_epc_bme_notify(struct pci_epc *epc) +void pci_epc_deinit_notify(struct pci_epc *epc) { struct pci_epf *epf; @@ -792,13 +792,41 @@ void pci_epc_bme_notify(struct pci_epc *epc) mutex_lock(&epc->list_lock); list_for_each_entry(epf, &epc->pci_epf, list) { mutex_lock(&epf->lock); - if (epf->event_ops && epf->event_ops->bme) - epf->event_ops->bme(epf); + if (epf->event_ops && epf->event_ops->epc_deinit) + epf->event_ops->epc_deinit(epf); + mutex_unlock(&epf->lock); + } + epc->init_complete = false; + mutex_unlock(&epc->list_lock); +} +EXPORT_SYMBOL_GPL(pci_epc_deinit_notify); + +/** + * pci_epc_bus_master_enable_notify() - Notify the EPF device that the EPC + * device has received the Bus Master + * Enable event from the Root complex + * @epc: the EPC device that received the Bus Master Enable event + * + * Notify the EPF device that the EPC device has generated the Bus Master Enable + * event due to host setting the Bus Master Enable bit in the Command register. + */ +void pci_epc_bus_master_enable_notify(struct pci_epc *epc) +{ + struct pci_epf *epf; + + if (IS_ERR_OR_NULL(epc)) + return; + + mutex_lock(&epc->list_lock); + list_for_each_entry(epf, &epc->pci_epf, list) { + mutex_lock(&epf->lock); + if (epf->event_ops && epf->event_ops->bus_master_enable) + epf->event_ops->bus_master_enable(epf); mutex_unlock(&epf->lock); } mutex_unlock(&epc->list_lock); } -EXPORT_SYMBOL_GPL(pci_epc_bme_notify); +EXPORT_SYMBOL_GPL(pci_epc_bus_master_enable_notify); /** * pci_epc_destroy() - destroy the EPC device @@ -867,7 +895,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops, INIT_LIST_HEAD(&epc->pci_epf); device_initialize(&epc->dev); - epc->dev.class = pci_epc_class; + epc->dev.class = &pci_epc_class; epc->dev.parent = dev; epc->dev.release = pci_epc_release; epc->ops = ops; @@ -927,20 +955,13 @@ EXPORT_SYMBOL_GPL(__devm_pci_epc_create); static int __init pci_epc_init(void) { - pci_epc_class = class_create("pci_epc"); - if (IS_ERR(pci_epc_class)) { - pr_err("failed to create pci epc class --> %ld\n", - PTR_ERR(pci_epc_class)); - return PTR_ERR(pci_epc_class); - } - - return 0; + return class_register(&pci_epc_class); } module_init(pci_epc_init); static void __exit pci_epc_exit(void) { - class_destroy(pci_epc_class); + class_unregister(&pci_epc_class); } module_exit(pci_epc_exit); diff --git a/drivers/pci/hotplug/acpiphp_ampere_altra.c b/drivers/pci/hotplug/acpiphp_ampere_altra.c index 3fddd04851b6..f5c9e741c1d4 100644 --- a/drivers/pci/hotplug/acpiphp_ampere_altra.c +++ b/drivers/pci/hotplug/acpiphp_ampere_altra.c @@ -124,4 +124,5 @@ static struct platform_driver altra_led_driver = { module_platform_driver(altra_led_driver); MODULE_AUTHOR("D Scott Phillips "); +MODULE_DESCRIPTION("ACPI PCI Hot Plug Extension for Ampere Altra"); MODULE_LICENSE("GPL"); diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e0a614acee05..273dd8c66f4e 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -46,6 +46,9 @@ extern int pciehp_poll_time; /** * struct controller - PCIe hotplug controller * @pcie: pointer to the controller's PCIe port service device + * @dsn: cached copy of Device Serial Number of Function 0 in the hotplug slot + * (PCIe r6.2 sec 7.9.3); used to determine whether a hotplugged device + * was replaced with a different one during system sleep * @slot_cap: cached copy of the Slot Capabilities register * @inband_presence_disabled: In-Band Presence Detect Disable supported by * controller and disabled per spec recommendation (PCIe r5.0, appendix I @@ -87,6 +90,7 @@ extern int pciehp_poll_time; */ struct controller { struct pcie_device *pcie; + u64 dsn; u32 slot_cap; /* capabilities and quirks */ unsigned int inband_presence_disabled:1; diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index ddd55ad97a58..ff458e692fed 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -284,6 +284,32 @@ static int pciehp_suspend(struct pcie_device *dev) return 0; } +static bool pciehp_device_replaced(struct controller *ctrl) +{ + struct pci_dev *pdev __free(pci_dev_put); + u32 reg; + + pdev = pci_get_slot(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); + if (!pdev) + return true; + + if (pci_read_config_dword(pdev, PCI_VENDOR_ID, ®) || + reg != (pdev->vendor | (pdev->device << 16)) || + pci_read_config_dword(pdev, PCI_CLASS_REVISION, ®) || + reg != (pdev->revision | (pdev->class << 8))) + return true; + + if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL && + (pci_read_config_dword(pdev, PCI_SUBSYSTEM_VENDOR_ID, ®) || + reg != (pdev->subsystem_vendor | (pdev->subsystem_device << 16)))) + return true; + + if (pci_get_dsn(pdev) != ctrl->dsn) + return true; + + return false; +} + static int pciehp_resume_noirq(struct pcie_device *dev) { struct controller *ctrl = get_service_data(dev); @@ -293,9 +319,23 @@ static int pciehp_resume_noirq(struct pcie_device *dev) ctrl->cmd_busy = true; /* clear spurious events from rediscovery of inserted card */ - if (ctrl->state == ON_STATE || ctrl->state == BLINKINGOFF_STATE) + if (ctrl->state == ON_STATE || ctrl->state == BLINKINGOFF_STATE) { pcie_clear_hotplug_events(ctrl); + /* + * If hotplugged device was replaced with a different one + * during system sleep, mark the old device disconnected + * (to prevent its driver from accessing the new device) + * and synthesize a Presence Detect Changed event. + */ + if (pciehp_device_replaced(ctrl)) { + ctrl_dbg(ctrl, "device replaced during system sleep\n"); + pci_walk_bus(ctrl->pcie->port->subordinate, + pci_dev_set_disconnected, NULL); + pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC); + } + } + return 0; } #endif diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index b1d0a1b3917d..061f01f60db4 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1055,6 +1055,11 @@ struct controller *pcie_init(struct pcie_device *dev) } } + pdev = pci_get_slot(subordinate, PCI_DEVFN(0, 0)); + if (pdev) + ctrl->dsn = pci_get_dsn(pdev); + pci_dev_put(pdev); + return ctrl; } diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index ad12515a4a12..65e50bee1a8c 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -72,6 +72,10 @@ int pciehp_configure_device(struct controller *ctrl) pci_bus_add_devices(parent); down_read_nested(&ctrl->reset_lock, ctrl->depth); + dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); + ctrl->dsn = pci_get_dsn(dev); + pci_dev_put(dev); + out: pci_unlock_rescan_remove(); return ret; diff --git a/drivers/pci/iomap.c b/drivers/pci/iomap.c index c9725428e387..a715a4803c95 100644 --- a/drivers/pci/iomap.c +++ b/drivers/pci/iomap.c @@ -23,6 +23,10 @@ * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR from offset to the end, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). * */ void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, @@ -63,6 +67,10 @@ EXPORT_SYMBOL(pci_iomap_range); * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR from offset to the end, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). * */ void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, @@ -106,6 +114,10 @@ EXPORT_SYMBOL_GPL(pci_iomap_wc_range); * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR without checking for its length first, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). If you need automatic cleanup, use pcim_iomap(). * */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { @@ -127,6 +139,10 @@ EXPORT_SYMBOL(pci_iomap); * * @maxlen specifies the maximum length to map. If you want to get access to * the complete BAR without checking for its length first, pass %0 here. + * + * NOTE: + * This function is never managed, even if you initialized with + * pcim_enable_device(). * */ void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long maxlen) { diff --git a/drivers/pci/of.c b/drivers/pci/of.c index b908fe1ae951..dacea3fc5128 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -239,28 +239,62 @@ int of_get_pci_domain_nr(struct device_node *node) } EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); +/** + * of_pci_preserve_config - Return true if the boot configuration needs to + * be preserved + * @node: Device tree node. + * + * Look for "linux,pci-probe-only" property for a given PCI controller's + * node and return true if found. Also look in the chosen node if the + * property is not found in the given controller's node. Having this + * property ensures that the kernel doesn't reconfigure the BARs and bridge + * windows that are already done by the platform firmware. + * + * Return: true if the property exists; false otherwise. + */ +bool of_pci_preserve_config(struct device_node *node) +{ + u32 val = 0; + int ret; + + if (!node) { + pr_warn("device node is NULL, trying with of_chosen\n"); + node = of_chosen; + } + +retry: + ret = of_property_read_u32(node, "linux,pci-probe-only", &val); + if (ret) { + if (ret == -ENODATA || ret == -EOVERFLOW) { + pr_warn("Incorrect value for linux,pci-probe-only in %pOF, ignoring\n", + node); + return false; + } + if (ret == -EINVAL) { + if (node == of_chosen) + return false; + + node = of_chosen; + goto retry; + } + } + + if (val) + return true; + else + return false; +} + /** * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only * is present and valid */ void of_pci_check_probe_only(void) { - u32 val; - int ret; - - ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val); - if (ret) { - if (ret == -ENODATA || ret == -EOVERFLOW) - pr_warn("linux,pci-probe-only without valid value, ignoring\n"); - return; - } - - if (val) + if (of_pci_preserve_config(of_chosen)) pci_add_flags(PCI_PROBE_ONLY); else pci_clear_flags(PCI_PROBE_ONLY); - - pr_info("PROBE_ONLY %s\n", val ? "enabled" : "disabled"); } EXPORT_SYMBOL_GPL(of_pci_check_probe_only); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 004575091596..9cc447da9475 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -119,6 +119,28 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) return (phys_addr_t)mcfg_addr; } +bool pci_acpi_preserve_config(struct pci_host_bridge *host_bridge) +{ + if (ACPI_HANDLE(&host_bridge->dev)) { + union acpi_object *obj; + + /* + * Evaluate the "PCI Boot Configuration" _DSM Function. If it + * exists and returns 0, we must preserve any PCI resource + * assignments made by firmware for this host bridge. + */ + obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(&host_bridge->dev), + &pci_acpi_dsm_guid, + 1, DSM_PCI_PRESERVE_BOOT_CONFIG, + NULL, ACPI_TYPE_INTEGER); + if (obj && obj->integer.value == 0) + return true; + ACPI_FREE(obj); + } + + return false; +} + /* _HPX PCI Setting Record (Type 0); same as _HPP */ struct hpx_type0 { u32 revision; /* Not present in _HPP */ diff --git a/drivers/pci/pci-mid.c b/drivers/pci/pci-mid.c index fbfd78127123..bed9f0755271 100644 --- a/drivers/pci/pci-mid.c +++ b/drivers/pci/pci-mid.c @@ -38,8 +38,8 @@ pci_power_t mid_pci_get_power_state(struct pci_dev *pdev) * arch/x86/platform/intel-mid/pwr.c. */ static const struct x86_cpu_id lpss_cpu_ids[] = { - X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL_MID, NULL), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, NULL), + X86_MATCH_VFM(INTEL_ATOM_SALTWELL_MID, NULL), + X86_MATCH_VFM(INTEL_ATOM_SILVERMONT_MID, NULL), {} }; diff --git a/drivers/pci/pci-pf-stub.c b/drivers/pci/pci-pf-stub.c index 45855a5e9fca..da4db4928907 100644 --- a/drivers/pci/pci-pf-stub.c +++ b/drivers/pci/pci-pf-stub.c @@ -39,4 +39,5 @@ static struct pci_driver pf_stub_driver = { }; module_pci_driver(pf_stub_driver); +MODULE_DESCRIPTION("SR-IOV PF stub driver with no functionality"); MODULE_LICENSE("GPL"); diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index d1f4c1ce7bd1..9bc478df4e8f 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c @@ -92,5 +92,6 @@ static void __exit pci_stub_exit(void) module_init(pci_stub_init); module_exit(pci_stub_exit); +MODULE_DESCRIPTION("VM device assignment stub driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Chris Wright "); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 35fb1f17a589..e3a49f66982d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -946,30 +946,67 @@ void pci_request_acs(void) } static const char *disable_acs_redir_param; +static const char *config_acs_param; -/** - * pci_disable_acs_redir - disable ACS redirect capabilities - * @dev: the PCI device - * - * For only devices specified in the disable_acs_redir parameter. - */ -static void pci_disable_acs_redir(struct pci_dev *dev) -{ - int ret = 0; - const char *p; - int pos; +struct pci_acs { + u16 cap; u16 ctrl; + u16 fw_ctrl; +}; - if (!disable_acs_redir_param) +static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, + const char *p, u16 mask, u16 flags) +{ + char *delimit; + int ret = 0; + + if (!p) return; - p = disable_acs_redir_param; while (*p) { + if (!mask) { + /* Check for ACS flags */ + delimit = strstr(p, "@"); + if (delimit) { + int end; + u32 shift = 0; + + end = delimit - p - 1; + + while (end > -1) { + if (*(p + end) == '0') { + mask |= 1 << shift; + shift++; + end--; + } else if (*(p + end) == '1') { + mask |= 1 << shift; + flags |= 1 << shift; + shift++; + end--; + } else if ((*(p + end) == 'x') || (*(p + end) == 'X')) { + shift++; + end--; + } else { + pci_err(dev, "Invalid ACS flags... Ignoring\n"); + return; + } + } + p = delimit + 1; + } else { + pci_err(dev, "ACS Flags missing\n"); + return; + } + } + + if (mask & ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | PCI_ACS_CR | + PCI_ACS_UF | PCI_ACS_EC | PCI_ACS_DT)) { + pci_err(dev, "Invalid ACS flags specified\n"); + return; + } + ret = pci_dev_str_match(dev, p, &p); if (ret < 0) { - pr_info_once("PCI: Can't parse disable_acs_redir parameter: %s\n", - disable_acs_redir_param); - + pr_info_once("PCI: Can't parse ACS command line parameter\n"); break; } else if (ret == 1) { /* Found a match */ @@ -989,56 +1026,38 @@ static void pci_disable_acs_redir(struct pci_dev *dev) if (!pci_dev_specific_disable_acs_redir(dev)) return; - pos = dev->acs_cap; - if (!pos) { - pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n"); - return; - } + pci_dbg(dev, "ACS mask = %#06x\n", mask); + pci_dbg(dev, "ACS flags = %#06x\n", flags); - pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); + /* If mask is 0 then we copy the bit from the firmware setting. */ + caps->ctrl = (caps->ctrl & ~mask) | (caps->fw_ctrl & mask); + caps->ctrl |= flags; - /* P2P Request & Completion Redirect */ - ctrl &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC); - - pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); - - pci_info(dev, "disabled ACS redirect\n"); + pci_info(dev, "Configured ACS to %#06x\n", caps->ctrl); } /** * pci_std_enable_acs - enable ACS on devices using standard ACS capabilities * @dev: the PCI device + * @caps: default ACS controls */ -static void pci_std_enable_acs(struct pci_dev *dev) +static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps) { - int pos; - u16 cap; - u16 ctrl; - - pos = dev->acs_cap; - if (!pos) - return; - - pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); - pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); - /* Source Validation */ - ctrl |= (cap & PCI_ACS_SV); + caps->ctrl |= (caps->cap & PCI_ACS_SV); /* P2P Request Redirect */ - ctrl |= (cap & PCI_ACS_RR); + caps->ctrl |= (caps->cap & PCI_ACS_RR); /* P2P Completion Redirect */ - ctrl |= (cap & PCI_ACS_CR); + caps->ctrl |= (caps->cap & PCI_ACS_CR); /* Upstream Forwarding */ - ctrl |= (cap & PCI_ACS_UF); + caps->ctrl |= (caps->cap & PCI_ACS_UF); /* Enable Translation Blocking for external devices and noats */ if (pci_ats_disabled() || dev->external_facing || dev->untrusted) - ctrl |= (cap & PCI_ACS_TB); - - pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); + caps->ctrl |= (caps->cap & PCI_ACS_TB); } /** @@ -1047,23 +1066,33 @@ static void pci_std_enable_acs(struct pci_dev *dev) */ static void pci_enable_acs(struct pci_dev *dev) { - if (!pci_acs_enable) - goto disable_acs_redir; + struct pci_acs caps; + int pos; - if (!pci_dev_specific_enable_acs(dev)) - goto disable_acs_redir; + pos = dev->acs_cap; + if (!pos) + return; - pci_std_enable_acs(dev); + pci_read_config_word(dev, pos + PCI_ACS_CAP, &caps.cap); + pci_read_config_word(dev, pos + PCI_ACS_CTRL, &caps.ctrl); + caps.fw_ctrl = caps.ctrl; + + /* If an iommu is present we start with kernel default caps */ + if (pci_acs_enable) { + if (pci_dev_specific_enable_acs(dev)) + pci_std_enable_acs(dev, &caps); + } -disable_acs_redir: /* - * Note: pci_disable_acs_redir() must be called even if ACS was not - * enabled by the kernel because it may have been enabled by - * platform firmware. So if we are told to disable it, we should - * always disable it after setting the kernel's default - * preferences. + * Always apply caps from the command line, even if there is no iommu. + * Trust that the admin has a reason to change the ACS settings. */ - pci_disable_acs_redir(dev); + __pci_config_acs(dev, &caps, disable_acs_redir_param, + PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC, + ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC)); + __pci_config_acs(dev, &caps, config_acs_param, 0, 0); + + pci_write_config_word(dev, pos + PCI_ACS_CTRL, caps.ctrl); } /** @@ -2218,12 +2247,6 @@ void pci_disable_enabled_device(struct pci_dev *dev) */ void pci_disable_device(struct pci_dev *dev) { - struct pci_devres *dr; - - dr = find_pci_dr(dev); - if (dr) - dr->enabled = 0; - dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0, "disabling already-disabled device"); @@ -3872,7 +3895,15 @@ EXPORT_SYMBOL(pci_enable_atomic_ops_to_root); */ void pci_release_region(struct pci_dev *pdev, int bar) { - struct pci_devres *dr; + /* + * This is done for backwards compatibility, because the old PCI devres + * API had a mode in which the function became managed if it had been + * enabled with pcim_enable_device() instead of pci_enable_device(). + */ + if (pci_is_managed(pdev)) { + pcim_release_region(pdev, bar); + return; + } if (pci_resource_len(pdev, bar) == 0) return; @@ -3882,10 +3913,6 @@ void pci_release_region(struct pci_dev *pdev, int bar) else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) release_mem_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)); - - dr = find_pci_dr(pdev); - if (dr) - dr->region_mask &= ~(1 << bar); } EXPORT_SYMBOL(pci_release_region); @@ -3896,6 +3923,8 @@ EXPORT_SYMBOL(pci_release_region); * @res_name: Name to be associated with resource. * @exclusive: whether the region access is exclusive or not * + * Returns: 0 on success, negative error code on failure. + * * Mark the PCI region associated with PCI device @pdev BAR @bar as * being reserved by owner @res_name. Do not access any * address inside the PCI regions unless this call returns @@ -3911,7 +3940,12 @@ EXPORT_SYMBOL(pci_release_region); static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_name, int exclusive) { - struct pci_devres *dr; + if (pci_is_managed(pdev)) { + if (exclusive == IORESOURCE_EXCLUSIVE) + return pcim_request_region_exclusive(pdev, bar, res_name); + + return pcim_request_region(pdev, bar, res_name); + } if (pci_resource_len(pdev, bar) == 0) return 0; @@ -3927,10 +3961,6 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, goto err_out; } - dr = find_pci_dr(pdev); - if (dr) - dr->region_mask |= 1 << bar; - return 0; err_out: @@ -3945,6 +3975,8 @@ err_out: * @bar: BAR to be reserved * @res_name: Name to be associated with resource * + * Returns: 0 on success, negative error code on failure. + * * Mark the PCI region associated with PCI device @pdev BAR @bar as * being reserved by owner @res_name. Do not access any * address inside the PCI regions unless this call returns @@ -3952,6 +3984,11 @@ err_out: * * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. + * + * NOTE: + * This is a "hybrid" function: It's normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. This hybrid feature is + * DEPRECATED! If you want managed cleanup, use the pcim_* functions instead. */ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) { @@ -4002,6 +4039,13 @@ err_out: * @pdev: PCI device whose resources are to be reserved * @bars: Bitmask of BARs to be requested * @res_name: Name to be associated with resource + * + * Returns: 0 on success, negative error code on failure. + * + * NOTE: + * This is a "hybrid" function: It's normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. This hybrid feature is + * DEPRECATED! If you want managed cleanup, use the pcim_* functions instead. */ int pci_request_selected_regions(struct pci_dev *pdev, int bars, const char *res_name) @@ -4010,6 +4054,19 @@ int pci_request_selected_regions(struct pci_dev *pdev, int bars, } EXPORT_SYMBOL(pci_request_selected_regions); +/** + * pci_request_selected_regions_exclusive - Request regions exclusively + * @pdev: PCI device to request regions from + * @bars: bit mask of BARs to request + * @res_name: name to be associated with the requests + * + * Returns: 0 on success, negative error code on failure. + * + * NOTE: + * This is a "hybrid" function: It's normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. This hybrid feature is + * DEPRECATED! If you want managed cleanup, use the pcim_* functions instead. + */ int pci_request_selected_regions_exclusive(struct pci_dev *pdev, int bars, const char *res_name) { @@ -4027,7 +4084,6 @@ EXPORT_SYMBOL(pci_request_selected_regions_exclusive); * successful call to pci_request_regions(). Call this function only * after all use of the PCI regions has ceased. */ - void pci_release_regions(struct pci_dev *pdev) { pci_release_selected_regions(pdev, (1 << PCI_STD_NUM_BARS) - 1); @@ -4046,6 +4102,11 @@ EXPORT_SYMBOL(pci_release_regions); * * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. + * + * NOTE: + * This is a "hybrid" function: It's normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. This hybrid feature is + * DEPRECATED! If you want managed cleanup, use the pcim_* functions instead. */ int pci_request_regions(struct pci_dev *pdev, const char *res_name) { @@ -4059,6 +4120,8 @@ EXPORT_SYMBOL(pci_request_regions); * @pdev: PCI device whose resources are to be reserved * @res_name: Name to be associated with resource. * + * Returns: 0 on success, negative error code on failure. + * * Mark all PCI regions associated with PCI device @pdev as being reserved * by owner @res_name. Do not access any address inside the PCI regions * unless this call returns successfully. @@ -4068,6 +4131,11 @@ EXPORT_SYMBOL(pci_request_regions); * * Returns 0 on success, or %EBUSY on error. A warning message is also * printed on failure. + * + * NOTE: + * This is a "hybrid" function: It's normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. This hybrid feature is + * DEPRECATED! If you want managed cleanup, use the pcim_* functions instead. */ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) { @@ -4399,11 +4467,22 @@ void pci_disable_parity(struct pci_dev *dev) * @enable: boolean: whether to enable or disable PCI INTx * * Enables/disables PCI INTx for device @pdev + * + * NOTE: + * This is a "hybrid" function: It's normally unmanaged, but becomes managed + * when pcim_enable_device() has been called in advance. This hybrid feature is + * DEPRECATED! If you want managed cleanup, use pcim_intx() instead. */ void pci_intx(struct pci_dev *pdev, int enable) { u16 pci_command, new; + /* Preserve the "hybrid" behavior for backwards compatibility */ + if (pci_is_managed(pdev)) { + WARN_ON_ONCE(pcim_intx(pdev, enable) != 0); + return; + } + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); if (enable) @@ -4411,17 +4490,8 @@ void pci_intx(struct pci_dev *pdev, int enable) else new = pci_command | PCI_COMMAND_INTX_DISABLE; - if (new != pci_command) { - struct pci_devres *dr; - + if (new != pci_command) pci_write_config_word(pdev, PCI_COMMAND, new); - - dr = find_pci_dr(pdev); - if (dr && !dr->restore_intx) { - dr->restore_intx = 1; - dr->orig_intx = !enable; - } - } } EXPORT_SYMBOL_GPL(pci_intx); @@ -4753,7 +4823,7 @@ static int pci_bus_max_d3cold_delay(const struct pci_bus *bus) */ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) { - struct pci_dev *child; + struct pci_dev *child __free(pci_dev_put) = NULL; int delay; if (pci_dev_is_disconnected(dev)) @@ -4782,8 +4852,8 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) return 0; } - child = list_first_entry(&dev->subordinate->devices, struct pci_dev, - bus_list); + child = pci_dev_get(list_first_entry(&dev->subordinate->devices, + struct pci_dev, bus_list)); up_read(&pci_bus_sem); /* @@ -4883,6 +4953,9 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev) */ int pci_bridge_secondary_bus_reset(struct pci_dev *dev) { + if (!dev->block_cfg_access) + pci_warn_once(dev, "unlocked secondary bus reset via: %pS\n", + __builtin_return_address(0)); pcibios_reset_secondary_bus(dev); return pci_bridge_wait_for_secondary_bus(dev, "bus reset"); @@ -5441,10 +5514,12 @@ static void pci_bus_lock(struct pci_bus *bus) { struct pci_dev *dev; + pci_dev_lock(bus->self); list_for_each_entry(dev, &bus->devices, bus_list) { - pci_dev_lock(dev); if (dev->subordinate) pci_bus_lock(dev->subordinate); + else + pci_dev_lock(dev); } } @@ -5456,8 +5531,10 @@ static void pci_bus_unlock(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->subordinate) pci_bus_unlock(dev->subordinate); - pci_dev_unlock(dev); + else + pci_dev_unlock(dev); } + pci_dev_unlock(bus->self); } /* Return 1 on successful lock, 0 on contention */ @@ -5465,15 +5542,15 @@ static int pci_bus_trylock(struct pci_bus *bus) { struct pci_dev *dev; + if (!pci_dev_trylock(bus->self)) + return 0; + list_for_each_entry(dev, &bus->devices, bus_list) { - if (!pci_dev_trylock(dev)) - goto unlock; if (dev->subordinate) { - if (!pci_bus_trylock(dev->subordinate)) { - pci_dev_unlock(dev); + if (!pci_bus_trylock(dev->subordinate)) goto unlock; - } - } + } else if (!pci_dev_trylock(dev)) + goto unlock; } return 1; @@ -5481,8 +5558,10 @@ unlock: list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) { if (dev->subordinate) pci_bus_unlock(dev->subordinate); - pci_dev_unlock(dev); + else + pci_dev_unlock(dev); } + pci_dev_unlock(bus->self); return 0; } @@ -5514,9 +5593,10 @@ static void pci_slot_lock(struct pci_slot *slot) list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot != slot) continue; - pci_dev_lock(dev); if (dev->subordinate) pci_bus_lock(dev->subordinate); + else + pci_dev_lock(dev); } } @@ -5542,14 +5622,13 @@ static int pci_slot_trylock(struct pci_slot *slot) list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot != slot) continue; - if (!pci_dev_trylock(dev)) - goto unlock; if (dev->subordinate) { if (!pci_bus_trylock(dev->subordinate)) { pci_dev_unlock(dev); goto unlock; } - } + } else if (!pci_dev_trylock(dev)) + goto unlock; } return 1; @@ -5560,7 +5639,8 @@ unlock: continue; if (dev->subordinate) pci_bus_unlock(dev->subordinate); - pci_dev_unlock(dev); + else + pci_dev_unlock(dev); } return 0; } @@ -6019,24 +6099,7 @@ int pcie_link_speed_mbps(struct pci_dev *pdev) if (err) return err; - switch (to_pcie_link_speed(lnksta)) { - case PCIE_SPEED_2_5GT: - return 2500; - case PCIE_SPEED_5_0GT: - return 5000; - case PCIE_SPEED_8_0GT: - return 8000; - case PCIE_SPEED_16_0GT: - return 16000; - case PCIE_SPEED_32_0GT: - return 32000; - case PCIE_SPEED_64_0GT: - return 64000; - default: - break; - } - - return -EINVAL; + return pcie_dev_speed_mbps(to_pcie_link_speed(lnksta)); } EXPORT_SYMBOL(pcie_link_speed_mbps); @@ -6839,6 +6902,8 @@ static int __init pci_setup(char *str) pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS); } else if (!strncmp(str, "disable_acs_redir=", 18)) { disable_acs_redir_param = str + 18; + } else if (!strncmp(str, "config_acs=", 11)) { + config_acs_param = str + 11; } else { pr_err("PCI: Unknown option `%s'\n", str); } @@ -6863,6 +6928,7 @@ static int __init pci_realloc_setup_params(void) resource_alignment_param = kstrdup(resource_alignment_param, GFP_KERNEL); disable_acs_redir_param = kstrdup(disable_acs_redir_param, GFP_KERNEL); + config_acs_param = kstrdup(config_acs_param, GFP_KERNEL); return 0; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fd44565c4756..79c8398f3938 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -16,12 +16,55 @@ /* Power stable to PERST# inactive from PCIe card Electromechanical Spec */ #define PCIE_T_PVPERL_MS 100 +/* + * End of conventional reset (PERST# de-asserted) to first configuration + * request (device able to respond with a "Request Retry Status" completion), + * from PCIe r6.0, sec 6.6.1. + */ +#define PCIE_T_RRS_READY_MS 100 + /* * PCIe r6.0, sec 5.3.3.2.1 * Recommends 1ms to 10ms timeout to check L2 ready. */ #define PCIE_PME_TO_L2_TIMEOUT_US 10000 +/* + * PCIe r6.0, sec 6.6.1 + * + * - "With a Downstream Port that does not support Link speeds greater + * than 5.0 GT/s, software must wait a minimum of 100 ms following exit + * from a Conventional Reset before sending a Configuration Request to + * the device immediately below that Port." + * + * - "With a Downstream Port that supports Link speeds greater than + * 5.0 GT/s, software must wait a minimum of 100 ms after Link training + * completes before sending a Configuration Request to the device + * immediately below that Port." + */ +#define PCIE_RESET_CONFIG_DEVICE_WAIT_MS 100 + +/* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ +#define PCIE_MSG_TYPE_R_RC 0 +#define PCIE_MSG_TYPE_R_ADDR 1 +#define PCIE_MSG_TYPE_R_ID 2 +#define PCIE_MSG_TYPE_R_BC 3 +#define PCIE_MSG_TYPE_R_LOCAL 4 +#define PCIE_MSG_TYPE_R_GATHER 5 + +/* Power Management Messages; PCIe r6.0, sec 2.2.8.2 */ +#define PCIE_MSG_CODE_PME_TURN_OFF 0x19 + +/* INTx Mechanism Messages; PCIe r6.0, sec 2.2.8.1 */ +#define PCIE_MSG_CODE_ASSERT_INTA 0x20 +#define PCIE_MSG_CODE_ASSERT_INTB 0x21 +#define PCIE_MSG_CODE_ASSERT_INTC 0x22 +#define PCIE_MSG_CODE_ASSERT_INTD 0x23 +#define PCIE_MSG_CODE_DEASSERT_INTA 0x24 +#define PCIE_MSG_CODE_DEASSERT_INTB 0x25 +#define PCIE_MSG_CODE_DEASSERT_INTC 0x26 +#define PCIE_MSG_CODE_DEASSERT_INTD 0x27 + extern const unsigned char pcie_link_speed[]; extern bool pci_early_dump; @@ -290,6 +333,28 @@ void pci_bus_put(struct pci_bus *bus); (speed) == PCIE_SPEED_2_5GT ? 2500*8/10 : \ 0) +static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed) +{ + switch (speed) { + case PCIE_SPEED_2_5GT: + return 2500; + case PCIE_SPEED_5_0GT: + return 5000; + case PCIE_SPEED_8_0GT: + return 8000; + case PCIE_SPEED_16_0GT: + return 16000; + case PCIE_SPEED_32_0GT: + return 32000; + case PCIE_SPEED_64_0GT: + return 64000; + default: + break; + } + + return -EINVAL; +} + const char *pci_speed_string(enum pci_bus_speed speed); enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev); enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev); @@ -648,6 +713,7 @@ int of_pci_get_max_link_speed(struct device_node *node); u32 of_pci_get_slot_power_limit(struct device_node *node, u8 *slot_power_limit_value, u8 *slot_power_limit_scale); +bool of_pci_preserve_config(struct device_node *node); int pci_set_of_node(struct pci_dev *dev); void pci_release_of_node(struct pci_dev *dev); void pci_set_bus_of_node(struct pci_bus *bus); @@ -686,6 +752,11 @@ of_pci_get_slot_power_limit(struct device_node *node, return 0; } +static inline bool of_pci_preserve_config(struct device_node *node) +{ + return false; +} + static inline int pci_set_of_node(struct pci_dev *dev) { return 0; } static inline void pci_release_of_node(struct pci_dev *dev) { } static inline void pci_set_bus_of_node(struct pci_bus *bus) { } @@ -732,6 +803,7 @@ static inline void pci_restore_aer_state(struct pci_dev *dev) { } #endif #ifdef CONFIG_ACPI +bool pci_acpi_preserve_config(struct pci_host_bridge *bridge); int pci_acpi_program_hp_params(struct pci_dev *dev); extern const struct attribute_group pci_dev_acpi_attr_group; void pci_set_acpi_fwnode(struct pci_dev *dev); @@ -745,6 +817,10 @@ int acpi_pci_wakeup(struct pci_dev *dev, bool enable); bool acpi_pci_need_resume(struct pci_dev *dev); pci_power_t acpi_pci_choose_state(struct pci_dev *pdev); #else +static inline bool pci_acpi_preserve_config(struct pci_host_bridge *bridge) +{ + return false; +} static inline int pci_dev_acpi_reset(struct pci_dev *dev, bool probe) { return -ENOTTY; @@ -810,26 +886,12 @@ static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev) } #endif -/* - * Managed PCI resources. This manages device on/off, INTx/MSI/MSI-X - * on/off and BAR regions. pci_dev itself records MSI/MSI-X status, so - * there's no need to track it separately. pci_devres is initialized - * when a device is enabled using managed PCI device enable interface. - * - * TODO: Struct pci_devres and find_pci_dr() only need to be here because - * they're used in pci.c. Port or move these functions to devres.c and - * then remove them from here. - */ -struct pci_devres { - unsigned int enabled:1; - unsigned int pinned:1; - unsigned int orig_intx:1; - unsigned int restore_intx:1; - unsigned int mwi:1; - u32 region_mask; -}; +int pcim_intx(struct pci_dev *dev, int enable); -struct pci_devres *find_pci_dr(struct pci_dev *pdev); +int pcim_request_region(struct pci_dev *pdev, int bar, const char *name); +int pcim_request_region_exclusive(struct pci_dev *pdev, int bar, + const char *name); +void pcim_release_region(struct pci_dev *pdev, int bar); /* * Config Address for PCI Configuration Mechanism #1 diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index ac6293c24976..13b8586924ea 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -1497,6 +1497,22 @@ static int aer_probe(struct pcie_device *dev) return 0; } +static int aer_suspend(struct pcie_device *dev) +{ + struct aer_rpc *rpc = get_service_data(dev); + + aer_disable_rootport(rpc); + return 0; +} + +static int aer_resume(struct pcie_device *dev) +{ + struct aer_rpc *rpc = get_service_data(dev); + + aer_enable_rootport(rpc); + return 0; +} + /** * aer_root_reset - reset Root Port hierarchy, RCEC, or RCiEP * @dev: pointer to Root Port, RCEC, or RCiEP @@ -1561,6 +1577,8 @@ static struct pcie_port_service_driver aerdriver = { .service = PCIE_PORT_SERVICE_AER, .probe = aer_probe, + .suspend = aer_suspend, + .resume = aer_resume, .remove = aer_remove, }; diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index a668820696dc..2b6ef7efa3c1 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -412,13 +412,44 @@ void pci_dpc_init(struct pci_dev *pdev) } } +static void dpc_enable(struct pcie_device *dev) +{ + struct pci_dev *pdev = dev->port; + int dpc = pdev->dpc_cap; + u16 ctl; + + /* + * Clear DPC Interrupt Status so we don't get an interrupt for an + * old event when setting DPC Interrupt Enable. + */ + pci_write_config_word(pdev, dpc + PCI_EXP_DPC_STATUS, + PCI_EXP_DPC_STATUS_INTERRUPT); + + pci_read_config_word(pdev, dpc + PCI_EXP_DPC_CTL, &ctl); + ctl &= ~PCI_EXP_DPC_CTL_EN_MASK; + ctl |= PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN; + pci_write_config_word(pdev, dpc + PCI_EXP_DPC_CTL, ctl); +} + +static void dpc_disable(struct pcie_device *dev) +{ + struct pci_dev *pdev = dev->port; + int dpc = pdev->dpc_cap; + u16 ctl; + + /* Disable DPC triggering and DPC interrupts */ + pci_read_config_word(pdev, dpc + PCI_EXP_DPC_CTL, &ctl); + ctl &= ~(PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN); + pci_write_config_word(pdev, dpc + PCI_EXP_DPC_CTL, ctl); +} + #define FLAG(x, y) (((x) & (y)) ? '+' : '-') static int dpc_probe(struct pcie_device *dev) { struct pci_dev *pdev = dev->port; struct device *device = &dev->device; int status; - u16 ctl, cap; + u16 cap; if (!pcie_aer_is_native(pdev) && !pcie_ports_dpc_native) return -ENOTSUPP; @@ -433,11 +464,7 @@ static int dpc_probe(struct pcie_device *dev) } pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CAP, &cap); - - pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, &ctl); - ctl &= ~PCI_EXP_DPC_CTL_EN_MASK; - ctl |= PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN; - pci_write_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, ctl); + dpc_enable(dev); pci_info(pdev, "enabled with IRQ %d\n", dev->irq); pci_info(pdev, "error containment capabilities: Int Msg #%d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n", @@ -450,14 +477,21 @@ static int dpc_probe(struct pcie_device *dev) return status; } +static int dpc_suspend(struct pcie_device *dev) +{ + dpc_disable(dev); + return 0; +} + +static int dpc_resume(struct pcie_device *dev) +{ + dpc_enable(dev); + return 0; +} + static void dpc_remove(struct pcie_device *dev) { - struct pci_dev *pdev = dev->port; - u16 ctl; - - pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, &ctl); - ctl &= ~(PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN); - pci_write_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, ctl); + dpc_disable(dev); } static struct pcie_port_service_driver dpcdriver = { @@ -465,6 +499,8 @@ static struct pcie_port_service_driver dpcdriver = { .port_type = PCIE_ANY_PORT, .service = PCIE_PORT_SERVICE_DPC, .probe = dpc_probe, + .suspend = dpc_suspend, + .resume = dpc_resume, .remove = dpc_remove, }; diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index bb65dfe43409..6af5e0425872 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -786,7 +786,7 @@ static const struct pci_error_handlers pcie_portdrv_err_handler = { static struct pci_driver pcie_portdriver = { .name = "pcieport", - .id_table = &port_pci_ids[0], + .id_table = port_pci_ids, .probe = pcie_portdrv_probe, .remove = pcie_portdrv_remove, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4c367f13acdc..b14b9876c030 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -889,6 +889,17 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus) dev_set_msi_domain(&bus->dev, d); } +static bool pci_preserve_config(struct pci_host_bridge *host_bridge) +{ + if (pci_acpi_preserve_config(host_bridge)) + return true; + + if (host_bridge->dev.parent && host_bridge->dev.parent->of_node) + return of_pci_preserve_config(host_bridge->dev.parent->of_node); + + return false; +} + static int pci_register_host_bridge(struct pci_host_bridge *bridge) { struct device *parent = bridge->dev.parent; @@ -983,6 +994,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE) dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n"); + /* Check if the boot configuration by FW needs to be preserved */ + bridge->preserve_config = pci_preserve_config(bridge); + /* Coalesce contiguous windows */ resource_list_for_each_entry_safe(window, n, &resources) { if (list_is_last(&window->node, &resources)) @@ -3079,20 +3093,18 @@ int pci_host_probe(struct pci_host_bridge *bridge) bus = bridge->bus; - /* - * We insert PCI resources into the iomem_resource and - * ioport_resource trees in either pci_bus_claim_resources() - * or pci_bus_assign_resources(). - */ - if (pci_has_flag(PCI_PROBE_ONLY)) { + /* If we must preserve the resource configuration, claim now */ + if (bridge->preserve_config) pci_bus_claim_resources(bus); - } else { - pci_bus_size_bridges(bus); - pci_bus_assign_resources(bus); - list_for_each_entry(child, &bus->children, node) - pcie_bus_configure_settings(child); - } + /* + * Assign whatever was left unassigned. If we didn't claim above, + * this will reassign everything. + */ + pci_assign_unassigned_root_bus_resources(bus); + + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); pci_bus_add_devices(bus); return 0; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 568410e64ce6..a2ce4e08edf5 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -5099,6 +5099,10 @@ static const struct pci_dev_acs_enabled { { PCI_VENDOR_ID_BROADCOM, 0x1750, pci_quirk_mf_endpoint_acs }, { PCI_VENDOR_ID_BROADCOM, 0x1751, pci_quirk_mf_endpoint_acs }, { PCI_VENDOR_ID_BROADCOM, 0x1752, pci_quirk_mf_endpoint_acs }, + { PCI_VENDOR_ID_BROADCOM, 0x1760, pci_quirk_mf_endpoint_acs }, + { PCI_VENDOR_ID_BROADCOM, 0x1761, pci_quirk_mf_endpoint_acs }, + { PCI_VENDOR_ID_BROADCOM, 0x1762, pci_quirk_mf_endpoint_acs }, + { PCI_VENDOR_ID_BROADCOM, 0x1763, pci_quirk_mf_endpoint_acs }, { PCI_VENDOR_ID_BROADCOM, 0xD714, pci_quirk_brcm_acs }, /* Amazon Annapurna Labs */ { PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031, pci_quirk_al_acs }, diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 909e6a7c3cc3..23082bc0ca37 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -14,6 +14,7 @@ * tighter packing. Prefetchable range support. */ +#include #include #include #include @@ -21,6 +22,8 @@ #include #include #include +#include +#include #include #include #include "pci.h" @@ -829,11 +832,9 @@ static resource_size_t calculate_memsize(resource_size_t size, size = min_size; if (old_size == 1) old_size = 0; - if (size < old_size) - size = old_size; - size = ALIGN(max(size, add_size) + children_add_size, align); - return size; + size = max(size, add_size) + children_add_size; + return ALIGN(max(size, old_size), align); } resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus, @@ -959,7 +960,7 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, for (order = 0; order <= max_order; order++) { resource_size_t align1 = 1; - align1 <<= (order + 20); + align1 <<= order + __ffs(SZ_1M); if (!align) min_align = align1; @@ -971,6 +972,67 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, return min_align; } +/** + * pbus_upstream_space_available - Check no upstream resource limits allocation + * @bus: The bus + * @mask: Mask the resource flag, then compare it with type + * @type: The type of resource from bridge + * @size: The size required from the bridge window + * @align: Required alignment for the resource + * + * Checks that @size can fit inside the upstream bridge resources that are + * already assigned. + * + * Return: %true if enough space is available on all assigned upstream + * resources. + */ +static bool pbus_upstream_space_available(struct pci_bus *bus, unsigned long mask, + unsigned long type, resource_size_t size, + resource_size_t align) +{ + struct resource_constraint constraint = { + .max = RESOURCE_SIZE_MAX, + .align = align, + }; + struct pci_bus *downstream = bus; + struct resource *r; + + while ((bus = bus->parent)) { + if (pci_is_root_bus(bus)) + break; + + pci_bus_for_each_resource(bus, r) { + if (!r || !r->parent || (r->flags & mask) != type) + continue; + + if (resource_size(r) >= size) { + struct resource gap = {}; + + if (find_resource_space(r, &gap, size, &constraint) == 0) { + gap.flags = type; + pci_dbg(bus->self, + "Assigned bridge window %pR to %pR free space at %pR\n", + r, &bus->busn_res, &gap); + return true; + } + } + + if (bus->self) { + pci_info(bus->self, + "Assigned bridge window %pR to %pR cannot fit 0x%llx required for %s bridging to %pR\n", + r, &bus->busn_res, + (unsigned long long)size, + pci_name(downstream->self), + &downstream->busn_res); + } + + return false; + } + } + + return true; +} + /** * pbus_size_mem() - Size the memory window of a given bus * @@ -997,7 +1059,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, struct list_head *realloc_head) { struct pci_dev *dev; - resource_size_t min_align, align, size, size0, size1; + resource_size_t min_align, win_align, align, size, size0, size1; resource_size_t aligns[24]; /* Alignments from 1MB to 8TB */ int order, max_order; struct resource *b_res = find_bus_resource_of_type(bus, @@ -1049,7 +1111,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, * resources. */ align = pci_resource_alignment(dev, r); - order = __ffs(align) - 20; + order = __ffs(align) - __ffs(SZ_1M); if (order < 0) order = 0; if (order >= ARRAY_SIZE(aligns)) { @@ -1076,10 +1138,23 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, } } + win_align = window_alignment(bus, b_res->flags); min_align = calculate_mem_align(aligns, max_order); - min_align = max(min_align, window_alignment(bus, b_res->flags)); + min_align = max(min_align, win_align); size0 = calculate_memsize(size, min_size, 0, 0, resource_size(b_res), min_align); add_align = max(min_align, add_align); + + if (bus->self && size0 && + !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type, + size0, add_align)) { + min_align = 1ULL << (max_order + __ffs(SZ_1M)); + min_align = max(min_align, win_align); + size0 = calculate_memsize(size, min_size, 0, 0, resource_size(b_res), win_align); + add_align = win_align; + pci_info(bus->self, "bridge window %pR to %pR requires relaxed alignment rules\n", + b_res, &bus->busn_res); + } + size1 = (!realloc_head || (realloc_head && !add_size && !children_add_size)) ? size0 : calculate_memsize(size, min_size, add_size, children_add_size, resource_size(b_res), add_align); diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index 5a4adf6c04cf..c7e1089ffdaf 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -37,7 +37,9 @@ MODULE_PARM_DESC(nirqs, "number of interrupts to allocate (more may be useful fo static dev_t switchtec_devt; static DEFINE_IDA(switchtec_minor_ida); -struct class *switchtec_class; +const struct class switchtec_class = { + .name = "switchtec", +}; EXPORT_SYMBOL_GPL(switchtec_class); enum mrpc_state { @@ -1363,7 +1365,7 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev) dev = &stdev->dev; device_initialize(dev); - dev->class = switchtec_class; + dev->class = &switchtec_class; dev->parent = &pdev->dev; dev->groups = switchtec_device_groups; dev->release = stdev_release; @@ -1851,11 +1853,9 @@ static int __init switchtec_init(void) if (rc) return rc; - switchtec_class = class_create("switchtec"); - if (IS_ERR(switchtec_class)) { - rc = PTR_ERR(switchtec_class); + rc = class_register(&switchtec_class); + if (rc) goto err_create_class; - } rc = pci_register_driver(&switchtec_pci_driver); if (rc) @@ -1866,7 +1866,7 @@ static int __init switchtec_init(void) return 0; err_pci_register: - class_destroy(switchtec_class); + class_unregister(&switchtec_class); err_create_class: unregister_chrdev_region(switchtec_devt, max_devices); @@ -1878,7 +1878,7 @@ module_init(switchtec_init); static void __exit switchtec_exit(void) { pci_unregister_driver(&switchtec_pci_driver); - class_destroy(switchtec_class); + class_unregister(&switchtec_class); unregister_chrdev_region(switchtec_devt, max_devices); ida_destroy(&switchtec_minor_ida); diff --git a/drivers/peci/controller/peci-aspeed.c b/drivers/peci/controller/peci-aspeed.c index 7fdc25afcf2f..de7046e6b9c4 100644 --- a/drivers/peci/controller/peci-aspeed.c +++ b/drivers/peci/controller/peci-aspeed.c @@ -351,6 +351,7 @@ static int clk_aspeed_peci_set_rate(struct clk_hw *hw, unsigned long rate, clk_aspeed_peci_find_div_values(this_rate, &msg_timing, &clk_div_exp); val = readl(aspeed_peci->base + ASPEED_PECI_CTRL); + val &= ~ASPEED_PECI_CTRL_CLK_DIV_MASK; val |= FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, clk_div_exp); writel(val, aspeed_peci->base + ASPEED_PECI_CTRL); diff --git a/drivers/peci/core.c b/drivers/peci/core.c index 8f8bda2f2a62..8ff3e5d225ae 100644 --- a/drivers/peci/core.c +++ b/drivers/peci/core.c @@ -163,9 +163,8 @@ EXPORT_SYMBOL_NS_GPL(devm_peci_controller_add, PECI); static const struct peci_device_id * peci_bus_match_device_id(const struct peci_device_id *id, struct peci_device *device) { - while (id->family != 0) { - if (id->family == device->info.family && - id->model == device->info.model) + while (id->x86_vfm != 0) { + if (id->x86_vfm == device->info.x86_vfm) return id; id++; } diff --git a/drivers/peci/cpu.c b/drivers/peci/cpu.c index bd990acd92b8..152bbd8e717a 100644 --- a/drivers/peci/cpu.c +++ b/drivers/peci/cpu.c @@ -294,38 +294,31 @@ peci_cpu_probe(struct peci_device *device, const struct peci_device_id *id) static const struct peci_device_id peci_cpu_device_ids[] = { { /* Haswell Xeon */ - .family = 6, - .model = INTEL_FAM6_HASWELL_X, + .x86_vfm = INTEL_HASWELL_X, .data = "hsx", }, { /* Broadwell Xeon */ - .family = 6, - .model = INTEL_FAM6_BROADWELL_X, + .x86_vfm = INTEL_BROADWELL_X, .data = "bdx", }, { /* Broadwell Xeon D */ - .family = 6, - .model = INTEL_FAM6_BROADWELL_D, + .x86_vfm = INTEL_BROADWELL_D, .data = "bdxd", }, { /* Skylake Xeon */ - .family = 6, - .model = INTEL_FAM6_SKYLAKE_X, + .x86_vfm = INTEL_SKYLAKE_X, .data = "skx", }, { /* Icelake Xeon */ - .family = 6, - .model = INTEL_FAM6_ICELAKE_X, + .x86_vfm = INTEL_ICELAKE_X, .data = "icx", }, { /* Icelake Xeon D */ - .family = 6, - .model = INTEL_FAM6_ICELAKE_D, + .x86_vfm = INTEL_ICELAKE_D, .data = "icxd", }, { /* Sapphire Rapids Xeon */ - .family = 6, - .model = INTEL_FAM6_SAPPHIRERAPIDS_X, + .x86_vfm = INTEL_SAPPHIRERAPIDS_X, .data = "spr", }, { } diff --git a/drivers/peci/device.c b/drivers/peci/device.c index ee01f03c29b7..37ca7dd61807 100644 --- a/drivers/peci/device.c +++ b/drivers/peci/device.c @@ -100,8 +100,7 @@ static int peci_device_info_init(struct peci_device *device) if (ret) return ret; - device->info.family = peci_x86_cpu_family(cpu_id); - device->info.model = peci_x86_cpu_model(cpu_id); + device->info.x86_vfm = IFM(peci_x86_cpu_family(cpu_id), peci_x86_cpu_model(cpu_id)); ret = peci_get_revision(device, &revision); if (ret) diff --git a/drivers/peci/internal.h b/drivers/peci/internal.h index 506bafcccbbf..7a4f6eae2f90 100644 --- a/drivers/peci/internal.h +++ b/drivers/peci/internal.h @@ -66,13 +66,11 @@ struct peci_request *peci_xfer_ep_mmio64_readl(struct peci_device *device, u8 ba /** * struct peci_device_id - PECI device data to match * @data: pointer to driver private data specific to device - * @family: device family - * @model: device model + * @x86_vfm: device vendor-family-model */ struct peci_device_id { const void *data; - u16 family; - u8 model; + u32 x86_vfm; }; extern const struct device_type peci_device_type; diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c index 0fe577f0d6c1..68aa595b6ad8 100644 --- a/drivers/phy/ti/phy-da8xx-usb.c +++ b/drivers/phy/ti/phy-da8xx-usb.c @@ -14,11 +14,13 @@ #include #include #include +#include #include #define PHY_INIT_BITS (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN) struct da8xx_usb_phy { + struct device *dev; struct phy_provider *phy_provider; struct phy *usb11_phy; struct phy *usb20_phy; @@ -39,6 +41,12 @@ static int da8xx_usb11_phy_power_on(struct phy *phy) regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, CFGCHIP2_USB1SUSPENDM); + /* + * USB1.1 can used USB2.0 output clock as reference clock so this is here to prevent USB2.0 + * from shutting PHY's power when USB1.1 might use it + */ + pm_runtime_get_sync(d_phy->dev); + return 0; } @@ -49,6 +57,7 @@ static int da8xx_usb11_phy_power_off(struct phy *phy) regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, 0); clk_disable_unprepare(d_phy->usb11_clk); + pm_runtime_put_sync(d_phy->dev); return 0; } @@ -118,6 +127,35 @@ static const struct phy_ops da8xx_usb20_phy_ops = { .owner = THIS_MODULE, }; +static int __maybe_unused da8xx_runtime_suspend(struct device *dev) +{ + struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev); + + dev_dbg(dev, "Suspending ...\n"); + + regmap_set_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN); + + return 0; +} + +static int __maybe_unused da8xx_runtime_resume(struct device *dev) +{ + u32 mask = CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | CFGCHIP2_PHY_PLLON; + struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev); + u32 pll_status; + + regmap_update_bits(d_phy->regmap, CFGCHIP(2), mask, CFGCHIP2_PHY_PLLON); + + dev_dbg(dev, "Resuming ...\n"); + + return regmap_read_poll_timeout(d_phy->regmap, CFGCHIP(2), pll_status, + pll_status & CFGCHIP2_PHYCLKGD, 1000, 500000); +} + +static const struct dev_pm_ops da8xx_usb_phy_pm_ops = { + SET_RUNTIME_PM_OPS(da8xx_runtime_suspend, da8xx_runtime_resume, NULL) +}; + static struct phy *da8xx_usb_phy_of_xlate(struct device *dev, const struct of_phandle_args *args) { @@ -147,6 +185,8 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev) if (!d_phy) return -ENOMEM; + d_phy->dev = dev; + if (pdata) d_phy->regmap = pdata->cfgchip; else @@ -208,6 +248,14 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev) regmap_write_bits(d_phy->regmap, CFGCHIP(2), PHY_INIT_BITS, PHY_INIT_BITS); + pm_runtime_set_active(dev); + devm_pm_runtime_enable(dev); + /* + * Prevent runtime pm from being ON by default. Users can enable + * it using power/control in sysfs. + */ + pm_runtime_forbid(dev); + return 0; } @@ -232,6 +280,7 @@ static struct platform_driver da8xx_usb_phy_driver = { .remove_new = da8xx_usb_phy_remove, .driver = { .name = "da8xx-usb-phy", + .pm = &da8xx_usb_phy_pm_ops, .of_match_table = da8xx_usb_phy_ids, }, }; diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 061aa9647c19..c2aab0cfab33 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -946,4 +946,5 @@ static struct platform_driver goldfish_pipe_driver = { module_platform_driver(goldfish_pipe_driver); MODULE_AUTHOR("David Turner "); +MODULE_DESCRIPTION("Goldfish virtual device for QEMU pipes"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c index af972cdc04b5..63d03a0df5cc 100644 --- a/drivers/pps/clients/pps_parport.c +++ b/drivers/pps/clients/pps_parport.c @@ -216,7 +216,6 @@ static struct parport_driver pps_parport_driver = { .name = KBUILD_MODNAME, .match_port = parport_attach, .detach = parport_detach, - .devmodel = true, }; module_parport_driver(pps_parport_driver); diff --git a/drivers/pps/generators/pps_gen_parport.c b/drivers/pps/generators/pps_gen_parport.c index b3e084b75c23..d46eed159495 100644 --- a/drivers/pps/generators/pps_gen_parport.c +++ b/drivers/pps/generators/pps_gen_parport.c @@ -232,7 +232,6 @@ static struct parport_driver pps_gen_parport_driver = { .name = KBUILD_MODNAME, .match_port = parport_attach, .detach = parport_detach, - .devmodel = true, }; module_parport_driver(pps_gen_parport_driver); diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 6e779bb14d98..1d4c7310f1a6 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -1275,7 +1275,6 @@ static struct parport_driver imm_driver = { .name = "imm", .match_port = imm_attach, .detach = imm_detach, - .devmodel = true, }; module_parport_driver(imm_driver); diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 2d9fcc45ad85..a06329b47851 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -1151,7 +1151,6 @@ static struct parport_driver ppa_driver = { .name = "ppa", .match_port = ppa_attach, .detach = ppa_detach, - .devmodel = true, }; module_parport_driver(ppa_driver); diff --git a/drivers/siox/siox-bus-gpio.c b/drivers/siox/siox-bus-gpio.c index 9e01642e72de..d6f936464063 100644 --- a/drivers/siox/siox-bus-gpio.c +++ b/drivers/siox/siox-bus-gpio.c @@ -148,5 +148,6 @@ static struct platform_driver siox_gpio_driver = { module_platform_driver(siox_gpio_driver); MODULE_AUTHOR("Uwe Kleine-Koenig "); +MODULE_DESCRIPTION("SIOX GPIO bus driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/slimbus/stream.c b/drivers/slimbus/stream.c index 1d6b38657917..863ab3075d7e 100644 --- a/drivers/slimbus/stream.c +++ b/drivers/slimbus/stream.c @@ -18,15 +18,17 @@ * and the first slot of the next consecutive Segment. * @segdist_code: Segment Distribution Code SD[11:0] * @seg_offset_mask: Segment offset mask in SD[11:0] - * @segdist_codes: List of all possible Segmet Distribution codes. */ -static const struct segdist_code { +struct segdist_code { int ratem; int seg_interval; int segdist_code; u32 seg_offset_mask; -} segdist_codes[] = { +}; + +/* segdist_codes - List of all possible Segment Distribution codes. */ +static const struct segdist_code segdist_codes[] = { {1, 1536, 0x200, 0xdff}, {2, 768, 0x100, 0xcff}, {4, 384, 0x080, 0xc7f}, diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 1d267e6c22a4..84eb454ed443 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -315,7 +315,6 @@ static struct parport_driver butterfly_driver = { .name = "spi_butterfly", .match_port = butterfly_attach, .detach = butterfly_detach, - .devmodel = true, }; module_parport_driver(butterfly_driver); diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index 3c0c24ed1f3d..e61e89b4119f 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -318,7 +318,6 @@ static struct parport_driver spi_lm70llp_drv = { .name = DRVNAME, .match_port = spi_lm70llp_attach, .detach = spi_lm70llp_detach, - .devmodel = true, }; module_parport_driver(spi_lm70llp_drv); diff --git a/drivers/spmi/hisi-spmi-controller.c b/drivers/spmi/hisi-spmi-controller.c index fa068b34b040..3cafdf22c909 100644 --- a/drivers/spmi/hisi-spmi-controller.c +++ b/drivers/spmi/hisi-spmi-controller.c @@ -344,6 +344,7 @@ static void __exit spmi_controller_exit(void) } module_exit(spmi_controller_exit); +MODULE_DESCRIPTION("Hisilicon 3670 SPMI Controller driver"); MODULE_LICENSE("GPL v2"); MODULE_VERSION("1.0"); MODULE_ALIAS("platform:spmi_controller"); diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index 791cdc160c51..f240fcc5a4e1 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -1891,5 +1891,6 @@ static struct platform_driver spmi_pmic_arb_driver = { }; module_platform_driver(spmi_pmic_arb_driver); +MODULE_DESCRIPTION("Qualcomm MSM SPMI Controller (PMIC Arbiter) driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spmi_pmic_arb"); diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index c8d52c63d79f..8e2fd0c0fee2 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -1276,4 +1276,5 @@ void fbtft_remove_common(struct device *dev, struct fb_info *info) } EXPORT_SYMBOL(fbtft_remove_common); +MODULE_DESCRIPTION("Core FB support for small TFT LCD display modules"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index fa43d35bbcec..27ca5f796c5f 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -182,5 +182,6 @@ static void __exit manager_exit(void) module_init(manager_init); module_exit(manager_exit); +MODULE_DESCRIPTION("Greybus audio operations manager"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Svetlin Ankov "); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 5dc4721105d4..6ca938dca4fd 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -10,12 +10,6 @@ #define GBAUDIO_INVALID_ID 0xFF -/* mixer control */ -struct gb_mixer_control { - int min, max; - unsigned int reg, rreg, shift, rshift, invert; -}; - struct gbaudio_ctl_pvt { unsigned int ctl_id; unsigned int data_cport; diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index c0d338db6b52..d4d86b3898de 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -522,4 +522,5 @@ static struct greybus_driver gb_bootrom_driver = { module_greybus_driver(gb_bootrom_driver); +MODULE_DESCRIPTION("BOOTROM Greybus driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index b8b2bdfa59e5..ca71023df447 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -1374,4 +1374,5 @@ static struct greybus_driver gb_camera_driver = { module_greybus_driver(gb_camera_driver); +MODULE_DESCRIPTION("Greybus Camera protocol driver."); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index d827f03f5253..d992db8d45cb 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -354,4 +354,5 @@ static void __exit gbphy_exit(void) } module_exit(gbphy_exit); +MODULE_DESCRIPTION("Greybus Bridged-Phy Bus driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 5217aacfcf54..9b26e148d40f 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -631,4 +631,5 @@ static struct gbphy_driver gpio_driver = { }; module_gbphy_driver(gpio_driver); +MODULE_DESCRIPTION("GPIO Greybus driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 15335c38cb26..63c77a3df591 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -516,4 +516,5 @@ static struct greybus_driver gb_hid_driver = { }; module_greybus_driver(gb_hid_driver); +MODULE_DESCRIPTION("HID class driver for the Greybus"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 22325ab9d652..14f1ff6d448c 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -318,4 +318,5 @@ static struct gbphy_driver i2c_driver = { }; module_gbphy_driver(i2c_driver); +MODULE_DESCRIPTION("I2C bridge driver for the Greybus 'generic' I2C module"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 00360f4a0485..e509fdc715db 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1339,4 +1339,5 @@ static struct greybus_driver gb_lights_driver = { }; module_greybus_driver(gb_lights_driver); +MODULE_DESCRIPTION("Greybus Lights protocol driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c index 971f36dccac6..57dcf9453bf1 100644 --- a/drivers/staging/greybus/log.c +++ b/drivers/staging/greybus/log.c @@ -129,4 +129,5 @@ static struct greybus_driver gb_log_driver = { }; module_greybus_driver(gb_log_driver); +MODULE_DESCRIPTION("Greybus driver for the log protocol"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 4313d3bbc23a..1f19323b0e1a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -1175,4 +1175,5 @@ static void __exit loopback_exit(void) } module_exit(loopback_exit); +MODULE_DESCRIPTION("Loopback bridge driver for the Greybus loopback module"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 75cb170e05fb..2ef46822f676 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -1136,4 +1136,5 @@ static struct greybus_driver gb_power_supply_driver = { }; module_greybus_driver(gb_power_supply_driver); +MODULE_DESCRIPTION("Power Supply driver for a Greybus module"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 01883fbcd79b..1cb7b9089ead 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -327,4 +327,5 @@ static struct gbphy_driver pwm_driver = { }; module_gbphy_driver(pwm_driver); +MODULE_DESCRIPTION("PWM Greybus driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 836d35e5fa85..71de6776739c 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -377,4 +377,5 @@ static void __exit raw_exit(void) } module_exit(raw_exit); +MODULE_DESCRIPTION("Greybus driver for the Raw protocol"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 25bee5335c70..5326ea372b24 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -880,4 +880,5 @@ static struct gbphy_driver sdio_driver = { }; module_gbphy_driver(sdio_driver); +MODULE_DESCRIPTION("SD/MMC Greybus driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 68e8d272db6d..45ea8d1bdd51 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -75,4 +75,5 @@ static struct gbphy_driver spi_driver = { }; module_gbphy_driver(spi_driver); +MODULE_DESCRIPTION("Greybus SPI bridge PHY driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 34f10685139f..0e4ae01eb00f 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -567,4 +567,5 @@ void gb_spilib_master_exit(struct gb_connection *connection) } EXPORT_SYMBOL_GPL(gb_spilib_master_exit); +MODULE_DESCRIPTION("Greybus SPI library"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 999ce613dca8..cdf4ebb93b10 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -1024,4 +1024,5 @@ static void gb_uart_driver_exit(void) } module_exit(gb_uart_driver_exit); +MODULE_DESCRIPTION("UART driver for the Greybus 'generic' UART module"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index b7badf87a3f0..475f24f20cd4 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -242,4 +242,5 @@ static struct gbphy_driver usb_driver = { }; module_gbphy_driver(usb_driver); +MODULE_DESCRIPTION("USB host driver for the Greybus 'generic' USB module"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 89bef8045549..ee112aa13ff1 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -245,4 +245,5 @@ static __exit void gb_vibrator_exit(void) } module_exit(gb_vibrator_exit); +MODULE_DESCRIPTION("Greybus Vibrator protocol driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 6c1f91c859ca..e6ad088636f6 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -109,12 +109,12 @@ static int adt7316_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adt7316_i2c_id[] = { - { "adt7316", 0 }, - { "adt7317", 0 }, - { "adt7318", 0 }, - { "adt7516", 0 }, - { "adt7517", 0 }, - { "adt7519", 0 }, + { "adt7316" }, + { "adt7317" }, + { "adt7318" }, + { "adt7516" }, + { "adt7517" }, + { "adt7519" }, { } }; diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 79467f056a05..f4260786d50a 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -209,15 +209,6 @@ struct adt7316_chip_info { #define ADT7316_TEMP_AIN_INT_MASK \ (ADT7316_TEMP_INT_MASK) -/* - * struct adt7316_chip_info - chip specific information - */ - -struct adt7316_limit_regs { - u16 data_high; - u16 data_low; -}; - static ssize_t adt7316_show_enabled(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index b7af5fe63e09..cd00d9607565 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -721,8 +721,8 @@ static int ad5933_probe(struct i2c_client *client) } static const struct i2c_device_id ad5933_id[] = { - { "ad5933", 0 }, - { "ad5934", 0 }, + { "ad5933" }, + { "ad5934" }, {} }; diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index e5ca78e57384..d09211589d1c 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -300,7 +300,7 @@ int nvec_write_sync(struct nvec_chip *nvec, { mutex_lock(&nvec->sync_write_mutex); - if (msg != NULL) + if (msg) *msg = NULL; nvec->sync_write_pending = (data[1] << 8) + data[0]; @@ -322,7 +322,7 @@ int nvec_write_sync(struct nvec_chip *nvec, dev_dbg(nvec->dev, "nvec_sync_write: pong!\n"); - if (msg != NULL) + if (msg) *msg = nvec->last_sync_msg; else nvec_msg_free(nvec, nvec->last_sync_msg); @@ -570,6 +570,22 @@ static void nvec_tx_set(struct nvec_chip *nvec) (uint)nvec->tx->size, nvec->tx->data[1]); } +/** + * tegra_i2c_writel - safely write to an I2C client controller register + * @val: value to be written + * @reg: register to write to + * + * A write to an I2C controller register needs to be read back to make sure + * that the value has arrived. + */ +static void tegra_i2c_writel(u32 val, void *reg) +{ + writel_relaxed(val, reg); + + /* read back register to make sure that register writes completed */ + readl_relaxed(reg); +} + /** * nvec_interrupt - Interrupt handler * @irq: The IRQ @@ -604,7 +620,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) if ((status & RNW) == 0) { received = readl(nvec->base + I2C_SL_RCVD); if (status & RCVD) - writel(0, nvec->base + I2C_SL_RCVD); + tegra_i2c_writel(0, nvec->base + I2C_SL_RCVD); } if (status == (I2C_SL_IRQ | RCVD)) @@ -696,7 +712,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) /* Send data if requested, but not on end of transmission */ if ((status & (RNW | END_TRANS)) == RNW) - writel(to_send, nvec->base + I2C_SL_RCVD); + tegra_i2c_writel(to_send, nvec->base + I2C_SL_RCVD); /* If we have send the first byte */ if (status == (I2C_SL_IRQ | RNW | RCVD)) @@ -713,15 +729,6 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) status & RCVD ? " RCVD" : "", status & RNW ? " RNW" : ""); - /* - * TODO: replace the udelay with a read back after each writel above - * in order to work around a hardware issue, see i2c-tegra.c - * - * Unfortunately, this change causes an initialisation issue with the - * touchpad, which needs to be fixed first. - */ - udelay(100); - return IRQ_HANDLED; } @@ -737,15 +744,15 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN | (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); - writel(val, nvec->base + I2C_CNFG); + tegra_i2c_writel(val, nvec->base + I2C_CNFG); clk_set_rate(nvec->i2c_clk, 8 * 80000); - writel(I2C_SL_NEWSL, nvec->base + I2C_SL_CNFG); - writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); + tegra_i2c_writel(I2C_SL_NEWSL, nvec->base + I2C_SL_CNFG); + tegra_i2c_writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); - writel(nvec->i2c_addr >> 1, nvec->base + I2C_SL_ADDR1); - writel(0, nvec->base + I2C_SL_ADDR2); + tegra_i2c_writel(nvec->i2c_addr >> 1, nvec->base + I2C_SL_ADDR1); + tegra_i2c_writel(0, nvec->base + I2C_SL_ADDR2); enable_irq(nvec->irq); } @@ -754,7 +761,7 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) static void nvec_disable_i2c_slave(struct nvec_chip *nvec) { disable_irq(nvec->irq); - writel(I2C_SL_NEWSL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG); + tegra_i2c_writel(I2C_SL_NEWSL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG); clk_disable_unprepare(nvec->i2c_clk); } #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h index 8c85f1c866d3..d87bace0a19b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h @@ -88,9 +88,7 @@ enum version_8190_loopback { VERSION_8190_BE }; -#define IC_VersionCut_C 0x2 #define IC_VersionCut_D 0x3 -#define IC_VersionCut_E 0x4 enum rf_optype { RF_OP_By_SW_3wire = 0, @@ -138,13 +136,6 @@ struct tx_fwinfo_8190pci { u32 PacketID:13; }; -struct phy_ofdm_rx_status_rxsc_sgien_exintfflag { - u8 reserved:4; - u8 rxsc:2; - u8 sgi_en:1; - u8 ex_intf_flag:1; -}; - struct phy_sts_ofdm_819xpci { u8 trsw_gain_X[4]; u8 pwdb_all; diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index fdf8fc66939d..b3d4b3394284 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -859,8 +859,8 @@ static u8 _rtl92e_query_is_short(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc) { u8 tmp_Short; - tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : - ((tcb_desc->bUseShortPreamble) ? 1 : 0); + tmp_Short = (TxHT == 1) ? ((tcb_desc->use_short_gi) ? 1 : 0) : + ((tcb_desc->use_short_preamble) ? 1 : 0); if (TxHT == 1 && TxRate != DESC90_RATEMCS15) tmp_Short = 0; @@ -892,18 +892,18 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, pTxFwInfo->RxAMD = 0; } - pTxFwInfo->RtsEnable = (cb_desc->bRTSEnable) ? 1 : 0; - pTxFwInfo->CtsEnable = (cb_desc->bCTSEnable) ? 1 : 0; - pTxFwInfo->RtsSTBC = (cb_desc->bRTSSTBC) ? 1 : 0; + pTxFwInfo->RtsEnable = (cb_desc->rts_enable) ? 1 : 0; + pTxFwInfo->CtsEnable = (cb_desc->cts_enable) ? 1 : 0; + pTxFwInfo->RtsSTBC = (cb_desc->rtsstbc) ? 1 : 0; pTxFwInfo->RtsHT = (cb_desc->rts_rate & 0x80) ? 1 : 0; pTxFwInfo->RtsRate = _rtl92e_rate_mgn_to_hw(cb_desc->rts_rate); pTxFwInfo->RtsBandwidth = 0; pTxFwInfo->RtsSubcarrier = cb_desc->RTSSC; pTxFwInfo->RtsShort = (pTxFwInfo->RtsHT == 0) ? (cb_desc->rts_use_short_preamble ? 1 : 0) : - (cb_desc->bRTSUseShortGI ? 1 : 0); + (cb_desc->rts_use_short_gi ? 1 : 0); if (priv->current_chnl_bw == HT_CHANNEL_WIDTH_20_40) { - if (cb_desc->bPacketBW) { + if (cb_desc->packet_bw) { pTxFwInfo->TxBandwidth = 1; pTxFwInfo->TxSubCarrier = 0; } else { @@ -934,7 +934,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, pdesc->NoEnc = 1; pdesc->SecType = 0x0; - if (cb_desc->bHwSec) { + if (cb_desc->hw_sec) { static u8 tmp; if (!tmp) @@ -1640,13 +1640,12 @@ bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, if (stats->Length < 24) stats->bHwError |= 1; - if (stats->bHwError) { + if (stats->bHwError) return false; - } stats->RxDrvInfoSize = pdesc->RxDrvInfoSize; stats->RxBufShift = (pdesc->Shift) & 0x03; - stats->Decrypted = !pdesc->SWDec; + stats->decrypted = !pdesc->SWDec; pDrvInfo = (struct rx_fwinfo *)(skb->data + stats->RxBufShift); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h index 615b84bca9b8..9deffdf96072 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h @@ -11,6 +11,7 @@ #define _RTL_CAM_H #include + struct net_device; void rtl92e_cam_reset(struct net_device *dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 08d057ab8f74..9eeae01dc98d 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -951,10 +951,10 @@ static void _rtl92e_watchdog_wq_cb(void *data) return; if (priv->rtllib->link_state >= MAC80211_LINKED) { - if (priv->rtllib->CntAfterLink < 2) - priv->rtllib->CntAfterLink++; + if (priv->rtllib->cnt_after_link < 2) + priv->rtllib->cnt_after_link++; } else { - priv->rtllib->CntAfterLink = 0; + priv->rtllib->cnt_after_link = 0; } rtl92e_dm_watchdog(dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index aebe67f1a46d..0c7f38a4a7db 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -377,7 +377,7 @@ static void _rtl92e_dm_init_bandwidth_autoswitch(struct net_device *dev) priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH; priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW; - priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false; + priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz = false; priv->rtllib->bandwidth_auto_switch.bautoswitch_enable = false; } @@ -388,14 +388,14 @@ static void _rtl92e_dm_bandwidth_autoswitch(struct net_device *dev) if (priv->current_chnl_bw == HT_CHANNEL_WIDTH_20 || !priv->rtllib->bandwidth_auto_switch.bautoswitch_enable) return; - if (!priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz) { + if (!priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz) { if (priv->undecorated_smoothed_pwdb <= priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz) - priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = true; + priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz = true; } else { if (priv->undecorated_smoothed_pwdb >= priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz) - priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false; + priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz = false; } } @@ -1335,51 +1335,52 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) for (i = 0; i < RF90_PATH_MAX; i++) { dm_rx_path_sel_table.rf_rssi[i] = priv->stats.rx_rssi_percentage[i]; - if (priv->brfpath_rxenable[i]) { - rf_num++; - cur_rf_rssi = dm_rx_path_sel_table.rf_rssi[i]; + if (!priv->brfpath_rxenable[i]) + continue; - if (rf_num == 1) { - max_rssi_index = min_rssi_index = sec_rssi_index = i; - tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; - } else if (rf_num == 2) { - if (cur_rf_rssi >= tmp_max_rssi) { - tmp_max_rssi = cur_rf_rssi; - max_rssi_index = i; - } else { - tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; - sec_rssi_index = min_rssi_index = i; - } + rf_num++; + cur_rf_rssi = dm_rx_path_sel_table.rf_rssi[i]; + + if (rf_num == 1) { + max_rssi_index = min_rssi_index = sec_rssi_index = i; + tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; + } else if (rf_num == 2) { + if (cur_rf_rssi >= tmp_max_rssi) { + tmp_max_rssi = cur_rf_rssi; + max_rssi_index = i; } else { - if (cur_rf_rssi > tmp_max_rssi) { - tmp_sec_rssi = tmp_max_rssi; - sec_rssi_index = max_rssi_index; - tmp_max_rssi = cur_rf_rssi; - max_rssi_index = i; - } else if (cur_rf_rssi == tmp_max_rssi) { + tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; + sec_rssi_index = min_rssi_index = i; + } + } else { + if (cur_rf_rssi > tmp_max_rssi) { + tmp_sec_rssi = tmp_max_rssi; + sec_rssi_index = max_rssi_index; + tmp_max_rssi = cur_rf_rssi; + max_rssi_index = i; + } else if (cur_rf_rssi == tmp_max_rssi) { + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } else if ((cur_rf_rssi < tmp_max_rssi) && + (cur_rf_rssi > tmp_sec_rssi)) { + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } else if (cur_rf_rssi == tmp_sec_rssi) { + if (tmp_sec_rssi == tmp_min_rssi) { tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; - } else if ((cur_rf_rssi < tmp_max_rssi) && - (cur_rf_rssi > tmp_sec_rssi)) { - tmp_sec_rssi = cur_rf_rssi; - sec_rssi_index = i; - } else if (cur_rf_rssi == tmp_sec_rssi) { - if (tmp_sec_rssi == tmp_min_rssi) { - tmp_sec_rssi = cur_rf_rssi; - sec_rssi_index = i; - } - } else if ((cur_rf_rssi < tmp_sec_rssi) && - (cur_rf_rssi > tmp_min_rssi)) { - ; - } else if (cur_rf_rssi == tmp_min_rssi) { - if (tmp_sec_rssi == tmp_min_rssi) { - tmp_min_rssi = cur_rf_rssi; - min_rssi_index = i; - } - } else if (cur_rf_rssi < tmp_min_rssi) { + } + } else if ((cur_rf_rssi < tmp_sec_rssi) && + (cur_rf_rssi > tmp_min_rssi)) { + ; + } else if (cur_rf_rssi == tmp_min_rssi) { + if (tmp_sec_rssi == tmp_min_rssi) { tmp_min_rssi = cur_rf_rssi; min_rssi_index = i; } + } else if (cur_rf_rssi < tmp_min_rssi) { + tmp_min_rssi = cur_rf_rssi; + min_rssi_index = i; } } } @@ -1387,59 +1388,52 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) rf_num = 0; if (dm_rx_path_sel_table.cck_method == CCK_Rx_Version_2) { for (i = 0; i < RF90_PATH_MAX; i++) { - if (priv->brfpath_rxenable[i]) { - rf_num++; - cur_cck_pwdb = - dm_rx_path_sel_table.cck_pwdb_sta[i]; + if (!priv->brfpath_rxenable[i]) + continue; - if (rf_num == 1) { - cck_rx_ver2_max_index = i; - cck_rx_ver2_sec_index = i; + rf_num++; + cur_cck_pwdb = dm_rx_path_sel_table.cck_pwdb_sta[i]; + + if (rf_num == 1) { + cck_rx_ver2_max_index = i; + cck_rx_ver2_sec_index = i; + tmp_cck_max_pwdb = cur_cck_pwdb; + tmp_cck_min_pwdb = cur_cck_pwdb; + tmp_cck_sec_pwdb = cur_cck_pwdb; + } else if (rf_num == 2) { + if (cur_cck_pwdb >= tmp_cck_max_pwdb) { tmp_cck_max_pwdb = cur_cck_pwdb; - tmp_cck_min_pwdb = cur_cck_pwdb; - tmp_cck_sec_pwdb = cur_cck_pwdb; - } else if (rf_num == 2) { - if (cur_cck_pwdb >= tmp_cck_max_pwdb) { - tmp_cck_max_pwdb = cur_cck_pwdb; - cck_rx_ver2_max_index = i; - } else { - tmp_cck_sec_pwdb = cur_cck_pwdb; - tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } + cck_rx_ver2_max_index = i; } else { - if (cur_cck_pwdb > tmp_cck_max_pwdb) { - tmp_cck_sec_pwdb = - tmp_cck_max_pwdb; - cck_rx_ver2_sec_index = - cck_rx_ver2_max_index; - tmp_cck_max_pwdb = cur_cck_pwdb; - cck_rx_ver2_max_index = i; - } else if (cur_cck_pwdb == - tmp_cck_max_pwdb) { + tmp_cck_sec_pwdb = cur_cck_pwdb; + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + } else { + if (cur_cck_pwdb > tmp_cck_max_pwdb) { + tmp_cck_sec_pwdb = tmp_cck_max_pwdb; + cck_rx_ver2_sec_index = cck_rx_ver2_max_index; + tmp_cck_max_pwdb = cur_cck_pwdb; + cck_rx_ver2_max_index = i; + } else if (cur_cck_pwdb == tmp_cck_max_pwdb) { + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } else if (PWDB_IN_RANGE) { + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } else if (cur_cck_pwdb == tmp_cck_sec_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } else if (PWDB_IN_RANGE) { - tmp_cck_sec_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } else if (cur_cck_pwdb == - tmp_cck_sec_pwdb) { - if (tmp_cck_sec_pwdb == - tmp_cck_min_pwdb) { - tmp_cck_sec_pwdb = - cur_cck_pwdb; - cck_rx_ver2_sec_index = - i; - } - } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && - (cur_cck_pwdb > tmp_cck_min_pwdb)) { - ; - } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - tmp_cck_min_pwdb = cur_cck_pwdb; - } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { - tmp_cck_min_pwdb = cur_cck_pwdb; } + } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && + (cur_cck_pwdb > tmp_cck_min_pwdb)) { + ; + } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) + tmp_cck_min_pwdb = cur_cck_pwdb; + } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { + tmp_cck_min_pwdb = cur_cck_pwdb; } } } @@ -1758,7 +1752,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev) if (priv->rtllib->link_state == MAC80211_LINKED) { if (priv->undecorated_smoothed_pwdb <= - RegC38_TH) { + REG_C38_TH) { if (reg_c38_State != RegC38_NonFsync_Other_AP) { rtl92e_writeb(dev, @@ -1769,7 +1763,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev) RegC38_NonFsync_Other_AP; } } else if (priv->undecorated_smoothed_pwdb >= - (RegC38_TH + 5)) { + (REG_C38_TH + 5)) { if (reg_c38_State) { rtl92e_writeb(dev, rOFDM0_RxDetector3, diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h index 84e673452be4..55641f17412b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h @@ -33,8 +33,6 @@ #define RATE_ADAPTIVE_TH_LOW_40M 10 #define VERY_LOW_RSSI 15 -#define WA_IOT_TH_VAL 25 - #define E_FOR_TX_POWER_TRACK 300 #define TX_POWER_NEAR_FIELD_THRESH_HIGH 68 #define TX_POWER_NEAR_FIELD_THRESH_LOW 62 @@ -44,7 +42,7 @@ #define CURRENT_TX_RATE_REG 0x1e0 #define INITIAL_TX_RATE_REG 0x1e1 #define TX_RETRY_COUNT_REG 0x1ac -#define RegC38_TH 20 +#define REG_C38_TH 20 /*--------------------------Define Parameters-------------------------------*/ @@ -135,8 +133,6 @@ extern struct dig_t dm_digtable; extern const u32 dm_tx_bb_gain[TX_BB_GAIN_TABLE_LEN]; extern const u8 dm_cck_tx_bb_gain[CCK_TX_BB_GAIN_TABLE_LEN][8]; extern const u8 dm_cck_tx_bb_gain_ch14[CCK_TX_BB_GAIN_TABLE_LEN][8]; -/* Maps table index to iq amplify gain (dB, 12 to -24dB) */ -#define dm_tx_bb_gain_idx_to_amplify(idx) (-idx + 12) /*------------------------Export global variable----------------------------*/ diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h index 866e0efbc4fd..3e39c4835ac8 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h @@ -14,6 +14,7 @@ #include struct net_device; + bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index d131ef525f46..c21a0560410a 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -241,7 +241,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED)) return 0; if ((priv->rtllib->link_state == MAC80211_LINKED) && - (priv->rtllib->CntAfterLink < 2)) + (priv->rtllib->cnt_after_link < 2)) return 0; } diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c index 9b0a981f6f22..e38cd0c9c013 100644 --- a/drivers/staging/rtl8192e/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c @@ -496,7 +496,7 @@ void ht_on_assoc_rsp(struct rtllib_device *ieee) ieee->HTHighestOperaRate = ht_get_highest_mcs_rate(ieee, ieee->dot11ht_oper_rate_set, pMcsFilter); - ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate; + ieee->ht_curr_op_rate = ieee->HTHighestOperaRate; ht_info->current_op_mode = pPeerHTInfo->opt_mode; } @@ -625,7 +625,7 @@ EXPORT_SYMBOL(HT_update_self_and_peer_setting); u8 ht_c_check(struct rtllib_device *ieee, u8 *pFrame) { if (ieee->ht_info->current_ht_support) { - if ((IsQoSDataFrame(pFrame) && frame_order(pFrame)) == 1) { + if ((is_qos_data_frame(pFrame) && frame_order(pFrame)) == 1) { netdev_dbg(ieee->dev, "HT CONTROL FILED EXIST!!\n"); return true; } diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c index 9903fe3f3c77..ed6a488bc7ac 100644 --- a/drivers/staging/rtl8192e/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c @@ -18,7 +18,7 @@ static void RxPktPendingTimeout(struct timer_list *t) unsigned long flags = 0; u8 index = 0; - bool bPktInBuf = false; + bool pkt_in_buf = false; spin_lock_irqsave(&(ieee->reorder_spinlock), flags); if (ts->rx_timeout_indicate_seq != 0xffff) { @@ -50,7 +50,7 @@ static void RxPktPendingTimeout(struct timer_list *t) list_add_tail(&pReorderEntry->list, &ieee->RxReorder_Unused_List); } else { - bPktInBuf = true; + pkt_in_buf = true; break; } } @@ -68,10 +68,10 @@ static void RxPktPendingTimeout(struct timer_list *t) return; } rtllib_indicate_packets(ieee, ieee->stats_IndicateArray, index); - bPktInBuf = false; + pkt_in_buf = false; } - if (bPktInBuf && (ts->rx_timeout_indicate_seq == 0xffff)) { + if (pkt_in_buf && (ts->rx_timeout_indicate_seq == 0xffff)) { ts->rx_timeout_indicate_seq = ts->rx_indicate_seq; mod_timer(&ts->rx_pkt_pending_timer, jiffies + msecs_to_jiffies(ieee->ht_info->rx_reorder_pending_time) @@ -431,7 +431,7 @@ void remove_all_ts(struct rtllib_device *ieee) } } -void TsStartAddBaProcess(struct rtllib_device *ieee, struct tx_ts_record *pTxTS) +void rtllib_ts_start_add_ba_process(struct rtllib_device *ieee, struct tx_ts_record *pTxTS) { if (pTxTS->add_ba_req_in_progress == false) { pTxTS->add_ba_req_in_progress = true; diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 0809af3fd041..022851b7f1a9 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -105,26 +105,26 @@ struct cb_desc { u8 bCmdOrInit:1; u8 tx_dis_rate_fallback:1; u8 tx_use_drv_assinged_rate:1; - u8 bHwSec:1; + u8 hw_sec:1; u8 nStuckCount; /* Tx Firmware Related flags (10-11)*/ - u8 bCTSEnable:1; - u8 bRTSEnable:1; - u8 bUseShortGI:1; - u8 bUseShortPreamble:1; + u8 cts_enable:1; + u8 rts_enable:1; + u8 use_short_gi:1; + u8 use_short_preamble:1; u8 tx_enable_fw_calc_dur:1; u8 ampdu_enable:1; - u8 bRTSSTBC:1; + u8 rtsstbc:1; u8 RTSSC:1; - u8 bRTSBW:1; - u8 bPacketBW:1; + u8 rts_bw:1; + u8 packet_bw:1; u8 rts_use_short_preamble:1; - u8 bRTSUseShortGI:1; + u8 rts_use_short_gi:1; u8 multicast:1; - u8 bBroadcast:1; + u8 broadcast:1; u8 drv_agg_enable:1; u8 reserved2:1; @@ -338,9 +338,9 @@ enum rt_op_mode { #define RTLLIB_QCTL_TID 0x000F #define FC_QOS_BIT BIT(7) -#define IsDataFrame(pdu) (((pdu[0] & 0x0C) == 0x08) ? true : false) -#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT))) -#define IsQoSDataFrame(pframe) \ +#define is_data_frame(pdu) (((pdu[0] & 0x0C) == 0x08) ? true : false) +#define is_legacy_data_frame(pdu) (is_data_frame(pdu) && (!(pdu[0]&FC_QOS_BIT))) +#define is_qos_data_frame(pframe) \ ((*(u16 *)pframe&(IEEE80211_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA)) == \ (IEEE80211_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA)) #define frame_order(pframe) (*(u16 *)pframe&IEEE80211_FCTL_ORDER) @@ -481,7 +481,7 @@ struct rtllib_rx_stats { u16 bHwError:1; u16 bCRC:1; u16 bICV:1; - u16 Decrypted:1; + u16 decrypted:1; u32 time_stamp_low; u32 time_stamp_high; @@ -489,7 +489,7 @@ struct rtllib_rx_stats { u8 RxBufShift; bool bIsAMPDU; bool bFirstMPDU; - bool bContainHTC; + bool contain_htc; u32 RxPWDBAll; u8 RxMIMOSignalStrength[4]; s8 RxMIMOSignalQuality[2]; @@ -728,7 +728,7 @@ union frameqos { #define QOS_VERSION_1 1 struct rtllib_qos_information_element { - u8 elementID; + u8 element_id; u8 length; u8 qui[QOS_OUI_LEN]; u8 qui_type; @@ -799,7 +799,7 @@ static inline const char *eap_get_type(int type) eap_types[type]; } -static inline u8 Frame_QoSTID(u8 *buf) +static inline u8 frame_qos_tid(u8 *buf) { struct ieee80211_hdr_3addr *hdr; u16 fc; @@ -910,14 +910,14 @@ struct rtllib_network { u8 hidden_ssid_len; struct rtllib_qos_data qos_data; - bool bWithAironetIE; + bool with_aironet_ie; bool ckip_supported; bool ccx_rm_enable; - u8 CcxRmState[2]; - bool bMBssidValid; - u8 MBssidMask; - u8 MBssid[ETH_ALEN]; - bool bWithCcxVerNum; + u8 ccx_rm_state[2]; + bool mb_ssid_valid; + u8 mb_ssid_mask; + u8 mb_ssid[ETH_ALEN]; + bool with_ccx_ver_num; u8 bss_ccx_ver_number; /* These are network statistics */ struct rtllib_rx_stats stats; @@ -949,8 +949,8 @@ struct rtllib_network { u8 wmm_info; struct rtllib_wmm_ac_param wmm_param[4]; u8 turbo_enable; - u16 CountryIeLen; - u8 CountryIeBuf[MAX_IE_LEN]; + u16 country_ie_len; + u8 country_ie_buf[MAX_IE_LEN]; struct bss_ht bssht; bool broadcom_cap_exist; bool realtek_cap_exit; @@ -1018,7 +1018,7 @@ struct tx_pending { struct bandwidth_autoswitch { long threshold_20Mhzto40Mhz; long threshold_40Mhzto20Mhz; - bool bforced_tx20Mhz; + bool forced_tx_20MHz; bool bautoswitch_enable; }; @@ -1168,7 +1168,7 @@ struct rtllib_device { bool disable_mgnt_queue; unsigned long status; - u8 CntAfterLink; + u8 cnt_after_link; enum rt_op_mode op_mode; @@ -1198,7 +1198,7 @@ struct rtllib_device { u8 reg_dot11tx_ht_oper_rate_set[16]; u8 dot11ht_oper_rate_set[16]; u8 reg_ht_supp_rate_set[16]; - u8 HTCurrentOperaRate; + u8 ht_curr_op_rate; u8 HTHighestOperaRate; u8 tx_dis_rate_fallback; u8 tx_use_drv_assinged_rate; @@ -1407,9 +1407,9 @@ struct rtllib_device { struct work_struct wx_sync_scan_wq; union { - struct rtllib_rxb *RfdArray[REORDER_WIN_SIZE]; + struct rtllib_rxb *rfd_array[REORDER_WIN_SIZE]; struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE]; - struct rtllib_rxb *prxbIndicateArray[REORDER_WIN_SIZE]; + struct rtllib_rxb *prxb_indicate_array[REORDER_WIN_SIZE]; struct { struct sw_chnl_cmd PreCommonCmd[MAX_PRECMD_CNT]; struct sw_chnl_cmd PostCommonCmd[MAX_POSTCMD_CNT]; @@ -1770,7 +1770,7 @@ void rtllib_reset_ba_entry(struct ba_record *ba); bool rtllib_get_ts(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *addr, u8 TID, enum tr_select tx_rx_select, bool bAddNewTs); void rtllib_ts_init(struct rtllib_device *ieee); -void TsStartAddBaProcess(struct rtllib_device *ieee, +void rtllib_ts_start_add_ba_process(struct rtllib_device *ieee, struct tx_ts_record *pTxTS); void remove_peer_ts(struct rtllib_device *ieee, u8 *addr); void remove_all_ts(struct rtllib_device *ieee); @@ -1803,7 +1803,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, struct rtllib_rx_stats *stats); void rtllib_indicate_packets(struct rtllib_device *ieee, - struct rtllib_rxb **prxbIndicateArray, u8 index); + struct rtllib_rxb **prxb_indicate_array, u8 index); #define RT_ASOC_RETRY_LIMIT 5 u8 mgnt_query_tx_rate_exclude_cck_rates(struct rtllib_device *ieee); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index cbb8c8dbe9b0..639877069fad 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -182,7 +182,7 @@ static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = key->tx_pn[0]; hdr = (struct ieee80211_hdr *)skb->data; - if (!tcb_desc->bHwSec) { + if (!tcb_desc->hw_sec) { struct aead_request *req; struct scatterlist sg[2]; u8 *aad = key->tx_aad; @@ -265,7 +265,7 @@ static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) key->dot11rsna_stats_ccmp_replays++; return -4; } - if (!tcb_desc->bHwSec) { + if (!tcb_desc->hw_sec) { size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; struct aead_request *req; struct scatterlist sg[2]; @@ -407,4 +407,5 @@ static void __exit rtllib_crypto_ccmp_exit(void) module_init(rtllib_crypto_ccmp_init); module_exit(rtllib_crypto_ccmp_exit); +MODULE_DESCRIPTION("Support module for rtllib CCMP crypto"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index 0244b524a7d4..dc0917b03511 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -268,7 +268,7 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) hdr = (struct ieee80211_hdr *)skb->data; - if (!tcb_desc->bHwSec) { + if (!tcb_desc->hw_sec) { if (!tkey->tx_phase1_done) { tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, tkey->tx_iv32); @@ -285,7 +285,7 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) memmove(pos, pos + 8, hdr_len); pos += hdr_len; - if (tcb_desc->bHwSec) { + if (tcb_desc->hw_sec) { *pos++ = Hi8(tkey->tx_iv16); *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F; *pos++ = Lo8(tkey->tx_iv16); @@ -301,7 +301,7 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = (tkey->tx_iv32 >> 16) & 0xff; *pos++ = (tkey->tx_iv32 >> 24) & 0xff; - if (!tcb_desc->bHwSec) { + if (!tcb_desc->hw_sec) { icv = skb_put(skb, 4); crc = ~crc32_le(~0, pos, len); icv[0] = crc; @@ -319,7 +319,7 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) tkey->tx_iv32++; } - if (!tcb_desc->bHwSec) + if (!tcb_desc->hw_sec) return ret; return 0; } @@ -371,7 +371,7 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); pos += 8; - if (!tcb_desc->bHwSec || (skb->cb[0] == 1)) { + if (!tcb_desc->hw_sec || (skb->cb[0] == 1)) { if ((iv32 < tkey->rx_iv32 || (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) && tkey->initialized) { @@ -708,4 +708,5 @@ static void __exit rtllib_crypto_tkip_exit(void) module_init(rtllib_crypto_tkip_init); module_exit(rtllib_crypto_tkip_exit); +MODULE_DESCRIPTION("Support module for rtllib TKIP crypto"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c index 21c2b7666d6f..10092f6884ff 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c @@ -102,7 +102,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) /* Copy rest of the WEP key (the secret part) */ memcpy(key + 3, wep->key, wep->key_len); - if (!tcb_desc->bHwSec) { + if (!tcb_desc->hw_sec) { /* Append little-endian CRC32 and encrypt it to produce ICV */ crc = ~crc32_le(~0, pos, len); icv = skb_put(skb, 4); @@ -155,7 +155,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) /* Apply RC4 to data and compute CRC32 over decrypted data */ plen = skb->len - hdr_len - 8; - if (!tcb_desc->bHwSec) { + if (!tcb_desc->hw_sec) { arc4_setkey(&wep->rx_ctx_arc4, key, klen); arc4_crypt(&wep->rx_ctx_arc4, pos, pos, plen + 4); @@ -238,4 +238,5 @@ static void __exit rtllib_crypto_wep_exit(void) module_init(rtllib_crypto_wep_init); module_exit(rtllib_crypto_wep_exit); +MODULE_DESCRIPTION("Support module for rtllib WEP crypto"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index e7af4a25b0be..469a69726c16 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -175,4 +175,5 @@ static void __exit rtllib_exit(void) module_init(rtllib_init); module_exit(rtllib_exit); +MODULE_DESCRIPTION("Support module for rtllib wireless devices"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index ee469c9118b8..84ca5d769b7e 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -55,7 +55,7 @@ static inline void rtllib_monitor_rx(struct rtllib_device *ieee, /* Called only as a tasklet (software IRQ) */ static struct rtllib_frag_entry * rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq, - unsigned int frag, u8 tid, u8 *src, u8 *dst) + unsigned int frag, u8 tid, u8 *src, u8 *dst) { struct rtllib_frag_entry *entry; int i; @@ -84,7 +84,7 @@ rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq, /* Called only as a tasklet (software IRQ) */ static struct sk_buff * rtllib_frag_cache_get(struct rtllib_device *ieee, - struct ieee80211_hdr *hdr) + struct ieee80211_hdr *hdr) { struct sk_buff *skb = NULL; u16 fc = le16_to_cpu(hdr->frame_control); @@ -143,7 +143,7 @@ rtllib_frag_cache_get(struct rtllib_device *ieee, * should have already been received */ entry = rtllib_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, - hdr->addr1); + hdr->addr1); if (entry) { entry->last_frag = frag; skb = entry->skb; @@ -155,7 +155,7 @@ rtllib_frag_cache_get(struct rtllib_device *ieee, /* Called only as a tasklet (software IRQ) */ static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, - struct ieee80211_hdr *hdr) + struct ieee80211_hdr *hdr) { u16 fc = le16_to_cpu(hdr->frame_control); u16 sc = le16_to_cpu(hdr->seq_ctrl); @@ -181,7 +181,7 @@ static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, } entry = rtllib_frag_cache_find(ieee, seq, -1, tid, hdr->addr2, - hdr->addr1); + hdr->addr1); if (!entry) { netdev_dbg(ieee->dev, @@ -202,8 +202,7 @@ static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, */ static inline int rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats, u16 type, - u16 stype) + struct rtllib_rx_stats *rx_stats, u16 type, u16 stype) { /* On the struct stats definition there is written that * this is not mandatory.... but seems that the probe @@ -228,7 +227,7 @@ rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb, /* Called by rtllib_rx_frame_decrypt */ static int rtllib_is_eapol_frame(struct rtllib_device *ieee, - struct sk_buff *skb, size_t hdrlen) + struct sk_buff *skb, size_t hdrlen) { struct net_device *dev = ieee->dev; u16 fc, ethertype; @@ -282,10 +281,10 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, struct cb_desc *tcb_desc = (struct cb_desc *) (skb->cb + MAX_DEV_ADDR_SIZE); - tcb_desc->bHwSec = 1; + tcb_desc->hw_sec = 1; if (ieee->need_sw_enc) - tcb_desc->bHwSec = 0; + tcb_desc->hw_sec = 0; } hdr = (struct ieee80211_hdr *)skb->data; @@ -321,10 +320,10 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb, struct cb_desc *tcb_desc = (struct cb_desc *) (skb->cb + MAX_DEV_ADDR_SIZE); - tcb_desc->bHwSec = 1; + tcb_desc->hw_sec = 1; if (ieee->need_sw_enc) - tcb_desc->bHwSec = 0; + tcb_desc->hw_sec = 0; } hdr = (struct ieee80211_hdr *)skb->data; @@ -346,7 +345,7 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb, /* this function is stolen from ipw2200 driver*/ #define IEEE_PACKET_RETRY_TIME (5 * HZ) static int is_duplicate_packet(struct rtllib_device *ieee, - struct ieee80211_hdr *header) + struct ieee80211_hdr *header) { u16 fc = le16_to_cpu(header->frame_control); u16 sc = le16_to_cpu(header->seq_ctrl); @@ -403,40 +402,40 @@ drop: return 1; } -static bool AddReorderEntry(struct rx_ts_record *ts, - struct rx_reorder_entry *pReorderEntry) +static bool add_reorder_entry(struct rx_ts_record *ts, + struct rx_reorder_entry *pReorderEntry) { - struct list_head *pList = &ts->rx_pending_pkt_list; + struct list_head *list = &ts->rx_pending_pkt_list; - while (pList->next != &ts->rx_pending_pkt_list) { + while (list->next != &ts->rx_pending_pkt_list) { if (SN_LESS(pReorderEntry->SeqNum, ((struct rx_reorder_entry *) - list_entry(pList->next, struct rx_reorder_entry, + list_entry(list->next, struct rx_reorder_entry, list))->SeqNum)) - pList = pList->next; + list = list->next; else if (SN_EQUAL(pReorderEntry->SeqNum, - ((struct rx_reorder_entry *)list_entry(pList->next, + ((struct rx_reorder_entry *)list_entry(list->next, struct rx_reorder_entry, list))->SeqNum)) return false; else break; } - pReorderEntry->list.next = pList->next; + pReorderEntry->list.next = list->next; pReorderEntry->list.next->prev = &pReorderEntry->list; - pReorderEntry->list.prev = pList; - pList->next = &pReorderEntry->list; + pReorderEntry->list.prev = list; + list->next = &pReorderEntry->list; return true; } void rtllib_indicate_packets(struct rtllib_device *ieee, - struct rtllib_rxb **prxbIndicateArray, u8 index) + struct rtllib_rxb **prxb_indicate_array, u8 index) { struct net_device_stats *stats = &ieee->stats; u8 i = 0, j = 0; u16 ethertype; for (j = 0; j < index; j++) { - struct rtllib_rxb *prxb = prxbIndicateArray[j]; + struct rtllib_rxb *prxb = prxb_indicate_array[j]; for (i = 0; i < prxb->nr_subframes; i++) { struct sk_buff *sub_skb = prxb->subframes[i]; @@ -491,13 +490,13 @@ void rtllib_flush_rx_ts_pending_pkts(struct rtllib_device *ieee, struct rx_ts_record *ts) { struct rx_reorder_entry *pRxReorderEntry; - u8 RfdCnt = 0; + u8 rfd_cnt = 0; del_timer_sync(&ts->rx_pkt_pending_timer); while (!list_empty(&ts->rx_pending_pkt_list)) { - if (RfdCnt >= REORDER_WIN_SIZE) { + if (rfd_cnt >= REORDER_WIN_SIZE) { netdev_info(ieee->dev, - "-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n", + "-------------->%s() error! rfd_cnt >= REORDER_WIN_SIZE\n", __func__); break; } @@ -509,36 +508,36 @@ void rtllib_flush_rx_ts_pending_pkts(struct rtllib_device *ieee, pRxReorderEntry->SeqNum); list_del_init(&pRxReorderEntry->list); - ieee->RfdArray[RfdCnt] = pRxReorderEntry->prxb; + ieee->rfd_array[rfd_cnt] = pRxReorderEntry->prxb; - RfdCnt = RfdCnt + 1; + rfd_cnt = rfd_cnt + 1; list_add_tail(&pRxReorderEntry->list, &ieee->RxReorder_Unused_List); } - rtllib_indicate_packets(ieee, ieee->RfdArray, RfdCnt); + rtllib_indicate_packets(ieee, ieee->rfd_array, rfd_cnt); ts->rx_indicate_seq = 0xffff; } -static void RxReorderIndicatePacket(struct rtllib_device *ieee, - struct rtllib_rxb *prxb, - struct rx_ts_record *ts, u16 SeqNum) +static void rx_reorder_indicate_packet(struct rtllib_device *ieee, + struct rtllib_rxb *prxb, + struct rx_ts_record *ts, u16 SeqNum) { struct rt_hi_throughput *ht_info = ieee->ht_info; struct rx_reorder_entry *pReorderEntry = NULL; - u8 WinSize = ht_info->rx_reorder_win_size; - u16 WinEnd = 0; + u8 win_size = ht_info->rx_reorder_win_size; + u16 win_end = 0; u8 index = 0; - bool bMatchWinStart = false, bPktInBuf = false; + bool match_win_start = false, pkt_in_buf = false; unsigned long flags; netdev_dbg(ieee->dev, - "%s(): Seq is %d, ts->rx_indicate_seq is %d, WinSize is %d\n", - __func__, SeqNum, ts->rx_indicate_seq, WinSize); + "%s(): Seq is %d, ts->rx_indicate_seq is %d, win_size is %d\n", + __func__, SeqNum, ts->rx_indicate_seq, win_size); spin_lock_irqsave(&(ieee->reorder_spinlock), flags); - WinEnd = (ts->rx_indicate_seq + WinSize - 1) % 4096; + win_end = (ts->rx_indicate_seq + win_size - 1) % 4096; /* Rx Reorder initialize condition.*/ if (ts->rx_indicate_seq == 0xffff) ts->rx_indicate_seq = SeqNum; @@ -563,17 +562,17 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, /* Sliding window manipulation. Conditions includes: * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 - * 2. Incoming SeqNum is larger than the WinEnd => Window shift N + * 2. Incoming SeqNum is larger than the win_end => Window shift N */ if (SN_EQUAL(SeqNum, ts->rx_indicate_seq)) { ts->rx_indicate_seq = (ts->rx_indicate_seq + 1) % 4096; - bMatchWinStart = true; - } else if (SN_LESS(WinEnd, SeqNum)) { - if (SeqNum >= (WinSize - 1)) - ts->rx_indicate_seq = SeqNum + 1 - WinSize; + match_win_start = true; + } else if (SN_LESS(win_end, SeqNum)) { + if (SeqNum >= (win_size - 1)) + ts->rx_indicate_seq = SeqNum + 1 - win_size; else ts->rx_indicate_seq = 4095 - - (WinSize - (SeqNum + 1)) + 1; + (win_size - (SeqNum + 1)) + 1; netdev_dbg(ieee->dev, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", ts->rx_indicate_seq, SeqNum); @@ -589,12 +588,12 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, * 2. All packets with SeqNum larger than or equal to * WinStart => Buffer it. */ - if (bMatchWinStart) { + if (match_win_start) { /* Current packet is going to be indicated.*/ netdev_dbg(ieee->dev, "Packets indication! IndicateSeq: %d, NewSeq: %d\n", ts->rx_indicate_seq, SeqNum); - ieee->prxbIndicateArray[0] = prxb; + ieee->prxb_indicate_array[0] = prxb; index = 1; } else { /* Current packet is going to be inserted into pending list.*/ @@ -610,7 +609,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pReorderEntry->SeqNum = SeqNum; pReorderEntry->prxb = prxb; - if (!AddReorderEntry(ts, pReorderEntry)) { + if (!add_reorder_entry(ts, pReorderEntry)) { int i; netdev_dbg(ieee->dev, @@ -665,7 +664,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, netdev_err(ieee->dev, "%s(): Buffer overflow!\n", __func__); - bPktInBuf = true; + pkt_in_buf = true; break; } @@ -675,7 +674,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, ts->rx_indicate_seq = (ts->rx_indicate_seq + 1) % 4096; - ieee->prxbIndicateArray[index] = pReorderEntry->prxb; + ieee->prxb_indicate_array[index] = pReorderEntry->prxb; netdev_dbg(ieee->dev, "%s(): Indicate SeqNum %d!\n", __func__, pReorderEntry->SeqNum); index++; @@ -683,7 +682,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, list_add_tail(&pReorderEntry->list, &ieee->RxReorder_Unused_List); } else { - bPktInBuf = true; + pkt_in_buf = true; break; } } @@ -706,11 +705,11 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, flags); return; } - rtllib_indicate_packets(ieee, ieee->prxbIndicateArray, index); - bPktInBuf = false; + rtllib_indicate_packets(ieee, ieee->prxb_indicate_array, index); + pkt_in_buf = false; } - if (bPktInBuf && ts->rx_timeout_indicate_seq == 0xffff) { + if (pkt_in_buf && ts->rx_timeout_indicate_seq == 0xffff) { netdev_dbg(ieee->dev, "%s(): SET rx timeout timer\n", __func__); ts->rx_timeout_indicate_seq = ts->rx_indicate_seq; spin_unlock_irqrestore(&ieee->reorder_spinlock, flags); @@ -728,11 +727,10 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)skb->data; u16 fc = le16_to_cpu(hdr->frame_control); - u16 LLCOffset = sizeof(struct ieee80211_hdr_3addr); - u16 ChkLength; + u16 llc_offset = sizeof(struct ieee80211_hdr_3addr); bool is_aggregate_frame = false; u16 nSubframe_Length; - u8 nPadding_Length = 0; + u8 pad_len = 0; u16 SeqNum = 0; struct sk_buff *sub_skb; /* just for debug purpose */ @@ -742,16 +740,14 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, is_aggregate_frame = true; if (RTLLIB_QOS_HAS_SEQ(fc)) - LLCOffset += 2; - if (rx_stats->bContainHTC) - LLCOffset += sHTCLng; + llc_offset += 2; + if (rx_stats->contain_htc) + llc_offset += sHTCLng; - ChkLength = LLCOffset; - - if (skb->len <= ChkLength) + if (skb->len <= llc_offset) return 0; - skb_pull(skb, LLCOffset); + skb_pull(skb, llc_offset); ieee->is_aggregate_frame = is_aggregate_frame; if (!is_aggregate_frame) { rxb->nr_subframes = 1; @@ -833,15 +829,15 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, skb_pull(skb, nSubframe_Length); if (skb->len != 0) { - nPadding_Length = 4 - ((nSubframe_Length + + pad_len = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4); - if (nPadding_Length == 4) - nPadding_Length = 0; + if (pad_len == 4) + pad_len = 0; - if (skb->len < nPadding_Length) + if (skb->len < pad_len) return 0; - skb_pull(skb, nPadding_Length); + skb_pull(skb, pad_len); } } @@ -862,7 +858,7 @@ static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee, netdev_info(ieee->dev, "%s: find HTCControl!\n", __func__); hdrlen += 4; - rx_stats->bContainHTC = true; + rx_stats->contain_htc = true; } return hdrlen; @@ -881,8 +877,8 @@ static int rtllib_rx_check_duplicate(struct rtllib_device *ieee, if (!ieee->ht_info->cur_rx_reorder_enable || !ieee->current_network.qos_data.active || - !IsDataFrame(skb->data) || - IsLegacyDataFrame(skb->data)) { + !is_data_frame(skb->data) || + is_legacy_data_frame(skb->data)) { if (!ieee80211_is_beacon(hdr->frame_control)) { if (is_duplicate_packet(ieee, hdr)) return -1; @@ -891,7 +887,7 @@ static int rtllib_rx_check_duplicate(struct rtllib_device *ieee, struct rx_ts_record *ts = NULL; if (rtllib_get_ts(ieee, (struct ts_common_info **)&ts, hdr->addr2, - (u8)Frame_QoSTID((u8 *)(skb->data)), RX_DIR, true)) { + (u8)frame_qos_tid((u8 *)(skb->data)), RX_DIR, true)) { if ((fc & (1 << 11)) && (frag == ts->rx_last_frag_num) && (WLAN_GET_SEQ_SEQ(sc) == ts->rx_last_seq_num)) return -1; @@ -1025,7 +1021,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, sc = le16_to_cpu(hdr->seq_ctrl); frag = WLAN_GET_SEQ_FRAG(sc); - if ((!rx_stats->Decrypted)) + if ((!rx_stats->decrypted)) ieee->need_sw_enc = 1; else ieee->need_sw_enc = 0; @@ -1223,7 +1219,7 @@ static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee, kfree(rxb); } -static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, +static int rtllib_rx_infra_adhoc(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; @@ -1322,9 +1318,9 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, /* Get TS for Rx Reorder */ hdr = (struct ieee80211_hdr *)skb->data; - if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) + if (ieee->current_network.qos_data.active && is_qos_data_frame(skb->data) && !is_multicast_ether_addr(hdr->addr1)) { - TID = Frame_QoSTID(skb->data); + TID = frame_qos_tid(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); rtllib_get_ts(ieee, (struct ts_common_info **)&ts, hdr->addr2, TID, RX_DIR, true); @@ -1366,7 +1362,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, if (!ieee->ht_info->cur_rx_reorder_enable || !ts) rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src); else - RxReorderIndicatePacket(ieee, rxb, ts, SeqNum); + rx_reorder_indicate_packet(ieee, rxb, ts, SeqNum); dev_kfree_skb(skb); @@ -1383,7 +1379,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, return 0; } -static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb, +static int rtllib_rx_monitor(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -1431,10 +1427,10 @@ int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, switch (ieee->iw_mode) { case IW_MODE_INFRA: - ret = rtllib_rx_InfraAdhoc(ieee, skb, rx_stats); + ret = rtllib_rx_infra_adhoc(ieee, skb, rx_stats); break; case IW_MODE_MONITOR: - ret = rtllib_rx_Monitor(ieee, skb, rx_stats); + ret = rtllib_rx_monitor(ieee, skb, rx_stats); break; default: netdev_info(ieee->dev, "%s: ERR iw mode!!!\n", __func__); @@ -1456,7 +1452,7 @@ static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; static int rtllib_verify_qos_info(struct rtllib_qos_information_element *info_element, int sub_type) { - if (info_element->elementID != QOS_ELEMENT_ID) + if (info_element->element_id != QOS_ELEMENT_ID) return -1; if (info_element->qui_subtype != sub_type) return -1; @@ -1813,21 +1809,21 @@ static void rtllib_parse_mife_generic(struct rtllib_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x01) { if (info_element->len == 6) { - memcpy(network->CcxRmState, &info_element->data[4], 2); - if (network->CcxRmState[0] != 0) + memcpy(network->ccx_rm_state, &info_element->data[4], 2); + if (network->ccx_rm_state[0] != 0) network->ccx_rm_enable = true; else network->ccx_rm_enable = false; - network->MBssidMask = network->CcxRmState[1] & 0x07; - if (network->MBssidMask != 0) { - network->bMBssidValid = true; - network->MBssidMask = 0xff << - (network->MBssidMask); - ether_addr_copy(network->MBssid, + network->mb_ssid_mask = network->ccx_rm_state[1] & 0x07; + if (network->mb_ssid_mask != 0) { + network->mb_ssid_valid = true; + network->mb_ssid_mask = 0xff << + (network->mb_ssid_mask); + ether_addr_copy(network->mb_ssid, network->bssid); - network->MBssid[5] &= network->MBssidMask; + network->mb_ssid[5] &= network->mb_ssid_mask; } else { - network->bMBssidValid = false; + network->mb_ssid_valid = false; } } else { network->ccx_rm_enable = false; @@ -1839,10 +1835,10 @@ static void rtllib_parse_mife_generic(struct rtllib_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x03) { if (info_element->len == 5) { - network->bWithCcxVerNum = true; + network->with_ccx_ver_num = true; network->bss_ccx_ver_number = info_element->data[4]; } else { - network->bWithCcxVerNum = false; + network->with_ccx_ver_num = false; network->bss_ccx_ver_number = 0; } } @@ -1914,7 +1910,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, switch (info_element->id) { case MFIE_TYPE_SSID: if (rtllib_is_empty_essid(info_element->data, - info_element->len)) { + info_element->len)) { network->flags |= NETWORK_EMPTY_ESSID; break; } @@ -2090,7 +2086,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, netdev_dbg(ieee->dev, "MFIE_TYPE_AIRONET: %d bytes\n", info_element->len); if (info_element->len > IE_CISCO_FLAG_POSITION) { - network->bWithAironetIE = true; + network->with_aironet_ie = true; if ((info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_MIC) || @@ -2100,7 +2096,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, else network->ckip_supported = false; } else { - network->bWithAironetIE = false; + network->with_aironet_ie = false; network->ckip_supported = false; } break; @@ -2183,8 +2179,8 @@ static inline int rtllib_network_init( network->turbo_enable = 0; network->SignalStrength = stats->SignalStrength; network->RSSI = stats->SignalStrength; - network->CountryIeLen = 0; - memset(network->CountryIeBuf, 0, MAX_IE_LEN); + network->country_ie_len = 0; + memset(network->country_ie_buf, 0, MAX_IE_LEN); ht_initialize_bss_desc(&network->bssht); network->flags |= NETWORK_HAS_CCK; @@ -2193,10 +2189,10 @@ static inline int rtllib_network_init( network->wzc_ie_len = 0; if (rtllib_parse_info_param(ieee, - beacon->info_element, - (stats->len - sizeof(*beacon)), - network, - stats)) + beacon->info_element, + (stats->len - sizeof(*beacon)), + network, + stats)) return 1; network->mode = 0; @@ -2342,21 +2338,21 @@ static inline void update_network(struct rtllib_device *ieee, dst->RSSI = src->RSSI; dst->turbo_enable = src->turbo_enable; - dst->CountryIeLen = src->CountryIeLen; - memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen); + dst->country_ie_len = src->country_ie_len; + memcpy(dst->country_ie_buf, src->country_ie_buf, src->country_ie_len); - dst->bWithAironetIE = src->bWithAironetIE; + dst->with_aironet_ie = src->with_aironet_ie; dst->ckip_supported = src->ckip_supported; - memcpy(dst->CcxRmState, src->CcxRmState, 2); + memcpy(dst->ccx_rm_state, src->ccx_rm_state, 2); dst->ccx_rm_enable = src->ccx_rm_enable; - dst->MBssidMask = src->MBssidMask; - dst->bMBssidValid = src->bMBssidValid; - memcpy(dst->MBssid, src->MBssid, 6); - dst->bWithCcxVerNum = src->bWithCcxVerNum; + dst->mb_ssid_mask = src->mb_ssid_mask; + dst->mb_ssid_valid = src->mb_ssid_valid; + memcpy(dst->mb_ssid, src->mb_ssid, 6); + dst->with_ccx_ver_num = src->with_ccx_ver_num; dst->bss_ccx_ver_number = src->bss_ccx_ver_number; } -static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel) +static int is_passive_channel(struct rtllib_device *rtllib, u8 channel) { if (channel > MAX_CHANNEL_NUMBER) { netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__); @@ -2432,7 +2428,7 @@ static inline void rtllib_process_probe_response( goto free_network; if (ieee80211_is_probe_resp(frame_ctl)) { - if (IsPassiveChannel(ieee, network->channel)) { + if (is_passive_channel(ieee, network->channel)) { netdev_info(ieee->dev, "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); @@ -2562,7 +2558,7 @@ static void rtllib_rx_mgt(struct rtllib_device *ieee, schedule_work(&ieee->ps_task); } else if (ieee80211_is_probe_resp(header->frame_control)) { netdev_dbg(ieee->dev, "received PROBE RESPONSE\n"); - rtllib_process_probe_response(ieee, - (struct rtllib_probe_response *)header, stats); + rtllib_process_probe_response(ieee, (struct rtllib_probe_response *)header, + stats); } } diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 97fdca828da7..0fc97c868f81 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -421,7 +421,7 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee) * So we switch to MAC80211_LINKED_SCANNING to remember * that we are still logically linked (not interested in * new network events, despite for updating the net list, - * but we are temporarly 'unlinked' as the driver shall + * but we are temporarily 'unlinked' as the driver shall * not filter RX frames and the channel is changing. * So the only situation in which are interested is to check * if the state become LINKED because of the #1 situation @@ -934,7 +934,7 @@ static void rtllib_associate_abort(struct rtllib_device *ieee) ieee->associate_seq++; - /* don't scan, and avoid to have the RX path possibily + /* don't scan, and avoid to have the RX path possibly * try again to associate. Even do not react to AUTH or * ASSOC response. Just wait for the retry wq to be scheduled. * Here we will check if there are good nets to associate @@ -1359,7 +1359,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time) return 0; timeout = ieee->current_network.beacon_interval; ieee->current_network.dtim_data = RTLLIB_DTIM_INVALID; - /* there's no need to nofity AP that I find you buffered + /* there's no need to notify AP that I find you buffered * with broadcast packet */ if (dtim & (RTLLIB_DTIM_UCAST & ieee->ps)) @@ -1806,7 +1806,7 @@ void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee) spin_lock_irqsave(&ieee->lock, flags); - /* called with 2nd parm 0, no tx mgmt lock required */ + /* called with 2nd param 0, no tx mgmt lock required */ rtllib_sta_wakeup(ieee, 0); /* update the tx status */ diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 1aeb207a3fee..8e2abd16eb86 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -228,7 +228,7 @@ err_free: return NULL; } -static int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu) +static int rtllib_classify(struct sk_buff *skb) { struct ethhdr *eth; struct iphdr *ip; @@ -275,12 +275,12 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, if (!ht_info->current_ht_support || !ht_info->enable_ht) return; - if (!IsQoSDataFrame(skb->data)) + if (!is_qos_data_frame(skb->data)) return; if (is_multicast_ether_addr(hdr->addr1)) return; - if (tcb_desc->bdhcp || ieee->CntAfterLink < 2) + if (tcb_desc->bdhcp || ieee->cnt_after_link < 2) return; if (ht_info->iot_action & HT_IOT_ACT_TX_NO_AGGREGATION) @@ -290,7 +290,7 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, return; if (ht_info->current_ampdu_enable) { if (!rtllib_get_ts(ieee, (struct ts_common_info **)(&ts), hdr->addr1, - skb->priority, TX_DIR, true)) { + skb->priority, TX_DIR, true)) { netdev_info(ieee->dev, "%s: can't get TS\n", __func__); return; } @@ -301,7 +301,7 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, } else if (tcb_desc->bdhcp == 1) { ; } else if (!ts->disable_add_ba) { - TsStartAddBaProcess(ieee, ts); + rtllib_ts_start_add_ba_process(ieee, ts); } return; } else if (!ts->using_ba) { @@ -319,51 +319,51 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, } } -static void rtllib_query_ShortPreambleMode(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) +static void rtllib_query_short_preamble_mode(struct rtllib_device *ieee, + struct cb_desc *tcb_desc) { - tcb_desc->bUseShortPreamble = false; + tcb_desc->use_short_preamble = false; if (tcb_desc->data_rate == 2) return; else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - tcb_desc->bUseShortPreamble = true; + tcb_desc->use_short_preamble = true; } -static void rtllib_query_HTCapShortGI(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) +static void rtllib_query_ht_cap_short_gi(struct rtllib_device *ieee, + struct cb_desc *tcb_desc) { struct rt_hi_throughput *ht_info = ieee->ht_info; - tcb_desc->bUseShortGI = false; + tcb_desc->use_short_gi = false; if (!ht_info->current_ht_support || !ht_info->enable_ht) return; if (ht_info->cur_bw_40mhz && ht_info->cur_short_gi_40mhz) - tcb_desc->bUseShortGI = true; + tcb_desc->use_short_gi = true; else if (!ht_info->cur_bw_40mhz && ht_info->cur_short_gi_20mhz) - tcb_desc->bUseShortGI = true; + tcb_desc->use_short_gi = true; } -static void rtllib_query_BandwidthMode(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) +static void rtllib_query_bandwidth_mode(struct rtllib_device *ieee, + struct cb_desc *tcb_desc) { struct rt_hi_throughput *ht_info = ieee->ht_info; - tcb_desc->bPacketBW = false; + tcb_desc->packet_bw = false; if (!ht_info->current_ht_support || !ht_info->enable_ht) return; - if (tcb_desc->multicast || tcb_desc->bBroadcast) + if (tcb_desc->multicast || tcb_desc->broadcast) return; if ((tcb_desc->data_rate & 0x80) == 0) return; if (ht_info->cur_bw_40mhz && ht_info->cur_tx_bw40mhz && - !ieee->bandwidth_auto_switch.bforced_tx20Mhz) - tcb_desc->bPacketBW = true; + !ieee->bandwidth_auto_switch.forced_tx_20MHz) + tcb_desc->packet_bw = true; } static void rtllib_query_protectionmode(struct rtllib_device *ieee, @@ -372,13 +372,13 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee, { struct rt_hi_throughput *ht_info; - tcb_desc->bRTSSTBC = false; - tcb_desc->bRTSUseShortGI = false; - tcb_desc->bCTSEnable = false; + tcb_desc->rtsstbc = false; + tcb_desc->rts_use_short_gi = false; + tcb_desc->cts_enable = false; tcb_desc->RTSSC = 0; - tcb_desc->bRTSBW = false; + tcb_desc->rts_bw = false; - if (tcb_desc->bBroadcast || tcb_desc->multicast) + if (tcb_desc->broadcast || tcb_desc->multicast) return; if (is_broadcast_ether_addr(skb->data + 16)) @@ -386,11 +386,11 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee, if (ieee->mode < WIRELESS_MODE_N_24G) { if (skb->len > ieee->rts) { - tcb_desc->bRTSEnable = true; + tcb_desc->rts_enable = true; tcb_desc->rts_rate = MGN_24M; } else if (ieee->current_network.buseprotection) { - tcb_desc->bRTSEnable = true; - tcb_desc->bCTSEnable = true; + tcb_desc->rts_enable = true; + tcb_desc->cts_enable = true; tcb_desc->rts_rate = MGN_24M; } return; @@ -400,54 +400,54 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee, while (true) { if (ht_info->iot_action & HT_IOT_ACT_FORCED_CTS2SELF) { - tcb_desc->bCTSEnable = true; + tcb_desc->cts_enable = true; tcb_desc->rts_rate = MGN_24M; - tcb_desc->bRTSEnable = true; + tcb_desc->rts_enable = true; break; } else if (ht_info->iot_action & (HT_IOT_ACT_FORCED_RTS | HT_IOT_ACT_PURE_N_MODE)) { - tcb_desc->bRTSEnable = true; + tcb_desc->rts_enable = true; tcb_desc->rts_rate = MGN_24M; break; } if (ieee->current_network.buseprotection) { - tcb_desc->bRTSEnable = true; - tcb_desc->bCTSEnable = true; + tcb_desc->rts_enable = true; + tcb_desc->cts_enable = true; tcb_desc->rts_rate = MGN_24M; break; } if (ht_info->current_ht_support && ht_info->enable_ht) { - u8 HTOpMode = ht_info->current_op_mode; + u8 ht_op_mode = ht_info->current_op_mode; - if ((ht_info->cur_bw_40mhz && (HTOpMode == 2 || - HTOpMode == 3)) || - (!ht_info->cur_bw_40mhz && HTOpMode == 3)) { + if ((ht_info->cur_bw_40mhz && (ht_op_mode == 2 || + ht_op_mode == 3)) || + (!ht_info->cur_bw_40mhz && ht_op_mode == 3)) { tcb_desc->rts_rate = MGN_24M; - tcb_desc->bRTSEnable = true; + tcb_desc->rts_enable = true; break; } } if (skb->len > ieee->rts) { tcb_desc->rts_rate = MGN_24M; - tcb_desc->bRTSEnable = true; + tcb_desc->rts_enable = true; break; } if (tcb_desc->ampdu_enable) { tcb_desc->rts_rate = MGN_24M; - tcb_desc->bRTSEnable = false; + tcb_desc->rts_enable = false; break; } goto NO_PROTECTION; } if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - tcb_desc->bUseShortPreamble = true; + tcb_desc->use_short_preamble = true; return; NO_PROTECTION: - tcb_desc->bRTSEnable = false; - tcb_desc->bCTSEnable = false; + tcb_desc->rts_enable = false; + tcb_desc->cts_enable = false; tcb_desc->rts_rate = 0; tcb_desc->RTSSC = 0; - tcb_desc->bRTSBW = false; + tcb_desc->rts_bw = false; } static void rtllib_txrate_selectmode(struct rtllib_device *ieee, @@ -472,11 +472,11 @@ static u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb, if (is_multicast_ether_addr(dst)) return 0; - if (IsQoSDataFrame(skb->data)) { + if (is_qos_data_frame(skb->data)) { struct tx_ts_record *ts = NULL; if (!rtllib_get_ts(ieee, (struct ts_common_info **)(&ts), dst, - skb->priority, TX_DIR, true)) + skb->priority, TX_DIR, true)) return 0; seqnum = ts->tx_cur_seq; ts->tx_cur_seq = (ts->tx_cur_seq + 1) % 4096; @@ -510,8 +510,8 @@ static u8 rtllib_current_rate(struct rtllib_device *ieee) if (ieee->mode & IEEE_MODE_MASK) return ieee->rate; - if (ieee->HTCurrentOperaRate) - return ieee->HTCurrentOperaRate; + if (ieee->ht_curr_op_rate) + return ieee->ht_curr_op_rate; else return ieee->rate & 0x7F; } @@ -538,8 +538,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) u8 src[ETH_ALEN]; struct lib80211_crypt_data *crypt = NULL; struct cb_desc *tcb_desc; - u8 bIsMulticast = false; - u8 IsAmsdu = false; + u8 is_multicast = false; bool bdhcp = false; spin_lock_irqsave(&ieee->lock, flags); @@ -548,8 +547,8 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) * creating it... */ if (!(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) || - ((!ieee->softmac_data_hard_start_xmit && - (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { + ((!ieee->softmac_data_hard_start_xmit && + (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { netdev_warn(ieee->dev, "No xmit handler.\n"); goto success; } @@ -607,7 +606,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) } } - skb->priority = rtllib_classify(skb, IsAmsdu); + skb->priority = rtllib_classify(skb); crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && crypt && crypt->ops; if (!encrypt && ieee->ieee802_1x && @@ -648,21 +647,17 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) ether_addr_copy(header.addr1, ieee->current_network.bssid); ether_addr_copy(header.addr2, src); - if (IsAmsdu) - ether_addr_copy(header.addr3, - ieee->current_network.bssid); - else - ether_addr_copy(header.addr3, dest); + ether_addr_copy(header.addr3, dest); } - bIsMulticast = is_multicast_ether_addr(header.addr1); + is_multicast = is_multicast_ether_addr(header.addr1); header.frame_control = cpu_to_le16(fc); /* Determine fragmentation size based on destination (multicast * and broadcast are not fragmented) */ - if (bIsMulticast) { + if (is_multicast) { frag_size = MAX_FRAG_THRESHOLD; qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; } else { @@ -751,14 +746,14 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) if (encrypt) { if (ieee->hwsec_active) - tcb_desc->bHwSec = 1; + tcb_desc->hw_sec = 1; else - tcb_desc->bHwSec = 0; + tcb_desc->hw_sec = 0; skb_reserve(skb_frag, crypt->ops->extra_mpdu_prefix_len + crypt->ops->extra_msdu_prefix_len); } else { - tcb_desc->bHwSec = 0; + tcb_desc->hw_sec = 0; } frag_hdr = skb_put_data(skb_frag, &header, hdr_len); @@ -774,7 +769,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) /* The last fragment has the remaining length */ bytes = bytes_last_frag; } - if ((qos_activated) && (!bIsMulticast)) { + if ((qos_activated) && (!is_multicast)) { frag_hdr->seq_ctrl = cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag, header.addr1)); @@ -809,7 +804,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) skb_put(skb_frag, 4); } - if ((qos_activated) && (!bIsMulticast)) { + if ((qos_activated) && (!is_multicast)) { if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; else @@ -845,9 +840,9 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) if (is_multicast_ether_addr(header.addr1)) tcb_desc->multicast = 1; if (is_broadcast_ether_addr(header.addr1)) - tcb_desc->bBroadcast = 1; + tcb_desc->broadcast = 1; rtllib_txrate_selectmode(ieee, tcb_desc); - if (tcb_desc->multicast || tcb_desc->bBroadcast) + if (tcb_desc->multicast || tcb_desc->broadcast) tcb_desc->data_rate = ieee->basic_rate; else tcb_desc->data_rate = rtllib_current_rate(ieee); @@ -868,11 +863,11 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) tcb_desc->bdhcp = 1; } - rtllib_query_ShortPreambleMode(ieee, tcb_desc); + rtllib_query_short_preamble_mode(ieee, tcb_desc); rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); - rtllib_query_HTCapShortGI(ieee, tcb_desc); - rtllib_query_BandwidthMode(ieee, tcb_desc); + rtllib_query_ht_cap_short_gi(ieee, tcb_desc); + rtllib_query_bandwidth_mode(ieee, tcb_desc); rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); } diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index d7d678b04ca8..12f2fdb1b3cb 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -247,7 +247,7 @@ void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) { struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; - /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/ + /* Fill up TxCmd Descriptor according as USB FW Tx Aggregation info.*/ /* dw0 */ ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff); ptx_desc->txdw0 |= diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h index 759a2d27d8f2..0cc780cf4341 100644 --- a/drivers/staging/rtl8712/rtl871x_event.h +++ b/drivers/staging/rtl8712/rtl871x_event.h @@ -37,7 +37,7 @@ struct surveydone_event { }; /* - * Used to report the link result of joinning the given bss + * Used to report the link result of joining the given bss * join_res: * -1: authentication fail * -2: association fail diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h index c5b12f74ebf8..f09d50a29b82 100644 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ b/drivers/staging/rtl8712/rtl871x_io.h @@ -62,7 +62,7 @@ #define IO_WR_BURST(x) (IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | \ ((x) & _IOSZ_MASK_)) #define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_)) -/*below is for the intf_option bit defition...*/ +/*below is for the intf_option bit definition...*/ #define _INTF_ASYNC_ BIT(0) /*support async io*/ struct intf_priv; struct intf_hdl; diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index fccfa0915a02..70c295e97068 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -944,7 +944,7 @@ void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf) /* When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send * the ADDBA req frame with start seq control = 0 to wifi client after - * the WPA handshake and the seqence number of following data packet + * the WPA handshake and the sequence number of following data packet * will be 0. In this case, the Rx reorder sequence is not longer than 0 * and the WiFi client will drop the data with seq number 0. * So, the 8712 firmware has to inform driver with receiving the diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 6353dbe554d3..408616e9afcf 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -117,12 +117,9 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, /*init xmit_buf*/ _init_queue(&pxmitpriv->free_xmitbuf_queue); _init_queue(&pxmitpriv->pending_xmitbuf_queue); - pxmitpriv->pallocated_xmitbuf = - kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4, GFP_ATOMIC); - if (!pxmitpriv->pallocated_xmitbuf) + pxmitpriv->pxmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf), GFP_ATOMIC); + if (!pxmitpriv->pxmitbuf) goto clean_up_frame_buf; - pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - - ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3); pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; for (i = 0; i < NR_XMITBUFF; i++) { INIT_LIST_HEAD(&pxmitbuf->list); @@ -165,8 +162,8 @@ clean_up_alloc_buf: for (k = 0; k < 8; k++) /* delete xmit urb's */ usb_free_urb(pxmitbuf->pxmit_urb[k]); } - kfree(pxmitpriv->pallocated_xmitbuf); - pxmitpriv->pallocated_xmitbuf = NULL; + kfree(pxmitpriv->pxmitbuf); + pxmitpriv->pxmitbuf = NULL; clean_up_frame_buf: kfree(pxmitpriv->pallocated_frame_buf); pxmitpriv->pallocated_frame_buf = NULL; @@ -193,7 +190,7 @@ void _free_xmit_priv(struct xmit_priv *pxmitpriv) pxmitbuf++; } kfree(pxmitpriv->pallocated_frame_buf); - kfree(pxmitpriv->pallocated_xmitbuf); + kfree(pxmitpriv->pxmitbuf); free_hwxmits(padapter); } diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index cdcbc87a3cad..784172c385e3 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -244,7 +244,6 @@ struct xmit_priv { int cmdseq; struct __queue free_xmitbuf_queue; struct __queue pending_xmitbuf_queue; - u8 *pallocated_xmitbuf; u8 *pxmitbuf; uint free_xmitbuf_cnt; }; diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index b2181e1e2d38..0a3451cdc8a1 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -26,13 +26,6 @@ #define RTL871X_VENQT_READ 0xc0 #define RTL871X_VENQT_WRITE 0x40 -struct zero_bulkout_context { - void *pbuf; - void *purb; - void *pirp; - void *padapter; -}; - uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv) { pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/drivers/staging/rtl8723bs/hal/Hal8723BReg.h b/drivers/staging/rtl8723bs/hal/Hal8723BReg.h index 6bf7933cbe4a..0b327a70aa15 100644 --- a/drivers/staging/rtl8723bs/hal/Hal8723BReg.h +++ b/drivers/staging/rtl8723bs/hal/Hal8723BReg.h @@ -19,420 +19,47 @@ #ifndef __INC_HAL8723BREG_H #define __INC_HAL8723BREG_H -/* */ -/* */ -/* */ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ -#define REG_SYS_ISO_CTRL_8723B 0x0000 /* 2 Byte */ -#define REG_SYS_FUNC_EN_8723B 0x0002 /* 2 Byte */ -#define REG_APS_FSMCO_8723B 0x0004 /* 4 Byte */ -#define REG_SYS_CLKR_8723B 0x0008 /* 2 Byte */ -#define REG_9346CR_8723B 0x000A /* 2 Byte */ -#define REG_EE_VPD_8723B 0x000C /* 2 Byte */ -#define REG_AFE_MISC_8723B 0x0010 /* 1 Byte */ -#define REG_SPS0_CTRL_8723B 0x0011 /* 7 Byte */ -#define REG_SPS_OCP_CFG_8723B 0x0018 /* 4 Byte */ -#define REG_RSV_CTRL_8723B 0x001C /* 3 Byte */ -#define REG_RF_CTRL_8723B 0x001F /* 1 Byte */ -#define REG_LPLDO_CTRL_8723B 0x0023 /* 1 Byte */ -#define REG_AFE_XTAL_CTRL_8723B 0x0024 /* 4 Byte */ -#define REG_AFE_PLL_CTRL_8723B 0x0028 /* 4 Byte */ -#define REG_MAC_PLL_CTRL_EXT_8723B 0x002c /* 4 Byte */ -#define REG_EFUSE_CTRL_8723B 0x0030 -#define REG_EFUSE_TEST_8723B 0x0034 -#define REG_PWR_DATA_8723B 0x0038 -#define REG_CAL_TIMER_8723B 0x003C -#define REG_ACLK_MON_8723B 0x003E -#define REG_GPIO_MUXCFG_8723B 0x0040 -#define REG_GPIO_IO_SEL_8723B 0x0042 -#define REG_MAC_PINMUX_CFG_8723B 0x0043 -#define REG_GPIO_PIN_CTRL_8723B 0x0044 -#define REG_GPIO_INTM_8723B 0x0048 -#define REG_LEDCFG0_8723B 0x004C -#define REG_LEDCFG1_8723B 0x004D -#define REG_LEDCFG2_8723B 0x004E -#define REG_LEDCFG3_8723B 0x004F -#define REG_FSIMR_8723B 0x0050 -#define REG_FSISR_8723B 0x0054 -#define REG_HSIMR_8723B 0x0058 -#define REG_HSISR_8723B 0x005c -#define REG_GPIO_EXT_CTRL 0x0060 -#define REG_MULTI_FUNC_CTRL_8723B 0x0068 -#define REG_GPIO_STATUS_8723B 0x006C -#define REG_SDIO_CTRL_8723B 0x0070 -#define REG_OPT_CTRL_8723B 0x0074 -#define REG_AFE_XTAL_CTRL_EXT_8723B 0x0078 -#define REG_MCUFWDL_8723B 0x0080 -#define REG_BT_PATCH_STATUS_8723B 0x0088 -#define REG_HIMR0_8723B 0x00B0 -#define REG_HISR0_8723B 0x00B4 -#define REG_HIMR1_8723B 0x00B8 -#define REG_HISR1_8723B 0x00BC -#define REG_PMC_DBG_CTRL2_8723B 0x00CC -#define REG_EFUSE_BURN_GNT_8723B 0x00CF -#define REG_HPON_FSM_8723B 0x00EC -#define REG_SYS_CFG_8723B 0x00F0 -#define REG_SYS_CFG1_8723B 0x00FC -#define REG_ROM_VERSION 0x00FD - /* */ /* */ /* 0x0100h ~ 0x01FFh MACTOP General Configuration */ /* */ /* */ -#define REG_CR_8723B 0x0100 -#define REG_PBP_8723B 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL_8723B 0x0106 -#define REG_TRXDMA_CTRL_8723B 0x010C -#define REG_TRXFF_BNDY_8723B 0x0114 -#define REG_TRXFF_STATUS_8723B 0x0118 -#define REG_RXFF_PTR_8723B 0x011C -#define REG_CPWM_8723B 0x012F -#define REG_FWIMR_8723B 0x0130 -#define REG_FWISR_8723B 0x0134 -#define REG_FTIMR_8723B 0x0138 -#define REG_PKTBUF_DBG_CTRL_8723B 0x0140 -#define REG_RXPKTBUF_CTRL_8723B 0x0142 -#define REG_PKTBUF_DBG_DATA_L_8723B 0x0144 -#define REG_PKTBUF_DBG_DATA_H_8723B 0x0148 - -#define REG_TC0_CTRL_8723B 0x0150 -#define REG_TC1_CTRL_8723B 0x0154 -#define REG_TC2_CTRL_8723B 0x0158 -#define REG_TC3_CTRL_8723B 0x015C -#define REG_TC4_CTRL_8723B 0x0160 -#define REG_TCUNIT_BASE_8723B 0x0164 -#define REG_RSVD3_8723B 0x0168 -#define REG_C2HEVT_MSG_NORMAL_8723B 0x01A0 #define REG_C2HEVT_CMD_SEQ_88XX 0x01A1 -#define REG_C2HEVT_CMD_CONTENT_88XX 0x01A2 #define REG_C2HEVT_CMD_LEN_88XX 0x01AE -#define REG_C2HEVT_CLEAR_8723B 0x01AF -#define REG_MCUTST_1_8723B 0x01C0 -#define REG_MCUTST_WOWLAN_8723B 0x01C7 -#define REG_FMETHR_8723B 0x01C8 -#define REG_HMETFR_8723B 0x01CC -#define REG_HMEBOX_0_8723B 0x01D0 -#define REG_HMEBOX_1_8723B 0x01D4 -#define REG_HMEBOX_2_8723B 0x01D8 -#define REG_HMEBOX_3_8723B 0x01DC -#define REG_LLT_INIT_8723B 0x01E0 -#define REG_HMEBOX_EXT0_8723B 0x01F0 -#define REG_HMEBOX_EXT1_8723B 0x01F4 -#define REG_HMEBOX_EXT2_8723B 0x01F8 -#define REG_HMEBOX_EXT3_8723B 0x01FC /* */ /* */ /* 0x0200h ~ 0x027Fh TXDMA Configuration */ /* */ /* */ -#define REG_RQPN_8723B 0x0200 -#define REG_FIFOPAGE_8723B 0x0204 -#define REG_DWBCN0_CTRL_8723B REG_TDECTRL -#define REG_TXDMA_OFFSET_CHK_8723B 0x020C -#define REG_TXDMA_STATUS_8723B 0x0210 -#define REG_RQPN_NPQ_8723B 0x0214 #define REG_DWBCN1_CTRL_8723B 0x0228 -/* */ -/* */ -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -/* */ -/* */ -#define REG_RXDMA_AGG_PG_TH_8723B 0x0280 -#define REG_FW_UPD_RDPTR_8723B 0x0284 /* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */ -#define REG_RXDMA_CONTROL_8723B 0x0286 /* Control the RX DMA. */ -#define REG_RXPKT_NUM_8723B 0x0287 /* The number of packets in RXPKTBUF. */ -#define REG_RXDMA_STATUS_8723B 0x0288 -#define REG_RXDMA_PRO_8723B 0x0290 -#define REG_EARLY_MODE_CONTROL_8723B 0x02BC -#define REG_RSVD5_8723B 0x02F0 -#define REG_RSVD6_8723B 0x02F4 - -/* */ -/* */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* */ -/* */ -#define REG_PCIE_CTRL_REG_8723B 0x0300 -#define REG_INT_MIG_8723B 0x0304 /* Interrupt Migration */ -#define REG_BCNQ_DESA_8723B 0x0308 /* TX Beacon Descriptor Address */ -#define REG_HQ_DESA_8723B 0x0310 /* TX High Queue Descriptor Address */ -#define REG_MGQ_DESA_8723B 0x0318 /* TX Manage Queue Descriptor Address */ -#define REG_VOQ_DESA_8723B 0x0320 /* TX VO Queue Descriptor Address */ -#define REG_VIQ_DESA_8723B 0x0328 /* TX VI Queue Descriptor Address */ -#define REG_BEQ_DESA_8723B 0x0330 /* TX BE Queue Descriptor Address */ -#define REG_BKQ_DESA_8723B 0x0338 /* TX BK Queue Descriptor Address */ -#define REG_RX_DESA_8723B 0x0340 /* RX Queue Descriptor Address */ -#define REG_DBI_WDATA_8723B 0x0348 /* DBI Write Data */ -#define REG_DBI_RDATA_8723B 0x034C /* DBI Read Data */ -#define REG_DBI_ADDR_8723B 0x0350 /* DBI Address */ -#define REG_DBI_FLAG_8723B 0x0352 /* DBI Read/Write Flag */ -#define REG_MDIO_WDATA_8723B 0x0354 /* MDIO for Write PCIE PHY */ -#define REG_MDIO_RDATA_8723B 0x0356 /* MDIO for Reads PCIE PHY */ -#define REG_MDIO_CTL_8723B 0x0358 /* MDIO for Control */ -#define REG_DBG_SEL_8723B 0x0360 /* Debug Selection Register */ -#define REG_PCIE_HRPWM_8723B 0x0361 /* PCIe RPWM */ -#define REG_PCIE_HCPWM_8723B 0x0363 /* PCIe CPWM */ -#define REG_PCIE_MULTIFET_CTRL_8723B 0x036A /* PCIE Multi-Fethc Control */ - /* spec version 11 */ /* */ /* */ /* 0x0400h ~ 0x047Fh Protocol Configuration */ /* */ /* */ -#define REG_VOQ_INFORMATION_8723B 0x0400 -#define REG_VIQ_INFORMATION_8723B 0x0404 -#define REG_BEQ_INFORMATION_8723B 0x0408 -#define REG_BKQ_INFORMATION_8723B 0x040C -#define REG_MGQ_INFORMATION_8723B 0x0410 -#define REG_HGQ_INFORMATION_8723B 0x0414 -#define REG_BCNQ_INFORMATION_8723B 0x0418 -#define REG_TXPKT_EMPTY_8723B 0x041A - #define REG_FWHW_TXQ_CTRL_8723B 0x0420 -#define REG_HWSEQ_CTRL_8723B 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY_8723B 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY_8723B 0x0425 -#define REG_LIFECTRL_CTRL_8723B 0x0426 -#define REG_MULTI_BCNQ_OFFSET_8723B 0x0427 -#define REG_SPEC_SIFS_8723B 0x0428 -#define REG_RL_8723B 0x042A -#define REG_TXBF_CTRL_8723B 0x042C -#define REG_DARFRC_8723B 0x0430 -#define REG_RARFRC_8723B 0x0438 -#define REG_RRSR_8723B 0x0440 #define REG_ARFR0_8723B 0x0444 #define REG_ARFR1_8723B 0x044C #define REG_CCK_CHECK_8723B 0x0454 #define REG_AMPDU_MAX_TIME_8723B 0x0456 -#define REG_TXPKTBUF_BCNQ_BDNY1_8723B 0x0457 #define REG_AMPDU_MAX_LENGTH_8723B 0x0458 -#define REG_TXPKTBUF_WMAC_LBK_BF_HD_8723B 0x045D -#define REG_NDPA_OPT_CTRL_8723B 0x045F -#define REG_FAST_EDCA_CTRL_8723B 0x0460 -#define REG_RD_RESP_PKT_TH_8723B 0x0463 #define REG_DATA_SC_8723B 0x0483 -#define REG_TXRPT_START_OFFSET 0x04AC -#define REG_POWER_STAGE1_8723B 0x04B4 -#define REG_POWER_STAGE2_8723B 0x04B8 -#define REG_AMPDU_BURST_MODE_8723B 0x04BC -#define REG_PKT_VO_VI_LIFE_TIME_8723B 0x04C0 -#define REG_PKT_BE_BK_LIFE_TIME_8723B 0x04C2 -#define REG_STBC_SETTING_8723B 0x04C4 -#define REG_HT_SINGLE_AMPDU_8723B 0x04C7 -#define REG_PROT_MODE_CTRL_8723B 0x04C8 #define REG_MAX_AGGR_NUM_8723B 0x04CA -#define REG_RTS_MAX_AGGR_NUM_8723B 0x04CB -#define REG_BAR_MODE_CTRL_8723B 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT_8723B 0x04CF -#define REG_MACID_PKT_DROP0_8723B 0x04D0 -#define REG_MACID_PKT_SLEEP_8723B 0x04D4 /* */ /* */ /* 0x0500h ~ 0x05FFh EDCA Configuration */ /* */ /* */ -#define REG_EDCA_VO_PARAM_8723B 0x0500 -#define REG_EDCA_VI_PARAM_8723B 0x0504 -#define REG_EDCA_BE_PARAM_8723B 0x0508 -#define REG_EDCA_BK_PARAM_8723B 0x050C -#define REG_BCNTCFG_8723B 0x0510 #define REG_PIFS_8723B 0x0512 -#define REG_RDG_PIFS_8723B 0x0513 -#define REG_SIFS_CTX_8723B 0x0514 -#define REG_SIFS_TRX_8723B 0x0516 -#define REG_AGGR_BREAK_TIME_8723B 0x051A -#define REG_SLOT_8723B 0x051B -#define REG_TX_PTCL_CTRL_8723B 0x0520 -#define REG_TXPAUSE_8723B 0x0522 -#define REG_DIS_TXREQ_CLR_8723B 0x0523 -#define REG_RD_CTRL_8723B 0x0524 -/* */ -/* Format for offset 540h-542h: */ -/* [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting beacon content before TBTT. */ -/* [7:4]: Reserved. */ -/* [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding to send the beacon packet. */ -/* [23:20]: Reserved */ -/* Description: */ -/* | */ -/* |<--Setup--|--Hold------------>| */ -/* --------------|---------------------- */ -/* | */ -/* TBTT */ -/* Note: We cannot update beacon content to HW or send any AC packets during the time between Setup and Hold. */ -/* Described by Designer Tim and Bruce, 2011-01-14. */ -/* */ -#define REG_TBTT_PROHIBIT_8723B 0x0540 -#define REG_RD_NAV_NXT_8723B 0x0544 -#define REG_NAV_PROT_LEN_8723B 0x0546 -#define REG_BCN_CTRL_8723B 0x0550 -#define REG_BCN_CTRL_1_8723B 0x0551 -#define REG_MBID_NUM_8723B 0x0552 -#define REG_DUAL_TSF_RST_8723B 0x0553 -#define REG_BCN_INTERVAL_8723B 0x0554 -#define REG_DRVERLYINT_8723B 0x0558 -#define REG_BCNDMATIM_8723B 0x0559 -#define REG_ATIMWND_8723B 0x055A -#define REG_USTIME_TSF_8723B 0x055C -#define REG_BCN_MAX_ERR_8723B 0x055D -#define REG_RXTSF_OFFSET_CCK_8723B 0x055E -#define REG_RXTSF_OFFSET_OFDM_8723B 0x055F -#define REG_TSFTR_8723B 0x0560 -#define REG_CTWND_8723B 0x0572 -#define REG_SECONDARY_CCA_CTRL_8723B 0x0577 -#define REG_PSTIMER_8723B 0x0580 -#define REG_TIMER0_8723B 0x0584 -#define REG_TIMER1_8723B 0x0588 -#define REG_ACMHWCTRL_8723B 0x05C0 -#define REG_SCH_TXCMD_8723B 0x05F8 /* 0x0600h ~ 0x07FFh WMAC Configuration */ -#define REG_MAC_CR_8723B 0x0600 -#define REG_TCR_8723B 0x0604 -#define REG_RCR_8723B 0x0608 #define REG_RX_PKT_LIMIT_8723B 0x060C -#define REG_RX_DLK_TIME_8723B 0x060D -#define REG_RX_DRVINFO_SZ_8723B 0x060F -#define REG_MACID_8723B 0x0610 -#define REG_BSSID_8723B 0x0618 -#define REG_MAR_8723B 0x0620 -#define REG_MBIDCAMCFG_8723B 0x0628 - -#define REG_USTIME_EDCA_8723B 0x0638 -#define REG_MAC_SPEC_SIFS_8723B 0x063A -#define REG_RESP_SIFP_CCK_8723B 0x063C -#define REG_RESP_SIFS_OFDM_8723B 0x063E -#define REG_ACKTO_8723B 0x0640 -#define REG_CTS2TO_8723B 0x0641 -#define REG_EIFS_8723B 0x0642 - -#define REG_NAV_UPPER_8723B 0x0652 /* unit of 128 */ #define REG_TRXPTCL_CTL_8723B 0x0668 -/* Security */ -#define REG_CAMCMD_8723B 0x0670 -#define REG_CAMWRITE_8723B 0x0674 -#define REG_CAMREAD_8723B 0x0678 -#define REG_CAMDBG_8723B 0x067C -#define REG_SECCFG_8723B 0x0680 - -/* Power */ -#define REG_WOW_CTRL_8723B 0x0690 -#define REG_PS_RX_INFO_8723B 0x0692 -#define REG_UAPSD_TID_8723B 0x0693 -#define REG_WKFMCAM_CMD_8723B 0x0698 -#define REG_WKFMCAM_NUM_8723B 0x0698 -#define REG_WKFMCAM_RWD_8723B 0x069C -#define REG_RXFLTMAP0_8723B 0x06A0 -#define REG_RXFLTMAP1_8723B 0x06A2 -#define REG_RXFLTMAP2_8723B 0x06A4 -#define REG_BCN_PSR_RPT_8723B 0x06A8 -#define REG_BT_COEX_TABLE_8723B 0x06C0 -#define REG_BFMER0_INFO_8723B 0x06E4 -#define REG_BFMER1_INFO_8723B 0x06EC -#define REG_CSI_RPT_PARAM_BW20_8723B 0x06F4 -#define REG_CSI_RPT_PARAM_BW40_8723B 0x06F8 -#define REG_CSI_RPT_PARAM_BW80_8723B 0x06FC - -/* Hardware Port 2 */ -#define REG_MACID1_8723B 0x0700 -#define REG_BSSID1_8723B 0x0708 -#define REG_BFMEE_SEL_8723B 0x0714 -#define REG_SND_PTCL_CTRL_8723B 0x0718 - -/* Redifine 8192C register definition for compatibility */ - -/* TODO: use these definition when using REG_xxx naming rule. */ -/* NOTE: DO NOT Remove these definition. Use later. */ -#define EFUSE_CTRL_8723B REG_EFUSE_CTRL_8723B /* E-Fuse Control. */ -#define EFUSE_TEST_8723B REG_EFUSE_TEST_8723B /* E-Fuse Test. */ -#define MSR_8723B (REG_CR_8723B + 2) /* Media Status register */ -#define ISR_8723B REG_HISR0_8723B -#define TSFR_8723B REG_TSFTR_8723B /* Timing Sync Function Timer Register. */ - -#define PBP_8723B REG_PBP_8723B - -/* Redifine MACID register, to compatible prior ICs. */ -#define IDR0_8723B REG_MACID_8723B /* MAC ID Register, Offset 0x0050-0x0053 */ -#define IDR4_8723B (REG_MACID_8723B + 4) /* MAC ID Register, Offset 0x0054-0x0055 */ - -/* 9. Security Control Registers (Offset:) */ -#define RWCAM_8723B REG_CAMCMD_8723B /* IN 8190 Data Sheet is called CAMcmd */ -#define WCAMI_8723B REG_CAMWRITE_8723B /* Software write CAM input content */ -#define RCAMO_8723B REG_CAMREAD_8723B /* Software read/write CAM config */ -#define CAMDBG_8723B REG_CAMDBG_8723B -#define SECR_8723B REG_SECCFG_8723B /* Security Configuration Register */ - -/* 8195 IMR/ISR bits (offset 0xB0, 8bits) */ -#define IMR_DISABLED_8723B 0 -/* IMR DW0(0x00B0-00B3) Bit 0-31 */ -#define IMR_TIMER2_8723B BIT31 /* Timeout interrupt 2 */ -#define IMR_TIMER1_8723B BIT30 /* Timeout interrupt 1 */ -#define IMR_PSTIMEOUT_8723B BIT29 /* Power Save Time Out Interrupt */ -#define IMR_GTINT4_8723B BIT28 /* When GTIMER4 expires, this bit is set to 1 */ -#define IMR_GTINT3_8723B BIT27 /* When GTIMER3 expires, this bit is set to 1 */ -#define IMR_TXBCN0ERR_8723B BIT26 /* Transmit Beacon0 Error */ -#define IMR_TXBCN0OK_8723B BIT25 /* Transmit Beacon0 OK */ -#define IMR_TSF_BIT32_TOGGLE_8723B BIT24 /* TSF Timer BIT32 toggle indication interrupt */ -#define IMR_BCNDMAINT0_8723B BIT20 /* Beacon DMA Interrupt 0 */ -#define IMR_BCNDERR0_8723B BIT16 /* Beacon Queue DMA OK0 */ -#define IMR_HSISR_IND_ON_INT_8723B BIT15 /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */ -#define IMR_BCNDMAINT_E_8723B BIT14 /* Beacon DMA Interrupt Extension for Win7 */ -#define IMR_ATIMEND_8723B BIT12 /* CTWidnow End or ATIM Window End */ -#define IMR_C2HCMD_8723B BIT10 /* CPU to Host Command INT Status, Write 1 clear */ -#define IMR_CPWM2_8723B BIT9 /* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_CPWM_8723B BIT8 /* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_HIGHDOK_8723B BIT7 /* High Queue DMA OK */ -#define IMR_MGNTDOK_8723B BIT6 /* Management Queue DMA OK */ -#define IMR_BKDOK_8723B BIT5 /* AC_BK DMA OK */ -#define IMR_BEDOK_8723B BIT4 /* AC_BE DMA OK */ -#define IMR_VIDOK_8723B BIT3 /* AC_VI DMA OK */ -#define IMR_VODOK_8723B BIT2 /* AC_VO DMA OK */ -#define IMR_RDU_8723B BIT1 /* Rx Descriptor Unavailable */ -#define IMR_ROK_8723B BIT0 /* Receive DMA OK */ - -/* IMR DW1(0x00B4-00B7) Bit 0-31 */ -#define IMR_BCNDMAINT7_8723B BIT27 /* Beacon DMA Interrupt 7 */ -#define IMR_BCNDMAINT6_8723B BIT26 /* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT5_8723B BIT25 /* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT4_8723B BIT24 /* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT3_8723B BIT23 /* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT2_8723B BIT22 /* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT1_8723B BIT21 /* Beacon DMA Interrupt 1 */ -#define IMR_BCNDOK7_8723B BIT20 /* Beacon Queue DMA OK Interrupt 7 */ -#define IMR_BCNDOK6_8723B BIT19 /* Beacon Queue DMA OK Interrupt 6 */ -#define IMR_BCNDOK5_8723B BIT18 /* Beacon Queue DMA OK Interrupt 5 */ -#define IMR_BCNDOK4_8723B BIT17 /* Beacon Queue DMA OK Interrupt 4 */ -#define IMR_BCNDOK3_8723B BIT16 /* Beacon Queue DMA OK Interrupt 3 */ -#define IMR_BCNDOK2_8723B BIT15 /* Beacon Queue DMA OK Interrupt 2 */ -#define IMR_BCNDOK1_8723B BIT14 /* Beacon Queue DMA OK Interrupt 1 */ -#define IMR_ATIMEND_E_8723B BIT13 /* ATIM Window End Extension for Win7 */ -#define IMR_TXERR_8723B BIT11 /* Tx Error Flag Interrupt Status, write 1 clear. */ -#define IMR_RXERR_8723B BIT10 /* Rx Error Flag INT Status, Write 1 clear */ -#define IMR_TXFOVW_8723B BIT9 /* Transmit FIFO Overflow */ -#define IMR_RXFOVW_8723B BIT8 /* Receive FIFO Overflow */ - -/* 2 ACMHWCTRL 0x05C0 */ -#define ACMHW_HWEN_8723B BIT(0) -#define ACMHW_VOQEN_8723B BIT(1) -#define ACMHW_VIQEN_8723B BIT(2) -#define ACMHW_BEQEN_8723B BIT(3) -#define ACMHW_VOQSTATUS_8723B BIT(5) -#define ACMHW_VIQSTATUS_8723B BIT(6) -#define ACMHW_BEQSTATUS_8723B BIT(7) - -/* 8195 (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */ -#define RCR_TCPOFLD_EN BIT25 /* Enable TCP checksum offload */ - #endif /* #ifndef __INC_HAL8723BREG_H */ diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c index dd0f74b0cf0d..4da2487f6750 100644 --- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c +++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c @@ -70,13 +70,6 @@ static bool CheckPositive( return false; } -static bool CheckNegative( - struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2 -) -{ - return true; -} - /****************************************************************************** * AGC_TAB.TXT ******************************************************************************/ @@ -244,10 +237,7 @@ void ODM_ReadAndConfig_MP_8723B_AGC_TAB(struct dm_odm_t *pDM_Odm) READ_NEXT_PAIR(v1, v2, i); } else { READ_NEXT_PAIR(v1, v2, i); - if (!CheckNegative(pDM_Odm, v1, v2)) - bMatched = false; - else - bMatched = true; + bMatched = true; READ_NEXT_PAIR(v1, v2, i); } @@ -506,10 +496,7 @@ void ODM_ReadAndConfig_MP_8723B_PHY_REG(struct dm_odm_t *pDM_Odm) READ_NEXT_PAIR(v1, v2, i); } else { READ_NEXT_PAIR(v1, v2, i); - if (!CheckNegative(pDM_Odm, v1, v2)) - bMatched = false; - else - bMatched = true; + bMatched = true; READ_NEXT_PAIR(v1, v2, i); } diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c index 47e66f4ad9d1..1f0cc8d58df3 100644 --- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c +++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c @@ -68,13 +68,6 @@ static bool CheckPositive( return false; } -static bool CheckNegative( - struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2 -) -{ - return true; -} - /****************************************************************************** * MAC_REG.TXT ******************************************************************************/ @@ -214,10 +207,7 @@ void ODM_ReadAndConfig_MP_8723B_MAC_REG(struct dm_odm_t *pDM_Odm) READ_NEXT_PAIR(v1, v2, i); } else { READ_NEXT_PAIR(v1, v2, i); - if (!CheckNegative(pDM_Odm, v1, v2)) - bMatched = false; - else - bMatched = true; + bMatched = true; READ_NEXT_PAIR(v1, v2, i); } diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c index efc68c17b126..155ec311a52e 100644 --- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c +++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c @@ -78,13 +78,6 @@ static bool CheckPositive( return false; } -static bool CheckNegative( - struct dm_odm_t *pDM_Odm, const u32 Condition1, const u32 Condition2 -) -{ - return true; -} - /****************************************************************************** * RadioA.TXT ******************************************************************************/ @@ -245,10 +238,7 @@ void ODM_ReadAndConfig_MP_8723B_RadioA(struct dm_odm_t *pDM_Odm) READ_NEXT_PAIR(v1, v2, i); } else { READ_NEXT_PAIR(v1, v2, i); - if (!CheckNegative(pDM_Odm, v1, v2)) - bMatched = false; - else - bMatched = true; + bMatched = true; READ_NEXT_PAIR(v1, v2, i); } diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h index f5c804a1b9d5..010274ba8079 100644 --- a/drivers/staging/rtl8723bs/hal/odm.h +++ b/drivers/staging/rtl8723bs/hal/odm.h @@ -76,7 +76,7 @@ /* Remove DIG by Yuchen */ -/* Remoce BB power saving by Yuchn */ +/* Remove BB power saving by Yuchn */ /* Remove DIG by yuchen */ @@ -878,7 +878,7 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */ struct odm_mac_status_info *pMacInfo; /* MAC_INFO_88E MacInfo; */ - /* Different Team independt structure?? */ + /* Different Team independent structure?? */ /* */ /* TX_RTP_CMN TX_retrpo; */ diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index a59ae622f05e..d1ac2f44939c 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -700,7 +700,7 @@ void rtl8723b_download_rsvd_page(struct adapter *padapter, u8 mstatus) rtw_write8(padapter, REG_BCN_CTRL, val8); /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ + /* If exists, the original value of 0x422[6] will be 1, we should check this to */ /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ /* the beacon cannot be sent by HW. */ /* 2010.06.23. Added by tynli. */ @@ -964,7 +964,7 @@ void rtl8723b_download_BTCoex_AP_mode_rsvd_page(struct adapter *padapter) rtw_write8(padapter, REG_BCN_CTRL, val8); /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ + /* If exists, the original value of 0x422[6] will be 1, we should check this to */ /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ /* the beacon cannot be sent by HW. */ /* 2010.06.23. Added by tynli. */ diff --git a/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h b/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h index 586a3dabc5ca..f8cf2aee5157 100644 --- a/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h +++ b/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h @@ -46,59 +46,11 @@ /* 5. Other definition for BB/RF R/W */ /* */ - -/* */ -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 1. Page1(0x100) */ -/* */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* */ -/* 2. Page2(0x200) */ -/* */ -/* The following two definition are only used for USB interface. */ -#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB read/write command address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB read/write command data. */ - /* */ /* 3. Page8(0x800) */ /* */ #define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting?? */ -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 - -#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ - -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 - #define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ #define rFPGA0_XA_HSSIParameter2 0x824 #define rFPGA0_XB_HSSIParameter1 0x828 @@ -113,10 +65,6 @@ #define rFPGA0_XA_LSSIParameter 0x840 #define rFPGA0_XB_LSSIParameter 0x844 -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - -#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ #define rFPGA0_XCD_SwitchControl 0x85c #define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */ @@ -127,33 +75,17 @@ #define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Control */ #define rFPGA0_XCD_RFInterfaceSW 0x874 -#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 /* Useless now */ -#define rFPGA0_AnalogParameter4 0x88c - #define rFPGA0_XA_LSSIReadBack 0x8a0 /* Transceiver LSSI Readback */ #define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ #define TransceiverA_HSPI_Readback 0x8b8 /* Transceiver A HSPI Readback */ #define TransceiverB_HSPI_Readback 0x8bc /* Transceiver B HSPI Readback */ -#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now RF Interface Readback Value */ -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ /* */ /* 4. Page9(0x900) */ /* */ #define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC RF BW Setting?? */ -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now Status report?? */ #define rS0S1_PathSwitch 0x948 /* */ @@ -163,135 +95,39 @@ #define rCCK0_System 0xa00 #define rCCK0_AFESetting 0xa04 /* Disable init gain now Select RX path by RSSI */ -#define rCCK0_CCA 0xa08 /* Disable init gain now Init gain */ -#define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. Not the same as 90 series */ -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel estimation threshold */ -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f channel report */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ /* */ /* PageB(0xB00) */ /* */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rConfig_Pmpd_AntA 0xb28 #define rConfig_AntA 0xb68 #define rConfig_AntB 0xb6c -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rConfig_Pmpd_AntB 0xb98 -#define rAPK 0xbd8 /* */ /* 6. PageC(0xC00) */ /* */ -#define rOFDM0_LSTF 0xc00 - #define rOFDM0_TRxPathEnable 0xc04 #define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c -#define rOFDM0_XARxAFE 0xc10 /* RxIQ DC offset, Rx digital filter, DC notch filter */ #define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */ -#define rOFDM0_XBRxAFE 0xc18 #define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /* PD, BW & SBD DM tune init gain */ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */ #define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ #define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ -#define rOFDM0_XAAGCCore1 0xc50 /* DIG */ -#define rOFDM0_XAAGCCore2 0xc54 -#define rOFDM0_XBAGCCore1 0xc58 -#define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c - -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 #define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c #define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ -#define rOFDM0_XATxAFE 0xc84 #define rOFDM0_XBTxIQImbalance 0xc88 -#define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 #define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 #define rOFDM0_XDTxAFE 0xc9c #define rOFDM0_RxIQExtAnta 0xca0 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 -#define rOFDM0_RxHPParameter 0xce0 #define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 /* */ /* 7. PageD(0xD00) */ /* */ #define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ - -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - /* */ /* 8. PageE(0xE00) */ @@ -316,7 +152,6 @@ #define rRx_IQK_Tone_B 0xe54 #define rTx_IQK_PI_B 0xe58 #define rRx_IQK_PI_B 0xe5c -#define rIQK_AGC_Cont 0xe60 #define rBlue_Tooth 0xe6c #define rRx_Wait_CCA 0xe70 @@ -331,19 +166,9 @@ #define rTx_Power_Before_IQK_A 0xe94 #define rTx_Power_After_IQK_A 0xe9c -#define rRx_Power_Before_IQK_A 0xea0 #define rRx_Power_Before_IQK_A_2 0xea4 -#define rRx_Power_After_IQK_A 0xea8 #define rRx_Power_After_IQK_A_2 0xeac -#define rTx_Power_Before_IQK_B 0xeb4 -#define rTx_Power_After_IQK_B 0xebc - -#define rRx_Power_Before_IQK_B 0xec0 -#define rRx_Power_Before_IQK_B_2 0xec4 -#define rRx_Power_After_IQK_B 0xec8 -#define rRx_Power_After_IQK_B_2 0xecc - #define rRx_OFDM 0xed0 #define rRx_Wait_RIFS 0xed4 #define rRx_TO_Rx 0xed8 @@ -351,709 +176,43 @@ #define rSleep 0xee0 #define rPMPD_ANAEN 0xeec -/* */ -/* 7. RF Register 0x00-0x2E (RF 8256) */ -/* RF-0222D 0x00-3F */ -/* */ -/* Zebra1 */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ - -/* endif */ -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - /* */ /* RL6052 Register definition */ /* */ #define RF_AC 0x00 /* */ -#define RF_IQADJ_G1 0x01 /* */ -#define RF_IQADJ_G2 0x02 /* */ -#define RF_BS_PA_APSET_G1_G4 0x03 -#define RF_BS_PA_APSET_G5_G8 0x04 -#define RF_POW_TRSW 0x05 /* */ - -#define RF_GAIN_RX 0x06 /* */ -#define RF_GAIN_TX 0x07 /* */ - #define RF_TXM_IDAC 0x08 /* */ -#define RF_IPA_G 0x09 /* */ -#define RF_TXBIAS_G 0x0A -#define RF_TXPA_AG 0x0B -#define RF_IPA_A 0x0C /* */ -#define RF_TXBIAS_A 0x0D -#define RF_BS_PA_APSET_G9_G11 0x0E -#define RF_BS_IQGEN 0x0F /* */ -#define RF_MODE1 0x10 /* */ -#define RF_MODE2 0x11 /* */ - -#define RF_RX_AGC_HP 0x12 /* */ -#define RF_TX_AGC 0x13 /* */ -#define RF_BIAS 0x14 /* */ -#define RF_IPA 0x15 /* */ -#define RF_TXBIAS 0x16 /* */ -#define RF_POW_ABILITY 0x17 /* */ -#define RF_MODE_AG 0x18 /* */ -#define rRfChannel 0x18 /* RF channel and BW switch */ #define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 /* */ - -#define RF_RX_G1 0x1A /* */ -#define RF_RX_G2 0x1B /* */ - -#define RF_RX_BB2 0x1C /* */ -#define RF_RX_BB1 0x1D /* */ - -#define RF_RCK1 0x1E /* */ -#define RF_RCK2 0x1F /* */ - -#define RF_TX_G1 0x20 /* */ -#define RF_TX_G2 0x21 /* */ -#define RF_TX_G3 0x22 /* */ - -#define RF_TX_BB1 0x23 /* */ - -#define RF_T_METER 0x24 /* */ - -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ #define RF_RCK_OS 0x30 /* RF TX PA control */ #define RF_TXPA_G1 0x31 /* RF TX PA control */ #define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C /* */ -#define RF_TRSW 0x3F -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B -#define RF_0x52 0x52 #define RF_WE_LUT 0xEF -#define RF_S0S1 0xB0 - -/* */ -/* Bit Mask */ -/* */ -/* 1. Page1(0x100) */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 - -#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && (_Offset <= 0xfff)) /* 2. Page8(0x800) */ #define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 -#define bCCKEn 0x1000000 -#define bOFDMEn 0x2000000 - -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f - -#define bAntennaSelect 0x0300 - -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* chane gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 #define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ #define b3WireAddressLength 0x400 -#define b3WireRFPowerDown 0x1 /* Useless now */ -/* define bHWSISelect 0x8 */ -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf - #define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#define bRFSI_ANTSW 0x100 -#define bRFSI_ANTSWB 0x200 -#define bRFSI_PAPE 0x400 -#define bBandSelect 0x1 -#define bHTSIG2_GI 0x80 -#define bHTSIG2_Smoothing 0x01 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 - #define bLSSIReadAddress 0x7f800000 /* T65 RF */ #define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ #define bLSSIReadBackData 0xfffff /* T65 RF */ -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -#define bADClkPhase 0x4000000 /* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -#define bXtalCap01 0xc0000000 /* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 - -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and also HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - /* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - #define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 switch */ -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* the threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* the threshold for ant diversity */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -/* define bRxMF_Hold 0x3800 */ -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -/* define bRxPath1 0x01 */ -/* define bRxPath2 0x02 */ -/* define bRxPath3 0x04 */ -/* define bRxPath4 0x08 */ -/* define bTxPath1 0x10 */ -/* define bTxPath2 0x20 */ -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register */ -/* Zebra1 */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - - /* */ /* Other Definition */ /* */ -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - /* for PutRegsetting & GetRegSetting BitMask */ #define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ #define bMaskByte1 0xff00 @@ -1065,48 +224,9 @@ #define bMaskH3Bytes 0xffffff00 #define bMask12Bits 0xfff #define bMaskH4Bits 0xf0000000 -#define bMaskOFDM_D 0xffc00000 -#define bMaskCCK 0x3f3f3f3f - #define bEnable 0x1 /* Useless */ -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -/* define max debug item in each debug page */ -/* define bMaxItem_FPGA_PHY0 0x9 */ -/* define bMaxItem_FPGA_PHY1 0x3 */ -/* define bMaxItem_PHY_11B 0x16 */ -/* define bMaxItem_OFDM_PHY0 0x29 */ -/* define bMaxItem_OFDM_PHY1 0x0 */ - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/*--------------------------Define Parameters-------------------------------*/ +#define rDPDT_control 0x92c #endif /* __INC_HAL8192SPHYREG_H */ diff --git a/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h b/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h index e30071935d27..b81252d374ef 100644 --- a/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h +++ b/drivers/staging/rtl8723bs/include/HalPwrSeqCmd.h @@ -49,8 +49,6 @@ /*---------------------------------------------*/ /* define the base address of each block */ #define PWR_BASEADDR_MAC 0x00 -#define PWR_BASEADDR_USB 0x01 -#define PWR_BASEADDR_PCIE 0x02 #define PWR_BASEADDR_SDIO 0x03 /*---------------------------------------------*/ @@ -64,21 +62,12 @@ /*---------------------------------------------*/ /* 3 The value of fab_msk: 4 bits */ /*---------------------------------------------*/ -#define PWR_FAB_TSMC_MSK BIT(0) -#define PWR_FAB_UMC_MSK BIT(1) #define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) /*---------------------------------------------*/ /* 3 The value of cut_msk: 8 bits */ /*---------------------------------------------*/ #define PWR_CUT_TESTCHIP_MSK BIT(0) -#define PWR_CUT_A_MSK BIT(1) -#define PWR_CUT_B_MSK BIT(2) -#define PWR_CUT_C_MSK BIT(3) -#define PWR_CUT_D_MSK BIT(4) -#define PWR_CUT_E_MSK BIT(5) -#define PWR_CUT_F_MSK BIT(6) -#define PWR_CUT_G_MSK BIT(7) #define PWR_CUT_ALL_MSK 0xFF diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index ea6bb44c5e1d..9e6ca1dec525 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -490,7 +490,6 @@ static inline u8 *myid(struct eeprom_priv *peepriv) } /* HCI Related header file */ -#include #include #include diff --git a/drivers/staging/rtl8723bs/include/hal_com_h2c.h b/drivers/staging/rtl8723bs/include/hal_com_h2c.h index 24cd9415fa95..a59d13090565 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_h2c.h +++ b/drivers/staging/rtl8723bs/include/hal_com_h2c.h @@ -9,86 +9,10 @@ #define H2C_RSVDPAGE_LOC_LEN 5 #define H2C_MEDIA_STATUS_RPT_LEN 3 -#define H2C_KEEP_ALIVE_CTRL_LEN 2 -#define H2C_DISCON_DECISION_LEN 3 -#define H2C_AP_OFFLOAD_LEN 3 -#define H2C_AP_WOW_GPIO_CTRL_LEN 4 -#define H2C_AP_PS_LEN 2 #define H2C_PWRMODE_LEN 7 #define H2C_PSTUNEPARAM_LEN 4 #define H2C_MACID_CFG_LEN 7 -#define H2C_BTMP_OPER_LEN 4 -#define H2C_WOWLAN_LEN 4 -#define H2C_REMOTE_WAKE_CTRL_LEN 3 -#define H2C_AOAC_GLOBAL_INFO_LEN 2 -#define H2C_AOAC_RSVDPAGE_LOC_LEN 7 -#define H2C_SCAN_OFFLOAD_CTRL_LEN 4 -#define H2C_BT_FW_PATCH_LEN 6 #define H2C_RSSI_SETTING_LEN 4 -#define H2C_AP_REQ_TXRPT_LEN 2 -#define H2C_FORCE_BT_TXPWR_LEN 3 -#define H2C_BCN_RSVDPAGE_LEN 5 -#define H2C_PROBERSP_RSVDPAGE_LEN 5 - -/* _RSVDPAGE_LOC_CMD_0x00 */ -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd, 0, 8, __Value) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+1, 0, 8, __Value) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+2, 0, 8, __Value) -#define SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+3, 0, 8, __Value) -#define SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(__pH2CCmd, __Value)SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+4, 0, 8, __Value) - -/* _MEDIA_STATUS_RPT_PARM_CMD_0x01 */ -#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 1, __Value) -#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 1, __Value) -#define SET_H2CCMD_MSRRPT_PARM_MACID(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd+1, 0, 8, __Value) -#define SET_H2CCMD_MSRRPT_PARM_MACID_END(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd+2, 0, 8, __Value) - -/* _KEEP_ALIVE_CMD_0x03 */ -#define SET_H2CCMD_KEEPALIVE_PARM_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 1, __Value) -#define SET_H2CCMD_KEEPALIVE_PARM_ADOPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 1, __Value) -#define SET_H2CCMD_KEEPALIVE_PARM_PKT_TYPE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 2, 1, __Value) -#define SET_H2CCMD_KEEPALIVE_PARM_CHECK_PERIOD(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd+1, 0, 8, __Value) - -/* _DISCONNECT_DECISION_CMD_0x04 */ -#define SET_H2CCMD_DISCONDECISION_PARM_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 1, __Value) -#define SET_H2CCMD_DISCONDECISION_PARM_ADOPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 1, __Value) -#define SET_H2CCMD_DISCONDECISION_PARM_CHECK_PERIOD(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd+1, 0, 8, __Value) -#define SET_H2CCMD_DISCONDECISION_PARM_TRY_PKT_NUM(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd+2, 0, 8, __Value) - -/* _WoWLAN PARAM_CMD_0x80 */ -#define SET_H2CCMD_WOWLAN_FUNC_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 1, __Value) -#define SET_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 1, __Value) -#define SET_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 2, 1, __Value) -#define SET_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 3, 1, __Value) -#define SET_H2CCMD_WOWLAN_ALL_PKT_DROP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 4, 1, __Value) -#define SET_H2CCMD_WOWLAN_GPIO_ACTIVE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 5, 1, __Value) -#define SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 6, 1, __Value) -#define SET_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 7, 1, __Value) -#define SET_H2CCMD_WOWLAN_GPIONUM(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE((__pH2CCmd)+1, 0, 7, __Value) -#define SET_H2CCMD_WOWLAN_DATAPIN_WAKE_UP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE((__pH2CCmd)+1, 7, 1, __Value) -#define SET_H2CCMD_WOWLAN_GPIO_DURATION(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+2, 0, 8, __Value) -/* define SET_H2CCMD_WOWLAN_GPIO_PULSE_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE((__pH2CCmd)+3, 0, 1, __Value) */ -#define SET_H2CCMD_WOWLAN_GPIO_PULSE_COUNT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+3, 0, 8, __Value) - -/* _REMOTE_WAKEUP_CMD_0x81 */ -#define SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 1, __Value) -#define SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 1, __Value) -#define SET_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 2, 1, __Value) -#define SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 3, 1, __Value) -#define SET_H2CCMD_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 4, 1, __Value) -#define SET_H2CCMD_REMOTE_WAKE_CTRL_FW_UNICAST_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 7, 1, __Value) -#define SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE((__pH2CCmd)+2, 0, 1, __Value) - -/* AOAC_GLOBAL_INFO_0x82 */ -#define SET_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd, 0, 8, __Value) -#define SET_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+1, 0, 8, __Value) - -/* AOAC_RSVDPAGE_LOC_0x83 */ -#define SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd), 0, 8, __Value) -#define SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+1, 0, 8, __Value) -#define SET_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+2, 0, 8, __Value) -#define SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+3, 0, 8, __Value) -#define SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT((__pH2CCmd)+4, 0, 8, __Value) /* */ /* Structure -------------------------------------------------- */ diff --git a/drivers/staging/rtl8723bs/include/hal_com_reg.h b/drivers/staging/rtl8723bs/include/hal_com_reg.h index d8d03752dc2e..9a02ae69d7a4 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_reg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_reg.h @@ -7,91 +7,34 @@ #ifndef __HAL_COMMON_REG_H__ #define __HAL_COMMON_REG_H__ - -#define MAC_ADDR_LEN 6 - -#define HAL_NAV_UPPER_UNIT 128 /* micro-second */ - -/* 8188E PKT_BUFF_ACCESS_CTRL value */ -#define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 -#define DISABLE_TRXPKT_BUF_ACCESS 0x0 - -/* */ -/* */ -/* */ - /* */ /* */ /* 0x0000h ~ 0x00FFh System Configuration */ /* */ /* */ -#define REG_SYS_ISO_CTRL 0x0000 #define REG_SYS_FUNC_EN 0x0002 #define REG_APS_FSMCO 0x0004 #define REG_SYS_CLKR 0x0008 #define REG_9346CR 0x000A #define REG_SYS_EEPROM_CTRL 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS0_CTRL_6 0x0016 -#define REG_POWER_OFF_IN_PROCESS 0x0017 -#define REG_SPS_OCP_CFG 0x0018 #define REG_RSV_CTRL 0x001C #define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 #define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_LDO_CTRL 0x0027 /* 1.5v for 8188EE test chip, 1.4v for MP chip */ -#define REG_AFE_PLL_CTRL 0x0028 #define REG_MAC_PHY_CTRL 0x002c /* for 92d, DMDP, SMSP, DMSP contrl */ -#define REG_APE_PLL_CTRL_EXT 0x002c #define REG_EFUSE_CTRL 0x0030 #define REG_EFUSE_TEST 0x0034 #define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E #define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 #define REG_GPIO_INTM 0x0048 #define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D #define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 #define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c -#define REG_GPIO_PIN_CTRL_2 0x0060 /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ #define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ #define REG_MULTI_FUNC_CTRL 0x0068 /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ -#define REG_GSSR 0x006c -#define REG_AFE_XTAL_CTRL_EXT 0x0078 /* RTL8188E */ #define REG_MCUFWDL 0x0080 -#define REG_MCUTSTCFG 0x0084 -#define REG_FDHM0 0x0088 #define REG_EFUSE_ACCESS 0x00CF /* Efuse access protection for RTL8723 */ -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC #define REG_SYS_CFG 0x00F0 #define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only. */ -#define REG_TYPE_ID 0x00FC - -/* */ -/* 2010/12/29 MH Add for 92D */ -/* */ -#define REG_MAC_PHY_CTRL_NORMAL 0x00f8 - /* */ /* */ @@ -100,44 +43,15 @@ /* */ #define REG_CR 0x0100 #define REG_PBP 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 #define REG_TRXDMA_CTRL 0x010C #define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C #define REG_HIMR 0x0120 #define REG_HISR 0x0124 -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_FTIMR 0x0138 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C #define REG_C2HEVT_MSG_NORMAL 0x01A0 #define REG_C2HEVT_CLEAR 0x01AF -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 #define REG_HMETFR 0x01CC #define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC -#define REG_LLT_INIT 0x01E0 - /* */ /* */ @@ -145,9 +59,7 @@ /* */ /* */ #define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 #define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C #define REG_TXDMA_STATUS 0x0210 #define REG_RQPN_NPQ 0x0214 #define REG_AUTO_LLT 0x0224 @@ -160,109 +72,25 @@ /* */ #define REG_RXDMA_AGG_PG_TH 0x0280 #define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - -/* */ -/* */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* */ -/* */ -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 /* Interrupt Migration */ -#define REG_BCNQ_DESA 0x0308 /* TX Beacon Descriptor Address */ -#define REG_HQ_DESA 0x0310 /* TX High Queue Descriptor Address */ -#define REG_MGQ_DESA 0x0318 /* TX Manage Queue Descriptor Address */ -#define REG_VOQ_DESA 0x0320 /* TX VO Queue Descriptor Address */ -#define REG_VIQ_DESA 0x0328 /* TX VI Queue Descriptor Address */ -#define REG_BEQ_DESA 0x0330 /* TX BE Queue Descriptor Address */ -#define REG_BKQ_DESA 0x0338 /* TX BK Queue Descriptor Address */ -#define REG_RX_DESA 0x0340 /* RX Queue Descriptor Address */ -/* sherry added for DBI Read/Write 20091126 */ -#define REG_DBI_WDATA 0x0348 /* Backdoor REG for Access Configuration */ -#define REG_DBI_RDATA 0x034C /* Backdoor REG for Access Configuration */ -#define REG_DBI_CTRL 0x0350 /* Backdoor REG for Access Configuration */ -#define REG_DBI_FLAG 0x0352 /* Backdoor REG for Access Configuration */ -#define REG_MDIO 0x0354 /* MDIO for Access PCIE PHY */ -#define REG_DBG_SEL 0x0360 /* Debug Selection Register */ -#define REG_PCIE_HRPWM 0x0361 /* PCIe RPWM */ -#define REG_PCIE_HCPWM 0x0363 /* PCIe CPWM */ -#define REG_WATCH_DOG 0x0368 - -/* RTL8723 series ------------------------------- */ -#define REG_PCIE_HISR_EN 0x0394 /* PCIE Local Interrupt Enable Register */ -#define REG_PCIE_HISR 0x03A0 -#define REG_PCIE_HISRE 0x03A4 -#define REG_PCIE_HIMR 0x03A8 -#define REG_PCIE_HIMRE 0x03AC - -#define REG_USB_HIMR 0xFE38 -#define REG_USB_HIMRE 0xFE3C -#define REG_USB_HISR 0xFE78 -#define REG_USB_HISRE 0xFE7C - /* */ /* */ /* 0x0400h ~ 0x047Fh Protocol Configuration */ /* */ /* */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 #define REG_TXPKT_EMPTY 0x041A -#define REG_CPU_MGQ_INFORMATION 0x041C #define REG_FWHW_TXQ_CTRL 0x0420 #define REG_HWSEQ_CTRL 0x0423 -#define REG_BCNQ_BDNY 0x0424 -#define REG_MGQ_BDNY 0x0425 -#define REG_LIFETIME_CTRL 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 #define REG_SPEC_SIFS 0x0428 #define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 #define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_BCNQ1_BDNY 0x0457 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 - -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 - -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 #define REG_PKT_VO_VI_LIFE_TIME 0x04C0 #define REG_PKT_BE_BK_LIFE_TIME 0x04C2 -#define REG_STBC_SETTING 0x04C4 -#define REG_QUEUE_CTRL 0x04C6 -#define REG_SINGLE_AMPDU_CTRL 0x04c7 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_RTS_MAX_AGGR_NUM 0x04CB #define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF #define REG_EARLY_MODE_CONTROL 0x04D0 #define REG_MACID_SLEEP 0x04D4 #define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_TX_RPT_CTRL 0x04EC -#define REG_TX_RPT_TIME 0x04F0 /* 2 byte */ -#define REG_DUMMY 0x04FC /* */ /* */ @@ -274,16 +102,11 @@ #define REG_EDCA_BE_PARAM 0x0508 #define REG_EDCA_BK_PARAM 0x050C #define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 #define REG_SIFS_CTX 0x0514 #define REG_SIFS_TRX 0x0516 #define REG_TSFTR_SYN_OFFSET 0x0518 -#define REG_AGGR_BREAK_TIME 0x051A #define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 #define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 #define REG_RD_CTRL 0x0524 /* */ /* Format for offset 540h-542h: */ @@ -301,90 +124,39 @@ /* Described by Designer Tim and Bruce, 2011-01-14. */ /* */ #define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 #define REG_BCN_CTRL 0x0550 #define REG_BCN_CTRL_1 0x0551 -#define REG_MBID_NUM 0x0552 #define REG_DUAL_TSF_RST 0x0553 #define REG_BCN_INTERVAL 0x0554 /* The same as REG_MBSSID_BCN_SPACE */ #define REG_DRVERLYINT 0x0558 #define REG_BCNDMATIM 0x0559 #define REG_ATIMWND 0x055A -#define REG_USTIME_TSF 0x055C #define REG_BCN_MAX_ERR 0x055D #define REG_RXTSF_OFFSET_CCK 0x055E #define REG_RXTSF_OFFSET_OFDM 0x055F #define REG_TSFTR 0x0560 -#define REG_TSFTR1 0x0568 /* HW Port 1 TSF Register */ -#define REG_ATIMWND_1 0x0570 -#define REG_P2P_CTWIN 0x0572 /* 1 Byte long (in unit of TU) */ -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 #define REG_ACMHWCTRL 0x05C0 -#define REG_NOA_DESC_SEL 0x05CF -#define REG_NOA_DESC_DURATION 0x05E0 -#define REG_NOA_DESC_INTERVAL 0x05E4 -#define REG_NOA_DESC_START 0x05E8 -#define REG_NOA_DESC_COUNT 0x05EC - -#define REG_DMC 0x05F0 /* Dual MAC Co-Existence Register */ -#define REG_SCH_TX_CMD 0x05F8 - -#define REG_FW_RESET_TSF_CNT_1 0x05FC -#define REG_FW_RESET_TSF_CNT_0 0x05FD -#define REG_FW_BCN_DIS_CNT 0x05FE /* */ /* */ /* 0x0600h ~ 0x07FFh WMAC Configuration */ /* */ /* */ -#define REG_APSD_CTRL 0x0600 #define REG_BWOPMODE 0x0603 #define REG_TCR 0x0604 #define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D #define REG_RX_DRVINFO_SZ 0x060F #define REG_MACID 0x0610 #define REG_BSSID 0x0618 #define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 -#define REG_PNO_STATUS 0x0631 -#define REG_USTIME_EDCA 0x0638 #define REG_MAC_SPEC_SIFS 0x063A /* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */ #define REG_RESP_SIFS_CCK 0x063C /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ #define REG_RESP_SIFS_OFDM 0x063E /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ #define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - - -/* RXERR_RPT */ -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDMfalse_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCKfalse_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HTfalse_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) /* */ /* Note: */ @@ -398,81 +170,19 @@ #define REG_NAV_UPPER 0x0652 /* unit of 128 */ /* WMA, BA, CCX */ -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 #define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 /* Security */ #define REG_CAMCMD 0x0670 #define REG_CAMWRITE 0x0674 #define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C #define REG_SECCFG 0x0680 /* Power */ -#define REG_WOW_CTRL 0x0690 -#define REG_PS_RX_INFO 0x0692 -#define REG_UAPSD_TID 0x0693 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_NUM REG_WKFMCAM_CMD -#define REG_WKFMCAM_RWD 0x069C #define REG_RXFLTMAP0 0x06A0 #define REG_RXFLTMAP1 0x06A2 #define REG_RXFLTMAP2 0x06A4 #define REG_BCN_PSR_RPT 0x06A8 -#define REG_BT_COEX_TABLE 0x06C0 - -/* Hardware Port 2 */ -#define REG_MACID1 0x0700 -#define REG_BSSID1 0x0708 - - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h USB Configuration */ -/* */ -/* */ -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -/* for 92DU high_Queue low_Queue Normal_Queue select */ -#define REG_USB_High_NORMAL_Queue_Select_MAC0 0xFE44 -/* define REG_USB_LOW_Queue_Select_MAC0 0xFE45 */ -#define REG_USB_High_NORMAL_Queue_Select_MAC1 0xFE47 -/* define REG_USB_LOW_Queue_Select_MAC1 0xFE48 */ - -/* For test chip */ -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_TEST_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 /* 0xFE66~0xFE6B */ -#define REG_TEST_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_TEST_SIE_STRING 0xFE80 /* 0xFE80~0xFEB9 */ - - -/* For normal chip */ -#define REG_NORMAL_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_NORMAL_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 /* 0xFE65~0xFE67 */ -#define REG_NORMAL_SIE_PHY 0xFE68 /* 0xFE68~0xFE6B */ -#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C -#define REG_NORMAL_SIE_GPS_EP 0xFE6D /* 0xFE6D, for RTL8723 only. */ -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_NORMAL_SIE_STRING 0xFE80 /* 0xFE80~0xFEDF */ - /* */ /* */ @@ -486,37 +196,14 @@ #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ #define EFUSE_TEST REG_EFUSE_TEST /* E-Fuse Test. */ #define MSR (REG_CR + 2) /* Media Status register */ -/* define ISR REG_HISR */ - -#define TSFR REG_TSFTR /* Timing Sync Function Timer Register. */ -#define TSFR1 REG_TSFTR1 /* HW Port 1 TSF Register */ #define PBP REG_PBP -/* Redifine MACID register, to compatible prior ICs. */ -#define IDR0 REG_MACID /* MAC ID Register, Offset 0x0050-0x0053 */ -#define IDR4 (REG_MACID + 4) /* MAC ID Register, Offset 0x0054-0x0055 */ - - /* */ /* 9. Security Control Registers (Offset:) */ /* */ #define RWCAM REG_CAMCMD /* IN 8190 Data Sheet is called CAMcmd */ #define WCAMI REG_CAMWRITE /* Software write CAM input content */ -#define RCAMO REG_CAMREAD /* Software read/write CAM config */ -#define CAMDBG REG_CAMDBG -#define SECR REG_SECCFG /* Security Configuration Register */ - -/* Unused register */ -#define UnusedRegister 0x1BF -#define DCAM UnusedRegister -#define PSR UnusedRegister -#define BBAddr UnusedRegister -#define PhyDataR UnusedRegister - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A /* */ /* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ @@ -527,20 +214,6 @@ #define HSISR_PDNINT BIT7 #define HSISR_GPIO9_INT BIT25 -/* */ -/* USB INTR CONTENT */ -/* */ -#define USB_C2H_CMDID_OFFSET 0 -#define USB_C2H_SEQ_OFFSET 1 -#define USB_C2H_EVENT_OFFSET 2 -#define USB_INTR_CPWM_OFFSET 16 -#define USB_INTR_CONTENT_C2H_OFFSET 0 -#define USB_INTR_CONTENT_CPWM1_OFFSET 16 -#define USB_INTR_CONTENT_CPWM2_OFFSET 20 -#define USB_INTR_CONTENT_HISR_OFFSET 48 -#define USB_INTR_CONTENT_HISRE_OFFSET 52 -#define USB_INTR_CONTENT_LENGTH 56 - /* */ /* Response Rate Set Register (offset 0x440, 24bits) */ /* */ @@ -549,59 +222,14 @@ #define RRSR_5_5M BIT2 #define RRSR_11M BIT3 #define RRSR_6M BIT4 -#define RRSR_9M BIT5 #define RRSR_12M BIT6 -#define RRSR_18M BIT7 #define RRSR_24M BIT8 -#define RRSR_36M BIT9 -#define RRSR_48M BIT10 -#define RRSR_54M BIT11 -#define RRSR_MCS0 BIT12 -#define RRSR_MCS1 BIT13 -#define RRSR_MCS2 BIT14 -#define RRSR_MCS3 BIT15 -#define RRSR_MCS4 BIT16 -#define RRSR_MCS5 BIT17 -#define RRSR_MCS6 BIT18 -#define RRSR_MCS7 BIT19 #define RRSR_CCK_RATES (RRSR_11M|RRSR_5_5M|RRSR_2M|RRSR_1M) -#define RRSR_OFDM_RATES (RRSR_54M|RRSR_48M|RRSR_36M|RRSR_24M|RRSR_18M|RRSR_12M|RRSR_9M|RRSR_6M) - -/* WOL bit information */ -#define HAL92C_WOL_PTK_UPDATE_EVENT BIT0 -#define HAL92C_WOL_GTK_UPDATE_EVENT BIT1 -#define HAL92C_WOL_DISASSOC_EVENT BIT2 -#define HAL92C_WOL_DEAUTH_EVENT BIT3 -#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT4 /* */ /* Rate Definition */ /* */ -/* CCK */ -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -/* OFDM */ -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -/* MCS 1 Spatial Stream */ -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 - /* CCK */ #define RATE_1M BIT(0) #define RATE_2M BIT(1) @@ -616,22 +244,12 @@ #define RATE_36M BIT(9) #define RATE_48M BIT(10) #define RATE_54M BIT(11) -/* MCS 1 Spatial Stream */ -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) /* ALL CCK Rate */ #define RATE_BITMAP_ALL 0xFFFFF /* Only use CCK 1M rate for ACK */ #define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 -#define RATE_RRSR_WITHOUT_CCK 0xFFFF0 /* */ /* BW_OPMODE bits (Offset 0x603, 8bit) */ @@ -642,88 +260,19 @@ /* CAM Config Setting (offset 0x680, 1 byte) */ /* */ #define CAM_VALID BIT15 -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT5 #define CAM_CONTENT_COUNT 8 -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 #define CAM_AES 0x04 -#define CAM_WEP104 0x05 -#define CAM_SMS4 0x6 #define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_CONFIG_USEDK true -#define CAM_CONFIG_NO_USEDK false #define CAM_WRITE BIT16 -#define CAM_READ 0x00000000 #define CAM_POLLINIG BIT31 -/* */ -/* 10. Power Save Control Registers */ -/* */ -#define WOW_PMEN BIT0 /* Power management Enable. */ -#define WOW_WOMEN BIT1 /* WoW function on or off. */ -#define WOW_MAGIC BIT2 /* Magic packet */ -#define WOW_UWF BIT3 /* Unicast Wakeup frame. */ - /* */ /* 12. Host Interrupt Status Registers */ /* */ -/* */ -/* 8190 IMR/ISR bits */ -/* */ -#define IMR8190_DISABLED 0x0 -#define IMR_DISABLED 0x0 -/* IMR DW0 Bit 0-31 */ -#define IMR_BCNDMAINT6 BIT31 /* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT5 BIT30 /* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT4 BIT29 /* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT3 BIT28 /* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT2 BIT27 /* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT1 BIT26 /* Beacon DMA Interrupt 1 */ -#define IMR_BCNDOK8 BIT25 /* Beacon Queue DMA OK Interrupt 8 */ -#define IMR_BCNDOK7 BIT24 /* Beacon Queue DMA OK Interrupt 7 */ -#define IMR_BCNDOK6 BIT23 /* Beacon Queue DMA OK Interrupt 6 */ -#define IMR_BCNDOK5 BIT22 /* Beacon Queue DMA OK Interrupt 5 */ -#define IMR_BCNDOK4 BIT21 /* Beacon Queue DMA OK Interrupt 4 */ -#define IMR_BCNDOK3 BIT20 /* Beacon Queue DMA OK Interrupt 3 */ -#define IMR_BCNDOK2 BIT19 /* Beacon Queue DMA OK Interrupt 2 */ -#define IMR_BCNDOK1 BIT18 /* Beacon Queue DMA OK Interrupt 1 */ -#define IMR_TIMEOUT2 BIT17 /* Timeout interrupt 2 */ -#define IMR_TIMEOUT1 BIT16 /* Timeout interrupt 1 */ -#define IMR_TXFOVW BIT15 /* Transmit FIFO Overflow */ -#define IMR_PSTIMEOUT BIT14 /* Power save time out interrupt */ -#define IMR_BcnInt BIT13 /* Beacon DMA Interrupt 0 */ -#define IMR_RXFOVW BIT12 /* Receive FIFO Overflow */ -#define IMR_RDU BIT11 /* Receive Descriptor Unavailable */ -#define IMR_ATIMEND BIT10 /* For 92C, ATIM Window End Interrupt. For 8723 and later ICs, it also means P2P CTWin End interrupt. */ -#define IMR_BDOK BIT9 /* Beacon Queue DMA OK Interrupt */ -#define IMR_HIGHDOK BIT8 /* High Queue DMA OK Interrupt */ -#define IMR_TBDOK BIT7 /* Transmit Beacon OK interrupt */ -#define IMR_MGNTDOK BIT6 /* Management Queue DMA OK Interrupt */ -#define IMR_TBDER BIT5 /* For 92C, Transmit Beacon Error Interrupt */ -#define IMR_BKDOK BIT4 /* AC_BK DMA OK Interrupt */ -#define IMR_BEDOK BIT3 /* AC_BE DMA OK Interrupt */ -#define IMR_VIDOK BIT2 /* AC_VI DMA OK Interrupt */ -#define IMR_VODOK BIT1 /* AC_VO DMA Interrupt */ -#define IMR_ROK BIT0 /* Receive DMA OK Interrupt */ - -/* 13. Host Interrupt Status Extension Register (Offset: 0x012C-012Eh) */ -#define IMR_TSF_BIT32_TOGGLE BIT15 -#define IMR_BcnInt_E BIT12 -#define IMR_TXERR BIT11 -#define IMR_RXERR BIT10 -#define IMR_C2HCMD BIT9 -#define IMR_CPWM BIT8 -/* RSVD [2-7] */ -#define IMR_OCPINT BIT1 -#define IMR_WLANOFF BIT0 /* */ /* 8192C (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */ @@ -733,34 +282,15 @@ #define RCR_APP_ICV BIT29 /* MACRX will retain the ICV at the bottom of the packet. */ #define RCR_APP_PHYST_RXFF BIT28 /* PHY Status is appended before RX packet in RXFF */ #define RCR_APP_BA_SSN BIT27 /* SSN of previous TXBA is appended as after original RXDESC as the 4-th DW of RXDESC. */ -#define RCR_NONQOS_VHT BIT26 /* Reserved */ -#define RCR_RSVD_BIT25 BIT25 /* Reserved */ -#define RCR_ENMBID BIT24 /* Enable Multiple BssId. Only response ACK to the packets whose DID(A1) matching to the addresses in the MBSSID CAM Entries. */ -#define RCR_LSIGEN BIT23 /* Enable LSIG TXOP Protection function. Search KEYCAM for each rx packet to check if LSIGEN bit is set. */ -#define RCR_MFBEN BIT22 /* Enable immediate MCS Feedback function. When Rx packet with MRQ = 1'b1, then search KEYCAM to find sender's MCS Feedback function and send response. */ -#define RCR_RSVD_BIT21 BIT21 /* Reserved */ -#define RCR_RSVD_BIT20 BIT20 /* Reserved */ -#define RCR_RSVD_BIT19 BIT19 /* Reserved */ -#define RCR_TIM_PARSER_EN BIT18 /* RX Beacon TIM Parser. */ -#define RCR_BM_DATA_EN BIT17 /* Broadcast data packet interrupt enable. */ -#define RCR_UC_DATA_EN BIT16 /* Unicast data packet interrupt enable. */ -#define RCR_RSVD_BIT15 BIT15 /* Reserved */ #define RCR_HTC_LOC_CTRL BIT14 /* MFC<--HTC = 1 MFC-->HTC = 0 */ #define RCR_AMF BIT13 /* Accept management type frame */ -#define RCR_ACF BIT12 /* Accept control type frame. Control frames BA, BAR, and PS-Poll (when in AP mode) are not controlled by this bit. They are controlled by ADF. */ #define RCR_ADF BIT11 /* Accept data type frame. This bit also regulates BA, BAR, and PS-Poll (AP mode only). */ -#define RCR_RSVD_BIT10 BIT10 /* Reserved */ -#define RCR_AICV BIT9 /* Accept ICV error packet */ #define RCR_ACRC32 BIT8 /* Accept CRC32 error packet */ #define RCR_CBSSID_BCN BIT7 /* Accept BSSID match packet (Rx beacon, probe rsp) */ #define RCR_CBSSID_DATA BIT6 /* Accept BSSID match packet (Data) */ -#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match packet */ -#define RCR_APWRMGT BIT5 /* Accept power management packet */ -#define RCR_ADD3 BIT4 /* Accept address 3 match packet */ #define RCR_AB BIT3 /* Accept broadcast packet */ #define RCR_AM BIT2 /* Accept multicast packet */ #define RCR_APM BIT1 /* Accept physical match packet */ -#define RCR_AAP BIT0 /* Accept all unicast packet */ /* */ @@ -769,76 +299,25 @@ /* */ /* */ -/* 2 SYS_ISO_CTRL */ -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) -#define PWC_EV12V BIT(15) - - /* 2 SYS_FUNC_EN */ #define FEN_BBRSTB BIT(0) #define FEN_BB_GLB_RSTn BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) #define FEN_DIO_PCIE BIT(5) #define FEN_PCIEA BIT(6) #define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) #define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) #define FEN_ELDR BIT(12) -#define FEN_EN_25_1 BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) /* 2 APS_FSMCO */ -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) #define EnPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) /* 2 SYS_CLKR */ -#define ANAD16V_EN BIT(0) #define ANA8M BIT(1) -#define MACSLP BIT(4) #define LOADER_CLK_EN BIT(5) /* 2 9346CR /REG_SYS_EEPROM_CTRL */ #define BOOT_FROM_EEPROM BIT(4) -#define EEPROMSEL BIT(4) #define EEPROM_EN BIT(5) @@ -847,20 +326,7 @@ #define RF_RSTB BIT(1) #define RF_SDMRSTB BIT(2) - -/* 2 LDOV12D_CTRL */ -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - - - /* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EF_TRPT BIT(7) -#define EF_CELL_SEL (BIT(8)|BIT(9)) /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */ -#define LDOE25_EN BIT(31) #define EFUSE_SEL(x) (((x) & 0x3) << 8) #define EFUSE_SEL_MASK 0x300 #define EFUSE_WIFI_SEL_0 0x0 @@ -871,41 +337,13 @@ /* 2 8051FWDL */ /* 2 MCUFWDL */ -#define MCUFWDL_EN BIT(0) #define MCUFWDL_RDY BIT(1) #define FWDL_ChkSum_rpt BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) #define WINTINI_RDY BIT(6) #define RAM_DL_SEL BIT(7) -#define ROM_DLEN BIT(19) -#define CPRST BIT(23) - /* 2 REG_SYS_CFG */ -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define SW_OFFLOAD_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15)) -#define BT_FUNC BIT(16) #define VENDOR_ID BIT(19) -#define EXT_VENDOR_ID (BIT(18)|BIT(19)) /* Currently only for RTL8723B */ -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) /* RTL ID */ -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) -#define RF_TYPE_ID BIT(27) #define RTL_ID BIT(23) /* TestChip ID, 1:Test(RLE); 0:MP(RL) */ #define SPS_SEL BIT(24) /* 1:LDO regulator mode; 0:Switching regulator mode */ @@ -913,31 +351,10 @@ #define CHIP_VER_RTL_MASK 0xF000 /* Bit 12 ~ 15 */ #define CHIP_VER_RTL_SHIFT 12 -#define EXT_VENDOR_ID_SHIFT 18 /* 2 REG_GPIO_OUTSTS (For RTL8723 only) */ -#define EFS_HCI_SEL (BIT(0)|BIT(1)) -#define PAD_HCI_SEL (BIT(2)|BIT(3)) -#define HCI_SEL (BIT(4)|BIT(5)) -#define PKG_SEL_HCI BIT(6) -#define FEN_GPS BIT(7) -#define FEN_BT BIT(8) -#define FEN_WL BIT(9) -#define FEN_PCI BIT(10) -#define FEN_USB BIT(11) -#define BTRF_HWPDN_N BIT(12) -#define WLRF_HWPDN_N BIT(13) -#define PDN_BT_N BIT(14) -#define PDN_GPS_N BIT(15) -#define BT_CTL_HWPDN BIT(16) -#define GPS_CTL_HWPDN BIT(17) -#define PPHY_SUSB BIT(20) -#define UPHY_SUSB BIT(21) -#define PCI_SUSEN BIT(22) -#define USB_SUSEN BIT(23) #define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) - /* */ /* */ /* 0x0100h ~ 0x01FFh MACTOP General Configuration */ @@ -961,46 +378,19 @@ /* Network type */ #define _NETTYPE(x) (((x) & 0x3) << 16) #define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 #define NT_LINK_AD_HOC 0x1 #define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 /* 2 PBP - Page Size Register */ -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 #define _PSRX(x) (x) #define _PSTX(x) ((x) << 4) -#define PBP_64 0x0 #define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - /* 2 TX/RXDMA */ -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) #define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) /* For normal driver, 0x10C */ -#define _TXDMA_CMQ_MAP(x) (((x)&0x3) << 16) #define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) #define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) #define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) @@ -1008,26 +398,10 @@ #define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) #define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) -#define QUEUE_EXTRA 0 #define QUEUE_LOW 1 #define QUEUE_NORMAL 2 #define QUEUE_HIGH 3 - -/* 2 TRXFF_BNDY */ - - -/* 2 LLT_INIT */ -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - - /* */ /* */ /* 0x0200h ~ 0x027Fh TXDMA Configuration */ @@ -1038,35 +412,12 @@ #define _LPQ(x) (((x) & 0xFF) << 8) #define _PUBQ(x) (((x) & 0xFF) << 16) #define _NPQ(x) ((x) & 0xFF) /* NOTE: in RQPN_NPQ register */ -#define _EPQ(x) (((x) & 0xFF) << 16) /* NOTE: in RQPN_EPQ register */ - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) #define LD_RQPN BIT(31) - -/* 2 TDECTL */ -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - - -/* 2 TXDMA_OFFSET_CHK */ -#define DROP_DATA_EN BIT(9) - /* 2 AUTO_LLT */ -#define BIT_SHIFT_TXPKTNUM 24 -#define BIT_MASK_TXPKTNUM 0xff -#define BIT_TXPKTNUM(x) (((x) & BIT_MASK_TXPKTNUM) << BIT_SHIFT_TXPKTNUM) - -#define BIT_TDE_DBG_SEL BIT(23) #define BIT_AUTO_INIT_LLT BIT(16) -#define BIT_SHIFT_Tx_OQT_free_space 8 -#define BIT_MASK_Tx_OQT_free_space 0xff -#define BIT_Tx_OQT_free_space(x) (((x) & BIT_MASK_Tx_OQT_free_space) << BIT_SHIFT_Tx_OQT_free_space) - - /* */ /* */ /* 0x0280h ~ 0x028Bh RX DMA Configuration */ @@ -1112,13 +463,6 @@ /* */ /* */ -/* 2 EDCA setting */ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - - #define _LRL(x) ((x) & 0x3F) #define _SRL(x) (((x) & 0x3F) << 8) @@ -1126,33 +470,16 @@ /* 2 BCN_CTRL */ #define EN_TXBCN_RPT BIT(2) #define EN_BCN_FUNCTION BIT(3) -#define STOP_BCNQ BIT(6) -#define DIS_RX_BSSID_FIT BIT(6) #define DIS_ATIM BIT(0) #define DIS_BCNQ_SUB BIT(1) #define DIS_TSF_UDT BIT(4) -/* The same function but different bit field. */ -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - - /* 2 ACMHWCTRL */ #define AcmHw_HwEn BIT(0) #define AcmHw_BeqEn BIT(1) #define AcmHw_ViqEn BIT(2) #define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) - -/* 2 REG_DUAL_TSF_RST (0x553) */ -#define DUAL_TSF_RST_P2P BIT(4) - -/* 2 REG_NOA_DESC_SEL (0x5CF) */ -#define NOA_DESC_SEL_0 0 -#define NOA_DESC_SEL_1 BIT(4) /* */ /* */ @@ -1160,56 +487,17 @@ /* */ /* */ -/* 2 APSD_CTRL */ -#define APSDOFF BIT(6) - /* 2 TCR */ #define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - /* 2 RCR */ -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) #define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define EnMBID BIT(24) -#define FORCEACK BIT(26) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - /* 2 SECCFG */ #define SCR_TxUseDK BIT(0) /* Force Tx Use Default Key */ #define SCR_RxUseDK BIT(1) /* Force Rx Use Default Key */ #define SCR_TxEncEnable BIT(2) /* Enable Tx Encryption */ #define SCR_RxDecEnable BIT(3) /* Enable Rx Decryption */ -#define SCR_SKByA2 BIT(4) /* Search kEY BY A2 */ -#define SCR_NoSKMC BIT(5) /* No Key Search Multicast */ #define SCR_TXBCUSEDK BIT(6) /* Force Tx Broadcast packets Use Default Key */ #define SCR_RXBCUSEDK BIT(7) /* Force Rx Broadcast packets Use Default Key */ #define SCR_CHK_KEYID BIT(8) @@ -1222,13 +510,6 @@ /* I/O bus domain address mapping */ #define SDIO_LOCAL_BASE 0x10250000 -#define WLAN_IOREG_BASE 0x10260000 -#define FIRMWARE_FIFO_BASE 0x10270000 -#define TX_HIQ_BASE 0x10310000 -#define TX_MIQ_BASE 0x10320000 -#define TX_LOQ_BASE 0x10330000 -#define TX_EPQ_BASE 0x10350000 -#define RX_RX0FF_BASE 0x10340000 /* SDIO host local register space mapping. */ #define SDIO_LOCAL_MSK 0x0FFF @@ -1236,12 +517,10 @@ #define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */ #define WLAN_RX0FF_MSK 0x0003 -#define SDIO_WITHOUT_REF_DEVICE_ID 0 /* Without reference to the SDIO Device ID */ #define SDIO_LOCAL_DEVICE_ID 0 /* 0b[16], 000b[15:13] */ #define WLAN_TX_HIQ_DEVICE_ID 4 /* 0b[16], 100b[15:13] */ #define WLAN_TX_MIQ_DEVICE_ID 5 /* 0b[16], 101b[15:13] */ #define WLAN_TX_LOQ_DEVICE_ID 6 /* 0b[16], 110b[15:13] */ -#define WLAN_TX_EXQ_DEVICE_ID 3 /* 0b[16], 011b[15:13] */ #define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */ #define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */ @@ -1252,49 +531,21 @@ #define PUBLIC_QUEUE_IDX 3 #define SDIO_MAX_TX_QUEUE 3 /* HIQ, MIQ and LOQ */ -#define SDIO_MAX_RX_QUEUE 1 #define SDIO_REG_TX_CTRL 0x0000 /* SDIO Tx Control */ #define SDIO_REG_HIMR 0x0014 /* SDIO Host Interrupt Mask */ #define SDIO_REG_HISR 0x0018 /* SDIO Host Interrupt Service Routine */ -#define SDIO_REG_HCPWM 0x0019 /* HCI Current Power Mode */ #define SDIO_REG_RX0_REQ_LEN 0x001C /* RXDMA Request Length */ #define SDIO_REG_OQT_FREE_PG 0x001E /* OQT Free Page */ #define SDIO_REG_FREE_TXPG 0x0020 /* Free Tx Buffer Page */ -#define SDIO_REG_HCPWM1 0x0024 /* HCI Current Power Mode 1 */ -#define SDIO_REG_HCPWM2 0x0026 /* HCI Current Power Mode 2 */ -#define SDIO_REG_FREE_TXPG_SEQ 0x0028 /* Free Tx Page Sequence */ -#define SDIO_REG_HTSFR_INFO 0x0030 /* HTSF Informaion */ #define SDIO_REG_HRPWM1 0x0080 /* HCI Request Power Mode 1 */ -#define SDIO_REG_HRPWM2 0x0082 /* HCI Request Power Mode 2 */ -#define SDIO_REG_HPS_CLKR 0x0084 /* HCI Power Save Clock */ #define SDIO_REG_HSUS_CTRL 0x0086 /* SDIO HCI Suspend Control */ -#define SDIO_REG_HIMR_ON 0x0090 /* SDIO Host Extension Interrupt Mask Always */ -#define SDIO_REG_HISR_ON 0x0091 /* SDIO Host Extension Interrupt Status Always */ #define SDIO_HIMR_DISABLED 0 /* RTL8723/RTL8188E SDIO Host Interrupt Mask Register */ #define SDIO_HIMR_RX_REQUEST_MSK BIT0 #define SDIO_HIMR_AVAL_MSK BIT1 -#define SDIO_HIMR_TXERR_MSK BIT2 -#define SDIO_HIMR_RXERR_MSK BIT3 -#define SDIO_HIMR_TXFOVW_MSK BIT4 -#define SDIO_HIMR_RXFOVW_MSK BIT5 -#define SDIO_HIMR_TXBCNOK_MSK BIT6 -#define SDIO_HIMR_TXBCNERR_MSK BIT7 -#define SDIO_HIMR_BCNERLY_INT_MSK BIT16 -#define SDIO_HIMR_C2HCMD_MSK BIT17 -#define SDIO_HIMR_CPWM1_MSK BIT18 -#define SDIO_HIMR_CPWM2_MSK BIT19 -#define SDIO_HIMR_HSISR_IND_MSK BIT20 -#define SDIO_HIMR_GTINT3_IND_MSK BIT21 -#define SDIO_HIMR_GTINT4_IND_MSK BIT22 -#define SDIO_HIMR_PSTIMEOUT_MSK BIT23 -#define SDIO_HIMR_OCPINT_MSK BIT24 -#define SDIO_HIMR_ATIMEND_MSK BIT25 -#define SDIO_HIMR_ATIMEND_E_MSK BIT26 -#define SDIO_HIMR_CTWEND_MSK BIT27 /* SDIO Host Interrupt Service Routine */ #define SDIO_HISR_RX_REQUEST BIT0 @@ -1305,7 +556,6 @@ #define SDIO_HISR_RXFOVW BIT5 #define SDIO_HISR_TXBCNOK BIT6 #define SDIO_HISR_TXBCNERR BIT7 -#define SDIO_HISR_BCNERLY_INT BIT16 #define SDIO_HISR_C2HCMD BIT17 #define SDIO_HISR_CPWM1 BIT18 #define SDIO_HISR_CPWM2 BIT19 @@ -1314,9 +564,6 @@ #define SDIO_HISR_GTINT4_IND BIT22 #define SDIO_HISR_PSTIMEOUT BIT23 #define SDIO_HISR_OCPINT BIT24 -#define SDIO_HISR_ATIMEND BIT25 -#define SDIO_HISR_ATIMEND_E BIT26 -#define SDIO_HISR_CTWEND BIT27 #define MASK_SDIO_HISR_CLEAR (SDIO_HISR_TXERR |\ SDIO_HISR_RXERR |\ @@ -1333,15 +580,8 @@ SDIO_HISR_PSTIMEOUT |\ SDIO_HISR_OCPINT) -/* SDIO HCI Suspend Control Register */ -#define HCI_RESUME_PWR_RDY BIT1 -#define HCI_SUS_CTRL BIT0 - /* SDIO Tx FIFO related */ #define SDIO_TX_FREE_PG_QUEUE 4 /* The number of Tx FIFO free page */ -#define SDIO_TX_FIFO_PAGE_SZ 128 - -#define MAX_TX_AGG_PACKET_NUMBER 0x8 /* */ /* */ @@ -1349,46 +589,14 @@ /* */ /* */ -/* 2 USB Information (0xFE17) */ -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -/* 2 Special Option */ -#define USB_AGG_EN BIT(3) - -/* 0; Use interrupt endpoint to upload interrupt pkt */ -/* 1; Use bulk endpoint to upload interrupt pkt, */ -#define INT_BULK_SEL BIT(4) - /* 2REG_C2HEVT_CLEAR */ #define C2H_EVT_HOST_CLOSE 0x00 /* Set by driver and notify FW that the driver has read the C2H command message */ #define C2H_EVT_FW_CLOSE 0xFF /* Set by FW indicating that FW had set the C2H command message and it's not yet read by driver. */ - /* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ -#define WL_HWPDN_EN BIT0 /* Enable GPIO[9] as WiFi HW PDn source */ #define WL_HWPDN_SL BIT1 /* WiFi HW PDn polarity control */ #define WL_FUNC_EN BIT2 /* WiFi function enable */ -#define WL_HWROF_EN BIT3 /* Enable GPIO[9] as WiFi RF HW PDn source */ -#define BT_HWPDN_EN BIT16 /* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_SL BIT17 /* BT HW PDn polarity control */ #define BT_FUNC_EN BIT18 /* BT function enable */ -#define BT_HWROF_EN BIT19 /* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define GPS_HWPDN_EN BIT20 /* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_SL BIT21 /* GPS HW PDn polarity control */ #define GPS_FUNC_EN BIT22 /* GPS function enable */ -/* */ -/* General definitions */ -/* */ - -#define LAST_ENTRY_OF_TX_PKT_BUFFER_8723B 255 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 - #endif /* __HAL_COMMON_H__ */ diff --git a/drivers/staging/rtl8723bs/include/hal_phy_reg_8723b.h b/drivers/staging/rtl8723bs/include/hal_phy_reg_8723b.h deleted file mode 100644 index b0b1ac1090fc..000000000000 --- a/drivers/staging/rtl8723bs/include/hal_phy_reg_8723b.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __INC_HAL8723BPHYREG_H__ -#define __INC_HAL8723BPHYREG_H__ - -#include - -/* BB Register Definition */ -/* */ -/* 4. Page9(0x900) */ -/* */ -#define rDPDT_control 0x92c -#define rfe_ctrl_anta_src 0x930 -#define rS0S1_PathSwitch 0x948 -#define AGC_table_select 0xb2c - -/* */ -/* PageB(0xB00) */ -/* */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rPdp_AntA_8 0xb08 -#define rPdp_AntA_C 0xb0c -#define rPdp_AntA_10 0xb10 -#define rPdp_AntA_14 0xb14 -#define rPdp_AntA_18 0xb18 -#define rPdp_AntA_1C 0xb1c -#define rPdp_AntA_20 0xb20 -#define rPdp_AntA_24 0xb24 - -#define rConfig_Pmpd_AntA 0xb28 -#define rConfig_ram64x16 0xb2c - -#define rBndA 0xb30 -#define rHssiPar 0xb34 - -#define rConfig_AntA 0xb68 -#define rConfig_AntB 0xb6c - -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rPdp_AntB_8 0xb78 -#define rPdp_AntB_C 0xb7c -#define rPdp_AntB_10 0xb80 -#define rPdp_AntB_14 0xb84 -#define rPdp_AntB_18 0xb88 -#define rPdp_AntB_1C 0xb8c -#define rPdp_AntB_20 0xb90 -#define rPdp_AntB_24 0xb94 - -#define rConfig_Pmpd_AntB 0xb98 - -#define rBndB 0xba0 - -#define rAPK 0xbd8 -#define rPm_Rx0_AntA 0xbdc -#define rPm_Rx1_AntA 0xbe0 -#define rPm_Rx2_AntA 0xbe4 -#define rPm_Rx3_AntA 0xbe8 -#define rPm_Rx0_AntB 0xbec -#define rPm_Rx1_AntB 0xbf0 -#define rPm_Rx2_AntB 0xbf4 -#define rPm_Rx3_AntB 0xbf8 - -#endif diff --git a/drivers/staging/rtl8723bs/include/hal_pwr_seq.h b/drivers/staging/rtl8723bs/include/hal_pwr_seq.h index 0a2e60770668..5e43cc89f535 100644 --- a/drivers/staging/rtl8723bs/include/hal_pwr_seq.h +++ b/drivers/staging/rtl8723bs/include/hal_pwr_seq.h @@ -28,9 +28,7 @@ #define RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS 26 #define RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS 15 #define RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS 15 -#define RTL8723B_TRANS_SUS_TO_CARDEMU_STEPS 15 #define RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS 15 -#define RTL8723B_TRANS_PDN_TO_CARDEMU_STEPS 15 #define RTL8723B_TRANS_ACT_TO_LPS_STEPS 15 #define RTL8723B_TRANS_LPS_TO_ACT_STEPS 15 #define RTL8723B_TRANS_ACT_TO_SWLPS_STEPS 22 @@ -128,11 +126,6 @@ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0},/* 0x04[16] = 0*/\ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7},/* 0x04[15] = 1*/ -#define RTL8723B_TRANS_PDN_TO_CARDEMU \ - /* format */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0},/* 0x04[15] = 0*/ - #define RTL8723B_TRANS_ACT_TO_LPS \ /* format */ \ /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here*/ \ diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h index c1d7249e3e9d..f9ecd9047d52 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h @@ -17,7 +17,7 @@ #include "rtl8723b_cmd.h" #include "rtw_mp.h" #include "hal_pwr_seq.h" -#include "hal_phy_reg_8723b.h" +#include "Hal8192CPhyReg.h" #include "hal_phy_cfg.h" /* */ diff --git a/drivers/staging/rtl8723bs/include/rtw_efuse.h b/drivers/staging/rtl8723bs/include/rtw_efuse.h index 5938a6bfb573..0cb8c6f6d34d 100644 --- a/drivers/staging/rtl8723bs/include/rtw_efuse.h +++ b/drivers/staging/rtl8723bs/include/rtw_efuse.h @@ -7,19 +7,6 @@ #ifndef __RTW_EFUSE_H__ #define __RTW_EFUSE_H__ - -#define EFUSE_ERROE_HANDLE 1 - -#define PG_STATE_HEADER 0x01 -#define PG_STATE_WORD_0 0x02 -#define PG_STATE_WORD_1 0x04 -#define PG_STATE_WORD_2 0x08 -#define PG_STATE_WORD_3 0x10 -#define PG_STATE_DATA 0x20 - -#define PG_SWBYTE_H 0x01 -#define PG_SWBYTE_L 0x02 - #define PGPKT_DATA_SIZE 8 #define EFUSE_WIFI 0 diff --git a/drivers/staging/rtl8723bs/include/rtw_ht.h b/drivers/staging/rtl8723bs/include/rtw_ht.h index 1527d8be2d7a..54fadb92334c 100644 --- a/drivers/staging/rtl8723bs/include/rtw_ht.h +++ b/drivers/staging/rtl8723bs/include/rtw_ht.h @@ -63,43 +63,21 @@ enum { #define LDPC_HT_ENABLE_RX BIT0 #define LDPC_HT_ENABLE_TX BIT1 -#define LDPC_HT_TEST_TX_ENABLE BIT2 #define LDPC_HT_CAP_TX BIT3 #define STBC_HT_ENABLE_RX BIT0 #define STBC_HT_ENABLE_TX BIT1 -#define STBC_HT_TEST_TX_ENABLE BIT2 #define STBC_HT_CAP_TX BIT3 #define BEAMFORMING_HT_BEAMFORMER_ENABLE BIT0 /* Declare our NIC supports beamformer */ #define BEAMFORMING_HT_BEAMFORMEE_ENABLE BIT1 /* Declare our NIC supports beamformee */ -#define BEAMFORMING_HT_BEAMFORMER_TEST BIT2 /* Transmiting Beamforming no matter the target supports it or not */ - -/* */ -/* The HT Control field */ -/* */ -#define SET_HT_CTRL_CSI_STEERING(_pEleStart, _val) SET_BITS_TO_LE_1BYTE((_pEleStart)+2, 6, 2, _val) -#define SET_HT_CTRL_NDP_ANNOUNCEMENT(_pEleStart, _val) SET_BITS_TO_LE_1BYTE((_pEleStart)+3, 0, 1, _val) -#define GET_HT_CTRL_NDP_ANNOUNCEMENT(_pEleStart) LE_BITS_TO_1BYTE((_pEleStart)+3, 0, 1) /* 20/40 BSS Coexist */ #define SET_EXT_CAPABILITY_ELE_BSS_COEXIST(_pEleStart, _val) SET_BITS_TO_LE_1BYTE((_pEleStart), 0, 1, _val) -#define GET_EXT_CAPABILITY_ELE_BSS_COEXIST(_pEleStart) LE_BITS_TO_1BYTE((_pEleStart), 0, 1) - #define GET_HT_CAPABILITY_ELE_LDPC_CAP(_pEleStart) LE_BITS_TO_1BYTE(_pEleStart, 0, 1) #define GET_HT_CAPABILITY_ELE_TX_STBC(_pEleStart) LE_BITS_TO_1BYTE(_pEleStart, 7, 1) #define GET_HT_CAPABILITY_ELE_RX_STBC(_pEleStart) LE_BITS_TO_1BYTE((_pEleStart)+1, 0, 2) -/* TXBF Capabilities */ -#define SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(_pEleStart, _val) SET_BITS_TO_LE_4BYTE(((u8 *)(_pEleStart))+21, 3, 1, ((u8)_val)) -#define SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(_pEleStart, _val) SET_BITS_TO_LE_4BYTE(((u8 *)(_pEleStart))+21, 4, 1, ((u8)_val)) -#define SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(_pEleStart, _val) SET_BITS_TO_LE_4BYTE(((u8 *)(_pEleStart))+21, 10, 1, ((u8)_val)) -#define SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(_pEleStart, _val) SET_BITS_TO_LE_4BYTE(((u8 *)(_pEleStart))+21, 15, 2, ((u8)_val)) -#define SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(_pEleStart, _val) SET_BITS_TO_LE_4BYTE(((u8 *)(_pEleStart))+21, 23, 2, ((u8)_val)) - -#define GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(_pEleStart) LE_BITS_TO_4BYTE((_pEleStart)+21, 10, 1) -#define GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(_pEleStart) LE_BITS_TO_4BYTE((_pEleStart)+21, 15, 2) - #endif /* _RTL871X_HT_H_ */ diff --git a/drivers/staging/rtl8723bs/include/rtw_io.h b/drivers/staging/rtl8723bs/include/rtw_io.h index e98083a07a66..be9741a056e5 100644 --- a/drivers/staging/rtl8723bs/include/rtw_io.h +++ b/drivers/staging/rtl8723bs/include/rtw_io.h @@ -8,70 +8,13 @@ #ifndef _RTW_IO_H_ #define _RTW_IO_H_ -#define NUM_IOREQ 8 - -#define MAX_PROT_SZ (64-16) - -#define _IOREADY 0 -#define _IO_WAIT_COMPLETE 1 -#define _IO_WAIT_RSP 2 - -/* IO COMMAND TYPE */ -#define _IOSZ_MASK_ (0x7F) -#define _IO_WRITE_ BIT(7) -#define _IO_FIXED_ BIT(8) -#define _IO_BURST_ BIT(9) -#define _IO_BYTE_ BIT(10) -#define _IO_HW_ BIT(11) -#define _IO_WORD_ BIT(12) -#define _IO_SYNC_ BIT(13) -#define _IO_CMDMASK_ (0x1F80) - - /* For prompt mode accessing, caller shall free io_req Otherwise, io_handler will free io_req */ - - -/* IO STATUS TYPE */ -#define _IO_ERR_ BIT(2) -#define _IO_SUCCESS_ BIT(1) -#define _IO_DONE_ BIT(0) - - -#define IO_RD32 (_IO_SYNC_ | _IO_WORD_) -#define IO_RD16 (_IO_SYNC_ | _IO_HW_) -#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_) - -#define IO_RD32_ASYNC (_IO_WORD_) -#define IO_RD16_ASYNC (_IO_HW_) -#define IO_RD8_ASYNC (_IO_BYTE_) - -#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_) -#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_) -#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_) - -#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_) -#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_) -#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_) - -/* - - Only Sync. burst accessing is provided. - -*/ - -#define IO_WR_BURST(x) (_IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_)) -#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_)) - - - /* below is for the intf_option bit defition... */ -#define _INTF_ASYNC_ BIT(0) /* support async io */ - struct intf_priv; struct intf_hdl; struct io_queue; diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index fc0b43d38d9a..e103c4a15d1a 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -26,7 +26,6 @@ #define WIFI_NULL_STATE 0x00000000 #define WIFI_ASOC_STATE 0x00000001 /* Under Linked state... */ -#define WIFI_REASOC_STATE 0x00000002 #define WIFI_SLEEP_STATE 0x00000004 #define WIFI_STATION_STATE 0x00000008 #define WIFI_AP_STATE 0x00000010 @@ -35,34 +34,11 @@ #define WIFI_UNDER_LINKING 0x00000080 #define WIFI_UNDER_WPS 0x00000100 -/* define WIFI_UNDER_CMD 0x00000200 */ -/* define WIFI_UNDER_P2P 0x00000400 */ #define WIFI_STA_ALIVE_CHK_STATE 0x00000400 #define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station is under site surveying */ -#ifdef WDS -#define WIFI_WDS 0x00001000 -#define WIFI_WDS_RX_BEACON 0x00002000 /* already rx WDS AP beacon */ -#endif -#ifdef AUTO_CONFIG -#define WIFI_AUTOCONF 0x00004000 -#define WIFI_AUTOCONF_IND 0x00008000 -#endif - -/** -* ========== P2P Section Start =============== -#define WIFI_P2P_LISTEN_STATE 0x00010000 -#define WIFI_P2P_GROUP_FORMATION_STATE 0x00020000 - ========== P2P Section End =============== -*/ /* ifdef UNDER_MPTEST */ #define WIFI_MP_STATE 0x00010000 -#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continuous tx background */ -#define WIFI_MP_CTX_ST 0x00040000 /* in continuous tx with single-tone */ -#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continuous tx background due to out of skb */ -#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx */ -#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continuous tx with carrier suppression */ -#define WIFI_MP_LPBK_STATE 0x00400000 /* endif */ /* define _FW_UNDER_CMD WIFI_UNDER_CMD */ @@ -94,8 +70,6 @@ enum { GHZ_MAX, }; -#define rtw_band_valid(band) ((band) >= GHZ24_50 && (band) < GHZ_MAX) - /* there are several "locks" in mlme_priv, @@ -115,10 +89,6 @@ MUST always be first lock xmit_priv.lock and then call any queue functions which take __queue.lock. */ - -#define traffic_threshold 10 -#define traffic_scan_period 500 - struct sitesurvey_ctrl { u64 last_tx_pkts; uint last_rx_pkts; @@ -141,139 +111,6 @@ struct rt_link_detect_t { u32 LowPowerTransitionCount; }; -struct profile_info { - u8 ssidlen; - u8 ssid[WLAN_SSID_MAXLEN]; - u8 peermac[ETH_ALEN]; -}; - -struct tx_invite_req_info { - u8 token; - u8 benable; - u8 go_ssid[WLAN_SSID_MAXLEN]; - u8 ssidlen; - u8 go_bssid[ETH_ALEN]; - u8 peer_macaddr[ETH_ALEN]; - u8 operating_ch; /* This information will be set by using the p2p_set op_ch =x */ - u8 peer_ch; /* The listen channel for peer P2P device */ - -}; - -struct tx_invite_resp_info { - u8 token; /* Used to record the dialog token of p2p invitation request frame. */ -}; - -struct tx_provdisc_req_info { - u16 wps_config_method_request; /* Used when sending the provisioning request frame */ - u16 peer_channel_num[2]; /* The channel number which the receiver stands. */ - struct ndis_802_11_ssid ssid; - u8 peerDevAddr[ETH_ALEN]; /* Peer device address */ - u8 peerIFAddr[ETH_ALEN]; /* Peer interface address */ - u8 benable; /* This provision discovery request frame is trigger to send or not */ -}; - -struct rx_provdisc_req_info { /* When peer device issue prov_disc_req first, we should store the following information */ - u8 peerDevAddr[ETH_ALEN]; /* Peer device address */ - u8 strconfig_method_desc_of_prov_disc_req[4]; /* description for the config method located in the provisioning discovery request frame. */ - /* The UI must know this information to know which config method the remote p2p device is requiring. */ -}; - -struct tx_nego_req_info { - u16 peer_channel_num[2]; /* The channel number which the receiver stands. */ - u8 peerDevAddr[ETH_ALEN]; /* Peer device address */ - u8 benable; /* This negotiation request frame is trigger to send or not */ -}; - -struct group_id_info { - u8 go_device_addr[ETH_ALEN]; /* The GO's device address of this P2P group */ - u8 ssid[WLAN_SSID_MAXLEN]; /* The SSID of this P2P group */ -}; - -struct scan_limit_info { - u8 scan_op_ch_only; /* When this flag is set, the driver should just scan the operation channel */ - u8 operation_ch[2]; /* Store the operation channel of invitation request frame */ -}; - -struct wifidirect_info { - struct adapter *padapter; - struct timer_list find_phase_timer; - struct timer_list restore_p2p_state_timer; - - /* Used to do the scanning. After confirming the peer is availalble, the driver transmits the P2P frame to peer. */ - struct timer_list pre_tx_scan_timer; - struct timer_list reset_ch_sitesurvey; - struct timer_list reset_ch_sitesurvey2; /* Just for resetting the scan limit function by using p2p nego */ - struct tx_provdisc_req_info tx_prov_disc_info; - struct rx_provdisc_req_info rx_prov_disc_info; - struct tx_invite_req_info invitereq_info; - struct profile_info profileinfo[P2P_MAX_PERSISTENT_GROUP_NUM]; /* Store the profile information of persistent group */ - struct tx_invite_resp_info inviteresp_info; - struct tx_nego_req_info nego_req_info; - struct group_id_info groupid_info; /* Store the group id information when doing the group negotiation handshake. */ - struct scan_limit_info rx_invitereq_info; /* Used for get the limit scan channel from the Invitation procedure */ - struct scan_limit_info p2p_info; /* Used for get the limit scan channel from the P2P negotiation handshake */ - enum p2p_role role; - enum p2p_state pre_p2p_state; - enum p2p_state p2p_state; - u8 device_addr[ETH_ALEN]; /* The device address should be the mac address of this device. */ - u8 interface_addr[ETH_ALEN]; - u8 social_chan[4]; - u8 listen_channel; - u8 operating_channel; - u8 listen_dwell; /* This value should be between 1 and 3 */ - u8 support_rate[8]; - u8 p2p_wildcard_ssid[P2P_WILDCARD_SSID_LEN]; - u8 intent; /* should only include the intent value. */ - u8 p2p_peer_interface_addr[ETH_ALEN]; - u8 p2p_peer_device_addr[ETH_ALEN]; - u8 peer_intent; /* Included the intent value and tie breaker value. */ - u8 device_name[WPS_MAX_DEVICE_NAME_LEN]; /* Device name for displaying on searching device screen */ - u8 device_name_len; - u8 profileindex; /* Used to point to the index of profileinfo array */ - u8 peer_operating_ch; - u8 find_phase_state_exchange_cnt; - u16 device_password_id_for_nego; /* The device password ID for group negotiation */ - u8 negotiation_dialog_token; - u8 nego_ssid[WLAN_SSID_MAXLEN]; /* SSID information for group negotiation */ - u8 nego_ssidlen; - u8 p2p_group_ssid[WLAN_SSID_MAXLEN]; - u8 p2p_group_ssid_len; - u8 persistent_supported; /* Flag to know the persistent function should be supported or not. */ - /* In the Sigma test, the Sigma will provide this enable from the sta_set_p2p CAPI. */ - /* 0: disable */ - /* 1: enable */ - u8 session_available; /* Flag to set the WFD session available to enable or disable "by Sigma" */ - /* In the Sigma test, the Sigma will disable the session available by using the sta_preset CAPI. */ - /* 0: disable */ - /* 1: enable */ - - u8 wfd_tdls_enable; /* Flag to enable or disable the TDLS by WFD Sigma */ - /* 0: disable */ - /* 1: enable */ - u8 wfd_tdls_weaksec; /* Flag to enable or disable the weak security function for TDLS by WFD Sigma */ - /* 0: disable */ - /* In this case, the driver can't issue the tdsl setup request frame. */ - /* 1: enable */ - /* In this case, the driver can issue the tdls setup request frame */ - /* even the current security is weak security. */ - - enum p2p_wpsinfo ui_got_wps_info; /* This field will store the WPS value (PIN value or PBC) that UI had got from the user. */ - u16 supported_wps_cm; /* This field describes the WPS config method which this driver supported. */ - /* The value should be the combination of config method defined in page104 of WPS v2.0 spec. */ - u8 external_uuid; /* UUID flag */ - u8 uuid[16]; /* UUID */ - uint channel_list_attr_len; /* This field will contain the length of body of P2P Channel List attribute of group negotitation response frame. */ - u8 channel_list_attr[100]; /* This field will contain the body of P2P Channel List attribute of group negotitation response frame. */ - /* We will use the channel_cnt and channel_list fields when constructing the group negotitation confirm frame. */ - u8 driver_interface; /* Indicate DRIVER_WEXT or DRIVER_CFG80211 */ -}; - -struct tdls_ss_record { /* signal strength record */ - u8 macaddr[ETH_ALEN]; - u8 rx_pwd_ba11; - u8 is_tdls_sta; /* true: direct link sta, false: else */ -}; - /* used for mlme_priv.roam_flags */ enum { RTW_ROAM_ON_EXPIRED = BIT0, @@ -408,11 +245,6 @@ struct mlme_priv { unsigned long timeBcnInfoChkStart; }; -#define rtw_mlme_set_auto_scan_int(adapter, ms) \ - do { \ - adapter->mlmepriv.auto_scan_int_ms = ms; \ - while (0) - void rtw_mlme_reset_auto_scan_int(struct adapter *adapter); struct hostapd_priv { @@ -556,20 +388,6 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 fea #define rtw_roam_flags(adapter) ((adapter)->mlmepriv.roam_flags) #define rtw_chk_roam_flags(adapter, flags) ((adapter)->mlmepriv.roam_flags & flags) -#define rtw_clr_roam_flags(adapter, flags) \ - do { \ - ((adapter)->mlmepriv.roam_flags &= ~flags); \ - } while (0) - -#define rtw_set_roam_flags(adapter, flags) \ - do { \ - ((adapter)->mlmepriv.roam_flags |= flags); \ - } while (0) - -#define rtw_assign_roam_flags(adapter, flags) \ - do { \ - ((adapter)->mlmepriv.roam_flags = flags); \ - } while (0) void _rtw_roaming(struct adapter *adapter, struct wlan_network *tgt_network); void rtw_roaming(struct adapter *adapter, struct wlan_network *tgt_network); diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 65e138a5238f..5b8574f5a251 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -20,50 +20,18 @@ /* define DISCONNECT_TO (3000) */ #define ADDBA_TO (2000) -#define LINKED_TO (1) /* unit:2 sec, 1x2 =2 sec */ - #define REAUTH_LIMIT (4) #define REASSOC_LIMIT (4) -#define READDBA_LIMIT (2) - -#define ROAMING_LIMIT 8 -/* define IOCMD_REG0 0x10250370 */ -/* define IOCMD_REG1 0x10250374 */ -/* define IOCMD_REG2 0x10250378 */ - -/* define FW_DYNAMIC_FUN_SWITCH 0x10250364 */ - -/* define WRITE_BB_CMD 0xF0000001 */ -/* define SET_CHANNEL_CMD 0xF3000000 */ -/* define UPDATE_RA_CMD 0xFD0000A2 */ #define DYNAMIC_FUNC_DISABLE (0x0) /* ====== ODM_ABILITY_E ======== */ /* BB ODM section BIT 0-15 */ #define DYNAMIC_BB_DIG BIT0 /* ODM_BB_DIG */ -#define DYNAMIC_BB_RA_MASK BIT1 /* ODM_BB_RA_MASK */ #define DYNAMIC_BB_DYNAMIC_TXPWR BIT2 /* ODM_BB_DYNAMIC_TXPWR */ -#define DYNAMIC_BB_BB_FA_CNT BIT3 /* ODM_BB_FA_CNT */ -#define DYNAMIC_BB_RSSI_MONITOR BIT4 /* ODM_BB_RSSI_MONITOR */ -#define DYNAMIC_BB_CCK_PD BIT5 /* ODM_BB_CCK_PD */ #define DYNAMIC_BB_ANT_DIV BIT6 /* ODM_BB_ANT_DIV */ -#define DYNAMIC_BB_PWR_SAVE BIT7 /* ODM_BB_PWR_SAVE */ -#define DYNAMIC_BB_PWR_TRAIN BIT8 /* ODM_BB_PWR_TRAIN */ -#define DYNAMIC_BB_RATE_ADAPTIVE BIT9 /* ODM_BB_RATE_ADAPTIVE */ -#define DYNAMIC_BB_PATH_DIV BIT10/* ODM_BB_PATH_DIV */ -#define DYNAMIC_BB_PSD BIT11/* ODM_BB_PSD */ -#define DYNAMIC_BB_RXHP BIT12/* ODM_BB_RXHP */ -#define DYNAMIC_BB_ADAPTIVITY BIT13/* ODM_BB_ADAPTIVITY */ -#define DYNAMIC_BB_DYNAMIC_ATC BIT14/* ODM_BB_DYNAMIC_ATC */ - -/* MAC DM section BIT 16-23 */ -#define DYNAMIC_MAC_EDCA_TURBO BIT16/* ODM_MAC_EDCA_TURBO */ -#define DYNAMIC_MAC_EARLY_MODE BIT17/* ODM_MAC_EARLY_MODE */ /* RF ODM section BIT 24-31 */ -#define DYNAMIC_RF_TX_PWR_TRACK BIT24/* ODM_RF_TX_PWR_TRACK */ -#define DYNAMIC_RF_RX_GAIN_TRACK BIT25/* ODM_RF_RX_GAIN_TRACK */ #define DYNAMIC_RF_CALIBRATION BIT26/* ODM_RF_CALIBRATION */ #define DYNAMIC_ALL_FUNC_ENABLE 0xFFFFFFF @@ -91,11 +59,6 @@ MCS rate definitions *********************************************************/ #define MCS_RATE_1R (0x000000ff) -#define MCS_RATE_2R (0x0000ffff) -#define MCS_RATE_3R (0x00ffffff) -#define MCS_RATE_4R (0xffffffff) -#define MCS_RATE_2R_13TO15_OFF (0x00001fff) - extern unsigned char RTW_WPA_OUI[]; extern unsigned char WMM_OUI[]; diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h index ea3abee325ef..f94bb18479da 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mp.h +++ b/drivers/staging/rtl8723bs/include/rtw_mp.h @@ -8,7 +8,6 @@ #define _RTW_MP_H_ #define MAX_MP_XMITBUF_SZ 2048 -#define NR_MP_XMITFRAME 8 struct mp_xmit_frame { struct list_head list; @@ -151,12 +150,6 @@ struct mpt_context { }; /* endif */ -/* E-Fuse */ -#define EFUSE_MAP_SIZE 512 - -#define EFUSE_MAX_SIZE 512 -/* end of E-Fuse */ - /* define RTPRIV_IOCTL_MP (SIOCIWFIRSTPRIV + 0x17) */ enum { WRITE_REG = 1, @@ -259,33 +252,11 @@ struct mp_priv { u8 *TXradomBuffer; }; -#define LOWER true -#define RAISE false - /* Hardware Registers */ -#define BB_REG_BASE_ADDR 0x800 - -#define MAX_RF_PATH_NUMS RF_PATH_MAX - extern u8 mpdatarate[NumRates]; #define MAX_TX_PWR_INDEX_N_MODE 64 /* 0x3F */ -#define RX_PKT_BROADCAST 1 -#define RX_PKT_DEST_ADDR 2 -#define RX_PKT_PHY_MATCH 3 - -#define Mac_OFDM_OK 0x00000000 -#define Mac_OFDM_Fail 0x10000000 -#define Mac_OFDM_FasleAlarm 0x20000000 -#define Mac_CCK_OK 0x30000000 -#define Mac_CCK_Fail 0x40000000 -#define Mac_CCK_FasleAlarm 0x50000000 -#define Mac_HT_OK 0x60000000 -#define Mac_HT_Fail 0x70000000 -#define Mac_HT_FasleAlarm 0x90000000 -#define Mac_DropPacket 0xA0000000 - #define REG_RF_BB_GAIN_OFFSET 0x7f #define RF_GAIN_OFFSET_MASK 0xfffff diff --git a/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h b/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h index 0767dbb84199..c27d07861b8c 100644 --- a/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8723bs/include/rtw_pwrctrl.h @@ -9,25 +9,8 @@ #include -#define FW_PWR0 0 -#define FW_PWR1 1 -#define FW_PWR2 2 -#define FW_PWR3 3 - - -#define HW_PWR0 7 -#define HW_PWR1 6 -#define HW_PWR2 2 -#define HW_PWR3 0 -#define HW_PWR4 8 - -#define FW_PWRMSK 0x7 - - #define XMIT_ALIVE BIT(0) -#define RECV_ALIVE BIT(1) #define CMD_ALIVE BIT(2) -#define EVT_ALIVE BIT(3) #define BTCOEX_ALIVE BIT(4) @@ -58,31 +41,17 @@ enum { #define PS_ALL_ON BIT(2) #define PS_ST_ACTIVE BIT(3) -#define PS_ISR_ENABLE BIT(4) -#define PS_IMR_ENABLE BIT(5) #define PS_ACK BIT(6) #define PS_TOGGLE BIT(7) #define PS_STATE_MASK (0x0F) -#define PS_STATE_HW_MASK (0x07) -#define PS_SEQ_MASK (0xc0) #define PS_STATE(x) (PS_STATE_MASK & (x)) -#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x)) -#define PS_SEQ(x) (PS_SEQ_MASK & (x)) #define PS_STATE_S0 (PS_DPS) -#define PS_STATE_S1 (PS_LCLK) #define PS_STATE_S2 (PS_RF_OFF) -#define PS_STATE_S3 (PS_ALL_ON) #define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON)) - -#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON)) -#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE)) -#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) - - struct reportpwrstate_parm { unsigned char mode; unsigned char state; /* the CPWM value */ @@ -91,10 +60,6 @@ struct reportpwrstate_parm { #define LPS_DELAY_TIME (1 * HZ) /* 1 sec */ -#define EXE_PWR_NONE 0x01 -#define EXE_PWR_IPS 0x02 -#define EXE_PWR_LPS 0x04 - /* RF state. */ enum rt_rf_power_state { rf_on, /* RF is on after RFSleep or RFOff */ @@ -247,9 +212,6 @@ struct pwrctrl_priv { _set_timer(&(pwrctl)->pwr_state_check_timer, (ms)); \ } while (0) -#define rtw_set_pwr_state_check_timer(pwrctl) \ - _rtw_set_pwr_state_check_timer((pwrctl), (pwrctl)->pwr_state_check_interval) - extern void rtw_init_pwrctrl_priv(struct adapter *adapter); extern void rtw_free_pwrctrl_priv(struct adapter *adapter); diff --git a/drivers/staging/rtl8723bs/include/rtw_recv.h b/drivers/staging/rtl8723bs/include/rtw_recv.h index fef2fd0e8c84..c93594f75436 100644 --- a/drivers/staging/rtl8723bs/include/rtw_recv.h +++ b/drivers/staging/rtl8723bs/include/rtw_recv.h @@ -9,8 +9,6 @@ #define NR_RECVBUFF (8) -#define NR_PREALLOC_RECV_SKB (8) - #define NR_RECVFRAME 256 #define RXFRAME_ALIGN 8 @@ -18,21 +16,11 @@ #define DRVINFO_SZ 4 /* unit is 8bytes */ -#define MAX_RXFRAME_CNT 512 #define MAX_RX_NUMBLKS (32) #define RECVFRAME_HDR_ALIGN 128 - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 - - #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 -#define RX_MAX_QUEUE 2 - #define MAX_SUBFRAME_COUNT 64 #define LLC_HEADER_LENGTH 6 @@ -178,7 +166,6 @@ struct rx_pkt_attrib { #define RECVBUFF_ALIGN_SZ 8 #define RXDESC_SIZE 24 -#define RXDESC_OFFSET RXDESC_SIZE struct recv_stat { __le32 rxdw0; @@ -191,8 +178,6 @@ struct recv_stat { #endif /* if BUF_DESC_ARCH is defined, rx_buf_desc occupy 4 double words */ }; -#define EOR BIT(30) - /* accesser of recv_priv: rtw_recv_entry(dispatch / passive level); recv_thread(passive) ; returnpkt(dispatch) ; halt(passive) ; @@ -363,7 +348,6 @@ extern union recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue); extern union recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue); /* get a free recv_frame from pfree_recv_queue */ extern int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue); -#define rtw_dequeue_recvframe(queue) rtw_alloc_recvframe(queue) extern int _rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue); extern int rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue); diff --git a/drivers/staging/rtl8723bs/include/rtw_security.h b/drivers/staging/rtl8723bs/include/rtw_security.h index 7587fa888527..98afbd3054a4 100644 --- a/drivers/staging/rtl8723bs/include/rtw_security.h +++ b/drivers/staging/rtl8723bs/include/rtw_security.h @@ -22,14 +22,9 @@ const char *security_type_str(u8 value); -#define SHA256_MAC_LEN 32 #define AES_BLOCK_SIZE 16 #define AES_PRIV_SIZE (4 * 44) -#define RTW_KEK_LEN 16 -#define RTW_KCK_LEN 16 -#define RTW_REPLAY_CTR_LEN 8 - enum { ENCRYP_PROTOCOL_OPENSYS, /* open system */ ENCRYP_PROTOCOL_WEP, /* WEP */ diff --git a/drivers/staging/rtl8723bs/include/rtw_xmit.h b/drivers/staging/rtl8723bs/include/rtw_xmit.h index 676ead0372fa..a3b4310caddf 100644 --- a/drivers/staging/rtl8723bs/include/rtw_xmit.h +++ b/drivers/staging/rtl8723bs/include/rtw_xmit.h @@ -35,7 +35,6 @@ #define BCN_QUEUE_INX 4 #define MGT_QUEUE_INX 5 #define HIGH_QUEUE_INX 6 -#define TXCMD_QUEUE_INX 7 #define HW_QUEUE_ENTRY 8 @@ -192,16 +191,7 @@ struct pkt_attrib { #define NULL_FRAMETAG (0x0) #define DATA_FRAMETAG 0x01 -#define L2_FRAMETAG 0x02 #define MGNT_FRAMETAG 0x03 -#define AMSDU_FRAMETAG 0x04 - -#define EII_FRAMETAG 0x05 -#define IEEE8023_FRAMETAG 0x06 - -#define MP_FRAMETAG 0x07 - -#define TXAGG_FRAMETAG 0x08 enum { XMITBUF_DATA = 0, diff --git a/drivers/staging/rtl8723bs/include/sdio_hal.h b/drivers/staging/rtl8723bs/include/sdio_hal.h index 6fae19dd0cbd..024acf9b530d 100644 --- a/drivers/staging/rtl8723bs/include/sdio_hal.h +++ b/drivers/staging/rtl8723bs/include/sdio_hal.h @@ -7,10 +7,6 @@ #ifndef __SDIO_HAL_H__ #define __SDIO_HAL_H__ - -extern u8 sd_hal_bus_init(struct adapter *padapter); -extern u8 sd_hal_bus_deinit(struct adapter *padapter); - u8 sd_int_isr(struct adapter *padapter); void sd_int_dpc(struct adapter *padapter); void rtw_set_hal_ops(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/include/sdio_osintf.h b/drivers/staging/rtl8723bs/include/sdio_osintf.h deleted file mode 100644 index 146b44f95e29..000000000000 --- a/drivers/staging/rtl8723bs/include/sdio_osintf.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __SDIO_OSINTF_H__ -#define __SDIO_OSINTF_H__ - - - -u8 sd_hal_bus_init(struct adapter *padapter); -u8 sd_hal_bus_deinit(struct adapter *padapter); -void sd_c2h_hdl(struct adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723bs/include/sta_info.h b/drivers/staging/rtl8723bs/include/sta_info.h index 1ea3fe22b99a..b3535fed3de7 100644 --- a/drivers/staging/rtl8723bs/include/sta_info.h +++ b/drivers/staging/rtl8723bs/include/sta_info.h @@ -222,53 +222,24 @@ struct sta_info { + sta->sta_stats.rx_ctrl_pkts \ + sta->sta_stats.rx_data_pkts) -#define sta_last_rx_pkts(sta) \ - (sta->sta_stats.last_rx_mgnt_pkts \ - + sta->sta_stats.last_rx_ctrl_pkts \ - + sta->sta_stats.last_rx_data_pkts) - #define sta_rx_data_pkts(sta) \ (sta->sta_stats.rx_data_pkts) #define sta_last_rx_data_pkts(sta) \ (sta->sta_stats.last_rx_data_pkts) -#define sta_rx_mgnt_pkts(sta) \ - (sta->sta_stats.rx_mgnt_pkts) - -#define sta_last_rx_mgnt_pkts(sta) \ - (sta->sta_stats.last_rx_mgnt_pkts) - #define sta_rx_beacon_pkts(sta) \ (sta->sta_stats.rx_beacon_pkts) #define sta_last_rx_beacon_pkts(sta) \ (sta->sta_stats.last_rx_beacon_pkts) -#define sta_rx_probereq_pkts(sta) \ - (sta->sta_stats.rx_probereq_pkts) - -#define sta_last_rx_probereq_pkts(sta) \ - (sta->sta_stats.last_rx_probereq_pkts) - #define sta_rx_probersp_pkts(sta) \ (sta->sta_stats.rx_probersp_pkts) #define sta_last_rx_probersp_pkts(sta) \ (sta->sta_stats.last_rx_probersp_pkts) -#define sta_rx_probersp_bm_pkts(sta) \ - (sta->sta_stats.rx_probersp_bm_pkts) - -#define sta_last_rx_probersp_bm_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_bm_pkts) - -#define sta_rx_probersp_uo_pkts(sta) \ - (sta->sta_stats.rx_probersp_uo_pkts) - -#define sta_last_rx_probersp_uo_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_uo_pkts) - #define sta_update_last_rx_pkts(sta) \ do { \ sta->sta_stats.last_rx_mgnt_pkts = sta->sta_stats.rx_mgnt_pkts; \ @@ -281,21 +252,6 @@ struct sta_info { sta->sta_stats.last_rx_data_pkts = sta->sta_stats.rx_data_pkts; \ } while (0) -#define STA_RX_PKTS_ARG(sta) \ - sta->sta_stats.rx_mgnt_pkts \ - , sta->sta_stats.rx_ctrl_pkts \ - , sta->sta_stats.rx_data_pkts - -#define STA_LAST_RX_PKTS_ARG(sta) \ - sta->sta_stats.last_rx_mgnt_pkts \ - , sta->sta_stats.last_rx_ctrl_pkts \ - , sta->sta_stats.last_rx_data_pkts - -#define STA_RX_PKTS_DIFF_ARG(sta) \ - sta->sta_stats.rx_mgnt_pkts - sta->sta_stats.last_rx_mgnt_pkts \ - , sta->sta_stats.rx_ctrl_pkts - sta->sta_stats.last_rx_ctrl_pkts \ - , sta->sta_stats.rx_data_pkts - sta->sta_stats.last_rx_data_pkts - #define STA_PKTS_FMT "(m:%llu, c:%llu, d:%llu)" struct sta_priv { diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h index 53f9411fcc4c..230b2c4ffd3b 100644 --- a/drivers/staging/rtl8723bs/include/wifi.h +++ b/drivers/staging/rtl8723bs/include/wifi.h @@ -7,30 +7,11 @@ #ifndef _WIFI_H_ #define _WIFI_H_ -#define WLAN_ETHHDR_LEN 14 -#define WLAN_ETHADDR_LEN 6 -#define WLAN_IEEE_OUI_LEN 3 -#define WLAN_ADDR_LEN 6 -#define WLAN_CRC_LEN 4 -#define WLAN_BSSID_LEN 6 -#define WLAN_BSS_TS_LEN 8 #define WLAN_HDR_A3_LEN 24 -#define WLAN_HDR_A4_LEN 30 #define WLAN_HDR_A3_QOS_LEN 26 -#define WLAN_HDR_A4_QOS_LEN 32 -#define WLAN_SSID_MAXLEN 32 -#define WLAN_DATA_MAXLEN 2312 -#define WLAN_A3_PN_OFFSET 24 -#define WLAN_A4_PN_OFFSET 30 - -#define WLAN_MIN_ETHFRM_LEN 60 -#define WLAN_MAX_ETHFRM_LEN 1514 -#define WLAN_ETHHDR_LEN 14 #define WLAN_WMM_LEN 24 -#define P80211CAPTURE_VERSION 0x80211001 - /* This value is tested by WiFi 11n Test Plan 5.2.3. */ /* This test verifies the WLAN NIC can update the NAV through sending the CTS with large duration. */ #define WiFiNavUpperUs 30000 /* 30 ms */ @@ -164,9 +145,6 @@ enum { #define GetFragNum(pbuf) \ (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) & 0x0f) -#define GetTupleCache(pbuf) \ - (cpu_to_le16(*(unsigned short *)((size_t)(pbuf) + 22))) - #define SetFragNum(pbuf, num) \ do { \ *(unsigned short *)((size_t)(pbuf) + 22) = \ @@ -305,27 +283,13 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) /*----------------------------------------------------------------------------- Below is for the security related definition ------------------------------------------------------------------------------*/ -#define _RESERVED_FRAME_TYPE_ 0 -#define _SKB_FRAME_TYPE_ 2 -#define _PRE_ALLOCMEM_ 1 -#define _PRE_ALLOCHDR_ 3 -#define _PRE_ALLOCLLCHDR_ 4 -#define _PRE_ALLOCICVHDR_ 5 -#define _PRE_ALLOCMICHDR_ 6 - -#define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */ -#define _CRCLNG_ 4 #define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */ -#define _ASOCRSP_IE_OFFSET_ 6 #define _REASOCREQ_IE_OFFSET_ 10 -#define _REASOCRSP_IE_OFFSET_ 6 #define _PROBEREQ_IE_OFFSET_ 0 #define _PROBERSP_IE_OFFSET_ 12 #define _AUTH_IE_OFFSET_ 6 -#define _DEAUTH_IE_OFFSET_ 0 #define _BEACON_IE_OFFSET_ 12 -#define _PUBLIC_ACTION_IE_OFFSET_ 8 #define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_ @@ -336,20 +300,11 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) #define _AUTH_SEQ_NUM_ 2 #define _BEACON_ITERVAL_ 2 #define _CAPABILITY_ 2 -#define _CURRENT_APADDR_ 6 -#define _LISTEN_INTERVAL_ 2 #define _RSON_CODE_ 2 #define _ASOC_ID_ 2 #define _STATUS_CODE_ 2 #define _TIMESTAMP_ 8 -#define AUTH_ODD_TO 0 -#define AUTH_EVEN_TO 1 - -#define WLAN_ETHCONV_ENCAP 1 -#define WLAN_ETHCONV_RFC1042 2 -#define WLAN_ETHCONV_8021h 3 - /*----------------------------------------------------------------------------- Below is the definition for 802.11i / 802.1x ------------------------------------------------------------------------------*/ @@ -361,18 +316,10 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) Below is the definition for WMM ------------------------------------------------------------------------------*/ #define _WMM_IE_Length_ 7 /* for WMM STA */ -#define _WMM_Para_Element_Length_ 24 - /*----------------------------------------------------------------------------- Below is the definition for 802.11n ------------------------------------------------------------------------------*/ - -#define SetOrderBit(pbuf) \ - do { \ - *(unsigned short *)(pbuf) |= cpu_to_le16(_ORDER_); \ - } while (0) - #define GetOrderBit(pbuf) (((*(unsigned short *)(pbuf)) & cpu_to_le16(_ORDER_)) != 0) #define ACT_CAT_VENDOR 0x7F/* 127 */ @@ -440,244 +387,20 @@ struct ADDBA_request { #define IEEE80211_HT_CAP_SGI_40 0x0040 #define IEEE80211_HT_CAP_TX_STBC 0x0080 #define IEEE80211_HT_CAP_RX_STBC_1R 0x0100 -#define IEEE80211_HT_CAP_RX_STBC_2R 0x0200 #define IEEE80211_HT_CAP_RX_STBC_3R 0x0300 -#define IEEE80211_HT_CAP_DELAY_BA 0x0400 #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 /* 802.11n HT capability AMPDU settings */ #define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03 #define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C -/* 802.11n HT capability MSC set */ -#define IEEE80211_SUPP_MCS_SET_UEQM 4 -#define IEEE80211_HT_CAP_MAX_STREAMS 4 -#define IEEE80211_SUPP_MCS_SET_LEN 10 -/* maximum streams the spec allows */ -#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01 -#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02 -#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C -#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10 -/* 802.11n HT capability TXBF capability */ -#define IEEE80211_HT_CAP_TXBF_RX_NDP 0x00000008 -#define IEEE80211_HT_CAP_TXBF_TX_NDP 0x00000010 -#define IEEE80211_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP 0x00000400 /* endif */ /* ===============WPS Section =============== */ -/* For WPSv1.0 */ -#define WPSOUI 0x0050f204 /* WPS attribute ID */ -#define WPS_ATTR_VER1 0x104A -#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044 -#define WPS_ATTR_RESP_TYPE 0x103B -#define WPS_ATTR_UUID_E 0x1047 -#define WPS_ATTR_MANUFACTURER 0x1021 -#define WPS_ATTR_MODEL_NAME 0x1023 -#define WPS_ATTR_MODEL_NUMBER 0x1024 -#define WPS_ATTR_SERIAL_NUMBER 0x1042 -#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054 -#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055 -#define WPS_ATTR_DEVICE_NAME 0x1011 -#define WPS_ATTR_CONF_METHOD 0x1008 -#define WPS_ATTR_RF_BANDS 0x103C -#define WPS_ATTR_DEVICE_PWID 0x1012 -#define WPS_ATTR_REQUEST_TYPE 0x103A -#define WPS_ATTR_ASSOCIATION_STATE 0x1002 -#define WPS_ATTR_CONFIG_ERROR 0x1009 -#define WPS_ATTR_VENDOR_EXT 0x1049 #define WPS_ATTR_SELECTED_REGISTRAR 0x1041 -/* Value of WPS attribute "WPS_ATTR_DEVICE_NAME */ -#define WPS_MAX_DEVICE_NAME_LEN 32 - -/* Value of WPS Request Type Attribute */ -#define WPS_REQ_TYPE_ENROLLEE_INFO_ONLY 0x00 -#define WPS_REQ_TYPE_ENROLLEE_OPEN_8021X 0x01 -#define WPS_REQ_TYPE_REGISTRAR 0x02 -#define WPS_REQ_TYPE_WLAN_MANAGER_REGISTRAR 0x03 - -/* Value of WPS Response Type Attribute */ -#define WPS_RESPONSE_TYPE_INFO_ONLY 0x00 -#define WPS_RESPONSE_TYPE_8021X 0x01 -#define WPS_RESPONSE_TYPE_REGISTRAR 0x02 -#define WPS_RESPONSE_TYPE_AP 0x03 - -/* Value of WPS WiFi Simple Configuration State Attribute */ -#define WPS_WSC_STATE_NOT_CONFIG 0x01 -#define WPS_WSC_STATE_CONFIG 0x02 - -/* Value of WPS Version Attribute */ -#define WPS_VERSION_1 0x10 - -/* Value of WPS Configuration Method Attribute */ -#define WPS_CONFIG_METHOD_FLASH 0x0001 -#define WPS_CONFIG_METHOD_ETHERNET 0x0002 -#define WPS_CONFIG_METHOD_LABEL 0x0004 -#define WPS_CONFIG_METHOD_DISPLAY 0x0008 -#define WPS_CONFIG_METHOD_E_NFC 0x0010 -#define WPS_CONFIG_METHOD_I_NFC 0x0020 -#define WPS_CONFIG_METHOD_NFC 0x0040 -#define WPS_CONFIG_METHOD_PBC 0x0080 -#define WPS_CONFIG_METHOD_KEYPAD 0x0100 -#define WPS_CONFIG_METHOD_VPBC 0x0280 -#define WPS_CONFIG_METHOD_PPBC 0x0480 -#define WPS_CONFIG_METHOD_VDISPLAY 0x2008 -#define WPS_CONFIG_METHOD_PDISPLAY 0x4008 - -/* Value of Category ID of WPS Primary Device Type Attribute */ -#define WPS_PDT_CID_DISPLAYS 0x0007 -#define WPS_PDT_CID_MULIT_MEDIA 0x0008 -#define WPS_PDT_CID_RTK_WIDI WPS_PDT_CID_MULIT_MEDIA - -/* Value of Sub Category ID of WPS Primary Device Type Attribute */ -#define WPS_PDT_SCID_MEDIA_SERVER 0x0005 -#define WPS_PDT_SCID_RTK_DMP WPS_PDT_SCID_MEDIA_SERVER - -/* Value of Device Password ID */ -#define WPS_DPID_PIN 0x0000 -#define WPS_DPID_USER_SPEC 0x0001 -#define WPS_DPID_MACHINE_SPEC 0x0002 -#define WPS_DPID_REKEY 0x0003 -#define WPS_DPID_PBC 0x0004 -#define WPS_DPID_REGISTRAR_SPEC 0x0005 - -/* Value of WPS RF Bands Attribute */ -#define WPS_RF_BANDS_2_4_GHZ 0x01 -#define WPS_RF_BANDS_5_GHZ 0x02 - -/* Value of WPS Association State Attribute */ -#define WPS_ASSOC_STATE_NOT_ASSOCIATED 0x00 -#define WPS_ASSOC_STATE_CONNECTION_SUCCESS 0x01 -#define WPS_ASSOC_STATE_CONFIGURATION_FAILURE 0x02 -#define WPS_ASSOC_STATE_ASSOCIATION_FAILURE 0x03 -#define WPS_ASSOC_STATE_IP_FAILURE 0x04 - /* =====================P2P Section ===================== */ -/* For P2P */ -#define P2POUI 0x506F9A09 - -/* P2P Attribute ID */ -#define P2P_ATTR_STATUS 0x00 -#define P2P_ATTR_MINOR_REASON_CODE 0x01 -#define P2P_ATTR_CAPABILITY 0x02 -#define P2P_ATTR_DEVICE_ID 0x03 -#define P2P_ATTR_GO_INTENT 0x04 -#define P2P_ATTR_CONF_TIMEOUT 0x05 -#define P2P_ATTR_LISTEN_CH 0x06 -#define P2P_ATTR_GROUP_BSSID 0x07 -#define P2P_ATTR_EX_LISTEN_TIMING 0x08 -#define P2P_ATTR_INTENTED_IF_ADDR 0x09 -#define P2P_ATTR_MANAGEABILITY 0x0A -#define P2P_ATTR_CH_LIST 0x0B -#define P2P_ATTR_NOA 0x0C -#define P2P_ATTR_DEVICE_INFO 0x0D -#define P2P_ATTR_GROUP_INFO 0x0E -#define P2P_ATTR_GROUP_ID 0x0F -#define P2P_ATTR_INTERFACE 0x10 -#define P2P_ATTR_OPERATING_CH 0x11 -#define P2P_ATTR_INVITATION_FLAGS 0x12 - -/* Value of Status Attribute */ -#define P2P_STATUS_SUCCESS 0x00 -#define P2P_STATUS_FAIL_INFO_UNAVAILABLE 0x01 -#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 0x02 -#define P2P_STATUS_FAIL_LIMIT_REACHED 0x03 -#define P2P_STATUS_FAIL_INVALID_PARAM 0x04 -#define P2P_STATUS_FAIL_REQUEST_UNABLE 0x05 -#define P2P_STATUS_FAIL_PREVOUS_PROTO_ERR 0x06 -#define P2P_STATUS_FAIL_NO_COMMON_CH 0x07 -#define P2P_STATUS_FAIL_UNKNOWN_P2PGROUP 0x08 -#define P2P_STATUS_FAIL_BOTH_GOINTENT_15 0x09 -#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVSION 0x0A -#define P2P_STATUS_FAIL_USER_REJECT 0x0B - -/* Value of Invitation Flags Attribute */ -#define P2P_INVITATION_FLAGS_PERSISTENT BIT(0) - -#define DMP_P2P_DEVCAP_SUPPORT (P2P_DEVCAP_SERVICE_DISCOVERY | \ - P2P_DEVCAP_CLIENT_DISCOVERABILITY | \ - P2P_DEVCAP_CONCURRENT_OPERATION | \ - P2P_DEVCAP_INVITATION_PROC) - -#define DMP_P2P_GRPCAP_SUPPORT (P2P_GRPCAP_INTRABSS) - -/* Value of Device Capability Bitmap */ -#define P2P_DEVCAP_SERVICE_DISCOVERY BIT(0) -#define P2P_DEVCAP_CLIENT_DISCOVERABILITY BIT(1) -#define P2P_DEVCAP_CONCURRENT_OPERATION BIT(2) -#define P2P_DEVCAP_INFRA_MANAGED BIT(3) -#define P2P_DEVCAP_DEVICE_LIMIT BIT(4) -#define P2P_DEVCAP_INVITATION_PROC BIT(5) - -/* Value of Group Capability Bitmap */ -#define P2P_GRPCAP_GO BIT(0) -#define P2P_GRPCAP_PERSISTENT_GROUP BIT(1) -#define P2P_GRPCAP_GROUP_LIMIT BIT(2) -#define P2P_GRPCAP_INTRABSS BIT(3) -#define P2P_GRPCAP_CROSS_CONN BIT(4) -#define P2P_GRPCAP_PERSISTENT_RECONN BIT(5) -#define P2P_GRPCAP_GROUP_FORMATION BIT(6) - -/* P2P Public Action Frame (Management Frame) */ -#define P2P_PUB_ACTION_ACTION 0x09 - -/* P2P Public Action Frame Type */ -#define P2P_GO_NEGO_REQ 0 -#define P2P_GO_NEGO_RESP 1 -#define P2P_GO_NEGO_CONF 2 -#define P2P_INVIT_REQ 3 -#define P2P_INVIT_RESP 4 -#define P2P_DEVDISC_REQ 5 -#define P2P_DEVDISC_RESP 6 -#define P2P_PROVISION_DISC_REQ 7 -#define P2P_PROVISION_DISC_RESP 8 - -/* P2P Action Frame Type */ -#define P2P_NOTICE_OF_ABSENCE 0 -#define P2P_PRESENCE_REQUEST 1 -#define P2P_PRESENCE_RESPONSE 2 -#define P2P_GO_DISC_REQUEST 3 - - -#define P2P_MAX_PERSISTENT_GROUP_NUM 10 - -#define P2P_PROVISIONING_SCAN_CNT 3 - -#define P2P_WILDCARD_SSID_LEN 7 - -#define P2P_FINDPHASE_EX_NONE 0 /* default value, used when: (1)p2p disabled or (2)p2p enabled but only do 1 scan phase */ -#define P2P_FINDPHASE_EX_FULL 1 /* used when p2p enabled and want to do 1 scan phase and P2P_FINDPHASE_EX_MAX-1 find phase */ -#define P2P_FINDPHASE_EX_SOCIAL_FIRST (P2P_FINDPHASE_EX_FULL+1) -#define P2P_FINDPHASE_EX_MAX 4 -#define P2P_FINDPHASE_EX_SOCIAL_LAST P2P_FINDPHASE_EX_MAX - -#define P2P_PROVISION_TIMEOUT 5000 /* 5 seconds timeout for sending the provision discovery request */ -#define P2P_CONCURRENT_PROVISION_TIMEOUT 3000 /* 3 seconds timeout for sending the provision discovery request under concurrent mode */ -#define P2P_GO_NEGO_TIMEOUT 5000 /* 5 seconds timeout for receiving the group negotiation response */ -#define P2P_CONCURRENT_GO_NEGO_TIMEOUT 3000 /* 3 seconds timeout for sending the negotiation request under concurrent mode */ -#define P2P_TX_PRESCAN_TIMEOUT 100 /* 100ms */ -#define P2P_INVITE_TIMEOUT 5000 /* 5 seconds timeout for sending the invitation request */ -#define P2P_CONCURRENT_INVITE_TIMEOUT 3000 /* 3 seconds timeout for sending the invitation request under concurrent mode */ -#define P2P_RESET_SCAN_CH 25000 /* 25 seconds timeout to reset the scan channel (based on channel plan) */ -#define P2P_MAX_INTENT 15 - -#define P2P_MAX_NOA_NUM 2 - -/* WPS Configuration Method */ -#define WPS_CM_NONE 0x0000 -#define WPS_CM_LABEL 0x0004 -#define WPS_CM_DISPLYA 0x0008 -#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010 -#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020 -#define WPS_CM_NFC_INTERFACE 0x0040 -#define WPS_CM_PUSH_BUTTON 0x0080 -#define WPS_CM_KEYPAD 0x0100 -#define WPS_CM_SW_PUHS_BUTTON 0x0280 -#define WPS_CM_HW_PUHS_BUTTON 0x0480 -#define WPS_CM_SW_DISPLAY_PIN 0x2008 -#define WPS_CM_LCD_DISPLAY_PIN 0x4008 - enum p2p_role { P2P_ROLE_DISABLE = 0, P2P_ROLE_DEVICE = 1, @@ -718,28 +441,6 @@ enum p2p_wpsinfo { P2P_GOT_WPSINFO_PBC = 3, }; -#define P2P_PRIVATE_IOCTL_SET_LEN 64 - -/* =====================WFD Section ===================== */ -/* For Wi-Fi Display */ -#define WFD_ATTR_DEVICE_INFO 0x00 -#define WFD_ATTR_ASSOC_BSSID 0x01 -#define WFD_ATTR_COUPLED_SINK_INFO 0x06 -#define WFD_ATTR_LOCAL_IP_ADDR 0x08 -#define WFD_ATTR_SESSION_INFO 0x09 -#define WFD_ATTR_ALTER_MAC 0x0a - -/* For WFD Device Information Attribute */ -#define WFD_DEVINFO_SOURCE 0x0000 -#define WFD_DEVINFO_PSINK 0x0001 -#define WFD_DEVINFO_SSINK 0x0002 -#define WFD_DEVINFO_DUAL 0x0003 - -#define WFD_DEVINFO_SESSION_AVAIL 0x0010 -#define WFD_DEVINFO_WSD 0x0040 -#define WFD_DEVINFO_PC_TDLS 0x0080 -#define WFD_DEVINFO_HDCP_SUPPORT 0x0100 - #define IP_MCAST_MAC(mac) ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x5e)) #define ICMPV6_MCAST_MAC(mac) ((mac[0] == 0x33) && (mac[1] == 0x33) && (mac[2] != 0xff)) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 3fe27ee75b47..eb3c73cc2662 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -2549,9 +2549,7 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, bool ack = true; u8 tx_ch = (u8)ieee80211_frequency_to_channel(chan->center_freq); u8 category, action; - int type = (-1); struct adapter *padapter; - struct rtw_wdev_priv *pwdev_priv; if (!ndev) { ret = -EINVAL; @@ -2559,7 +2557,6 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, } padapter = rtw_netdev_priv(ndev); - pwdev_priv = adapter_wdev_data(padapter); /* cookie generation */ *cookie = (unsigned long)buf; @@ -2581,19 +2578,6 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len); } while (dump_cnt < dump_limit && tx_ret != _SUCCESS); - switch (type) { - case P2P_GO_NEGO_CONF: - rtw_clear_scan_deny(padapter); - break; - case P2P_INVIT_RESP: - if (pwdev_priv->invit_info.flags & BIT(0) && pwdev_priv->invit_info.status == 0) { - rtw_set_scan_deny(padapter, 5000); - rtw_pwr_wakeup_ex(padapter, 5000); - rtw_clear_scan_deny(padapter); - } - break; - } - cancel_ps_deny: rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX); exit: @@ -2602,7 +2586,6 @@ exit: static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band) { -#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ #define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ ht_cap->ht_supported = true; diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index b3599ec6293a..deec33f63bcf 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -591,7 +591,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) static void stop_streaming(struct vb2_queue *vq) { int ret; - unsigned long timeout; + unsigned long time_left; struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vq); struct vchiq_mmal_port *port = dev->capture.port; @@ -636,9 +636,9 @@ static void stop_streaming(struct vb2_queue *vq) v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n", __func__, atomic_read(&port->buffers_with_vpu)); - timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt, - HZ); - if (timeout == 0) { + time_left = wait_for_completion_timeout(&dev->capture.frame_cmplt, + HZ); + if (time_left == 0) { v4l2_err(&dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n", __func__, atomic_read(&port->buffers_with_vpu)); diff --git a/drivers/staging/vc04_services/interface/TESTING b/drivers/staging/vc04_services/interface/TESTING index a6d63efcbcb9..273952dc9d85 100644 --- a/drivers/staging/vc04_services/interface/TESTING +++ b/drivers/staging/vc04_services/interface/TESTING @@ -31,7 +31,7 @@ Here are the most common kernel configurations: 3. BCM2837 target SoC (ARM 64 bit) - Use the defconfig as a base and then enable all VCHIQ options. + Use the defconfig which has most of the VCHIQ options enabled. * Scenarios @@ -80,3 +80,46 @@ Here are the most common kernel configurations: vchi ping (size 0, 100 async, 100 oneway) -> infus vchi ping (size 0, 200 async, 0 oneway) -> infus ... + + * Debugfs test + + Command: cat /sys/kernel/debug/vchiq/state + + Example output: + State 0: CONNECTED + tx_pos=0x1e8(@43b0acda), rx_pos=0x170(@05493af8) + Version: 8 (min 3) + Stats: ctrl_tx_count=7, ctrl_rx_count=7, error_count=0 + Slots: 30 available (29 data), 0 recyclable, 0 stalls (0 data) + Platform: 2835 (VC master) + Local: slots 34-64 tx_pos=0x1e8 recycle=0x1f + Slots claimed: + DEBUG: SLOT_HANDLER_COUNT = 20(0x14) + DEBUG: SLOT_HANDLER_LINE = 1937(0x791) + DEBUG: PARSE_LINE = 1864(0x748) + DEBUG: PARSE_HEADER = -249155224(0xf1263168) + DEBUG: PARSE_MSGID = 67362817(0x403e001) + DEBUG: AWAIT_COMPLETION_LINE = 0(0x0) + DEBUG: DEQUEUE_MESSAGE_LINE = 0(0x0) + DEBUG: SERVICE_CALLBACK_LINE = 0(0x0) + DEBUG: MSG_QUEUE_FULL_COUNT = 0(0x0) + DEBUG: COMPLETION_QUEUE_FULL_COUNT = 0(0x0) + Remote: slots 2-32 tx_pos=0x170 recycle=0x1f + Slots claimed: + 2: 10/9 + DEBUG: SLOT_HANDLER_COUNT = 20(0x14) + DEBUG: SLOT_HANDLER_LINE = 1851(0x73b) + DEBUG: PARSE_LINE = 1827(0x723) + DEBUG: PARSE_HEADER = -150330912(0xf70a21e0) + DEBUG: PARSE_MSGID = 67113022(0x400103e) + DEBUG: AWAIT_COMPLETION_LINE = 0(0x0) + DEBUG: DEQUEUE_MESSAGE_LINE = 0(0x0) + DEBUG: SERVICE_CALLBACK_LINE = 0(0x0) + DEBUG: MSG_QUEUE_FULL_COUNT = 0(0x0) + DEBUG: COMPLETION_QUEUE_FULL_COUNT = 0(0x0) + Service 0: LISTENING (ref 1) 'PEEK little-endian (0x4b454550)' remote n/a (msg use 0/3840, slot use 0/15) + Bulk: tx_pending=0 (size 0), rx_pending=0 (size 0) + Ctrl: tx_count=0, tx_bytes=0, rx_count=0, rx_bytes=0 + Bulk: tx_count=0, tx_bytes=0, rx_count=0, rx_bytes=0 + 0 quota stalls, 0 slot stalls, 0 bulk stalls, 0 aborted, 0 errors + instance b511f60b diff --git a/drivers/staging/vc04_services/interface/TODO b/drivers/staging/vc04_services/interface/TODO index 05f129c0c254..dfb1ee49633f 100644 --- a/drivers/staging/vc04_services/interface/TODO +++ b/drivers/staging/vc04_services/interface/TODO @@ -16,13 +16,6 @@ some of the ones we want: to manage these buffers as dmabufs so that we can zero-copy import camera images into vc4 for rendering/display. -* Fix kernel module support - -Even the VPU firmware doesn't support a VCHI re-connect, the driver -should properly handle a module unload. This also includes that all -resources must be freed (kthreads, debugfs entries, ...) and global -variables avoided. - * Documentation A short top-down description of this driver's architecture (function of diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 5f518e5a9273..c4d97dbf6ba8 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -109,11 +109,6 @@ struct vchiq_arm_state { int first_connect; }; -struct vchiq_2835_state { - int inited; - struct vchiq_arm_state arm_state; -}; - struct vchiq_pagelist_info { struct pagelist *pagelist; size_t pagelist_buffer_size; @@ -167,7 +162,7 @@ cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info } static inline bool -is_adjacent_block(u32 *addrs, u32 addr, unsigned int k) +is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k) { u32 tmp; @@ -382,8 +377,8 @@ create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf, /* Combine adjacent blocks for performance */ k = 0; for_each_sg(scatterlist, sg, dma_buffers, i) { - u32 len = sg_dma_len(sg); - u32 addr = sg_dma_address(sg); + unsigned int len = sg_dma_len(sg); + dma_addr_t addr = sg_dma_address(sg); /* Note: addrs is the address + page_count - 1 * The firmware expects blocks after the first to be page- @@ -593,49 +588,32 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state return 0; } -static void -vchiq_arm_init_state(struct vchiq_state *state, - struct vchiq_arm_state *arm_state) -{ - if (arm_state) { - rwlock_init(&arm_state->susp_res_lock); - - init_completion(&arm_state->ka_evt); - atomic_set(&arm_state->ka_use_count, 0); - atomic_set(&arm_state->ka_use_ack_count, 0); - atomic_set(&arm_state->ka_release_count, 0); - - arm_state->state = state; - arm_state->first_connect = 0; - } -} - int vchiq_platform_init_state(struct vchiq_state *state) { - struct vchiq_2835_state *platform_state; + struct vchiq_arm_state *platform_state; - state->platform_state = kzalloc(sizeof(*platform_state), GFP_KERNEL); - if (!state->platform_state) + platform_state = kzalloc(sizeof(*platform_state), GFP_KERNEL); + if (!platform_state) return -ENOMEM; - platform_state = (struct vchiq_2835_state *)state->platform_state; + rwlock_init(&platform_state->susp_res_lock); - platform_state->inited = 1; - vchiq_arm_init_state(state, &platform_state->arm_state); + init_completion(&platform_state->ka_evt); + atomic_set(&platform_state->ka_use_count, 0); + atomic_set(&platform_state->ka_use_ack_count, 0); + atomic_set(&platform_state->ka_release_count, 0); + + platform_state->state = state; + + state->platform_state = (struct opaque_platform_state *)platform_state; return 0; } static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state) { - struct vchiq_2835_state *platform_state; - - platform_state = (struct vchiq_2835_state *)state->platform_state; - - WARN_ON_ONCE(!platform_state->inited); - - return &platform_state->arm_state; + return (struct vchiq_arm_state *)state->platform_state; } void @@ -758,8 +736,8 @@ void free_bulk_waiter(struct vchiq_instance *instance) int vchiq_shutdown(struct vchiq_instance *instance) { - int status = 0; struct vchiq_state *state = instance->state; + int ret = 0; if (mutex_lock_killable(&state->mutex)) return -EAGAIN; @@ -769,12 +747,12 @@ int vchiq_shutdown(struct vchiq_instance *instance) mutex_unlock(&state->mutex); - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, status); + dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); free_bulk_waiter(instance); kfree(instance); - return status; + return ret; } EXPORT_SYMBOL(vchiq_shutdown); @@ -785,26 +763,26 @@ static int vchiq_is_connected(struct vchiq_instance *instance) int vchiq_connect(struct vchiq_instance *instance) { - int status; struct vchiq_state *state = instance->state; + int ret; if (mutex_lock_killable(&state->mutex)) { dev_dbg(state->dev, "core: call to mutex_lock failed\n"); - status = -EAGAIN; + ret = -EAGAIN; goto failed; } - status = vchiq_connect_internal(state, instance); + ret = vchiq_connect_internal(state, instance); - if (!status) + if (!ret) instance->connected = 1; mutex_unlock(&state->mutex); failed: - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, status); + dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - return status; + return ret; } EXPORT_SYMBOL(vchiq_connect); @@ -813,10 +791,9 @@ vchiq_add_service(struct vchiq_instance *instance, const struct vchiq_service_params_kernel *params, unsigned int *phandle) { - int status; struct vchiq_state *state = instance->state; struct vchiq_service *service = NULL; - int srvstate; + int srvstate, ret; *phandle = VCHIQ_SERVICE_HANDLE_INVALID; @@ -828,14 +805,14 @@ vchiq_add_service(struct vchiq_instance *instance, if (service) { *phandle = service->handle; - status = 0; + ret = 0; } else { - status = -EINVAL; + ret = -EINVAL; } - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, status); + dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - return status; + return ret; } int @@ -843,9 +820,9 @@ vchiq_open_service(struct vchiq_instance *instance, const struct vchiq_service_params_kernel *params, unsigned int *phandle) { - int status = -EINVAL; struct vchiq_state *state = instance->state; struct vchiq_service *service = NULL; + int ret = -EINVAL; *phandle = VCHIQ_SERVICE_HANDLE_INVALID; @@ -856,17 +833,17 @@ vchiq_open_service(struct vchiq_instance *instance, if (service) { *phandle = service->handle; - status = vchiq_open_service_internal(service, current->pid); - if (status) { + ret = vchiq_open_service_internal(service, current->pid); + if (ret) { vchiq_remove_service(instance, service->handle); *phandle = VCHIQ_SERVICE_HANDLE_INVALID; } } failed: - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, status); + dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - return status; + return ret; } EXPORT_SYMBOL(vchiq_open_service); @@ -874,20 +851,20 @@ int vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int handle, const void *data, unsigned int size, void *userdata, enum vchiq_bulk_mode mode) { - int status; + int ret; while (1) { switch (mode) { case VCHIQ_BULK_MODE_NOCALLBACK: case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(instance, handle, - (void *)data, NULL, - size, userdata, mode, - VCHIQ_BULK_TRANSMIT); + ret = vchiq_bulk_transfer(instance, handle, + (void *)data, NULL, + size, userdata, mode, + VCHIQ_BULK_TRANSMIT); break; case VCHIQ_BULK_MODE_BLOCKING: - status = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size, - VCHIQ_BULK_TRANSMIT); + ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size, + VCHIQ_BULK_TRANSMIT); break; default: return -EINVAL; @@ -898,13 +875,13 @@ vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int handle, const * to implement a retry mechanism since this function is * supposed to block until queued */ - if (status != -EAGAIN) + if (ret != -EAGAIN) break; msleep(1); } - return status; + return ret; } EXPORT_SYMBOL(vchiq_bulk_transmit); @@ -912,19 +889,19 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle, void *data, unsigned int size, void *userdata, enum vchiq_bulk_mode mode) { - int status; + int ret; while (1) { switch (mode) { case VCHIQ_BULK_MODE_NOCALLBACK: case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(instance, handle, data, NULL, - size, userdata, - mode, VCHIQ_BULK_RECEIVE); + ret = vchiq_bulk_transfer(instance, handle, data, NULL, + size, userdata, + mode, VCHIQ_BULK_RECEIVE); break; case VCHIQ_BULK_MODE_BLOCKING: - status = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size, - VCHIQ_BULK_RECEIVE); + ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size, + VCHIQ_BULK_RECEIVE); break; default: return -EINVAL; @@ -935,13 +912,13 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle, * to implement a retry mechanism since this function is * supposed to block until queued */ - if (status != -EAGAIN) + if (ret != -EAGAIN) break; msleep(1); } - return status; + return ret; } EXPORT_SYMBOL(vchiq_bulk_receive); @@ -950,8 +927,8 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl unsigned int size, enum vchiq_bulk_dir dir) { struct vchiq_service *service; - int status; struct bulk_waiter_node *waiter = NULL, *iter; + int ret; service = find_service_by_handle(instance, handle); if (!service) @@ -991,10 +968,10 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl return -ENOMEM; } - status = vchiq_bulk_transfer(instance, handle, data, NULL, size, - &waiter->bulk_waiter, - VCHIQ_BULK_MODE_BLOCKING, dir); - if ((status != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { + ret = vchiq_bulk_transfer(instance, handle, data, NULL, size, + &waiter->bulk_waiter, + VCHIQ_BULK_MODE_BLOCKING, dir); + if ((ret != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; if (bulk) { @@ -1013,7 +990,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl waiter, current->pid); } - return status; + return ret; } static int @@ -1078,6 +1055,43 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, return 0; } +static int +service_single_message(struct vchiq_instance *instance, + enum vchiq_reason reason, + struct vchiq_service *service, void *bulk_userdata) +{ + struct user_service *user_service; + + user_service = (struct user_service *)service->base.userdata; + + dev_dbg(service->state->dev, "arm: msg queue full\n"); + /* + * If there is no MESSAGE_AVAILABLE in the completion + * queue, add one + */ + if ((user_service->message_available_pos - + instance->completion_remove) < 0) { + int ret; + + dev_dbg(instance->state->dev, + "arm: Inserting extra MESSAGE_AVAILABLE\n"); + ret = add_completion(instance, reason, NULL, user_service, + bulk_userdata); + if (ret) + return ret; + } + + if (wait_for_completion_interruptible(&user_service->remove_event)) { + dev_dbg(instance->state->dev, "arm: interrupted\n"); + return -EAGAIN; + } else if (instance->closing) { + dev_dbg(instance->state->dev, "arm: closing\n"); + return -EINVAL; + } + + return 0; +} + int service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, struct vchiq_header *header, unsigned int handle, void *bulk_userdata) @@ -1127,41 +1141,18 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, spin_lock(&service->state->msg_queue_spinlock); while (user_service->msg_insert == (user_service->msg_remove + MSG_QUEUE_SIZE)) { + int ret; + spin_unlock(&service->state->msg_queue_spinlock); DEBUG_TRACE(SERVICE_CALLBACK_LINE); DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); - dev_dbg(service->state->dev, "arm: msg queue full\n"); - /* - * If there is no MESSAGE_AVAILABLE in the completion - * queue, add one - */ - if ((user_service->message_available_pos - - instance->completion_remove) < 0) { - int status; - dev_dbg(instance->state->dev, - "arm: Inserting extra MESSAGE_AVAILABLE\n"); - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - status = add_completion(instance, reason, NULL, user_service, - bulk_userdata); - if (status) { - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - vchiq_service_put(service); - return status; - } - } - - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - if (wait_for_completion_interruptible(&user_service->remove_event)) { - dev_dbg(instance->state->dev, "arm: interrupted\n"); + ret = service_single_message(instance, reason, + service, bulk_userdata); + if (ret) { DEBUG_TRACE(SERVICE_CALLBACK_LINE); vchiq_service_put(service); - return -EAGAIN; - } else if (instance->closing) { - dev_dbg(instance->state->dev, "arm: closing\n"); - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - vchiq_service_put(service); - return -EINVAL; + return ret; } DEBUG_TRACE(SERVICE_CALLBACK_LINE); spin_lock(&service->state->msg_queue_spinlock); @@ -1294,8 +1285,6 @@ vchiq_keepalive_thread_func(void *v) { struct vchiq_state *state = (struct vchiq_state *)v; struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - int status; struct vchiq_instance *instance; unsigned int ka_handle; int ret; @@ -1313,20 +1302,20 @@ vchiq_keepalive_thread_func(void *v) goto exit; } - status = vchiq_connect(instance); - if (status) { - dev_err(state->dev, "suspend: %s: vchiq_connect failed %d\n", __func__, status); + ret = vchiq_connect(instance); + if (ret) { + dev_err(state->dev, "suspend: %s: vchiq_connect failed %d\n", __func__, ret); goto shutdown; } - status = vchiq_add_service(instance, ¶ms, &ka_handle); - if (status) { + ret = vchiq_add_service(instance, ¶ms, &ka_handle); + if (ret) { dev_err(state->dev, "suspend: %s: vchiq_open_service failed %d\n", - __func__, status); + __func__, ret); goto shutdown; } - while (1) { + while (!kthread_should_stop()) { long rc = 0, uc = 0; if (wait_for_completion_interruptible(&arm_state->ka_evt)) { @@ -1348,17 +1337,17 @@ vchiq_keepalive_thread_func(void *v) */ while (uc--) { atomic_inc(&arm_state->ka_use_ack_count); - status = vchiq_use_service(instance, ka_handle); - if (status) { + ret = vchiq_use_service(instance, ka_handle); + if (ret) { dev_err(state->dev, "suspend: %s: vchiq_use_service error %d\n", - __func__, status); + __func__, ret); } } while (rc--) { - status = vchiq_release_service(instance, ka_handle); - if (status) { + ret = vchiq_release_service(instance, ka_handle); + if (ret) { dev_err(state->dev, "suspend: %s: vchiq_release_service error %d\n", - __func__, status); + __func__, ret); } } } @@ -1408,13 +1397,13 @@ vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, write_unlock_bh(&arm_state->susp_res_lock); if (!ret) { - int status = 0; + int ret = 0; long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); - while (ack_cnt && !status) { + while (ack_cnt && !ret) { /* Send the use notify to videocore */ - status = vchiq_send_remote_use_active(state); - if (!status) + ret = vchiq_send_remote_use_active(state); + if (!ret) ack_cnt--; else atomic_add(ack_cnt, &arm_state->ka_use_ack_count); @@ -1451,7 +1440,6 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) write_lock_bh(&arm_state->susp_res_lock); if (!arm_state->videocore_use_count || !(*entity_uc)) { - /* Don't use BUG_ON - don't allow user thread to crash kernel */ WARN_ON(!arm_state->videocore_use_count); WARN_ON(!(*entity_uc)); ret = -EINVAL; @@ -1730,7 +1718,7 @@ static int vchiq_probe(struct platform_device *pdev) struct device_node *fw_node; const struct vchiq_platform_info *info; struct vchiq_drv_mgmt *mgmt; - int err; + int ret; info = of_device_get_match_data(&pdev->dev); if (!info) @@ -1755,8 +1743,8 @@ static int vchiq_probe(struct platform_device *pdev) mgmt->info = info; platform_set_drvdata(pdev, mgmt); - err = vchiq_platform_init(pdev, &mgmt->state); - if (err) + ret = vchiq_platform_init(pdev, &mgmt->state); + if (ret) goto failed_platform_init; vchiq_debugfs_init(&mgmt->state); @@ -1768,8 +1756,8 @@ static int vchiq_probe(struct platform_device *pdev) * Simply exit on error since the function handles cleanup in * cases of failure. */ - err = vchiq_register_chrdev(&pdev->dev); - if (err) { + ret = vchiq_register_chrdev(&pdev->dev); + if (ret) { dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n"); goto error_exit; } @@ -1782,18 +1770,26 @@ static int vchiq_probe(struct platform_device *pdev) failed_platform_init: dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n"); error_exit: - return err; + return ret; } static void vchiq_remove(struct platform_device *pdev) { struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(&pdev->dev); + struct vchiq_arm_state *arm_state; vchiq_device_unregister(bcm2835_audio); vchiq_device_unregister(bcm2835_camera); vchiq_debugfs_deinit(); vchiq_deregister_chrdev(); + kthread_stop(mgmt->state.sync_thread); + kthread_stop(mgmt->state.recycle_thread); + kthread_stop(mgmt->state.slot_handler_thread); + + arm_state = vchiq_platform_get_arm_state(&mgmt->state); + kthread_stop(arm_state->ka_thread); + kfree(mgmt); } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h index fd1b9d3555ce..b402aac333d9 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -109,9 +109,6 @@ vchiq_release_service(struct vchiq_instance *instance, unsigned int handle); extern int vchiq_check_service(struct vchiq_service *service); -extern void -vchiq_dump_platform_use_state(struct vchiq_state *state); - extern void vchiq_dump_service_use_state(struct vchiq_state *state); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index df3af821f218..50af04b217f4 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -501,16 +501,21 @@ remote_event_create(wait_queue_head_t *wq, struct remote_event *event) * routines where switched to the "interruptible" family of functions, as the * former was deemed unjustified and the use "killable" set all VCHIQ's * threads in D state. + * + * Returns: 0 on success, a negative error code on failure */ static inline int remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) { + int ret = 0; + if (!event->fired) { event->armed = 1; dsb(sy); - if (wait_event_interruptible(*wq, event->fired)) { + ret = wait_event_interruptible(*wq, event->fired); + if (ret) { event->armed = 0; - return 0; + return ret; } event->armed = 0; /* Ensure that the peer sees that we are not waiting (armed == 0). */ @@ -518,7 +523,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) } event->fired = 0; - return 1; + return ret; } /* @@ -1140,6 +1145,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service, struct vchiq_header *header; ssize_t callback_result; int svc_fourcc; + int ret; local = state->local; @@ -1147,7 +1153,9 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service, mutex_lock_killable(&state->sync_mutex)) return -EAGAIN; - remote_event_wait(&state->sync_release_event, &local->sync_release); + ret = remote_event_wait(&state->sync_release_event, &local->sync_release); + if (ret) + return ret; /* Ensure that reads don't overtake the remote_event_wait. */ rmb(); @@ -1929,13 +1937,16 @@ slot_handler_func(void *v) { struct vchiq_state *state = v; struct vchiq_shared_state *local = state->local; + int ret; DEBUG_INITIALISE(local); - while (1) { + while (!kthread_should_stop()) { DEBUG_COUNT(SLOT_HANDLER_COUNT); DEBUG_TRACE(SLOT_HANDLER_LINE); - remote_event_wait(&state->trigger_event, &local->trigger); + ret = remote_event_wait(&state->trigger_event, &local->trigger); + if (ret) + return ret; /* Ensure that reads don't overtake the remote_event_wait. */ rmb(); @@ -1966,6 +1977,7 @@ recycle_func(void *v) struct vchiq_shared_state *local = state->local; u32 *found; size_t length; + int ret; length = sizeof(*found) * BITSET_SIZE(VCHIQ_MAX_SERVICES); @@ -1974,8 +1986,10 @@ recycle_func(void *v) if (!found) return -ENOMEM; - while (1) { - remote_event_wait(&state->recycle_event, &local->recycle); + while (!kthread_should_stop()) { + ret = remote_event_wait(&state->recycle_event, &local->recycle); + if (ret) + return ret; process_free_queue(state, found, length); } @@ -1992,14 +2006,17 @@ sync_func(void *v) (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, state->remote->slot_sync); int svc_fourcc; + int ret; - while (1) { + while (!kthread_should_stop()) { struct vchiq_service *service; int msgid, size; int type; unsigned int localport, remoteport; - remote_event_wait(&state->sync_trigger_event, &local->sync_trigger); + ret = remote_event_wait(&state->sync_trigger_event, &local->sync_trigger); + if (ret) + return ret; /* Ensure that reads don't overtake the remote_event_wait. */ rmb(); @@ -2163,14 +2180,12 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, s mutex_init(&state->slot_mutex); mutex_init(&state->recycle_mutex); mutex_init(&state->sync_mutex); - mutex_init(&state->bulk_transfer_mutex); spin_lock_init(&state->msg_queue_spinlock); spin_lock_init(&state->bulk_waiter_spinlock); spin_lock_init(&state->quota_spinlock); init_completion(&state->slot_available_event); - init_completion(&state->slot_remove_event); init_completion(&state->data_quota_event); state->slot_queue_available = 0; @@ -3372,7 +3387,7 @@ vchiq_dump_shared_state(struct seq_file *f, struct vchiq_state *state, }; int i; - seq_printf(f, " %s: slots %d-%d tx_pos=%x recycle=%x\n", + seq_printf(f, " %s: slots %d-%d tx_pos=0x%x recycle=0x%x\n", label, shared->slot_first, shared->slot_last, shared->tx_pos, shared->slot_queue_recycle); @@ -3388,7 +3403,7 @@ vchiq_dump_shared_state(struct seq_file *f, struct vchiq_state *state, } for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { - seq_printf(f, " DEBUG: %s = %d(%x)\n", + seq_printf(f, " DEBUG: %s = %d(0x%x)\n", debug_names[i], shared->debug[i], shared->debug[i]); } } @@ -3416,7 +3431,7 @@ vchiq_dump_service_state(struct seq_file *f, struct vchiq_service *service) if (service->public_fourcc != VCHIQ_FOURCC_INVALID) scnprintf(remoteport + len2, sizeof(remoteport) - len2, - " (client %x)", service->client_id); + " (client 0x%x)", service->client_id); } else { strscpy(remoteport, "n/a", sizeof(remoteport)); } @@ -3477,7 +3492,7 @@ void vchiq_dump_state(struct seq_file *f, struct vchiq_state *state) seq_printf(f, "State %d: %s\n", state->id, conn_state_names[state->conn_state]); - seq_printf(f, " tx_pos=%x(@%pK), rx_pos=%x(@%pK)\n", + seq_printf(f, " tx_pos=0x%x(@%pK), rx_pos=0x%x(@%pK)\n", state->local->tx_pos, state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK), state->rx_pos, diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 382ec08f6a14..77cc4d7ac077 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -347,8 +347,6 @@ struct vchiq_state { struct mutex sync_mutex; - struct mutex bulk_transfer_mutex; - spinlock_t msg_queue_spinlock; spinlock_t bulk_waiter_spinlock; @@ -393,8 +391,6 @@ struct vchiq_state { /* Signalled when a free slot becomes available. */ struct completion slot_available_event; - struct completion slot_remove_event; - /* Signalled when a free data slot becomes available. */ struct completion data_quota_event; @@ -548,8 +544,6 @@ int vchiq_platform_init_state(struct vchiq_state *state); int vchiq_check_service(struct vchiq_service *service); -void vchiq_on_remote_use_active(struct vchiq_state *state); - int vchiq_send_remote_use(struct vchiq_state *state); int vchiq_send_remote_use_active(struct vchiq_state *state); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c index 430f2ed2ccd3..9cd2a64dce5e 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c @@ -1324,7 +1324,7 @@ static struct miscdevice vchiq_miscdev = { * vchiq_register_chrdev - Register the char driver for vchiq * and create the necessary class and * device files in userspace. - * @parent The parent of the char device. + * @parent: The parent of the char device. * * Returns 0 on success else returns the error code. */ diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c index fca920d41e4f..67489c334f7b 100644 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c @@ -655,7 +655,7 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, { struct mmal_msg_context *msg_context; int ret; - unsigned long timeout; + unsigned long time_left; /* payload size must not cause message to exceed max size */ if (payload_len > @@ -693,9 +693,9 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, return ret; } - timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt, - SYNC_MSG_TIMEOUT * HZ); - if (timeout == 0) { + time_left = wait_for_completion_timeout(&msg_context->u.sync.cmplt, + SYNC_MSG_TIMEOUT * HZ); + if (time_left == 0) { pr_err("timed out waiting for sync completion\n"); ret = -ETIME; /* todo: what happens if the message arrives after aborting */ diff --git a/drivers/staging/vme_user/vme_user.c b/drivers/staging/vme_user/vme_user.c index 36183f923768..5829a4141561 100644 --- a/drivers/staging/vme_user/vme_user.c +++ b/drivers/staging/vme_user/vme_user.c @@ -106,6 +106,7 @@ static struct vme_dev *vme_user_bridge; /* Pointer to user device */ static const struct class vme_user_sysfs_class = { .name = DRIVER_NAME, }; + static const int type[VME_DEVS] = { MASTER_MINOR, MASTER_MINOR, MASTER_MINOR, MASTER_MINOR, SLAVE_MINOR, SLAVE_MINOR, diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO index e154b2f3b247..876cdccb6948 100644 --- a/drivers/staging/vt6656/TODO +++ b/drivers/staging/vt6656/TODO @@ -11,7 +11,6 @@ TODO: - switch to use LIB80211 - switch to use MAC80211 - use kernel coding style -- checkpatch.pl fixes - sparse fixes - integrate with drivers/net/wireless diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index 448fd2ec8f6e..0abdb69ee9f4 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -22,20 +22,25 @@ config USB4_DEBUGFS_WRITE bool "Enable write by debugfs to configuration spaces (DANGEROUS)" help Enables writing to device configuration registers through - debugfs interface. + debugfs interface. You can use tools such as Thunderbolt/USB4 + debugging tools to access these registers. For more + information see: + + https://github.com/intel/tbtools Only enable this if you know what you are doing! Never enable this for production systems or distro kernels. config USB4_DEBUGFS_MARGINING - bool "Expose receiver lane margining operations under USB4 ports (DANGEROUS)" + bool "Expose receiver lane margining operations under USB4 ports and retimers (DANGEROUS)" depends on DEBUG_FS depends on USB4_DEBUGFS_WRITE help - Enables hardware and software based receiver lane margining support - under each USB4 port. Used for electrical quality and robustness - validation during manufacturing. Should not be enabled by distro - kernels. + Enables hardware and software based receiver lane margining + support under each USB4 port and retimer, including retimers + on the other side of the cable. Used for electrical quality + and robustness validation during manufacturing. Should not be + enabled by distro kernels. config USB4_KUNIT_TEST bool "KUnit tests" if !KUNIT_ALL_TESTS diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c index 70b52aac3d97..11185cc1db92 100644 --- a/drivers/thunderbolt/debugfs.c +++ b/drivers/thunderbolt/debugfs.c @@ -7,6 +7,7 @@ * Mika Westerberg */ +#include #include #include #include @@ -33,6 +34,44 @@ #define COUNTER_SET_LEN 3 +/* Sideband registers and their sizes as defined in the USB4 spec */ +struct sb_reg { + unsigned int reg; + unsigned int size; +}; + +#define SB_MAX_SIZE 64 + +/* Sideband registers for router */ +static const struct sb_reg port_sb_regs[] = { + { USB4_SB_VENDOR_ID, 4 }, + { USB4_SB_PRODUCT_ID, 4 }, + { USB4_SB_DEBUG_CONF, 4 }, + { USB4_SB_DEBUG, 54 }, + { USB4_SB_LRD_TUNING, 4 }, + { USB4_SB_OPCODE, 4 }, + { USB4_SB_METADATA, 4 }, + { USB4_SB_LINK_CONF, 3 }, + { USB4_SB_GEN23_TXFFE, 4 }, + { USB4_SB_GEN4_TXFFE, 4 }, + { USB4_SB_VERSION, 4 }, + { USB4_SB_DATA, 64 }, +}; + +/* Sideband registers for retimer */ +static const struct sb_reg retimer_sb_regs[] = { + { USB4_SB_VENDOR_ID, 4 }, + { USB4_SB_PRODUCT_ID, 4 }, + { USB4_SB_FW_VERSION, 4 }, + { USB4_SB_LRD_TUNING, 4 }, + { USB4_SB_OPCODE, 4 }, + { USB4_SB_METADATA, 4 }, + { USB4_SB_GEN23_TXFFE, 4 }, + { USB4_SB_GEN4_TXFFE, 4 }, + { USB4_SB_VERSION, 4 }, + { USB4_SB_DATA, 64 }, +}; + #define DEBUGFS_ATTR(__space, __write) \ static int __space ## _open(struct inode *inode, struct file *file) \ { \ @@ -184,16 +223,167 @@ static ssize_t switch_regs_write(struct file *file, const char __user *user_buf, return regs_write(sw, NULL, user_buf, count, ppos); } + +static bool parse_sb_line(char **line, u8 *reg, u8 *data, size_t data_size, + size_t *bytes_read) +{ + char *field, *token; + int i; + + token = strsep(line, "\n"); + if (!token) + return false; + + /* Parse the register first */ + field = strsep(&token, " "); + if (!field) + return false; + if (kstrtou8(field, 0, reg)) + return false; + + /* Then the values for the register, up to data_size */ + for (i = 0; i < data_size; i++) { + field = strsep(&token, " "); + if (!field) + break; + if (kstrtou8(field, 0, &data[i])) + return false; + } + + *bytes_read = i; + return true; +} + +static ssize_t sb_regs_write(struct tb_port *port, const struct sb_reg *sb_regs, + size_t size, enum usb4_sb_target target, u8 index, + char *buf, size_t count, loff_t *ppos) +{ + u8 reg, data[SB_MAX_SIZE]; + size_t bytes_read; + char *line = buf; + + /* User did hardware changes behind the driver's back */ + add_taint(TAINT_USER, LOCKDEP_STILL_OK); + + /* + * For sideband registers we accept: + * reg b0 b1 b2...\n + * + * Here "reg" is the byte offset of the sideband register and "b0".. + * are the byte values. There can be less byte values than the register + * size. The leftovers will not be overwritten. + */ + while (parse_sb_line(&line, ®, data, ARRAY_SIZE(data), &bytes_read)) { + const struct sb_reg *sb_reg; + int ret; + + /* At least one byte must be passed */ + if (bytes_read < 1) + return -EINVAL; + + /* Find the register */ + sb_reg = NULL; + for (int i = 0; i < size; i++) { + if (sb_regs[i].reg == reg) { + sb_reg = &sb_regs[i]; + break; + } + } + + if (!sb_reg) + return -EINVAL; + + if (bytes_read > sb_regs->size) + return -E2BIG; + + ret = usb4_port_sb_write(port, target, index, sb_reg->reg, data, + bytes_read); + if (ret) + return ret; + } + + return 0; +} + +static ssize_t port_sb_regs_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct tb_port *port = s->private; + struct tb_switch *sw = port->sw; + struct tb *tb = sw->tb; + char *buf; + int ret; + + buf = validate_and_copy_from_user(user_buf, &count); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + pm_runtime_get_sync(&sw->dev); + + if (mutex_lock_interruptible(&tb->lock)) { + ret = -ERESTARTSYS; + goto out_rpm_put; + } + + ret = sb_regs_write(port, port_sb_regs, ARRAY_SIZE(port_sb_regs), + USB4_SB_TARGET_ROUTER, 0, buf, count, ppos); + + mutex_unlock(&tb->lock); +out_rpm_put: + pm_runtime_mark_last_busy(&sw->dev); + pm_runtime_put_autosuspend(&sw->dev); + + return ret < 0 ? ret : count; +} + +static ssize_t retimer_sb_regs_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct tb_retimer *rt = s->private; + struct tb *tb = rt->tb; + char *buf; + int ret; + + buf = validate_and_copy_from_user(user_buf, &count); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + pm_runtime_get_sync(&rt->dev); + + if (mutex_lock_interruptible(&tb->lock)) { + ret = -ERESTARTSYS; + goto out_rpm_put; + } + + ret = sb_regs_write(rt->port, retimer_sb_regs, ARRAY_SIZE(retimer_sb_regs), + USB4_SB_TARGET_RETIMER, rt->index, buf, count, ppos); + + mutex_unlock(&tb->lock); +out_rpm_put: + pm_runtime_mark_last_busy(&rt->dev); + pm_runtime_put_autosuspend(&rt->dev); + + return ret < 0 ? ret : count; +} #define DEBUGFS_MODE 0600 #else #define port_regs_write NULL #define switch_regs_write NULL +#define port_sb_regs_write NULL +#define retimer_sb_regs_write NULL #define DEBUGFS_MODE 0400 #endif #if IS_ENABLED(CONFIG_USB4_DEBUGFS_MARGINING) /** * struct tb_margining - Lane margining support + * @port: USB4 port through which the margining operations are run + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER + * @dev: Pointer to the device that is the target (USB4 port or retimer) * @caps: Port lane margining capabilities * @results: Last lane margining results * @lanes: %0, %1 or %7 (all) @@ -210,6 +400,10 @@ static ssize_t switch_regs_write(struct file *file, const char __user *user_buf, * right/high */ struct tb_margining { + struct tb_port *port; + enum usb4_sb_target target; + u8 index; + struct device *dev; u32 caps[2]; u32 results[2]; unsigned int lanes; @@ -225,37 +419,37 @@ struct tb_margining { bool right_high; }; -static bool supports_software(const struct usb4_port *usb4) +static bool supports_software(const struct tb_margining *margining) { - return usb4->margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW; + return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW; } -static bool supports_hardware(const struct usb4_port *usb4) +static bool supports_hardware(const struct tb_margining *margining) { - return usb4->margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW; + return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW; } -static bool both_lanes(const struct usb4_port *usb4) +static bool both_lanes(const struct tb_margining *margining) { - return usb4->margining->caps[0] & USB4_MARGIN_CAP_0_2_LANES; + return margining->caps[0] & USB4_MARGIN_CAP_0_2_LANES; } -static unsigned int independent_voltage_margins(const struct usb4_port *usb4) +static unsigned int +independent_voltage_margins(const struct tb_margining *margining) { - return (usb4->margining->caps[0] & USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK) >> - USB4_MARGIN_CAP_0_VOLTAGE_INDP_SHIFT; + return FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0]); } -static bool supports_time(const struct usb4_port *usb4) +static bool supports_time(const struct tb_margining *margining) { - return usb4->margining->caps[0] & USB4_MARGIN_CAP_0_TIME; + return margining->caps[0] & USB4_MARGIN_CAP_0_TIME; } /* Only applicable if supports_time() returns true */ -static unsigned int independent_time_margins(const struct usb4_port *usb4) +static unsigned int +independent_time_margins(const struct tb_margining *margining) { - return (usb4->margining->caps[1] & USB4_MARGIN_CAP_1_TIME_INDP_MASK) >> - USB4_MARGIN_CAP_1_TIME_INDP_SHIFT; + return FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1]); } static ssize_t @@ -263,9 +457,8 @@ margining_ber_level_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; unsigned int val; int ret = 0; char *buf; @@ -273,7 +466,7 @@ margining_ber_level_write(struct file *file, const char __user *user_buf, if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; - if (usb4->margining->software) { + if (margining->software) { ret = -EINVAL; goto out_unlock; } @@ -290,13 +483,13 @@ margining_ber_level_write(struct file *file, const char __user *user_buf, if (ret) goto out_free; - if (val < usb4->margining->min_ber_level || - val > usb4->margining->max_ber_level) { + if (val < margining->min_ber_level || + val > margining->max_ber_level) { ret = -EINVAL; goto out_free; } - usb4->margining->ber_level = val; + margining->ber_level = val; out_free: free_page((unsigned long)buf); @@ -316,52 +509,50 @@ static void ber_level_show(struct seq_file *s, unsigned int val) static int margining_ber_level_show(struct seq_file *s, void *not_used) { - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; + const struct tb_margining *margining = s->private; - if (usb4->margining->software) + if (margining->software) return -EINVAL; - ber_level_show(s, usb4->margining->ber_level); + ber_level_show(s, margining->ber_level); return 0; } DEBUGFS_ATTR_RW(margining_ber_level); static int margining_caps_show(struct seq_file *s, void *not_used) { - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; u32 cap0, cap1; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; /* Dump the raw caps first */ - cap0 = usb4->margining->caps[0]; + cap0 = margining->caps[0]; seq_printf(s, "0x%08x\n", cap0); - cap1 = usb4->margining->caps[1]; + cap1 = margining->caps[1]; seq_printf(s, "0x%08x\n", cap1); seq_printf(s, "# software margining: %s\n", - supports_software(usb4) ? "yes" : "no"); - if (supports_hardware(usb4)) { + supports_software(margining) ? "yes" : "no"); + if (supports_hardware(margining)) { seq_puts(s, "# hardware margining: yes\n"); seq_puts(s, "# minimum BER level contour: "); - ber_level_show(s, usb4->margining->min_ber_level); + ber_level_show(s, margining->min_ber_level); seq_puts(s, "# maximum BER level contour: "); - ber_level_show(s, usb4->margining->max_ber_level); + ber_level_show(s, margining->max_ber_level); } else { seq_puts(s, "# hardware margining: no\n"); } seq_printf(s, "# both lanes simultaneously: %s\n", - both_lanes(usb4) ? "yes" : "no"); + both_lanes(margining) ? "yes" : "no"); seq_printf(s, "# voltage margin steps: %u\n", - usb4->margining->voltage_steps); + margining->voltage_steps); seq_printf(s, "# maximum voltage offset: %u mV\n", - usb4->margining->max_voltage_offset); + margining->max_voltage_offset); - switch (independent_voltage_margins(usb4)) { + switch (independent_voltage_margins(margining)) { case USB4_MARGIN_CAP_0_VOLTAGE_MIN: seq_puts(s, "# returns minimum between high and low voltage margins\n"); break; @@ -373,12 +564,12 @@ static int margining_caps_show(struct seq_file *s, void *not_used) break; } - if (supports_time(usb4)) { + if (supports_time(margining)) { seq_puts(s, "# time margining: yes\n"); seq_printf(s, "# time margining is destructive: %s\n", cap1 & USB4_MARGIN_CAP_1_TIME_DESTR ? "yes" : "no"); - switch (independent_time_margins(usb4)) { + switch (independent_time_margins(margining)) { case USB4_MARGIN_CAP_1_TIME_MIN: seq_puts(s, "# returns minimum between left and right time margins\n"); break; @@ -391,9 +582,9 @@ static int margining_caps_show(struct seq_file *s, void *not_used) } seq_printf(s, "# time margin steps: %u\n", - usb4->margining->time_steps); + margining->time_steps); seq_printf(s, "# maximum time offset: %u mUI\n", - usb4->margining->max_time_offset); + margining->max_time_offset); } else { seq_puts(s, "# time margining: no\n"); } @@ -408,9 +599,8 @@ margining_lanes_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; int ret = 0; char *buf; @@ -426,13 +616,13 @@ margining_lanes_write(struct file *file, const char __user *user_buf, } if (!strcmp(buf, "0")) { - usb4->margining->lanes = 0; + margining->lanes = 0; } else if (!strcmp(buf, "1")) { - usb4->margining->lanes = 1; + margining->lanes = 1; } else if (!strcmp(buf, "all")) { /* Needs to be supported */ - if (both_lanes(usb4)) - usb4->margining->lanes = 7; + if (both_lanes(margining)) + margining->lanes = 7; else ret = -EINVAL; } else { @@ -448,16 +638,15 @@ out_free: static int margining_lanes_show(struct seq_file *s, void *not_used) { - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; unsigned int lanes; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; - lanes = usb4->margining->lanes; - if (both_lanes(usb4)) { + lanes = margining->lanes; + if (both_lanes(margining)) { if (!lanes) seq_puts(s, "[0] 1 all\n"); else if (lanes == 1) @@ -481,9 +670,8 @@ static ssize_t margining_mode_write(struct file *file, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; int ret = 0; char *buf; @@ -499,13 +687,13 @@ static ssize_t margining_mode_write(struct file *file, } if (!strcmp(buf, "software")) { - if (supports_software(usb4)) - usb4->margining->software = true; + if (supports_software(margining)) + margining->software = true; else ret = -EINVAL; } else if (!strcmp(buf, "hardware")) { - if (supports_hardware(usb4)) - usb4->margining->software = false; + if (supports_hardware(margining)) + margining->software = false; else ret = -EINVAL; } else { @@ -521,23 +709,22 @@ out_free: static int margining_mode_show(struct seq_file *s, void *not_used) { - const struct tb_port *port = s->private; - const struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; const char *space = ""; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; - if (supports_software(usb4)) { - if (usb4->margining->software) + if (supports_software(margining)) { + if (margining->software) seq_puts(s, "[software]"); else seq_puts(s, "software"); space = " "; } - if (supports_hardware(usb4)) { - if (usb4->margining->software) + if (supports_hardware(margining)) { + if (margining->software) seq_printf(s, "%shardware", space); else seq_printf(s, "%s[hardware]", space); @@ -552,10 +739,10 @@ DEBUGFS_ATTR_RW(margining_mode); static int margining_run_write(void *data, u64 val) { - struct tb_port *port = data; - struct usb4_port *usb4 = port->usb4; + struct tb_margining *margining = data; + struct tb_port *port = margining->port; + struct device *dev = margining->dev; struct tb_switch *sw = port->sw; - struct tb_margining *margining; struct tb_switch *down_sw; struct tb *tb = sw->tb; int ret, clx; @@ -563,7 +750,7 @@ static int margining_run_write(void *data, u64 val) if (val != 1) return -EINVAL; - pm_runtime_get_sync(&sw->dev); + pm_runtime_get_sync(dev); if (mutex_lock_interruptible(&tb->lock)) { ret = -ERESTARTSYS; @@ -590,27 +777,33 @@ static int margining_run_write(void *data, u64 val) clx = ret; } - margining = usb4->margining; - if (margining->software) { - tb_port_dbg(port, "running software %s lane margining for lanes %u\n", - margining->time ? "time" : "voltage", margining->lanes); - ret = usb4_port_sw_margin(port, margining->lanes, margining->time, + tb_port_dbg(port, + "running software %s lane margining for %s lanes %u\n", + margining->time ? "time" : "voltage", dev_name(dev), + margining->lanes); + ret = usb4_port_sw_margin(port, margining->target, margining->index, + margining->lanes, margining->time, margining->right_high, USB4_MARGIN_SW_COUNTER_CLEAR); if (ret) goto out_clx; - ret = usb4_port_sw_margin_errors(port, &margining->results[0]); + ret = usb4_port_sw_margin_errors(port, margining->target, + margining->index, + &margining->results[0]); } else { - tb_port_dbg(port, "running hardware %s lane margining for lanes %u\n", - margining->time ? "time" : "voltage", margining->lanes); + tb_port_dbg(port, + "running hardware %s lane margining for %s lanes %u\n", + margining->time ? "time" : "voltage", dev_name(dev), + margining->lanes); /* Clear the results */ margining->results[0] = 0; margining->results[1] = 0; - ret = usb4_port_hw_margin(port, margining->lanes, - margining->ber_level, margining->time, - margining->right_high, margining->results); + ret = usb4_port_hw_margin(port, margining->target, margining->index, + margining->lanes, margining->ber_level, + margining->time, margining->right_high, + margining->results); } out_clx: @@ -619,8 +812,8 @@ out_clx: out_unlock: mutex_unlock(&tb->lock); out_rpm_put: - pm_runtime_mark_last_busy(&sw->dev); - pm_runtime_put_autosuspend(&sw->dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return ret; } @@ -632,16 +825,15 @@ static ssize_t margining_results_write(struct file *file, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; /* Just clear the results */ - usb4->margining->results[0] = 0; - usb4->margining->results[1] = 0; + margining->results[0] = 0; + margining->results[1] = 0; mutex_unlock(&tb->lock); return count; @@ -652,7 +844,7 @@ static void voltage_margin_show(struct seq_file *s, { unsigned int tmp, voltage; - tmp = val & USB4_MARGIN_HW_RES_1_MARGIN_MASK; + tmp = FIELD_GET(USB4_MARGIN_HW_RES_1_MARGIN_MASK, val); voltage = tmp * margining->max_voltage_offset / margining->voltage_steps; seq_printf(s, "%u mV (%u)", voltage, tmp); if (val & USB4_MARGIN_HW_RES_1_EXCEEDS) @@ -665,7 +857,7 @@ static void time_margin_show(struct seq_file *s, { unsigned int tmp, interval; - tmp = val & USB4_MARGIN_HW_RES_1_MARGIN_MASK; + tmp = FIELD_GET(USB4_MARGIN_HW_RES_1_MARGIN_MASK, val); interval = tmp * margining->max_time_offset / margining->time_steps; seq_printf(s, "%u mUI (%u)", interval, tmp); if (val & USB4_MARGIN_HW_RES_1_EXCEEDS) @@ -675,15 +867,12 @@ static void time_margin_show(struct seq_file *s, static int margining_results_show(struct seq_file *s, void *not_used) { - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb_margining *margining; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; - margining = usb4->margining; /* Dump the raw results first */ seq_printf(s, "0x%08x\n", margining->results[0]); /* Only the hardware margining has two result dwords */ @@ -745,9 +934,8 @@ static ssize_t margining_test_write(struct file *file, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; int ret = 0; char *buf; @@ -762,10 +950,10 @@ static ssize_t margining_test_write(struct file *file, goto out_free; } - if (!strcmp(buf, "time") && supports_time(usb4)) - usb4->margining->time = true; + if (!strcmp(buf, "time") && supports_time(margining)) + margining->time = true; else if (!strcmp(buf, "voltage")) - usb4->margining->time = false; + margining->time = false; else ret = -EINVAL; @@ -778,15 +966,14 @@ out_free: static int margining_test_show(struct seq_file *s, void *not_used) { - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; - if (supports_time(usb4)) { - if (usb4->margining->time) + if (supports_time(margining)) { + if (margining->time) seq_puts(s, "voltage [time]\n"); else seq_puts(s, "[voltage] time\n"); @@ -804,9 +991,8 @@ static ssize_t margining_margin_write(struct file *file, size_t count, loff_t *ppos) { struct seq_file *s = file->private_data; - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; int ret = 0; char *buf; @@ -821,18 +1007,18 @@ static ssize_t margining_margin_write(struct file *file, goto out_free; } - if (usb4->margining->time) { + if (margining->time) { if (!strcmp(buf, "left")) - usb4->margining->right_high = false; + margining->right_high = false; else if (!strcmp(buf, "right")) - usb4->margining->right_high = true; + margining->right_high = true; else ret = -EINVAL; } else { if (!strcmp(buf, "low")) - usb4->margining->right_high = false; + margining->right_high = false; else if (!strcmp(buf, "high")) - usb4->margining->right_high = true; + margining->right_high = true; else ret = -EINVAL; } @@ -846,20 +1032,19 @@ out_free: static int margining_margin_show(struct seq_file *s, void *not_used) { - struct tb_port *port = s->private; - struct usb4_port *usb4 = port->usb4; - struct tb *tb = port->sw->tb; + struct tb_margining *margining = s->private; + struct tb *tb = margining->port->sw->tb; if (mutex_lock_interruptible(&tb->lock)) return -ERESTARTSYS; - if (usb4->margining->time) { - if (usb4->margining->right_high) + if (margining->time) { + if (margining->right_high) seq_puts(s, "left [right]\n"); else seq_puts(s, "[left] right\n"); } else { - if (usb4->margining->right_high) + if (margining->right_high) seq_puts(s, "low [high]\n"); else seq_puts(s, "[low] high\n"); @@ -870,51 +1055,44 @@ static int margining_margin_show(struct seq_file *s, void *not_used) } DEBUGFS_ATTR_RW(margining_margin); -static void margining_port_init(struct tb_port *port) +static struct tb_margining *margining_alloc(struct tb_port *port, + struct device *dev, + enum usb4_sb_target target, + u8 index, struct dentry *parent) { struct tb_margining *margining; - struct dentry *dir, *parent; - struct usb4_port *usb4; - char dir_name[10]; + struct dentry *dir; unsigned int val; int ret; - usb4 = port->usb4; - if (!usb4) - return; - - snprintf(dir_name, sizeof(dir_name), "port%d", port->port); - parent = debugfs_lookup(dir_name, port->sw->debugfs_dir); - margining = kzalloc(sizeof(*margining), GFP_KERNEL); if (!margining) - return; + return NULL; - ret = usb4_port_margining_caps(port, margining->caps); + margining->port = port; + margining->target = target; + margining->index = index; + margining->dev = dev; + + ret = usb4_port_margining_caps(port, target, index, margining->caps); if (ret) { kfree(margining); - return; + return NULL; } - usb4->margining = margining; - /* Set the initial mode */ - if (supports_software(usb4)) + if (supports_software(margining)) margining->software = true; - val = (margining->caps[0] & USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK) >> - USB4_MARGIN_CAP_0_VOLTAGE_STEPS_SHIFT; + val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]); margining->voltage_steps = val; - val = (margining->caps[0] & USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK) >> - USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_SHIFT; + val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]); margining->max_voltage_offset = 74 + val * 2; - if (supports_time(usb4)) { - val = (margining->caps[1] & USB4_MARGIN_CAP_1_TIME_STEPS_MASK) >> - USB4_MARGIN_CAP_1_TIME_STEPS_SHIFT; + if (supports_time(margining)) { + val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_STEPS_MASK, margining->caps[1]); margining->time_steps = val; - val = (margining->caps[1] & USB4_MARGIN_CAP_1_TIME_OFFSET_MASK) >> - USB4_MARGIN_CAP_1_TIME_OFFSET_SHIFT; + val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_OFFSET_MASK, margining->caps[1]); /* * Store it as mUI (milli Unit Interval) because we want * to keep it as integer. @@ -923,30 +1101,46 @@ static void margining_port_init(struct tb_port *port) } dir = debugfs_create_dir("margining", parent); - if (supports_hardware(usb4)) { - val = (margining->caps[1] & USB4_MARGIN_CAP_1_MIN_BER_MASK) >> - USB4_MARGIN_CAP_1_MIN_BER_SHIFT; + if (supports_hardware(margining)) { + val = FIELD_GET(USB4_MARGIN_CAP_1_MIN_BER_MASK, margining->caps[1]); margining->min_ber_level = val; - val = (margining->caps[1] & USB4_MARGIN_CAP_1_MAX_BER_MASK) >> - USB4_MARGIN_CAP_1_MAX_BER_SHIFT; + val = FIELD_GET(USB4_MARGIN_CAP_1_MAX_BER_MASK, margining->caps[1]); margining->max_ber_level = val; /* Set the default to minimum */ margining->ber_level = margining->min_ber_level; - debugfs_create_file("ber_level_contour", 0400, dir, port, + debugfs_create_file("ber_level_contour", 0400, dir, margining, &margining_ber_level_fops); } - debugfs_create_file("caps", 0400, dir, port, &margining_caps_fops); - debugfs_create_file("lanes", 0600, dir, port, &margining_lanes_fops); - debugfs_create_file("mode", 0600, dir, port, &margining_mode_fops); - debugfs_create_file("run", 0600, dir, port, &margining_run_fops); - debugfs_create_file("results", 0600, dir, port, &margining_results_fops); - debugfs_create_file("test", 0600, dir, port, &margining_test_fops); - if (independent_voltage_margins(usb4) == USB4_MARGIN_CAP_0_VOLTAGE_HL || - (supports_time(usb4) && - independent_time_margins(usb4) == USB4_MARGIN_CAP_1_TIME_LR)) - debugfs_create_file("margin", 0600, dir, port, &margining_margin_fops); + debugfs_create_file("caps", 0400, dir, margining, &margining_caps_fops); + debugfs_create_file("lanes", 0600, dir, margining, &margining_lanes_fops); + debugfs_create_file("mode", 0600, dir, margining, &margining_mode_fops); + debugfs_create_file("run", 0600, dir, margining, &margining_run_fops); + debugfs_create_file("results", 0600, dir, margining, + &margining_results_fops); + debugfs_create_file("test", 0600, dir, margining, &margining_test_fops); + if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_0_VOLTAGE_HL || + (supports_time(margining) && + independent_time_margins(margining) == USB4_MARGIN_CAP_1_TIME_LR)) + debugfs_create_file("margin", 0600, dir, margining, + &margining_margin_fops); + return margining; +} + +static void margining_port_init(struct tb_port *port) +{ + struct dentry *parent; + char dir_name[10]; + + if (!port->usb4) + return; + + snprintf(dir_name, sizeof(dir_name), "port%d", port->port); + parent = debugfs_lookup(dir_name, port->sw->debugfs_dir); + port->usb4->margining = margining_alloc(port, &port->usb4->dev, + USB4_SB_TARGET_ROUTER, 0, + parent); } static void margining_port_remove(struct tb_port *port) @@ -1020,11 +1214,27 @@ static void margining_xdomain_remove(struct tb_xdomain *xd) downstream = tb_port_at(xd->route, parent_sw); margining_port_remove(downstream); } + +static void margining_retimer_init(struct tb_retimer *rt, struct dentry *debugfs_dir) +{ + rt->margining = margining_alloc(rt->port, &rt->dev, + USB4_SB_TARGET_RETIMER, rt->index, + debugfs_dir); +} + +static void margining_retimer_remove(struct tb_retimer *rt) +{ + kfree(rt->margining); + rt->margining = NULL; +} #else static inline void margining_switch_init(struct tb_switch *sw) { } static inline void margining_switch_remove(struct tb_switch *sw) { } static inline void margining_xdomain_init(struct tb_xdomain *xd) { } static inline void margining_xdomain_remove(struct tb_xdomain *xd) { } +static inline void margining_retimer_init(struct tb_retimer *rt, + struct dentry *debugfs_dir) { } +static inline void margining_retimer_remove(struct tb_retimer *rt) { } #endif static int port_clear_all_counters(struct tb_port *port) @@ -1505,6 +1715,60 @@ out: } DEBUGFS_ATTR_RW(counters); +static int sb_regs_show(struct tb_port *port, const struct sb_reg *sb_regs, + size_t size, enum usb4_sb_target target, u8 index, + struct seq_file *s) +{ + int ret, i; + + seq_puts(s, "# register value\n"); + + for (i = 0; i < size; i++) { + const struct sb_reg *regs = &sb_regs[i]; + u8 data[64]; + int j; + + memset(data, 0, sizeof(data)); + ret = usb4_port_sb_read(port, target, index, regs->reg, data, + regs->size); + if (ret) + return ret; + + seq_printf(s, "0x%02x", regs->reg); + for (j = 0; j < regs->size; j++) + seq_printf(s, " 0x%02x", data[j]); + seq_puts(s, "\n"); + } + + return 0; +} + +static int port_sb_regs_show(struct seq_file *s, void *not_used) +{ + struct tb_port *port = s->private; + struct tb_switch *sw = port->sw; + struct tb *tb = sw->tb; + int ret; + + pm_runtime_get_sync(&sw->dev); + + if (mutex_lock_interruptible(&tb->lock)) { + ret = -ERESTARTSYS; + goto out_rpm_put; + } + + ret = sb_regs_show(port, port_sb_regs, ARRAY_SIZE(port_sb_regs), + USB4_SB_TARGET_ROUTER, 0, s); + + mutex_unlock(&tb->lock); +out_rpm_put: + pm_runtime_mark_last_busy(&sw->dev); + pm_runtime_put_autosuspend(&sw->dev); + + return ret; +} +DEBUGFS_ATTR_RW(port_sb_regs); + /** * tb_switch_debugfs_init() - Add debugfs entries for router * @sw: Pointer to the router @@ -1539,6 +1803,9 @@ void tb_switch_debugfs_init(struct tb_switch *sw) if (port->config.counters_support) debugfs_create_file("counters", 0600, debugfs_dir, port, &counters_fops); + if (port->usb4) + debugfs_create_file("sb_regs", DEBUGFS_MODE, debugfs_dir, + port, &port_sb_regs_fops); } margining_switch_init(sw); @@ -1590,6 +1857,59 @@ void tb_service_debugfs_remove(struct tb_service *svc) svc->debugfs_dir = NULL; } +static int retimer_sb_regs_show(struct seq_file *s, void *not_used) +{ + struct tb_retimer *rt = s->private; + struct tb *tb = rt->tb; + int ret; + + pm_runtime_get_sync(&rt->dev); + + if (mutex_lock_interruptible(&tb->lock)) { + ret = -ERESTARTSYS; + goto out_rpm_put; + } + + ret = sb_regs_show(rt->port, retimer_sb_regs, ARRAY_SIZE(retimer_sb_regs), + USB4_SB_TARGET_RETIMER, rt->index, s); + + mutex_unlock(&tb->lock); +out_rpm_put: + pm_runtime_mark_last_busy(&rt->dev); + pm_runtime_put_autosuspend(&rt->dev); + + return ret; +} +DEBUGFS_ATTR_RW(retimer_sb_regs); + +/** + * tb_retimer_debugfs_init() - Add debugfs directory for retimer + * @rt: Pointer to retimer structure + * + * Adds and populates retimer debugfs directory. + */ +void tb_retimer_debugfs_init(struct tb_retimer *rt) +{ + struct dentry *debugfs_dir; + + debugfs_dir = debugfs_create_dir(dev_name(&rt->dev), tb_debugfs_root); + debugfs_create_file("sb_regs", DEBUGFS_MODE, debugfs_dir, rt, + &retimer_sb_regs_fops); + margining_retimer_init(rt, debugfs_dir); +} + +/** + * tb_retimer_debugfs_remove() - Remove retimer debugfs directory + * @rt: Pointer to retimer structure + * + * Removes the retimer debugfs directory along with its contents. + */ +void tb_retimer_debugfs_remove(struct tb_retimer *rt) +{ + debugfs_lookup_and_remove(dev_name(&rt->dev), tb_debugfs_root); + margining_retimer_remove(rt); +} + void tb_debugfs_init(void) { tb_debugfs_root = debugfs_create_dir("thunderbolt", NULL); diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 6eaaa5074ce8..721319329afa 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -14,7 +14,11 @@ #include "sb_regs.h" #include "tb.h" +#if IS_ENABLED(CONFIG_USB4_DEBUGFS_MARGINING) #define TB_MAX_RETIMER_INDEX 6 +#else +#define TB_MAX_RETIMER_INDEX 2 +#endif /** * tb_retimer_nvm_read() - Read contents of retimer NVM @@ -319,6 +323,8 @@ static ssize_t nvm_version_show(struct device *dev, if (!rt->nvm) ret = -EAGAIN; + else if (rt->no_nvm_upgrade) + ret = -EOPNOTSUPP; else ret = sysfs_emit(buf, "%x.%x\n", rt->nvm->major, rt->nvm->minor); @@ -366,35 +372,29 @@ const struct device_type tb_retimer_type = { .release = tb_retimer_release, }; -static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) +static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status, + bool on_board) { struct tb_retimer *rt; u32 vendor, device; int ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_VENDOR_ID, &vendor, - sizeof(vendor)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_VENDOR_ID, &vendor, sizeof(vendor)); if (ret) { if (ret != -ENODEV) tb_port_warn(port, "failed read retimer VendorId: %d\n", ret); return ret; } - ret = usb4_port_retimer_read(port, index, USB4_SB_PRODUCT_ID, &device, - sizeof(device)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_PRODUCT_ID, &device, sizeof(device)); if (ret) { if (ret != -ENODEV) tb_port_warn(port, "failed read retimer ProductId: %d\n", ret); return ret; } - /* - * Check that it supports NVM operations. If not then don't add - * the device at all. - */ - ret = usb4_port_retimer_nvm_sector_size(port, index); - if (ret < 0) - return ret; rt = kzalloc(sizeof(*rt), GFP_KERNEL); if (!rt) @@ -407,6 +407,13 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) rt->port = port; rt->tb = port->sw->tb; + /* + * Only support NVM upgrade for on-board retimers. The retimers + * on the other side of the connection. + */ + if (!on_board || usb4_port_retimer_nvm_sector_size(port, index) <= 0) + rt->no_nvm_upgrade = true; + rt->dev.parent = &port->usb4->dev; rt->dev.bus = &tb_bus_type; rt->dev.type = &tb_retimer_type; @@ -437,12 +444,14 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) pm_runtime_mark_last_busy(&rt->dev); pm_runtime_use_autosuspend(&rt->dev); + tb_retimer_debugfs_init(rt); return 0; } static void tb_retimer_remove(struct tb_retimer *rt) { dev_info(&rt->dev, "retimer disconnected\n"); + tb_retimer_debugfs_remove(rt); tb_nvm_free(rt->nvm); device_unregister(&rt->dev); } @@ -485,7 +494,7 @@ static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index) int tb_retimer_scan(struct tb_port *port, bool add) { u32 status[TB_MAX_RETIMER_INDEX + 1] = {}; - int ret, i, last_idx = 0; + int ret, i, max, last_idx = 0; /* * Send broadcast RT to make sure retimer indices facing this @@ -520,26 +529,28 @@ int tb_retimer_scan(struct tb_port *port, bool add) break; } - tb_retimer_unset_inbound_sbtx(port); - - if (!last_idx) - return 0; - - /* Add on-board retimers if they do not exist already */ + max = i; ret = 0; - for (i = 1; i <= last_idx; i++) { + + /* Add retimers if they do not exist already */ + for (i = 1; i <= max; i++) { struct tb_retimer *rt; + /* Skip cable retimers */ + if (usb4_port_retimer_is_cable(port, i)) + continue; + rt = tb_port_find_retimer(port, i); if (rt) { put_device(&rt->dev); } else if (add) { - ret = tb_retimer_add(port, i, status[i]); + ret = tb_retimer_add(port, i, status[i], i <= last_idx); if (ret && ret != -EOPNOTSUPP) break; } } + tb_retimer_unset_inbound_sbtx(port); return ret; } diff --git a/drivers/thunderbolt/sb_regs.h b/drivers/thunderbolt/sb_regs.h index f37a4320f10a..2a88edfc97b2 100644 --- a/drivers/thunderbolt/sb_regs.h +++ b/drivers/thunderbolt/sb_regs.h @@ -12,6 +12,10 @@ #define USB4_SB_VENDOR_ID 0x00 #define USB4_SB_PRODUCT_ID 0x01 +#define USB4_SB_FW_VERSION 0x02 +#define USB4_SB_DEBUG_CONF 0x05 +#define USB4_SB_DEBUG 0x06 +#define USB4_SB_LRD_TUNING 0x07 #define USB4_SB_OPCODE 0x08 enum usb4_sb_opcode { @@ -22,6 +26,7 @@ enum usb4_sb_opcode { USB4_SB_OPCODE_SET_INBOUND_SBTX = 0x5055534c, /* "LSUP" */ USB4_SB_OPCODE_UNSET_INBOUND_SBTX = 0x50555355, /* "USUP" */ USB4_SB_OPCODE_QUERY_LAST_RETIMER = 0x5453414c, /* "LAST" */ + USB4_SB_OPCODE_QUERY_CABLE_RETIMER = 0x524c4243, /* "CBLR" */ USB4_SB_OPCODE_GET_NVM_SECTOR_SIZE = 0x53534e47, /* "GNSS" */ USB4_SB_OPCODE_NVM_SET_OFFSET = 0x53504f42, /* "BOPS" */ USB4_SB_OPCODE_NVM_BLOCK_WRITE = 0x574b4c42, /* "BLKW" */ @@ -35,6 +40,10 @@ enum usb4_sb_opcode { #define USB4_SB_METADATA 0x09 #define USB4_SB_METADATA_NVM_AUTH_WRITE_MASK GENMASK(5, 0) +#define USB4_SB_LINK_CONF 0x0c +#define USB4_SB_GEN23_TXFFE 0x0d +#define USB4_SB_GEN4_TXFFE 0x0e +#define USB4_SB_VERSION 0x0f #define USB4_SB_DATA 0x12 /* USB4_SB_OPCODE_READ_LANE_MARGINING_CAP */ @@ -42,30 +51,21 @@ enum usb4_sb_opcode { #define USB4_MARGIN_CAP_0_MODES_SW BIT(1) #define USB4_MARGIN_CAP_0_2_LANES BIT(2) #define USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK GENMASK(4, 3) -#define USB4_MARGIN_CAP_0_VOLTAGE_INDP_SHIFT 3 #define USB4_MARGIN_CAP_0_VOLTAGE_MIN 0x0 #define USB4_MARGIN_CAP_0_VOLTAGE_HL 0x1 #define USB4_MARGIN_CAP_0_VOLTAGE_BOTH 0x2 #define USB4_MARGIN_CAP_0_TIME BIT(5) #define USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK GENMASK(12, 6) -#define USB4_MARGIN_CAP_0_VOLTAGE_STEPS_SHIFT 6 #define USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK GENMASK(18, 13) -#define USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_SHIFT 13 #define USB4_MARGIN_CAP_1_TIME_DESTR BIT(8) #define USB4_MARGIN_CAP_1_TIME_INDP_MASK GENMASK(10, 9) -#define USB4_MARGIN_CAP_1_TIME_INDP_SHIFT 9 #define USB4_MARGIN_CAP_1_TIME_MIN 0x0 #define USB4_MARGIN_CAP_1_TIME_LR 0x1 #define USB4_MARGIN_CAP_1_TIME_BOTH 0x2 #define USB4_MARGIN_CAP_1_TIME_STEPS_MASK GENMASK(15, 11) -#define USB4_MARGIN_CAP_1_TIME_STEPS_SHIFT 11 #define USB4_MARGIN_CAP_1_TIME_OFFSET_MASK GENMASK(20, 16) -#define USB4_MARGIN_CAP_1_TIME_OFFSET_SHIFT 16 #define USB4_MARGIN_CAP_1_MIN_BER_MASK GENMASK(25, 21) -#define USB4_MARGIN_CAP_1_MIN_BER_SHIFT 21 #define USB4_MARGIN_CAP_1_MAX_BER_MASK GENMASK(30, 26) -#define USB4_MARGIN_CAP_1_MAX_BER_SHIFT 26 -#define USB4_MARGIN_CAP_1_MAX_BER_SHIFT 26 /* USB4_SB_OPCODE_RUN_HW_LANE_MARGINING */ #define USB4_MARGIN_HW_TIME BIT(3) diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 18aae4ccaed5..b47f7873c847 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -329,6 +329,7 @@ struct usb4_port { * @nvm: Pointer to the NVM if the retimer has one (%NULL otherwise) * @no_nvm_upgrade: Prevent NVM upgrade of this retimer * @auth_status: Status of last NVM authentication + * @margining: Pointer to margining structure if enabled */ struct tb_retimer { struct device dev; @@ -340,6 +341,9 @@ struct tb_retimer { struct tb_nvm *nvm; bool no_nvm_upgrade; u32 auth_status; +#ifdef CONFIG_USB4_DEBUGFS_MARGINING + struct tb_margining *margining; +#endif }; /** @@ -1327,26 +1331,43 @@ int usb4_port_router_offline(struct tb_port *port); int usb4_port_router_online(struct tb_port *port); int usb4_port_enumerate_retimers(struct tb_port *port); bool usb4_port_clx_supported(struct tb_port *port); -int usb4_port_margining_caps(struct tb_port *port, u32 *caps); bool usb4_port_asym_supported(struct tb_port *port); int usb4_port_asym_set_link_width(struct tb_port *port, enum tb_link_width width); int usb4_port_asym_start(struct tb_port *port); -int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes, - unsigned int ber_level, bool timing, bool right_high, - u32 *results); -int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing, +/** + * enum tb_sb_target - Sideband transaction target + * @USB4_SB_TARGET_ROUTER: Target is the router itself + * @USB4_SB_TARGET_PARTNER: Target is partner + * @USB4_SB_TARGET_RETIMER: Target is retimer + */ +enum usb4_sb_target { + USB4_SB_TARGET_ROUTER, + USB4_SB_TARGET_PARTNER, + USB4_SB_TARGET_RETIMER, +}; + +int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, u8 index, + u8 reg, void *buf, u8 size); +int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target, + u8 index, u8 reg, const void *buf, u8 size); + +int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target, + u8 index, u32 *caps); +int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target, + u8 index, unsigned int lanes, unsigned int ber_level, + bool timing, bool right_high, u32 *results); +int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target, + u8 index, unsigned int lanes, bool timing, bool right_high, u32 counter); -int usb4_port_sw_margin_errors(struct tb_port *port, u32 *errors); +int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target, + u8 index, u32 *errors); int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index); int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index); -int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, - u8 size); -int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg, - const void *buf, u8 size); int usb4_port_retimer_is_last(struct tb_port *port, u8 index); +int usb4_port_retimer_is_cable(struct tb_port *port, u8 index); int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index); int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, unsigned int address); @@ -1445,6 +1466,8 @@ void tb_xdomain_debugfs_init(struct tb_xdomain *xd); void tb_xdomain_debugfs_remove(struct tb_xdomain *xd); void tb_service_debugfs_init(struct tb_service *svc); void tb_service_debugfs_remove(struct tb_service *svc); +void tb_retimer_debugfs_init(struct tb_retimer *rt); +void tb_retimer_debugfs_remove(struct tb_retimer *rt); #else static inline void tb_debugfs_init(void) { } static inline void tb_debugfs_exit(void) { } @@ -1454,6 +1477,8 @@ static inline void tb_xdomain_debugfs_init(struct tb_xdomain *xd) { } static inline void tb_xdomain_debugfs_remove(struct tb_xdomain *xd) { } static inline void tb_service_debugfs_init(struct tb_service *svc) { } static inline void tb_service_debugfs_remove(struct tb_service *svc) { } +static inline void tb_retimer_debugfs_init(struct tb_retimer *rt) { } +static inline void tb_retimer_debugfs_remove(struct tb_retimer *rt) { } #endif #endif diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index de480bf2a53d..4d83b65afb5b 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -17,12 +17,6 @@ #define USB4_DATA_RETRIES 3 #define USB4_DATA_DWORDS 16 -enum usb4_sb_target { - USB4_SB_TARGET_ROUTER, - USB4_SB_TARGET_PARTNER, - USB4_SB_TARGET_RETIMER, -}; - #define USB4_NVM_READ_OFFSET_MASK GENMASK(23, 2) #define USB4_NVM_READ_OFFSET_SHIFT 2 #define USB4_NVM_READ_LENGTH_MASK GENMASK(27, 24) @@ -1289,8 +1283,20 @@ static int usb4_port_write_data(struct tb_port *port, const void *data, dwords); } -static int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, - u8 index, u8 reg, void *buf, u8 size) +/** + * usb4_port_sb_read() - Read from sideband register + * @port: USB4 port to read + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER + * @reg: Sideband register index + * @buf: Buffer where the sideband data is copied + * @size: Size of @buf + * + * Reads data from sideband register @reg and copies it into @buf. + * Returns %0 in case of success and negative errno in case of failure. + */ +int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, u8 index, + u8 reg, void *buf, u8 size) { size_t dwords = DIV_ROUND_UP(size, 4); int ret; @@ -1329,8 +1335,20 @@ static int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, return buf ? usb4_port_read_data(port, buf, dwords) : 0; } -static int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target, - u8 index, u8 reg, const void *buf, u8 size) +/** + * usb4_port_sb_write() - Write to sideband register + * @port: USB4 port to write + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER + * @reg: Sideband register index + * @buf: Data to write + * @size: Size of @buf + * + * Writes @buf to sideband register @reg. Returns %0 in case of success + * and negative errno in case of failure. + */ +int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target, + u8 index, u8 reg, const void *buf, u8 size) { size_t dwords = DIV_ROUND_UP(size, 4); int ret; @@ -1610,26 +1628,31 @@ int usb4_port_asym_start(struct tb_port *port) /** * usb4_port_margining_caps() - Read USB4 port marginig capabilities * @port: USB4 port + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER * @caps: Array with at least two elements to hold the results * * Reads the USB4 port lane margining capabilities into @caps. */ -int usb4_port_margining_caps(struct tb_port *port, u32 *caps) +int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target, + u8 index, u32 *caps) { int ret; - ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + ret = usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_READ_LANE_MARGINING_CAP, 500); if (ret) return ret; - return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_DATA, caps, sizeof(*caps) * 2); + return usb4_port_sb_read(port, target, index, USB4_SB_DATA, caps, + sizeof(*caps) * 2); } /** * usb4_port_hw_margin() - Run hardware lane margining on port * @port: USB4 port + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER * @lanes: Which lanes to run (must match the port capabilities). Can be * %0, %1 or %7. * @ber_level: BER level contour value @@ -1640,9 +1663,9 @@ int usb4_port_margining_caps(struct tb_port *port, u32 *caps) * Runs hardware lane margining on USB4 port and returns the result in * @results. */ -int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes, - unsigned int ber_level, bool timing, bool right_high, - u32 *results) +int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target, + u8 index, unsigned int lanes, unsigned int ber_level, + bool timing, bool right_high, u32 *results) { u32 val; int ret; @@ -1656,23 +1679,25 @@ int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes, val |= (ber_level << USB4_MARGIN_HW_BER_SHIFT) & USB4_MARGIN_HW_BER_MASK; - ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_METADATA, &val, sizeof(val)); + ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val, + sizeof(val)); if (ret) return ret; - ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + ret = usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_RUN_HW_LANE_MARGINING, 2500); if (ret) return ret; - return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_DATA, results, sizeof(*results) * 2); + return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results, + sizeof(*results) * 2); } /** * usb4_port_sw_margin() - Run software lane margining on port * @port: USB4 port + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER * @lanes: Which lanes to run (must match the port capabilities). Can be * %0, %1 or %7. * @timing: Perform timing margining instead of voltage @@ -1683,7 +1708,8 @@ int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes, * counters by calling usb4_port_sw_margin_errors(). Returns %0 in * success and negative errno otherwise. */ -int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing, +int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target, + u8 index, unsigned int lanes, bool timing, bool right_high, u32 counter) { u32 val; @@ -1697,34 +1723,37 @@ int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing, val |= (counter << USB4_MARGIN_SW_COUNTER_SHIFT) & USB4_MARGIN_SW_COUNTER_MASK; - ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_METADATA, &val, sizeof(val)); + ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val, + sizeof(val)); if (ret) return ret; - return usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + return usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500); } /** * usb4_port_sw_margin_errors() - Read the software margining error counters * @port: USB4 port + * @target: Sideband target + * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER * @errors: Error metadata is copied here. * * This reads back the software margining error counters from the port. * Returns %0 in success and negative errno otherwise. */ -int usb4_port_sw_margin_errors(struct tb_port *port, u32 *errors) +int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target, + u8 index, u32 *errors) { int ret; - ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0, + ret = usb4_port_sb_op(port, target, index, USB4_SB_OPCODE_READ_SW_MARGIN_ERR, 150); if (ret) return ret; - return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0, - USB4_SB_METADATA, errors, sizeof(*errors)); + return usb4_port_sb_read(port, target, index, USB4_SB_METADATA, errors, + sizeof(*errors)); } static inline int usb4_port_retimer_op(struct tb_port *port, u8 index, @@ -1776,47 +1805,6 @@ int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index) USB4_SB_OPCODE_UNSET_INBOUND_SBTX, 500); } -/** - * usb4_port_retimer_read() - Read from retimer sideband registers - * @port: USB4 port - * @index: Retimer index - * @reg: Sideband register to read - * @buf: Data from @reg is stored here - * @size: Number of bytes to read - * - * Function reads retimer sideband registers starting from @reg. The - * retimer is connected to @port at @index. Returns %0 in case of - * success, and read data is copied to @buf. If there is no retimer - * present at given @index returns %-ENODEV. In any other failure - * returns negative errno. - */ -int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, - u8 size) -{ - return usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, reg, buf, - size); -} - -/** - * usb4_port_retimer_write() - Write to retimer sideband registers - * @port: USB4 port - * @index: Retimer index - * @reg: Sideband register to write - * @buf: Data that is written starting from @reg - * @size: Number of bytes to write - * - * Writes retimer sideband registers starting from @reg. The retimer is - * connected to @port at @index. Returns %0 in case of success. If there - * is no retimer present at given @index returns %-ENODEV. In any other - * failure returns negative errno. - */ -int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg, - const void *buf, u8 size) -{ - return usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, reg, buf, - size); -} - /** * usb4_port_retimer_is_last() - Is the retimer last on-board retimer * @port: USB4 port @@ -1837,8 +1825,32 @@ int usb4_port_retimer_is_last(struct tb_port *port, u8 index) if (ret) return ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); + return ret ? ret : metadata & 1; +} + +/** + * usb4_port_retimer_is_cable() - Is the retimer cable retimer + * @port: USB4 port + * @index: Retimer index + * + * If the retimer at @index is last cable retimer this function returns + * %1 and %0 if it is on-board retimer. In case a retimer is not present + * at @index returns %-ENODEV. Otherwise returns negative errno. + */ +int usb4_port_retimer_is_cable(struct tb_port *port, u8 index) +{ + u32 metadata; + int ret; + + ret = usb4_port_retimer_op(port, index, USB4_SB_OPCODE_QUERY_CABLE_RETIMER, + 500); + if (ret) + return ret; + + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); return ret ? ret : metadata & 1; } @@ -1863,8 +1875,8 @@ int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index) if (ret) return ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); return ret ? ret : metadata & USB4_NVM_SECTOR_SIZE_MASK; } @@ -1889,8 +1901,8 @@ int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, metadata = (dwaddress << USB4_NVM_SET_OFFSET_SHIFT) & USB4_NVM_SET_OFFSET_MASK; - ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); if (ret) return ret; @@ -1912,8 +1924,8 @@ static int usb4_port_retimer_nvm_write_next_block(void *data, u8 index = info->index; int ret; - ret = usb4_port_retimer_write(port, index, USB4_SB_DATA, - buf, dwords * 4); + ret = usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_DATA, buf, dwords * 4); if (ret) return ret; @@ -1992,8 +2004,8 @@ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index, u32 metadata, val; int ret; - ret = usb4_port_retimer_read(port, index, USB4_SB_OPCODE, &val, - sizeof(val)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_OPCODE, &val, sizeof(val)); if (ret) return ret; @@ -2004,8 +2016,9 @@ int usb4_port_retimer_nvm_authenticate_status(struct tb_port *port, u8 index, return 0; case -EAGAIN: - ret = usb4_port_retimer_read(port, index, USB4_SB_METADATA, - &metadata, sizeof(metadata)); + ret = usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, + sizeof(metadata)); if (ret) return ret; @@ -2030,8 +2043,8 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, if (dwords < USB4_DATA_DWORDS) metadata |= dwords << USB4_NVM_READ_LENGTH_SHIFT; - ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata, - sizeof(metadata)); + ret = usb4_port_sb_write(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_METADATA, &metadata, sizeof(metadata)); if (ret) return ret; @@ -2039,8 +2052,8 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, if (ret) return ret; - return usb4_port_retimer_read(port, index, USB4_SB_DATA, buf, - dwords * 4); + return usb4_port_sb_read(port, USB4_SB_TARGET_RETIMER, index, + USB4_SB_DATA, buf, dwords * 4); } /** diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 8c964da75f2d..37164289277b 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1660,5 +1660,6 @@ console_initcall(amiserial_console_init); #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ +MODULE_DESCRIPTION("Serial driver for the amiga builtin port"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:amiga-serial"); diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 34421ec06a69..c60745f8e621 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -470,4 +470,5 @@ static struct platform_driver goldfish_tty_platform_driver = { module_platform_driver(goldfish_tty_platform_driver); +MODULE_DESCRIPTION("Goldfish TTY Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index be35f7334ecd..5d37a0984916 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -4634,5 +4634,6 @@ module_init(gsm_init); module_exit(gsm_exit); +MODULE_DESCRIPTION("GSM 0710 tty multiplexor"); MODULE_LICENSE("GPL"); MODULE_ALIAS_LDISC(N_GSM0710); diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 1615f074ab86..4a4dc58b866a 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -822,6 +822,7 @@ static void __exit n_hdlc_exit(void) module_init(n_hdlc_init); module_exit(n_hdlc_exit); +MODULE_DESCRIPTION("HDLC line discipline support"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Paul Fulghum paulkf@microgate.com"); module_param(maxframe, int, 0); diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 6a7b286f6f5a..e5310c65cf52 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include "../serial_mctrl_gpio.h" @@ -93,6 +93,10 @@ struct serial8250_config { #define UART_BUG_THRE BIT(3) /* UART has buggy THRE reassertion */ #define UART_BUG_TXRACE BIT(5) /* UART Tx fails to set remote DR */ +/* Module parameters */ +#define UART_NR CONFIG_SERIAL_8250_NR_UARTS + +extern unsigned int nr_uarts; #ifdef CONFIG_SERIAL_8250_SHARE_IRQ #define SERIAL8250_SHARE_IRQS 1 @@ -100,6 +104,9 @@ struct serial8250_config { #define SERIAL8250_SHARE_IRQS 0 #endif +extern unsigned int share_irqs; +extern unsigned int skip_txen_test; + #define SERIAL8250_PORT_FLAGS(_base, _irq, _flags) \ { \ .iobase = _base, \ @@ -111,6 +118,19 @@ struct serial8250_config { #define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0) +extern struct uart_driver serial8250_reg; +void serial8250_register_ports(struct uart_driver *drv, struct device *dev); + +/* Legacy ISA bus related APIs */ +typedef void (*serial8250_isa_config_fn)(int, struct uart_port *, u32 *); +extern serial8250_isa_config_fn serial8250_isa_config; + +void serial8250_isa_init_ports(void); + +extern struct platform_device *serial8250_isa_devs; + +extern const struct uart_ops *univ8250_port_base_ops; +extern struct uart_ops univ8250_port_ops; static inline int serial_in(struct uart_8250_port *up, int offset) { @@ -200,6 +220,7 @@ static inline bool serial8250_clear_THRI(struct uart_8250_port *up) return true; } +struct uart_8250_port *serial8250_setup_port(int index); struct uart_8250_port *serial8250_get_port(int line); void serial8250_rpm_get(struct uart_8250_port *p); @@ -301,6 +322,12 @@ static inline int serial8250_pnp_init(void) { return 0; } static inline void serial8250_pnp_exit(void) { } #endif +#ifdef CONFIG_SERIAL_8250_RSA +void univ8250_rsa_support(struct uart_ops *ops); +#else +static inline void univ8250_rsa_support(struct uart_ops *ops) { } +#endif + #ifdef CONFIG_SERIAL_8250_FINTEK int fintek_8250_probe(struct uart_8250_port *uart); #else diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index b0adafc44747..29e4b83e0376 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -6,11 +6,9 @@ * * Copyright (C) 2001 Russell King. * - * Supports: ISA-compatible 8250/16550 ports - * PNP 8250/16550 ports + * Supports: * early_serial_setup() ports * userspace-configurable "phantom" ports - * "serial8250" platform devices * serial8250_register_8250_port() ports */ @@ -35,52 +33,13 @@ #include #include #include -#ifdef CONFIG_SPARC -#include -#endif #include #include "8250.h" -/* - * Configuration: - * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option - * is unsafe when used on edge-triggered interrupts. - */ -static unsigned int share_irqs = SERIAL8250_SHARE_IRQS; - -static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; - -static struct uart_driver serial8250_reg; - -static unsigned int skip_txen_test; /* force skip of txen test at init time */ - #define PASS_LIMIT 512 -#include -/* - * SERIAL_PORT_DFNS tells us about built-in ports that have no - * standard enumeration mechanism. Platforms that can find all - * serial ports via mechanisms like ACPI or PCI need not supply it. - */ -#ifndef SERIAL_PORT_DFNS -#define SERIAL_PORT_DFNS -#endif - -static const struct old_serial_port old_serial_port[] = { - SERIAL_PORT_DFNS /* defined in asm/serial.h */ -}; - -#define UART_NR CONFIG_SERIAL_8250_NR_UARTS - -#ifdef CONFIG_SERIAL_8250_RSA - -#define PORT_RSA_MAX 4 -static unsigned long probe_rsa[PORT_RSA_MAX]; -static unsigned int probe_rsa_count; -#endif /* CONFIG_SERIAL_8250_RSA */ - struct irq_info { struct hlist_node node; int irq; @@ -345,45 +304,8 @@ static void univ8250_release_irq(struct uart_8250_port *up) serial_unlink_irq_chain(up); } -#ifdef CONFIG_SERIAL_8250_RSA -static int serial8250_request_rsa_resource(struct uart_8250_port *up) -{ - unsigned long start = UART_RSA_BASE << up->port.regshift; - unsigned int size = 8 << up->port.regshift; - struct uart_port *port = &up->port; - int ret = -EINVAL; - - switch (port->iotype) { - case UPIO_HUB6: - case UPIO_PORT: - start += port->iobase; - if (request_region(start, size, "serial-rsa")) - ret = 0; - else - ret = -EBUSY; - break; - } - - return ret; -} - -static void serial8250_release_rsa_resource(struct uart_8250_port *up) -{ - unsigned long offset = UART_RSA_BASE << up->port.regshift; - unsigned int size = 8 << up->port.regshift; - struct uart_port *port = &up->port; - - switch (port->iotype) { - case UPIO_HUB6: - case UPIO_PORT: - release_region(port->iobase + offset, size); - break; - } -} -#endif - -static const struct uart_ops *base_ops; -static struct uart_ops univ8250_port_ops; +const struct uart_ops *univ8250_port_base_ops = NULL; +struct uart_ops univ8250_port_ops; static const struct uart_8250_ops univ8250_driver_ops = { .setup_irq = univ8250_setup_irq, @@ -411,85 +333,12 @@ struct uart_8250_port *serial8250_get_port(int line) } EXPORT_SYMBOL_GPL(serial8250_get_port); -static void (*serial8250_isa_config)(int port, struct uart_port *up, - u32 *capabilities); - -void serial8250_set_isa_configurator( - void (*v)(int port, struct uart_port *up, u32 *capabilities)) -{ - serial8250_isa_config = v; -} -EXPORT_SYMBOL(serial8250_set_isa_configurator); - -#ifdef CONFIG_SERIAL_8250_RSA - -static void univ8250_config_port(struct uart_port *port, int flags) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - up->probe &= ~UART_PROBE_RSA; - if (port->type == PORT_RSA) { - if (serial8250_request_rsa_resource(up) == 0) - up->probe |= UART_PROBE_RSA; - } else if (flags & UART_CONFIG_TYPE) { - int i; - - for (i = 0; i < probe_rsa_count; i++) { - if (probe_rsa[i] == up->port.iobase) { - if (serial8250_request_rsa_resource(up) == 0) - up->probe |= UART_PROBE_RSA; - break; - } - } - } - - base_ops->config_port(port, flags); - - if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA) - serial8250_release_rsa_resource(up); -} - -static int univ8250_request_port(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - int ret; - - ret = base_ops->request_port(port); - if (ret == 0 && port->type == PORT_RSA) { - ret = serial8250_request_rsa_resource(up); - if (ret < 0) - base_ops->release_port(port); - } - - return ret; -} - -static void univ8250_release_port(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - if (port->type == PORT_RSA) - serial8250_release_rsa_resource(up); - base_ops->release_port(port); -} - -static void univ8250_rsa_support(struct uart_ops *ops) -{ - ops->config_port = univ8250_config_port; - ops->request_port = univ8250_request_port; - ops->release_port = univ8250_release_port; -} - -#else -#define univ8250_rsa_support(x) do { } while (0) -#endif /* CONFIG_SERIAL_8250_RSA */ - static inline void serial8250_apply_quirks(struct uart_8250_port *up) { up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0; } -static struct uart_8250_port *serial8250_setup_port(int index) +struct uart_8250_port *serial8250_setup_port(int index) { struct uart_8250_port *up; @@ -501,8 +350,8 @@ static struct uart_8250_port *serial8250_setup_port(int index) up->port.port_id = index; serial8250_init_port(up); - if (!base_ops) - base_ops = up->port.ops; + if (!univ8250_port_base_ops) + univ8250_port_base_ops = up->port.ops; up->port.ops = &univ8250_port_ops; timer_setup(&up->timer, serial8250_timeout, 0); @@ -514,57 +363,7 @@ static struct uart_8250_port *serial8250_setup_port(int index) return up; } -static void __init serial8250_isa_init_ports(void) -{ - struct uart_8250_port *up; - static int first = 1; - int i, irqflag = 0; - - if (!first) - return; - first = 0; - - if (nr_uarts > UART_NR) - nr_uarts = UART_NR; - - /* - * Set up initial isa ports based on nr_uart module param, or else - * 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++) - serial8250_setup_port(i); - - /* chain base port ops to support Remote Supervisor Adapter */ - univ8250_port_ops = *base_ops; - univ8250_rsa_support(&univ8250_port_ops); - - if (share_irqs) - irqflag = IRQF_SHARED; - - for (i = 0, up = serial8250_ports; - i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; - i++, up++) { - struct uart_port *port = &up->port; - - port->iobase = old_serial_port[i].port; - port->irq = irq_canonicalize(old_serial_port[i].irq); - port->irqflags = 0; - port->uartclk = old_serial_port[i].baud_base * 16; - port->flags = old_serial_port[i].flags; - port->hub6 = 0; - port->membase = old_serial_port[i].iomem_base; - port->iotype = old_serial_port[i].io_type; - port->regshift = old_serial_port[i].iomem_reg_shift; - - port->irqflags |= irqflag; - if (serial8250_isa_config != NULL) - serial8250_isa_config(i, &up->port, &up->capabilities); - } -} - -static void __init -serial8250_register_ports(struct uart_driver *drv, struct device *dev) +void __init serial8250_register_ports(struct uart_driver *drv, struct device *dev) { int i; @@ -721,7 +520,7 @@ console_initcall(univ8250_console_init); #define SERIAL8250_CONSOLE NULL #endif -static struct uart_driver serial8250_reg = { +struct uart_driver serial8250_reg = { .owner = THIS_MODULE, .driver_name = "serial", .dev_name = "ttyS", @@ -822,120 +621,6 @@ void serial8250_resume_port(int line) } EXPORT_SYMBOL(serial8250_resume_port); -/* - * Register a set of serial devices attached to a platform device. The - * list is terminated with a zero flags entry, which means we expect - * all entries to have at least UPF_BOOT_AUTOCONF set. - */ -static int serial8250_probe(struct platform_device *dev) -{ - struct plat_serial8250_port *p = dev_get_platdata(&dev->dev); - struct uart_8250_port uart; - int ret, i, irqflag = 0; - - memset(&uart, 0, sizeof(uart)); - - if (share_irqs) - irqflag = IRQF_SHARED; - - for (i = 0; p && p->flags != 0; p++, i++) { - uart.port.iobase = p->iobase; - uart.port.membase = p->membase; - uart.port.irq = p->irq; - uart.port.irqflags = p->irqflags; - uart.port.uartclk = p->uartclk; - uart.port.regshift = p->regshift; - uart.port.iotype = p->iotype; - uart.port.flags = p->flags; - uart.port.mapbase = p->mapbase; - uart.port.mapsize = p->mapsize; - uart.port.hub6 = p->hub6; - uart.port.has_sysrq = p->has_sysrq; - uart.port.private_data = p->private_data; - uart.port.type = p->type; - uart.bugs = p->bugs; - uart.port.serial_in = p->serial_in; - uart.port.serial_out = p->serial_out; - uart.dl_read = p->dl_read; - uart.dl_write = p->dl_write; - uart.port.handle_irq = p->handle_irq; - uart.port.handle_break = p->handle_break; - uart.port.set_termios = p->set_termios; - uart.port.set_ldisc = p->set_ldisc; - uart.port.get_mctrl = p->get_mctrl; - uart.port.pm = p->pm; - uart.port.dev = &dev->dev; - uart.port.irqflags |= irqflag; - ret = serial8250_register_8250_port(&uart); - if (ret < 0) { - dev_err(&dev->dev, "unable to register port at index %d " - "(IO%lx MEM%llx IRQ%d): %d\n", i, - p->iobase, (unsigned long long)p->mapbase, - p->irq, ret); - } - } - return 0; -} - -/* - * Remove serial ports registered against a platform device. - */ -static void serial8250_remove(struct platform_device *dev) -{ - int i; - - for (i = 0; i < nr_uarts; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; - - if (up->port.dev == &dev->dev) - serial8250_unregister_port(i); - } -} - -static int serial8250_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - - for (i = 0; i < UART_NR; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; - - if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) - uart_suspend_port(&serial8250_reg, &up->port); - } - - return 0; -} - -static int serial8250_resume(struct platform_device *dev) -{ - int i; - - for (i = 0; i < UART_NR; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; - - if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) - serial8250_resume_port(i); - } - - return 0; -} - -static struct platform_driver serial8250_isa_driver = { - .probe = serial8250_probe, - .remove_new = serial8250_remove, - .suspend = serial8250_suspend, - .resume = serial8250_resume, - .driver = { - .name = "serial8250", - }, -}; - -/* - * This "device" covers _all_ ISA 8250-compatible serial devices listed - * in the table in include/asm/serial.h - */ -static struct platform_device *serial8250_isa_devs; - /* * serial8250_register_8250_port and serial8250_unregister_port allows for * 16x50 serial ports to be configured at run-time, to support PCMCIA @@ -1212,134 +897,5 @@ void serial8250_unregister_port(int line) } EXPORT_SYMBOL(serial8250_unregister_port); -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", - nr_uarts, str_enabled_disabled(share_irqs)); - -#ifdef CONFIG_SPARC - ret = sunserial_register_minors(&serial8250_reg, UART_NR); -#else - serial8250_reg.nr = UART_NR; - ret = uart_register_driver(&serial8250_reg); -#endif - if (ret) - goto out; - - ret = serial8250_pnp_init(); - if (ret) - goto unreg_uart_drv; - - serial8250_isa_devs = platform_device_alloc("serial8250", - PLAT8250_DEV_LEGACY); - if (!serial8250_isa_devs) { - ret = -ENOMEM; - goto unreg_pnp; - } - - ret = platform_device_add(serial8250_isa_devs); - if (ret) - goto put_dev; - - serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); - - ret = platform_driver_register(&serial8250_isa_driver); - if (ret == 0) - goto out; - - platform_device_del(serial8250_isa_devs); -put_dev: - platform_device_put(serial8250_isa_devs); -unreg_pnp: - serial8250_pnp_exit(); -unreg_uart_drv: -#ifdef CONFIG_SPARC - sunserial_unregister_minors(&serial8250_reg, UART_NR); -#else - uart_unregister_driver(&serial8250_reg); -#endif -out: - return ret; -} - -static void __exit serial8250_exit(void) -{ - struct platform_device *isa_dev = serial8250_isa_devs; - - /* - * This tells serial8250_unregister_port() not to re-register - * the ports (thereby making serial8250_isa_driver permanently - * in use.) - */ - serial8250_isa_devs = NULL; - - platform_driver_unregister(&serial8250_isa_driver); - platform_device_unregister(isa_dev); - - serial8250_pnp_exit(); - -#ifdef CONFIG_SPARC - sunserial_unregister_minors(&serial8250_reg, UART_NR); -#else - uart_unregister_driver(&serial8250_reg); -#endif -} - -module_init(serial8250_init); -module_exit(serial8250_exit); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); - -module_param_hw(share_irqs, uint, other, 0644); -MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)"); - -module_param(nr_uarts, uint, 0644); -MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); - -module_param(skip_txen_test, uint, 0644); -MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time"); - -#ifdef CONFIG_SERIAL_8250_RSA -module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444); -MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); -#endif -MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); - -#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS -#ifndef MODULE -/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name - * working as well for the module options so we don't break people. We - * need to keep the names identical and the convenient macros will happily - * refuse to let us do that by failing the build with redefinition errors - * of global variables. So we stick them inside a dummy function to avoid - * those conflicts. The options still get parsed, and the redefined - * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. - * - * This is hacky. I'm sorry. - */ -static void __used s8250_options(void) -{ -#undef MODULE_PARAM_PREFIX -#define MODULE_PARAM_PREFIX "8250_core." - - module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644); - module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644); - module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644); -#ifdef CONFIG_SERIAL_8250_RSA - __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, - ¶m_array_ops, .arr = &__param_arr_probe_rsa, - 0444, -1, 0); -#endif -} -#else -MODULE_ALIAS("8250_core"); -#endif -#endif diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index fb809e32c6ae..ab9e7f204260 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -616,7 +616,7 @@ static int dw8250_probe(struct platform_device *pdev) if (IS_ERR(data->pclk)) return PTR_ERR(data->pclk); - data->rst = devm_reset_control_get_optional_exclusive(dev, NULL); + data->rst = devm_reset_control_array_get_optional_exclusive(dev); if (IS_ERR(data->rst)) return PTR_ERR(data->rst); diff --git a/drivers/tty/serial/8250/8250_parisc.c b/drivers/tty/serial/8250/8250_parisc.c index 948d0a1c6ae8..4ba05a98791c 100644 --- a/drivers/tty/serial/8250/8250_parisc.c +++ b/drivers/tty/serial/8250/8250_parisc.c @@ -127,4 +127,5 @@ static int __init probe_serial_gsc(void) module_init(probe_serial_gsc); +MODULE_DESCRIPTION("Serial Device Initialisation for Lasi/Asp/Wax/Dino"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_pcilib.c b/drivers/tty/serial/8250/8250_pcilib.c index d234e9194feb..ea906d721b2c 100644 --- a/drivers/tty/serial/8250/8250_pcilib.c +++ b/drivers/tty/serial/8250/8250_pcilib.c @@ -37,4 +37,5 @@ int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port, return 0; } EXPORT_SYMBOL_NS_GPL(serial8250_pci_setup_port, SERIAL_8250_PCI); +MODULE_DESCRIPTION("8250 PCI library"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c new file mode 100644 index 000000000000..d5c8d851348d --- /dev/null +++ b/drivers/tty/serial/8250/8250_platform.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Universal/legacy platform driver for 8250/16550-type serial ports + * + * Supports: ISA-compatible 8250/16550 ports + * PNP 8250/16550 ports + * "serial8250" platform devices + */ +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_SPARC +#include +#endif + +#include "8250.h" + +/* + * Configuration: + * share_irqs Whether we pass IRQF_SHARED to request_irq(). + * This option is unsafe when used on edge-triggered interrupts. + * skip_txen_test Force skip of txen test at init time. + */ +unsigned int share_irqs = SERIAL8250_SHARE_IRQS; +unsigned int skip_txen_test; + +unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; + +#include + +/* + * SERIAL_PORT_DFNS tells us about built-in ports that have no + * standard enumeration mechanism. Platforms that can find all + * serial ports via mechanisms like ACPI or PCI need not supply it. + */ +#ifndef SERIAL_PORT_DFNS +#define SERIAL_PORT_DFNS +#endif + +static const struct old_serial_port old_serial_port[] = { + SERIAL_PORT_DFNS /* defined in asm/serial.h */ +}; + +serial8250_isa_config_fn serial8250_isa_config; +void serial8250_set_isa_configurator(serial8250_isa_config_fn v) +{ + serial8250_isa_config = v; +} +EXPORT_SYMBOL(serial8250_set_isa_configurator); + +static void __init __serial8250_isa_init_ports(void) +{ + int i, irqflag = 0; + + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; + + /* + * Set up initial isa ports based on nr_uart module param, or else + * 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++) + serial8250_setup_port(i); + + /* chain base port ops to support Remote Supervisor Adapter */ + univ8250_port_ops = *univ8250_port_base_ops; + univ8250_rsa_support(&univ8250_port_ops); + + if (share_irqs) + irqflag = IRQF_SHARED; + + for (i = 0; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++) { + struct uart_8250_port *up = serial8250_get_port(i); + struct uart_port *port = &up->port; + + port->iobase = old_serial_port[i].port; + port->irq = irq_canonicalize(old_serial_port[i].irq); + port->irqflags = 0; + port->uartclk = old_serial_port[i].baud_base * 16; + port->flags = old_serial_port[i].flags; + port->hub6 = 0; + port->membase = old_serial_port[i].iomem_base; + port->iotype = old_serial_port[i].io_type; + port->regshift = old_serial_port[i].iomem_reg_shift; + + port->irqflags |= irqflag; + if (serial8250_isa_config != NULL) + serial8250_isa_config(i, &up->port, &up->capabilities); + } +} + +void __init serial8250_isa_init_ports(void) +{ + DO_ONCE(__serial8250_isa_init_ports); +} + +/* + * Register a set of serial devices attached to a platform device. The + * list is terminated with a zero flags entry, which means we expect + * all entries to have at least UPF_BOOT_AUTOCONF set. + */ +static int serial8250_probe(struct platform_device *dev) +{ + struct plat_serial8250_port *p = dev_get_platdata(&dev->dev); + struct uart_8250_port uart; + int ret, i, irqflag = 0; + + memset(&uart, 0, sizeof(uart)); + + if (share_irqs) + irqflag = IRQF_SHARED; + + for (i = 0; p && p->flags != 0; p++, i++) { + uart.port.iobase = p->iobase; + uart.port.membase = p->membase; + uart.port.irq = p->irq; + uart.port.irqflags = p->irqflags; + uart.port.uartclk = p->uartclk; + uart.port.regshift = p->regshift; + uart.port.iotype = p->iotype; + uart.port.flags = p->flags; + uart.port.mapbase = p->mapbase; + uart.port.mapsize = p->mapsize; + uart.port.hub6 = p->hub6; + uart.port.has_sysrq = p->has_sysrq; + uart.port.private_data = p->private_data; + uart.port.type = p->type; + uart.bugs = p->bugs; + uart.port.serial_in = p->serial_in; + uart.port.serial_out = p->serial_out; + uart.dl_read = p->dl_read; + uart.dl_write = p->dl_write; + uart.port.handle_irq = p->handle_irq; + uart.port.handle_break = p->handle_break; + uart.port.set_termios = p->set_termios; + uart.port.set_ldisc = p->set_ldisc; + uart.port.get_mctrl = p->get_mctrl; + uart.port.pm = p->pm; + uart.port.dev = &dev->dev; + uart.port.irqflags |= irqflag; + ret = serial8250_register_8250_port(&uart); + if (ret < 0) { + dev_err(&dev->dev, "unable to register port at index %d " + "(IO%lx MEM%llx IRQ%d): %d\n", i, + p->iobase, (unsigned long long)p->mapbase, + p->irq, ret); + } + } + return 0; +} + +/* + * Remove serial ports registered against a platform device. + */ +static void serial8250_remove(struct platform_device *dev) +{ + int i; + + for (i = 0; i < nr_uarts; i++) { + struct uart_8250_port *up = serial8250_get_port(i); + + if (up->port.dev == &dev->dev) + serial8250_unregister_port(i); + } +} + +static int serial8250_suspend(struct platform_device *dev, pm_message_t state) +{ + int i; + + for (i = 0; i < UART_NR; i++) { + struct uart_8250_port *up = serial8250_get_port(i); + + if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) + uart_suspend_port(&serial8250_reg, &up->port); + } + + return 0; +} + +static int serial8250_resume(struct platform_device *dev) +{ + int i; + + for (i = 0; i < UART_NR; i++) { + struct uart_8250_port *up = serial8250_get_port(i); + + if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) + serial8250_resume_port(i); + } + + return 0; +} + +static struct platform_driver serial8250_isa_driver = { + .probe = serial8250_probe, + .remove_new = serial8250_remove, + .suspend = serial8250_suspend, + .resume = serial8250_resume, + .driver = { + .name = "serial8250", + }, +}; + +/* + * This "device" covers _all_ ISA 8250-compatible serial devices listed + * in the table in include/asm/serial.h + */ +struct platform_device *serial8250_isa_devs; + +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", + nr_uarts, str_enabled_disabled(share_irqs)); + +#ifdef CONFIG_SPARC + ret = sunserial_register_minors(&serial8250_reg, UART_NR); +#else + serial8250_reg.nr = UART_NR; + ret = uart_register_driver(&serial8250_reg); +#endif + if (ret) + goto out; + + ret = serial8250_pnp_init(); + if (ret) + goto unreg_uart_drv; + + serial8250_isa_devs = platform_device_alloc("serial8250", + PLAT8250_DEV_LEGACY); + if (!serial8250_isa_devs) { + ret = -ENOMEM; + goto unreg_pnp; + } + + ret = platform_device_add(serial8250_isa_devs); + if (ret) + goto put_dev; + + serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); + + ret = platform_driver_register(&serial8250_isa_driver); + if (ret == 0) + goto out; + + platform_device_del(serial8250_isa_devs); +put_dev: + platform_device_put(serial8250_isa_devs); +unreg_pnp: + serial8250_pnp_exit(); +unreg_uart_drv: +#ifdef CONFIG_SPARC + sunserial_unregister_minors(&serial8250_reg, UART_NR); +#else + uart_unregister_driver(&serial8250_reg); +#endif +out: + return ret; +} +module_init(serial8250_init); + +static void __exit serial8250_exit(void) +{ + struct platform_device *isa_dev = serial8250_isa_devs; + + /* + * This tells serial8250_unregister_port() not to re-register + * the ports (thereby making serial8250_isa_driver permanently + * in use.) + */ + serial8250_isa_devs = NULL; + + platform_driver_unregister(&serial8250_isa_driver); + platform_device_unregister(isa_dev); + + serial8250_pnp_exit(); + +#ifdef CONFIG_SPARC + sunserial_unregister_minors(&serial8250_reg, UART_NR); +#else + uart_unregister_driver(&serial8250_reg); +#endif +} +module_exit(serial8250_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic 8250/16x50 serial platform driver"); + +module_param_hw(share_irqs, uint, other, 0644); +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)"); + +module_param(nr_uarts, uint, 0644); +MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); + +module_param(skip_txen_test, uint, 0644); +MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time"); + +MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); + +#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS +#ifndef MODULE +/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name + * working as well for the module options so we don't break people. We + * need to keep the names identical and the convenient macros will happily + * refuse to let us do that by failing the build with redefinition errors + * of global variables. So we stick them inside a dummy function to avoid + * those conflicts. The options still get parsed, and the redefined + * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. + * + * This is hacky. I'm sorry. + */ +static void __used s8250_options(void) +{ +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX "8250_core." + + module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644); + module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644); + module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644); +} +#else +MODULE_ALIAS("8250_core"); +#endif +#endif diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 893bc493f662..2786918aea98 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3473,4 +3473,5 @@ int serial8250_console_exit(struct uart_port *port) #endif /* CONFIG_SERIAL_8250_CONSOLE */ +MODULE_DESCRIPTION("Base port operations for 8250/16550-type serial ports"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index ba96fa913e7f..1ac86b565374 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -182,5 +182,6 @@ OF_EARLYCON_DECLARE(mmp, "mrvl,mmp-uart", early_serial_pxa_setup); #endif MODULE_AUTHOR("Sergei Ianovich"); +MODULE_DESCRIPTION("driver for PXA on-board UARTS"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pxa2xx-uart"); diff --git a/drivers/tty/serial/8250/8250_rsa.c b/drivers/tty/serial/8250/8250_rsa.c new file mode 100644 index 000000000000..dfaa613e452d --- /dev/null +++ b/drivers/tty/serial/8250/8250_rsa.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include + +#include +#include + +#include "8250.h" + +#define PORT_RSA_MAX 4 +static unsigned long probe_rsa[PORT_RSA_MAX]; +static unsigned int probe_rsa_count; + +static int rsa8250_request_resource(struct uart_8250_port *up) +{ + unsigned long start = UART_RSA_BASE << up->port.regshift; + unsigned int size = 8 << up->port.regshift; + struct uart_port *port = &up->port; + int ret = -EINVAL; + + switch (port->iotype) { + case UPIO_HUB6: + case UPIO_PORT: + start += port->iobase; + if (request_region(start, size, "serial-rsa")) + ret = 0; + else + ret = -EBUSY; + break; + } + + return ret; +} + +static void rsa8250_release_resource(struct uart_8250_port *up) +{ + unsigned long offset = UART_RSA_BASE << up->port.regshift; + unsigned int size = 8 << up->port.regshift; + struct uart_port *port = &up->port; + + switch (port->iotype) { + case UPIO_HUB6: + case UPIO_PORT: + release_region(port->iobase + offset, size); + break; + } +} + +static void univ8250_config_port(struct uart_port *port, int flags) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int i; + + up->probe &= ~UART_PROBE_RSA; + if (port->type == PORT_RSA) { + if (rsa8250_request_resource(up) == 0) + up->probe |= UART_PROBE_RSA; + } else if (flags & UART_CONFIG_TYPE) { + for (i = 0; i < probe_rsa_count; i++) { + if (probe_rsa[i] == up->port.iobase) { + if (rsa8250_request_resource(up) == 0) + up->probe |= UART_PROBE_RSA; + break; + } + } + } + + univ8250_port_base_ops->config_port(port, flags); + + if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA) + rsa8250_release_resource(up); +} + +static int univ8250_request_port(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + int ret; + + ret = univ8250_port_base_ops->request_port(port); + if (ret == 0 && port->type == PORT_RSA) { + ret = rsa8250_request_resource(up); + if (ret < 0) + univ8250_port_base_ops->release_port(port); + } + + return ret; +} + +static void univ8250_release_port(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + if (port->type == PORT_RSA) + rsa8250_release_resource(up); + univ8250_port_base_ops->release_port(port); +} + +void univ8250_rsa_support(struct uart_ops *ops) +{ + ops->config_port = univ8250_config_port; + ops->request_port = univ8250_request_port; + ops->release_port = univ8250_release_port; +} + +module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444); +MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); + +#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS +#ifndef MODULE +/* + * Keep the old "8250" name working as well for the module options so we don't + * break people. We need to keep the names identical and the convenient macros + * will happily refuse to let us do that by failing the build with redefinition + * errors of global variables. So we stick them inside a dummy function to + * avoid those conflicts. The options still get parsed, and the redefined + * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. + * + * This is hacky. I'm sorry. + */ +static void __used rsa8250_options(void) +{ +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX "8250_core." + + __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, + ¶m_array_ops, .arr = &__param_arr_probe_rsa, + 0444, -1, 0); +} +#endif +#endif diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 69ac00270547..1516de629b61 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -3,9 +3,13 @@ # Makefile for the 8250 serial device drivers. # -obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o +obj-$(CONFIG_SERIAL_8250) += 8250.o 8250-y := 8250_core.o +8250-y += 8250_platform.o 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +8250-$(CONFIG_SERIAL_8250_RSA) += 8250_rsa.o + +obj-$(CONFIG_SERIAL_8250) += 8250_base.o 8250_base-y := 8250_port.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o 8250_base-$(CONFIG_SERIAL_8250_DWLIB) += 8250_dwlib.o diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 2056aed46688..58e279ea7ee0 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -864,4 +864,5 @@ static struct pcmcia_driver serial_cs_driver = { }; module_pcmcia_driver(serial_cs_driver); +MODULE_DESCRIPTION("driver for PCMCIA serial devices"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/esp32_acm.c b/drivers/tty/serial/esp32_acm.c index d4e8bdb1cdef..85eb0392e379 100644 --- a/drivers/tty/serial/esp32_acm.c +++ b/drivers/tty/serial/esp32_acm.c @@ -455,4 +455,5 @@ module_init(esp32s3_acm_init); module_exit(esp32s3_acm_exit); MODULE_AUTHOR("Max Filippov "); +MODULE_DESCRIPTION("Espressif ESP32 USB ACM gadget support"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/esp32_uart.c b/drivers/tty/serial/esp32_uart.c index 6fc61f323355..8c86cf9cb763 100644 --- a/drivers/tty/serial/esp32_uart.c +++ b/drivers/tty/serial/esp32_uart.c @@ -775,4 +775,5 @@ module_init(esp32_uart_init); module_exit(esp32_uart_exit); MODULE_AUTHOR("Max Filippov "); +MODULE_DESCRIPTION("Espressif ESP32 UART support"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index ff32cd2d2863..67d4a72eda77 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -265,6 +265,11 @@ static const struct of_device_id imx_uart_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, imx_uart_dt_ids); +static inline struct imx_port *to_imx_port(struct uart_port *port) +{ + return container_of(port, struct imx_port, port); +} + static inline void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset) { writel(val, sport->port.membase + offset); @@ -378,7 +383,7 @@ static void imx_uart_disable_loopback_rs485(struct imx_port *sport) /* called with port.lock taken and irqs off */ static void imx_uart_start_rx(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned int ucr1, ucr2; ucr1 = imx_uart_readl(sport, UCR1); @@ -402,7 +407,7 @@ static void imx_uart_start_rx(struct uart_port *port) /* called with port.lock taken and irqs off */ static void imx_uart_stop_tx(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); u32 ucr1, ucr4, usr2; if (sport->tx_state == OFF) @@ -467,7 +472,7 @@ static void imx_uart_stop_tx(struct uart_port *port) static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); u32 ucr1, ucr2, ucr4, uts; ucr1 = imx_uart_readl(sport, UCR1); @@ -512,7 +517,7 @@ static void imx_uart_stop_rx(struct uart_port *port) /* called with port.lock taken and irqs off */ static void imx_uart_enable_ms(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); mod_timer(&sport->timer, jiffies); @@ -663,7 +668,7 @@ static void imx_uart_dma_tx(struct imx_port *sport) /* called with port.lock taken and irqs off */ static void imx_uart_start_tx(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); struct tty_port *tport = &sport->port.state->port; u32 ucr1; @@ -1044,7 +1049,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) */ static unsigned int imx_uart_tx_empty(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned int ret; ret = (imx_uart_readl(sport, USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0; @@ -1059,7 +1064,7 @@ static unsigned int imx_uart_tx_empty(struct uart_port *port) /* called with port.lock taken and irqs off */ static unsigned int imx_uart_get_mctrl(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned int ret = imx_uart_get_hwmctrl(sport); mctrl_gpio_get(sport->gpios, &ret); @@ -1070,7 +1075,7 @@ static unsigned int imx_uart_get_mctrl(struct uart_port *port) /* called with port.lock taken and irqs off */ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); u32 ucr3, uts; if (!(port->rs485.flags & SER_RS485_ENABLED)) { @@ -1113,7 +1118,7 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) */ static void imx_uart_break_ctl(struct uart_port *port, int break_state) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned long flags; u32 ucr1; @@ -1435,7 +1440,7 @@ static void imx_uart_disable_dma(struct imx_port *sport) static int imx_uart_startup(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); int retval; unsigned long flags; int dma_is_inited = 0; @@ -1549,7 +1554,7 @@ static int imx_uart_startup(struct uart_port *port) static void imx_uart_shutdown(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned long flags; u32 ucr1, ucr2, ucr4, uts; int loops; @@ -1674,7 +1679,7 @@ static void imx_uart_shutdown(struct uart_port *port) /* called with port.lock taken and irqs off */ static void imx_uart_flush_buffer(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); struct scatterlist *sgl = &sport->tx_sgl[0]; if (!sport->dma_chan_tx) @@ -1701,7 +1706,7 @@ static void imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, const struct ktermios *old) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned long flags; u32 ucr2, old_ucr2, ufcr; unsigned int baud, quot; @@ -1904,7 +1909,7 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser) static int imx_uart_poll_init(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned long flags; u32 ucr1, ucr2; int retval; @@ -1953,7 +1958,7 @@ static int imx_uart_poll_init(struct uart_port *port) static int imx_uart_poll_get_char(struct uart_port *port) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); if (!(imx_uart_readl(sport, USR2) & USR2_RDR)) return NO_POLL_CHAR; @@ -1962,7 +1967,7 @@ static int imx_uart_poll_get_char(struct uart_port *port) static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); unsigned int status; /* drain */ @@ -1984,7 +1989,7 @@ static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c) static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485conf) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); u32 ucr2, ufcr; if (rs485conf->flags & SER_RS485_ENABLED) { @@ -2043,7 +2048,7 @@ static struct imx_port *imx_uart_ports[UART_NR]; #if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch) { - struct imx_port *sport = (struct imx_port *)port; + struct imx_port *sport = to_imx_port(port); while (imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL) barrier(); diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 8b60ac0ad7cd..ecec483d4d59 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -761,4 +761,5 @@ static void __exit owl_uart_exit(void) module_init(owl_uart_init); module_exit(owl_uart_exit); +MODULE_DESCRIPTION("Actions Semi Owl family serial console"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index bf0065d1c8e9..c79dcd7c8d1a 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1467,6 +1468,29 @@ static const struct serial_rs485 sc16is7xx_rs485_supported = { .delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */ }; +/* Reset device, purging any pending irq / data */ +static int sc16is7xx_reset(struct device *dev, struct regmap *regmap) +{ + struct gpio_desc *reset_gpio; + + /* Assert reset GPIO if defined and valid. */ + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to get reset GPIO\n"); + + if (reset_gpio) { + /* The minimum reset pulse width is 3 us. */ + fsleep(5); + gpiod_set_value_cansleep(reset_gpio, 0); /* Deassert GPIO */ + } else { + /* Software reset */ + regmap_write(regmap, SC16IS7XX_IOCONTROL_REG, + SC16IS7XX_IOCONTROL_SRESET_BIT); + } + + return 0; +} + int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, struct regmap *regmaps[], int irq) { @@ -1536,9 +1560,9 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, } sched_set_fifo(s->kworker_task); - /* reset device, purging any pending irq / data */ - regmap_write(regmaps[0], SC16IS7XX_IOCONTROL_REG, - SC16IS7XX_IOCONTROL_SRESET_BIT); + ret = sc16is7xx_reset(dev, regmaps[0]); + if (ret) + goto out_kthread; /* Mark each port line and status as uninitialised. */ for (i = 0; i < devtype->nr_uart; ++i) { @@ -1663,6 +1687,7 @@ out_ports: uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port); } +out_kthread: kthread_stop(s->kworker_task); out_clk: diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_base.h index b6c38d2edfd4..0d50db5b660b 100644 --- a/drivers/tty/serial/serial_base.h +++ b/drivers/tty/serial/serial_base.h @@ -49,3 +49,19 @@ void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port int serial_core_register_port(struct uart_driver *drv, struct uart_port *port); void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port); + +#ifdef CONFIG_SERIAL_CORE_CONSOLE + +int serial_base_match_and_update_preferred_console(struct uart_driver *drv, + struct uart_port *port); + +#else + +static inline +int serial_base_match_and_update_preferred_console(struct uart_driver *drv, + struct uart_port *port) +{ + return 0; +} + +#endif diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c index 4df2a4b10445..d822499ba9d6 100644 --- a/drivers/tty/serial/serial_base_bus.c +++ b/drivers/tty/serial/serial_base_bus.c @@ -8,6 +8,7 @@ * The serial core bus manages the serial core controller instances. */ +#include #include #include #include @@ -204,6 +205,42 @@ void serial_base_port_device_remove(struct serial_port_device *port_dev) put_device(&port_dev->dev); } +#ifdef CONFIG_SERIAL_CORE_CONSOLE + +/** + * serial_base_match_and_update_preferred_console - Match and update a preferred console + * @drv: Serial port device driver + * @port: Serial port instance + * + * Tries to match and update the preferred console for a serial port for + * the kernel command line option console=DEVNAME:0.0. + * + * Cannot be called early for ISA ports, depends on struct device. + * + * Return: 0 on success, negative error code on failure. + */ +int serial_base_match_and_update_preferred_console(struct uart_driver *drv, + struct uart_port *port) +{ + const char *port_match __free(kfree) = NULL; + int ret; + + port_match = kasprintf(GFP_KERNEL, "%s:%d.%d", dev_name(port->dev), + port->ctrl_id, port->port_id); + if (!port_match) + return -ENOMEM; + + ret = match_devname_and_update_preferred_console(port_match, + drv->dev_name, + port->line); + if (ret == -ENOENT) + return 0; + + return ret; +} + +#endif + static int serial_base_init(void) { int ret; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2a8006e3d687..9a18d0b95a41 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3422,6 +3422,10 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port) if (ret) goto err_unregister_ctrl_dev; + ret = serial_base_match_and_update_preferred_console(drv, port); + if (ret) + goto err_unregister_port_dev; + ret = serial_core_add_one_port(drv, port); if (ret) goto err_unregister_port_dev; diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c index e51ca593ab86..8855688a5b6c 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -385,4 +385,5 @@ void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios) } EXPORT_SYMBOL_GPL(mctrl_gpio_disable_irq_wake); +MODULE_DESCRIPTION("Helpers for controlling modem lines via GPIO"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index f738980a8b2c..b80e9a528e17 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -317,6 +317,37 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { .error_clear = SCIF_ERROR_CLEAR, }, + /* + * The "SCIF" that is in RZ/V2H(P) SoC is similar to one found on RZ/G2L SoC + * with below differences, + * - Break out of interrupts are different: ERI, BRI, RXI, TXI, TEI, DRI, + * TEI-DRI, RXI-EDGE and TXI-EDGE. + * - SCSMR register does not have CM bit (BIT(7)) ie it does not support synchronous mode. + * - SCFCR register does not have SCFCR_MCE bit. + * - SCSPTR register has only bits SCSPTR_SPB2DT and SCSPTR_SPB2IO. + */ + [SCIx_RZV2H_SCIF_REGTYPE] = { + .regs = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x02, 8 }, + [SCSCR] = { 0x04, 16 }, + [SCxTDR] = { 0x06, 8 }, + [SCxSR] = { 0x08, 16 }, + [SCxRDR] = { 0x0a, 8 }, + [SCFCR] = { 0x0c, 16 }, + [SCFDR] = { 0x0e, 16 }, + [SCSPTR] = { 0x10, 16 }, + [SCLSR] = { 0x12, 16 }, + [SEMR] = { 0x14, 8 }, + }, + .fifosize = 16, + .overrun_reg = SCLSR, + .overrun_mask = SCLSR_ORER, + .sampling_rate_mask = SCI_SR(32), + .error_mask = SCIF_DEFAULT_ERROR_MASK, + .error_clear = SCIF_ERROR_CLEAR, + }, + /* * Common SH-3 SCIF definitions. */ @@ -757,7 +788,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) } sci_serial_out(port, SCPDR, data); sci_serial_out(port, SCPCR, ctrl); - } else if (sci_getreg(port, SCSPTR)->size) { + } else if (sci_getreg(port, SCSPTR)->size && s->cfg->regtype != SCIx_RZV2H_SCIF_REGTYPE) { u16 status = sci_serial_in(port, SCSPTR); /* RTS# is always output; and active low, unless autorts */ @@ -2124,8 +2155,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) if (!(mctrl & TIOCM_RTS)) { /* Disable Auto RTS */ - sci_serial_out(port, SCFCR, - sci_serial_in(port, SCFCR) & ~SCFCR_MCE); + if (s->cfg->regtype != SCIx_RZV2H_SCIF_REGTYPE) + sci_serial_out(port, SCFCR, + sci_serial_in(port, SCFCR) & ~SCFCR_MCE); /* Clear RTS */ sci_set_rts(port, 0); @@ -2137,8 +2169,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) } /* Enable Auto RTS */ - sci_serial_out(port, SCFCR, - sci_serial_in(port, SCFCR) | SCFCR_MCE); + if (s->cfg->regtype != SCIx_RZV2H_SCIF_REGTYPE) + sci_serial_out(port, SCFCR, + sci_serial_in(port, SCFCR) | SCFCR_MCE); } else { /* Set RTS */ sci_set_rts(port, 1); @@ -3225,6 +3258,10 @@ static const struct of_device_id of_sci_match[] __maybe_unused = { .compatible = "renesas,scif-r9a07g044", .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE), }, + { + .compatible = "renesas,scif-r9a09g057", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZV2H_SCIF_REGTYPE), + }, /* Family-specific types */ { .compatible = "renesas,rcar-gen1-scif", @@ -3533,6 +3570,13 @@ static int __init rzscifa_early_console_setup(struct earlycon_device *device, return early_console_setup(device, PORT_SCIF); } +static int __init rzv2hscif_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + port_cfg.regtype = SCIx_RZV2H_SCIF_REGTYPE; + return early_console_setup(device, PORT_SCIF); +} + static int __init scifa_early_console_setup(struct earlycon_device *device, const char *opt) { @@ -3553,6 +3597,7 @@ OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup); OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup); OF_EARLYCON_DECLARE(scif, "renesas,scif-r7s9210", rzscifa_early_console_setup); OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a07g044", rzscifa_early_console_setup); +OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a09g057", rzv2hscif_early_console_setup); OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup); OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup); OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup); diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 67a5fc70bb4b..0f463da5e7ce 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -1382,44 +1382,29 @@ static inline struct console *SUNSU_CONSOLE(void) static enum su_type su_get_type(struct device_node *dp) { - struct device_node *ap = of_find_node_by_path("/aliases"); - enum su_type rc = SU_PORT_PORT; + struct device_node *ap __free(device_node) = + of_find_node_by_path("/aliases"); if (ap) { const char *keyb = of_get_property(ap, "keyboard", NULL); const char *ms = of_get_property(ap, "mouse", NULL); - struct device_node *match; if (keyb) { - match = of_find_node_by_path(keyb); + struct device_node *match __free(device_node) = + of_find_node_by_path(keyb); - /* - * The pointer is used as an identifier not - * as a pointer, we can drop the refcount on - * the of__node immediately after getting it. - */ - of_node_put(match); - - if (dp == match) { - rc = SU_PORT_KBD; - goto out; - } + if (dp == match) + return SU_PORT_KBD; } if (ms) { - match = of_find_node_by_path(ms); + struct device_node *match __free(device_node) = + of_find_node_by_path(ms); - of_node_put(match); - - if (dp == match) { - rc = SU_PORT_MS; - goto out; - } + if (dp == match) + return SU_PORT_MS; } } - -out: - of_node_put(ap); - return rc; + return SU_PORT_PORT; } static int su_probe(struct platform_device *op) diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 8112d9d5a0d8..bd8d92ee7c53 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -89,6 +89,7 @@ */ static const char driver_name[] = "SyncLink GT"; static const char tty_dev_prefix[] = "ttySLG"; +MODULE_DESCRIPTION("Device driver for Microgate SyncLink GT serial adapters"); MODULE_LICENSE("GPL"); #define MAX_DEVICES 32 diff --git a/drivers/tty/ttynull.c b/drivers/tty/ttynull.c index e4c4273993bc..6b2f7208b564 100644 --- a/drivers/tty/ttynull.c +++ b/drivers/tty/ttynull.c @@ -106,4 +106,5 @@ static void __exit ttynull_exit(void) module_init(ttynull_init); module_exit(ttynull_exit); +MODULE_DESCRIPTION("NULL TTY driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index a2116e135a82..804355da46f5 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1033,9 +1033,7 @@ static int kbd_led_trigger_activate(struct led_classdev *cdev) tasklet_disable(&keyboard_tasklet); if (ledstate != -1U) - led_trigger_event(&trigger->trigger, - ledstate & trigger->mask ? - LED_FULL : LED_OFF); + led_set_brightness(cdev, ledstate & trigger->mask ? LED_FULL : LED_OFF); tasklet_enable(&keyboard_tasklet); return 0; diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 5ce429286ab0..20d2a55cb40b 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -1145,4 +1145,5 @@ static void __exit uio_exit(void) module_init(uio_init) module_exit(uio_exit) +MODULE_DESCRIPTION("Userspace IO core module"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c index 64eafd59e6e7..8c164e51ff9e 100644 --- a/drivers/uio/uio_aec.c +++ b/drivers/uio/uio_aec.c @@ -144,4 +144,5 @@ static struct pci_driver pci_driver = { }; module_pci_driver(pci_driver); +MODULE_DESCRIPTION("Adrienne Electronics Corp time code PCI device"); MODULE_LICENSE("GPL"); diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c index 653f842a1491..1cc3b8b5a345 100644 --- a/drivers/uio/uio_cif.c +++ b/drivers/uio/uio_cif.c @@ -130,5 +130,6 @@ static struct pci_driver hilscher_pci_driver = { module_pci_driver(hilscher_pci_driver); MODULE_DEVICE_TABLE(pci, hilscher_pci_ids); +MODULE_DESCRIPTION("UIO Hilscher CIF card driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger"); diff --git a/drivers/uio/uio_mf624.c b/drivers/uio/uio_mf624.c index 5065c6a073a8..790412f8dfd5 100644 --- a/drivers/uio/uio_mf624.c +++ b/drivers/uio/uio_mf624.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * UIO driver fo Humusoft MF624 DAQ card. + * UIO driver for Humusoft MF624 DAQ card. * Copyright (C) 2011 Rostislav Lisovy , * Czech Technical University in Prague */ @@ -221,5 +221,6 @@ static struct pci_driver mf624_pci_driver = { MODULE_DEVICE_TABLE(pci, mf624_pci_id); module_pci_driver(mf624_pci_driver); +MODULE_DESCRIPTION("UIO driver for Humusoft MF624 DAQ card"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Rostislav Lisovy "); diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c index 2319d6de8d04..a1a58802c793 100644 --- a/drivers/uio/uio_netx.c +++ b/drivers/uio/uio_netx.c @@ -170,5 +170,6 @@ static struct pci_driver netx_pci_driver = { module_pci_driver(netx_pci_driver); MODULE_DEVICE_TABLE(pci, netx_pci_ids); +MODULE_DESCRIPTION("UIO driver for Hilscher NetX based fieldbus cards"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Hans J. Koch, Manuel Traut"); diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index 5945c4b1e11f..cfabc12ee0e3 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c @@ -16,6 +16,7 @@ #include #include #include +#include "core.h" /* USB Wrapper register offsets */ #define USBSS_PID 0x0 @@ -85,6 +86,18 @@ static inline void cdns_ti_writel(struct cdns_ti *data, u32 offset, u32 value) writel(value, data->usbss + offset); } +static struct cdns3_platform_data cdns_ti_pdata = { + .quirks = CDNS3_DRD_SUSPEND_RESIDENCY_ENABLE, /* Errata i2409 */ +}; + +static const struct of_dev_auxdata cdns_ti_auxdata[] = { + { + .compatible = "cdns,usb3", + .platform_data = &cdns_ti_pdata, + }, + {}, +}; + static int cdns_ti_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -176,7 +189,7 @@ static int cdns_ti_probe(struct platform_device *pdev) reg |= USBSS_W1_PWRUP_RST; cdns_ti_writel(data, USBSS_W1, reg); - error = of_platform_populate(node, NULL, NULL, dev); + error = of_platform_populate(node, NULL, cdns_ti_auxdata, dev); if (error) { dev_err(dev, "failed to create children: %d\n", error); goto err; diff --git a/drivers/usb/cdns3/cdnsp-pci.c b/drivers/usb/cdns3/cdnsp-pci.c index 0725668ffea4..225540fc81ba 100644 --- a/drivers/usb/cdns3/cdnsp-pci.c +++ b/drivers/usb/cdns3/cdnsp-pci.c @@ -231,7 +231,7 @@ static const struct pci_device_id cdnsp_pci_ids[] = { static struct pci_driver cdnsp_pci_driver = { .name = "cdnsp-pci", - .id_table = &cdnsp_pci_ids[0], + .id_table = cdnsp_pci_ids, .probe = cdnsp_pci_probe, .remove = cdnsp_pci_remove, .driver = { diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h index 81a9c9d6be08..57d47348dc19 100644 --- a/drivers/usb/cdns3/core.h +++ b/drivers/usb/cdns3/core.h @@ -44,6 +44,7 @@ struct cdns3_platform_data { bool suspend, bool wakeup); unsigned long quirks; #define CDNS3_DEFAULT_PM_RUNTIME_ALLOW BIT(0) +#define CDNS3_DRD_SUSPEND_RESIDENCY_ENABLE BIT(1) }; /** diff --git a/drivers/usb/cdns3/drd.c b/drivers/usb/cdns3/drd.c index 8b936a2e93a0..84fb38a5723a 100644 --- a/drivers/usb/cdns3/drd.c +++ b/drivers/usb/cdns3/drd.c @@ -389,7 +389,7 @@ static irqreturn_t cdns_drd_irq(int irq, void *data) int cdns_drd_init(struct cdns *cdns) { void __iomem *regs; - u32 state; + u32 state, reg; int ret; regs = devm_ioremap_resource(cdns->dev, &cdns->otg_res); @@ -433,6 +433,14 @@ int cdns_drd_init(struct cdns *cdns) cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *) &cdns->otg_v1_regs->ien; writel(1, &cdns->otg_v1_regs->simulate); + + if (cdns->pdata && + (cdns->pdata->quirks & CDNS3_DRD_SUSPEND_RESIDENCY_ENABLE)) { + reg = readl(&cdns->otg_v1_regs->susp_ctrl); + reg |= SUSP_CTRL_SUSPEND_RESIDENCY_ENABLE; + writel(reg, &cdns->otg_v1_regs->susp_ctrl); + } + cdns->version = CDNS3_CONTROLLER_V1; } else { dev_err(cdns->dev, "not supported DID=0x%08x\n", state); diff --git a/drivers/usb/cdns3/drd.h b/drivers/usb/cdns3/drd.h index d72370c321d3..1e2aee14d629 100644 --- a/drivers/usb/cdns3/drd.h +++ b/drivers/usb/cdns3/drd.h @@ -193,6 +193,9 @@ struct cdns_otg_irq_regs { /* OTGREFCLK - bitmasks */ #define OTGREFCLK_STB_CLK_SWITCH_EN BIT(31) +/* SUPS_CTRL - bitmasks */ +#define SUSP_CTRL_SUSPEND_RESIDENCY_ENABLE BIT(17) + /* OVERRIDE - bitmasks */ #define OVERRIDE_IDPULLUP BIT(0) /* Only for CDNS3_CONTROLLER_V0 version */ diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index a17b6d619305..bdc04ce919f7 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -557,7 +557,7 @@ static void ci_hdrc_imx_shutdown(struct platform_device *pdev) ci_hdrc_imx_remove(pdev); } -static int __maybe_unused imx_controller_suspend(struct device *dev, +static int imx_controller_suspend(struct device *dev, pm_message_t msg) { struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); @@ -582,7 +582,7 @@ static int __maybe_unused imx_controller_suspend(struct device *dev, return 0; } -static int __maybe_unused imx_controller_resume(struct device *dev, +static int imx_controller_resume(struct device *dev, pm_message_t msg) { struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); @@ -618,7 +618,7 @@ clk_disable: return ret; } -static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) +static int ci_hdrc_imx_suspend(struct device *dev) { int ret; @@ -636,7 +636,7 @@ static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) return ret; } -static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) +static int ci_hdrc_imx_resume(struct device *dev) { struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); int ret; @@ -652,7 +652,7 @@ static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) return ret; } -static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev) +static int ci_hdrc_imx_runtime_suspend(struct device *dev) { struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); @@ -664,15 +664,14 @@ static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev) return imx_controller_suspend(dev, PMSG_AUTO_SUSPEND); } -static int __maybe_unused ci_hdrc_imx_runtime_resume(struct device *dev) +static int ci_hdrc_imx_runtime_resume(struct device *dev) { return imx_controller_resume(dev, PMSG_AUTO_RESUME); } static const struct dev_pm_ops ci_hdrc_imx_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume) - SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend, - ci_hdrc_imx_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume) + RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend, ci_hdrc_imx_runtime_resume, NULL) }; static struct platform_driver ci_hdrc_imx_driver = { .probe = ci_hdrc_imx_probe, @@ -681,7 +680,7 @@ static struct platform_driver ci_hdrc_imx_driver = { .driver = { .name = "imx_usb", .of_match_table = ci_hdrc_imx_dt_ids, - .pm = &ci_hdrc_imx_pm_ops, + .pm = pm_ptr(&ci_hdrc_imx_pm_ops), }, }; diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 7b5b47ce8a02..1661639cd2eb 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -303,4 +303,5 @@ module_platform_driver(ci_hdrc_msm_driver); MODULE_ALIAS("platform:msm_hsusb"); MODULE_ALIAS("platform:ci13xxx_msm"); +MODULE_DESCRIPTION("ChipIdea Highspeed Dual Role Controller"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c index 2cc305803217..9538d425f0a0 100644 --- a/drivers/usb/chipidea/ci_hdrc_tegra.c +++ b/drivers/usb/chipidea/ci_hdrc_tegra.c @@ -372,7 +372,7 @@ static void tegra_usb_remove(struct platform_device *pdev) pm_runtime_force_suspend(&pdev->dev); } -static int __maybe_unused tegra_usb_runtime_resume(struct device *dev) +static int tegra_usb_runtime_resume(struct device *dev) { struct tegra_usb *usb = dev_get_drvdata(dev); int err; @@ -386,7 +386,7 @@ static int __maybe_unused tegra_usb_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused tegra_usb_runtime_suspend(struct device *dev) +static int tegra_usb_runtime_suspend(struct device *dev) { struct tegra_usb *usb = dev_get_drvdata(dev); @@ -396,15 +396,14 @@ static int __maybe_unused tegra_usb_runtime_suspend(struct device *dev) } static const struct dev_pm_ops tegra_usb_pm = { - SET_RUNTIME_PM_OPS(tegra_usb_runtime_suspend, tegra_usb_runtime_resume, - NULL) + RUNTIME_PM_OPS(tegra_usb_runtime_suspend, tegra_usb_runtime_resume, NULL) }; static struct platform_driver tegra_usb_driver = { .driver = { .name = "tegra-usb", .of_match_table = tegra_usb_of_match, - .pm = &tegra_usb_pm, + .pm = pm_ptr(&tegra_usb_pm), }, .probe = tegra_usb_probe, .remove_new = tegra_usb_remove, diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 311007b1d904..6bd9fe565385 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2592,4 +2592,5 @@ static struct usb_driver usbtmc_driver = { module_usb_driver(usbtmc_driver); +MODULE_DESCRIPTION("USB Test & Measurement class driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index b84efae26e15..59b55d6cf490 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -433,4 +433,5 @@ static void __exit usb_common_exit(void) subsys_initcall(usb_common_init); module_exit(usb_common_exit); +MODULE_DESCRIPTION("Common code for host and device side USB"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c index 0697fde51d00..e11803225775 100644 --- a/drivers/usb/common/usb-otg-fsm.c +++ b/drivers/usb/common/usb-otg-fsm.c @@ -449,4 +449,5 @@ int otg_statemachine(struct otg_fsm *fsm) return fsm->state_changed; } EXPORT_SYMBOL_GPL(otg_statemachine); +MODULE_DESCRIPTION("OTG Finite State Machine"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index e02ba15f6e34..b35734d03109 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -517,6 +517,19 @@ static int usb_unbind_interface(struct device *dev) return 0; } +static void usb_shutdown_interface(struct device *dev) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_driver *driver; + + if (!dev->driver) + return; + + driver = to_usb_driver(dev->driver); + if (driver->shutdown) + driver->shutdown(intf); +} + /** * usb_driver_claim_interface - bind a driver to an interface * @driver: the driver to be bound @@ -1059,6 +1072,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, new_driver->driver.bus = &usb_bus_type; new_driver->driver.probe = usb_probe_interface; new_driver->driver.remove = usb_unbind_interface; + new_driver->driver.shutdown = usb_shutdown_interface; new_driver->driver.owner = owner; new_driver->driver.mod_name = mod_name; new_driver->driver.dev_groups = new_driver->dev_groups; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a0c432b14b20..0b4685aad2d5 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1150,4 +1150,5 @@ static void __exit usb_exit(void) subsys_initcall(usb_init); module_exit(usb_exit); +MODULE_DESCRIPTION("USB core host-side support"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 74ac79abd8f3..e7bf9cc635be 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -885,10 +885,10 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, } /* DMA sg buffer */ - for_each_sg(ureq->sg, sg, ureq->num_sgs, i) { + for_each_sg(ureq->sg, sg, ureq->num_mapped_sgs, i) { dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc, sg_dma_address(sg) + sg->offset, sg_dma_len(sg), - sg_is_last(sg)); + (i == (ureq->num_mapped_sgs - 1))); desc_count += hs_ep->desc_count; } diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 5a1500d0bdd9..a937eadbc9b3 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -133,7 +133,15 @@ static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) p->no_clock_gating = true; } -static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) +static void dwc2_set_ltq_danube_params(struct dwc2_hsotg *hsotg) +{ + struct dwc2_core_params *p = &hsotg->params; + + p->otg_caps.hnp_support = false; + p->otg_caps.srp_support = false; +} + +static void dwc2_set_ltq_ase_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; @@ -142,12 +150,21 @@ static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) p->host_rx_fifo_size = 288; p->host_nperio_tx_fifo_size = 128; p->host_perio_tx_fifo_size = 96; - p->max_transfer_size = 65535; - p->max_packet_count = 511; p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; } +static void dwc2_set_ltq_xrx200_params(struct dwc2_hsotg *hsotg) +{ + struct dwc2_core_params *p = &hsotg->params; + + p->otg_caps.hnp_support = false; + p->otg_caps.srp_support = false; + p->host_rx_fifo_size = 288; + p->host_nperio_tx_fifo_size = 128; + p->host_perio_tx_fifo_size = 136; +} + static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; @@ -297,8 +314,11 @@ const struct of_device_id dwc2_of_match_table[] = { { .compatible = "ingenic,x1830-otg", .data = dwc2_set_x1600_params }, { .compatible = "ingenic,x2000-otg", .data = dwc2_set_x2000_params }, { .compatible = "rockchip,rk3066-usb", .data = dwc2_set_rk_params }, - { .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params }, - { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, + { .compatible = "lantiq,danube-usb", .data = &dwc2_set_ltq_danube_params }, + { .compatible = "lantiq,ase-usb", .data = &dwc2_set_ltq_ase_params }, + { .compatible = "lantiq,arx100-usb", .data = &dwc2_set_ltq_ase_params }, + { .compatible = "lantiq,xrx200-usb", .data = &dwc2_set_ltq_xrx200_params }, + { .compatible = "lantiq,xrx300-usb", .data = &dwc2_set_ltq_xrx200_params }, { .compatible = "snps,dwc2" }, { .compatible = "samsung,s3c6400-hsotg", .data = dwc2_set_s3c6400_params }, diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index cb82557678dd..734de2a8bd21 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -108,22 +108,27 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) { u32 reg; + int i; - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - if (enable && !dwc->dis_u3_susphy_quirk) - reg |= DWC3_GUSB3PIPECTL_SUSPHY; - else - reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; + for (i = 0; i < dwc->num_usb3_ports; i++) { + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(i)); + if (enable && !dwc->dis_u3_susphy_quirk) + reg |= DWC3_GUSB3PIPECTL_SUSPHY; + else + reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(i), reg); + } - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - if (enable && !dwc->dis_u2_susphy_quirk) - reg |= DWC3_GUSB2PHYCFG_SUSPHY; - else - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + for (i = 0; i < dwc->num_usb2_ports; i++) { + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i)); + if (enable && !dwc->dis_u2_susphy_quirk) + reg |= DWC3_GUSB2PHYCFG_SUSPHY; + else + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg); + } } void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) @@ -599,6 +604,18 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) parms->hwparams9 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS9); } +static void dwc3_config_soc_bus(struct dwc3 *dwc) +{ + if (dwc->gsbuscfg0_reqinfo != DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) { + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0); + reg &= ~DWC3_GSBUSCFG0_REQINFO(~0); + reg |= DWC3_GSBUSCFG0_REQINFO(dwc->gsbuscfg0_reqinfo); + dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, reg); + } +} + static int dwc3_core_ulpi_init(struct dwc3 *dwc) { int intf; @@ -1338,6 +1355,8 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_set_incr_burst_type(dwc); + dwc3_config_soc_bus(dwc); + ret = dwc3_phy_power_on(dwc); if (ret) goto err_exit_phy; @@ -1576,6 +1595,27 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); } +static void dwc3_get_software_properties(struct dwc3 *dwc) +{ + struct device *tmpdev; + u16 gsbuscfg0_reqinfo; + int ret; + + dwc->gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED; + + /* + * Iterate over all parent nodes for finding swnode properties + * and non-DT (non-ABI) properties. + */ + for (tmpdev = dwc->dev; tmpdev; tmpdev = tmpdev->parent) { + ret = device_property_read_u16(tmpdev, + "snps,gsbuscfg0-reqinfo", + &gsbuscfg0_reqinfo); + if (!ret) + dwc->gsbuscfg0_reqinfo = gsbuscfg0_reqinfo; + } +} + static void dwc3_get_properties(struct dwc3 *dwc) { struct device *dev = dwc->dev; @@ -2090,6 +2130,8 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_get_properties(dwc); + dwc3_get_software_properties(dwc); + dwc->reset = devm_reset_control_array_get_optional_shared(dev); if (IS_ERR(dwc->reset)) { ret = PTR_ERR(dwc->reset); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 3781c736c1a1..1e561fd8b86e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -194,6 +194,10 @@ #define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */ #define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff +/* Global SoC Bus Configuration Register: AHB-prot/AXI-cache/OCP-ReqInfo */ +#define DWC3_GSBUSCFG0_REQINFO(n) (((n) & 0xffff) << 16) +#define DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED 0xffffffff + /* Global Debug LSP MUX Select */ #define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */ #define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff) @@ -1153,6 +1157,9 @@ struct dwc3_scratchpad_array { * @num_ep_resized: carries the current number endpoints which have had its tx * fifo resized. * @debug_root: root debugfs directory for this device to put its files in. + * @gsbuscfg0_reqinfo: store GSBUSCFG0.DATRDREQINFO, DESRDREQINFO, + * DATWRREQINFO, and DESWRREQINFO value passed from + * glue driver. */ struct dwc3 { struct work_struct drd_work; @@ -1380,6 +1387,7 @@ struct dwc3 { int last_fifo_depth; int num_ep_resized; struct dentry *debug_root; + u32 gsbuscfg0_reqinfo; }; #define INCRX_BURST_MODE 0 diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c index 6095f4dee6ce..bb4d894c16e9 100644 --- a/drivers/usb/dwc3/dwc3-xilinx.c +++ b/drivers/usb/dwc3/dwc3-xilinx.c @@ -246,6 +246,31 @@ static const struct of_device_id dwc3_xlnx_of_match[] = { }; MODULE_DEVICE_TABLE(of, dwc3_xlnx_of_match); +static int dwc3_set_swnode(struct device *dev) +{ + struct device_node *np = dev->of_node, *dwc3_np; + struct property_entry props[2]; + int prop_idx = 0, ret = 0; + + dwc3_np = of_get_compatible_child(np, "snps,dwc3"); + if (!dwc3_np) { + ret = -ENODEV; + dev_err(dev, "failed to find dwc3 core child\n"); + return ret; + } + + memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); + if (of_dma_is_coherent(dwc3_np)) + props[prop_idx++] = PROPERTY_ENTRY_U16("snps,gsbuscfg0-reqinfo", + 0xffff); + of_node_put(dwc3_np); + + if (prop_idx) + ret = device_create_managed_software_node(dev, props, NULL); + + return ret; +} + static int dwc3_xlnx_probe(struct platform_device *pdev) { struct dwc3_xlnx *priv_data; @@ -288,6 +313,10 @@ static int dwc3_xlnx_probe(struct platform_device *pdev) if (ret) goto err_clk_put; + ret = dwc3_set_swnode(dev); + if (ret) + goto err_clk_put; + ret = of_platform_populate(np, NULL, NULL, dev); if (ret) goto err_clk_put; diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index a171b27a7845..e0533cee6870 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -126,7 +126,7 @@ out: int dwc3_host_init(struct dwc3 *dwc) { - struct property_entry props[5]; + struct property_entry props[6]; struct platform_device *xhci; int ret, irq; int prop_idx = 0; @@ -162,6 +162,8 @@ int dwc3_host_init(struct dwc3 *dwc) props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk"); + props[prop_idx++] = PROPERTY_ENTRY_BOOL("write-64-hi-lo-quirk"); + if (dwc->usb3_lpm_capable) props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable"); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index dd794a723070..2cfb421c6dda 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2806,5 +2806,6 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, } EXPORT_SYMBOL_GPL(usb_composite_overwrite_options); +MODULE_DESCRIPTION("infrastructure for Composite USB Gadgets"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index f616059c5e1e..724b2631f249 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -854,4 +854,5 @@ static struct usb_function_instance *acm_alloc_instance(void) return &opts->func_inst; } DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); +MODULE_DESCRIPTION("USB CDC serial (ACM) function driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index f55f60639e42..6cb7771e8a69 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -966,5 +966,6 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc); +MODULE_DESCRIPTION("USB CDC Ethernet (ECM) link function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c index 3b445bd88498..6de81ea17274 100644 --- a/drivers/usb/gadget/function/f_eem.c +++ b/drivers/usb/gadget/function/f_eem.c @@ -674,5 +674,6 @@ static struct usb_function *eem_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(eem, eem_alloc_inst, eem_alloc); +MODULE_DESCRIPTION("USB CDC Ethernet (EEM) link function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index a057cbedf3c9..0616e248c136 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -4298,5 +4298,6 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len) } DECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc); +MODULE_DESCRIPTION("user mode file system API for USB composite function controllers"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Nazarewicz"); diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 2db01e03bfbf..93dae017ae45 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -1322,6 +1322,7 @@ err_unlock: } DECLARE_USB_FUNCTION_INIT(hid, hidg_alloc_inst, hidg_alloc); +MODULE_DESCRIPTION("USB HID function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Fabien Chouteau"); diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index 17ac6ace0cff..979b028edb99 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c @@ -593,4 +593,5 @@ void __exit lb_modexit(void) usb_function_unregister(&Loopbackusb_func); } +MODULE_DESCRIPTION("USB peripheral loopback configuration driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index c265a1f62fc1..cfd712fd7452 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3577,6 +3577,7 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc); +MODULE_DESCRIPTION("Mass Storage USB Composite Function"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Nazarewicz"); diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 20c6fbd94f32..67052a664e74 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -38,6 +38,7 @@ #include "u_midi.h" MODULE_AUTHOR("Ben Williamson"); +MODULE_DESCRIPTION("USB MIDI class function driver"); MODULE_LICENSE("GPL v2"); static const char f_midi_shortname[] = "f_midi"; diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c index ec8cd7c7bbfc..38e8ed3144f0 100644 --- a/drivers/usb/gadget/function/f_midi2.c +++ b/drivers/usb/gadget/function/f_midi2.c @@ -150,6 +150,9 @@ struct f_midi2 { #define func_to_midi2(f) container_of(f, struct f_midi2, func) +/* convert from MIDI protocol number (1 or 2) to SNDRV_UMP_EP_INFO_PROTO_* */ +#define to_ump_protocol(v) (((v) & 3) << 8) + /* get EP name string */ static const char *ump_ep_name(const struct f_midi2_ep *ep) { @@ -564,8 +567,7 @@ static void reply_ump_stream_ep_config(struct f_midi2_ep *ep) .status = UMP_STREAM_MSG_STATUS_STREAM_CFG, }; - if ((ep->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK) == - SNDRV_UMP_EP_INFO_PROTO_MIDI2) + if (ep->info.protocol == 2) rep.protocol = UMP_STREAM_MSG_EP_INFO_CAP_MIDI2 >> 8; else rep.protocol = UMP_STREAM_MSG_EP_INFO_CAP_MIDI1 >> 8; @@ -627,13 +629,13 @@ static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data) return; case UMP_STREAM_MSG_STATUS_STREAM_CFG_REQUEST: if (*data & UMP_STREAM_MSG_EP_INFO_CAP_MIDI2) { - ep->info.protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI2; + ep->info.protocol = 2; DBG(midi2, "Switching Protocol to MIDI2\n"); } else { - ep->info.protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI1; + ep->info.protocol = 1; DBG(midi2, "Switching Protocol to MIDI1\n"); } - snd_ump_switch_protocol(ep->ump, ep->info.protocol); + snd_ump_switch_protocol(ep->ump, to_ump_protocol(ep->info.protocol)); reply_ump_stream_ep_config(ep); return; case UMP_STREAM_MSG_STATUS_FB_DISCOVERY: @@ -1065,7 +1067,8 @@ static void f_midi2_midi1_ep_out_complete(struct usb_ep *usb_ep, group = midi2->out_cable_mapping[cable].group; bytes = midi1_packet_bytes[*buf & 0x0f]; for (c = 0; c < bytes; c++) { - snd_ump_convert_to_ump(cvt, group, ep->info.protocol, + snd_ump_convert_to_ump(cvt, group, + to_ump_protocol(ep->info.protocol), buf[c + 1]); if (cvt->ump_bytes) { snd_ump_receive(ep->ump, cvt->ump, @@ -1375,7 +1378,7 @@ static void assign_block_descriptors(struct f_midi2 *midi2, desc->nNumGroupTrm = b->num_groups; desc->iBlockItem = ep->blks[blk].string_id; - if (ep->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2) + if (ep->info.protocol == 2) desc->bMIDIProtocol = USB_MS_MIDI_PROTO_2_0; else desc->bMIDIProtocol = USB_MS_MIDI_PROTO_1_0_128; @@ -1552,7 +1555,7 @@ static int f_midi2_create_card(struct f_midi2 *midi2) if (midi2->info.static_block) ump->info.flags |= SNDRV_UMP_EP_INFO_STATIC_BLOCKS; ump->info.protocol_caps = (ep->info.protocol_caps & 3) << 8; - ump->info.protocol = (ep->info.protocol & 3) << 8; + ump->info.protocol = to_ump_protocol(ep->info.protocol); ump->info.version = 0x0101; ump->info.family_id = ep->info.family; ump->info.model_id = ep->info.model; @@ -2868,4 +2871,5 @@ static struct usb_function *f_midi2_alloc(struct usb_function_instance *fi) DECLARE_USB_FUNCTION_INIT(midi2, f_midi2_alloc_inst, f_midi2_alloc); +MODULE_DESCRIPTION("USB MIDI 2.0 class function driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 0acc32ed9960..8e761249d672 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1797,5 +1797,6 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(ncm, ncm_alloc_inst, ncm_alloc); +MODULE_DESCRIPTION("USB CDC Network (NCM) link function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yauheni Kaliuta"); diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index dcb093210305..1305e2326cdf 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -487,4 +487,5 @@ static struct usb_function *obex_alloc(struct usb_function_instance *fi) DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); MODULE_AUTHOR("Felipe Balbi"); +MODULE_DESCRIPTION("USB CDC OBEX function driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index 0bebbdf3f213..0aa9e8224cae 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -729,4 +729,5 @@ void gphonet_cleanup(struct net_device *dev) DECLARE_USB_FUNCTION_INIT(phonet, phonet_alloc_inst, phonet_alloc); MODULE_AUTHOR("Rémi Denis-Courmont"); +MODULE_DESCRIPTION("USB CDC Phonet function"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 44e20c6c36d3..ef2ffde625c3 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -1527,6 +1527,7 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(printer, gprinter_alloc_inst, gprinter_alloc); +MODULE_DESCRIPTION("USB printer function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Craig Nadler"); diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index b47f99d17ee9..7cec19d65fb5 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -1013,5 +1013,6 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc); +MODULE_DESCRIPTION("RNDIS link function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 65c50092aea2..8f7e7a2b2ff2 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -392,6 +392,7 @@ static struct usb_function *gser_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc); +MODULE_DESCRIPTION("generic USB serial function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Al Borchers"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 2edbd9b510d6..6f3702210450 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -1284,4 +1284,5 @@ static void __exit sslb_modexit(void) module_init(sslb_modinit); module_exit(sslb_modexit); +MODULE_DESCRIPTION("USB peripheral source/sink configuration driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_subset.c b/drivers/usb/gadget/function/f_subset.c index 8ae9689ef2a0..ea3fdd842462 100644 --- a/drivers/usb/gadget/function/f_subset.c +++ b/drivers/usb/gadget/function/f_subset.c @@ -500,5 +500,6 @@ static struct usb_function *geth_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc); +MODULE_DESCRIPTION("\"CDC Subset\" Ethernet link function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 37befd6db001..90906d714736 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -2301,5 +2301,6 @@ static void __exit tcm_exit(void) } module_exit(tcm_exit); +MODULE_DESCRIPTION("Target based USB-Gadget"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sebastian Andrzej Siewior"); diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 7de74a3dd392..2b9fb4daa806 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -1823,5 +1823,6 @@ static struct usb_function *f_audio_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc); +MODULE_DESCRIPTION("USB Audio Class 1.0 Function (using u_audio API)"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ruslan Bilovol"); diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c index e2d7f69128a0..49cf5aae90ca 100644 --- a/drivers/usb/gadget/function/f_uac1_legacy.c +++ b/drivers/usb/gadget/function/f_uac1_legacy.c @@ -1014,5 +1014,6 @@ static struct usb_function *f_audio_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(uac1_legacy, f_audio_alloc_inst, f_audio_alloc); +MODULE_DESCRIPTION("USB Audio class function driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Bryan Wu"); diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 383f6854cfec..2d6d3286ffde 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -2063,7 +2063,10 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ goto end; \ } \ \ - ret = scnprintf(opts->name, min(sizeof(opts->name), len), \ + if (len && page[len - 1] == '\n') \ + len--; \ + \ + ret = scnprintf(opts->name, min(sizeof(opts->name), len + 1), \ "%s", page); \ \ end: \ @@ -2251,6 +2254,7 @@ static struct usb_function *afunc_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc); +MODULE_DESCRIPTION("USB Audio Class 2.0 Function"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yadwinder Singh"); MODULE_AUTHOR("Jaswinder Singh"); diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 929666805bd2..40187b7112e7 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -1118,5 +1118,6 @@ err_config: } DECLARE_USB_FUNCTION_INIT(uvc, uvc_alloc_inst, uvc_alloc); +MODULE_DESCRIPTION("USB Video Class Gadget driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Laurent Pinchart"); diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c index 2a4163b0f6fe..75831f2c7abe 100644 --- a/drivers/usb/gadget/function/storage_common.c +++ b/drivers/usb/gadget/function/storage_common.c @@ -537,4 +537,5 @@ ssize_t fsg_store_forced_eject(struct fsg_lun *curlun, struct rw_semaphore *file } EXPORT_SYMBOL_GPL(fsg_store_forced_eject); +MODULE_DESCRIPTION("Common definitions for mass storage functionality"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 95191083b455..09e2838917e2 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -1245,5 +1245,6 @@ void gether_disconnect(struct gether *link) } EXPORT_SYMBOL_GPL(gether_disconnect); +MODULE_DESCRIPTION("Ethernet-over-USB link layer utilities for Gadget stack"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index a92eb6d90976..eec7f7a2e40f 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -1536,4 +1536,5 @@ static void __exit userial_cleanup(void) } module_exit(userial_cleanup); +MODULE_DESCRIPTION("utilities for USB gadget \"serial port\"/TTY support"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index b62e45235e8e..d70fb5bc2357 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -434,6 +434,7 @@ static void __exit dbgp_exit(void) } MODULE_AUTHOR("Stephane Duverger"); +MODULE_DESCRIPTION("EHCI Debug Port device gadget"); MODULE_LICENSE("GPL"); module_init(dbgp_init); module_exit(dbgp_exit); diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c index 265c392810d7..e4a419b19f45 100644 --- a/drivers/usb/gadget/legacy/gmidi.c +++ b/drivers/usb/gadget/legacy/gmidi.c @@ -31,6 +31,7 @@ /*-------------------------------------------------------------------------*/ MODULE_AUTHOR("Ben Williamson"); +MODULE_DESCRIPTION("USB MIDI Gadget Driver"); MODULE_LICENSE("GPL v2"); static const char longname[] = "MIDI Gadget"; diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c index 23312a07efb4..e25e0d8dd387 100644 --- a/drivers/usb/gadget/legacy/zero.c +++ b/drivers/usb/gadget/legacy/zero.c @@ -425,4 +425,5 @@ static struct usb_composite_driver zero_driver = { module_usb_composite_driver(zero_driver); MODULE_AUTHOR("David Brownell"); +MODULE_DESCRIPTION("Gadget Zero, for USB development"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c index 821a6ab5da56..f4781e611aaa 100644 --- a/drivers/usb/gadget/udc/aspeed_udc.c +++ b/drivers/usb/gadget/udc/aspeed_udc.c @@ -1009,6 +1009,8 @@ static void ast_udc_getstatus(struct ast_udc_dev *udc) break; case USB_RECIP_ENDPOINT: epnum = crq.wIndex & USB_ENDPOINT_NUMBER_MASK; + if (epnum >= AST_UDC_NUM_ENDPOINTS) + goto stall; status = udc->ep[epnum].stopped; break; default: diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c index 1691541c9413..50c3d0974d9b 100644 --- a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c +++ b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c @@ -121,7 +121,7 @@ static const struct pci_device_id cdns2_pci_ids[] = { static struct pci_driver cdns2_pci_driver = { .name = "cdns2-pci", - .id_table = &cdns2_pci_ids[0], + .id_table = cdns2_pci_ids, .probe = cdns2_pci_probe, .remove = cdns2_pci_remove, .driver = { diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 3c4d68fd5c33..bfa2eba4e3a7 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -293,4 +293,5 @@ module_exit(ohci_exynos_cleanup); MODULE_ALIAS("platform:exynos-ohci"); MODULE_AUTHOR("Jingoo Han "); +MODULE_DESCRIPTION("OHCI support for Samsung S5P/Exynos SoC Series"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index d467472f9d3c..3f871fe62b90 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -196,31 +196,6 @@ struct ehci_regs { #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) } __packed; -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct ehci_dbg_port { - u32 control; -#define DBGP_OWNER (1<<30) -#define DBGP_ENABLED (1<<28) -#define DBGP_DONE (1<<16) -#define DBGP_INUSE (1<<10) -#define DBGP_ERRCODE(x) (((x)>>7)&0x07) -# define DBGP_ERR_BAD 1 -# define DBGP_ERR_SIGNAL 2 -#define DBGP_ERROR (1<<6) -#define DBGP_GO (1<<5) -#define DBGP_OUT (1<<4) -#define DBGP_LEN(x) (((x)>>0)&0x0f) - u32 pids; -#define DBGP_PID_GET(x) (((x)>>16)&0xff) -#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) - u32 data03; - u32 data47; - u32 address; -#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) -} __packed; - #define QTD_NEXT(dma) cpu_to_le32((u32)dma) /* diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index 872d9cddbcef..161c09953c4e 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -1150,11 +1150,48 @@ static ssize_t dbc_bInterfaceProtocol_store(struct device *dev, return size; } +static ssize_t dbc_poll_interval_ms_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct xhci_dbc *dbc; + struct xhci_hcd *xhci; + + xhci = hcd_to_xhci(dev_get_drvdata(dev)); + dbc = xhci->dbc; + + return sysfs_emit(buf, "%u\n", dbc->poll_interval); +} + +static ssize_t dbc_poll_interval_ms_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct xhci_dbc *dbc; + struct xhci_hcd *xhci; + u32 value; + int ret; + + ret = kstrtou32(buf, 0, &value); + if (ret || value > DBC_POLL_INTERVAL_MAX) + return -EINVAL; + + xhci = hcd_to_xhci(dev_get_drvdata(dev)); + dbc = xhci->dbc; + + dbc->poll_interval = value; + + mod_delayed_work(system_wq, &dbc->event_work, 0); + + return size; +} + static DEVICE_ATTR_RW(dbc); static DEVICE_ATTR_RW(dbc_idVendor); static DEVICE_ATTR_RW(dbc_idProduct); static DEVICE_ATTR_RW(dbc_bcdDevice); static DEVICE_ATTR_RW(dbc_bInterfaceProtocol); +static DEVICE_ATTR_RW(dbc_poll_interval_ms); static struct attribute *dbc_dev_attrs[] = { &dev_attr_dbc.attr, @@ -1162,6 +1199,7 @@ static struct attribute *dbc_dev_attrs[] = { &dev_attr_dbc_idProduct.attr, &dev_attr_dbc_bcdDevice.attr, &dev_attr_dbc_bInterfaceProtocol.attr, + &dev_attr_dbc_poll_interval_ms.attr, NULL }; ATTRIBUTE_GROUPS(dbc_dev); diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h index 92661b555c2a..0118c6288a3c 100644 --- a/drivers/usb/host/xhci-dbgcap.h +++ b/drivers/usb/host/xhci-dbgcap.h @@ -95,7 +95,7 @@ struct dbc_ep { #define DBC_QUEUE_SIZE 16 #define DBC_WRITE_BUF_SIZE 8192 #define DBC_POLL_INTERVAL_DEFAULT 64 /* milliseconds */ - +#define DBC_POLL_INTERVAL_MAX 5000 /* milliseconds */ /* * Private structure for DbC hardware state: */ diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 3100219d6496..d7654f475daf 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -136,10 +136,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, if (!ring || !first || !last) return; - /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ - chain_links = !!(xhci_link_trb_quirk(xhci) || - (ring->type == TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))); + chain_links = xhci_link_chain_quirk(xhci, ring->type); next = ring->enq_seg->next; xhci_link_segments(ring->enq_seg, first, ring->type, chain_links); @@ -156,7 +153,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, ring->last_seg = last; } - for (seg = last; seg != ring->last_seg; seg = seg->next) + for (seg = ring->enq_seg; seg != ring->last_seg; seg = seg->next) seg->next->num = seg->num + 1; } @@ -327,18 +324,19 @@ EXPORT_SYMBOL_GPL(xhci_initialize_ring_info); /* Allocate segments and link them for a ring */ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, - struct xhci_segment **first, struct xhci_segment **last, - unsigned int num_segs, unsigned int num, - unsigned int cycle_state, enum xhci_ring_type type, - unsigned int max_packet, gfp_t flags) + struct xhci_segment **first, + struct xhci_segment **last, + unsigned int num_segs, + unsigned int cycle_state, + enum xhci_ring_type type, + unsigned int max_packet, + gfp_t flags) { struct xhci_segment *prev; + unsigned int num = 0; bool chain_links; - /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ - chain_links = !!(xhci_link_trb_quirk(xhci) || - (type == TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))); + chain_links = xhci_link_chain_quirk(xhci, type); prev = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags); if (!prev) @@ -394,9 +392,8 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, if (num_segs == 0) return ring; - ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg, - &ring->last_seg, num_segs, 0, cycle_state, type, - max_packet, flags); + ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg, &ring->last_seg, num_segs, + cycle_state, type, max_packet, flags); if (ret) goto fail; @@ -434,10 +431,8 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, struct xhci_segment *last; int ret; - ret = xhci_alloc_segments_for_ring(xhci, &first, &last, - num_new_segs, ring->enq_seg->num + 1, - ring->cycle_state, ring->type, - ring->bounce_buf_len, flags); + ret = xhci_alloc_segments_for_ring(xhci, &first, &last, num_new_segs, ring->cycle_state, + ring->type, ring->bounce_buf_len, flags); if (ret) return -ENOMEM; @@ -2325,7 +2320,10 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); erst_base &= ERST_BASE_RSVDP; erst_base |= ir->erst.erst_dma_addr & ~ERST_BASE_RSVDP; - xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); + if (xhci->quirks & XHCI_WRITE_64_HI_LO) + hi_lo_writeq(erst_base, &ir->ir_set->erst_base); + else + xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); /* Set the event ring dequeue address of this interrupter */ xhci_set_hc_event_deq(xhci, ir); diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c index 93f8b355bc70..247cc7c2ce70 100644 --- a/drivers/usb/host/xhci-pci-renesas.c +++ b/drivers/usb/host/xhci-pci-renesas.c @@ -627,4 +627,5 @@ exit: } EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw); +MODULE_DESCRIPTION("Support for Renesas xHCI controller with firmware"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 05881153883e..dc1e345ab67e 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -50,6 +50,7 @@ #define PCI_DEVICE_ID_INTEL_DENVERTON_XHCI 0x19d0 #define PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI 0x8a13 #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 +#define PCI_DEVICE_ID_INTEL_TIGER_LAKE_PCH_XHCI 0xa0ed #define PCI_DEVICE_ID_INTEL_COMET_LAKE_XHCI 0xa3af #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI 0x54ed @@ -373,7 +374,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_MISSING_CAS; if (pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || + (pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_PCH_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI)) xhci->quirks |= XHCI_RESET_TO_DEFAULT; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 3d071b875308..31bdfa52eeb2 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -256,6 +256,9 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk")) xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK; + if (device_property_read_bool(tmpdev, "write-64-hi-lo-quirk")) + xhci->quirks |= XHCI_WRITE_64_HI_LO; + device_property_read_u32(tmpdev, "imod-interval-ns", &xhci->imod_interval); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fd0cde3d1569..b7517c3c8059 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -250,9 +250,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, * AMD 0.96 host, carry over the chain bit of the previous TRB * (which may mean the chain bit is cleared). */ - if (!(ring->type == TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST)) && - !xhci_link_trb_quirk(xhci)) { + if (!xhci_link_chain_quirk(xhci, ring->type)) { next->link.control &= cpu_to_le32(~TRB_CHAIN); next->link.control |= cpu_to_le32(chain); } @@ -283,7 +281,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, * Only for transfer and command rings where driver is the producer, not for * event rings. */ -static unsigned int xhci_num_trbs_free(struct xhci_hcd *xhci, struct xhci_ring *ring) +static unsigned int xhci_num_trbs_free(struct xhci_ring *ring) { struct xhci_segment *enq_seg = ring->enq_seg; union xhci_trb *enq = ring->enqueue; @@ -654,25 +652,6 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci, stream_id); return -ENODEV; } - /* - * A cancelled TD can complete with a stall if HW cached the trb. - * In this case driver can't find td, but if the ring is empty we - * can move the dequeue pointer to the current enqueue position. - * We shouldn't hit this anymore as cached cancelled TRBs are given back - * after clearing the cache, but be on the safe side and keep it anyway - */ - if (!td) { - if (list_empty(&ep_ring->td_list)) { - new_seg = ep_ring->enq_seg; - new_deq = ep_ring->enqueue; - new_cycle = ep_ring->cycle_state; - xhci_dbg(xhci, "ep ring empty, Set new dequeue = enqueue"); - goto deq_found; - } else { - xhci_warn(xhci, "Can't find new dequeue state, missing td\n"); - return -EINVAL; - } - } hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id); new_seg = ep_ring->deq_seg; @@ -709,8 +688,6 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci, } while (!cycle_found || !td_last_trb_found); -deq_found: - /* Don't update the ring cycle state for the producer (us). */ addr = xhci_trb_virt_to_dma(new_seg, new_deq); if (addr == 0) { @@ -738,7 +715,7 @@ deq_found: lower_32_bits(addr) | trb_sct | new_cycle, upper_32_bits(addr), STREAM_ID_FOR_TRB(stream_id), SLOT_ID_FOR_TRB(slot_id) | - EP_ID_FOR_TRB(ep_index) | TRB_TYPE(TRB_SET_DEQ), false); + EP_INDEX_FOR_TRB(ep_index) | TRB_TYPE(TRB_SET_DEQ), false); if (ret < 0) { xhci_free_command(xhci, cmd); return ret; @@ -783,10 +760,6 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } } -/* - * Must be called with xhci->lock held in interrupt context, - * releases and re-acquires xhci->lock - */ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, struct xhci_td *cur_td, int status) { @@ -1511,8 +1484,8 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, ring_doorbell_for_active_rings(xhci, slot_id, ep_index); } -static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id, - struct xhci_command *command, u32 cmd_comp_code) +static void xhci_handle_cmd_enable_slot(int slot_id, struct xhci_command *command, + u32 cmd_comp_code) { if (cmd_comp_code == COMP_SUCCESS) command->slot_id = slot_id; @@ -1537,8 +1510,7 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) xhci_free_device_endpoint_resources(xhci, virt_dev, true); } -static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, - u32 cmd_comp_code) +static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id) { struct xhci_virt_device *virt_dev; struct xhci_input_control_ctx *ctrl_ctx; @@ -1780,14 +1752,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3])); switch (cmd_type) { case TRB_ENABLE_SLOT: - xhci_handle_cmd_enable_slot(xhci, slot_id, cmd, cmd_comp_code); + xhci_handle_cmd_enable_slot(slot_id, cmd, cmd_comp_code); break; case TRB_DISABLE_SLOT: xhci_handle_cmd_disable_slot(xhci, slot_id); break; case TRB_CONFIG_EP: if (!cmd->completion) - xhci_handle_cmd_config_ep(xhci, slot_id, cmd_comp_code); + xhci_handle_cmd_config_ep(xhci, slot_id); break; case TRB_EVAL_CONTEXT: break; @@ -1905,9 +1877,7 @@ static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci) } while (!(pll_lock_check & 0x1) && --retry_count); } -static void handle_port_status(struct xhci_hcd *xhci, - struct xhci_interrupter *ir, - union xhci_trb *event) +static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) { struct usb_hcd *hcd; u32 port_id; @@ -2156,30 +2126,34 @@ static void xhci_clear_hub_tt_buffer(struct xhci_hcd *xhci, struct xhci_td *td, } } -/* Check if an error has halted the endpoint ring. The class driver will - * cleanup the halt for a non-default control endpoint if we indicate a stall. - * However, a babble and other errors also halt the endpoint ring, and the class - * driver won't clear the halt in that case, so we need to issue a Set Transfer - * Ring Dequeue Pointer command manually. +/* + * Check if xhci internal endpoint state has gone to a "halt" state due to an + * error or stall, including default control pipe protocol stall. + * The internal halt needs to be cleared with a reset endpoint command. + * + * External device side is also halted in functional stall cases. Class driver + * will clear the device halt with a CLEAR_FEATURE(ENDPOINT_HALT) request later. */ -static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci, - struct xhci_ep_ctx *ep_ctx, - unsigned int trb_comp_code) +static bool xhci_halted_host_endpoint(struct xhci_ep_ctx *ep_ctx, unsigned int comp_code) { - /* TRB completion codes that may require a manual halt cleanup */ - if (trb_comp_code == COMP_USB_TRANSACTION_ERROR || - trb_comp_code == COMP_BABBLE_DETECTED_ERROR || - trb_comp_code == COMP_SPLIT_TRANSACTION_ERROR) - /* The 0.95 spec says a babbling control endpoint - * is not halted. The 0.96 spec says it is. Some HW - * claims to be 0.95 compliant, but it halts the control - * endpoint anyway. Check if a babble halted the - * endpoint. + /* Stall halts both internal and device side endpoint */ + if (comp_code == COMP_STALL_ERROR) + return true; + + /* TRB completion codes that may require internal halt cleanup */ + if (comp_code == COMP_USB_TRANSACTION_ERROR || + comp_code == COMP_BABBLE_DETECTED_ERROR || + comp_code == COMP_SPLIT_TRANSACTION_ERROR) + /* + * The 0.95 spec says a babbling control endpoint is not halted. + * The 0.96 spec says it is. Some HW claims to be 0.95 + * compliant, but it halts the control endpoint anyway. + * Check endpoint context if endpoint is halted. */ if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_HALTED) - return 1; + return true; - return 0; + return false; } int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code) @@ -2349,8 +2323,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, case COMP_STOPPED_LENGTH_INVALID: goto finish_td; default: - if (!xhci_requires_manual_halt_cleanup(xhci, - ep_ctx, trb_comp_code)) + if (!xhci_halted_host_endpoint(ep_ctx, trb_comp_code)) break; xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n", trb_comp_code, ep->ep_index); @@ -2460,7 +2433,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, requested = remaining; break; case COMP_STOPPED_LENGTH_INVALID: - requested = 0; + /* exclude stopped trb with invalid length from length sum */ + sum_trbs_for_length = true; + ep_trb_len = 0; remaining = 0; break; default: @@ -2589,6 +2564,33 @@ finish_td: return finish_td(xhci, ep, ep_ring, td, trb_comp_code); } +/* Transfer events which don't point to a transfer TRB, see xhci 4.17.4 */ +static int handle_transferless_tx_event(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + u32 trb_comp_code) +{ + switch (trb_comp_code) { + case COMP_STALL_ERROR: + case COMP_USB_TRANSACTION_ERROR: + case COMP_INVALID_STREAM_TYPE_ERROR: + case COMP_INVALID_STREAM_ID_ERROR: + xhci_dbg(xhci, "Stream transaction error ep %u no id\n", ep->ep_index); + if (ep->err_count++ > MAX_SOFT_RETRY) + xhci_handle_halted_endpoint(xhci, ep, NULL, EP_HARD_RESET); + else + xhci_handle_halted_endpoint(xhci, ep, NULL, EP_SOFT_RESET); + break; + case COMP_RING_UNDERRUN: + case COMP_RING_OVERRUN: + case COMP_STOPPED_LENGTH_INVALID: + break; + default: + xhci_err(xhci, "Transfer event %u for unknown stream ring slot %u ep %u\n", + trb_comp_code, ep->vdev->slot_id, ep->ep_index); + return -ENODEV; + } + return 0; +} + /* * If this function returns an error condition, it means it got a Transfer * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. @@ -2609,7 +2611,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, int status = -EINPROGRESS; struct xhci_ep_ctx *ep_ctx; u32 trb_comp_code; - int td_num = 0; slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1; @@ -2632,37 +2633,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, goto err_out; } - /* Some transfer events don't always point to a trb, see xhci 4.17.4 */ - if (!ep_ring) { - switch (trb_comp_code) { - case COMP_STALL_ERROR: - case COMP_USB_TRANSACTION_ERROR: - case COMP_INVALID_STREAM_TYPE_ERROR: - case COMP_INVALID_STREAM_ID_ERROR: - xhci_dbg(xhci, "Stream transaction error ep %u no id\n", - ep_index); - if (ep->err_count++ > MAX_SOFT_RETRY) - xhci_handle_halted_endpoint(xhci, ep, NULL, - EP_HARD_RESET); - else - xhci_handle_halted_endpoint(xhci, ep, NULL, - EP_SOFT_RESET); - break; - case COMP_RING_UNDERRUN: - case COMP_RING_OVERRUN: - case COMP_STOPPED_LENGTH_INVALID: - break; - default: - xhci_err(xhci, "ERROR Transfer event for unknown stream ring slot %u ep %u\n", - slot_id, ep_index); - goto err_out; - } - return 0; - } - - /* Count current td numbers if ep->skip is set */ - if (ep->skip) - td_num += list_count_nodes(&ep_ring->td_list); + if (!ep_ring) + return handle_transferless_tx_event(xhci, ep, trb_comp_code); /* Look for common error cases */ switch (trb_comp_code) { @@ -2744,18 +2716,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, * a Ring Overrun Event for IN Isoch endpoint or Ring * Underrun Event for OUT Isoch endpoint. */ - xhci_dbg(xhci, "underrun event on endpoint\n"); - if (!list_empty(&ep_ring->td_list)) - xhci_dbg(xhci, "Underrun Event for slot %u ep %d still with TDs queued?\n", - slot_id, ep_index); + xhci_dbg(xhci, "Underrun event on slot %u ep %u\n", slot_id, ep_index); if (ep->skip) break; return 0; case COMP_RING_OVERRUN: - xhci_dbg(xhci, "overrun event on endpoint\n"); - if (!list_empty(&ep_ring->td_list)) - xhci_dbg(xhci, "Overrun Event for slot %u ep %d still with TDs queued?\n", - slot_id, ep_index); + xhci_dbg(xhci, "Overrun event on slot %u ep %u\n", slot_id, ep_index); if (ep->skip) break; return 0; @@ -2822,44 +2788,17 @@ static int handle_tx_event(struct xhci_hcd *xhci, xhci_dbg(xhci, "td_list is empty while skip flag set. Clear skip flag for slot %u ep %u.\n", slot_id, ep_index); } - if (trb_comp_code == COMP_STALL_ERROR || - xhci_requires_manual_halt_cleanup(xhci, ep_ctx, - trb_comp_code)) { - xhci_handle_halted_endpoint(xhci, ep, NULL, - EP_HARD_RESET); - } - return 0; - } - /* We've skipped all the TDs on the ep ring when ep->skip set */ - if (ep->skip && td_num == 0) { - ep->skip = false; - xhci_dbg(xhci, "All tds on the ep_ring skipped. Clear skip flag for slot %u ep %u.\n", - slot_id, ep_index); - return 0; + td = NULL; + goto check_endpoint_halted; } td = list_first_entry(&ep_ring->td_list, struct xhci_td, td_list); - if (ep->skip) - td_num--; /* Is this a TRB in the currently executing TD? */ ep_seg = trb_in_td(xhci, td, ep_trb_dma, false); - /* - * Skip the Force Stopped Event. The event_trb(event_dma) of FSE - * is not in the current TD pointed by ep_ring->dequeue because - * that the hardware dequeue pointer still at the previous TRB - * of the current TD. The previous TRB maybe a Link TD or the - * last TRB of the previous TD. The command completion handle - * will take care the rest. - */ - if (!ep_seg && (trb_comp_code == COMP_STOPPED || - trb_comp_code == COMP_STOPPED_LENGTH_INVALID)) { - continue; - } - if (!ep_seg) { if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { @@ -2867,6 +2806,18 @@ static int handle_tx_event(struct xhci_hcd *xhci, continue; } + /* + * Skip the Force Stopped Event. The 'ep_trb' of FSE is not in the current + * TD pointed by 'ep_ring->dequeue' because that the hardware dequeue + * pointer still at the previous TRB of the current TD. The previous TRB + * maybe a Link TD or the last TRB of the previous TD. The command + * completion handle will take care the rest. + */ + if (trb_comp_code == COMP_STOPPED || + trb_comp_code == COMP_STOPPED_LENGTH_INVALID) { + return 0; + } + /* * Some hosts give a spurious success event after a short * transfer. Ignore it. @@ -2916,10 +2867,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, return -ESHUTDOWN; } } - if (trb_comp_code == COMP_SHORT_PACKET) - ep_ring->last_td_was_short = true; - else - ep_ring->last_td_was_short = false; if (ep->skip) { xhci_dbg(xhci, @@ -2928,37 +2875,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, ep->skip = false; } - ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / - sizeof(*ep_trb)]; - - trace_xhci_handle_transfer(ep_ring, - (struct xhci_generic_trb *) ep_trb); - - /* - * No-op TRB could trigger interrupts in a case where - * a URB was killed and a STALL_ERROR happens right - * after the endpoint ring stopped. Reset the halted - * endpoint. Otherwise, the endpoint remains stalled - * indefinitely. - */ - - if (trb_is_noop(ep_trb)) { - if (trb_comp_code == COMP_STALL_ERROR || - xhci_requires_manual_halt_cleanup(xhci, ep_ctx, - trb_comp_code)) - xhci_handle_halted_endpoint(xhci, ep, td, - EP_HARD_RESET); - } else { - td->status = status; - - /* update the urb's actual_length and give back to the core */ - if (usb_endpoint_xfer_control(&td->urb->ep->desc)) - process_ctrl_td(xhci, ep, ep_ring, td, ep_trb, event); - else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc)) - process_isoc_td(xhci, ep, ep_ring, td, ep_trb, event); - else - process_bulk_intr_td(xhci, ep, ep_ring, td, ep_trb, event); - } /* * If ep->skip is set, it means there are missed tds on the * endpoint ring need to take care of. @@ -2967,6 +2883,38 @@ static int handle_tx_event(struct xhci_hcd *xhci, */ } while (ep->skip); + if (trb_comp_code == COMP_SHORT_PACKET) + ep_ring->last_td_was_short = true; + else + ep_ring->last_td_was_short = false; + + ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / sizeof(*ep_trb)]; + trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb); + + /* + * No-op TRB could trigger interrupts in a case where a URB was killed + * and a STALL_ERROR happens right after the endpoint ring stopped. + * Reset the halted endpoint. Otherwise, the endpoint remains stalled + * indefinitely. + */ + + if (trb_is_noop(ep_trb)) + goto check_endpoint_halted; + + td->status = status; + + /* update the urb's actual_length and give back to the core */ + if (usb_endpoint_xfer_control(&td->urb->ep->desc)) + process_ctrl_td(xhci, ep, ep_ring, td, ep_trb, event); + else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc)) + process_isoc_td(xhci, ep, ep_ring, td, ep_trb, event); + else + process_bulk_intr_td(xhci, ep, ep_ring, td, ep_trb, event); + +check_endpoint_halted: + if (xhci_halted_host_endpoint(ep_ctx, trb_comp_code)) + xhci_handle_halted_endpoint(xhci, ep, td, EP_HARD_RESET); + return 0; err_out: @@ -3005,7 +2953,7 @@ static int xhci_handle_event_trb(struct xhci_hcd *xhci, struct xhci_interrupter handle_cmd_completion(xhci, &event->event_cmd); break; case TRB_PORT_STATUS: - handle_port_status(xhci, ir, event); + handle_port_status(xhci, event); break; case TRB_TRANSFER: handle_tx_event(xhci, ir, &event->trans_event); @@ -3065,8 +3013,7 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, } /* Clear the interrupt pending bit for a specific interrupter. */ -static void xhci_clear_interrupt_pending(struct xhci_hcd *xhci, - struct xhci_interrupter *ir) +static void xhci_clear_interrupt_pending(struct xhci_interrupter *ir) { if (!ir->ip_autoclear) { u32 irq_pending; @@ -3087,7 +3034,7 @@ static int xhci_handle_events(struct xhci_hcd *xhci, struct xhci_interrupter *ir int err; u64 temp; - xhci_clear_interrupt_pending(xhci, ir); + xhci_clear_interrupt_pending(ir); /* Event ring hasn't been allocated yet. */ if (!ir->event_ring || !ir->event_ring->dequeue) { @@ -3260,7 +3207,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, if (ep_ring != xhci->cmd_ring) { new_segs = xhci_ring_expansion_needed(xhci, ep_ring, num_trbs); - } else if (xhci_num_trbs_free(xhci, ep_ring) <= num_trbs) { + } else if (xhci_num_trbs_free(ep_ring) <= num_trbs) { xhci_err(xhci, "Do not support expand command ring\n"); return -ENOMEM; } @@ -3278,9 +3225,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, /* If we're not dealing with 0.95 hardware or isoc rings * on AMD 0.96 host, clear the chain bit. */ - if (!xhci_link_trb_quirk(xhci) && - !(ep_ring->type == TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))) + if (!xhci_link_chain_quirk(xhci, ep_ring->type)) ep_ring->enqueue->link.control &= cpu_to_le32(~TRB_CHAIN); else @@ -3435,8 +3380,7 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } -static void check_interval(struct xhci_hcd *xhci, struct urb *urb, - struct xhci_ep_ctx *ep_ctx) +static void check_interval(struct urb *urb, struct xhci_ep_ctx *ep_ctx) { int xhci_interval; int ep_interval; @@ -3477,7 +3421,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_ep_ctx *ep_ctx; ep_ctx = xhci_get_ep_ctx(xhci, xhci->devs[slot_id]->out_ctx, ep_index); - check_interval(xhci, urb, ep_ctx); + check_interval(urb, ep_ctx); return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index); } @@ -3723,7 +3667,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, upper_32_bits(send_addr), length_field, field); - td->num_trbs++; addr += trb_buff_len; sent_len = trb_buff_len; @@ -3750,7 +3693,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb_priv->td[1].last_trb_seg = ring->enq_seg; field = TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC; queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field); - urb_priv->td[1].num_trbs++; } check_trb_math(urb, enqd_len); @@ -3801,7 +3743,6 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb_priv = urb->hcpriv; td = &urb_priv->td[0]; - td->num_trbs = num_trbs; /* * Don't give the first TRB to the hardware (by toggling the cycle bit) @@ -4122,7 +4063,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, goto cleanup; } td = &urb_priv->td[i]; - td->num_trbs = trbs_per_td; /* use SIA as default, if frame id is used overwrite it */ sia_frame_id = TRB_SIA; if (!(urb->transfer_flags & URB_ISO_ASAP) && @@ -4286,7 +4226,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, * Check interval value. This should be done before we start to * calculate the start frame value. */ - check_interval(xhci, urb, ep_ctx); + check_interval(urb, ep_ctx); /* Calculate the start frame and put it in urb->start_frame. */ if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) { @@ -4439,7 +4379,7 @@ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd, int slot_id, unsigned int ep_index, int suspend) { u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id); - u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); + u32 trb_ep_index = EP_INDEX_FOR_TRB(ep_index); u32 type = TRB_TYPE(TRB_STOP_RING); u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend); @@ -4452,7 +4392,7 @@ int xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd, enum xhci_ep_reset_type reset_type) { u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id); - u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); + u32 trb_ep_index = EP_INDEX_FOR_TRB(ep_index); u32 type = TRB_TYPE(TRB_RESET_EP); if (reset_type == EP_SOFT_RESET) diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 5762564b9d73..24405315ffe6 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -250,6 +250,7 @@ DECLARE_EVENT_CLASS(xhci_log_urb, TP_PROTO(struct urb *urb), TP_ARGS(urb), TP_STRUCT__entry( + __string(devname, dev_name(&urb->dev->dev)) __field(void *, urb) __field(unsigned int, pipe) __field(unsigned int, stream) @@ -265,6 +266,7 @@ DECLARE_EVENT_CLASS(xhci_log_urb, __field(int, slot_id) ), TP_fast_assign( + __assign_str(devname); __entry->urb = urb; __entry->pipe = urb->pipe; __entry->stream = urb->stream_id; @@ -279,7 +281,8 @@ DECLARE_EVENT_CLASS(xhci_log_urb, __entry->type = usb_endpoint_type(&urb->ep->desc); __entry->slot_id = urb->dev->slot_id; ), - TP_printk("ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x", + TP_printk("%s ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x", + __get_str(devname), __entry->epnum, __entry->dir_in ? "in" : "out", __print_symbolic(__entry->type, { USB_ENDPOINT_XFER_INT, "intr" }, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 78d014c4d884..ebd0afd59a60 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -17,6 +17,7 @@ #include #include #include +#include /* Code sharing between pci-quirks and xhci hcd */ #include "xhci-ext-caps.h" @@ -805,12 +806,18 @@ struct xhci_transfer_event { __le32 flags; }; -/* Transfer event TRB length bit mask */ -/* bits 0:23 */ -#define EVENT_TRB_LEN(p) ((p) & 0xffffff) +/* Transfer event flags bitfield, also for select command completion events */ +#define TRB_TO_SLOT_ID(p) (((p) >> 24) & 0xff) +#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24) -/** Transfer Event bit fields **/ -#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) +#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) /* Endpoint ID 1 - 31 */ +#define EP_ID_FOR_TRB(p) (((p) & 0x1f) << 16) + +#define TRB_TO_EP_INDEX(p) (TRB_TO_EP_ID(p) - 1) /* Endpoint index 0 - 30 */ +#define EP_INDEX_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) + +/* Transfer event TRB length bit mask */ +#define EVENT_TRB_LEN(p) ((p) & 0xffffff) /* Completion Code - only applicable for some types of TRBs */ #define COMP_CODE_MASK (0xff << 24) @@ -950,8 +957,6 @@ struct xhci_event_cmd { __le32 flags; }; -/* flags bitmasks */ - /* Address device - disable SetAddress */ #define TRB_BSR (1<<9) @@ -987,13 +992,8 @@ enum xhci_setup_dev { /* bits 16:23 are the virtual function ID */ /* bits 24:31 are the slot ID */ -#define TRB_TO_SLOT_ID(p) (((p) & (0xff<<24)) >> 24) -#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24) /* Stop Endpoint TRB - ep_index to endpoint ID for this TRB */ -#define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1) -#define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) - #define SUSPEND_PORT_FOR_TRB(p) (((p) & 1) << 23) #define TRB_TO_SUSPEND_PORT(p) (((p) & (1 << 23)) >> 23) #define LAST_EP_INDEX 30 @@ -1294,7 +1294,6 @@ struct xhci_td { /* actual_length of the URB has already been set */ bool urb_length_set; bool error_mid_td; - unsigned int num_trbs; }; /* @@ -1628,6 +1627,7 @@ struct xhci_hcd { #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) #define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) #define XHCI_ZHAOXIN_HOST BIT_ULL(46) +#define XHCI_WRITE_64_HI_LO BIT_ULL(47) unsigned int num_active_eps; unsigned int limit_active_eps; @@ -1749,9 +1749,12 @@ static inline void xhci_write_64(struct xhci_hcd *xhci, lo_hi_writeq(val, regs); } -static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci) + +/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ +static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type) { - return xhci->quirks & XHCI_LINK_TRB_QUIRK; + return (xhci->quirks & XHCI_LINK_TRB_QUIRK) || + (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); } /* xHCI debugging */ @@ -2021,8 +2024,7 @@ static inline const char *xhci_decode_trb(char *str, size_t size, field1, field0, xhci_trb_comp_code_string(GET_COMP_CODE(field2)), EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3), - /* Macro decrements 1, maybe it shouldn't?!? */ - TRB_TO_EP_INDEX(field3) + 1, + TRB_TO_EP_ID(field3), xhci_trb_type_string(type), field3 & EVENT_DATA ? 'E' : 'e', field3 & TRB_CYCLE ? 'C' : 'c'); @@ -2137,8 +2139,7 @@ static inline const char *xhci_decode_trb(char *str, size_t size, xhci_trb_type_string(type), field1, field0, TRB_TO_SLOT_ID(field3), - /* Macro decrements 1, maybe it shouldn't?!? */ - TRB_TO_EP_INDEX(field3) + 1, + TRB_TO_EP_ID(field3), field3 & TRB_TSP ? 'T' : 't', field3 & TRB_CYCLE ? 'C' : 'c'); break; @@ -2148,8 +2149,7 @@ static inline const char *xhci_decode_trb(char *str, size_t size, xhci_trb_type_string(type), TRB_TO_SLOT_ID(field3), TRB_TO_SUSPEND_PORT(field3), - /* Macro decrements 1, maybe it shouldn't?!? */ - TRB_TO_EP_INDEX(field3) + 1, + TRB_TO_EP_ID(field3), field3 & TRB_CYCLE ? 'C' : 'c'); break; case TRB_SET_DEQ: @@ -2159,8 +2159,7 @@ static inline const char *xhci_decode_trb(char *str, size_t size, field1, field0, TRB_TO_STREAM_ID(field2), TRB_TO_SLOT_ID(field3), - /* Macro decrements 1, maybe it shouldn't?!? */ - TRB_TO_EP_INDEX(field3) + 1, + TRB_TO_EP_ID(field3), field3 & TRB_CYCLE ? 'C' : 'c'); break; case TRB_RESET_DEV: diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c index 78aaee56c2b7..7ab4856aba0e 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -148,4 +148,5 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); #endif +MODULE_DESCRIPTION("EZUSB device support"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index 4d30095d6ad2..2d9af74a62c1 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -127,5 +127,6 @@ static struct usb_driver isight_firmware_driver = { module_usb_driver(isight_firmware_driver); +MODULE_DESCRIPTION("iSight firmware loading support"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Matthew Garrett "); diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_usb_dev.c index f2bcc1a8b95f..56710e6b1653 100644 --- a/drivers/usb/misc/onboard_usb_dev.c +++ b/drivers/usb/misc/onboard_usb_dev.c @@ -454,16 +454,18 @@ static struct onboard_dev *_find_onboard_dev(struct device *dev) return onboard_dev; } +static bool onboard_dev_usbdev_match(struct usb_device *udev) +{ + /* Onboard devices using this driver must have a device tree node */ + return !!udev->dev.of_node; +} + static int onboard_dev_usbdev_probe(struct usb_device *udev) { struct device *dev = &udev->dev; struct onboard_dev *onboard_dev; int err; - /* ignore supported devices without device tree node */ - if (!dev->of_node) - return -ENODEV; - onboard_dev = _find_onboard_dev(dev); if (IS_ERR(onboard_dev)) return PTR_ERR(onboard_dev); @@ -513,6 +515,7 @@ MODULE_DEVICE_TABLE(usb, onboard_dev_id_table); static struct usb_device_driver onboard_dev_usbdev_driver = { .name = "onboard-usb-dev", + .match = onboard_dev_usbdev_match, .probe = onboard_dev_usbdev_probe, .disconnect = onboard_dev_usbdev_disconnect, .generic_subclass = 1, diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c index 7da404f55a6d..b98cda1cef73 100644 --- a/drivers/usb/misc/usb251xb.c +++ b/drivers/usb/misc/usb251xb.c @@ -726,15 +726,15 @@ static int __maybe_unused usb251xb_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(usb251xb_pm_ops, usb251xb_suspend, usb251xb_resume); static const struct i2c_device_id usb251xb_id[] = { - { "usb2422", 0 }, - { "usb2512b", 0 }, - { "usb2512bi", 0 }, - { "usb2513b", 0 }, - { "usb2513bi", 0 }, - { "usb2514b", 0 }, - { "usb2514bi", 0 }, - { "usb2517", 0 }, - { "usb2517i", 0 }, + { "usb2422" }, + { "usb2512b" }, + { "usb2512bi" }, + { "usb2513b" }, + { "usb2513bi" }, + { "usb2514b" }, + { "usb2514bi" }, + { "usb2517" }, + { "usb2517i" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, usb251xb_id); diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 72765077932c..3b33e4878c60 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -390,7 +390,7 @@ static SIMPLE_DEV_PM_OPS(usb3503_platform_pm_ops, usb3503_platform_suspend, usb3503_platform_resume); static const struct i2c_device_id usb3503_id[] = { - { USB3503_I2C_NAME, 0 }, + { USB3503_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, usb3503_id); diff --git a/drivers/usb/misc/usb4604.c b/drivers/usb/misc/usb4604.c index 065e269ba4e3..c9a2fb3518ae 100644 --- a/drivers/usb/misc/usb4604.c +++ b/drivers/usb/misc/usb4604.c @@ -135,7 +135,7 @@ static SIMPLE_DEV_PM_OPS(usb4604_i2c_pm_ops, usb4604_i2c_suspend, usb4604_i2c_resume); static const struct i2c_device_id usb4604_id[] = { - { "usb4604", 0 }, + { "usb4604" }, { } }; MODULE_DEVICE_TABLE(i2c, usb4604_id); diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 9a0649d23693..4745a320eae4 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -531,4 +531,5 @@ static const struct file_operations yurex_fops = { module_usb_driver(yurex_driver); +MODULE_DESCRIPTION("USB YUREX driver support"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 824904abe76f..af852d53aac6 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -419,4 +419,5 @@ static void __exit mon_exit(void) module_init(mon_init); module_exit(mon_exit); +MODULE_DESCRIPTION("USB Monitor"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 108d9a593a80..953094c1930c 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -191,7 +191,7 @@ static void otg_timer(struct timer_list *t) spin_unlock_irqrestore(&musb->lock, flags); } -static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) +static void __maybe_unused da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) { static unsigned long last_timer; @@ -220,6 +220,13 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) mod_timer(&musb->dev_timer, timeout); } +static int da8xx_babble_recover(struct musb *musb) +{ + dev_dbg(musb->controller, "resetting controller to recover from babble\n"); + musb_writel(musb->ctrl_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); + return 0; +} + static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) { struct musb *musb = hci; @@ -328,13 +335,6 @@ static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode) struct da8xx_glue *glue = dev_get_drvdata(musb->controller->parent); enum phy_mode phy_mode; - /* - * The PHY has some issues when it is forced in device or host mode. - * Unless the user request another mode, configure the PHY in OTG mode. - */ - if (!musb->is_initialized) - return phy_set_mode(glue->phy, PHY_MODE_USB_OTG); - switch (musb_mode) { case MUSB_HOST: /* Force VBUS valid, ID = 0 */ phy_mode = PHY_MODE_USB_HOST; @@ -483,7 +483,11 @@ static const struct musb_platform_ops da8xx_ops = { .disable = da8xx_musb_disable, .set_mode = da8xx_musb_set_mode, + +#ifndef CONFIG_USB_MUSB_HOST .try_idle = da8xx_musb_try_idle, +#endif + .recover = da8xx_babble_recover, .set_vbus = da8xx_musb_set_vbus, }; diff --git a/drivers/usb/musb/mpfs.c b/drivers/usb/musb/mpfs.c index f0f56df38835..29c7e5cdb230 100644 --- a/drivers/usb/musb/mpfs.c +++ b/drivers/usb/musb/mpfs.c @@ -190,6 +190,8 @@ static int mpfs_probe(struct platform_device *pdev) pdata->config = &mpfs_musb_hdrc_config; pdata->platform_ops = &mpfs_ops; + pdata->extvbus = device_property_read_bool(dev, "microchip,ext-vbus-drv"); + pdata->mode = usb_get_dr_mode(dev); if (pdata->mode == USB_DR_MODE_UNKNOWN) { dev_info(dev, "No dr_mode property found, defaulting to otg\n"); diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c index 97e6603c7149..ada508be090a 100644 --- a/drivers/usb/phy/phy-am335x-control.c +++ b/drivers/usb/phy/phy-am335x-control.c @@ -189,4 +189,5 @@ static struct platform_driver am335x_control_driver = { }; module_platform_driver(am335x_control_driver); +MODULE_DESCRIPTION("AM335x USB PHY Control Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index e39665cf4b4a..6db88e00f127 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -142,4 +142,5 @@ static struct platform_driver am335x_phy_driver = { }; module_platform_driver(am335x_phy_driver); +MODULE_DESCRIPTION("AM335x USB PHY Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index b610a2de4ae5..c223b4dc1b19 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -423,6 +423,7 @@ static void uas_data_cmplt(struct urb *urb) uas_log_cmd_state(cmnd, "data cmplt err", status); /* error: no data transfered */ scsi_set_resid(cmnd, sdb->length); + set_host_byte(cmnd, DID_ERROR); } else { scsi_set_resid(cmnd, sdb->length - urb->actual_length); } @@ -1232,9 +1233,8 @@ static void uas_disconnect(struct usb_interface *intf) * hang on reboot when the device is still in uas mode. Note the reset is * necessary as some devices won't revert to usb-storage mode without it. */ -static void uas_shutdown(struct device *dev) +static void uas_shutdown(struct usb_interface *intf) { - struct usb_interface *intf = to_usb_interface(dev); struct usb_device *udev = interface_to_usbdev(intf); struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata; @@ -1257,7 +1257,7 @@ static struct usb_driver uas_driver = { .suspend = uas_suspend, .resume = uas_resume, .reset_resume = uas_reset_resume, - .driver.shutdown = uas_shutdown, + .shutdown = uas_shutdown, .id_table = uas_usb_ids, }; @@ -1287,6 +1287,7 @@ static void __exit uas_exit(void) module_init(uas_init); module_exit(uas_exit); +MODULE_DESCRIPTION("USB Attached SCSI driver"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(USB_STORAGE); MODULE_AUTHOR( diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index a49a31639f6f..d36f3b6992bb 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -68,9 +68,102 @@ MODULE_AUTHOR("Matthew Dharm "); MODULE_DESCRIPTION("USB Mass Storage driver for Linux"); MODULE_LICENSE("GPL"); -static unsigned int delay_use = 1; -module_param(delay_use, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); +static unsigned int delay_use = 1 * MSEC_PER_SEC; + +/** + * parse_delay_str - parse an unsigned decimal integer delay + * @str: String to parse. + * @ndecimals: Number of decimal to scale up. + * @suffix: Suffix string to parse. + * @val: Where to store the parsed value. + * + * Parse an unsigned decimal value in @str, optionally end with @suffix. + * Stores the parsed value in @val just as it is if @str ends with @suffix. + * Otherwise store the value scale up by 10^(@ndecimal). + * + * Returns 0 on success, a negative error code otherwise. + */ +static int parse_delay_str(const char *str, int ndecimals, const char *suffix, + unsigned int *val) +{ + int n, n2, l; + char buf[16]; + + l = strlen(suffix); + n = strlen(str); + if (n > 0 && str[n - 1] == '\n') + --n; + if (n >= l && !strncmp(&str[n - l], suffix, l)) { + n -= l; + n2 = 0; + } else + n2 = ndecimals; + + if (n + n2 > sizeof(buf) - 1) + return -EINVAL; + + memcpy(buf, str, n); + while (n2-- > 0) + buf[n++] = '0'; + buf[n] = 0; + + return kstrtouint(buf, 10, val); +} + +/** + * format_delay_ms - format an integer value into a delay string + * @val: The integer value to format, scaled by 10^(@ndecimals). + * @ndecimals: Number of decimal to scale down. + * @suffix: Suffix string to format. + * @str: Where to store the formatted string. + * @size: The size of buffer for @str. + * + * Format an integer value in @val scale down by 10^(@ndecimals) without @suffix + * if @val is divisible by 10^(@ndecimals). + * Otherwise format a value in @val just as it is with @suffix + * + * Returns the number of characters written into @str. + */ +static int format_delay_ms(unsigned int val, int ndecimals, const char *suffix, + char *str, int size) +{ + u64 delay_ms = val; + unsigned int rem = do_div(delay_ms, int_pow(10, ndecimals)); + int ret; + + if (rem) + ret = scnprintf(str, size, "%u%s\n", val, suffix); + else + ret = scnprintf(str, size, "%u\n", (unsigned int)delay_ms); + return ret; +} + +static int delay_use_set(const char *s, const struct kernel_param *kp) +{ + unsigned int delay_ms; + int ret; + + ret = parse_delay_str(skip_spaces(s), 3, "ms", &delay_ms); + if (ret < 0) + return ret; + + *((unsigned int *)kp->arg) = delay_ms; + return 0; +} + +static int delay_use_get(char *s, const struct kernel_param *kp) +{ + unsigned int delay_ms = *((unsigned int *)kp->arg); + + return format_delay_ms(delay_ms, 3, "ms", s, PAGE_SIZE); +} + +static const struct kernel_param_ops delay_use_ops = { + .set = delay_use_set, + .get = delay_use_get, +}; +module_param_cb(delay_use, &delay_use_ops, &delay_use, 0644); +MODULE_PARM_DESC(delay_use, "time to delay before using a new device"); static char quirks[128]; module_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR); @@ -1064,7 +1157,7 @@ int usb_stor_probe2(struct us_data *us) if (delay_use > 0) dev_dbg(dev, "waiting for device to settle before scanning\n"); queue_delayed_work(system_freezable_wq, &us->scan_dwork, - delay_use * HZ); + msecs_to_jiffies(delay_use)); return 0; /* We come here if there are any problems */ diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 596cd4806018..92cc1b136120 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -746,7 +746,7 @@ int dp_altmode_probe(struct typec_altmode *alt) dp->alt = alt; alt->desc = "DisplayPort"; - alt->ops = &dp_altmode_ops; + typec_altmode_set_ops(alt, &dp_altmode_ops); if (plug) { plug->desc = "Displayport"; diff --git a/drivers/usb/typec/anx7411.c b/drivers/usb/typec/anx7411.c index b12a07edc71b..5a5bf3532ad7 100644 --- a/drivers/usb/typec/anx7411.c +++ b/drivers/usb/typec/anx7411.c @@ -1566,7 +1566,7 @@ static void anx7411_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id anx7411_id[] = { - {"anx7411", 0}, + { "anx7411" }, {} }; diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 9610e647a8d4..9262fcd4144f 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -467,6 +467,22 @@ static const struct attribute_group *typec_altmode_groups[] = { NULL }; +/** + * typec_altmode_set_ops - Set ops for altmode + * @adev: Handle to the alternate mode + * @ops: Ops for the alternate mode + * + * After setting ops, attribute visiblity needs to be refreshed if the alternate + * mode can be activated. + */ +void typec_altmode_set_ops(struct typec_altmode *adev, + const struct typec_altmode_ops *ops) +{ + adev->ops = ops; + sysfs_update_group(&adev->dev.kobj, &typec_altmode_group); +} +EXPORT_SYMBOL_GPL(typec_altmode_set_ops); + static int altmode_id_get(struct device *dev) { struct ida *ids; @@ -2317,7 +2333,7 @@ void typec_port_register_altmodes(struct typec_port *port, continue; } - alt->ops = ops; + typec_altmode_set_ops(alt, ops); typec_altmode_set_drvdata(alt, drvdata); altmodes[index] = alt; index++; diff --git a/drivers/usb/typec/mux/gpio-sbu-mux.c b/drivers/usb/typec/mux/gpio-sbu-mux.c index 374168482d36..8902102c05a8 100644 --- a/drivers/usb/typec/mux/gpio-sbu-mux.c +++ b/drivers/usb/typec/mux/gpio-sbu-mux.c @@ -66,6 +66,9 @@ static int gpio_sbu_mux_set(struct typec_mux_dev *mux, { struct gpio_sbu_mux *sbu_mux = typec_mux_get_drvdata(mux); + if (!sbu_mux->enable_gpio) + return -EOPNOTSUPP; + mutex_lock(&sbu_mux->lock); switch (state->mode) { @@ -102,7 +105,8 @@ static int gpio_sbu_mux_probe(struct platform_device *pdev) mutex_init(&sbu_mux->lock); - sbu_mux->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + sbu_mux->enable_gpio = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); if (IS_ERR(sbu_mux->enable_gpio)) return dev_err_probe(dev, PTR_ERR(sbu_mux->enable_gpio), "unable to acquire enable gpio\n"); diff --git a/drivers/usb/typec/mux/nb7vpq904m.c b/drivers/usb/typec/mux/nb7vpq904m.c index b17826713753..b57b6c9c40fe 100644 --- a/drivers/usb/typec/mux/nb7vpq904m.c +++ b/drivers/usb/typec/mux/nb7vpq904m.c @@ -69,6 +69,7 @@ struct nb7vpq904m { bool swap_data_lanes; struct typec_switch *typec_switch; + struct typec_mux *typec_mux; struct mutex lock; /* protect non-concurrent retimer & switch */ @@ -275,6 +276,7 @@ static int nb7vpq904m_sw_set(struct typec_switch_dev *sw, enum typec_orientation static int nb7vpq904m_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state) { struct nb7vpq904m *nb7 = typec_retimer_get_drvdata(retimer); + struct typec_mux_state mux_state; int ret = 0; mutex_lock(&nb7->lock); @@ -292,7 +294,14 @@ static int nb7vpq904m_retimer_set(struct typec_retimer *retimer, struct typec_re mutex_unlock(&nb7->lock); - return ret; + if (ret) + return ret; + + mux_state.alt = state->alt; + mux_state.data = state->data; + mux_state.mode = state->mode; + + return typec_mux_set(nb7->typec_mux, &mux_state); } static const struct regmap_config nb7_regmap = { @@ -321,46 +330,48 @@ static int nb7vpq904m_parse_data_lanes_mapping(struct nb7vpq904m *nb7) ep = of_graph_get_endpoint_by_regs(nb7->client->dev.of_node, 1, 0); - if (ep) { - ret = of_property_count_u32_elems(ep, "data-lanes"); - if (ret == -EINVAL) - /* Property isn't here, consider default mapping */ - goto out_done; - if (ret < 0) - goto out_error; + if (!ep) + return 0; - if (ret != DATA_LANES_COUNT) { - dev_err(&nb7->client->dev, "expected 4 data lanes\n"); - ret = -EINVAL; - goto out_error; - } - ret = of_property_read_u32_array(ep, "data-lanes", data_lanes, DATA_LANES_COUNT); - if (ret) - goto out_error; + ret = of_property_count_u32_elems(ep, "data-lanes"); + if (ret == -EINVAL) + /* Property isn't here, consider default mapping */ + goto out_done; + if (ret < 0) + goto out_error; - for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) { - for (j = 0; j < DATA_LANES_COUNT; j++) { - if (data_lanes[j] != supported_data_lane_mapping[i][j]) - break; - } + if (ret != DATA_LANES_COUNT) { + dev_err(&nb7->client->dev, "expected 4 data lanes\n"); + ret = -EINVAL; + goto out_error; + } - if (j == DATA_LANES_COUNT) + ret = of_property_read_u32_array(ep, "data-lanes", data_lanes, DATA_LANES_COUNT); + if (ret) + goto out_error; + + for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) { + for (j = 0; j < DATA_LANES_COUNT; j++) { + if (data_lanes[j] != supported_data_lane_mapping[i][j]) break; } - switch (i) { - case NORMAL_LANE_MAPPING: + if (j == DATA_LANES_COUNT) break; - case INVERT_LANE_MAPPING: - nb7->swap_data_lanes = true; - dev_info(&nb7->client->dev, "using inverted data lanes mapping\n"); - break; - default: - dev_err(&nb7->client->dev, "invalid data lanes mapping\n"); - ret = -EINVAL; - goto out_error; - } + } + + switch (i) { + case NORMAL_LANE_MAPPING: + break; + case INVERT_LANE_MAPPING: + nb7->swap_data_lanes = true; + dev_info(&nb7->client->dev, "using inverted data lanes mapping\n"); + break; + default: + dev_err(&nb7->client->dev, "invalid data lanes mapping\n"); + ret = -EINVAL; + goto out_error; } out_done: @@ -411,9 +422,16 @@ static int nb7vpq904m_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(nb7->typec_switch), "failed to acquire orientation-switch\n"); + nb7->typec_mux = fwnode_typec_mux_get(dev->fwnode); + if (IS_ERR(nb7->typec_mux)) { + ret = dev_err_probe(dev, PTR_ERR(nb7->typec_mux), + "Failed to acquire mode-switch\n"); + goto err_switch_put; + } + ret = nb7vpq904m_parse_data_lanes_mapping(nb7); if (ret) - return ret; + goto err_mux_put; ret = regulator_enable(nb7->vcc_supply); if (ret) @@ -456,6 +474,12 @@ err_disable_gpio: gpiod_set_value(nb7->enable_gpio, 0); regulator_disable(nb7->vcc_supply); +err_mux_put: + typec_mux_put(nb7->typec_mux); + +err_switch_put: + typec_switch_put(nb7->typec_switch); + return ret; } @@ -469,6 +493,9 @@ static void nb7vpq904m_remove(struct i2c_client *client) gpiod_set_value(nb7->enable_gpio, 0); regulator_disable(nb7->vcc_supply); + + typec_mux_put(nb7->typec_mux); + typec_switch_put(nb7->typec_switch); } static const struct i2c_device_id nb7vpq904m_table[] = { diff --git a/drivers/usb/typec/mux/ptn36502.c b/drivers/usb/typec/mux/ptn36502.c index 0ec86ef32a87..129d9d24b932 100644 --- a/drivers/usb/typec/mux/ptn36502.c +++ b/drivers/usb/typec/mux/ptn36502.c @@ -67,6 +67,7 @@ struct ptn36502 { struct typec_retimer *retimer; struct typec_switch *typec_switch; + struct typec_mux *typec_mux; struct mutex lock; /* protect non-concurrent retimer & switch */ @@ -235,6 +236,7 @@ static int ptn36502_sw_set(struct typec_switch_dev *sw, enum typec_orientation o static int ptn36502_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state) { struct ptn36502 *ptn = typec_retimer_get_drvdata(retimer); + struct typec_mux_state mux_state; int ret = 0; mutex_lock(&ptn->lock); @@ -252,7 +254,14 @@ static int ptn36502_retimer_set(struct typec_retimer *retimer, struct typec_reti mutex_unlock(&ptn->lock); - return ret; + if (ret) + return ret; + + mux_state.alt = state->alt; + mux_state.data = state->data; + mux_state.mode = state->mode; + + return typec_mux_set(ptn->typec_mux, &mux_state); } static int ptn36502_detect(struct ptn36502 *ptn) @@ -321,9 +330,18 @@ static int ptn36502_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(ptn->typec_switch), "Failed to acquire orientation-switch\n"); + ptn->typec_mux = fwnode_typec_mux_get(dev->fwnode); + if (IS_ERR(ptn->typec_mux)) { + ret = dev_err_probe(dev, PTR_ERR(ptn->typec_mux), + "Failed to acquire mode-switch\n"); + goto err_switch_put; + } + ret = regulator_enable(ptn->vdd18_supply); - if (ret) - return dev_err_probe(dev, ret, "Failed to enable vdd18\n"); + if (ret) { + ret = dev_err_probe(dev, ret, "Failed to enable vdd18\n"); + goto err_mux_put; + } ret = ptn36502_detect(ptn); if (ret) @@ -363,6 +381,12 @@ err_switch_unregister: err_disable_regulator: regulator_disable(ptn->vdd18_supply); +err_mux_put: + typec_mux_put(ptn->typec_mux); + +err_switch_put: + typec_switch_put(ptn->typec_switch); + return ret; } @@ -374,6 +398,9 @@ static void ptn36502_remove(struct i2c_client *client) typec_switch_unregister(ptn->sw); regulator_disable(ptn->vdd18_supply); + + typec_mux_put(ptn->typec_mux); + typec_switch_put(ptn->typec_switch); } static const struct i2c_device_id ptn36502_table[] = { diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index ef18a448b740..e2fe479e16ad 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1820,8 +1820,8 @@ static const struct of_device_id fusb302_dt_match[] __maybe_unused = { MODULE_DEVICE_TABLE(of, fusb302_dt_match); static const struct i2c_device_id fusb302_i2c_device_id[] = { - {"typec_fusb302", 0}, - {}, + { "typec_fusb302" }, + {} }; MODULE_DEVICE_TABLE(i2c, fusb302_i2c_device_id); diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index c962014bba4e..b862fdf3fe1d 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -67,6 +67,18 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val) return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16)); } +static bool tcpci_check_std_output_cap(struct regmap *regmap, u8 mask) +{ + unsigned int reg; + int ret; + + ret = regmap_read(regmap, TCPC_STD_OUTPUT_CAP, ®); + if (ret < 0) + return ret; + + return (reg & mask) == mask; +} + static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -301,6 +313,28 @@ static int tcpci_set_polarity(struct tcpc_dev *tcpc, TCPC_TCPC_CTRL_ORIENTATION : 0); } +static int tcpci_set_orientation(struct tcpc_dev *tcpc, + enum typec_orientation orientation) +{ + struct tcpci *tcpci = tcpc_to_tcpci(tcpc); + unsigned int reg; + + switch (orientation) { + case TYPEC_ORIENTATION_NONE: + /* We can't put a single output into high impedance */ + fallthrough; + case TYPEC_ORIENTATION_NORMAL: + reg = TCPC_CONFIG_STD_OUTPUT_ORIENTATION_NORMAL; + break; + case TYPEC_ORIENTATION_REVERSE: + reg = TCPC_CONFIG_STD_OUTPUT_ORIENTATION_FLIPPED; + break; + } + + return regmap_update_bits(tcpci->regmap, TCPC_CONFIG_STD_OUTPUT, + TCPC_CONFIG_STD_OUTPUT_ORIENTATION_MASK, reg); +} + static void tcpci_set_partner_usb_comm_capable(struct tcpc_dev *tcpc, bool capable) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -830,6 +864,9 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) if (tcpci->data->vbus_vsafe0v) tcpci->tcpc.is_vbus_vsafe0v = tcpci_is_vbus_vsafe0v; + if (tcpci->data->set_orientation) + tcpci->tcpc.set_orientation = tcpci_set_orientation; + err = tcpci_parse_config(tcpci); if (err < 0) return ERR_PTR(err); @@ -873,6 +910,13 @@ static int tcpci_probe(struct i2c_client *client) if (err < 0) return err; + err = tcpci_check_std_output_cap(chip->data.regmap, + TCPC_STD_OUTPUT_CAP_ORIENTATION); + if (err < 0) + return err; + + chip->data.set_orientation = err; + chip->tcpci = tcpci_register_port(&client->dev, &chip->data); if (IS_ERR(chip->tcpci)) return PTR_ERR(chip->tcpci); @@ -903,7 +947,7 @@ static void tcpci_remove(struct i2c_client *client) } static const struct i2c_device_id tcpci_id[] = { - { "tcpci", 0 }, + { "tcpci" }, { } }; MODULE_DEVICE_TABLE(i2c, tcpci_id); diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c index eec3bcec119c..760e2f92b958 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c @@ -538,7 +538,7 @@ static void max_tcpci_remove(struct i2c_client *client) } static const struct i2c_device_id max_tcpci_id[] = { - { "maxtcpc", 0 }, + { "maxtcpc" }, { } }; MODULE_DEVICE_TABLE(i2c, max_tcpci_id); diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 5d4da962acc8..26f9006e95e1 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -57,6 +57,7 @@ S(SNK_DISCOVERY_DEBOUNCE), \ S(SNK_DISCOVERY_DEBOUNCE_DONE), \ S(SNK_WAIT_CAPABILITIES), \ + S(SNK_WAIT_CAPABILITIES_TIMEOUT), \ S(SNK_NEGOTIATE_CAPABILITIES), \ S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ S(SNK_TRANSITION_SINK), \ @@ -943,7 +944,7 @@ static int tcpm_pd_transmit(struct tcpm_port *port, enum tcpm_transmit_type tx_sop_type, const struct pd_message *msg) { - unsigned long timeout; + unsigned long time_left; int ret; unsigned int negotiated_rev; @@ -968,10 +969,10 @@ static int tcpm_pd_transmit(struct tcpm_port *port, return ret; mutex_unlock(&port->lock); - timeout = wait_for_completion_timeout(&port->tx_complete, - msecs_to_jiffies(PD_T_TCPC_TX_TIMEOUT)); + time_left = wait_for_completion_timeout(&port->tx_complete, + msecs_to_jiffies(PD_T_TCPC_TX_TIMEOUT)); mutex_lock(&port->lock); - if (!timeout) + if (!time_left) return -ETIMEDOUT; switch (port->tx_status) { @@ -3110,7 +3111,8 @@ static void tcpm_pd_data_request(struct tcpm_port *port, PD_MSG_CTRL_REJECT : PD_MSG_CTRL_NOT_SUPP, NONE_AMS); - } else if (port->state == SNK_WAIT_CAPABILITIES) { + } else if (port->state == SNK_WAIT_CAPABILITIES || + port->state == SNK_WAIT_CAPABILITIES_TIMEOUT) { /* * This message may be received even if VBUS is not * present. This is quite unexpected; see USB PD @@ -5041,10 +5043,31 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_SOFT_RESET, PD_T_SINK_WAIT_CAP); } else { - tcpm_set_state(port, hard_reset_state(port), + tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT, PD_T_SINK_WAIT_CAP); } break; + case SNK_WAIT_CAPABILITIES_TIMEOUT: + /* + * There are some USB PD sources in the field, which do not + * properly implement the specification and fail to start + * sending Source Capability messages after a soft reset. The + * specification suggests to do a hard reset when no Source + * capability message is received within PD_T_SINK_WAIT_CAP, + * but that might effectively kil the machine's power source. + * + * This slightly diverges from the specification and tries to + * recover from this by explicitly asking for the capabilities + * using the Get_Source_Cap control message before falling back + * to a hard reset. The control message should also be supported + * and handled by all USB PD source and dual role devices + * according to the specification. + */ + if (tcpm_pd_send_control(port, PD_CTRL_GET_SOURCE_CAP, TCPC_TX_SOP)) + tcpm_set_state_cond(port, hard_reset_state(port), 0); + else + tcpm_set_state(port, hard_reset_state(port), PD_T_SINK_WAIT_CAP); + break; case SNK_NEGOTIATE_CAPABILITIES: port->pd_capable = true; tcpm_set_partner_usb_comm_capable(port, @@ -5187,6 +5210,8 @@ static void run_state_machine(struct tcpm_port *port) case HARD_RESET_SEND: if (port->ams != NONE_AMS) tcpm_ams_finish(port); + if (!port->self_powered && port->port_type == TYPEC_PORT_SNK) + dev_err(port->dev, "Initiating hard-reset, which might result in machine power-loss.\n"); /* * State machine will be directed to HARD_RESET_START, * thus set upcoming_state to INVALID_STATE. diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c index ad76dbd20e65..ea768b19a7f1 100644 --- a/drivers/usb/typec/tipd/core.c +++ b/drivers/usb/typec/tipd/core.c @@ -892,19 +892,19 @@ tps6598x_register_port(struct tps6598x *tps, struct fwnode_handle *fwnode) return 0; } -static int tps_request_firmware(struct tps6598x *tps, const struct firmware **fw) +static int tps_request_firmware(struct tps6598x *tps, const struct firmware **fw, + const char **firmware_name) { - const char *firmware_name; int ret; ret = device_property_read_string(tps->dev, "firmware-name", - &firmware_name); + firmware_name); if (ret) return ret; - ret = request_firmware(fw, firmware_name, tps->dev); + ret = request_firmware(fw, *firmware_name, tps->dev); if (ret) { - dev_err(tps->dev, "failed to retrieve \"%s\"\n", firmware_name); + dev_err(tps->dev, "failed to retrieve \"%s\"\n", *firmware_name); return ret; } @@ -999,12 +999,7 @@ static int tps25750_start_patch_burst_mode(struct tps6598x *tps) u32 addr; struct device_node *np = tps->dev->of_node; - ret = device_property_read_string(tps->dev, "firmware-name", - &firmware_name); - if (ret) - return ret; - - ret = tps_request_firmware(tps, &fw); + ret = tps_request_firmware(tps, &fw, &firmware_name); if (ret) return ret; @@ -1155,12 +1150,7 @@ static int tps6598x_apply_patch(struct tps6598x *tps) const char *firmware_name; int ret; - ret = device_property_read_string(tps->dev, "firmware-name", - &firmware_name); - if (ret) - return ret; - - ret = tps_request_firmware(tps, &fw); + ret = tps_request_firmware(tps, &fw, &firmware_name); if (ret) return ret; @@ -1175,10 +1165,7 @@ static int tps6598x_apply_patch(struct tps6598x *tps) bytes_left = fw->size; while (bytes_left) { - if (bytes_left < TPS_MAX_LEN) - in_len = bytes_left; - else - in_len = TPS_MAX_LEN; + in_len = min(bytes_left, TPS_MAX_LEN); ret = tps6598x_exec_cmd(tps, "PTCd", in_len, fw->data + copied_bytes, TPS_PTCD_OUT_BYTES, out); @@ -1205,6 +1192,10 @@ static int tps6598x_apply_patch(struct tps6598x *tps) release_fw: release_firmware(fw); + if (ret) { + dev_err(tps->dev, "Failed to write patch %s of %zu bytes\n", + firmware_name, fw->size); + } return ret; }; diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig index bdcb1764cfae..680e1b87b152 100644 --- a/drivers/usb/typec/ucsi/Kconfig +++ b/drivers/usb/typec/ucsi/Kconfig @@ -69,4 +69,13 @@ config UCSI_PMIC_GLINK To compile the driver as a module, choose M here: the module will be called ucsi_glink. +config UCSI_LENOVO_YOGA_C630 + tristate "UCSI Interface Driver for Lenovo Yoga C630" + depends on EC_LENOVO_YOGA_C630 + help + This driver enables UCSI support on the Lenovo Yoga C630 laptop. + + To compile the driver as a module, choose M here: the module will be + called ucsi_yoga_c630. + endif diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile index b4679f94696b..aed41d23887b 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_UCSI_ACPI) += ucsi_acpi.o obj-$(CONFIG_UCSI_CCG) += ucsi_ccg.o obj-$(CONFIG_UCSI_STM32G0) += ucsi_stm32g0.o obj-$(CONFIG_UCSI_PMIC_GLINK) += ucsi_glink.o +obj-$(CONFIG_UCSI_LENOVO_YOGA_C630) += ucsi_yoga_c630.o diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c index 8be92fc1d12c..420af5139c70 100644 --- a/drivers/usb/typec/ucsi/displayport.c +++ b/drivers/usb/typec/ucsi/displayport.c @@ -333,7 +333,7 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, dp->con = con; dp->alt = alt; - alt->ops = &ucsi_displayport_ops; + typec_altmode_set_ops(alt, &ucsi_displayport_ops); typec_altmode_set_drvdata(alt, dp); return alt; diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c index b35c6e07911e..e623d80e177c 100644 --- a/drivers/usb/typec/ucsi/psy.c +++ b/drivers/usb/typec/ucsi/psy.c @@ -20,6 +20,7 @@ enum ucsi_psy_online_states { }; static enum power_supply_property ucsi_psy_props[] = { + POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_USB_TYPE, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_VOLTAGE_MIN, @@ -194,6 +195,35 @@ static int ucsi_psy_get_usb_type(struct ucsi_connector *con, return 0; } +static int ucsi_psy_get_charge_type(struct ucsi_connector *con, union power_supply_propval *val) +{ + if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) { + val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; + return 0; + } + + /* The Battery Charging Cabability Status field is only valid in sink role. */ + if ((con->status.flags & UCSI_CONSTAT_PWR_DIR) != TYPEC_SINK) { + val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; + return 0; + } + + switch (UCSI_CONSTAT_BC_STATUS(con->status.pwr_status)) { + case UCSI_CONSTAT_BC_NOMINAL_CHARGING: + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; + break; + case UCSI_CONSTAT_BC_SLOW_CHARGING: + case UCSI_CONSTAT_BC_TRICKLE_CHARGING: + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + default: + val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; + break; + } + + return 0; +} + static int ucsi_psy_get_prop(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -201,6 +231,8 @@ static int ucsi_psy_get_prop(struct power_supply *psy, struct ucsi_connector *con = power_supply_get_drvdata(psy); switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_TYPE: + return ucsi_psy_get_charge_type(con, val); case POWER_SUPPLY_PROP_USB_TYPE: return ucsi_psy_get_usb_type(con, val); case POWER_SUPPLY_PROP_ONLINE: diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 2cc7aedd490f..dcd3765cc1f5 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -36,18 +36,47 @@ */ #define UCSI_SWAP_TIMEOUT_MS 5000 -static int ucsi_read_message_in(struct ucsi *ucsi, void *buf, - size_t buf_size) +void ucsi_notify_common(struct ucsi *ucsi, u32 cci) { - /* - * Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the - * reads here. - */ - if (ucsi->version <= UCSI_VERSION_1_2) - buf_size = clamp(buf_size, 0, 16); + if (UCSI_CCI_CONNECTOR(cci)) + ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci)); - return ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, buf, buf_size); + if (cci & UCSI_CCI_ACK_COMPLETE && + test_bit(ACK_PENDING, &ucsi->flags)) + complete(&ucsi->complete); + + if (cci & UCSI_CCI_COMMAND_COMPLETE && + test_bit(COMMAND_PENDING, &ucsi->flags)) + complete(&ucsi->complete); } +EXPORT_SYMBOL_GPL(ucsi_notify_common); + +int ucsi_sync_control_common(struct ucsi *ucsi, u64 command) +{ + bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; + int ret; + + if (ack) + set_bit(ACK_PENDING, &ucsi->flags); + else + set_bit(COMMAND_PENDING, &ucsi->flags); + + ret = ucsi->ops->async_control(ucsi, command); + if (ret) + goto out_clear_bit; + + if (!wait_for_completion_timeout(&ucsi->complete, 5 * HZ)) + ret = -ETIMEDOUT; + +out_clear_bit: + if (ack) + clear_bit(ACK_PENDING, &ucsi->flags); + else + clear_bit(COMMAND_PENDING, &ucsi->flags); + + return ret; +} +EXPORT_SYMBOL_GPL(ucsi_sync_control_common); static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) { @@ -60,32 +89,79 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) ctrl |= UCSI_ACK_CONNECTOR_CHANGE; } - return ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); + return ucsi->ops->sync_control(ucsi, ctrl); } -static int ucsi_exec_command(struct ucsi *ucsi, u64 command); - -static int ucsi_read_error(struct ucsi *ucsi) +static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, + void *data, size_t size, bool conn_ack) { - u16 error; - int ret; + int ret, err; - /* Acknowledge the command that failed */ - ret = ucsi_acknowledge(ucsi, false); + *cci = 0; + + /* + * Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the + * reads here. + */ + if (ucsi->version <= UCSI_VERSION_1_2) + size = clamp(size, 0, 16); + + ret = ucsi->ops->sync_control(ucsi, command); if (ret) return ret; - ret = ucsi_exec_command(ucsi, UCSI_GET_ERROR_STATUS); + ret = ucsi->ops->read_cci(ucsi, cci); + if (ret) + return ret; + + if (*cci & UCSI_CCI_BUSY) + return -EBUSY; + + if (!(*cci & UCSI_CCI_COMMAND_COMPLETE)) + return -EIO; + + if (*cci & UCSI_CCI_NOT_SUPPORTED) + err = -EOPNOTSUPP; + else if (*cci & UCSI_CCI_ERROR) + err = -EIO; + else + err = 0; + + if (!err && data && UCSI_CCI_LENGTH(*cci)) + err = ucsi->ops->read_message_in(ucsi, data, size); + + /* + * Don't ACK connection change if there was an error. + */ + ret = ucsi_acknowledge(ucsi, err ? false : conn_ack); + if (ret) + return ret; + + return err; +} + +static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num) +{ + u64 command; + u16 error; + u32 cci; + int ret; + + command = UCSI_GET_ERROR_STATUS | UCSI_CONNECTOR_NUMBER(connector_num); + ret = ucsi_run_command(ucsi, command, &cci, + &error, sizeof(error), false); + + if (cci & UCSI_CCI_BUSY) { + ret = ucsi_run_command(ucsi, UCSI_CANCEL, &cci, NULL, 0, false); + + return ret ? ret : -EBUSY; + } + if (ret < 0) return ret; - ret = ucsi_read_message_in(ucsi, &error, sizeof(error)); - if (ret) - return ret; - - ret = ucsi_acknowledge(ucsi, false); - if (ret) - return ret; + if (cci & UCSI_CCI_ERROR) + return -EIO; switch (error) { case UCSI_ERROR_INCOMPATIBLE_PARTNER: @@ -117,6 +193,12 @@ static int ucsi_read_error(struct ucsi *ucsi) case UCSI_ERROR_SWAP_REJECTED: dev_warn(ucsi->dev, "Swap rejected\n"); break; + case UCSI_ERROR_REVERSE_CURRENT_PROTECTION: + dev_warn(ucsi->dev, "Reverse Current Protection detected\n"); + break; + case UCSI_ERROR_SET_SINK_PATH_REJECTED: + dev_warn(ucsi->dev, "Set Sink Path rejected\n"); + break; case UCSI_ERROR_UNDEFINED: default: dev_err(ucsi->dev, "unknown error %u\n", error); @@ -126,77 +208,44 @@ static int ucsi_read_error(struct ucsi *ucsi) return -EIO; } -static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) +static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, + void *data, size_t size, bool conn_ack) { + u8 connector_num; u32 cci; int ret; - ret = ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); - if (ret) - return ret; - - ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); - if (ret) - return ret; - - if (cmd != UCSI_CANCEL && cci & UCSI_CCI_BUSY) - return ucsi_exec_command(ucsi, UCSI_CANCEL); - - if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) - return -EIO; - - if (cci & UCSI_CCI_NOT_SUPPORTED) { - if (ucsi_acknowledge(ucsi, false) < 0) - dev_err(ucsi->dev, - "ACK of unsupported command failed\n"); - return -EOPNOTSUPP; - } - - if (cci & UCSI_CCI_ERROR) { - if (cmd == UCSI_GET_ERROR_STATUS) { - ret = ucsi_acknowledge(ucsi, false); - if (ret) - return ret; - - return -EIO; + if (ucsi->version > UCSI_VERSION_1_2) { + switch (UCSI_COMMAND(cmd)) { + case UCSI_GET_ALTERNATE_MODES: + connector_num = UCSI_GET_ALTMODE_GET_CONNECTOR_NUMBER(cmd); + break; + case UCSI_PPM_RESET: + case UCSI_CANCEL: + case UCSI_ACK_CC_CI: + case UCSI_SET_NOTIFICATION_ENABLE: + case UCSI_GET_CAPABILITY: + connector_num = 0; + break; + default: + connector_num = UCSI_DEFAULT_GET_CONNECTOR_NUMBER(cmd); + break; } - return ucsi_read_error(ucsi); + } else { + connector_num = 0; } - if (cmd == UCSI_CANCEL && cci & UCSI_CCI_CANCEL_COMPLETE) { - ret = ucsi_acknowledge(ucsi, false); - return ret ? ret : -EBUSY; - } - - return UCSI_CCI_LENGTH(cci); -} - -static int ucsi_send_command_common(struct ucsi *ucsi, u64 command, - void *data, size_t size, bool conn_ack) -{ - u8 length; - int ret; - mutex_lock(&ucsi->ppm_lock); - ret = ucsi_exec_command(ucsi, command); - if (ret < 0) - goto out; - - length = ret; - - if (data) { - ret = ucsi_read_message_in(ucsi, data, size); - if (ret) - goto out; + ret = ucsi_run_command(ucsi, cmd, &cci, data, size, conn_ack); + if (cci & UCSI_CCI_BUSY) { + ret = ucsi_run_command(ucsi, UCSI_CANCEL, &cci, NULL, 0, false); + return ret ? ret : -EBUSY; } - ret = ucsi_acknowledge(ucsi, conn_ack); - if (ret) - goto out; + if (cci & UCSI_CCI_ERROR) + return ucsi_read_error(ucsi, connector_num); - ret = length; -out: mutex_unlock(&ucsi->ppm_lock); return ret; } @@ -646,9 +695,13 @@ static int ucsi_read_pdos(struct ucsi_connector *con, static int ucsi_get_pdos(struct ucsi_connector *con, enum typec_role role, int is_partner, u32 *pdos) { + struct ucsi *ucsi = con->ucsi; u8 num_pdos; int ret; + if (!(ucsi->cap.features & UCSI_CAP_PDO_DETAILS)) + return 0; + /* UCSI max payload means only getting at most 4 PDOs at a time */ ret = ucsi_read_pdos(con, role, is_partner, pdos, 0, UCSI_MAX_PDOS); if (ret < 0) @@ -817,10 +870,11 @@ static int ucsi_check_altmodes(struct ucsi_connector *con) /* Ignoring the errors in this case. */ if (con->partner_altmode[0]) { num_partner_am = ucsi_get_num_altmode(con->partner_altmode); - if (num_partner_am > 0) - typec_partner_set_num_altmodes(con->partner, num_partner_am); + typec_partner_set_num_altmodes(con->partner, num_partner_am); ucsi_altmode_update_active(con); return 0; + } else { + typec_partner_set_num_altmodes(con->partner, 0); } return ret; @@ -968,7 +1022,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con) con->rdo = con->status.request_data_obj; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD); ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0); - ucsi_partner_task(con, ucsi_check_altmodes, 30, 0); + ucsi_partner_task(con, ucsi_check_altmodes, 30, HZ); ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ); break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: @@ -1143,7 +1197,7 @@ static int ucsi_check_connection(struct ucsi_connector *con) static int ucsi_check_cable(struct ucsi_connector *con) { u64 command; - int ret; + int ret, num_plug_am; if (con->cable) return 0; @@ -1175,6 +1229,13 @@ static int ucsi_check_cable(struct ucsi_connector *con) ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); if (ret < 0) return ret; + + if (con->plug_altmode[0]) { + num_plug_am = ucsi_get_num_altmode(con->plug_altmode); + typec_plug_set_num_altmodes(con->plug, num_plug_am); + } else { + typec_plug_set_num_altmodes(con->plug, 0); + } } return 0; @@ -1252,7 +1313,10 @@ static void ucsi_handle_connector_change(struct work_struct *work) } if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) - ucsi_partner_task(con, ucsi_check_altmodes, 1, 0); + ucsi_partner_task(con, ucsi_check_altmodes, 1, HZ); + + if (con->status.change & UCSI_CONSTAT_BC_CHANGE) + ucsi_port_psy_changed(con); out_unlock: mutex_unlock(&con->lock); @@ -1298,7 +1362,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) mutex_lock(&ucsi->ppm_lock); - ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); + ret = ucsi->ops->read_cci(ucsi, &cci); if (ret < 0) goto out; @@ -1310,15 +1374,13 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) */ if (cci & UCSI_CCI_RESET_COMPLETE) { command = UCSI_SET_NOTIFICATION_ENABLE; - ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, - sizeof(command)); + ret = ucsi->ops->async_control(ucsi, command); if (ret < 0) goto out; tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); do { - ret = ucsi->ops->read(ucsi, UCSI_CCI, - &cci, sizeof(cci)); + ret = ucsi->ops->read_cci(ucsi, &cci); if (ret < 0) goto out; if (cci & UCSI_CCI_COMMAND_COMPLETE) @@ -1332,8 +1394,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) } command = UCSI_PPM_RESET; - ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, - sizeof(command)); + ret = ucsi->ops->async_control(ucsi, command); if (ret < 0) goto out; @@ -1348,15 +1409,13 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) /* Give the PPM time to process a reset before reading CCI */ msleep(20); - ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); + ret = ucsi->ops->read_cci(ucsi, &cci); if (ret) goto out; /* If the PPM is still doing something else, reset it again. */ if (cci & ~UCSI_CCI_RESET_COMPLETE) { - ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, - &command, - sizeof(command)); + ret = ucsi->ops->async_control(ucsi, command); if (ret < 0) goto out; } @@ -1669,7 +1728,7 @@ out_unlock: static u64 ucsi_get_supported_notifications(struct ucsi *ucsi) { - u8 features = ucsi->cap.features; + u16 features = ucsi->cap.features; u64 ntfy = UCSI_ENABLE_NTFY_ALL; if (!(features & UCSI_CAP_ALT_MODE_DETAILS)) @@ -1685,6 +1744,23 @@ static u64 ucsi_get_supported_notifications(struct ucsi *ucsi) if (!(features & UCSI_CAP_PD_RESET)) ntfy &= ~UCSI_ENABLE_NTFY_PD_RESET_COMPLETE; + if (ucsi->version <= UCSI_VERSION_1_2) + return ntfy; + + ntfy |= UCSI_ENABLE_NTFY_SINK_PATH_STS_CHANGE; + + if (features & UCSI_CAP_GET_ATTENTION_VDO) + ntfy |= UCSI_ENABLE_NTFY_ATTENTION; + + if (features & UCSI_CAP_FW_UPDATE_REQUEST) + ntfy |= UCSI_ENABLE_NTFY_LPM_FW_UPDATE_REQ; + + if (features & UCSI_CAP_SECURITY_REQUEST) + ntfy |= UCSI_ENABLE_NTFY_SECURITY_REQ_PARTNER; + + if (features & UCSI_CAP_SET_RETIMER_MODE) + ntfy |= UCSI_ENABLE_NTFY_SET_RETIMER_MODE; + return ntfy; } @@ -1753,7 +1829,7 @@ static int ucsi_init(struct ucsi *ucsi) ucsi->ntfy = ntfy; mutex_lock(&ucsi->ppm_lock); - ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); + ret = ucsi->ops->read_cci(ucsi, &cci); mutex_unlock(&ucsi->ppm_lock); if (ret) return ret; @@ -1867,7 +1943,9 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) { struct ucsi *ucsi; - if (!ops || !ops->read || !ops->sync_write || !ops->async_write) + if (!ops || + !ops->read_version || !ops->read_cci || !ops->read_message_in || + !ops->sync_control || !ops->async_control) return ERR_PTR(-EINVAL); ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL); @@ -1877,6 +1955,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) INIT_WORK(&ucsi->resume_work, ucsi_resume_work); INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work); mutex_init(&ucsi->ppm_lock); + init_completion(&ucsi->complete); ucsi->dev = dev; ucsi->ops = ops; @@ -1903,8 +1982,7 @@ int ucsi_register(struct ucsi *ucsi) { int ret; - ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version, - sizeof(ucsi->version)); + ret = ucsi->ops->read_version(ucsi, &ucsi->version); if (ret) return ret; @@ -1943,7 +2021,7 @@ void ucsi_unregister(struct ucsi *ucsi) cancel_work_sync(&ucsi->resume_work); /* Disable notifications */ - ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); + ucsi->ops->async_control(ucsi, cmd); if (!ucsi->connector) return; diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index c4d103db9d0f..57129f3c0814 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -4,6 +4,7 @@ #define __DRIVER_USB_TYPEC_UCSI_H #include +#include #include #include #include @@ -56,9 +57,11 @@ struct dentry; /** * struct ucsi_operations - UCSI I/O operations - * @read: Read operation - * @sync_write: Blocking write operation - * @async_write: Non-blocking write operation + * @read_version: Read implemented UCSI version + * @read_cci: Read CCI register + * @read_message_in: Read message data from UCSI + * @sync_control: Blocking control operation + * @async_control: Non-blocking control operation * @update_altmodes: Squashes duplicate DP altmodes * @update_connector: Update connector capabilities before registering * @connector_status: Updates connector status, called holding connector lock @@ -68,12 +71,11 @@ struct dentry; * return immediately after sending the data to the PPM. */ struct ucsi_operations { - int (*read)(struct ucsi *ucsi, unsigned int offset, - void *val, size_t val_len); - int (*sync_write)(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len); - int (*async_write)(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len); + int (*read_version)(struct ucsi *ucsi, u16 *version); + int (*read_cci)(struct ucsi *ucsi, u32 *cci); + int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len); + int (*sync_control)(struct ucsi *ucsi, u64 command); + int (*async_control)(struct ucsi *ucsi, u64 command); bool (*update_altmodes)(struct ucsi *ucsi, struct ucsi_altmode *orig, struct ucsi_altmode *updated); void (*update_connector)(struct ucsi_connector *con); @@ -116,6 +118,9 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num); #define UCSI_CONNECTOR_NUMBER(_num_) ((u64)(_num_) << 16) #define UCSI_COMMAND(_cmd_) ((_cmd_) & 0xff) +#define UCSI_GET_ALTMODE_GET_CONNECTOR_NUMBER(_cmd_) (((_cmd_) >> 24) & GENMASK(6, 0)) +#define UCSI_DEFAULT_GET_CONNECTOR_NUMBER(_cmd_) (((_cmd_) >> 16) & GENMASK(6, 0)) + /* CONNECTOR_RESET command bits */ #define UCSI_CONNECTOR_RESET_HARD BIT(23) /* Deprecated in v1.1 */ @@ -124,18 +129,23 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num); #define UCSI_ACK_COMMAND_COMPLETE BIT(17) /* SET_NOTIFICATION_ENABLE command bits */ -#define UCSI_ENABLE_NTFY_CMD_COMPLETE BIT(16) -#define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE BIT(17) -#define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE BIT(18) -#define UCSI_ENABLE_NTFY_CAP_CHANGE BIT(21) -#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE BIT(22) -#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE BIT(23) -#define UCSI_ENABLE_NTFY_CAM_CHANGE BIT(24) -#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE BIT(25) -#define UCSI_ENABLE_NTFY_PARTNER_CHANGE BIT(27) -#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE BIT(28) -#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE BIT(30) -#define UCSI_ENABLE_NTFY_ERROR BIT(31) +#define UCSI_ENABLE_NTFY_CMD_COMPLETE BIT_ULL(16) +#define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE BIT_ULL(17) +#define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE BIT_ULL(18) +#define UCSI_ENABLE_NTFY_ATTENTION BIT_ULL(19) +#define UCSI_ENABLE_NTFY_LPM_FW_UPDATE_REQ BIT_ULL(20) +#define UCSI_ENABLE_NTFY_CAP_CHANGE BIT_ULL(21) +#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE BIT_ULL(22) +#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE BIT_ULL(23) +#define UCSI_ENABLE_NTFY_CAM_CHANGE BIT_ULL(24) +#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE BIT_ULL(25) +#define UCSI_ENABLE_NTFY_SECURITY_REQ_PARTNER BIT_ULL(26) +#define UCSI_ENABLE_NTFY_PARTNER_CHANGE BIT_ULL(27) +#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE BIT_ULL(28) +#define UCSI_ENABLE_NTFY_SET_RETIMER_MODE BIT_ULL(29) +#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE BIT_ULL(30) +#define UCSI_ENABLE_NTFY_ERROR BIT_ULL(31) +#define UCSI_ENABLE_NTFY_SINK_PATH_STS_CHANGE BIT_ULL(32) #define UCSI_ENABLE_NTFY_ALL 0xdbe70000 /* SET_UOR command bits */ @@ -193,6 +203,8 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num); #define UCSI_ERROR_HARD_RESET BIT(10) #define UCSI_ERROR_PPM_POLICY_CONFLICT BIT(11) #define UCSI_ERROR_SWAP_REJECTED BIT(12) +#define UCSI_ERROR_REVERSE_CURRENT_PROTECTION BIT(13) +#define UCSI_ERROR_SET_SINK_PATH_REJECTED BIT(14) #define UCSI_SET_NEW_CAM_ENTER(x) (((x) >> 23) & 0x1) #define UCSI_SET_NEW_CAM_GET_AM(x) (((x) >> 24) & 0xff) @@ -220,7 +232,13 @@ struct ucsi_capability { #define UCSI_CAP_CABLE_DETAILS BIT(5) #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6) #define UCSI_CAP_PD_RESET BIT(7) -#define UCSI_CAP_GET_PD_MESSAGE BIT(8) +#define UCSI_CAP_GET_PD_MESSAGE BIT(8) +#define UCSI_CAP_GET_ATTENTION_VDO BIT(9) +#define UCSI_CAP_FW_UPDATE_REQUEST BIT(10) +#define UCSI_CAP_NEGOTIATED_PWR_LEVEL_CHANGE BIT(11) +#define UCSI_CAP_SECURITY_REQUEST BIT(12) +#define UCSI_CAP_SET_RETIMER_MODE BIT(13) +#define UCSI_CAP_CHUNKING_SUPPORT BIT(14) u8 reserved_1; u8 num_alt_modes; u8 reserved_2; @@ -384,7 +402,7 @@ struct ucsi_debugfs_entry { struct ucsi { u16 version; struct device *dev; - struct driver_data *driver_data; + void *driver_data; const struct ucsi_operations *ops; @@ -408,6 +426,9 @@ struct ucsi { /* PPM communication flags */ unsigned long flags; #define EVENT_PENDING 0 +#define COMMAND_PENDING 1 +#define ACK_PENDING 2 + struct completion complete; unsigned long quirks; #define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */ @@ -472,6 +493,9 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command, void ucsi_altmode_update_active(struct ucsi_connector *con); int ucsi_resume(struct ucsi *ucsi); +void ucsi_notify_common(struct ucsi *ucsi, u32 cci); +int ucsi_sync_control_common(struct ucsi *ucsi, u64 command); + #if IS_ENABLED(CONFIG_POWER_SUPPLY) int ucsi_register_port_psy(struct ucsi_connector *con); void ucsi_unregister_port_psy(struct ucsi_connector *con); @@ -496,7 +520,7 @@ ucsi_register_displayport(struct ucsi_connector *con, bool override, int offset, struct typec_altmode_desc *desc) { - return NULL; + return typec_port_register_altmode(con->port, desc); } static inline void diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index adf32ca0f761..7a5dff8d9cc6 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -21,11 +21,7 @@ struct ucsi_acpi { struct device *dev; struct ucsi *ucsi; void *base; - struct completion complete; - unsigned long flags; -#define UCSI_ACPI_COMMAND_PENDING 1 -#define UCSI_ACPI_ACK_PENDING 2 -#define UCSI_ACPI_CHECK_BOGUS_EVENT 3 + bool check_bogus_event; guid_t guid; u64 cmd; }; @@ -46,8 +42,7 @@ static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) return 0; } -static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset, - void *val, size_t val_len) +static int ucsi_acpi_read_version(struct ucsi *ucsi, u16 *version) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; @@ -56,81 +51,94 @@ static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset, if (ret) return ret; - memcpy(val, ua->base + offset, val_len); + memcpy(version, ua->base + UCSI_VERSION, sizeof(*version)); return 0; } -static int ucsi_acpi_async_write(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len) +static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); + if (ret) + return ret; + + memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci)); + + return 0; +} + +static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); + if (ret) + return ret; + + memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len); + + return 0; +} + +static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); - memcpy(ua->base + offset, val, val_len); - ua->cmd = *(u64 *)val; + memcpy(ua->base + UCSI_CONTROL, &command, sizeof(command)); + ua->cmd = command; return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE); } -static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len) -{ - struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); - bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI; - int ret; - - if (ack) - set_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); - else - set_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); - - ret = ucsi_acpi_async_write(ucsi, offset, val, val_len); - if (ret) - goto out_clear_bit; - - if (!wait_for_completion_timeout(&ua->complete, 5 * HZ)) - ret = -ETIMEDOUT; - -out_clear_bit: - if (ack) - clear_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); - else - clear_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); - - return ret; -} - static const struct ucsi_operations ucsi_acpi_ops = { - .read = ucsi_acpi_read, - .sync_write = ucsi_acpi_sync_write, - .async_write = ucsi_acpi_async_write + .read_version = ucsi_acpi_read_version, + .read_cci = ucsi_acpi_read_cci, + .read_message_in = ucsi_acpi_read_message_in, + .sync_control = ucsi_sync_control_common, + .async_control = ucsi_acpi_async_control }; static int -ucsi_zenbook_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t val_len) +ucsi_zenbook_read_cci(struct ucsi *ucsi, u32 *cci) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; - if (offset == UCSI_VERSION || UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) { + if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) { ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); if (ret) return ret; } - memcpy(val, ua->base + offset, val_len); + memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci)); + + return 0; +} + +static int +ucsi_zenbook_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + + /* UCSI_MESSAGE_IN is never read for PPM_RESET, return stored data */ + memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len); return 0; } static const struct ucsi_operations ucsi_zenbook_ops = { - .read = ucsi_zenbook_read, - .sync_write = ucsi_acpi_sync_write, - .async_write = ucsi_acpi_async_write + .read_version = ucsi_acpi_read_version, + .read_cci = ucsi_zenbook_read_cci, + .read_message_in = ucsi_zenbook_read_message_in, + .sync_control = ucsi_sync_control_common, + .async_control = ucsi_acpi_async_control }; -static int ucsi_gram_read(struct ucsi *ucsi, unsigned int offset, - void *val, size_t val_len) +static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) { u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE | UCSI_CONSTAT_PDOS_CHANGE; @@ -138,47 +146,47 @@ static int ucsi_gram_read(struct ucsi *ucsi, unsigned int offset, struct ucsi_connector_status *status; int ret; - ret = ucsi_acpi_read(ucsi, offset, val, val_len); + ret = ucsi_acpi_read_message_in(ucsi, val, val_len); if (ret < 0) return ret; if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS && - test_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags) && - offset == UCSI_MESSAGE_IN) { + ua->check_bogus_event) { status = (struct ucsi_connector_status *)val; /* Clear the bogus change */ if (status->change == bogus_change) status->change = 0; - clear_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags); + ua->check_bogus_event = false; } return ret; } -static int ucsi_gram_sync_write(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len) +static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; - ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); + ret = ucsi_sync_control_common(ucsi, command); if (ret < 0) return ret; if (UCSI_COMMAND(ua->cmd) == UCSI_GET_PDOS && ua->cmd & UCSI_GET_PDOS_PARTNER_PDO(1) && ua->cmd & UCSI_GET_PDOS_SRC_PDOS) - set_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags); + ua->check_bogus_event = true; return ret; } static const struct ucsi_operations ucsi_gram_ops = { - .read = ucsi_gram_read, - .sync_write = ucsi_gram_sync_write, - .async_write = ucsi_acpi_async_write + .read_version = ucsi_acpi_read_version, + .read_cci = ucsi_acpi_read_cci, + .read_message_in = ucsi_gram_read_message_in, + .sync_control = ucsi_gram_sync_control, + .async_control = ucsi_acpi_async_control }; static const struct dmi_system_id ucsi_acpi_quirks[] = { @@ -206,19 +214,11 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) u32 cci; int ret; - ret = ua->ucsi->ops->read(ua->ucsi, UCSI_CCI, &cci, sizeof(cci)); + ret = ua->ucsi->ops->read_cci(ua->ucsi, &cci); if (ret) return; - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); - - if (cci & UCSI_CCI_ACK_COMPLETE && - test_bit(UCSI_ACPI_ACK_PENDING, &ua->flags)) - complete(&ua->complete); - if (cci & UCSI_CCI_COMMAND_COMPLETE && - test_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags)) - complete(&ua->complete); + ucsi_notify_common(ua->ucsi, cci); } static int ucsi_acpi_probe(struct platform_device *pdev) @@ -252,7 +252,6 @@ static int ucsi_acpi_probe(struct platform_device *pdev) if (ret) return ret; - init_completion(&ua->complete); ua->dev = &pdev->dev; id = dmi_first_match(ucsi_acpi_quirks); diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index dda7c7c94e08..b3ec799fc873 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -222,8 +222,6 @@ struct ucsi_ccg { u16 fw_build; struct work_struct pm_work; - struct completion complete; - u64 last_cmd_sent; bool has_multiple_dp; struct ucsi_ccg_altmode orig[UCSI_MAX_ALTMODES]; @@ -556,32 +554,34 @@ static void ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc, } } -static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset, - void *val, size_t val_len) +static int ucsi_ccg_read_version(struct ucsi *ucsi, u16 *version) +{ + struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); + u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_VERSION); + + return ccg_read(uc, reg, (u8 *)version, sizeof(*version)); +} + +static int ucsi_ccg_read_cci(struct ucsi *ucsi, u32 *cci) +{ + struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); + + spin_lock(&uc->op_lock); + *cci = uc->op_data.cci; + spin_unlock(&uc->op_lock); + + return 0; +} + +static int ucsi_ccg_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) { struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); - u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset); struct ucsi_capability *cap; struct ucsi_altmode *alt; - int ret = 0; - if (offset == UCSI_CCI) { - spin_lock(&uc->op_lock); - memcpy(val, &(uc->op_data).cci, val_len); - spin_unlock(&uc->op_lock); - } else if (offset == UCSI_MESSAGE_IN) { - spin_lock(&uc->op_lock); - memcpy(val, &(uc->op_data).message_in, val_len); - spin_unlock(&uc->op_lock); - } else { - ret = ccg_read(uc, reg, val, val_len); - } - - if (ret) - return ret; - - if (offset != UCSI_MESSAGE_IN) - return ret; + spin_lock(&uc->op_lock); + memcpy(val, uc->op_data.message_in, val_len); + spin_unlock(&uc->op_lock); switch (UCSI_COMMAND(uc->last_cmd_sent)) { case UCSI_GET_CURRENT_CAM: @@ -607,28 +607,26 @@ static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset, } uc->last_cmd_sent = 0; - return ret; + return 0; } -static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len) +static int ucsi_ccg_async_control(struct ucsi *ucsi, u64 command) { struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); - u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset); + u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_CONTROL); /* - * UCSI may read CCI instantly after async_write, + * UCSI may read CCI instantly after async_control, * clear CCI to avoid caller getting wrong data before we get CCI from ISR */ spin_lock(&uc->op_lock); uc->op_data.cci = 0; spin_unlock(&uc->op_lock); - return ccg_write(uc, reg, val, val_len); + return ccg_write(uc, reg, (u8 *)&command, sizeof(command)); } -static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, - const void *val, size_t val_len) +static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) { struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); struct ucsi_connector *con; @@ -637,29 +635,19 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, mutex_lock(&uc->lock); pm_runtime_get_sync(uc->dev); - set_bit(DEV_CMD_PENDING, &uc->flags); - if (offset == UCSI_CONTROL && val_len == sizeof(uc->last_cmd_sent)) { - uc->last_cmd_sent = *(u64 *)val; + uc->last_cmd_sent = command; - if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_SET_NEW_CAM && - uc->has_multiple_dp) { - con_index = (uc->last_cmd_sent >> 16) & - UCSI_CMD_CONNECTOR_MASK; - con = &uc->ucsi->connector[con_index - 1]; - ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); - } + if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_SET_NEW_CAM && + uc->has_multiple_dp) { + con_index = (uc->last_cmd_sent >> 16) & + UCSI_CMD_CONNECTOR_MASK; + con = &uc->ucsi->connector[con_index - 1]; + ucsi_ccg_update_set_new_cam_cmd(uc, con, &command); } - ret = ucsi_ccg_async_write(ucsi, offset, val, val_len); - if (ret) - goto err_clear_bit; + ret = ucsi_sync_control_common(ucsi, command); - if (!wait_for_completion_timeout(&uc->complete, msecs_to_jiffies(5000))) - ret = -ETIMEDOUT; - -err_clear_bit: - clear_bit(DEV_CMD_PENDING, &uc->flags); pm_runtime_put_sync(uc->dev); mutex_unlock(&uc->lock); @@ -667,9 +655,11 @@ err_clear_bit: } static const struct ucsi_operations ucsi_ccg_ops = { - .read = ucsi_ccg_read, - .sync_write = ucsi_ccg_sync_write, - .async_write = ucsi_ccg_async_write, + .read_version = ucsi_ccg_read_version, + .read_cci = ucsi_ccg_read_cci, + .read_message_in = ucsi_ccg_read_message_in, + .sync_control = ucsi_ccg_sync_control, + .async_control = ucsi_ccg_async_control, .update_altmodes = ucsi_ccg_update_altmodes }; @@ -694,9 +684,6 @@ static irqreturn_t ccg_irq_handler(int irq, void *data) if (ret) goto err_clear_irq; - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci)); - /* * As per CCGx UCSI interface guide, copy CCI and MESSAGE_IN * to the OpRegion before clear the UCSI interrupt @@ -708,9 +695,8 @@ static irqreturn_t ccg_irq_handler(int irq, void *data) err_clear_irq: ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg)); - if (!ret && test_bit(DEV_CMD_PENDING, &uc->flags) && - cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE)) - complete(&uc->complete); + if (!ret) + ucsi_notify_common(uc->ucsi, cci); return IRQ_HANDLED; } @@ -1429,7 +1415,6 @@ static int ucsi_ccg_probe(struct i2c_client *client) uc->client = client; uc->irq = client->irq; mutex_init(&uc->lock); - init_completion(&uc->complete); INIT_WORK(&uc->work, ccg_update_firmware); INIT_WORK(&uc->pm_work, ccg_pm_workaround_work); @@ -1516,7 +1501,7 @@ static const struct of_device_id ucsi_ccg_of_match_table[] = { MODULE_DEVICE_TABLE(of, ucsi_ccg_of_match_table); static const struct i2c_device_id ucsi_ccg_device_id[] = { - {"ccgx-ucsi", 0}, + { "ccgx-ucsi" }, {} }; MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id); diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index 2fa973afe4e6..16c328497e0b 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -64,12 +64,8 @@ struct pmic_glink_ucsi { struct ucsi *ucsi; struct completion read_ack; struct completion write_ack; - struct completion sync_ack; - bool sync_pending; struct mutex lock; /* protects concurrent access to PMIC Glink interface */ - int sync_val; - struct work_struct notify_work; struct work_struct register_work; @@ -114,6 +110,21 @@ out_unlock: return ret; } +static int pmic_glink_ucsi_read_version(struct ucsi *ucsi, u16 *version) +{ + return pmic_glink_ucsi_read(ucsi, UCSI_VERSION, version, sizeof(*version)); +} + +static int pmic_glink_ucsi_read_cci(struct ucsi *ucsi, u32 *cci) +{ + return pmic_glink_ucsi_read(ucsi, UCSI_CCI, cci, sizeof(*cci)); +} + +static int pmic_glink_ucsi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) +{ + return pmic_glink_ucsi_read(ucsi, UCSI_MESSAGE_IN, val, val_len); +} + static int pmic_glink_ucsi_locked_write(struct pmic_glink_ucsi *ucsi, unsigned int offset, const void *val, size_t val_len) { @@ -143,49 +154,18 @@ static int pmic_glink_ucsi_locked_write(struct pmic_glink_ucsi *ucsi, unsigned i return 0; } -static int pmic_glink_ucsi_async_write(struct ucsi *__ucsi, unsigned int offset, - const void *val, size_t val_len) +static int pmic_glink_ucsi_async_control(struct ucsi *__ucsi, u64 command) { struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi); int ret; mutex_lock(&ucsi->lock); - ret = pmic_glink_ucsi_locked_write(ucsi, offset, val, val_len); + ret = pmic_glink_ucsi_locked_write(ucsi, UCSI_CONTROL, &command, sizeof(command)); mutex_unlock(&ucsi->lock); return ret; } -static int pmic_glink_ucsi_sync_write(struct ucsi *__ucsi, unsigned int offset, - const void *val, size_t val_len) -{ - struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi); - unsigned long left; - int ret; - - /* TOFIX: Downstream forces recipient to CON when UCSI_GET_ALTERNATE_MODES command */ - - mutex_lock(&ucsi->lock); - ucsi->sync_val = 0; - reinit_completion(&ucsi->sync_ack); - ucsi->sync_pending = true; - ret = pmic_glink_ucsi_locked_write(ucsi, offset, val, val_len); - mutex_unlock(&ucsi->lock); - - left = wait_for_completion_timeout(&ucsi->sync_ack, 5 * HZ); - if (!left) { - dev_err(ucsi->dev, "timeout waiting for UCSI sync write response\n"); - /* return 0 here and let core UCSI code handle the CCI_BUSY */ - ret = 0; - } else if (ucsi->sync_val) { - dev_err(ucsi->dev, "sync write returned: %d\n", ucsi->sync_val); - } - - ucsi->sync_pending = false; - - return ret; -} - static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con) { struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi); @@ -216,9 +196,11 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con) } static const struct ucsi_operations pmic_glink_ucsi_ops = { - .read = pmic_glink_ucsi_read, - .sync_write = pmic_glink_ucsi_sync_write, - .async_write = pmic_glink_ucsi_async_write, + .read_version = pmic_glink_ucsi_read_version, + .read_cci = pmic_glink_ucsi_read_cci, + .read_message_in = pmic_glink_ucsi_read_message_in, + .sync_control = ucsi_sync_control_common, + .async_control = pmic_glink_ucsi_async_control, .update_connector = pmic_glink_ucsi_update_connector, .connector_status = pmic_glink_ucsi_connector_status, }; @@ -241,14 +223,12 @@ static void pmic_glink_ucsi_write_ack(struct pmic_glink_ucsi *ucsi, const void * if (resp->ret_code) return; - ucsi->sync_val = resp->ret_code; complete(&ucsi->write_ack); } static void pmic_glink_ucsi_notify(struct work_struct *work) { struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, notify_work); - unsigned int con_num; u32 cci; int ret; @@ -258,14 +238,7 @@ static void pmic_glink_ucsi_notify(struct work_struct *work) return; } - con_num = UCSI_CCI_CONNECTOR(cci); - if (con_num) - ucsi_connector_change(ucsi->ucsi, con_num); - - if (ucsi->sync_pending && - (cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))) { - complete(&ucsi->sync_ack); - } + ucsi_notify_common(ucsi->ucsi, cci); } static void pmic_glink_ucsi_register(struct work_struct *work) @@ -347,7 +320,6 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register); init_completion(&ucsi->read_ack); init_completion(&ucsi->write_ack); - init_completion(&ucsi->sync_ack); mutex_init(&ucsi->lock); ucsi->ucsi = ucsi_create(dev, &pmic_glink_ucsi_ops); diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c index ac69288e8bb0..ddbec2b78c8e 100644 --- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c @@ -61,11 +61,7 @@ struct ucsi_stm32g0 { struct i2c_client *i2c_bl; bool in_bootloader; u8 bl_version; - struct completion complete; struct device *dev; - unsigned long flags; -#define COMMAND_PENDING 1 -#define ACK_PENDING 2 const char *fw_name; struct ucsi *ucsi; bool suspended; @@ -359,8 +355,22 @@ static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset, void *val, return 0; } -static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, const void *val, - size_t len) +static int ucsi_stm32g0_read_version(struct ucsi *ucsi, u16 *version) +{ + return ucsi_stm32g0_read(ucsi, UCSI_VERSION, version, sizeof(*version)); +} + +static int ucsi_stm32g0_read_cci(struct ucsi *ucsi, u32 *cci) +{ + return ucsi_stm32g0_read(ucsi, UCSI_CCI, cci, sizeof(*cci)); +} + +static int ucsi_stm32g0_read_message_in(struct ucsi *ucsi, void *val, size_t len) +{ + return ucsi_stm32g0_read(ucsi, UCSI_MESSAGE_IN, val, len); +} + +static int ucsi_stm32g0_async_control(struct ucsi *ucsi, u64 command) { struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); struct i2c_client *client = g0->client; @@ -373,19 +383,19 @@ static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, cons unsigned char *buf; int ret; - buf = kmalloc(len + 1, GFP_KERNEL); + buf = kmalloc(sizeof(command) + 1, GFP_KERNEL); if (!buf) return -ENOMEM; - buf[0] = offset; - memcpy(&buf[1], val, len); - msg[0].len = len + 1; + buf[0] = UCSI_CONTROL; + memcpy(&buf[1], &command, sizeof(command)); + msg[0].len = sizeof(command) + 1; msg[0].buf = buf; ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); kfree(buf); if (ret != ARRAY_SIZE(msg)) { - dev_err(g0->dev, "i2c write %02x, %02x error: %d\n", client->addr, offset, ret); + dev_err(g0->dev, "i2c write %02x, %02x error: %d\n", client->addr, UCSI_CONTROL, ret); return ret < 0 ? ret : -EIO; } @@ -393,36 +403,6 @@ static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, cons return 0; } -static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const void *val, - size_t len) -{ - struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); - bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI; - int ret; - - if (ack) - set_bit(ACK_PENDING, &g0->flags); - else - set_bit(COMMAND_PENDING, &g0->flags); - - ret = ucsi_stm32g0_async_write(ucsi, offset, val, len); - if (ret) - goto out_clear_bit; - - if (!wait_for_completion_timeout(&g0->complete, msecs_to_jiffies(5000))) - ret = -ETIMEDOUT; - else - return 0; - -out_clear_bit: - if (ack) - clear_bit(ACK_PENDING, &g0->flags); - else - clear_bit(COMMAND_PENDING, &g0->flags); - - return ret; -} - static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) { struct ucsi_stm32g0 *g0 = data; @@ -436,21 +416,17 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) if (ret) return IRQ_NONE; - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(g0->ucsi, UCSI_CCI_CONNECTOR(cci)); - - if (cci & UCSI_CCI_ACK_COMPLETE && test_and_clear_bit(ACK_PENDING, &g0->flags)) - complete(&g0->complete); - if (cci & UCSI_CCI_COMMAND_COMPLETE && test_and_clear_bit(COMMAND_PENDING, &g0->flags)) - complete(&g0->complete); + ucsi_notify_common(g0->ucsi, cci); return IRQ_HANDLED; } static const struct ucsi_operations ucsi_stm32g0_ops = { - .read = ucsi_stm32g0_read, - .sync_write = ucsi_stm32g0_sync_write, - .async_write = ucsi_stm32g0_async_write, + .read_version = ucsi_stm32g0_read_version, + .read_cci = ucsi_stm32g0_read_cci, + .read_message_in = ucsi_stm32g0_read_message_in, + .sync_control = ucsi_sync_control_common, + .async_control = ucsi_stm32g0_async_control, }; static int ucsi_stm32g0_register(struct ucsi *ucsi) @@ -650,7 +626,6 @@ static int ucsi_stm32g0_probe(struct i2c_client *client) g0->dev = dev; g0->client = client; - init_completion(&g0->complete); i2c_set_clientdata(client, g0); g0->ucsi = ucsi_create(dev, &ucsi_stm32g0_ops); @@ -764,8 +739,8 @@ static const struct of_device_id __maybe_unused ucsi_stm32g0_typec_of_match[] = MODULE_DEVICE_TABLE(of, ucsi_stm32g0_typec_of_match); static const struct i2c_device_id ucsi_stm32g0_typec_i2c_devid[] = { - {"stm32g0-typec", 0}, - {}, + { "stm32g0-typec" }, + {} }; MODULE_DEVICE_TABLE(i2c, ucsi_stm32g0_typec_i2c_devid); diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c new file mode 100644 index 000000000000..f3a5e24ea84d --- /dev/null +++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024, Linaro Ltd + * Authors: + * Bjorn Andersson + * Dmitry Baryshkov + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ucsi.h" + +struct yoga_c630_ucsi { + struct yoga_c630_ec *ec; + struct ucsi *ucsi; + struct notifier_block nb; + u16 version; +}; + +static int yoga_c630_ucsi_read_version(struct ucsi *ucsi, u16 *version) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + + *version = uec->version; + + return 0; +} + +static int yoga_c630_ucsi_read_cci(struct ucsi *ucsi, u32 *cci) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + u8 buf[YOGA_C630_UCSI_READ_SIZE]; + int ret; + + ret = yoga_c630_ec_ucsi_read(uec->ec, buf); + if (ret) + return ret; + + memcpy(cci, buf, sizeof(*cci)); + + return 0; +} + +static int yoga_c630_ucsi_read_message_in(struct ucsi *ucsi, + void *val, size_t val_len) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + u8 buf[YOGA_C630_UCSI_READ_SIZE]; + int ret; + + ret = yoga_c630_ec_ucsi_read(uec->ec, buf); + if (ret) + return ret; + + memcpy(val, buf + YOGA_C630_UCSI_CCI_SIZE, + min(val_len, YOGA_C630_UCSI_DATA_SIZE)); + + return 0; +} + +static int yoga_c630_ucsi_async_control(struct ucsi *ucsi, u64 command) +{ + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); + + return yoga_c630_ec_ucsi_write(uec->ec, (u8*)&command); +} + +const struct ucsi_operations yoga_c630_ucsi_ops = { + .read_version = yoga_c630_ucsi_read_version, + .read_cci = yoga_c630_ucsi_read_cci, + .read_message_in = yoga_c630_ucsi_read_message_in, + .sync_control = ucsi_sync_control_common, + .async_control = yoga_c630_ucsi_async_control, +}; + +static int yoga_c630_ucsi_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct yoga_c630_ucsi *uec = container_of(nb, struct yoga_c630_ucsi, nb); + u32 cci; + int ret; + + switch (action) { + case LENOVO_EC_EVENT_USB: + case LENOVO_EC_EVENT_HPD: + ucsi_connector_change(uec->ucsi, 1); + return NOTIFY_OK; + + case LENOVO_EC_EVENT_UCSI: + ret = uec->ucsi->ops->read_cci(uec->ucsi, &cci); + if (ret) + return NOTIFY_DONE; + + ucsi_notify_common(uec->ucsi, cci); + + return NOTIFY_OK; + + default: + return NOTIFY_DONE; + } +} + +static int yoga_c630_ucsi_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct yoga_c630_ec *ec = adev->dev.platform_data; + struct yoga_c630_ucsi *uec; + int ret; + + uec = devm_kzalloc(&adev->dev, sizeof(*uec), GFP_KERNEL); + if (!uec) + return -ENOMEM; + + uec->ec = ec; + uec->nb.notifier_call = yoga_c630_ucsi_notify; + + uec->ucsi = ucsi_create(&adev->dev, &yoga_c630_ucsi_ops); + if (IS_ERR(uec->ucsi)) + return PTR_ERR(uec->ucsi); + + ucsi_set_drvdata(uec->ucsi, uec); + + uec->version = yoga_c630_ec_ucsi_get_version(uec->ec); + + auxiliary_set_drvdata(adev, uec); + + ret = yoga_c630_ec_register_notify(ec, &uec->nb); + if (ret) + return ret; + + return ucsi_register(uec->ucsi); +} + +static void yoga_c630_ucsi_remove(struct auxiliary_device *adev) +{ + struct yoga_c630_ucsi *uec = auxiliary_get_drvdata(adev); + + yoga_c630_ec_unregister_notify(uec->ec, &uec->nb); + ucsi_unregister(uec->ucsi); +} + +static const struct auxiliary_device_id yoga_c630_ucsi_id_table[] = { + { .name = YOGA_C630_MOD_NAME "." YOGA_C630_DEV_UCSI, }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, yoga_c630_ucsi_id_table); + +static struct auxiliary_driver yoga_c630_ucsi_driver = { + .name = YOGA_C630_DEV_UCSI, + .id_table = yoga_c630_ucsi_id_table, + .probe = yoga_c630_ucsi_probe, + .remove = yoga_c630_ucsi_remove, +}; + +module_auxiliary_driver(yoga_c630_ucsi_driver); + +MODULE_DESCRIPTION("Lenovo Yoga C630 UCSI"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c index fc01b31bbb87..6338d818bc8b 100644 --- a/drivers/usb/usbip/stub_rx.c +++ b/drivers/usb/usbip/stub_rx.c @@ -144,53 +144,62 @@ static int tweak_set_configuration_cmd(struct urb *urb) if (err && err != -ENODEV) dev_err(&sdev->udev->dev, "can't set config #%d, error %d\n", config, err); - return 0; + return err; } static int tweak_reset_device_cmd(struct urb *urb) { struct stub_priv *priv = (struct stub_priv *) urb->context; struct stub_device *sdev = priv->sdev; + int err; dev_info(&urb->dev->dev, "usb_queue_reset_device\n"); - if (usb_lock_device_for_reset(sdev->udev, NULL) < 0) { + err = usb_lock_device_for_reset(sdev->udev, NULL); + if (err < 0) { dev_err(&urb->dev->dev, "could not obtain lock to reset device\n"); - return 0; + return err; } - usb_reset_device(sdev->udev); + err = usb_reset_device(sdev->udev); usb_unlock_device(sdev->udev); - return 0; + return err; } /* * clear_halt, set_interface, and set_configuration require special tricks. + * Returns 1 if request was tweaked, 0 otherwise. */ -static void tweak_special_requests(struct urb *urb) +static int tweak_special_requests(struct urb *urb) { + int err; + if (!urb || !urb->setup_packet) - return; + return 0; if (usb_pipetype(urb->pipe) != PIPE_CONTROL) - return; + return 0; if (is_clear_halt_cmd(urb)) /* tweak clear_halt */ - tweak_clear_halt_cmd(urb); + err = tweak_clear_halt_cmd(urb); else if (is_set_interface_cmd(urb)) /* tweak set_interface */ - tweak_set_interface_cmd(urb); + err = tweak_set_interface_cmd(urb); else if (is_set_configuration_cmd(urb)) /* tweak set_configuration */ - tweak_set_configuration_cmd(urb); + err = tweak_set_configuration_cmd(urb); else if (is_reset_device_cmd(urb)) - tweak_reset_device_cmd(urb); - else + err = tweak_reset_device_cmd(urb); + else { usbip_dbg_stub_rx("no need to tweak\n"); + return 0; + } + + return !err; } /* @@ -468,6 +477,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, int support_sg = 1; int np = 0; int ret, i; + int is_tweaked; if (pipe == -1) return; @@ -580,8 +590,11 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, priv->urbs[i]->pipe = pipe; priv->urbs[i]->complete = stub_complete; - /* no need to submit an intercepted request, but harmless? */ - tweak_special_requests(priv->urbs[i]); + /* + * all URBs belong to a single PDU, so a global is_tweaked flag is + * enough + */ + is_tweaked = tweak_special_requests(priv->urbs[i]); masking_bogus_flags(priv->urbs[i]); } @@ -594,22 +607,32 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, /* urb is now ready to submit */ for (i = 0; i < priv->num_urbs; i++) { - ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL); + if (!is_tweaked) { + ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL); - if (ret == 0) - usbip_dbg_stub_rx("submit urb ok, seqnum %u\n", - pdu->base.seqnum); - else { - dev_err(&udev->dev, "submit_urb error, %d\n", ret); - usbip_dump_header(pdu); - usbip_dump_urb(priv->urbs[i]); + if (ret == 0) + usbip_dbg_stub_rx("submit urb ok, seqnum %u\n", + pdu->base.seqnum); + else { + dev_err(&udev->dev, "submit_urb error, %d\n", ret); + usbip_dump_header(pdu); + usbip_dump_urb(priv->urbs[i]); + /* + * Pessimistic. + * This connection will be discarded. + */ + usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); + break; + } + } else { /* - * Pessimistic. - * This connection will be discarded. + * An identical URB was already submitted in + * tweak_special_requests(). Skip submitting this URB to not + * duplicate the request. */ - usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); - break; + priv->urbs[i]->status = 0; + stub_complete(priv->urbs[i]); } } diff --git a/drivers/virtio/virtio_dma_buf.c b/drivers/virtio/virtio_dma_buf.c index 19a843fad6c6..9f4ef2f07203 100644 --- a/drivers/virtio/virtio_dma_buf.c +++ b/drivers/virtio/virtio_dma_buf.c @@ -91,5 +91,6 @@ int virtio_dma_buf_get_uuid(struct dma_buf *dma_buf, } EXPORT_SYMBOL(virtio_dma_buf_get_uuid); +MODULE_DESCRIPTION("dma-bufs for virtio exported objects"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index afb1cc4606c5..d82e86d3ddf6 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -504,7 +504,7 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev, if (result == 0) result = count; } else { - dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family, + dev_info(dev, "Device %02x-%012llx doesn't exist\n", rn.family, (unsigned long long)rn.id); result = -EINVAL; } diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 3a71c5eb2f83..19a0ea28e9f3 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -32,12 +32,8 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl, * We are in process context(kernel thread), so can sleep. */ dev = kzalloc(sizeof(struct w1_master) + sizeof(struct w1_bus_master), GFP_KERNEL); - if (!dev) { - pr_err("Failed to allocate %zd bytes for new w1 device.\n", - sizeof(struct w1_master)); + if (!dev) return NULL; - } - dev->bus_master = (struct w1_bus_master *)(dev + 1); diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index 1b2a7aa0af36..3d6d4b503220 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -195,38 +195,38 @@ enum { * Note: don't forget to add new options to btrfs_show_options() */ enum { - BTRFS_MOUNT_NODATASUM = (1UL << 0), - BTRFS_MOUNT_NODATACOW = (1UL << 1), - BTRFS_MOUNT_NOBARRIER = (1UL << 2), - BTRFS_MOUNT_SSD = (1UL << 3), - BTRFS_MOUNT_DEGRADED = (1UL << 4), - BTRFS_MOUNT_COMPRESS = (1UL << 5), - BTRFS_MOUNT_NOTREELOG = (1UL << 6), - BTRFS_MOUNT_FLUSHONCOMMIT = (1UL << 7), - BTRFS_MOUNT_SSD_SPREAD = (1UL << 8), - BTRFS_MOUNT_NOSSD = (1UL << 9), - BTRFS_MOUNT_DISCARD_SYNC = (1UL << 10), - BTRFS_MOUNT_FORCE_COMPRESS = (1UL << 11), - BTRFS_MOUNT_SPACE_CACHE = (1UL << 12), - BTRFS_MOUNT_CLEAR_CACHE = (1UL << 13), - BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED = (1UL << 14), - BTRFS_MOUNT_ENOSPC_DEBUG = (1UL << 15), - BTRFS_MOUNT_AUTO_DEFRAG = (1UL << 16), - BTRFS_MOUNT_USEBACKUPROOT = (1UL << 17), - BTRFS_MOUNT_SKIP_BALANCE = (1UL << 18), - BTRFS_MOUNT_PANIC_ON_FATAL_ERROR = (1UL << 19), - BTRFS_MOUNT_RESCAN_UUID_TREE = (1UL << 20), - BTRFS_MOUNT_FRAGMENT_DATA = (1UL << 21), - BTRFS_MOUNT_FRAGMENT_METADATA = (1UL << 22), - BTRFS_MOUNT_FREE_SPACE_TREE = (1UL << 23), - BTRFS_MOUNT_NOLOGREPLAY = (1UL << 24), - BTRFS_MOUNT_REF_VERIFY = (1UL << 25), - BTRFS_MOUNT_DISCARD_ASYNC = (1UL << 26), - BTRFS_MOUNT_IGNOREBADROOTS = (1UL << 27), - BTRFS_MOUNT_IGNOREDATACSUMS = (1UL << 28), - BTRFS_MOUNT_NODISCARD = (1UL << 29), - BTRFS_MOUNT_NOSPACECACHE = (1UL << 30), - BTRFS_MOUNT_IGNOREMETACSUMS = (1UL << 31), + BTRFS_MOUNT_NODATASUM = (1ULL << 0), + BTRFS_MOUNT_NODATACOW = (1ULL << 1), + BTRFS_MOUNT_NOBARRIER = (1ULL << 2), + BTRFS_MOUNT_SSD = (1ULL << 3), + BTRFS_MOUNT_DEGRADED = (1ULL << 4), + BTRFS_MOUNT_COMPRESS = (1ULL << 5), + BTRFS_MOUNT_NOTREELOG = (1ULL << 6), + BTRFS_MOUNT_FLUSHONCOMMIT = (1ULL << 7), + BTRFS_MOUNT_SSD_SPREAD = (1ULL << 8), + BTRFS_MOUNT_NOSSD = (1ULL << 9), + BTRFS_MOUNT_DISCARD_SYNC = (1ULL << 10), + BTRFS_MOUNT_FORCE_COMPRESS = (1ULL << 11), + BTRFS_MOUNT_SPACE_CACHE = (1ULL << 12), + BTRFS_MOUNT_CLEAR_CACHE = (1ULL << 13), + BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED = (1ULL << 14), + BTRFS_MOUNT_ENOSPC_DEBUG = (1ULL << 15), + BTRFS_MOUNT_AUTO_DEFRAG = (1ULL << 16), + BTRFS_MOUNT_USEBACKUPROOT = (1ULL << 17), + BTRFS_MOUNT_SKIP_BALANCE = (1ULL << 18), + BTRFS_MOUNT_PANIC_ON_FATAL_ERROR = (1ULL << 19), + BTRFS_MOUNT_RESCAN_UUID_TREE = (1ULL << 20), + BTRFS_MOUNT_FRAGMENT_DATA = (1ULL << 21), + BTRFS_MOUNT_FRAGMENT_METADATA = (1ULL << 22), + BTRFS_MOUNT_FREE_SPACE_TREE = (1ULL << 23), + BTRFS_MOUNT_NOLOGREPLAY = (1ULL << 24), + BTRFS_MOUNT_REF_VERIFY = (1ULL << 25), + BTRFS_MOUNT_DISCARD_ASYNC = (1ULL << 26), + BTRFS_MOUNT_IGNOREBADROOTS = (1ULL << 27), + BTRFS_MOUNT_IGNOREDATACSUMS = (1ULL << 28), + BTRFS_MOUNT_NODISCARD = (1ULL << 29), + BTRFS_MOUNT_NOSPACECACHE = (1ULL << 30), + BTRFS_MOUNT_IGNOREMETACSUMS = (1ULL << 31), BTRFS_MOUNT_IGNORESUPERFLAGS = (1ULL << 32), }; @@ -481,7 +481,7 @@ struct btrfs_fs_info { * required instead of the faster short fsync log commits */ u64 last_trans_log_full_commit; - unsigned long mount_opt; + unsigned long long mount_opt; unsigned long compress_type:4; unsigned int compress_level; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 0eda8c21d861..08d33cb372fb 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -82,7 +82,7 @@ struct btrfs_fs_context { u32 commit_interval; u32 metadata_ratio; u32 thread_pool_size; - unsigned long mount_opt; + unsigned long long mount_opt; unsigned long compress_type:4; unsigned int compress_level; refcount_t refs; @@ -642,7 +642,7 @@ static void btrfs_clear_oneshot_options(struct btrfs_fs_info *fs_info) } static bool check_ro_option(const struct btrfs_fs_info *fs_info, - unsigned long mount_opt, unsigned long opt, + unsigned long long mount_opt, unsigned long long opt, const char *opt_name) { if (mount_opt & opt) { @@ -653,7 +653,8 @@ static bool check_ro_option(const struct btrfs_fs_info *fs_info, return false; } -bool btrfs_check_options(const struct btrfs_fs_info *info, unsigned long *mount_opt, +bool btrfs_check_options(const struct btrfs_fs_info *info, + unsigned long long *mount_opt, unsigned long flags) { bool ret = true; @@ -1231,7 +1232,7 @@ static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info, } static inline void btrfs_remount_begin(struct btrfs_fs_info *fs_info, - unsigned long old_opts, int flags) + unsigned long long old_opts, int flags) { if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) && (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) || @@ -1245,7 +1246,7 @@ static inline void btrfs_remount_begin(struct btrfs_fs_info *fs_info, } static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info, - unsigned long old_opts) + unsigned long long old_opts) { const bool cache_opt = btrfs_test_opt(fs_info, SPACE_CACHE); diff --git a/fs/btrfs/super.h b/fs/btrfs/super.h index d2b8ebb46bc6..d80a86acfbbe 100644 --- a/fs/btrfs/super.h +++ b/fs/btrfs/super.h @@ -10,7 +10,8 @@ struct super_block; struct btrfs_fs_info; -bool btrfs_check_options(const struct btrfs_fs_info *info, unsigned long *mount_opt, +bool btrfs_check_options(const struct btrfs_fs_info *info, + unsigned long long *mount_opt, unsigned long flags); int btrfs_sync_fs(struct super_block *sb, int wait); char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info, diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index df7733044f7e..66f63e82af79 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -767,7 +767,8 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info) return 0; } -int btrfs_check_mountopts_zoned(const struct btrfs_fs_info *info, unsigned long *mount_opt) +int btrfs_check_mountopts_zoned(const struct btrfs_fs_info *info, + unsigned long long *mount_opt) { if (!btrfs_is_zoned(info)) return 0; diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h index d66d00c08001..30b2e48a1cec 100644 --- a/fs/btrfs/zoned.h +++ b/fs/btrfs/zoned.h @@ -58,7 +58,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache); void btrfs_destroy_dev_zone_info(struct btrfs_device *device); struct btrfs_zoned_device_info *btrfs_clone_dev_zone_info(struct btrfs_device *orig_dev); int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info); -int btrfs_check_mountopts_zoned(const struct btrfs_fs_info *info, unsigned long *mount_opt); +int btrfs_check_mountopts_zoned(const struct btrfs_fs_info *info, + unsigned long long *mount_opt); int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw, u64 *bytenr_ret); int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw, @@ -130,7 +131,7 @@ static inline int btrfs_check_zoned_mode(const struct btrfs_fs_info *fs_info) } static inline int btrfs_check_mountopts_zoned(const struct btrfs_fs_info *info, - unsigned long *mount_opt) + unsigned long long *mount_opt) { return 0; } diff --git a/include/dt-bindings/iio/adc/mediatek,mt6357-auxadc.h b/include/dt-bindings/iio/adc/mediatek,mt6357-auxadc.h new file mode 100644 index 000000000000..03ebb1d23953 --- /dev/null +++ b/include/dt-bindings/iio/adc/mediatek,mt6357-auxadc.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ + +#ifndef _DT_BINDINGS_MEDIATEK_MT6357_AUXADC_H +#define _DT_BINDINGS_MEDIATEK_MT6357_AUXADC_H + +/* ADC Channel Index */ +#define MT6357_AUXADC_BATADC 0 +#define MT6357_AUXADC_ISENSE 1 +#define MT6357_AUXADC_VCDT 2 +#define MT6357_AUXADC_BAT_TEMP 3 +#define MT6357_AUXADC_CHIP_TEMP 4 +#define MT6357_AUXADC_ACCDET 5 +#define MT6357_AUXADC_VDCXO 6 +#define MT6357_AUXADC_TSX_TEMP 7 +#define MT6357_AUXADC_HPOFS_CAL 8 +#define MT6357_AUXADC_DCXO_TEMP 9 +#define MT6357_AUXADC_VCORE_TEMP 10 +#define MT6357_AUXADC_VPROC_TEMP 11 +#define MT6357_AUXADC_VBAT 12 + +#endif diff --git a/include/dt-bindings/iio/adc/mediatek,mt6358-auxadc.h b/include/dt-bindings/iio/adc/mediatek,mt6358-auxadc.h new file mode 100644 index 000000000000..efa08398fafd --- /dev/null +++ b/include/dt-bindings/iio/adc/mediatek,mt6358-auxadc.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ + +#ifndef _DT_BINDINGS_MEDIATEK_MT6358_AUXADC_H +#define _DT_BINDINGS_MEDIATEK_MT6358_AUXADC_H + +/* ADC Channel Index */ +#define MT6358_AUXADC_BATADC 0 +#define MT6358_AUXADC_VCDT 1 +#define MT6358_AUXADC_BAT_TEMP 2 +#define MT6358_AUXADC_CHIP_TEMP 3 +#define MT6358_AUXADC_ACCDET 4 +#define MT6358_AUXADC_VDCXO 5 +#define MT6358_AUXADC_TSX_TEMP 6 +#define MT6358_AUXADC_HPOFS_CAL 7 +#define MT6358_AUXADC_DCXO_TEMP 8 +#define MT6358_AUXADC_VBIF 9 +#define MT6358_AUXADC_VCORE_TEMP 10 +#define MT6358_AUXADC_VPROC_TEMP 11 +#define MT6358_AUXADC_VGPU_TEMP 12 +#define MT6358_AUXADC_VBAT 13 + +#endif diff --git a/include/dt-bindings/iio/adc/mediatek,mt6359-auxadc.h b/include/dt-bindings/iio/adc/mediatek,mt6359-auxadc.h new file mode 100644 index 000000000000..59826393ee7e --- /dev/null +++ b/include/dt-bindings/iio/adc/mediatek,mt6359-auxadc.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ + +#ifndef _DT_BINDINGS_MEDIATEK_MT6359_AUXADC_H +#define _DT_BINDINGS_MEDIATEK_MT6359_AUXADC_H + +/* ADC Channel Index */ +#define MT6359_AUXADC_BATADC 0 +#define MT6359_AUXADC_BAT_TEMP 1 +#define MT6359_AUXADC_CHIP_TEMP 2 +#define MT6359_AUXADC_ACCDET 3 +#define MT6359_AUXADC_VDCXO 4 +#define MT6359_AUXADC_TSX_TEMP 5 +#define MT6359_AUXADC_HPOFS_CAL 6 +#define MT6359_AUXADC_DCXO_TEMP 7 +#define MT6359_AUXADC_VBIF 8 +#define MT6359_AUXADC_VCORE_TEMP 9 +#define MT6359_AUXADC_VPROC_TEMP 10 +#define MT6359_AUXADC_VGPU_TEMP 11 +#define MT6359_AUXADC_VBAT 12 +#define MT6359_AUXADC_IBAT 13 + +#endif diff --git a/include/dt-bindings/interconnect/mediatek,mt8183.h b/include/dt-bindings/interconnect/mediatek,mt8183.h new file mode 100644 index 000000000000..1088c350258d --- /dev/null +++ b/include/dt-bindings/interconnect/mediatek,mt8183.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_MEDIATEK_MT8183_H +#define __DT_BINDINGS_INTERCONNECT_MEDIATEK_MT8183_H + +#define SLAVE_DDR_EMI 0 +#define MASTER_MCUSYS 1 +#define MASTER_MFG 2 +#define MASTER_MMSYS 3 +#define MASTER_MM_VPU 4 +#define MASTER_MM_DISP 5 +#define MASTER_MM_VDEC 6 +#define MASTER_MM_VENC 7 +#define MASTER_MM_CAM 8 +#define MASTER_MM_IMG 9 +#define MASTER_MM_MDP 10 + +#endif diff --git a/include/dt-bindings/interconnect/mediatek,mt8195.h b/include/dt-bindings/interconnect/mediatek,mt8195.h new file mode 100644 index 000000000000..33e0e6cde732 --- /dev/null +++ b/include/dt-bindings/interconnect/mediatek,mt8195.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_MEDIATEK_MT8195_H +#define __DT_BINDINGS_INTERCONNECT_MEDIATEK_MT8195_H + +#define SLAVE_DDR_EMI 0 +#define MASTER_MCUSYS 1 +#define MASTER_GPUSYS 2 +#define MASTER_MMSYS 3 +#define MASTER_MM_VPU 4 +#define MASTER_MM_DISP 5 +#define MASTER_MM_VDEC 6 +#define MASTER_MM_VENC 7 +#define MASTER_MM_CAM 8 +#define MASTER_MM_IMG 9 +#define MASTER_MM_MDP 10 +#define MASTER_VPUSYS 11 +#define MASTER_VPU_0 12 +#define MASTER_VPU_1 13 +#define MASTER_MDLASYS 14 +#define MASTER_MDLA_0 15 +#define MASTER_UFS 16 +#define MASTER_PCIE_0 17 +#define MASTER_PCIE_1 18 +#define MASTER_USB 19 +#define MASTER_DBGIF 20 +#define SLAVE_HRT_DDR_EMI 21 +#define MASTER_HRT_MMSYS 22 +#define MASTER_HRT_MM_DISP 23 +#define MASTER_HRT_MM_VDEC 24 +#define MASTER_HRT_MM_VENC 25 +#define MASTER_HRT_MM_CAM 26 +#define MASTER_HRT_MM_IMG 27 +#define MASTER_HRT_MM_MDP 28 +#define MASTER_HRT_DBGIF 29 +#define MASTER_WIFI 30 +#define MASTER_BT 31 +#define MASTER_NETSYS 32 +#endif diff --git a/include/dt-bindings/interconnect/qcom,msm8953.h b/include/dt-bindings/interconnect/qcom,msm8953.h new file mode 100644 index 000000000000..12564c434af7 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,msm8953.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Qualcomm MSM8953 interconnect IDs + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_MSM8953_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_MSM8953_H + +/* BIMC fabric */ +#define MAS_APPS_PROC 0 +#define MAS_OXILI 1 +#define MAS_SNOC_BIMC_0 2 +#define MAS_SNOC_BIMC_2 3 +#define MAS_SNOC_BIMC_1 4 +#define MAS_TCU_0 5 +#define SLV_EBI 6 +#define SLV_BIMC_SNOC 7 + +/* PCNOC fabric */ +#define MAS_SPDM 0 +#define MAS_BLSP_1 1 +#define MAS_BLSP_2 2 +#define MAS_USB3 3 +#define MAS_CRYPTO 4 +#define MAS_SDCC_1 5 +#define MAS_SDCC_2 6 +#define MAS_SNOC_PCNOC 7 +#define PCNOC_M_0 8 +#define PCNOC_M_1 9 +#define PCNOC_INT_1 10 +#define PCNOC_INT_2 11 +#define PCNOC_S_0 12 +#define PCNOC_S_1 13 +#define PCNOC_S_2 14 +#define PCNOC_S_3 15 +#define PCNOC_S_4 16 +#define PCNOC_S_6 17 +#define PCNOC_S_7 18 +#define PCNOC_S_8 19 +#define PCNOC_S_9 20 +#define SLV_SPDM 21 +#define SLV_PDM 22 +#define SLV_TCSR 23 +#define SLV_SNOC_CFG 24 +#define SLV_TLMM 25 +#define SLV_MESSAGE_RAM 26 +#define SLV_BLSP_1 27 +#define SLV_BLSP_2 28 +#define SLV_PRNG 29 +#define SLV_CAMERA_SS_CFG 30 +#define SLV_DISP_SS_CFG 31 +#define SLV_VENUS_CFG 32 +#define SLV_GPU_CFG 33 +#define SLV_SDCC_1 34 +#define SLV_SDCC_2 35 +#define SLV_CRYPTO_0_CFG 36 +#define SLV_PMIC_ARB 37 +#define SLV_USB3 38 +#define SLV_IPA_CFG 39 +#define SLV_TCU 40 +#define SLV_PCNOC_SNOC 41 + +/* SNOC fabric */ +#define MAS_QDSS_BAM 0 +#define MAS_BIMC_SNOC 1 +#define MAS_PCNOC_SNOC 2 +#define MAS_IPA 3 +#define MAS_QDSS_ETR 4 +#define QDSS_INT 5 +#define SNOC_INT_0 6 +#define SNOC_INT_1 7 +#define SNOC_INT_2 8 +#define SLV_KPSS_AHB 9 +#define SLV_WCSS 10 +#define SLV_SNOC_BIMC_1 11 +#define SLV_IMEM 12 +#define SLV_SNOC_PCNOC 13 +#define SLV_QDSS_STM 14 +#define SLV_CATS_1 15 +#define SLV_LPASS 16 + +/* SNOC-MM fabric */ +#define MAS_JPEG 0 +#define MAS_MDP 1 +#define MAS_VENUS 2 +#define MAS_VFE0 3 +#define MAS_VFE1 4 +#define MAS_CPP 5 +#define SLV_SNOC_BIMC_0 6 +#define SLV_SNOC_BIMC_2 7 +#define SLV_CATS_0 8 + +#endif /* __DT_BINDINGS_INTERCONNECT_QCOM_MSM8953_H */ diff --git a/include/linux/auxiliary_bus.h b/include/linux/auxiliary_bus.h index 3ba4487c9cd9..1539bbd263d2 100644 --- a/include/linux/auxiliary_bus.h +++ b/include/linux/auxiliary_bus.h @@ -58,9 +58,10 @@ * in * @name: Match name found by the auxiliary device driver, * @id: unique identitier if multiple devices of the same name are exported, - * @irqs: irqs xarray contains irq indices which are used by the device, - * @lock: Synchronize irq sysfs creation, - * @irq_dir_exists: whether "irqs" directory exists, + * @sysfs: embedded struct which hold all sysfs related fields, + * @sysfs.irqs: irqs xarray contains irq indices which are used by the device, + * @sysfs.lock: Synchronize irq sysfs creation, + * @sysfs.irq_dir_exists: whether "irqs" directory exists, * * An auxiliary_device represents a part of its parent device's functionality. * It is given a name that, combined with the registering drivers diff --git a/include/linux/dev_printk.h b/include/linux/dev_printk.h index ae80a303c216..ca32b5bb28eb 100644 --- a/include/linux/dev_printk.h +++ b/include/linux/dev_printk.h @@ -277,4 +277,12 @@ do { \ __printf(3, 4) int dev_err_probe(const struct device *dev, int err, const char *fmt, ...); +/* Simple helper for dev_err_probe() when ERR_PTR() is to be returned. */ +#define dev_err_ptr_probe(dev, ___err, fmt, ...) \ + ERR_PTR(dev_err_probe(dev, ___err, fmt, ##__VA_ARGS__)) + +/* Simple helper for dev_err_probe() when ERR_CAST() is to be returned. */ +#define dev_err_cast_probe(dev, ___err_ptr, fmt, ...) \ + ERR_PTR(dev_err_probe(dev, PTR_ERR(___err_ptr), fmt, ##__VA_ARGS__)) + #endif /* _DEVICE_PRINTK_H_ */ diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 752dbde4cec1..9fc03068cabc 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -160,6 +160,16 @@ struct dma_interleaved_template { struct data_chunk sgl[]; }; +/** + * struct dma_vec - DMA vector + * @addr: Bus address of the start of the vector + * @len: Length in bytes of the DMA vector + */ +struct dma_vec { + dma_addr_t addr; + size_t len; +}; + /** * enum dma_ctrl_flags - DMA flags to augment operation preparation, * control completion, and communicate status. @@ -910,6 +920,10 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( struct dma_chan *chan, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_peripheral_dma_vec)( + struct dma_chan *chan, const struct dma_vec *vecs, + size_t nents, enum dma_transfer_direction direction, + unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, @@ -973,6 +987,25 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( dir, flags, NULL); } +/** + * dmaengine_prep_peripheral_dma_vec() - Prepare a DMA scatter-gather descriptor + * @chan: The channel to be used for this descriptor + * @vecs: The array of DMA vectors that should be transferred + * @nents: The number of DMA vectors in the array + * @dir: Specifies the direction of the data transfer + * @flags: DMA engine flags + */ +static inline struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec( + struct dma_chan *chan, const struct dma_vec *vecs, size_t nents, + enum dma_transfer_direction dir, unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_peripheral_dma_vec) + return NULL; + + return chan->device->device_prep_peripheral_dma_vec(chan, vecs, nents, + dir, flags); +} + static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction dir, unsigned long flags) diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h deleted file mode 100644 index 34c2175e6a1e..000000000000 --- a/include/linux/eeprom_93xx46.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Module: eeprom_93xx46 - * platform description for 93xx46 EEPROMs. - */ -#include - -struct eeprom_93xx46_platform_data { - unsigned char flags; -#define EE_ADDR8 0x01 /* 8 bit addr. cfg */ -#define EE_ADDR16 0x02 /* 16 bit addr. cfg */ -#define EE_READONLY 0x08 /* forbid writing */ -#define EE_SIZE1K 0x10 /* 1 kb of data, that is a 93xx46 */ -#define EE_SIZE2K 0x20 /* 2 kb of data, that is a 93xx56 */ -#define EE_SIZE4K 0x40 /* 4 kb of data, that is a 93xx66 */ - - unsigned int quirks; -/* Single word read transfers only; no sequential read. */ -#define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) -/* Instructions such as EWEN are (addrlen + 2) in length. */ -#define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) -/* Add extra cycle after address during a read */ -#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2) - - /* - * optional hooks to control additional logic - * before and after spi transfer. - */ - void (*prepare)(void *); - void (*finish)(void *); - struct gpio_desc *select; -}; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 424acb98c7c2..e9cc14b1f9a1 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -513,10 +513,10 @@ i2c_register_board_info(int busnum, struct i2c_board_info const *info, /** * struct i2c_algorithm - represent I2C transfer method - * @master_xfer: Issue a set of i2c transactions to the given I2C adapter + * @xfer: Issue a set of i2c transactions to the given I2C adapter * defined by the msgs array, with num messages available to transfer via * the adapter specified by adap. - * @master_xfer_atomic: same as @master_xfer. Yet, only using atomic context + * @xfer_atomic: same as @xfer. Yet, only using atomic context * so e.g. PMICs can be accessed very late before shutdown. Optional. * @smbus_xfer: Issue smbus transactions to the given I2C adapter. If this * is not present, then the bus layer will try and convert the SMBus calls @@ -525,33 +525,47 @@ i2c_register_board_info(int busnum, struct i2c_board_info const *info, * so e.g. PMICs can be accessed very late before shutdown. Optional. * @functionality: Return the flags that this algorithm/adapter pair supports * from the ``I2C_FUNC_*`` flags. - * @reg_slave: Register given client to I2C slave mode of this adapter - * @unreg_slave: Unregister given client from I2C slave mode of this adapter + * @reg_target: Register given client to local target mode of this adapter + * @unreg_target: Unregister given client from local target mode of this adapter + * + * @master_xfer: deprecated, use @xfer + * @master_xfer_atomic: deprecated, use @xfer_atomic + * @reg_slave: deprecated, use @reg_target + * @unreg_slave: deprecated, use @unreg_target + * * * The following structs are for those who like to implement new bus drivers: * i2c_algorithm is the interface to a class of hardware solutions which can * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584 * to name two of the most common. * - * The return codes from the ``master_xfer{_atomic}`` fields should indicate the + * The return codes from the ``xfer{_atomic}`` fields should indicate the * type of error code that occurred during the transfer, as documented in the * Kernel Documentation file Documentation/i2c/fault-codes.rst. Otherwise, the * number of messages executed should be returned. */ struct i2c_algorithm { /* - * If an adapter algorithm can't do I2C-level access, set master_xfer + * If an adapter algorithm can't do I2C-level access, set xfer * to NULL. If an adapter algorithm can do SMBus access, set * smbus_xfer. If set to NULL, the SMBus protocol is simulated * using common I2C messages. * - * master_xfer should return the number of messages successfully + * xfer should return the number of messages successfully * processed, or a negative value on error */ - int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num); - int (*master_xfer_atomic)(struct i2c_adapter *adap, + union { + int (*xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); + int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); + }; + union { + int (*xfer_atomic)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); + int (*master_xfer_atomic)(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num); + }; int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); @@ -563,8 +577,14 @@ struct i2c_algorithm { u32 (*functionality)(struct i2c_adapter *adap); #if IS_ENABLED(CONFIG_I2C_SLAVE) - int (*reg_slave)(struct i2c_client *client); - int (*unreg_slave)(struct i2c_client *client); + union { + int (*reg_target)(struct i2c_client *client); + int (*reg_slave)(struct i2c_client *client); + }; + union { + int (*unreg_target)(struct i2c_client *client); + int (*unreg_slave)(struct i2c_client *client); + }; #endif }; diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h index 383614ebd760..f8c1d2505940 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -37,6 +37,10 @@ struct iio_dev; * @append_status: Will be called to enable status append at the end of the sample, may be NULL. * @set_mode: Will be called to select the current mode, may be NULL. * @disable_all: Will be called to disable all channels, may be NULL. + * @disable_one: Will be called to disable a single channel after + * ad_sigma_delta_single_conversion(), may be NULL. + * Usage of this callback expects iio_chan_spec.address to contain + * the value required for the driver to identify the channel. * @postprocess_sample: Is called for each sampled data word, can be used to * modify or drop the sample data, it, may be NULL. * @has_registers: true if the device has writable and readable registers, false @@ -55,6 +59,7 @@ struct ad_sigma_delta_info { int (*append_status)(struct ad_sigma_delta *, bool append); int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode); int (*disable_all)(struct ad_sigma_delta *); + int (*disable_one)(struct ad_sigma_delta *, unsigned int chan); int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample); bool has_registers; unsigned int addr_shift; @@ -140,6 +145,15 @@ static inline int ad_sigma_delta_disable_all(struct ad_sigma_delta *sd) return 0; } +static inline int ad_sigma_delta_disable_one(struct ad_sigma_delta *sd, + unsigned int chan) +{ + if (sd->info->disable_one) + return sd->info->disable_one(sd, chan); + + return 0; +} + static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd, unsigned int mode) { diff --git a/include/linux/iio/buffer-dma.h b/include/linux/iio/buffer-dma.h index 6e27e47077d5..5eb66a399002 100644 --- a/include/linux/iio/buffer-dma.h +++ b/include/linux/iio/buffer-dma.h @@ -7,6 +7,7 @@ #ifndef __INDUSTRIALIO_DMA_BUFFER_H__ #define __INDUSTRIALIO_DMA_BUFFER_H__ +#include #include #include #include @@ -16,6 +17,9 @@ struct iio_dma_buffer_queue; struct iio_dma_buffer_ops; struct device; +struct dma_buf_attachment; +struct dma_fence; +struct sg_table; /** * enum iio_block_state - State of a struct iio_dma_buffer_block @@ -41,6 +45,10 @@ enum iio_block_state { * @queue: Parent DMA buffer queue * @kref: kref used to manage the lifetime of block * @state: Current state of the block + * @cyclic: True if this is a cyclic buffer + * @fileio: True if this buffer is used for fileio mode + * @sg_table: DMA table for the transfer when transferring a DMABUF + * @fence: DMA fence to be signaled when a DMABUF transfer is complete */ struct iio_dma_buffer_block { /* May only be accessed by the owner of the block */ @@ -63,6 +71,12 @@ struct iio_dma_buffer_block { * queue->list_lock if the block is not owned by the core. */ enum iio_block_state state; + + bool cyclic; + bool fileio; + + struct sg_table *sg_table; + struct dma_fence *fence; }; /** @@ -72,6 +86,7 @@ struct iio_dma_buffer_block { * @pos: Read offset in the active block * @block_size: Size of each block * @next_dequeue: index of next block that will be dequeued + * @enabled: Whether the buffer is operating in fileio mode */ struct iio_dma_buffer_queue_fileio { struct iio_dma_buffer_block *blocks[2]; @@ -80,6 +95,7 @@ struct iio_dma_buffer_queue_fileio { size_t block_size; unsigned int next_dequeue; + bool enabled; }; /** @@ -95,6 +111,7 @@ struct iio_dma_buffer_queue_fileio { * the DMA controller * @incoming: List of buffers on the incoming queue * @active: Whether the buffer is currently active + * @num_dmabufs: Total number of DMABUFs attached to this queue * @fileio: FileIO state */ struct iio_dma_buffer_queue { @@ -107,6 +124,7 @@ struct iio_dma_buffer_queue { struct list_head incoming; bool active; + atomic_t num_dmabufs; struct iio_dma_buffer_queue_fileio fileio; }; @@ -144,4 +162,17 @@ int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue, void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue); void iio_dma_buffer_release(struct iio_dma_buffer_queue *queue); +struct iio_dma_buffer_block * +iio_dma_buffer_attach_dmabuf(struct iio_buffer *buffer, + struct dma_buf_attachment *attach); +void iio_dma_buffer_detach_dmabuf(struct iio_buffer *buffer, + struct iio_dma_buffer_block *block); +int iio_dma_buffer_enqueue_dmabuf(struct iio_buffer *buffer, + struct iio_dma_buffer_block *block, + struct dma_fence *fence, + struct sg_table *sgt, + size_t size, bool cyclic); +void iio_dma_buffer_lock_queue(struct iio_buffer *buffer); +void iio_dma_buffer_unlock_queue(struct iio_buffer *buffer); + #endif diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h index 89c3fd7c29ca..e72552e026f3 100644 --- a/include/linux/iio/buffer_impl.h +++ b/include/linux/iio/buffer_impl.h @@ -9,8 +9,12 @@ #include #include +struct dma_buf_attachment; +struct dma_fence; struct iio_dev; +struct iio_dma_buffer_block; struct iio_buffer; +struct sg_table; /** * INDIO_BUFFER_FLAG_FIXED_WATERMARK - Watermark level of the buffer can not be @@ -39,6 +43,16 @@ struct iio_buffer; * device stops sampling. Calles are balanced with @enable. * @release: called when the last reference to the buffer is dropped, * should free all resources allocated by the buffer. + * @attach_dmabuf: called from userspace via ioctl to attach one external + * DMABUF. + * @detach_dmabuf: called from userspace via ioctl to detach one previously + * attached DMABUF. + * @enqueue_dmabuf: called from userspace via ioctl to queue this DMABUF + * object to this buffer. Requires a valid DMABUF fd, that + * was previouly attached to this buffer. + * @lock_queue: called when the core needs to lock the buffer queue; + * it is used when enqueueing DMABUF objects. + * @unlock_queue: used to unlock a previously locked buffer queue * @modes: Supported operating modes by this buffer type * @flags: A bitmask combination of INDIO_BUFFER_FLAG_* * @@ -68,6 +82,17 @@ struct iio_buffer_access_funcs { void (*release)(struct iio_buffer *buffer); + struct iio_dma_buffer_block * (*attach_dmabuf)(struct iio_buffer *buffer, + struct dma_buf_attachment *attach); + void (*detach_dmabuf)(struct iio_buffer *buffer, + struct iio_dma_buffer_block *block); + int (*enqueue_dmabuf)(struct iio_buffer *buffer, + struct iio_dma_buffer_block *block, + struct dma_fence *fence, struct sg_table *sgt, + size_t size, bool cyclic); + void (*lock_queue)(struct iio_buffer *buffer); + void (*unlock_queue)(struct iio_buffer *buffer); + unsigned int modes; unsigned int flags; }; @@ -136,6 +161,12 @@ struct iio_buffer { /* @ref: Reference count of the buffer. */ struct kref ref; + + /* @dmabufs: List of DMABUF attachments */ + struct list_head dmabufs; /* P: dmabufs_mutex */ + + /* @dmabufs_mutex: Protects dmabufs */ + struct mutex dmabufs_mutex; }; /** @@ -159,6 +190,8 @@ void iio_buffer_init(struct iio_buffer *buffer); struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer); void iio_buffer_put(struct iio_buffer *buffer); +void iio_buffer_signal_dmabuf_done(struct dma_fence *fence, int ret); + #else /* CONFIG_IIO_BUFFER */ static inline void iio_buffer_get(struct iio_buffer *buffer) {} diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index e9910b41d48e..333d1d8ccb37 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -441,4 +441,14 @@ ssize_t iio_read_channel_ext_info(struct iio_channel *chan, ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr, const char *buf, size_t len); +/** + * iio_read_channel_label() - read label for a given channel + * @chan: The channel being queried. + * @buf: Where to store the attribute value. Assumed to hold + * at least PAGE_SIZE bytes. + * + * Returns the number of bytes written to buf, or an error code. + */ +ssize_t iio_read_channel_label(struct iio_channel *chan, char *buf); + #endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 55e2b22086a1..894309294182 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -173,6 +173,27 @@ struct iio_event_spec { unsigned long mask_shared_by_all; }; +/** + * struct iio_scan_type - specification for channel data format in buffer + * @sign: 's' or 'u' to specify signed or unsigned + * @realbits: Number of valid bits of data + * @storagebits: Realbits + padding + * @shift: Shift right by this before masking out realbits. + * @repeat: Number of times real/storage bits repeats. When the + * repeat element is more than 1, then the type element in + * sysfs will show a repeat value. Otherwise, the number + * of repetitions is omitted. + * @endianness: little or big endian + */ +struct iio_scan_type { + char sign; + u8 realbits; + u8 storagebits; + u8 shift; + u8 repeat; + enum iio_endian endianness; +}; + /** * struct iio_chan_spec - specification of a single channel * @type: What type of measurement is the channel making. @@ -183,18 +204,13 @@ struct iio_event_spec { * @address: Driver specific identifier. * @scan_index: Monotonic index to give ordering in scans when read * from a buffer. - * @scan_type: struct describing the scan type - * @scan_type.sign: 's' or 'u' to specify signed or unsigned - * @scan_type.realbits: Number of valid bits of data - * @scan_type.storagebits: Realbits + padding - * @scan_type.shift: Shift right by this before masking out - * realbits. - * @scan_type.repeat: Number of times real/storage bits repeats. - * When the repeat element is more than 1, then - * the type element in sysfs will show a repeat - * value. Otherwise, the number of repetitions - * is omitted. - * @scan_type.endianness: little or big endian + * @scan_type: struct describing the scan type - mutually exclusive + * with ext_scan_type. + * @ext_scan_type: Used in rare cases where there is more than one scan + * format for a channel. When this is used, the flag + * has_ext_scan_type must be set and the driver must + * implement get_current_scan_type in struct iio_info. + * @num_ext_scan_type: Number of elements in ext_scan_type. * @info_mask_separate: What information is to be exported that is specific to * this channel. * @info_mask_separate_available: What availability information is to be @@ -238,6 +254,7 @@ struct iio_event_spec { * attributes but not for event codes. * @output: Channel is output. * @differential: Channel is differential. + * @has_ext_scan_type: True if ext_scan_type is used instead of scan_type. */ struct iio_chan_spec { enum iio_chan_type type; @@ -245,14 +262,13 @@ struct iio_chan_spec { int channel2; unsigned long address; int scan_index; - struct { - char sign; - u8 realbits; - u8 storagebits; - u8 shift; - u8 repeat; - enum iio_endian endianness; - } scan_type; + union { + struct iio_scan_type scan_type; + struct { + const struct iio_scan_type *ext_scan_type; + unsigned int num_ext_scan_type; + }; + }; long info_mask_separate; long info_mask_separate_available; long info_mask_shared_by_type; @@ -270,6 +286,7 @@ struct iio_chan_spec { unsigned indexed:1; unsigned output:1; unsigned differential:1; + unsigned has_ext_scan_type:1; }; @@ -432,6 +449,9 @@ struct iio_trigger; /* forward declaration */ * for better event identification. * @validate_trigger: function to validate the trigger when the * current trigger gets changed. + * @get_current_scan_type: must be implemented by drivers that use ext_scan_type + * in the channel spec to return the index of the currently + * active ext_scan type for a channel. * @update_scan_mode: function to configure device and scan buffer when * channels have changed * @debugfs_reg_access: function to read or write register value of device @@ -516,6 +536,8 @@ struct iio_info { int (*validate_trigger)(struct iio_dev *indio_dev, struct iio_trigger *trig); + int (*get_current_scan_type)(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan); int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); int (*debugfs_reg_access)(struct iio_dev *indio_dev, @@ -801,6 +823,38 @@ static inline bool iio_read_acpi_mount_matrix(struct device *dev, } #endif +/** + * iio_get_current_scan_type - Get the current scan type for a channel + * @indio_dev: the IIO device to get the scan type for + * @chan: the channel to get the scan type for + * + * Most devices only have one scan type per channel and can just access it + * directly without calling this function. Core IIO code and drivers that + * implement ext_scan_type in the channel spec should use this function to + * get the current scan type for a channel. + * + * Returns: the current scan type for the channel or error. + */ +static inline const struct iio_scan_type +*iio_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + int ret; + + if (chan->has_ext_scan_type) { + ret = indio_dev->info->get_current_scan_type(indio_dev, chan); + if (ret < 0) + return ERR_PTR(ret); + + if (ret >= chan->num_ext_scan_type) + return ERR_PTR(-EINVAL); + + return &chan->ext_scan_type[ret]; + } + + return &chan->scan_type; +} + ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals); int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 8898966bc0f0..e6a75356567a 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -9,6 +9,7 @@ #ifndef __IIO_ADIS_H__ #define __IIO_ADIS_H__ +#include #include #include #include @@ -21,6 +22,7 @@ #define ADIS_REG_PAGE_ID 0x00 struct adis; +struct iio_dev_attr; /** * struct adis_timeouts - ADIS chip variant timeouts @@ -84,6 +86,7 @@ struct adis_data { bool unmasked_drdy; bool has_paging; + bool has_fifo; unsigned int burst_reg_cmd; unsigned int burst_len; @@ -148,13 +151,8 @@ int __adis_reset(struct adis *adis); */ static inline int adis_reset(struct adis *adis) { - int ret; - - mutex_lock(&adis->state_lock); - ret = __adis_reset(adis); - mutex_unlock(&adis->state_lock); - - return ret; + guard(mutex)(&adis->state_lock); + return __adis_reset(adis); } int __adis_write_reg(struct adis *adis, unsigned int reg, @@ -246,13 +244,8 @@ static inline int __adis_read_reg_32(struct adis *adis, unsigned int reg, static inline int adis_write_reg(struct adis *adis, unsigned int reg, unsigned int val, unsigned int size) { - int ret; - - mutex_lock(&adis->state_lock); - ret = __adis_write_reg(adis, reg, val, size); - mutex_unlock(&adis->state_lock); - - return ret; + guard(mutex)(&adis->state_lock); + return __adis_write_reg(adis, reg, val, size); } /** @@ -265,13 +258,8 @@ static inline int adis_write_reg(struct adis *adis, unsigned int reg, static int adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, unsigned int size) { - int ret; - - mutex_lock(&adis->state_lock); - ret = __adis_read_reg(adis, reg, val, size); - mutex_unlock(&adis->state_lock); - - return ret; + guard(mutex)(&adis->state_lock); + return __adis_read_reg(adis, reg, val, size); } /** @@ -363,12 +351,8 @@ int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, static inline int adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, const u32 val, u8 size) { - int ret; - - mutex_lock(&adis->state_lock); - ret = __adis_update_bits_base(adis, reg, mask, val, size); - mutex_unlock(&adis->state_lock); - return ret; + guard(mutex)(&adis->state_lock); + return __adis_update_bits_base(adis, reg, mask, val, size); } /** @@ -409,35 +393,19 @@ int __adis_enable_irq(struct adis *adis, bool enable); static inline int adis_enable_irq(struct adis *adis, bool enable) { - int ret; - - mutex_lock(&adis->state_lock); - ret = __adis_enable_irq(adis, enable); - mutex_unlock(&adis->state_lock); - - return ret; + guard(mutex)(&adis->state_lock); + return __adis_enable_irq(adis, enable); } static inline int adis_check_status(struct adis *adis) { - int ret; - - mutex_lock(&adis->state_lock); - ret = __adis_check_status(adis); - mutex_unlock(&adis->state_lock); - - return ret; + guard(mutex)(&adis->state_lock); + return __adis_check_status(adis); } -static inline void adis_dev_lock(struct adis *adis) -{ - mutex_lock(&adis->state_lock); -} - -static inline void adis_dev_unlock(struct adis *adis) -{ - mutex_unlock(&adis->state_lock); -} +#define adis_dev_auto_lock(adis) guard(mutex)(&(adis)->state_lock) +#define adis_dev_auto_scoped_lock(adis) \ + scoped_guard(mutex, &(adis)->state_lock) int adis_single_conversion(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, @@ -515,11 +483,19 @@ int adis_single_conversion(struct iio_dev *indio_dev, #define ADIS_ROT_CHAN(mod, addr, si, info_sep, info_all, bits) \ ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, info_all, bits) +#define devm_adis_setup_buffer_and_trigger(adis, indio_dev, trigger_handler) \ + devm_adis_setup_buffer_and_trigger_with_attrs((adis), (indio_dev), \ + (trigger_handler), NULL, \ + NULL) + #ifdef CONFIG_IIO_ADIS_LIB_BUFFER int -devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, - irq_handler_t trigger_handler); +devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis, + struct iio_dev *indio_dev, + irq_handler_t trigger_handler, + const struct iio_buffer_setup_ops *ops, + const struct iio_dev_attr **buffer_attrs); int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); @@ -529,8 +505,11 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, #else /* CONFIG_IIO_BUFFER */ static inline int -devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, - irq_handler_t trigger_handler) +devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis, + struct iio_dev *indio_dev, + irq_handler_t trigger_handler, + const struct iio_buffer_setup_ops *ops, + const struct iio_dev_attr **buffer_attrs) { return 0; } diff --git a/include/linux/input.h b/include/linux/input.h index c22ac465254b..89a0be6ee0e2 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -275,7 +275,8 @@ struct input_handle; * it may not sleep * @events: event sequence handler. This method is being called by * input core with interrupts disabled and dev->event_lock - * spinlock held and so it may not sleep + * spinlock held and so it may not sleep. The method must return + * number of events passed to it. * @filter: similar to @event; separates normal event handlers from * "filters". * @match: called after comparing device's id with handler's id_table @@ -312,8 +313,8 @@ struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); - void (*events)(struct input_handle *handle, - const struct input_value *vals, unsigned int count); + unsigned int (*events)(struct input_handle *handle, + struct input_value *vals, unsigned int count); bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*match)(struct input_handler *handler, struct input_dev *dev); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5c9bdd3ffccc..3a36e64119c8 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -235,6 +236,9 @@ extern void enable_percpu_irq(unsigned int irq, unsigned int type); extern bool irq_percpu_is_enabled(unsigned int irq); extern void irq_wake_thread(unsigned int irq, void *dev_id); +DEFINE_LOCK_GUARD_1(disable_irq, int, + disable_irq(*_T->lock), enable_irq(*_T->lock)) + extern void disable_nmi_nosync(unsigned int irq); extern void disable_percpu_nmi(unsigned int irq); extern void enable_nmi(unsigned int irq); diff --git a/include/linux/ioport.h b/include/linux/ioport.h index db7fe25f3370..6e9fb667a1c5 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -188,6 +188,42 @@ enum { #define DEFINE_RES_DMA(_dma) \ DEFINE_RES_DMA_NAMED((_dma), NULL) +/** + * typedef resource_alignf - Resource alignment callback + * @data: Private data used by the callback + * @res: Resource candidate range (an empty resource space) + * @size: The minimum size of the empty space + * @align: Alignment from the constraints + * + * Callback allows calculating resource placement and alignment beyond min, + * max, and align fields in the struct resource_constraint. + * + * Return: Start address for the resource. + */ +typedef resource_size_t (*resource_alignf)(void *data, + const struct resource *res, + resource_size_t size, + resource_size_t align); + +/** + * struct resource_constraint - constraints to be met while searching empty + * resource space + * @min: The minimum address for the memory range + * @max: The maximum address for the memory range + * @align: Alignment for the start address of the empty space + * @alignf: Additional alignment constraints callback + * @alignf_data: Data provided for @alignf callback + * + * Contains the range and alignment constraints that have to be met during + * find_resource_space(). @alignf can be NULL indicating no alignment beyond + * @align is necessary. + */ +struct resource_constraint { + resource_size_t min, max, align; + resource_alignf alignf; + void *alignf_data; +}; + /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ extern struct resource ioport_resource; extern struct resource iomem_resource; @@ -207,10 +243,7 @@ extern void arch_remove_reservations(struct resource *avail); extern int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, resource_size_t max, resource_size_t align, - resource_size_t (*alignf)(void *, - const struct resource *, - resource_size_t, - resource_size_t), + resource_alignf alignf, void *alignf_data); struct resource *lookup_resource(struct resource *root, resource_size_t start); int adjust_resource(struct resource *res, resource_size_t start, @@ -264,6 +297,9 @@ static inline bool resource_union(const struct resource *r1, const struct resour return true; } +int find_resource_space(struct resource *root, struct resource *new, + resource_size_t size, struct resource_constraint *constraint); + /* Convenience shorthand with allocation */ #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) #define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) diff --git a/include/linux/math.h b/include/linux/math.h index dd4152711de7..f5f18dc3616b 100644 --- a/include/linux/math.h +++ b/include/linux/math.h @@ -112,6 +112,8 @@ struct type##_fract { \ __##type numerator; \ __##type denominator; \ }; +__STRUCT_FRACT(s8) +__STRUCT_FRACT(u8) __STRUCT_FRACT(s16) __STRUCT_FRACT(u16) __STRUCT_FRACT(s32) diff --git a/include/linux/mhi.h b/include/linux/mhi.h index b573f15762f8..fabd6ed8d258 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -290,6 +290,7 @@ struct mhi_controller_config { /** * struct mhi_controller - Master MHI controller structure + * @name: Device name of the MHI controller * @cntrl_dev: Pointer to the struct device of physical bus acting as the MHI * controller (required) * @mhi_dev: MHI device instance for the controller @@ -367,6 +368,7 @@ struct mhi_controller_config { * they can be populated depending on the usecase. */ struct mhi_controller { + const char *name; struct device *cntrl_dev; struct mhi_device *mhi_dev; struct dentry *debugfs_dentry; diff --git a/include/linux/misc/keba.h b/include/linux/misc/keba.h new file mode 100644 index 000000000000..323b31a847c5 --- /dev/null +++ b/include/linux/misc/keba.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2024, KEBA Industrial Automation Gmbh */ + +#ifndef _LINUX_MISC_KEBA_H +#define _LINUX_MISC_KEBA_H + +#include + +struct i2c_board_info; + +/** + * struct keba_i2c_auxdev - KEBA I2C auxiliary device + * @auxdev: auxiliary device object + * @io: address range of I2C controller IO memory + * @info_size: number of I2C devices to be probed + * @info: I2C devices to be probed + */ +struct keba_i2c_auxdev { + struct auxiliary_device auxdev; + struct resource io; + int info_size; + struct i2c_board_info *info; +}; + +#endif /* _LINUX_MISC_KEBA_H */ diff --git a/include/linux/parport.h b/include/linux/parport.h index fff39bc30629..464c2ad28039 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -252,13 +252,10 @@ struct parport { struct parport_driver { const char *name; - void (*attach) (struct parport *); void (*detach) (struct parport *); void (*match_port)(struct parport *); int (*probe)(struct pardevice *); struct device_driver driver; - bool devmodel; - struct list_head list; }; #define to_parport_driver(n) container_of(n, struct parport_driver, driver) @@ -301,9 +298,6 @@ int __must_check __parport_register_driver(struct parport_driver *, * to receive notifications about ports being found in the * system, as well as ports no longer available. * - * If devmodel is true then the new device model is used - * for registration. - * * The @driver structure is allocated by the caller and must not be * deallocated until after calling parport_unregister_driver(). * diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index acc5f96161fe..85bdf2adb760 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -197,6 +197,8 @@ struct pci_epc_features { #define to_pci_epc(device) container_of((device), struct pci_epc, dev) +#ifdef CONFIG_PCI_ENDPOINT + #define pci_epc_create(dev, ops) \ __pci_epc_create((dev), (ops), THIS_MODULE) #define devm_pci_epc_create(dev, ops) \ @@ -226,7 +228,8 @@ void pci_epc_linkup(struct pci_epc *epc); void pci_epc_linkdown(struct pci_epc *epc); void pci_epc_init_notify(struct pci_epc *epc); void pci_epc_notify_pending_init(struct pci_epc *epc, struct pci_epf *epf); -void pci_epc_bme_notify(struct pci_epc *epc); +void pci_epc_deinit_notify(struct pci_epc *epc); +void pci_epc_bus_master_enable_notify(struct pci_epc *epc); void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf, enum pci_epc_interface_type type); int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no, @@ -272,4 +275,14 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, phys_addr_t *phys_addr, size_t size); void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr, void __iomem *virt_addr, size_t size); + +#else +static inline void pci_epc_init_notify(struct pci_epc *epc) +{ +} + +static inline void pci_epc_deinit_notify(struct pci_epc *epc) +{ +} +#endif /* CONFIG_PCI_ENDPOINT */ #endif /* __LINUX_PCI_EPC_H */ diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index adee6a1b35db..0639d4dc8986 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -70,16 +70,18 @@ struct pci_epf_ops { /** * struct pci_epc_event_ops - Callbacks for capturing the EPC events - * @core_init: Callback for the EPC initialization complete event + * @epc_init: Callback for the EPC initialization complete event + * @epc_deinit: Callback for the EPC deinitialization event * @link_up: Callback for the EPC link up event * @link_down: Callback for the EPC link down event - * @bme: Callback for the EPC BME (Bus Master Enable) event + * @bus_master_enable: Callback for the EPC Bus Master Enable event */ struct pci_epc_event_ops { - int (*core_init)(struct pci_epf *epf); + int (*epc_init)(struct pci_epf *epf); + void (*epc_deinit)(struct pci_epf *epf); int (*link_up)(struct pci_epf *epf); int (*link_down)(struct pci_epf *epf); - int (*bme)(struct pci_epf *epf); + int (*bus_master_enable)(struct pci_epf *epf); }; /** diff --git a/include/linux/pci.h b/include/linux/pci.h index cafc5ab1cbcb..9e36b6c1810e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -367,10 +367,11 @@ struct pci_dev { this is D0-D3, D0 being fully functional, and D3 being off. */ u8 pm_cap; /* PM capability offset */ - unsigned int imm_ready:1; /* Supports Immediate Readiness */ unsigned int pme_support:5; /* Bitmask of states from which PME# can be generated */ unsigned int pme_poll:1; /* Poll device's PME status bit */ + unsigned int pinned:1; /* Whether this dev is pinned */ + unsigned int imm_ready:1; /* Supports Immediate Readiness */ unsigned int d1_support:1; /* Low power state D1 is supported */ unsigned int d2_support:1; /* Low power state D2 is supported */ unsigned int no_d1d2:1; /* D1 and D2 are forbidden */ @@ -1549,10 +1550,7 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t size, resource_size_t align, resource_size_t min, unsigned long type_mask, - resource_size_t (*alignf)(void *, - const struct resource *, - resource_size_t, - resource_size_t), + resource_alignf alignf, void *alignf_data); @@ -2300,6 +2298,8 @@ int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name); int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, const char *name); void pcim_iounmap_regions(struct pci_dev *pdev, int mask); +void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar, + unsigned long offset, unsigned long len); extern int pci_pci_problems; #define PCIPCI_FAIL 1 /* No PCI PCI DMA */ diff --git a/include/linux/peci-cpu.h b/include/linux/peci-cpu.h index ff8ae9c26c80..601cdd086bf6 100644 --- a/include/linux/peci-cpu.h +++ b/include/linux/peci-cpu.h @@ -6,6 +6,30 @@ #include +/* Copied from x86 */ +#define X86_VENDOR_INTEL 0 + +/* Copied from x86 */ +#define VFM_MODEL_BIT 0 +#define VFM_FAMILY_BIT 8 +#define VFM_VENDOR_BIT 16 +#define VFM_RSVD_BIT 24 + +#define VFM_MODEL_MASK GENMASK(VFM_FAMILY_BIT - 1, VFM_MODEL_BIT) +#define VFM_FAMILY_MASK GENMASK(VFM_VENDOR_BIT - 1, VFM_FAMILY_BIT) +#define VFM_VENDOR_MASK GENMASK(VFM_RSVD_BIT - 1, VFM_VENDOR_BIT) + +#define VFM_MODEL(vfm) (((vfm) & VFM_MODEL_MASK) >> VFM_MODEL_BIT) +#define VFM_FAMILY(vfm) (((vfm) & VFM_FAMILY_MASK) >> VFM_FAMILY_BIT) +#define VFM_VENDOR(vfm) (((vfm) & VFM_VENDOR_MASK) >> VFM_VENDOR_BIT) + +#define VFM_MAKE(_vendor, _family, _model) ( \ + ((_model) << VFM_MODEL_BIT) | \ + ((_family) << VFM_FAMILY_BIT) | \ + ((_vendor) << VFM_VENDOR_BIT) \ +) +/* End of copied code */ + #include "../../arch/x86/include/asm/intel-family.h" #define PECI_PCS_PKG_ID 0 /* Package Identifier Read */ diff --git a/include/linux/peci.h b/include/linux/peci.h index 90e241458ef6..3e0bc37591d6 100644 --- a/include/linux/peci.h +++ b/include/linux/peci.h @@ -59,8 +59,7 @@ static inline struct peci_controller *to_peci_controller(void *d) * struct peci_device - PECI device * @dev: device object to register PECI device to the device model * @info: PECI device characteristics - * @info.family: device family - * @info.model: device model + * @info.x86_vfm: device vendor-family-model * @info.peci_revision: PECI revision supported by the PECI device * @info.socket_id: the socket ID represented by the PECI device * @addr: address used on the PECI bus connected to the parent controller @@ -73,8 +72,7 @@ static inline struct peci_controller *to_peci_controller(void *d) struct peci_device { struct device dev; struct { - u16 family; - u8 model; + u32 x86_vfm; u8 peci_revision; u8 socket_id; } info; diff --git a/include/linux/printk.h b/include/linux/printk.h index 65c5184470f1..7239976698e4 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -60,6 +60,10 @@ static inline const char *printk_skip_headers(const char *buffer) #define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT #define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET +int match_devname_and_update_preferred_console(const char *match, + const char *name, + const short idx); + extern int console_printk[]; #define console_loglevel (console_printk[0]) diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 1c89611e0e06..0f2f50b8d28e 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -37,6 +37,7 @@ enum { SCIx_SH7705_SCIF_REGTYPE, SCIx_HSCIF_REGTYPE, SCIx_RZ_SCIFA_REGTYPE, + SCIx_RZV2H_SCIF_REGTYPE, SCIx_NR_REGTYPES, }; diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h index 8d8fac1626bd..cdb58d61c152 100644 --- a/include/linux/switchtec.h +++ b/include/linux/switchtec.h @@ -521,6 +521,6 @@ static inline struct switchtec_dev *to_stdev(struct device *dev) return container_of(dev, struct switchtec_dev, dev); } -extern struct class *switchtec_class; +extern const struct class switchtec_class; #endif diff --git a/include/linux/usb.h b/include/linux/usb.h index 1913a13833f2..832997a9da0a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1171,6 +1171,7 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf); * post_reset method is called. * @post_reset: Called by usb_reset_device() after the device * has been reset + * @shutdown: Called at shut-down time to quiesce the device. * @id_table: USB drivers use ID table to support hotplugging. * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * or your driver's probe function will never get called. @@ -1222,6 +1223,8 @@ struct usb_driver { int (*pre_reset)(struct usb_interface *intf); int (*post_reset)(struct usb_interface *intf); + void (*shutdown)(struct usb_interface *intf); + const struct usb_device_id *id_table; const struct attribute_group **dev_groups; diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 56dda8e1562d..df33333650a0 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -229,18 +229,18 @@ struct usb_ep { const char *name; const struct usb_ep_ops *ops; + const struct usb_endpoint_descriptor *desc; + const struct usb_ss_ep_comp_descriptor *comp_desc; struct list_head ep_list; struct usb_ep_caps caps; bool claimed; bool enabled; - unsigned maxpacket:16; - unsigned maxpacket_limit:16; - unsigned max_streams:16; unsigned mult:2; unsigned maxburst:5; u8 address; - const struct usb_endpoint_descriptor *desc; - const struct usb_ss_ep_comp_descriptor *comp_desc; + u16 maxpacket; + u16 maxpacket_limit; + u16 max_streams; }; /*-------------------------------------------------------------------------*/ diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h index 47a86b8a4a50..0ab39b6ea205 100644 --- a/include/linux/usb/tcpci.h +++ b/include/linux/usb/tcpci.h @@ -47,6 +47,9 @@ #define TCPC_SINK_FAST_ROLE_SWAP BIT(0) #define TCPC_CONFIG_STD_OUTPUT 0x18 +#define TCPC_CONFIG_STD_OUTPUT_ORIENTATION_MASK BIT(0) +#define TCPC_CONFIG_STD_OUTPUT_ORIENTATION_NORMAL 0 +#define TCPC_CONFIG_STD_OUTPUT_ORIENTATION_FLIPPED 1 #define TCPC_TCPC_CTRL 0x19 #define TCPC_TCPC_CTRL_ORIENTATION BIT(0) @@ -127,6 +130,7 @@ #define TCPC_DEV_CAP_2 0x26 #define TCPC_STD_INPUT_CAP 0x28 #define TCPC_STD_OUTPUT_CAP 0x29 +#define TCPC_STD_OUTPUT_CAP_ORIENTATION BIT(0) #define TCPC_MSG_HDR_INFO 0x2e #define TCPC_MSG_HDR_INFO_DATA_ROLE BIT(3) @@ -209,6 +213,9 @@ struct tcpci; * swap following Discover Identity on SOP' occurs. * Return true when the TCPM is allowed to request a Vconn swap * after Discovery Identity on SOP. + * @set_orientation: + * Optional; Enable setting the connector orientation + * CONFIG_STANDARD_OUTPUT (0x18) bit0. */ struct tcpci_data { struct regmap *regmap; @@ -216,6 +223,7 @@ struct tcpci_data { unsigned char auto_discharge_disconnect:1; unsigned char vbus_vsafe0v:1; unsigned char cable_comm_capable:1; + unsigned char set_orientation:1; int (*init)(struct tcpci *tcpci, struct tcpci_data *data); int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data, diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index b35b427561ab..549275f8ac1b 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -167,6 +167,9 @@ struct typec_port *typec_altmode2port(struct typec_altmode *alt); void typec_altmode_update_active(struct typec_altmode *alt, bool active); +void typec_altmode_set_ops(struct typec_altmode *alt, + const struct typec_altmode_ops *ops); + enum typec_plug_index { TYPEC_PLUG_SOP_P, TYPEC_PLUG_SOP_PP, diff --git a/include/linux/w1.h b/include/linux/w1.h index 9a2a0ef39018..064805bfae3f 100644 --- a/include/linux/w1.h +++ b/include/linux/w1.h @@ -85,7 +85,8 @@ typedef void (*w1_slave_found_callback)(struct w1_master *, u64); * * @data: the first parameter in all the functions below * - * @read_bit: Sample the line level @return the level read (0 or 1) + * @read_bit: Sample the line level + * @return the level read (0 or 1) * * @write_bit: Sets the line level * @@ -95,7 +96,7 @@ typedef void (*w1_slave_found_callback)(struct w1_master *, u64); * touch_bit(1) = write-1 / read cycle * @return the bit read (0 or 1) * - * @read_byte: Reads a bytes. Same as 8 touch_bit(1) calls. + * @read_byte: Reads a byte. Same as 8 touch_bit(1) calls. * @return the byte read * * @write_byte: Writes a byte. Same as 8 touch_bit(x) calls. @@ -114,7 +115,7 @@ typedef void (*w1_slave_found_callback)(struct w1_master *, u64); * @set_pullup: Put out a strong pull-up pulse of the specified duration. * @return -1=Error, 0=completed * - * @search: Really nice hardware can handles the different types of ROM search + * @search: Really nice hardware can handle the different types of ROM search * w1_master* is passed to the slave found callback. * u8 is search_type, W1_SEARCH or W1_ALARM_SEARCH * diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 6e7984bfb986..72af2f223e59 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -173,6 +173,7 @@ struct fib_result { unsigned char type; unsigned char scope; u32 tclassid; + dscp_t dscp; struct fib_nh_common *nhc; struct fib_info *fi; struct fib_table *table; diff --git a/include/uapi/linux/iio/buffer.h b/include/uapi/linux/iio/buffer.h index 13939032b3f6..c666aa95e532 100644 --- a/include/uapi/linux/iio/buffer.h +++ b/include/uapi/linux/iio/buffer.h @@ -5,6 +5,28 @@ #ifndef _UAPI_IIO_BUFFER_H_ #define _UAPI_IIO_BUFFER_H_ +#include + +/* Flags for iio_dmabuf.flags */ +#define IIO_BUFFER_DMABUF_CYCLIC (1 << 0) +#define IIO_BUFFER_DMABUF_SUPPORTED_FLAGS 0x00000001 + +/** + * struct iio_dmabuf - Descriptor for a single IIO DMABUF object + * @fd: file descriptor of the DMABUF object + * @flags: one or more IIO_BUFFER_DMABUF_* flags + * @bytes_used: number of bytes used in this DMABUF for the data transfer. + * Should generally be set to the DMABUF's size. + */ +struct iio_dmabuf { + __u32 fd; + __u32 flags; + __u64 bytes_used; +}; + #define IIO_BUFFER_GET_FD_IOCTL _IOWR('i', 0x91, int) +#define IIO_BUFFER_DMABUF_ATTACH_IOCTL _IOW('i', 0x92, int) +#define IIO_BUFFER_DMABUF_DETACH_IOCTL _IOW('i', 0x93, int) +#define IIO_BUFFER_DMABUF_ENQUEUE_IOCTL _IOW('i', 0x94, struct iio_dmabuf) #endif /* _UAPI_IIO_BUFFER_H_ */ diff --git a/include/uapi/misc/mrvl_cn10k_dpi.h b/include/uapi/misc/mrvl_cn10k_dpi.h new file mode 100644 index 000000000000..8db902eaa907 --- /dev/null +++ b/include/uapi/misc/mrvl_cn10k_dpi.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Marvell Octeon CN10K DPI driver + * + * Copyright (C) 2024 Marvell. + * + */ + +#ifndef __MRVL_CN10K_DPI_H__ +#define __MRVL_CN10K_DPI_H__ + +#include + +#define DPI_MAX_ENGINES 6 + +struct dpi_mps_mrrs_cfg { + __u16 max_read_req_sz; /* Max read request size */ + __u16 max_payload_sz; /* Max payload size */ + __u16 port; /* Ebus port */ + __u16 reserved; /* Reserved */ +}; + +struct dpi_engine_cfg { + __u64 fifo_mask; /* FIFO size mask in KBytes */ + __u16 molr[DPI_MAX_ENGINES]; /* Max outstanding load requests */ + __u16 update_molr; /* '1' to update engine MOLR */ + __u16 reserved; /* Reserved */ +}; + +/* DPI ioctl numbers */ +#define DPI_MAGIC_NUM 0xB8 + +/* Set MPS & MRRS parameters */ +#define DPI_MPS_MRRS_CFG _IOW(DPI_MAGIC_NUM, 1, struct dpi_mps_mrrs_cfg) + +/* Set Engine FIFO configuration */ +#define DPI_ENGINE_CFG _IOW(DPI_MAGIC_NUM, 2, struct dpi_engine_cfg) + +#endif /* __MRVL_CN10K_DPI_H__ */ diff --git a/kernel/printk/console_cmdline.h b/kernel/printk/console_cmdline.h index 3ca74ad391d6..0ab573b6d4dc 100644 --- a/kernel/printk/console_cmdline.h +++ b/kernel/printk/console_cmdline.h @@ -6,6 +6,7 @@ struct console_cmdline { char name[16]; /* Name of the driver */ int index; /* Minor dev. to use */ + char devname[32]; /* DEVNAME:0.0 style device name */ bool user_specified; /* Specified by command line vs. platform */ char *options; /* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 26dcd70db34c..39dc080b7d33 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2431,18 +2431,23 @@ static void set_user_specified(struct console_cmdline *c, bool user_specified) console_set_on_cmdline = 1; } -static int __add_preferred_console(const char *name, const short idx, char *options, +static int __add_preferred_console(const char *name, const short idx, + const char *devname, char *options, char *brl_options, bool user_specified) { struct console_cmdline *c; int i; + if (!name && !devname) + return -EINVAL; + /* * We use a signed short index for struct console for device drivers to * indicate a not yet assigned index or port. However, a negative index - * value is not valid for preferred console. + * value is not valid when the console name and index are defined on + * the command line. */ - if (idx < 0) + if (name && idx < 0) return -EINVAL; /* @@ -2450,9 +2455,10 @@ static int __add_preferred_console(const char *name, const short idx, char *opti * if we have a slot free. */ for (i = 0, c = console_cmdline; - i < MAX_CMDLINECONSOLES && c->name[0]; + i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]); i++, c++) { - if (strcmp(c->name, name) == 0 && c->index == idx) { + if ((name && strcmp(c->name, name) == 0 && c->index == idx) || + (devname && strcmp(c->devname, devname) == 0)) { if (!brl_options) preferred_console = i; set_user_specified(c, user_specified); @@ -2463,7 +2469,10 @@ static int __add_preferred_console(const char *name, const short idx, char *opti return -E2BIG; if (!brl_options) preferred_console = i; - strscpy(c->name, name, sizeof(c->name)); + if (name) + strscpy(c->name, name); + if (devname) + strscpy(c->devname, devname); c->options = options; set_user_specified(c, user_specified); braille_set_options(c, brl_options); @@ -2488,8 +2497,13 @@ __setup("console_msg_format=", console_msg_format_setup); */ static int __init console_setup(char *str) { - char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */ - char *s, *options, *brl_options = NULL; + static_assert(sizeof(console_cmdline[0].devname) >= sizeof(console_cmdline[0].name) + 4); + char buf[sizeof(console_cmdline[0].devname)]; + char *brl_options = NULL; + char *ttyname = NULL; + char *devname = NULL; + char *options; + char *s; int idx; /* @@ -2498,17 +2512,23 @@ static int __init console_setup(char *str) * for exactly this purpose. */ if (str[0] == 0 || strcmp(str, "null") == 0) { - __add_preferred_console("ttynull", 0, NULL, NULL, true); + __add_preferred_console("ttynull", 0, NULL, NULL, NULL, true); return 1; } if (_braille_console_setup(&str, &brl_options)) return 1; + /* For a DEVNAME:0.0 style console the character device is unknown early */ + if (strchr(str, ':')) + devname = buf; + else + ttyname = buf; + /* * Decode str into name, index, options. */ - if (isdigit(str[0])) + if (ttyname && isdigit(str[0])) scnprintf(buf, sizeof(buf), "ttyS%s", str); else strscpy(buf, str); @@ -2525,12 +2545,18 @@ static int __init console_setup(char *str) #endif for (s = buf; *s; s++) - if (isdigit(*s) || *s == ',') + if ((ttyname && isdigit(*s)) || *s == ',') break; - idx = simple_strtoul(s, NULL, 10); + + /* @idx will get defined when devname matches. */ + if (devname) + idx = -1; + else + idx = simple_strtoul(s, NULL, 10); + *s = 0; - __add_preferred_console(buf, idx, options, brl_options, true); + __add_preferred_console(ttyname, idx, devname, options, brl_options, true); return 1; } __setup("console=", console_setup); @@ -2550,7 +2576,51 @@ __setup("console=", console_setup); */ int add_preferred_console(const char *name, const short idx, char *options) { - return __add_preferred_console(name, idx, options, NULL, false); + return __add_preferred_console(name, idx, NULL, options, NULL, false); +} + +/** + * match_devname_and_update_preferred_console - Update a preferred console + * when matching devname is found. + * @devname: DEVNAME:0.0 style device name + * @name: Name of the corresponding console driver, e.g. "ttyS" + * @idx: Console index, e.g. port number. + * + * The function checks whether a device with the given @devname is + * preferred via the console=DEVNAME:0.0 command line option. + * It fills the missing console driver name and console index + * so that a later register_console() call could find (match) + * and enable this device. + * + * It might be used when a driver subsystem initializes particular + * devices with already known DEVNAME:0.0 style names. And it + * could predict which console driver name and index this device + * would later get associated with. + * + * Return: 0 on success, negative error code on failure. + */ +int match_devname_and_update_preferred_console(const char *devname, + const char *name, + const short idx) +{ + struct console_cmdline *c = console_cmdline; + int i; + + if (!devname || !strlen(devname) || !name || !strlen(name) || idx < 0) + return -EINVAL; + + for (i = 0; i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]); + i++, c++) { + if (!strcmp(devname, c->devname)) { + pr_info("associate the preferred console \"%s\" with \"%s%d\"\n", + devname, name, idx); + strscpy(c->name, name); + c->index = idx; + return 0; + } + } + + return -ENOENT; } bool console_suspend_enabled = true; @@ -3326,8 +3396,11 @@ static int try_enable_preferred_console(struct console *newcon, int i, err; for (i = 0, c = console_cmdline; - i < MAX_CMDLINECONSOLES && c->name[0]; + i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]); i++, c++) { + /* Console not yet initialized? */ + if (!c->name[0]) + continue; if (c->user_specified != user_specified) continue; if (!newcon->match || diff --git a/kernel/resource.c b/kernel/resource.c index fcbca39dbc45..14777afb0a99 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -48,14 +48,6 @@ struct resource iomem_resource = { }; EXPORT_SYMBOL(iomem_resource); -/* constraints to be met while allocating resources */ -struct resource_constraint { - resource_size_t min, max, align; - resource_size_t (*alignf)(void *, const struct resource *, - resource_size_t, resource_size_t); - void *alignf_data; -}; - static DEFINE_RWLOCK(resource_lock); static struct resource *next_resource(struct resource *p, bool skip_children) @@ -610,14 +602,6 @@ void __weak arch_remove_reservations(struct resource *avail) { } -static resource_size_t simple_align_resource(void *data, - const struct resource *avail, - resource_size_t size, - resource_size_t align) -{ - return avail->start; -} - static void resource_clip(struct resource *res, resource_size_t min, resource_size_t max) { @@ -628,16 +612,16 @@ static void resource_clip(struct resource *res, resource_size_t min, } /* - * Find empty slot in the resource tree with the given range and + * Find empty space in the resource tree with the given range and * alignment constraints */ -static int __find_resource(struct resource *root, struct resource *old, - struct resource *new, - resource_size_t size, - struct resource_constraint *constraint) +static int __find_resource_space(struct resource *root, struct resource *old, + struct resource *new, resource_size_t size, + struct resource_constraint *constraint) { struct resource *this = root->child; struct resource tmp = *new, avail, alloc; + resource_alignf alignf = constraint->alignf; tmp.start = root->start; /* @@ -666,8 +650,12 @@ static int __find_resource(struct resource *root, struct resource *old, avail.flags = new->flags & ~IORESOURCE_UNSET; if (avail.start >= tmp.start) { alloc.flags = avail.flags; - alloc.start = constraint->alignf(constraint->alignf_data, &avail, - size, constraint->align); + if (alignf) { + alloc.start = alignf(constraint->alignf_data, + &avail, size, constraint->align); + } else { + alloc.start = avail.start; + } alloc.end = alloc.start + size - 1; if (alloc.start <= alloc.end && resource_contains(&avail, &alloc)) { @@ -687,15 +675,27 @@ next: if (!this || this->end == root->end) return -EBUSY; } -/* - * Find empty slot in the resource tree given range and alignment. +/** + * find_resource_space - Find empty space in the resource tree + * @root: Root resource descriptor + * @new: Resource descriptor awaiting an empty resource space + * @size: The minimum size of the empty space + * @constraint: The range and alignment constraints to be met + * + * Finds an empty space under @root in the resource tree satisfying range and + * alignment @constraints. + * + * Return: + * * %0 - if successful, @new members start, end, and flags are altered. + * * %-EBUSY - if no empty space was found. */ -static int find_resource(struct resource *root, struct resource *new, +int find_resource_space(struct resource *root, struct resource *new, resource_size_t size, - struct resource_constraint *constraint) + struct resource_constraint *constraint) { - return __find_resource(root, NULL, new, size, constraint); + return __find_resource_space(root, NULL, new, size, constraint); } +EXPORT_SYMBOL_GPL(find_resource_space); /** * reallocate_resource - allocate a slot in the resource tree given range & alignment. @@ -717,7 +717,7 @@ static int reallocate_resource(struct resource *root, struct resource *old, write_lock(&resource_lock); - if ((err = __find_resource(root, old, &new, newsize, constraint))) + if ((err = __find_resource_space(root, old, &new, newsize, constraint))) goto out; if (resource_contains(&new, old)) { @@ -761,18 +761,12 @@ out: int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, resource_size_t max, resource_size_t align, - resource_size_t (*alignf)(void *, - const struct resource *, - resource_size_t, - resource_size_t), + resource_alignf alignf, void *alignf_data) { int err; struct resource_constraint constraint; - if (!alignf) - alignf = simple_align_resource; - constraint.min = min; constraint.max = max; constraint.align = align; @@ -786,7 +780,7 @@ int allocate_resource(struct resource *root, struct resource *new, } write_lock(&resource_lock); - err = find_resource(root, new, size, &constraint); + err = find_resource_space(root, new, size, &constraint); if (err >= 0 && __request_resource(root, new)) err = -EBUSY; write_unlock(&resource_lock); diff --git a/lib/math/prime_numbers.c b/lib/math/prime_numbers.c index d3b64b10da1c..9a17ee9af93a 100644 --- a/lib/math/prime_numbers.c +++ b/lib/math/prime_numbers.c @@ -311,4 +311,5 @@ module_exit(primes_exit); module_param_named(selftest, selftest_max, ulong, 0400); MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Prime number library"); MODULE_LICENSE("GPL"); diff --git a/lib/math/rational-test.c b/lib/math/rational-test.c index 01611ddff420..47486a95f088 100644 --- a/lib/math/rational-test.c +++ b/lib/math/rational-test.c @@ -53,4 +53,5 @@ static struct kunit_suite rational_test_suite = { kunit_test_suites(&rational_test_suite); +MODULE_DESCRIPTION("Rational fractions unit test"); MODULE_LICENSE("GPL v2"); diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c index 8dd250ad022b..77c2a669b6af 100644 --- a/lib/test_dynamic_debug.c +++ b/lib/test_dynamic_debug.c @@ -162,4 +162,5 @@ module_init(test_dynamic_debug_init); module_exit(test_dynamic_debug_exit); MODULE_AUTHOR("Jim Cromie "); +MODULE_DESCRIPTION("Kernel module for testing dynamic_debug"); MODULE_LICENSE("GPL"); diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index ada1e39b557e..0e638a37aa09 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1117,7 +1117,7 @@ bool __skb_flow_dissect(const struct net *net, } } - WARN_ON_ONCE(!net); + DEBUG_NET_WARN_ON_ONCE(!net); if (net) { enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR; struct bpf_prog_array *run_array; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f474106464d2..8f30e3f00b7f 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1629,6 +1629,7 @@ set_result: res->nhc = nhc; res->type = fa->fa_type; res->scope = fi->fib_scope; + res->dscp = fa->fa_dscp; res->fi = fi; res->table = tb; res->fa_head = &n->leaf; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 54512acbead7..5090912533d6 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2867,9 +2867,9 @@ EXPORT_SYMBOL_GPL(ip_route_output_flow); /* called with rcu_read_lock held */ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, - struct rtable *rt, u32 table_id, struct flowi4 *fl4, - struct sk_buff *skb, u32 portid, u32 seq, - unsigned int flags) + struct rtable *rt, u32 table_id, dscp_t dscp, + struct flowi4 *fl4, struct sk_buff *skb, u32 portid, + u32 seq, unsigned int flags) { struct rtmsg *r; struct nlmsghdr *nlh; @@ -2885,7 +2885,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, r->rtm_family = AF_INET; r->rtm_dst_len = 32; r->rtm_src_len = 0; - r->rtm_tos = fl4 ? fl4->flowi4_tos : 0; + r->rtm_tos = inet_dscp_to_dsfield(dscp); r->rtm_table = table_id < 256 ? table_id : RT_TABLE_COMPAT; if (nla_put_u32(skb, RTA_TABLE, table_id)) goto nla_put_failure; @@ -3035,7 +3035,7 @@ static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb, goto next; err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt, - table_id, NULL, skb, + table_id, 0, NULL, skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, flags); if (err) @@ -3331,7 +3331,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, fri.tb_id = table_id; fri.dst = res.prefix; fri.dst_len = res.prefixlen; - fri.dscp = inet_dsfield_to_dscp(fl4.flowi4_tos); + fri.dscp = res.dscp; fri.type = rt->rt_type; fri.offload = 0; fri.trap = 0; @@ -3358,8 +3358,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, err = fib_dump_info(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, RTM_NEWROUTE, &fri, 0); } else { - err = rt_fill_info(net, dst, src, rt, table_id, &fl4, skb, - NETLINK_CB(in_skb).portid, + err = rt_fill_info(net, dst, src, rt, table_id, res.dscp, &fl4, + skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, 0); } if (err < 0) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 78a1cc72dc38..706c2b52a1ac 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1459,18 +1459,18 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, if (ret < 0) goto out_err; - /* Bind the ct retriever */ - RCU_INIT_POINTER(svc->pe, pe); - pe = NULL; - /* Update the virtual service counters */ if (svc->port == FTPPORT) atomic_inc(&ipvs->ftpsvc_counter); else if (svc->port == 0) atomic_inc(&ipvs->nullsvc_counter); - if (svc->pe && svc->pe->conn_out) + if (pe && pe->conn_out) atomic_inc(&ipvs->conn_out_counter); + /* Bind the ct retriever */ + RCU_INIT_POINTER(svc->pe, pe); + pe = NULL; + /* Count only IPv4 services for old get/setsockopt interface */ if (svc->af == AF_INET) ipvs->num_services++; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 3b846cbdc050..4cbf71d0786b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3420,7 +3420,8 @@ static int ctnetlink_del_expect(struct sk_buff *skb, if (cda[CTA_EXPECT_ID]) { __be32 id = nla_get_be32(cda[CTA_EXPECT_ID]); - if (ntohl(id) != (u32)(unsigned long)exp) { + + if (id != nf_expect_get_id(exp)) { nf_ct_expect_put(exp); return -ENOENT; } diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index 15a236bebb46..eb4c4a4ac7ac 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -434,7 +434,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, res_map = scratch->map + (map_index ? m->bsize_max : 0); fill_map = scratch->map + (map_index ? 0 : m->bsize_max); - memset(res_map, 0xff, m->bsize_max * sizeof(*res_map)); + pipapo_resmap_init(m, res_map); nft_pipapo_for_each_field(f, i, m) { bool last = i == m->field_count - 1; @@ -542,7 +542,7 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net, goto out; } - memset(res_map, 0xff, m->bsize_max * sizeof(*res_map)); + pipapo_resmap_init(m, res_map); nft_pipapo_for_each_field(f, i, m) { bool last = i == m->field_count - 1; diff --git a/net/netfilter/nft_set_pipapo.h b/net/netfilter/nft_set_pipapo.h index 0d2e40e10f7f..4a2ff85ce1c4 100644 --- a/net/netfilter/nft_set_pipapo.h +++ b/net/netfilter/nft_set_pipapo.h @@ -278,4 +278,25 @@ static u64 pipapo_estimate_size(const struct nft_set_desc *desc) return size; } +/** + * pipapo_resmap_init() - Initialise result map before first use + * @m: Matching data, including mapping table + * @res_map: Result map + * + * Initialize all bits covered by the first field to one, so that after + * the first step, only the matching bits of the first bit group remain. + * + * If other fields have a large bitmap, set remainder of res_map to 0. + */ +static inline void pipapo_resmap_init(const struct nft_pipapo_match *m, unsigned long *res_map) +{ + const struct nft_pipapo_field *f = m->f; + int i; + + for (i = 0; i < f->bsize; i++) + res_map[i] = ULONG_MAX; + + for (i = f->bsize; i < m->bsize_max; i++) + res_map[i] = 0ul; +} #endif /* _NFT_SET_PIPAPO_H */ diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c index d08407d589ea..8910a5ac7ed1 100644 --- a/net/netfilter/nft_set_pipapo_avx2.c +++ b/net/netfilter/nft_set_pipapo_avx2.c @@ -1036,6 +1036,7 @@ nothing: /** * nft_pipapo_avx2_lookup_slow() - Fallback function for uncommon field sizes + * @mdata: Matching data, including mapping table * @map: Previous match result, used as initial bitmap * @fill: Destination bitmap to be filled with current match result * @f: Field, containing lookup and mapping tables @@ -1051,7 +1052,8 @@ nothing: * Return: -1 on no match, rule index of match if @last, otherwise first long * word index to be checked next (i.e. first filled word). */ -static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill, +static int nft_pipapo_avx2_lookup_slow(const struct nft_pipapo_match *mdata, + unsigned long *map, unsigned long *fill, const struct nft_pipapo_field *f, int offset, const u8 *pkt, bool first, bool last) @@ -1060,7 +1062,7 @@ static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill, int i, ret = -1, b; if (first) - memset(map, 0xff, bsize * sizeof(*map)); + pipapo_resmap_init(mdata, map); for (i = offset; i < bsize; i++) { if (f->bb == 8) @@ -1186,7 +1188,7 @@ next_match: } else if (f->groups == 16) { NFT_SET_PIPAPO_AVX2_LOOKUP(8, 16); } else { - ret = nft_pipapo_avx2_lookup_slow(res, fill, f, + ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f, ret, rp, first, last); } @@ -1202,7 +1204,7 @@ next_match: } else if (f->groups == 32) { NFT_SET_PIPAPO_AVX2_LOOKUP(4, 32); } else { - ret = nft_pipapo_avx2_lookup_slow(res, fill, f, + ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f, ret, rp, first, last); } diff --git a/samples/configfs/configfs_sample.c b/samples/configfs/configfs_sample.c index 37a657b25d58..fd5d163828c5 100644 --- a/samples/configfs/configfs_sample.c +++ b/samples/configfs/configfs_sample.c @@ -364,4 +364,5 @@ static void __exit configfs_example_exit(void) module_init(configfs_example_init); module_exit(configfs_example_exit); +MODULE_DESCRIPTION("Sample configfs module"); MODULE_LICENSE("GPL"); diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl index 797e20ea99a2..591d85e8ca7e 100644 --- a/scripts/syscall.tbl +++ b/scripts/syscall.tbl @@ -402,3 +402,4 @@ 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 +467 common uretprobe sys_uretprobe diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 5cfd0e99a13f..b1b333d1cf39 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -882,7 +882,6 @@ static struct parport_driver mts64_parport_driver = { .probe = snd_mts64_dev_probe, .match_port = snd_mts64_attach, .detach = snd_mts64_detach, - .devmodel = true, }; /********************************************************************* diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 619e3f594477..6fd9e8870021 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -668,7 +668,6 @@ static struct parport_driver portman_parport_driver = { .probe = snd_portman_dev_probe, .match_port = snd_portman_attach, .detach = snd_portman_detach, - .devmodel = true, }; /********************************************************************* diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 06eed383fdc0..bc8fe9e8f7f2 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -13,7 +13,8 @@ TARGETS += core TARGETS += cpufreq TARGETS += cpu-hotplug TARGETS += damon -TARGETS += devices +TARGETS += devices/error_logs +TARGETS += devices/probe TARGETS += dmabuf-heaps TARGETS += drivers/dma-buf TARGETS += drivers/s390x/uvdevice @@ -252,6 +253,7 @@ ifdef INSTALL_PATH install -m 744 kselftest/runner.sh $(INSTALL_PATH)/kselftest/ install -m 744 kselftest/prefix.pl $(INSTALL_PATH)/kselftest/ install -m 744 kselftest/ktap_helpers.sh $(INSTALL_PATH)/kselftest/ + install -m 744 kselftest/ksft.py $(INSTALL_PATH)/kselftest/ install -m 744 run_kselftest.sh $(INSTALL_PATH)/ rm -f $(TEST_LIST) @ret=1; \ diff --git a/tools/testing/selftests/devices/Makefile b/tools/testing/selftests/devices/Makefile deleted file mode 100644 index ca29249b30c3..000000000000 --- a/tools/testing/selftests/devices/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -TEST_PROGS := test_discoverable_devices.py -TEST_FILES := boards ksft.py - -include ../lib.mk diff --git a/tools/testing/selftests/devices/error_logs/Makefile b/tools/testing/selftests/devices/error_logs/Makefile new file mode 100644 index 000000000000..d546c3fb0a7f --- /dev/null +++ b/tools/testing/selftests/devices/error_logs/Makefile @@ -0,0 +1,3 @@ +TEST_PROGS := test_device_error_logs.py + +include ../../lib.mk diff --git a/tools/testing/selftests/devices/error_logs/test_device_error_logs.py b/tools/testing/selftests/devices/error_logs/test_device_error_logs.py new file mode 100755 index 000000000000..3dd56c8ec92c --- /dev/null +++ b/tools/testing/selftests/devices/error_logs/test_device_error_logs.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2024 Collabora Ltd +# +# This test checks for the presence of error (or more critical) log messages +# coming from devices in the kernel log. +# +# One failed test case is reported for each device that has outputted error +# logs. Devices with no errors do not produce a passing test case to avoid +# polluting the results, therefore a successful run will list 0 tests run. +# + +import glob +import os +import re +import sys + +# Allow ksft module to be imported from different directory +this_dir = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(this_dir, "../../kselftest/")) + +import ksft + +kmsg = "/dev/kmsg" + +RE_log = re.compile( + r"(?P[0-9]+),(?P[0-9]+),(?P[0-9]+),(?P[^;]*)(,[^;]*)*;(?P.*)" +) +RE_tag = re.compile(r" (?P[^=]+)=(?P.*)") + +PREFIX_ERROR = 3 + +logs = [] +error_log_per_device = {} + + +def parse_kmsg(): + current_log = {} + + with open(kmsg) as f: + os.set_blocking(f.fileno(), False) + + for line in f: + tag_line = RE_tag.match(line) + log_line = RE_log.match(line) + + if log_line: + if current_log: + logs.append(current_log) # Save last log + + current_log = { + "prefix": int(log_line.group("prefix")), + "sequence": int(log_line.group("sequence")), + "timestamp": int(log_line.group("timestamp")), + "flag": log_line.group("flag"), + "message": log_line.group("message"), + } + elif tag_line: + current_log[tag_line.group("key")] = tag_line.group("value") + + +def generate_per_device_error_log(): + for log in logs: + if log.get("DEVICE") and log["prefix"] <= PREFIX_ERROR: + if not error_log_per_device.get(log["DEVICE"]): + error_log_per_device[log["DEVICE"]] = [] + error_log_per_device[log["DEVICE"]].append(log) + + +parse_kmsg() + +generate_per_device_error_log() +num_tests = len(error_log_per_device) + +ksft.print_header() +ksft.set_plan(num_tests) + +for device in error_log_per_device: + for log in error_log_per_device[device]: + ksft.print_msg(log["message"]) + ksft.test_result_fail(device) +if num_tests == 0: + ksft.print_msg("No device error logs found") +ksft.finished() diff --git a/tools/testing/selftests/devices/probe/Makefile b/tools/testing/selftests/devices/probe/Makefile new file mode 100644 index 000000000000..f630108c3fdf --- /dev/null +++ b/tools/testing/selftests/devices/probe/Makefile @@ -0,0 +1,4 @@ +TEST_PROGS := test_discoverable_devices.py +TEST_FILES := boards + +include ../../lib.mk diff --git a/tools/testing/selftests/devices/boards/Dell Inc.,XPS 13 9300.yaml b/tools/testing/selftests/devices/probe/boards/Dell Inc.,XPS 13 9300.yaml similarity index 100% rename from tools/testing/selftests/devices/boards/Dell Inc.,XPS 13 9300.yaml rename to tools/testing/selftests/devices/probe/boards/Dell Inc.,XPS 13 9300.yaml diff --git a/tools/testing/selftests/devices/boards/google,spherion.yaml b/tools/testing/selftests/devices/probe/boards/google,spherion.yaml similarity index 86% rename from tools/testing/selftests/devices/boards/google,spherion.yaml rename to tools/testing/selftests/devices/probe/boards/google,spherion.yaml index 17157ecd8c14..3ea843324797 100644 --- a/tools/testing/selftests/devices/boards/google,spherion.yaml +++ b/tools/testing/selftests/devices/probe/boards/google,spherion.yaml @@ -11,6 +11,10 @@ # this, several optional keys can be used: # - dt-mmio: identify the MMIO address of the controller as defined in the # Devicetree. +# - of-fullname-regex: regular expression to match against the OF_FULLNAME +# property. Useful when the controller's address is not unique across other +# sibling controllers. In this case, dt-mmio can't be used, and this property +# allows the matching to include parent nodes as well to make it unique. # - usb-version: for USB controllers to differentiate between USB3 and USB2 # buses sharing the same controller. # - acpi-uid: _UID property of the controller as supplied by the ACPI. Useful to diff --git a/tools/testing/selftests/devices/test_discoverable_devices.py b/tools/testing/selftests/devices/probe/test_discoverable_devices.py similarity index 86% rename from tools/testing/selftests/devices/test_discoverable_devices.py rename to tools/testing/selftests/devices/probe/test_discoverable_devices.py index fbae8deb593d..d94a74b8a054 100755 --- a/tools/testing/selftests/devices/test_discoverable_devices.py +++ b/tools/testing/selftests/devices/probe/test_discoverable_devices.py @@ -14,13 +14,19 @@ # the description and examples of the file structure and vocabulary. # +import argparse import glob -import ksft import os import re import sys import yaml +# Allow ksft module to be imported from different directory +this_dir = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(this_dir, "../../kselftest/")) + +import ksft + pci_controllers = [] usb_controllers = [] @@ -63,6 +69,22 @@ def get_dt_mmio(sysfs_dev_dir): sysfs_dev_dir = os.path.dirname(sysfs_dev_dir) +def get_of_fullname(sysfs_dev_dir): + re_of_fullname = re.compile("OF_FULLNAME=(.*)") + of_full_name = None + + # PCI controllers' sysfs don't have an of_node, so have to read it from the + # parent + while not of_full_name: + try: + with open(os.path.join(sysfs_dev_dir, "uevent")) as f: + of_fullname = re_of_fullname.search(f.read()).group(1) + return of_fullname + except: + pass + sysfs_dev_dir = os.path.dirname(sysfs_dev_dir) + + def get_acpi_uid(sysfs_dev_dir): with open(os.path.join(sysfs_dev_dir, "firmware_node", "uid")) as f: return f.read() @@ -96,6 +118,11 @@ def find_controller_in_sysfs(controller, parent_sysfs=None): if str(controller["dt-mmio"]) != get_dt_mmio(c): continue + if controller.get("of-fullname-regex"): + re_of_fullname = re.compile(str(controller["of-fullname-regex"])) + if not re_of_fullname.match(get_of_fullname(c)): + continue + if controller.get("usb-version"): if controller["usb-version"] != get_usb_version(c): continue @@ -194,6 +221,9 @@ def generate_pathname(device): if device.get("dt-mmio"): pathname += "@" + str(device["dt-mmio"]) + if device.get("of-fullname-regex"): + pathname += "-" + str(device["of-fullname-regex"]) + if device.get("name"): pathname = pathname + "/" + device["name"] @@ -296,14 +326,24 @@ def run_test(yaml_file): parse_device_tree_node(device_tree) +parser = argparse.ArgumentParser() +parser.add_argument( + "--boards-dir", default="boards", help="Directory containing the board YAML files" +) +args = parser.parse_args() + find_pci_controller_dirs() find_usb_controller_dirs() ksft.print_header() +if not os.path.exists(args.boards_dir): + ksft.print_msg(f"Boards directory '{args.boards_dir}' doesn't exist") + ksft.exit_fail() + board_file = "" for board_filename in get_board_filenames(): - full_board_filename = os.path.join("boards", board_filename + ".yaml") + full_board_filename = os.path.join(args.boards_dir, board_filename + ".yaml") if os.path.exists(full_board_filename): board_file = full_board_filename diff --git a/tools/testing/selftests/devices/ksft.py b/tools/testing/selftests/kselftest/ksft.py similarity index 100% rename from tools/testing/selftests/devices/ksft.py rename to tools/testing/selftests/kselftest/ksft.py diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh index 73895711cdf4..5f3c28fc8624 100755 --- a/tools/testing/selftests/net/fib_tests.sh +++ b/tools/testing/selftests/net/fib_tests.sh @@ -1737,53 +1737,53 @@ ipv4_rt_dsfield() # DSCP 0x10 should match the specific route, no matter the ECN bits $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \ - grep -q "via 172.16.103.2" + grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2" log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT" $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \ - grep -q "via 172.16.103.2" + grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2" log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)" $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \ - grep -q "via 172.16.103.2" + grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2" log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)" $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \ - grep -q "via 172.16.103.2" + grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2" log_test $? 0 "IPv4 route with DSCP and ECN:CE" # Unknown DSCP should match the generic route, no matter the ECN bits $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT" $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)" $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)" $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE" # Null DSCP should match the generic route, no matter the ECN bits $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT" $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)" $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)" $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \ - grep -q "via 172.16.101.2" + grep -q "172.16.102.0/24 via 172.16.101.2" log_test $? 0 "IPv4 route with no DSCP and ECN:CE" } diff --git a/tools/testing/selftests/net/netfilter/nft_concat_range.sh b/tools/testing/selftests/net/netfilter/nft_concat_range.sh index 6d66240e149c..47088b005390 100755 --- a/tools/testing/selftests/net/netfilter/nft_concat_range.sh +++ b/tools/testing/selftests/net/netfilter/nft_concat_range.sh @@ -27,7 +27,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto net6_port_net6_port net_port_mac_proto_net" # Reported bugs, also described by TYPE_ variables below -BUGS="flush_remove_add reload" +BUGS="flush_remove_add reload net_port_proto_match" # List of possible paths to pktgen script from kernel tree for performance tests PKTGEN_SCRIPT_PATHS=" @@ -371,6 +371,22 @@ race_repeat 0 perf_duration 0 " +TYPE_net_port_proto_match=" +display net,port,proto +type_spec ipv4_addr . inet_service . inet_proto +chain_spec ip daddr . udp dport . meta l4proto +dst addr4 port proto +src +start 1 +count 9 +src_delta 9 +tools sendip bash +proto udp + +race_repeat 0 + +perf_duration 0 +" # Set template for all tests, types and rules are filled in depending on test set_template=' flush ruleset @@ -1555,6 +1571,64 @@ test_bug_reload() { nft flush ruleset } +# - add ranged element, check that packets match it +# - delete element again, check it is gone +test_bug_net_port_proto_match() { + setup veth send_"${proto}" set || return ${ksft_skip} + rstart=${start} + + range_size=1 + for i in $(seq 1 10); do + for j in $(seq 1 20) ; do + elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") + + nft "add element inet filter test { $elem }" || return 1 + nft "get element inet filter test { $elem }" | grep -q "$elem" + if [ $? -ne 0 ];then + local got=$(nft "get element inet filter test { $elem }") + err "post-add: should have returned $elem but got $got" + return 1 + fi + done + done + + # recheck after set was filled + for i in $(seq 1 10); do + for j in $(seq 1 20) ; do + elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") + + nft "get element inet filter test { $elem }" | grep -q "$elem" + if [ $? -ne 0 ];then + local got=$(nft "get element inet filter test { $elem }") + err "post-fill: should have returned $elem but got $got" + return 1 + fi + done + done + + # random del and re-fetch + for i in $(seq 1 10); do + for j in $(seq 1 20) ; do + local rnd=$((RANDOM%10)) + local got="" + + elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") + if [ $rnd -gt 0 ];then + continue + fi + + nft "delete element inet filter test { $elem }" + got=$(nft "get element inet filter test { $elem }" 2>/dev/null) + if [ $? -eq 0 ];then + err "post-delete: query for $elem returned $got instead of error." + return 1 + fi + done + done + + nft flush ruleset +} + test_reported_issues() { eval test_bug_"${subtest}" }