diff options
214 files changed, 20306 insertions, 2605 deletions
diff --git a/.clang-format b/.clang-format index 9b87ea1fc16e..1247d54f9e49 100644 --- a/.clang-format +++ b/.clang-format @@ -516,6 +516,7 @@ ForEachMacros: - 'of_property_for_each_string' - 'of_property_for_each_u32' - 'pci_bus_for_each_resource' + - 'pci_doe_for_each_off' - 'pcl_for_each_chunk' - 'pcl_for_each_segment' - 'pcm_for_each_format' diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl index 7c2b846521f3..8494ef27e8d2 100644 --- a/Documentation/ABI/testing/sysfs-bus-cxl +++ b/Documentation/ABI/testing/sysfs-bus-cxl @@ -7,6 +7,7 @@ Description: all descendant memdevs for unbind. Writing '1' to this attribute flushes that work. + What: /sys/bus/cxl/devices/memX/firmware_version Date: December, 2020 KernelVersion: v5.12 @@ -16,6 +17,7 @@ Description: Memory Device Output Payload in the CXL-2.0 specification. + What: /sys/bus/cxl/devices/memX/ram/size Date: December, 2020 KernelVersion: v5.12 @@ -25,6 +27,7 @@ Description: identically named field in the Identify Memory Device Output Payload in the CXL-2.0 specification. + What: /sys/bus/cxl/devices/memX/pmem/size Date: December, 2020 KernelVersion: v5.12 @@ -34,6 +37,7 @@ Description: identically named field in the Identify Memory Device Output Payload in the CXL-2.0 specification. + What: /sys/bus/cxl/devices/memX/serial Date: January, 2022 KernelVersion: v5.18 @@ -43,6 +47,7 @@ Description: capability. Mandatory for CXL devices, see CXL 2.0 8.1.12.2 Memory Device PCIe Capabilities and Extended Capabilities. + What: /sys/bus/cxl/devices/memX/numa_node Date: January, 2022 KernelVersion: v5.18 @@ -52,114 +57,334 @@ Description: host PCI device for this memory device, emit the CPU node affinity for this device. + What: /sys/bus/cxl/devices/*/devtype Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - CXL device objects export the devtype attribute which mirrors - the same value communicated in the DEVTYPE environment variable - for uevents for devices on the "cxl" bus. + (RO) CXL device objects export the devtype attribute which + mirrors the same value communicated in the DEVTYPE environment + variable for uevents for devices on the "cxl" bus. + What: /sys/bus/cxl/devices/*/modalias Date: December, 2021 KernelVersion: v5.18 Contact: [email protected] Description: - CXL device objects export the modalias attribute which mirrors - the same value communicated in the MODALIAS environment variable - for uevents for devices on the "cxl" bus. + (RO) CXL device objects export the modalias attribute which + mirrors the same value communicated in the MODALIAS environment + variable for uevents for devices on the "cxl" bus. + What: /sys/bus/cxl/devices/portX/uport Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - CXL port objects are enumerated from either a platform firmware - device (ACPI0017 and ACPI0016) or PCIe switch upstream port with - CXL component registers. The 'uport' symlink connects the CXL - portX object to the device that published the CXL port + (RO) CXL port objects are enumerated from either a platform + firmware device (ACPI0017 and ACPI0016) or PCIe switch upstream + port with CXL component registers. The 'uport' symlink connects + the CXL portX object to the device that published the CXL port capability. + What: /sys/bus/cxl/devices/portX/dportY Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - CXL port objects are enumerated from either a platform firmware - device (ACPI0017 and ACPI0016) or PCIe switch upstream port with - CXL component registers. The 'dportY' symlink identifies one or - more downstream ports that the upstream port may target in its - decode of CXL memory resources. The 'Y' integer reflects the - hardware port unique-id used in the hardware decoder target - list. + (RO) CXL port objects are enumerated from either a platform + firmware device (ACPI0017 and ACPI0016) or PCIe switch upstream + port with CXL component registers. The 'dportY' symlink + identifies one or more downstream ports that the upstream port + may target in its decode of CXL memory resources. The 'Y' + integer reflects the hardware port unique-id used in the + hardware decoder target list. + What: /sys/bus/cxl/devices/decoderX.Y Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - CXL decoder objects are enumerated from either a platform + (RO) CXL decoder objects are enumerated from either a platform firmware description, or a CXL HDM decoder register set in a PCIe device (see CXL 2.0 section 8.2.5.12 CXL HDM Decoder Capability Structure). The 'X' in decoderX.Y represents the cxl_port container of this decoder, and 'Y' represents the instance id of a given decoder resource. + What: /sys/bus/cxl/devices/decoderX.Y/{start,size} Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - The 'start' and 'size' attributes together convey the physical - address base and number of bytes mapped in the decoder's decode - window. For decoders of devtype "cxl_decoder_root" the address - range is fixed. For decoders of devtype "cxl_decoder_switch" the - address is bounded by the decode range of the cxl_port ancestor - of the decoder's cxl_port, and dynamically updates based on the - active memory regions in that address space. + (RO) The 'start' and 'size' attributes together convey the + physical address base and number of bytes mapped in the + decoder's decode window. For decoders of devtype + "cxl_decoder_root" the address range is fixed. For decoders of + devtype "cxl_decoder_switch" the address is bounded by the + decode range of the cxl_port ancestor of the decoder's cxl_port, + and dynamically updates based on the active memory regions in + that address space. + What: /sys/bus/cxl/devices/decoderX.Y/locked Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - CXL HDM decoders have the capability to lock the configuration - until the next device reset. For decoders of devtype - "cxl_decoder_root" there is no standard facility to unlock them. - For decoders of devtype "cxl_decoder_switch" a secondary bus - reset, of the PCIe bridge that provides the bus for this - decoders uport, unlocks / resets the decoder. + (RO) CXL HDM decoders have the capability to lock the + configuration until the next device reset. For decoders of + devtype "cxl_decoder_root" there is no standard facility to + unlock them. For decoders of devtype "cxl_decoder_switch" a + secondary bus reset, of the PCIe bridge that provides the bus + for this decoders uport, unlocks / resets the decoder. + What: /sys/bus/cxl/devices/decoderX.Y/target_list Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - Display a comma separated list of the current decoder target - configuration. The list is ordered by the current configured - interleave order of the decoder's dport instances. Each entry in - the list is a dport id. + (RO) Display a comma separated list of the current decoder + target configuration. The list is ordered by the current + configured interleave order of the decoder's dport instances. + Each entry in the list is a dport id. + What: /sys/bus/cxl/devices/decoderX.Y/cap_{pmem,ram,type2,type3} Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - When a CXL decoder is of devtype "cxl_decoder_root", it + (RO) When a CXL decoder is of devtype "cxl_decoder_root", it represents a fixed memory window identified by platform firmware. A fixed window may only support a subset of memory types. The 'cap_*' attributes indicate whether persistent memory, volatile memory, accelerator memory, and / or expander memory may be mapped behind this decoder's memory window. + What: /sys/bus/cxl/devices/decoderX.Y/target_type Date: June, 2021 KernelVersion: v5.14 Contact: [email protected] Description: - When a CXL decoder is of devtype "cxl_decoder_switch", it can - optionally decode either accelerator memory (type-2) or expander - memory (type-3). The 'target_type' attribute indicates the - current setting which may dynamically change based on what + (RO) When a CXL decoder is of devtype "cxl_decoder_switch", it + can optionally decode either accelerator memory (type-2) or + expander memory (type-3). The 'target_type' attribute indicates + the current setting which may dynamically change based on what memory regions are activated in this decode hierarchy. + + +What: /sys/bus/cxl/devices/endpointX/CDAT +Date: July, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RO) If this sysfs entry is not present no DOE mailbox was + found to support CDAT data. If it is present and the length of + the data is 0 reading the CDAT data failed. Otherwise the CDAT + data is reported. + + +What: /sys/bus/cxl/devices/decoderX.Y/mode +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) When a CXL decoder is of devtype "cxl_decoder_endpoint" it + translates from a host physical address range, to a device local + address range. Device-local address ranges are further split + into a 'ram' (volatile memory) range and 'pmem' (persistent + memory) range. The 'mode' attribute emits one of 'ram', 'pmem', + 'mixed', or 'none'. The 'mixed' indication is for error cases + when a decoder straddles the volatile/persistent partition + boundary, and 'none' indicates the decoder is not actively + decoding, or no DPA allocation policy has been set. + + 'mode' can be written, when the decoder is in the 'disabled' + state, with either 'ram' or 'pmem' to set the boundaries for the + next allocation. + + +What: /sys/bus/cxl/devices/decoderX.Y/dpa_resource +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RO) When a CXL decoder is of devtype "cxl_decoder_endpoint", + and its 'dpa_size' attribute is non-zero, this attribute + indicates the device physical address (DPA) base address of the + allocation. + + +What: /sys/bus/cxl/devices/decoderX.Y/dpa_size +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) When a CXL decoder is of devtype "cxl_decoder_endpoint" it + translates from a host physical address range, to a device local + address range. The range, base address plus length in bytes, of + DPA allocated to this decoder is conveyed in these 2 attributes. + Allocations can be mutated as long as the decoder is in the + disabled state. A write to 'dpa_size' releases the previous DPA + allocation and then attempts to allocate from the free capacity + in the device partition referred to by 'decoderX.Y/mode'. + Allocate and free requests can only be performed on the highest + instance number disabled decoder with non-zero size. I.e. + allocations are enforced to occur in increasing 'decoderX.Y/id' + order and frees are enforced to occur in decreasing + 'decoderX.Y/id' order. + + +What: /sys/bus/cxl/devices/decoderX.Y/interleave_ways +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RO) The number of targets across which this decoder's host + physical address (HPA) memory range is interleaved. The device + maps every Nth block of HPA (of size == + 'interleave_granularity') to consecutive DPA addresses. The + decoder's position in the interleave is determined by the + device's (endpoint or switch) switch ancestry. For root + decoders their interleave is specified by platform firmware and + they only specify a downstream target order for host bridges. + + +What: /sys/bus/cxl/devices/decoderX.Y/interleave_granularity +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RO) The number of consecutive bytes of host physical address + space this decoder claims at address N before the decode rotates + to the next target in the interleave at address N + + interleave_granularity (assuming N is aligned to + interleave_granularity). + + +What: /sys/bus/cxl/devices/decoderX.Y/create_pmem_region +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) Write a string in the form 'regionZ' to start the process + of defining a new persistent memory region (interleave-set) + within the decode range bounded by root decoder 'decoderX.Y'. + The value written must match the current value returned from + reading this attribute. An atomic compare exchange operation is + done on write to assign the requested id to a region and + allocate the region-id for the next creation attempt. EBUSY is + returned if the region name written does not match the current + cached value. + + +What: /sys/bus/cxl/devices/decoderX.Y/delete_region +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (WO) Write a string in the form 'regionZ' to delete that region, + provided it is currently idle / not bound to a driver. + + +What: /sys/bus/cxl/devices/regionZ/uuid +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) Write a unique identifier for the region. This field must + be set for persistent regions and it must not conflict with the + UUID of another region. + + +What: /sys/bus/cxl/devices/regionZ/interleave_granularity +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) Set the number of consecutive bytes each device in the + interleave set will claim. The possible interleave granularity + values are determined by the CXL spec and the participating + devices. + + +What: /sys/bus/cxl/devices/regionZ/interleave_ways +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) Configures the number of devices participating in the + region is set by writing this value. Each device will provide + 1/interleave_ways of storage for the region. + + +What: /sys/bus/cxl/devices/regionZ/size +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) System physical address space to be consumed by the region. + When written trigger the driver to allocate space out of the + parent root decoder's address space. When read the size of the + address space is reported and should match the span of the + region's resource attribute. Size shall be set after the + interleave configuration parameters. Once set it cannot be + changed, only freed by writing 0. The kernel makes no guarantees + that data is maintained over an address space freeing event, and + there is no guarantee that a free followed by an allocate + results in the same address being allocated. + + +What: /sys/bus/cxl/devices/regionZ/resource +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RO) A region is a contiguous partition of a CXL root decoder + address space. Region capacity is allocated by writing to the + size attribute, the resulting physical address space determined + by the driver is reflected here. It is therefore not useful to + read this before writing a value to the size attribute. + + +What: /sys/bus/cxl/devices/regionZ/target[0..N] +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) Write an endpoint decoder object name to 'targetX' where X + is the intended position of the endpoint device in the region + interleave and N is the 'interleave_ways' setting for the + region. ENXIO is returned if the write results in an impossible + to map decode scenario, like the endpoint is unreachable at that + position relative to the root decoder interleave. EBUSY is + returned if the position in the region is already occupied, or + if the region is not in a state to accept interleave + configuration changes. EINVAL is returned if the object name is + not an endpoint decoder. Once all positions have been + successfully written a final validation for decode conflicts is + performed before activating the region. + + +What: /sys/bus/cxl/devices/regionZ/commit +Date: May, 2022 +KernelVersion: v5.20 +Contact: [email protected] +Description: + (RW) Write a boolean 'true' string value to this attribute to + trigger the region to transition from the software programmed + state to the actively decoding in hardware state. The commit + operation in addition to validating that the region is in proper + configured state, validates that the decoders are being + committed in spec mandated order (last committed decoder id + + 1), and checks that the hardware accepts the commit request. + Reading this value indicates whether the region is committed or + not. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 54a9756f2dad..db5de5f0b9d3 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1735,12 +1735,13 @@ hugetlb_free_vmemmap= [KNL] Reguires CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP enabled. + Control if HugeTLB Vmemmap Optimization (HVO) is enabled. Allows heavy hugetlb users to free up some more memory (7 * PAGE_SIZE for each 2MB hugetlb page). - Format: { [oO][Nn]/Y/y/1 | [oO][Ff]/N/n/0 (default) } + Format: { on | off (default) } - [oO][Nn]/Y/y/1: enable the feature - [oO][Ff]/N/n/0: disable the feature + on: enable HVO + off: disable HVO Built with CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON=y, the default is on. diff --git a/Documentation/admin-guide/mm/hugetlbpage.rst b/Documentation/admin-guide/mm/hugetlbpage.rst index a90330d0a837..8e2727dc18d4 100644 --- a/Documentation/admin-guide/mm/hugetlbpage.rst +++ b/Documentation/admin-guide/mm/hugetlbpage.rst @@ -164,8 +164,8 @@ default_hugepagesz will all result in 256 2M huge pages being allocated. Valid default huge page size is architecture dependent. hugetlb_free_vmemmap - When CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP is set, this enables optimizing - unused vmemmap pages associated with each HugeTLB page. + When CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP is set, this enables HugeTLB + Vmemmap Optimization (HVO). When multiple huge page sizes are supported, ``/proc/sys/vm/nr_hugepages`` indicates the current number of pre-allocated huge pages of the default size. diff --git a/Documentation/admin-guide/mm/memory-hotplug.rst b/Documentation/admin-guide/mm/memory-hotplug.rst index 0f56ecd8ac05..a3c9e8ad8fa0 100644 --- a/Documentation/admin-guide/mm/memory-hotplug.rst +++ b/Documentation/admin-guide/mm/memory-hotplug.rst @@ -653,8 +653,8 @@ block might fail: - Concurrent activity that operates on the same physical memory area, such as allocating gigantic pages, can result in temporary offlining failures. -- Out of memory when dissolving huge pages, especially when freeing unused - vmemmap pages associated with each hugetlb page is enabled. +- Out of memory when dissolving huge pages, especially when HugeTLB Vmemmap + Optimization (HVO) is enabled. Offlining code may be able to migrate huge page contents, but may not be able to dissolve the source huge page because it fails allocating (unmovable) pages diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst index f74f722ad702..9b833e439f09 100644 --- a/Documentation/admin-guide/sysctl/vm.rst +++ b/Documentation/admin-guide/sysctl/vm.rst @@ -569,8 +569,7 @@ This knob is not available when the size of 'struct page' (a structure defined in include/linux/mm_types.h) is not power of two (an unusual system config could result in this). -Enable (set to 1) or disable (set to 0) the feature of optimizing vmemmap pages -associated with each HugeTLB page. +Enable (set to 1) or disable (set to 0) HugeTLB Vmemmap Optimization (HVO). Once enabled, the vmemmap pages of subsequent allocation of HugeTLB pages from buddy allocator will be optimized (7 pages per 2MB HugeTLB page and 4095 pages diff --git a/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml b/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml index 0f628b088cec..14486aee97b4 100644 --- a/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml @@ -19,8 +19,14 @@ properties: oneOf: - enum: - x-powers,axp209-gpio + - x-powers,axp221-gpio - x-powers,axp813-gpio - items: + - enum: + - x-powers,axp223-gpio + - x-powers,axp809-gpio + - const: x-powers,axp221-gpio + - items: - const: x-powers,axp803-gpio - const: x-powers,axp813-gpio diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml index 0681b9a3965f..d19d65c870aa 100644 --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml @@ -46,6 +46,7 @@ properties: - allwinner,sun8i-v3s-pinctrl - allwinner,sun9i-a80-pinctrl - allwinner,sun9i-a80-r-pinctrl + - allwinner,sun20i-d1-pinctrl - allwinner,sun50i-a64-pinctrl - allwinner,sun50i-a64-r-pinctrl - allwinner,sun50i-a100-pinctrl @@ -80,9 +81,6 @@ properties: - const: hosc - const: losc - resets: - maxItems: 1 - gpio-controller: true interrupt-controller: true gpio-line-names: true @@ -185,6 +183,18 @@ allOf: properties: compatible: enum: + - allwinner,sun20i-d1-pinctrl + + then: + properties: + interrupts: + minItems: 6 + maxItems: 6 + + - if: + properties: + compatible: + enum: - allwinner,sun9i-a80-pinctrl then: diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml index 47a56b83a610..7a11beb8f222 100644 --- a/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml @@ -152,7 +152,7 @@ examples: pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uid>, <&pinmux_uid>; - uid { + button-uid { label = "UID"; linux,code = <102>; gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8186.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8186.yaml index 8a2bb8608291..1eeb885ce0c6 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8186.yaml +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8186.yaml @@ -28,6 +28,8 @@ properties: gpio-ranges: maxItems: 1 + gpio-line-names: true + reg: description: | Physical address base for gpio base registers. There are 8 different GPIO @@ -105,31 +107,8 @@ patternProperties: drive-strength: enum: [2, 4, 6, 8, 10, 12, 14, 16] - mediatek,drive-strength-adv: - description: | - Describe the specific driving setup property. - For I2C pins, the existing generic driving setup can only support - 2/4/6/8/10/12/14/16mA driving. But in specific driving setup, they - can support 0.125/0.25/0.5/1mA adjustment. If we enable specific - driving setup, the existing generic setup will be disabled. - The specific driving setup is controlled by E1E0EN. - When E1=0/E0=0, the strength is 0.125mA. - When E1=0/E0=1, the strength is 0.25mA. - When E1=1/E0=0, the strength is 0.5mA. - When E1=1/E0=1, the strength is 1mA. - EN is used to enable or disable the specific driving setup. - Valid arguments are described as below: - 0: (E1, E0, EN) = (0, 0, 0) - 1: (E1, E0, EN) = (0, 0, 1) - 2: (E1, E0, EN) = (0, 1, 0) - 3: (E1, E0, EN) = (0, 1, 1) - 4: (E1, E0, EN) = (1, 0, 0) - 5: (E1, E0, EN) = (1, 0, 1) - 6: (E1, E0, EN) = (1, 1, 0) - 7: (E1, E0, EN) = (1, 1, 1) - So the valid arguments are from 0 to 7. - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2, 3, 4, 5, 6, 7] + drive-strength-microamp: + enum: [125, 250, 500, 1000] bias-pull-down: oneOf: @@ -291,7 +270,7 @@ examples: pinmux = <PINMUX_GPIO127__FUNC_SCL0>, <PINMUX_GPIO128__FUNC_SDA0>; bias-pull-up = <MTK_PULL_SET_RSEL_001>; - mediatek,drive-strength-adv = <7>; + drive-strength-microamp = <1000>; }; }; }; diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml index c90a132fbc79..e0e943e5b874 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml @@ -80,46 +80,30 @@ patternProperties: dt-bindings/pinctrl/mt65xx.h. It can only support 2/4/6/8/10/12/14/16mA in mt8192. enum: [2, 4, 6, 8, 10, 12, 14, 16] - mediatek,drive-strength-adv: - description: | - Describe the specific driving setup property. - For I2C pins, the existing generic driving setup can only support - 2/4/6/8/10/12/14/16mA driving. But in specific driving setup, they - can support 0.125/0.25/0.5/1mA adjustment. If we enable specific - driving setup, the existing generic setup will be disabled. - The specific driving setup is controlled by E1E0EN. - When E1=0/E0=0, the strength is 0.125mA. - When E1=0/E0=1, the strength is 0.25mA. - When E1=1/E0=0, the strength is 0.5mA. - When E1=1/E0=1, the strength is 1mA. - EN is used to enable or disable the specific driving setup. - Valid arguments are described as below: - 0: (E1, E0, EN) = (0, 0, 0) - 1: (E1, E0, EN) = (0, 0, 1) - 2: (E1, E0, EN) = (0, 1, 0) - 3: (E1, E0, EN) = (0, 1, 1) - 4: (E1, E0, EN) = (1, 0, 0) - 5: (E1, E0, EN) = (1, 0, 1) - 6: (E1, E0, EN) = (1, 1, 0) - 7: (E1, E0, EN) = (1, 1, 1) - So the valid arguments are from 0 to 7. - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2, 3, 4, 5, 6, 7] - - mediatek,pull-up-adv: - description: | - Pull up settings for 2 pull resistors, R0 and R1. User can - configure those special pins. Valid arguments are described as below: - 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled. - 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled. - 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled. - 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled. - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2, 3] - - bias-pull-down: true - - bias-pull-up: true + drive-strength-microamp: + enum: [125, 250, 500, 1000] + + bias-pull-down: + oneOf: + - type: boolean + description: normal pull down. + - enum: [100, 101, 102, 103] + description: PUPD/R1/R0 pull down type. See MTK_PUPD_SET_R1R0_ + defines in dt-bindings/pinctrl/mt65xx.h. + - enum: [200, 201, 202, 203] + description: RSEL pull down type. See MTK_PULL_SET_RSEL_ + defines in dt-bindings/pinctrl/mt65xx.h. + + bias-pull-up: + oneOf: + - type: boolean + description: normal pull up. + - enum: [100, 101, 102, 103] + description: PUPD/R1/R0 pull up type. See MTK_PUPD_SET_R1R0_ + defines in dt-bindings/pinctrl/mt65xx.h. + - enum: [200, 201, 202, 203] + description: RSEL pull up type. See MTK_PULL_SET_RSEL_ + defines in dt-bindings/pinctrl/mt65xx.h. bias-disable: true diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml index c5b755514c46..66fe17e9e4d3 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8195.yaml @@ -29,6 +29,8 @@ properties: description: gpio valid number range. maxItems: 1 + gpio-line-names: true + reg: description: | Physical address base for gpio base registers. There are 8 GPIO @@ -49,7 +51,7 @@ properties: description: The interrupt outputs to sysirq. maxItems: 1 - mediatek,rsel_resistance_in_si_unit: + mediatek,rsel-resistance-in-si-unit: type: boolean description: | Identifying i2c pins pull up/down type which is RSEL. It can support @@ -98,31 +100,8 @@ patternProperties: drive-strength: enum: [2, 4, 6, 8, 10, 12, 14, 16] - mediatek,drive-strength-adv: - description: | - Describe the specific driving setup property. - For I2C pins, the existing generic driving setup can only support - 2/4/6/8/10/12/14/16mA driving. But in specific driving setup, they - can support 0.125/0.25/0.5/1mA adjustment. If we enable specific - driving setup, the existing generic setup will be disabled. - The specific driving setup is controlled by E1E0EN. - When E1=0/E0=0, the strength is 0.125mA. - When E1=0/E0=1, the strength is 0.25mA. - When E1=1/E0=0, the strength is 0.5mA. - When E1=1/E0=1, the strength is 1mA. - EN is used to enable or disable the specific driving setup. - Valid arguments are described as below: - 0: (E1, E0, EN) = (0, 0, 0) - 1: (E1, E0, EN) = (0, 0, 1) - 2: (E1, E0, EN) = (0, 1, 0) - 3: (E1, E0, EN) = (0, 1, 1) - 4: (E1, E0, EN) = (1, 0, 0) - 5: (E1, E0, EN) = (1, 0, 1) - 6: (E1, E0, EN) = (1, 1, 0) - 7: (E1, E0, EN) = (1, 1, 1) - So the valid arguments are from 0 to 7. - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2, 3, 4, 5, 6, 7] + drive-strength-microamp: + enum: [125, 250, 500, 1000] bias-pull-down: oneOf: @@ -142,7 +121,7 @@ patternProperties: "MTK_PUPD_SET_R1R0_11" define in mt8195. For pull down type is RSEL, it can add RSEL define & resistance value(ohm) to set different resistance by identifying property - "mediatek,rsel_resistance_in_si_unit". + "mediatek,rsel-resistance-in-si-unit". It can support "MTK_PULL_SET_RSEL_000" & "MTK_PULL_SET_RSEL_001" & "MTK_PULL_SET_RSEL_010" & "MTK_PULL_SET_RSEL_011" & "MTK_PULL_SET_RSEL_100" & "MTK_PULL_SET_RSEL_101" @@ -161,7 +140,7 @@ patternProperties: }; An example of using si unit resistance value(ohm): &pio { - mediatek,rsel_resistance_in_si_unit; + mediatek,rsel-resistance-in-si-unit; } pincontroller { i2c0_pin { @@ -190,7 +169,7 @@ patternProperties: "MTK_PUPD_SET_R1R0_11" define in mt8195. For pull up type is RSEL, it can add RSEL define & resistance value(ohm) to set different resistance by identifying property - "mediatek,rsel_resistance_in_si_unit". + "mediatek,rsel-resistance-in-si-unit". It can support "MTK_PULL_SET_RSEL_000" & "MTK_PULL_SET_RSEL_001" & "MTK_PULL_SET_RSEL_010" & "MTK_PULL_SET_RSEL_011" & "MTK_PULL_SET_RSEL_100" & "MTK_PULL_SET_RSEL_101" @@ -209,7 +188,7 @@ patternProperties: }; An example of using si unit resistance value(ohm): &pio { - mediatek,rsel_resistance_in_si_unit; + mediatek,rsel-resistance-in-si-unit; } pincontroller { i2c0-pins { @@ -302,7 +281,7 @@ examples: pinmux = <PINMUX_GPIO8__FUNC_SDA0>, <PINMUX_GPIO9__FUNC_SCL0>; bias-disable; - mediatek,drive-strength-adv = <7>; + drive-strength-microamp = <1000>; }; }; }; diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml new file mode 100644 index 000000000000..e03530091478 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,msm8909-tlmm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. MSM8909 TLMM block + +maintainers: + - Stephan Gerhold <[email protected]> + +description: | + This binding describes the Top Level Mode Multiplexer (TLMM) block found + in the MSM8909 platform. + +allOf: + - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# + +properties: + compatible: + const: qcom,msm8909-tlmm + + reg: + maxItems: 1 + + interrupts: true + interrupt-controller: true + '#interrupt-cells': true + gpio-controller: true + gpio-reserved-ranges: true + '#gpio-cells': true + gpio-ranges: true + wakeup-parent: true + +required: + - compatible + - reg + +additionalProperties: false + +patternProperties: + '-state$': + oneOf: + - $ref: "#/$defs/qcom-msm8909-tlmm-state" + - patternProperties: + ".*": + $ref: "#/$defs/qcom-msm8909-tlmm-state" + +$defs: + qcom-msm8909-tlmm-state: + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state" + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([0-9]|[1-9][0-9]|10[0-9]|11[0-7])$" + - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, + sdc2_data, qdsd_clk, qdsd_cmd, qdsd_data0, qdsd_data1, + qdsd_data2, qdsd_data3 ] + minItems: 1 + maxItems: 16 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + enum: [ adsp_ext, atest_bbrx0, atest_bbrx1, atest_char, atest_char0, + atest_char1, atest_char2, atest_char3, atest_combodac, + atest_gpsadc0, atest_gpsadc1, atest_wlan0, atest_wlan1, + bimc_dte0, bimc_dte1, blsp_i2c1, blsp_i2c2, blsp_i2c3, + blsp_i2c4, blsp_i2c5, blsp_i2c6, blsp_spi1, blsp_spi1_cs1, + blsp_spi1_cs2, blsp_spi1_cs3, blsp_spi2, blsp_spi2_cs1, + blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3, blsp_spi3_cs1, + blsp_spi3_cs2, blsp_spi3_cs3, blsp_spi4, blsp_spi5, blsp_spi6, + blsp_uart1, blsp_uart2, blsp_uim1, blsp_uim2, cam_mclk, + cci_async, cci_timer0, cci_timer1, cci_timer2, cdc_pdm0, + dbg_out, dmic0_clk, dmic0_data, ebi0_wrcdc, ebi2_a, ebi2_lcd, + ext_lpass, gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, + gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b, gcc_plltest, gpio, + gsm0_tx, ldo_en, ldo_update, m_voc, mdp_vsync, modem_tsync, + nav_pps, nav_tsync, pa_indicator, pbs0, pbs1, pbs2, + pri_mi2s_data0_a, pri_mi2s_data0_b, pri_mi2s_data1_a, + pri_mi2s_data1_b, pri_mi2s_mclk_a, pri_mi2s_mclk_b, + pri_mi2s_sck_a, pri_mi2s_sck_b, pri_mi2s_ws_a, pri_mi2s_ws_b, + prng_rosc, pwr_crypto_enabled_a, pwr_crypto_enabled_b, + pwr_modem_enabled_a, pwr_modem_enabled_b, pwr_nav_enabled_a, + pwr_nav_enabled_b, qdss_cti_trig_in_a0, qdss_cti_trig_in_a1, + qdss_cti_trig_in_b0, qdss_cti_trig_in_b1, qdss_cti_trig_out_a0, + qdss_cti_trig_out_a1, qdss_cti_trig_out_b0, + qdss_cti_trig_out_b1, qdss_traceclk_a, qdss_tracectl_a, + qdss_tracedata_a, qdss_tracedata_b, sd_write, sec_mi2s, + smb_int, ssbi0, ssbi1, uim1_clk, uim1_data, uim1_present, + uim1_reset, uim2_clk, uim2_data, uim2_present, uim2_reset, + uim3_clk, uim3_data, uim3_present, uim3_reset, uim_batt, + wcss_bt, wcss_fm, wcss_wlan ] + + bias-disable: true + bias-pull-down: true + bias-pull-up: true + drive-strength: true + input-enable: true + output-high: true + output-low: true + + required: + - pins + - function + + additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + + pinctrl@1000000 { + compatible = "qcom,msm8909-tlmm"; + reg = <0x1000000 0x300000>; + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 117>; + interrupt-controller; + #interrupt-cells = <2>; + + gpio-wo-subnode-state { + pins = "gpio1"; + function = "gpio"; + }; + + uart-w-subnodes-state { + rx { + pins = "gpio4"; + function = "blsp_uart1"; + bias-pull-up; + }; + + tx { + pins = "gpio5"; + function = "blsp_uart1"; + bias-disable; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml index 6f2efc3772cb..694898f382be 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml @@ -52,6 +52,7 @@ properties: - qcom,pmi8998-gpio - qcom,pmk8350-gpio - qcom,pmm8155au-gpio + - qcom,pmp8074-gpio - qcom,pmr735a-gpio - qcom,pmr735b-gpio - qcom,pms405-gpio @@ -158,6 +159,7 @@ allOf: compatible: contains: enum: + - qcom,pm8226-gpio - qcom,pm8350b-gpio - qcom,pm8950-gpio then: @@ -233,6 +235,7 @@ allOf: - qcom,pm8150b-gpio - qcom,pm8150l-gpio - qcom,pmc8180c-gpio + - qcom,pmp8074-gpio - qcom,pms405-gpio then: properties: @@ -415,6 +418,7 @@ $defs: - gpio1-gpio10 for pmi8994 - gpio1-gpio4 for pmk8350 - gpio1-gpio10 for pmm8155au + - gpio1-gpio12 for pmp8074 (holes on gpio1 and gpio12) - gpio1-gpio4 for pmr735a - gpio1-gpio4 for pmr735b - gpio1-gpio12 for pms405 (holes on gpio1, gpio9 diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml index d32ee32776e8..33d1d37fdf6d 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml @@ -19,6 +19,11 @@ properties: compatible: const: qcom,sc7280-lpass-lpi-pinctrl + qcom,adsp-bypass-mode: + description: + Tells ADSP is in bypass mode. + type: boolean + reg: minItems: 2 maxItems: 2 diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml new file mode 100644 index 000000000000..3908807a8339 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,sm6375-tlmm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. SM6375 TLMM block + +maintainers: + - Konrad Dybcio <[email protected]> + +description: | + This binding describes the Top Level Mode Multiplexer (TLMM) block found + in the SM6375 platform. + +allOf: + - $ref: "pinctrl.yaml#" + - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# + +properties: + compatible: + const: qcom,sm6375-tlmm + + reg: + maxItems: 1 + + interrupts: true + interrupt-controller: true + '#interrupt-cells': true + gpio-controller: true + gpio-reserved-ranges: true + '#gpio-cells': true + gpio-ranges: true + wakeup-parent: true + +required: + - compatible + - reg + +additionalProperties: false + +patternProperties: + '-state$': + oneOf: + - $ref: "#/$defs/qcom-sm6375-tlmm-state" + - patternProperties: + ".*": + $ref: "#/$defs/qcom-sm6375-tlmm-state" + +$defs: + qcom-sm6375-tlmm-state: + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state" + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9]|15[0-6])$" + - enum: [ ufs_reset, sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, + sdc2_cmd, sdc2_data ] + minItems: 1 + maxItems: 36 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + + enum: [ adsp_ext, agera_pll, atest_char, atest_char0, atest_char1, + atest_char2, atest_char3, atest_tsens, atest_tsens2, + atest_usb1, atest_usb10, atest_usb11, atest_usb12, + atest_usb13, atest_usb2, atest_usb20, atest_usb21, + atest_usb22, atest_usb23, audio_ref, btfm_slimbus, cam_mclk, + cci_async, cci_i2c, cci_timer0, cci_timer1, cci_timer2, + cci_timer3, cci_timer4, cri_trng, dbg_out, ddr_bist, + ddr_pxi0, ddr_pxi1, ddr_pxi2, ddr_pxi3, dp_hot, edp_lcd, + gcc_gp1, gcc_gp2, gcc_gp3, gp_pdm0, gp_pdm1, gp_pdm2, gpio, + gps_tx, ibi_i3c, jitter_bist, ldo_en, ldo_update, lpass_ext, + m_voc, mclk, mdp_vsync, mdp_vsync0, mdp_vsync1, mdp_vsync2, + mdp_vsync3, mi2s_0, mi2s_1, mi2s_2, mss_lte, nav_gpio, + nav_pps, pa_indicator, phase_flag0, phase_flag1, phase_flag10, + phase_flag11, phase_flag12, phase_flag13, phase_flag14, + phase_flag15, phase_flag16, phase_flag17, phase_flag18, + phase_flag19, phase_flag2, phase_flag20, phase_flag21, + phase_flag22, phase_flag23, phase_flag24, phase_flag25, + phase_flag26, phase_flag27, phase_flag28, phase_flag29, + phase_flag3, phase_flag30, phase_flag31, phase_flag4, + phase_flag5, phase_flag6, phase_flag7, phase_flag8, + phase_flag9, pll_bist, pll_bypassnl, pll_clk, pll_reset, + prng_rosc0, prng_rosc1, prng_rosc2, prng_rosc3, qdss_cti, + qdss_gpio, qdss_gpio0, qdss_gpio1, qdss_gpio10, qdss_gpio11, + qdss_gpio12, qdss_gpio13, qdss_gpio14, qdss_gpio15, + qdss_gpio2, qdss_gpio3, qdss_gpio4, qdss_gpio5, qdss_gpio6, + qdss_gpio7, qdss_gpio8, qdss_gpio9, qlink0_enable, + qlink0_request, qlink0_wmss, qlink1_enable, qlink1_request, + qlink1_wmss, qup00, qup01, qup02, qup10, qup11_f1, qup11_f2, + qup12, qup13_f1, qup13_f2, qup14, sd_write, sdc1_tb, sdc2_tb, + sp_cmu, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3, tsense_pwm1, + tsense_pwm2, uim1_clk, uim1_data, uim1_present, uim1_reset, + uim2_clk, uim2_data, uim2_present, uim2_reset, usb2phy_ac, + usb_phy, vfr_1, vsense_trigger, wlan1_adc0, wlan1_adc1, + wlan2_adc0, wlan2_adc1 ] + + + bias-disable: true + bias-pull-down: true + bias-pull-up: true + drive-strength: true + input-enable: true + output-high: true + output-low: true + + required: + - pins + - function + + additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + pinctrl@500000 { + compatible = "qcom,sm6375-tlmm"; + reg = <0x00500000 0x800000>; + interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&tlmm 0 0 157>; + + gpio-wo-subnode-state { + pins = "gpio1"; + function = "gpio"; + }; + + uart-w-subnodes-state { + rx { + pins = "gpio18"; + function = "qup13_f2"; + bias-pull-up; + }; + + tx { + pins = "gpio19"; + function = "qup13_f2"; + bias-disable; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,pfc.yaml index 2a57df75d832..4fc758fea7e6 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc.yaml +++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc.yaml @@ -45,6 +45,7 @@ properties: - renesas,pfc-r8a77995 # R-Car D3 - renesas,pfc-r8a779a0 # R-Car V3U - renesas,pfc-r8a779f0 # R-Car S4-8 + - renesas,pfc-r8a779g0 # R-Car V4H - renesas,pfc-sh73a0 # SH-Mobile AG5 reg: diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml new file mode 100644 index 000000000000..eac6245db7dc --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzv2m-pinctrl.yaml @@ -0,0 +1,170 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/renesas,rzv2m-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/V2M combined Pin and GPIO controller + +maintainers: + - Geert Uytterhoeven <[email protected]> + - Phil Edworthy <[email protected]> + +description: + The Renesas RZ/V2M SoC features a combined Pin and GPIO controller. + Pin multiplexing and GPIO configuration is performed on a per-pin basis. + Each port features up to 16 pins, each of them configurable for GPIO function + (port mode) or in alternate function mode. + Up to 8 different alternate function modes exist for each single pin. + +properties: + compatible: + const: renesas,r9a09g011-pinctrl # RZ/V2M + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + description: + The first cell contains the global GPIO port index, constructed using the + RZV2M_GPIO() helper macro in <dt-bindings/pinctrl/rzv2m-pinctrl.h> and the + second cell represents consumer flag as mentioned in ../gpio/gpio.txt + E.g. "RZV2M_GPIO(8, 1)" for P8_1. + + gpio-ranges: + maxItems: 1 + + interrupts: + description: INEXINT[0..38] corresponding to individual pin inputs. + maxItems: 39 + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + +additionalProperties: + anyOf: + - type: object + allOf: + - $ref: pincfg-node.yaml# + - $ref: pinmux-node.yaml# + + description: + Pin controller client devices use pin configuration subnodes (children + and grandchildren) for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + phandle: true + pinmux: + description: + Values are constructed from GPIO port number, pin number, and + alternate function configuration number using the RZV2M_PORT_PINMUX() + helper macro in <dt-bindings/pinctrl/rzv2m-pinctrl.h>. + pins: true + bias-disable: true + bias-pull-down: true + bias-pull-up: true + drive-strength-microamp: + # Superset of supported values + enum: [ 1600, 1800, 2000, 3200, 3800, 4000, 6400, 7800, 8000, + 9000, 9600, 11000, 12000, 13000, 18000 ] + slew-rate: + description: 0 is slow slew rate, 1 is fast slew rate + enum: [ 0, 1 ] + gpio-hog: true + gpios: true + output-high: true + output-low: true + line-name: true + + - type: object + properties: + phandle: true + + additionalProperties: + $ref: "#/additionalProperties/anyOf/0" + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + - reg + - gpio-controller + - '#gpio-cells' + - gpio-ranges + - interrupts + - clocks + - power-domains + - resets + +examples: + - | + #include <dt-bindings/pinctrl/rzv2m-pinctrl.h> + #include <dt-bindings/clock/r9a09g011-cpg.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + pinctrl: pinctrl@b6250000 { + compatible = "renesas,r9a09g011-pinctrl"; + reg = <0xb6250000 0x800>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl 0 0 352>; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A09G011_PFC_PCLK>; + resets = <&cpg R9A09G011_PFC_PRESETN>; + power-domains = <&cpg>; + + i2c2_pins: i2c2 { + pinmux = <RZV2M_PORT_PINMUX(3, 8, 2)>, /* SDA */ + <RZV2M_PORT_PINMUX(3, 9, 2)>; /* SCL */ + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml index 335ffc1353b5..d35dcc4f0242 100644 --- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml @@ -59,6 +59,7 @@ properties: patternProperties: '^gpio@[0-9a-f]*$': type: object + additionalProperties: false properties: gpio-controller: true '#gpio-cells': @@ -68,8 +69,7 @@ patternProperties: maxItems: 1 clocks: maxItems: 1 - reset: - minItems: 1 + resets: maxItems: 1 gpio-ranges: minItems: 1 diff --git a/Documentation/devicetree/bindings/pinctrl/sunplus,sp7021-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/sunplus,sp7021-pinctrl.yaml index d8e75b3e64f1..15092fdd4b5b 100644 --- a/Documentation/devicetree/bindings/pinctrl/sunplus,sp7021-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/sunplus,sp7021-pinctrl.yaml @@ -288,11 +288,14 @@ required: additionalProperties: false +allOf: + - $ref: "pinctrl.yaml#" + examples: - | #include <dt-bindings/pinctrl/sppctl-sp7021.h> - pinctl@9c000100 { + pinctrl@9c000100 { compatible = "sunplus,sp7021-pctl"; reg = <0x9c000100 0x100>, <0x9c000300 0x100>, <0x9c0032e4 0x1c>, <0x9c000080 0x20>; diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml index 2722dc7bb03d..1e2b9b627b12 100644 --- a/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml @@ -274,6 +274,10 @@ patternProperties: slew-rate: enum: [0, 1] + output-enable: + description: + This will internally disable the tri-state for MIO pins. + drive-strength: description: Selects the drive strength for MIO pins, in mA. diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index 50f834563e19..09d5bfa920f2 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -92,12 +92,33 @@ examples: qcom,ipc = <&apcs 8 0>; qcom,smd-edge = <15>; - rpm-requests { - compatible = "qcom,rpm-msm8974"; - qcom,smd-channels = "rpm_requests"; + rpm-requests { + compatible = "qcom,rpm-msm8916"; + qcom,smd-channels = "rpm_requests"; + + clock-controller { + compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc"; + #clock-cells = <1>; + clocks = <&xo_board>; + clock-names = "xo"; + }; - /* Regulator nodes to follow */ + power-controller { + compatible = "qcom,msm8916-rpmpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmpd_opp_table>; + + rpmpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-1 { + opp-level = <1>; + }; + opp-2 { + opp-level = <2>; + }; + }; }; }; - }; -... + }; + }; diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.yaml index 62bebb5f83bc..9b3efe97f47c 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.yaml @@ -21,7 +21,7 @@ properties: patternProperties: "^.*-edge|rpm$": - type: object + $ref: /schemas/remoteproc/qcom,smd-edge.yaml# description: Each subnode of the SMD node represents a remote subsystem or a remote processor of some sort - or in SMD language an "edge". The name of the diff --git a/Documentation/driver-api/cxl/memory-devices.rst b/Documentation/driver-api/cxl/memory-devices.rst index db476bb170b6..5149ecdc53c7 100644 --- a/Documentation/driver-api/cxl/memory-devices.rst +++ b/Documentation/driver-api/cxl/memory-devices.rst @@ -362,6 +362,14 @@ CXL Core .. kernel-doc:: drivers/cxl/core/mbox.c :doc: cxl mbox +CXL Regions +----------- +.. kernel-doc:: drivers/cxl/core/region.c + :doc: cxl core region + +.. kernel-doc:: drivers/cxl/core/region.c + :identifiers: + External Interfaces =================== diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst index a7173843a294..7fb398649f51 100644 --- a/Documentation/kbuild/kconfig-language.rst +++ b/Documentation/kbuild/kconfig-language.rst @@ -672,7 +672,7 @@ Future kconfig work Work on kconfig is welcomed on both areas of clarifying semantics and on evaluating the use of a full SAT solver for it. A full SAT solver can be desirable to enable more complex dependency mappings and / or queries, -for instance on possible use case for a SAT solver could be that of handling +for instance one possible use case for a SAT solver could be that of handling the current known recursive dependency issues. It is not known if this would address such issues but such evaluation is desirable. If support for a full SAT solver proves too complex or that it cannot address recursive dependency issues diff --git a/Documentation/mm/highmem.rst b/Documentation/mm/highmem.rst index c9887f241c6c..0f731d9196b0 100644 --- a/Documentation/mm/highmem.rst +++ b/Documentation/mm/highmem.rst @@ -60,17 +60,40 @@ list shows them in order of preference of use. This function should be preferred, where feasible, over all the others. These mappings are thread-local and CPU-local, meaning that the mapping - can only be accessed from within this thread and the thread is bound the - CPU while the mapping is active. Even if the thread is preempted (since - preemption is never disabled by the function) the CPU can not be - unplugged from the system via CPU-hotplug until the mapping is disposed. + can only be accessed from within this thread and the thread is bound to the + CPU while the mapping is active. Although preemption is never disabled by + this function, the CPU can not be unplugged from the system via + CPU-hotplug until the mapping is disposed. It's valid to take pagefaults in a local kmap region, unless the context in which the local mapping is acquired does not allow it for other reasons. + As said, pagefaults and preemption are never disabled. There is no need to + disable preemption because, when context switches to a different task, the + maps of the outgoing task are saved and those of the incoming one are + restored. + kmap_local_page() always returns a valid virtual address and it is assumed that kunmap_local() will never fail. + On CONFIG_HIGHMEM=n kernels and for low memory pages this returns the + virtual address of the direct mapping. Only real highmem pages are + temporarily mapped. Therefore, users may call a plain page_address() + for pages which are known to not come from ZONE_HIGHMEM. However, it is + always safe to use kmap_local_page() / kunmap_local(). + + While it is significantly faster than kmap(), for the higmem case it + comes with restrictions about the pointers validity. Contrary to kmap() + mappings, the local mappings are only valid in the context of the caller + and cannot be handed to other contexts. This implies that users must + be absolutely sure to keep the use of the return address local to the + thread which mapped it. + + Most code can be designed to use thread local mappings. User should + therefore try to design their code to avoid the use of kmap() by mapping + pages in the same thread the address will be used and prefer + kmap_local_page(). + Nesting kmap_local_page() and kmap_atomic() mappings is allowed to a certain extent (up to KMAP_TYPE_NR) but their invocations have to be strictly ordered because the map implementation is stack based. See kmap_local_page() kdocs diff --git a/Documentation/mm/vmemmap_dedup.rst b/Documentation/mm/vmemmap_dedup.rst index c9c495f62d12..a4b12ff906c4 100644 --- a/Documentation/mm/vmemmap_dedup.rst +++ b/Documentation/mm/vmemmap_dedup.rst @@ -7,23 +7,25 @@ A vmemmap diet for HugeTLB and Device DAX HugeTLB ======= -The struct page structures (page structs) are used to describe a physical -page frame. By default, there is a one-to-one mapping from a page frame to -it's corresponding page struct. +This section is to explain how HugeTLB Vmemmap Optimization (HVO) works. + +The ``struct page`` structures are used to describe a physical page frame. By +default, there is a one-to-one mapping from a page frame to it's corresponding +``struct page``. HugeTLB pages consist of multiple base page size pages and is supported by many architectures. See Documentation/admin-guide/mm/hugetlbpage.rst for more details. On the x86-64 architecture, HugeTLB pages of size 2MB and 1GB are currently supported. Since the base page size on x86 is 4KB, a 2MB HugeTLB page consists of 512 base pages and a 1GB HugeTLB page consists of 4096 base pages. -For each base page, there is a corresponding page struct. +For each base page, there is a corresponding ``struct page``. -Within the HugeTLB subsystem, only the first 4 page structs are used to -contain unique information about a HugeTLB page. __NR_USED_SUBPAGE provides -this upper limit. The only 'useful' information in the remaining page structs +Within the HugeTLB subsystem, only the first 4 ``struct page`` are used to +contain unique information about a HugeTLB page. ``__NR_USED_SUBPAGE`` provides +this upper limit. The only 'useful' information in the remaining ``struct page`` is the compound_head field, and this field is the same for all tail pages. -By removing redundant page structs for HugeTLB pages, memory can be returned +By removing redundant ``struct page`` for HugeTLB pages, memory can be returned to the buddy allocator for other uses. Different architectures support different HugeTLB pages. For example, the @@ -44,7 +46,7 @@ page. | | 64KB | 2MB | 512MB | 16GB | | +--------------+-----------+-----------+-----------+-----------+-----------+ -When the system boot up, every HugeTLB page has more than one struct page +When the system boot up, every HugeTLB page has more than one ``struct page`` structs which size is (unit: pages):: struct_size = HugeTLB_Size / PAGE_SIZE * sizeof(struct page) / PAGE_SIZE @@ -74,10 +76,10 @@ Where n is how many pte entries which one page can contains. So the value of n is (PAGE_SIZE / sizeof(pte_t)). This optimization only supports 64-bit system, so the value of sizeof(pte_t) -is 8. And this optimization also applicable only when the size of struct page -is a power of two. In most cases, the size of struct page is 64 bytes (e.g. +is 8. And this optimization also applicable only when the size of ``struct page`` +is a power of two. In most cases, the size of ``struct page`` is 64 bytes (e.g. x86-64 and arm64). So if we use pmd level mapping for a HugeTLB page, the -size of struct page structs of it is 8 page frames which size depends on the +size of ``struct page`` structs of it is 8 page frames which size depends on the size of the base page. For the HugeTLB page of the pud level mapping, then:: @@ -86,7 +88,7 @@ For the HugeTLB page of the pud level mapping, then:: = PAGE_SIZE / 8 * 8 (pages) = PAGE_SIZE (pages) -Where the struct_size(pmd) is the size of the struct page structs of a +Where the struct_size(pmd) is the size of the ``struct page`` structs of a HugeTLB page of the pmd level mapping. E.g.: A 2MB HugeTLB page on x86_64 consists in 8 page frames while 1GB @@ -94,7 +96,7 @@ HugeTLB page consists in 4096. Next, we take the pmd level mapping of the HugeTLB page as an example to show the internal implementation of this optimization. There are 8 pages -struct page structs associated with a HugeTLB page which is pmd mapped. +``struct page`` structs associated with a HugeTLB page which is pmd mapped. Here is how things look before optimization:: @@ -122,10 +124,10 @@ Here is how things look before optimization:: +-----------+ The value of page->compound_head is the same for all tail pages. The first -page of page structs (page 0) associated with the HugeTLB page contains the 4 -page structs necessary to describe the HugeTLB. The only use of the remaining -pages of page structs (page 1 to page 7) is to point to page->compound_head. -Therefore, we can remap pages 1 to 7 to page 0. Only 1 page of page structs +page of ``struct page`` (page 0) associated with the HugeTLB page contains the 4 +``struct page`` necessary to describe the HugeTLB. The only use of the remaining +pages of ``struct page`` (page 1 to page 7) is to point to page->compound_head. +Therefore, we can remap pages 1 to 7 to page 0. Only 1 page of ``struct page`` will be used for each HugeTLB page. This will allow us to free the remaining 7 pages to the buddy allocator. @@ -167,13 +169,37 @@ entries that can be cached in a single TLB entry. The contiguous bit is used to increase the mapping size at the pmd and pte (last) level. So this type of HugeTLB page can be optimized only when its -size of the struct page structs is greater than 1 page. +size of the ``struct page`` structs is greater than **1** page. Notice: The head vmemmap page is not freed to the buddy allocator and all tail vmemmap pages are mapped to the head vmemmap page frame. So we can see -more than one struct page struct with PG_head (e.g. 8 per 2 MB HugeTLB page) -associated with each HugeTLB page. The compound_head() can handle this -correctly (more details refer to the comment above compound_head()). +more than one ``struct page`` struct with ``PG_head`` (e.g. 8 per 2 MB HugeTLB +page) associated with each HugeTLB page. The ``compound_head()`` can handle +this correctly. There is only **one** head ``struct page``, the tail +``struct page`` with ``PG_head`` are fake head ``struct page``. We need an +approach to distinguish between those two different types of ``struct page`` so +that ``compound_head()`` can return the real head ``struct page`` when the +parameter is the tail ``struct page`` but with ``PG_head``. The following code +snippet describes how to distinguish between real and fake head ``struct page``. + +.. code-block:: c + + if (test_bit(PG_head, &page->flags)) { + unsigned long head = READ_ONCE(page[1].compound_head); + + if (head & 1) { + if (head == (unsigned long)page + 1) + /* head struct page */ + else + /* tail struct page */ + } else { + /* head struct page */ + } + } + +We can safely access the field of the **page[1]** with ``PG_head`` because the +page is a compound page composed with at least two contiguous pages. +The implementation refers to ``page_fixed_fake_head()``. Device DAX ========== @@ -187,7 +213,7 @@ PMD_SIZE (2M on x86_64) and PUD_SIZE (1G on x86_64). The differences with HugeTLB are relatively minor. -It only use 3 page structs for storing all information as opposed +It only use 3 ``struct page`` for storing all information as opposed to 4 on HugeTLB pages. There's no remapping of vmemmap given that device-dax memory is not part of diff --git a/MAINTAINERS b/MAINTAINERS index b7221f4143cb..9b6c0f0bda14 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1390,10 +1390,14 @@ F: include/uapi/linux/apm_bios.h APPARMOR SECURITY MODULE M: John Johansen <[email protected]> -L: [email protected] (subscribers-only, general discussion) +M: John Johansen <[email protected]> +L: [email protected] (moderated for non-subscribers) S: Supported -W: wiki.apparmor.net +W: apparmor.net +B: https://gitlab.com/apparmor/apparmor-kernel +C: irc://irc.oftc.net/apparmor T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor +T: https://gitlab.com/apparmor/apparmor-kernel.git F: Documentation/admin-guide/LSM/apparmor.rst F: security/apparmor/ @@ -4783,7 +4787,6 @@ L: [email protected] S: Maintained F: Documentation/admin-guide/module-signing.rst F: certs/ -F: scripts/check-blacklist-hashes.awk F: scripts/sign-file.c F: tools/certs/ @@ -16058,6 +16061,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git F: Documentation/devicetree/bindings/pinctrl/ F: Documentation/driver-api/pin-control.rst F: drivers/pinctrl/ +F: include/dt-bindings/pinctrl/ F: include/linux/pinctrl/ PIN CONTROLLER - AMD @@ -129,6 +129,9 @@ endif $(if $(word 2, $(KBUILD_EXTMOD)), \ $(error building multiple external modules is not supported)) +$(foreach x, % :, $(if $(findstring $x, $(KBUILD_EXTMOD)), \ + $(error module directory path cannot contain '$x'))) + # Remove trailing slashes ifneq ($(filter %/, $(KBUILD_EXTMOD)),) KBUILD_EXTMOD := $(shell dirname $(KBUILD_EXTMOD).) @@ -755,8 +758,6 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE KBUILD_CFLAGS += -O2 -else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 -KBUILD_CFLAGS += -O3 else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += -Os endif @@ -1370,16 +1371,21 @@ endif ifneq ($(dtstree),) -%.dtb: include/config/kernel.release scripts_dtc +%.dtb: dtbs_prepare $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ -%.dtbo: include/config/kernel.release scripts_dtc +%.dtbo: dtbs_prepare $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ -PHONY += dtbs dtbs_install dtbs_check -dtbs: include/config/kernel.release scripts_dtc +PHONY += dtbs dtbs_prepare dtbs_install dtbs_check +dtbs: dtbs_prepare $(Q)$(MAKE) $(build)=$(dtstree) +# include/config/kernel.release is actually needed when installing DTBs because +# INSTALL_DTBS_PATH contains $(KERNELRELEASE). However, we do not want to make +# dtbs_install depend on it as dtbs_install may run as root. +dtbs_prepare: include/config/kernel.release scripts_dtc + ifneq ($(filter dtbs_check, $(MAKECMDGOALS)),) export CHECK_DTBS=y dtbs: dt_binding_check diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig index 0016149f9583..e31a8ebc3ecc 100644 --- a/arch/arc/configs/axs101_defconfig +++ b/arch/arc/configs/axs101_defconfig @@ -9,7 +9,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig index 5b031582a1cf..e0e8567f0d75 100644 --- a/arch/arc/configs/axs103_defconfig +++ b/arch/arc/configs/axs103_defconfig @@ -9,7 +9,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig index d4eec39e0112..fcbc952bc75b 100644 --- a/arch/arc/configs/axs103_smp_defconfig +++ b/arch/arc/configs/axs103_smp_defconfig @@ -9,7 +9,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arc/configs/haps_hs_defconfig b/arch/arc/configs/haps_hs_defconfig index 7337cdf4ffdd..d87ad7e88d62 100644 --- a/arch/arc/configs/haps_hs_defconfig +++ b/arch/arc/configs/haps_hs_defconfig @@ -11,7 +11,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EXPERT=y CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set diff --git a/arch/arc/configs/haps_hs_smp_defconfig b/arch/arc/configs/haps_hs_smp_defconfig index bc927221afc0..8d82cdb7f86a 100644 --- a/arch/arc/configs/haps_hs_smp_defconfig +++ b/arch/arc/configs/haps_hs_smp_defconfig @@ -11,7 +11,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arc/configs/hsdk_defconfig b/arch/arc/configs/hsdk_defconfig index aa000075a575..f856b03e0fb5 100644 --- a/arch/arc/configs/hsdk_defconfig +++ b/arch/arc/configs/hsdk_defconfig @@ -9,7 +9,6 @@ CONFIG_NAMESPACES=y # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_RAM=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arc/configs/nsim_700_defconfig b/arch/arc/configs/nsim_700_defconfig index 326f6cde7826..a1ce12bf5b16 100644 --- a/arch/arc/configs/nsim_700_defconfig +++ b/arch/arc/configs/nsim_700_defconfig @@ -11,7 +11,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig index bf39a0091679..ca10f4a2c823 100644 --- a/arch/arc/configs/nsimosci_defconfig +++ b/arch/arc/configs/nsimosci_defconfig @@ -10,7 +10,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig index 7121bd71c543..31b6ec3683c6 100644 --- a/arch/arc/configs/nsimosci_hs_defconfig +++ b/arch/arc/configs/nsimosci_hs_defconfig @@ -10,7 +10,6 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig index f9863b294a70..41a0037f48a5 100644 --- a/arch/arc/configs/nsimosci_hs_smp_defconfig +++ b/arch/arc/configs/nsimosci_hs_smp_defconfig @@ -8,7 +8,6 @@ CONFIG_IKCONFIG_PROC=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set CONFIG_KPROBES=y diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig index a12656ec0072..d93b65008d4a 100644 --- a/arch/arc/configs/tb10x_defconfig +++ b/arch/arc/configs/tb10x_defconfig @@ -14,7 +14,6 @@ CONFIG_INITRAMFS_SOURCE="../tb10x-rootfs.cpio" CONFIG_INITRAMFS_ROOT_UID=2100 CONFIG_INITRAMFS_ROOT_GID=501 # CONFIG_RD_GZIP is not set -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_KALLSYMS_ALL=y # CONFIG_AIO is not set CONFIG_EMBEDDED=y diff --git a/arch/arc/configs/vdk_hs38_defconfig b/arch/arc/configs/vdk_hs38_defconfig index d7c858df520c..0c3b21416819 100644 --- a/arch/arc/configs/vdk_hs38_defconfig +++ b/arch/arc/configs/vdk_hs38_defconfig @@ -4,7 +4,6 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig index 015c1d43889e..f9ad9d3ee702 100644 --- a/arch/arc/configs/vdk_hs38_smp_defconfig +++ b/arch/arc/configs/vdk_hs38_smp_defconfig @@ -4,7 +4,6 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3=y CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arm/boot/dts/imxrt1170-pinfunc.h b/arch/arm/boot/dts/imxrt1170-pinfunc.h new file mode 100644 index 000000000000..3b9fff2f08e1 --- /dev/null +++ b/arch/arm/boot/dts/imxrt1170-pinfunc.h @@ -0,0 +1,1561 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2021 + * Author(s): Jesse Taube <[email protected]> + */ + +#ifndef _DT_BINDINGS_PINCTRL_IMXRT1170_PINFUNC_H +#define _DT_BINDINGS_PINCTRL_IMXRT1170_PINFUNC_H + +#define IMX_PAD_SION 0x40000000 + +/* + * The pin function ID is a tuple of + * <mux_reg conf_reg input_reg mux_mode input_val> + */ + +#define IOMUXC_GPIO_LPSR_00_FLEXCAN3_TX 0x000 0x040 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_00_MIC_CLK 0x000 0x040 0x0 0x1 0x0 +#define IOMUXC_GPIO_LPSR_00_MQS_RIGHT 0x000 0x040 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_00_ARM_CM4_EVENTO 0x000 0x040 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_00_GPIO_MUX6_IO00 0x000 0x040 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_00_LPUART12_TXD 0x000 0x040 0x0B0 0x6 0x0 +#define IOMUXC_GPIO_LPSR_00_SAI4_MCLK 0x000 0x040 0x0C8 0x7 0x0 +#define IOMUXC_GPIO_LPSR_00_GPIO12_IO00 0x000 0x040 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_01_FLEXCAN3_RX 0x004 0x044 0x080 0x0 0x0 +#define IOMUXC_GPIO_LPSR_01_MIC_BITSTREAM0 0x004 0x044 0x0B4 0x1 0x0 +#define IOMUXC_GPIO_LPSR_01_MQS_LEFT 0x004 0x044 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_01_ARM_CM4_EVENTI 0x004 0x044 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_01_GPIO_MUX6_IO01 0x004 0x044 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_01_LPUART12_RXD 0x004 0x044 0x0AC 0x6 0x0 +#define IOMUXC_GPIO_LPSR_01_GPIO12_IO01 0x004 0x044 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_02_GPIO12_IO02 0x008 0x048 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_02_SRC_BOOT_MODE00 0x008 0x048 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_02_LPSPI5_SCK 0x008 0x048 0x098 0x1 0x0 +#define IOMUXC_GPIO_LPSR_02_SAI4_TX_DATA 0x008 0x048 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_02_MQS_RIGHT 0x008 0x048 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_02_GPIO_MUX6_IO02 0x008 0x048 0x0 0x5 0x0 + +#define IOMUXC_GPIO_LPSR_03_SRC_BOOT_MODE01 0x00C 0x04C 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_03_LPSPI5_PCS0 0x00C 0x04C 0x094 0x1 0x0 +#define IOMUXC_GPIO_LPSR_03_SAI4_TX_SYNC 0x00C 0x04C 0x0DC 0x2 0x0 +#define IOMUXC_GPIO_LPSR_03_MQS_LEFT 0x00C 0x04C 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_03_GPIO_MUX6_IO03 0x00C 0x04C 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_03_GPIO12_IO03 0x00C 0x04C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_04_LPI2C5_SDA 0x010 0x050 0x088 0x0 0x0 +#define IOMUXC_GPIO_LPSR_04_LPSPI5_SOUT 0x010 0x050 0x0A0 0x1 0x0 +#define IOMUXC_GPIO_LPSR_04_SAI4_TX_BCLK 0x010 0x050 0x0D8 0x2 0x0 +#define IOMUXC_GPIO_LPSR_04_LPUART12_RTS_B 0x010 0x050 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_04_GPIO_MUX6_IO04 0x010 0x050 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_04_LPUART11_TXD 0x010 0x050 0x0A8 0x6 0x0 +#define IOMUXC_GPIO_LPSR_04_GPIO12_IO04 0x010 0x050 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_05_GPIO12_IO05 0x014 0x054 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_05_LPI2C5_SCL 0x014 0x054 0x084 0x0 0x0 +#define IOMUXC_GPIO_LPSR_05_LPSPI5_SIN 0x014 0x054 0x09C 0x1 0x0 +#define IOMUXC_GPIO_LPSR_05_SAI4_MCLK 0x014 0x054 0x0C8 0x2 0x1 +#define IOMUXC_GPIO_LPSR_05_LPUART12_CTS_B 0x014 0x054 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_05_GPIO_MUX6_IO05 0x014 0x054 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_05_LPUART11_RXD 0x014 0x054 0x0A4 0x6 0x0 +#define IOMUXC_GPIO_LPSR_05_NMI_GLUE_NMI 0x014 0x054 0x0C4 0x7 0x0 + +#define IOMUXC_GPIO_LPSR_06_LPI2C6_SDA 0x018 0x058 0x090 0x0 0x0 +#define IOMUXC_GPIO_LPSR_06_SAI4_RX_DATA 0x018 0x058 0x0D0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_06_LPUART12_TXD 0x018 0x058 0x0B0 0x3 0x1 +#define IOMUXC_GPIO_LPSR_06_LPSPI6_PCS3 0x018 0x058 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_06_GPIO_MUX6_IO06 0x018 0x058 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_06_FLEXCAN3_TX 0x018 0x058 0x0 0x6 0x0 +#define IOMUXC_GPIO_LPSR_06_PIT2_TRIGGER3 0x018 0x058 0x0 0x7 0x0 +#define IOMUXC_GPIO_LPSR_06_LPSPI5_PCS1 0x018 0x058 0x0 0x8 0x0 +#define IOMUXC_GPIO_LPSR_06_GPIO12_IO06 0x018 0x058 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_07_LPI2C6_SCL 0x01C 0x05C 0x08C 0x0 0x0 +#define IOMUXC_GPIO_LPSR_07_SAI4_RX_BCLK 0x01C 0x05C 0x0CC 0x2 0x0 +#define IOMUXC_GPIO_LPSR_07_LPUART12_RXD 0x01C 0x05C 0x0AC 0x3 0x1 +#define IOMUXC_GPIO_LPSR_07_LPSPI6_PCS2 0x01C 0x05C 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_07_GPIO_MUX6_IO07 0x01C 0x05C 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_07_FLEXCAN3_RX 0x01C 0x05C 0x080 0x6 0x1 +#define IOMUXC_GPIO_LPSR_07_PIT2_TRIGGER2 0x01C 0x05C 0x0 0x7 0x0 +#define IOMUXC_GPIO_LPSR_07_LPSPI5_PCS2 0x01C 0x05C 0x0 0x8 0x0 +#define IOMUXC_GPIO_LPSR_07_GPIO12_IO07 0x01C 0x05C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_08_GPIO12_IO08 0x020 0x060 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_08_LPUART11_TXD 0x020 0x060 0x0A8 0x0 0x1 +#define IOMUXC_GPIO_LPSR_08_FLEXCAN3_TX 0x020 0x060 0x0 0x1 0x0 +#define IOMUXC_GPIO_LPSR_08_SAI4_RX_SYNC 0x020 0x060 0x0D4 0x2 0x0 +#define IOMUXC_GPIO_LPSR_08_MIC_CLK 0x020 0x060 0x0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_08_LPSPI6_PCS1 0x020 0x060 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_08_GPIO_MUX6_IO08 0x020 0x060 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_08_LPI2C5_SDA 0x020 0x060 0x088 0x6 0x1 +#define IOMUXC_GPIO_LPSR_08_PIT2_TRIGGER1 0x020 0x060 0x0 0x7 0x0 +#define IOMUXC_GPIO_LPSR_08_LPSPI5_PCS3 0x020 0x060 0x0 0x8 0x0 + +#define IOMUXC_GPIO_LPSR_09_GPIO12_IO09 0x024 0x064 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_09_LPUART11_RXD 0x024 0x064 0x0A4 0x0 0x1 +#define IOMUXC_GPIO_LPSR_09_FLEXCAN3_RX 0x024 0x064 0x080 0x1 0x2 +#define IOMUXC_GPIO_LPSR_09_PIT2_TRIGGER0 0x024 0x064 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_09_MIC_BITSTREAM0 0x024 0x064 0x0B4 0x3 0x1 +#define IOMUXC_GPIO_LPSR_09_LPSPI6_PCS0 0x024 0x064 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_09_GPIO_MUX6_IO09 0x024 0x064 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_09_LPI2C5_SCL 0x024 0x064 0x084 0x6 0x1 +#define IOMUXC_GPIO_LPSR_09_SAI4_TX_DATA 0x024 0x064 0x0 0x7 0x0 + +#define IOMUXC_GPIO_LPSR_10_GPIO12_IO10 0x028 0x068 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_10_JTAG_MUX_TRSTB 0x028 0x068 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_10_LPUART11_CTS_B 0x028 0x068 0x0 0x1 0x0 +#define IOMUXC_GPIO_LPSR_10_LPI2C6_SDA 0x028 0x068 0x090 0x2 0x1 +#define IOMUXC_GPIO_LPSR_10_MIC_BITSTREAM1 0x028 0x068 0x0B8 0x3 0x0 +#define IOMUXC_GPIO_LPSR_10_LPSPI6_SCK 0x028 0x068 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_10_GPIO_MUX6_IO10 0x028 0x068 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_10_LPI2C5_SCLS 0x028 0x068 0x0 0x6 0x0 +#define IOMUXC_GPIO_LPSR_10_SAI4_TX_SYNC 0x028 0x068 0x0DC 0x7 0x1 +#define IOMUXC_GPIO_LPSR_10_LPUART12_TXD 0x028 0x068 0x0B0 0x8 0x2 + +#define IOMUXC_GPIO_LPSR_11_JTAG_MUX_TDO 0x02C 0x06C 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_11_LPUART11_RTS_B 0x02C 0x06C 0x0 0x1 0x0 +#define IOMUXC_GPIO_LPSR_11_LPI2C6_SCL 0x02C 0x06C 0x08C 0x2 0x1 +#define IOMUXC_GPIO_LPSR_11_MIC_BITSTREAM2 0x02C 0x06C 0x0BC 0x3 0x0 +#define IOMUXC_GPIO_LPSR_11_LPSPI6_SOUT 0x02C 0x06C 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_11_GPIO_MUX6_IO11 0x02C 0x06C 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_11_LPI2C5_SDAS 0x02C 0x06C 0x0 0x6 0x0 +#define IOMUXC_GPIO_LPSR_11_ARM_TRACE_SWO 0x02C 0x06C 0x0 0x7 0x0 +#define IOMUXC_GPIO_LPSR_11_LPUART12_RXD 0x02C 0x06C 0x0AC 0x8 0x2 +#define IOMUXC_GPIO_LPSR_11_GPIO12_IO11 0x02C 0x06C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_12_GPIO12_IO12 0x030 0x070 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_12_JTAG_MUX_TDI 0x030 0x070 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_12_PIT2_TRIGGER0 0x030 0x070 0x0 0x1 0x0 +#define IOMUXC_GPIO_LPSR_12_MIC_BITSTREAM3 0x030 0x070 0x0C0 0x3 0x0 +#define IOMUXC_GPIO_LPSR_12_LPSPI6_SIN 0x030 0x070 0x0 0x4 0x0 +#define IOMUXC_GPIO_LPSR_12_GPIO_MUX6_IO12 0x030 0x070 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_12_LPI2C5_HREQ 0x030 0x070 0x0 0x6 0x0 +#define IOMUXC_GPIO_LPSR_12_SAI4_TX_BCLK 0x030 0x070 0x0D8 0x7 0x1 +#define IOMUXC_GPIO_LPSR_12_LPSPI5_SCK 0x030 0x070 0x098 0x8 0x1 + +#define IOMUXC_GPIO_LPSR_13_GPIO12_IO13 0x034 0x074 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_13_JTAG_MUX_MOD 0x034 0x074 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_13_MIC_BITSTREAM1 0x034 0x074 0x0B8 0x1 0x1 +#define IOMUXC_GPIO_LPSR_13_PIT2_TRIGGER1 0x034 0x074 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_13_GPIO_MUX6_IO13 0x034 0x074 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_13_SAI4_RX_DATA 0x034 0x074 0x0D0 0x7 0x1 +#define IOMUXC_GPIO_LPSR_13_LPSPI5_PCS0 0x034 0x074 0x094 0x8 0x1 + +#define IOMUXC_GPIO_LPSR_14_JTAG_MUX_TCK 0x038 0x078 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_14_MIC_BITSTREAM2 0x038 0x078 0x0BC 0x1 0x1 +#define IOMUXC_GPIO_LPSR_14_PIT2_TRIGGER2 0x038 0x078 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_14_GPIO_MUX6_IO14 0x038 0x078 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_14_SAI4_RX_BCLK 0x038 0x078 0x0CC 0x7 0x1 +#define IOMUXC_GPIO_LPSR_14_LPSPI5_SOUT 0x038 0x078 0x0A0 0x8 0x1 +#define IOMUXC_GPIO_LPSR_14_GPIO12_IO14 0x038 0x078 0x0 0xA 0x0 + +#define IOMUXC_GPIO_LPSR_15_GPIO12_IO15 0x03C 0x07C 0x0 0xA 0x0 +#define IOMUXC_GPIO_LPSR_15_JTAG_MUX_TMS 0x03C 0x07C 0x0 0x0 0x0 +#define IOMUXC_GPIO_LPSR_15_MIC_BITSTREAM3 0x03C 0x07C 0x0C0 0x1 0x1 +#define IOMUXC_GPIO_LPSR_15_PIT2_TRIGGER3 0x03C 0x07C 0x0 0x2 0x0 +#define IOMUXC_GPIO_LPSR_15_GPIO_MUX6_IO15 0x03C 0x07C 0x0 0x5 0x0 +#define IOMUXC_GPIO_LPSR_15_SAI4_RX_SYNC 0x03C 0x07C 0x0D4 0x7 0x1 +#define IOMUXC_GPIO_LPSR_15_LPSPI5_SIN 0x03C 0x07C 0x09C 0x8 0x1 + +#define IOMUXC_WAKEUP_DIG_GPIO13_IO00 0x40C94000 0x40C94040 0x0 0x5 0x0 +#define IOMUXC_WAKEUP_DIG_NMI_GLUE_NMI 0x40C94000 0x40C94040 0x0C4 0x7 0x1 + +#define IOMUXC_PMIC_ON_REQ_DIG_SNVS_LP_PMIC_ON_REQ 0x40C94004 0x40C94044 0x0 0x0 0x0 +#define IOMUXC_PMIC_ON_REQ_DIG_GPIO13_IO01 0x40C94004 0x40C94044 0x0 0x5 0x0 + +#define IOMUXC_PMIC_STBY_REQ_DIG_CCM_PMIC_VSTBY_REQ 0x40C94008 0x40C94048 0x0 0x0 0x0 +#define IOMUXC_PMIC_STBY_REQ_DIG_GPIO13_IO02 0x40C94008 0x40C94048 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_00_DIG_SNVS_TAMPER0 0x40C9400C 0x40C9404C 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_00_DIG_GPIO13_IO03 0x40C9400C 0x40C9404C 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_01_DIG_SNVS_TAMPER1 0x40C94010 0x40C94050 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_01_DIG_GPIO13_IO04 0x40C94010 0x40C94050 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_02_DIG_SNVS_TAMPER2 0x40C94014 0x40C94054 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_02_DIG_GPIO13_IO05 0x40C94014 0x40C94054 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_03_DIG_SNVS_TAMPER3 0x40C94018 0x40C94058 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_03_DIG_GPIO13_IO06 0x40C94018 0x40C94058 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_04_DIG_SNVS_TAMPER4 0x40C9401C 0x40C9405C 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_04_DIG_GPIO13_IO07 0x40C9401C 0x40C9405C 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_05_DIG_SNVS_TAMPER5 0x40C94020 0x40C94060 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_05_DIG_GPIO13_IO08 0x40C94020 0x40C94060 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_06_DIG_SNVS_TAMPER6 0x40C94024 0x40C94064 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_06_DIG_GPIO13_IO09 0x40C94024 0x40C94064 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_07_DIG_SNVS_TAMPER7 0x40C94028 0x40C94068 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_07_DIG_GPIO13_IO10 0x40C94028 0x40C94068 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_08_DIG_SNVS_TAMPER8 0x40C9402C 0x40C9406C 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_08_DIG_GPIO13_IO11 0x40C9402C 0x40C9406C 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SNVS_09_DIG_SNVS_TAMPER9 0x40C94030 0x40C94070 0x0 0x0 0x0 +#define IOMUXC_GPIO_SNVS_09_DIG_GPIO13_IO12 0x40C94030 0x40C94070 0x0 0x5 0x0 + +#define IOMUXC_TEST_MODE_DIG 0x0 0x40C94034 0x0 0x0 0x0 + +#define IOMUXC_POR_B_DIG 0x0 0x40C94038 0x0 0x0 0x0 + +#define IOMUXC_ONOFF_DIG 0x0 0x40C9403C 0x0 0x0 0x0 + +#define IOMUXC_GPIO_EMC_B1_00_SEMC_DATA00 0x010 0x254 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_00_FLEXPWM4_PWM0_A 0x010 0x254 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_00_GPIO_MUX1_IO00 0x010 0x254 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_00_FLEXIO1_D00 0x010 0x254 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_00_GPIO7_IO00 0x010 0x254 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_01_GPIO7_IO01 0x014 0x258 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_01_SEMC_DATA01 0x014 0x258 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_01_FLEXPWM4_PWM0_B 0x014 0x258 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_01_GPIO_MUX1_IO01 0x014 0x258 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_01_FLEXIO1_D01 0x014 0x258 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_02_SEMC_DATA02 0x018 0x25C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_02_FLEXPWM4_PWM1_A 0x018 0x25C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_02_GPIO_MUX1_IO02 0x018 0x25C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_02_FLEXIO1_D02 0x018 0x25C 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_02_GPIO7_IO02 0x018 0x25C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_03_SEMC_DATA03 0x01C 0x260 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_03_FLEXPWM4_PWM1_B 0x01C 0x260 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_03_GPIO_MUX1_IO03 0x01C 0x260 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_03_FLEXIO1_D03 0x01C 0x260 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_03_GPIO7_IO03 0x01C 0x260 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_04_GPIO7_IO04 0x020 0x264 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_04_SEMC_DATA04 0x020 0x264 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_04_FLEXPWM4_PWM2_A 0x020 0x264 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_04_GPIO_MUX1_IO04 0x020 0x264 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_04_FLEXIO1_D04 0x020 0x264 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_05_SEMC_DATA05 0x024 0x268 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_05_FLEXPWM4_PWM2_B 0x024 0x268 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_05_GPIO_MUX1_IO05 0x024 0x268 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_05_FLEXIO1_D05 0x024 0x268 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_05_GPIO7_IO05 0x024 0x268 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_06_SEMC_DATA06 0x028 0x26C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_06_FLEXPWM2_PWM0_A 0x028 0x26C 0x518 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_06_GPIO_MUX1_IO06 0x028 0x26C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_06_FLEXIO1_D06 0x028 0x26C 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_06_GPIO7_IO06 0x028 0x26C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_07_GPIO7_IO07 0x02C 0x270 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_07_SEMC_DATA07 0x02C 0x270 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_07_FLEXPWM2_PWM0_B 0x02C 0x270 0x524 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_07_GPIO_MUX1_IO07 0x02C 0x270 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_07_FLEXIO1_D07 0x02C 0x270 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_08_SEMC_DM00 0x030 0x274 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_08_FLEXPWM2_PWM1_A 0x030 0x274 0x51C 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_08_GPIO_MUX1_IO08 0x030 0x274 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_08_FLEXIO1_D08 0x030 0x274 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_08_GPIO7_IO08 0x030 0x274 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_09_SEMC_ADDR00 0x034 0x278 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_09_FLEXPWM2_PWM1_B 0x034 0x278 0x528 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_09_GPT5_CAPTURE1 0x034 0x278 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_09_GPIO_MUX1_IO09 0x034 0x278 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_09_FLEXIO1_D09 0x034 0x278 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_09_GPIO7_IO09 0x034 0x278 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_10_SEMC_ADDR01 0x038 0x27C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_10_FLEXPWM2_PWM2_A 0x038 0x27C 0x520 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_10_GPT5_CAPTURE2 0x038 0x27C 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_10_GPIO_MUX1_IO10 0x038 0x27C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_10_FLEXIO1_D10 0x038 0x27C 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_10_GPIO7_IO10 0x038 0x27C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_11_GPIO7_IO11 0x03C 0x280 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_11_SEMC_ADDR02 0x03C 0x280 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_11_FLEXPWM2_PWM2_B 0x03C 0x280 0x52C 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_11_GPT5_COMPARE1 0x03C 0x280 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_11_GPIO_MUX1_IO11 0x03C 0x280 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_11_FLEXIO1_D11 0x03C 0x280 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_12_SEMC_ADDR03 0x040 0x284 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_12_XBAR1_INOUT04 0x040 0x284 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_12_GPT5_COMPARE2 0x040 0x284 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_12_GPIO_MUX1_IO12 0x040 0x284 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_12_FLEXIO1_D12 0x040 0x284 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_12_GPIO7_IO12 0x040 0x284 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_13_SEMC_ADDR04 0x044 0x288 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_13_XBAR1_INOUT05 0x044 0x288 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_13_GPT5_COMPARE3 0x044 0x288 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_13_GPIO_MUX1_IO13 0x044 0x288 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_13_FLEXIO1_D13 0x044 0x288 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_13_GPIO7_IO13 0x044 0x288 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_14_GPIO7_IO14 0x048 0x28C 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_14_SEMC_ADDR05 0x048 0x28C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_14_XBAR1_INOUT06 0x048 0x28C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_14_GPT5_CLK 0x048 0x28C 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_14_GPIO_MUX1_IO14 0x048 0x28C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_14_FLEXIO1_D14 0x048 0x28C 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_15_SEMC_ADDR06 0x04C 0x290 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_15_XBAR1_INOUT07 0x04C 0x290 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_15_GPIO_MUX1_IO15 0x04C 0x290 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_15_FLEXIO1_D15 0x04C 0x290 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_15_GPIO7_IO15 0x04C 0x290 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_16_SEMC_ADDR07 0x050 0x294 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_16_XBAR1_INOUT08 0x050 0x294 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_16_GPIO_MUX1_IO16 0x050 0x294 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_16_FLEXIO1_D16 0x050 0x294 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_16_GPIO7_IO16 0x050 0x294 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_17_GPIO7_IO17 0x054 0x298 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_17_SEMC_ADDR08 0x054 0x298 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_17_FLEXPWM4_PWM3_A 0x054 0x298 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_17_TMR1_TIMER0 0x054 0x298 0x63C 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_17_GPIO_MUX1_IO17 0x054 0x298 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_17_FLEXIO1_D17 0x054 0x298 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_18_SEMC_ADDR09 0x058 0x29C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_18_FLEXPWM4_PWM3_B 0x058 0x29C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_18_TMR2_TIMER0 0x058 0x29C 0x648 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_18_GPIO_MUX1_IO18 0x058 0x29C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_18_FLEXIO1_D18 0x058 0x29C 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_18_GPIO7_IO18 0x058 0x29C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_19_SEMC_ADDR11 0x05C 0x2A0 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_19_FLEXPWM2_PWM3_A 0x05C 0x2A0 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_19_TMR3_TIMER0 0x05C 0x2A0 0x654 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_19_GPIO_MUX1_IO19 0x05C 0x2A0 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_19_FLEXIO1_D19 0x05C 0x2A0 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_19_GPIO7_IO19 0x05C 0x2A0 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_20_SEMC_ADDR12 0x060 0x2A4 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_20_FLEXPWM2_PWM3_B 0x060 0x2A4 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_20_TMR4_TIMER0 0x060 0x2A4 0x660 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_20_GPIO_MUX1_IO20 0x060 0x2A4 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_20_FLEXIO1_D20 0x060 0x2A4 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_20_GPIO7_IO20 0x060 0x2A4 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_21_GPIO7_IO21 0x064 0x2A8 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_21_SEMC_BA0 0x064 0x2A8 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_21_FLEXPWM3_PWM3_A 0x064 0x2A8 0x53C 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_21_GPIO_MUX1_IO21 0x064 0x2A8 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_21_FLEXIO1_D21 0x064 0x2A8 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_22_GPIO7_IO22 0x068 0x2AC 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_22_SEMC_BA1 0x068 0x2AC 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_22_FLEXPWM3_PWM3_B 0x068 0x2AC 0x54C 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_22_GPIO_MUX1_IO22 0x068 0x2AC 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_22_FLEXIO1_D22 0x068 0x2AC 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_23_SEMC_ADDR10 0x06C 0x2B0 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_23_FLEXPWM1_PWM0_A 0x06C 0x2B0 0x500 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_23_GPIO_MUX1_IO23 0x06C 0x2B0 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_23_FLEXIO1_D23 0x06C 0x2B0 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_23_GPIO7_IO23 0x06C 0x2B0 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_24_GPIO7_IO24 0x070 0x2B4 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_24_SEMC_CAS 0x070 0x2B4 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_24_FLEXPWM1_PWM0_B 0x070 0x2B4 0x50C 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_24_GPIO_MUX1_IO24 0x070 0x2B4 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_24_FLEXIO1_D24 0x070 0x2B4 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_25_GPIO7_IO25 0x074 0x2B8 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_25_SEMC_RAS 0x074 0x2B8 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_25_FLEXPWM1_PWM1_A 0x074 0x2B8 0x504 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_25_GPIO_MUX1_IO25 0x074 0x2B8 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_25_FLEXIO1_D25 0x074 0x2B8 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_26_SEMC_CLK 0x078 0x2BC 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_26_FLEXPWM1_PWM1_B 0x078 0x2BC 0x510 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_26_GPIO_MUX1_IO26 0x078 0x2BC 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_26_FLEXIO1_D26 0x078 0x2BC 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_26_GPIO7_IO26 0x078 0x2BC 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_27_GPIO7_IO27 0x07C 0x2C0 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_27_SEMC_CKE 0x07C 0x2C0 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_27_FLEXPWM1_PWM2_A 0x07C 0x2C0 0x508 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_27_GPIO_MUX1_IO27 0x07C 0x2C0 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_27_FLEXIO1_D27 0x07C 0x2C0 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_28_GPIO7_IO28 0x080 0x2C4 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_28_SEMC_WE 0x080 0x2C4 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_28_FLEXPWM1_PWM2_B 0x080 0x2C4 0x514 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_28_GPIO_MUX1_IO28 0x080 0x2C4 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_28_FLEXIO1_D28 0x080 0x2C4 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_29_SEMC_CS0 0x084 0x2C8 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_29_FLEXPWM3_PWM0_A 0x084 0x2C8 0x530 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_29_GPIO_MUX1_IO29 0x084 0x2C8 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_29_FLEXIO1_D29 0x084 0x2C8 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_29_GPIO7_IO29 0x084 0x2C8 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_30_SEMC_DATA08 0x088 0x2CC 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_30_FLEXPWM3_PWM0_B 0x088 0x2CC 0x540 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_30_GPIO_MUX1_IO30 0x088 0x2CC 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_30_FLEXIO1_D30 0x088 0x2CC 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B1_30_GPIO7_IO30 0x088 0x2CC 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_31_GPIO7_IO31 0x08C 0x2D0 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_31_SEMC_DATA09 0x08C 0x2D0 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_31_FLEXPWM3_PWM1_A 0x08C 0x2D0 0x534 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_31_GPIO_MUX1_IO31 0x08C 0x2D0 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_31_FLEXIO1_D31 0x08C 0x2D0 0x0 0x8 0x0 + +#define IOMUXC_GPIO_EMC_B1_32_GPIO8_IO00 0x090 0x2D4 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_32_SEMC_DATA10 0x090 0x2D4 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_32_FLEXPWM3_PWM1_B 0x090 0x2D4 0x544 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_32_GPIO_MUX2_IO00 0x090 0x2D4 0x0 0x5 0x0 + +#define IOMUXC_GPIO_EMC_B1_33_SEMC_DATA11 0x094 0x2D8 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_33_FLEXPWM3_PWM2_A 0x094 0x2D8 0x538 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_33_GPIO_MUX2_IO01 0x094 0x2D8 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_33_GPIO8_IO01 0x094 0x2D8 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_34_GPIO8_IO02 0x098 0x2DC 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_34_SEMC_DATA12 0x098 0x2DC 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_34_FLEXPWM3_PWM2_B 0x098 0x2DC 0x548 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_34_GPIO_MUX2_IO02 0x098 0x2DC 0x0 0x5 0x0 + +#define IOMUXC_GPIO_EMC_B1_35_GPIO8_IO03 0x09C 0x2E0 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_35_SEMC_DATA13 0x09C 0x2E0 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_35_XBAR1_INOUT09 0x09C 0x2E0 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_35_GPIO_MUX2_IO03 0x09C 0x2E0 0x0 0x5 0x0 + +#define IOMUXC_GPIO_EMC_B1_36_SEMC_DATA14 0x0A0 0x2E4 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_36_XBAR1_INOUT10 0x0A0 0x2E4 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_36_GPIO_MUX2_IO04 0x0A0 0x2E4 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_36_GPIO8_IO04 0x0A0 0x2E4 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_37_GPIO8_IO05 0x0A4 0x2E8 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_37_SEMC_DATA15 0x0A4 0x2E8 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_37_XBAR1_INOUT11 0x0A4 0x2E8 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_37_GPIO_MUX2_IO05 0x0A4 0x2E8 0x0 0x5 0x0 + +#define IOMUXC_GPIO_EMC_B1_38_GPIO8_IO06 0x0A8 0x2EC 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_38_SEMC_DM01 0x0A8 0x2EC 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_38_FLEXPWM1_PWM3_A 0x0A8 0x2EC 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_38_TMR1_TIMER1 0x0A8 0x2EC 0x640 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_38_GPIO_MUX2_IO06 0x0A8 0x2EC 0x0 0x5 0x0 + +#define IOMUXC_GPIO_EMC_B1_39_SEMC_DQS 0x0AC 0x2F0 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_39_FLEXPWM1_PWM3_B 0x0AC 0x2F0 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_39_TMR2_TIMER1 0x0AC 0x2F0 0x64C 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_39_GPIO_MUX2_IO07 0x0AC 0x2F0 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_39_GPIO8_IO07 0x0AC 0x2F0 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_40_SEMC_RDY 0x0B0 0x2F4 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_40_XBAR1_INOUT12 0x0B0 0x2F4 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_40_MQS_RIGHT 0x0B0 0x2F4 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_40_LPUART6_TXD 0x0B0 0x2F4 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B1_40_GPIO_MUX2_IO08 0x0B0 0x2F4 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_40_ENET_1G_MDC 0x0B0 0x2F4 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B1_40_CCM_CLKO1 0x0B0 0x2F4 0x0 0x9 0x0 +#define IOMUXC_GPIO_EMC_B1_40_GPIO8_IO08 0x0B0 0x2F4 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B1_41_GPIO8_IO09 0x0B4 0x2F8 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B1_41_SEMC_CSX00 0x0B4 0x2F8 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B1_41_XBAR1_INOUT13 0x0B4 0x2F8 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B1_41_MQS_LEFT 0x0B4 0x2F8 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B1_41_LPUART6_RXD 0x0B4 0x2F8 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B1_41_FLEXSPI2_B_DATA07 0x0B4 0x2F8 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B1_41_GPIO_MUX2_IO09 0x0B4 0x2F8 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B1_41_ENET_1G_MDIO 0x0B4 0x2F8 0x4C8 0x7 0x0 +#define IOMUXC_GPIO_EMC_B1_41_CCM_CLKO2 0x0B4 0x2F8 0x0 0x9 0x0 + +#define IOMUXC_GPIO_EMC_B2_00_SEMC_DATA16 0x0B8 0x2FC 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_00_CCM_ENET_REF_CLK_25M 0x0B8 0x2FC 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_00_TMR3_TIMER1 0x0B8 0x2FC 0x658 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_00_LPUART6_CTS_B 0x0B8 0x2FC 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_00_FLEXSPI2_B_DATA06 0x0B8 0x2FC 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_00_GPIO_MUX2_IO10 0x0B8 0x2FC 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_00_XBAR1_INOUT20 0x0B8 0x2FC 0x6D8 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_00_ENET_QOS_1588_EVENT1_OUT 0x0B8 0x2FC 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_00_LPSPI1_SCK 0x0B8 0x2FC 0x5D0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_00_LPI2C2_SCL 0x0B8 0x2FC 0x5B4 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_00_GPIO8_IO10 0x0B8 0x2FC 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_00_FLEXPWM3_PWM0_A 0x0B8 0x2FC 0x530 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_01_SEMC_DATA17 0x0BC 0x300 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_01_USDHC2_CD_B 0x0BC 0x300 0x6D0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_01_TMR4_TIMER1 0x0BC 0x300 0x664 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_01_LPUART6_RTS_B 0x0BC 0x300 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_01_FLEXSPI2_B_DATA05 0x0BC 0x300 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_01_GPIO_MUX2_IO11 0x0BC 0x300 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_01_XBAR1_INOUT21 0x0BC 0x300 0x6DC 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_01_ENET_QOS_1588_EVENT1_IN 0x0BC 0x300 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_01_LPSPI1_PCS0 0x0BC 0x300 0x5CC 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_01_LPI2C2_SDA 0x0BC 0x300 0x5B8 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_01_GPIO8_IO11 0x0BC 0x300 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_01_FLEXPWM3_PWM0_B 0x0BC 0x300 0x540 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_02_SEMC_DATA18 0x0C0 0x304 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_02_USDHC2_WP 0x0C0 0x304 0x6D4 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_02_VIDEO_MUX_CSI_DATA23 0x0C0 0x304 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_02_FLEXSPI2_B_DATA04 0x0C0 0x304 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_02_GPIO_MUX2_IO12 0x0C0 0x304 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_02_XBAR1_INOUT22 0x0C0 0x304 0x6E0 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_02_ENET_QOS_1588_EVENT1_AUX_IN 0x0C0 0x304 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_02_LPSPI1_SOUT 0x0C0 0x304 0x5D8 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_02_GPIO8_IO12 0x0C0 0x304 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_02_FLEXPWM3_PWM1_A 0x0C0 0x304 0x534 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_03_SEMC_DATA19 0x0C4 0x308 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_03_USDHC2_VSELECT 0x0C4 0x308 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_03_VIDEO_MUX_CSI_DATA22 0x0C4 0x308 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_03_FLEXSPI2_B_DATA03 0x0C4 0x308 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_03_GPIO_MUX2_IO13 0x0C4 0x308 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_03_XBAR1_INOUT23 0x0C4 0x308 0x6E4 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_03_ENET_1G_TX_DATA03 0x0C4 0x308 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_03_LPSPI1_SIN 0x0C4 0x308 0x5D4 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_03_GPIO8_IO13 0x0C4 0x308 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_03_FLEXPWM3_PWM1_B 0x0C4 0x308 0x544 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_04_SEMC_DATA20 0x0C8 0x30C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_04_USDHC2_RESET_B 0x0C8 0x30C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_04_SAI2_MCLK 0x0C8 0x30C 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_04_VIDEO_MUX_CSI_DATA21 0x0C8 0x30C 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_04_FLEXSPI2_B_DATA02 0x0C8 0x30C 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_04_GPIO_MUX2_IO14 0x0C8 0x30C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_04_XBAR1_INOUT24 0x0C8 0x30C 0x6E8 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_04_ENET_1G_TX_DATA02 0x0C8 0x30C 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_04_LPSPI3_SCK 0x0C8 0x30C 0x600 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_04_GPIO8_IO14 0x0C8 0x30C 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_04_FLEXPWM3_PWM2_A 0x0C8 0x30C 0x538 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_05_SEMC_DATA21 0x0CC 0x310 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_05_GPT3_CLK 0x0CC 0x310 0x598 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_05_SAI2_RX_SYNC 0x0CC 0x310 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_05_VIDEO_MUX_CSI_DATA20 0x0CC 0x310 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_05_FLEXSPI2_B_DATA01 0x0CC 0x310 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_05_GPIO_MUX2_IO15 0x0CC 0x310 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_05_XBAR1_INOUT25 0x0CC 0x310 0x6EC 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_05_ENET_1G_RX_CLK 0x0CC 0x310 0x4CC 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_05_LPSPI3_PCS0 0x0CC 0x310 0x5F0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_05_PIT1_TRIGGER0 0x0CC 0x310 0x0 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_05_GPIO8_IO15 0x0CC 0x310 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_05_FLEXPWM3_PWM2_B 0x0CC 0x310 0x548 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_06_SEMC_DATA22 0x0D0 0x314 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_06_GPT3_CAPTURE1 0x0D0 0x314 0x590 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_06_GPIO8_IO16 0x0D0 0x314 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_06_SAI2_RX_BCLK 0x0D0 0x314 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_06_FLEXPWM3_PWM3_A 0x0D0 0x314 0x53C 0xB 0x1 +#define IOMUXC_GPIO_EMC_B2_06_VIDEO_MUX_CSI_DATA19 0x0D0 0x314 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_06_FLEXSPI2_B_DATA00 0x0D0 0x314 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_06_GPIO_MUX2_IO16 0x0D0 0x314 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_06_XBAR1_INOUT26 0x0D0 0x314 0x6F0 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_06_ENET_1G_TX_ER 0x0D0 0x314 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_06_LPSPI3_SOUT 0x0D0 0x314 0x608 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_06_PIT1_TRIGGER1 0x0D0 0x314 0x0 0x9 0x0 + +#define IOMUXC_GPIO_EMC_B2_07_SEMC_DATA23 0x0D4 0x318 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_07_GPT3_CAPTURE2 0x0D4 0x318 0x594 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_07_SAI2_RX_DATA 0x0D4 0x318 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_07_VIDEO_MUX_CSI_DATA18 0x0D4 0x318 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_07_FLEXSPI2_B_DQS 0x0D4 0x318 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_07_GPIO_MUX2_IO17 0x0D4 0x318 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_07_XBAR1_INOUT27 0x0D4 0x318 0x6F4 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_07_ENET_1G_RX_DATA03 0x0D4 0x318 0x4DC 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_07_LPSPI3_SIN 0x0D4 0x318 0x604 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_07_PIT1_TRIGGER2 0x0D4 0x318 0x0 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_07_GPIO8_IO17 0x0D4 0x318 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_07_FLEXPWM3_PWM3_B 0x0D4 0x318 0x54C 0xB 0x1 + +#define IOMUXC_GPIO_EMC_B2_08_SEMC_DM02 0x0D8 0x31C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_08_GPT3_COMPARE1 0x0D8 0x31C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_08_SAI2_TX_DATA 0x0D8 0x31C 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_08_VIDEO_MUX_CSI_DATA17 0x0D8 0x31C 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_08_FLEXSPI2_B_SS0_B 0x0D8 0x31C 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_08_GPIO_MUX2_IO18 0x0D8 0x31C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_08_XBAR1_INOUT28 0x0D8 0x31C 0x6F8 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_08_ENET_1G_RX_DATA02 0x0D8 0x31C 0x4D8 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_08_LPSPI3_PCS1 0x0D8 0x31C 0x5F4 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_08_PIT1_TRIGGER3 0x0D8 0x31C 0x0 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_08_GPIO8_IO18 0x0D8 0x31C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_09_GPIO8_IO19 0x0DC 0x320 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_09_SEMC_DATA24 0x0DC 0x320 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_09_GPT3_COMPARE2 0x0DC 0x320 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_09_SAI2_TX_BCLK 0x0DC 0x320 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_09_VIDEO_MUX_CSI_DATA16 0x0DC 0x320 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_09_FLEXSPI2_B_SCLK 0x0DC 0x320 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_09_GPIO_MUX2_IO19 0x0DC 0x320 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_09_XBAR1_INOUT29 0x0DC 0x320 0x6FC 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_09_ENET_1G_CRS 0x0DC 0x320 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_09_LPSPI3_PCS2 0x0DC 0x320 0x5F8 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_09_TMR1_TIMER0 0x0DC 0x320 0x63C 0x9 0x1 + +#define IOMUXC_GPIO_EMC_B2_10_GPIO8_IO20 0x0E0 0x324 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_10_SEMC_DATA25 0x0E0 0x324 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_10_GPT3_COMPARE3 0x0E0 0x324 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_10_SAI2_TX_SYNC 0x0E0 0x324 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_10_VIDEO_MUX_CSI_FIELD 0x0E0 0x324 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_10_FLEXSPI2_A_SCLK 0x0E0 0x324 0x58C 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_10_GPIO_MUX2_IO20 0x0E0 0x324 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_10_XBAR1_INOUT30 0x0E0 0x324 0x700 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_10_ENET_1G_COL 0x0E0 0x324 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_10_LPSPI3_PCS3 0x0E0 0x324 0x5FC 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_10_TMR1_TIMER1 0x0E0 0x324 0x640 0x9 0x1 + +#define IOMUXC_GPIO_EMC_B2_11_SEMC_DATA26 0x0E4 0x328 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_11_SPDIF_IN 0x0E4 0x328 0x6B4 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_11_ENET_1G_TX_DATA00 0x0E4 0x328 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_11_SAI3_RX_SYNC 0x0E4 0x328 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_11_FLEXSPI2_A_SS0_B 0x0E4 0x328 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_11_GPIO_MUX2_IO21 0x0E4 0x328 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_11_XBAR1_INOUT31 0x0E4 0x328 0x704 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_11_EMVSIM1_IO 0x0E4 0x328 0x69C 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_11_TMR1_TIMER2 0x0E4 0x328 0x644 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_11_GPIO8_IO21 0x0E4 0x328 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_12_SEMC_DATA27 0x0E8 0x32C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_12_SPDIF_OUT 0x0E8 0x32C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_12_ENET_1G_TX_DATA01 0x0E8 0x32C 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_12_SAI3_RX_BCLK 0x0E8 0x32C 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_12_FLEXSPI2_A_DQS 0x0E8 0x32C 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_12_GPIO_MUX2_IO22 0x0E8 0x32C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_12_XBAR1_INOUT32 0x0E8 0x32C 0x708 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_12_EMVSIM1_CLK 0x0E8 0x32C 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_12_TMR1_TIMER3 0x0E8 0x32C 0x0 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_12_GPIO8_IO22 0x0E8 0x32C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_13_GPIO8_IO23 0x0EC 0x330 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_13_SEMC_DATA28 0x0EC 0x330 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_13_ENET_1G_TX_EN 0x0EC 0x330 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_13_SAI3_RX_DATA 0x0EC 0x330 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_13_FLEXSPI2_A_DATA00 0x0EC 0x330 0x57C 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_13_GPIO_MUX2_IO23 0x0EC 0x330 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_13_XBAR1_INOUT33 0x0EC 0x330 0x70C 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_13_EMVSIM1_RST 0x0EC 0x330 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_13_TMR2_TIMER0 0x0EC 0x330 0x648 0x9 0x1 + +#define IOMUXC_GPIO_EMC_B2_14_SEMC_DATA29 0x0F0 0x334 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_14_ENET_1G_TX_CLK_IO 0x0F0 0x334 0x4E8 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_14_SAI3_TX_DATA 0x0F0 0x334 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_14_FLEXSPI2_A_DATA01 0x0F0 0x334 0x580 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_14_GPIO_MUX2_IO24 0x0F0 0x334 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_14_XBAR1_INOUT34 0x0F0 0x334 0x710 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_14_SFA_ipp_do_atx_clk_under_test 0x0F0 0x334 0x0 0x7 0x0 +#define IOMUXC_GPIO_EMC_B2_14_EMVSIM1_SVEN 0x0F0 0x334 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_14_TMR2_TIMER1 0x0F0 0x334 0x64C 0x9 0x1 +#define IOMUXC_GPIO_EMC_B2_14_GPIO8_IO24 0x0F0 0x334 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_15_SEMC_DATA30 0x0F4 0x338 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_15_ENET_1G_RX_DATA00 0x0F4 0x338 0x4D0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_15_SAI3_TX_BCLK 0x0F4 0x338 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_15_FLEXSPI2_A_DATA02 0x0F4 0x338 0x584 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_15_GPIO_MUX2_IO25 0x0F4 0x338 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_15_XBAR1_INOUT35 0x0F4 0x338 0x714 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_15_EMVSIM1_PD 0x0F4 0x338 0x6A0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_15_TMR2_TIMER2 0x0F4 0x338 0x650 0x9 0x0 +#define IOMUXC_GPIO_EMC_B2_15_GPIO8_IO25 0x0F4 0x338 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_16_GPIO8_IO26 0x0F8 0x33C 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_16_SEMC_DATA31 0x0F8 0x33C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_16_XBAR1_INOUT14 0x0F8 0x33C 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_16_ENET_1G_RX_DATA01 0x0F8 0x33C 0x4D4 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_16_SAI3_TX_SYNC 0x0F8 0x33C 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_16_FLEXSPI2_A_DATA03 0x0F8 0x33C 0x588 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_16_GPIO_MUX2_IO26 0x0F8 0x33C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_16_EMVSIM1_POWER_FAIL 0x0F8 0x33C 0x6A4 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_16_TMR2_TIMER3 0x0F8 0x33C 0x0 0x9 0x0 + +#define IOMUXC_GPIO_EMC_B2_17_SEMC_DM03 0x0FC 0x340 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_17_XBAR1_INOUT15 0x0FC 0x340 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_17_ENET_1G_RX_EN 0x0FC 0x340 0x4E0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_17_SAI3_MCLK 0x0FC 0x340 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_17_FLEXSPI2_A_DATA04 0x0FC 0x340 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_17_GPIO_MUX2_IO27 0x0FC 0x340 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_17_WDOG1_ANY 0x0FC 0x340 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_17_TMR3_TIMER0 0x0FC 0x340 0x654 0x9 0x1 +#define IOMUXC_GPIO_EMC_B2_17_GPIO8_IO27 0x0FC 0x340 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_18_SEMC_DQS4 0x100 0x344 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_18_XBAR1_INOUT16 0x100 0x344 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_18_ENET_1G_RX_ER 0x100 0x344 0x4E4 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_18_EWM_OUT_B 0x100 0x344 0x0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_18_FLEXSPI2_A_DATA05 0x100 0x344 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_18_GPIO_MUX2_IO28 0x100 0x344 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_18_FLEXSPI1_A_DQS 0x100 0x344 0x550 0x6 0x0 +#define IOMUXC_GPIO_EMC_B2_18_WDOG1_B 0x100 0x344 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_18_TMR3_TIMER1 0x100 0x344 0x658 0x9 0x1 +#define IOMUXC_GPIO_EMC_B2_18_GPIO8_IO28 0x100 0x344 0x0 0xA 0x0 + +#define IOMUXC_GPIO_EMC_B2_19_GPIO8_IO29 0x104 0x348 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_19_SEMC_CLKX00 0x104 0x348 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_19_ENET_MDC 0x104 0x348 0x0 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_19_ENET_1G_MDC 0x104 0x348 0x0 0x2 0x0 +#define IOMUXC_GPIO_EMC_B2_19_ENET_1G_REF_CLK 0x104 0x348 0x4C4 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_19_FLEXSPI2_A_DATA06 0x104 0x348 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_19_GPIO_MUX2_IO29 0x104 0x348 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_19_ENET_QOS_MDC 0x104 0x348 0x0 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_19_TMR3_TIMER2 0x104 0x348 0x65C 0x9 0x0 + +#define IOMUXC_GPIO_EMC_B2_20_GPIO8_IO30 0x108 0x34C 0x0 0xA 0x0 +#define IOMUXC_GPIO_EMC_B2_20_SEMC_CLKX01 0x108 0x34C 0x0 0x0 0x0 +#define IOMUXC_GPIO_EMC_B2_20_ENET_MDIO 0x108 0x34C 0x4AC 0x1 0x0 +#define IOMUXC_GPIO_EMC_B2_20_ENET_1G_MDIO 0x108 0x34C 0x4C8 0x2 0x1 +#define IOMUXC_GPIO_EMC_B2_20_ENET_QOS_REF_CLK 0x108 0x34C 0x4A0 0x3 0x0 +#define IOMUXC_GPIO_EMC_B2_20_FLEXSPI2_A_DATA07 0x108 0x34C 0x0 0x4 0x0 +#define IOMUXC_GPIO_EMC_B2_20_GPIO_MUX2_IO30 0x108 0x34C 0x0 0x5 0x0 +#define IOMUXC_GPIO_EMC_B2_20_ENET_QOS_MDIO 0x108 0x34C 0x4EC 0x8 0x0 +#define IOMUXC_GPIO_EMC_B2_20_TMR3_TIMER3 0x108 0x34C 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_00_GPIO8_IO31 0x10C 0x350 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_00_EMVSIM1_IO 0x10C 0x350 0x69C 0x0 0x1 +#define IOMUXC_GPIO_AD_00_FLEXCAN2_TX 0x10C 0x350 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_00_ENET_1G_1588_EVENT1_IN 0x10C 0x350 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_00_GPT2_CAPTURE1 0x10C 0x350 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_00_FLEXPWM1_PWM0_A 0x10C 0x350 0x500 0x4 0x1 +#define IOMUXC_GPIO_AD_00_GPIO_MUX2_IO31 0x10C 0x350 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_00_LPUART7_TXD 0x10C 0x350 0x630 0x6 0x0 +#define IOMUXC_GPIO_AD_00_FLEXIO2_D00 0x10C 0x350 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_00_FLEXSPI2_B_SS1_B 0x10C 0x350 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_01_GPIO9_IO00 0x110 0x354 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_01_EMVSIM1_CLK 0x110 0x354 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_01_FLEXCAN2_RX 0x110 0x354 0x49C 0x1 0x0 +#define IOMUXC_GPIO_AD_01_ENET_1G_1588_EVENT1_OUT 0x110 0x354 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_01_GPT2_CAPTURE2 0x110 0x354 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_01_FLEXPWM1_PWM0_B 0x110 0x354 0x50C 0x4 0x1 +#define IOMUXC_GPIO_AD_01_GPIO_MUX3_IO00 0x110 0x354 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_01_LPUART7_RXD 0x110 0x354 0x62C 0x6 0x0 +#define IOMUXC_GPIO_AD_01_FLEXIO2_D01 0x110 0x354 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_01_FLEXSPI2_A_SS1_B 0x110 0x354 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_02_GPIO9_IO01 0x114 0x358 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_02_EMVSIM1_RST 0x114 0x358 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_02_LPUART7_CTS_B 0x114 0x358 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_02_ENET_1G_1588_EVENT2_IN 0x114 0x358 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_02_GPT2_COMPARE1 0x114 0x358 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_02_FLEXPWM1_PWM1_A 0x114 0x358 0x504 0x4 0x1 +#define IOMUXC_GPIO_AD_02_GPIO_MUX3_IO01 0x114 0x358 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_02_LPUART8_TXD 0x114 0x358 0x638 0x6 0x0 +#define IOMUXC_GPIO_AD_02_FLEXIO2_D02 0x114 0x358 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_02_VIDEO_MUX_EXT_DCIC1 0x114 0x358 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_03_GPIO9_IO02 0x118 0x35C 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_03_EMVSIM1_SVEN 0x118 0x35C 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_03_LPUART7_RTS_B 0x118 0x35C 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_03_ENET_1G_1588_EVENT2_OUT 0x118 0x35C 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_03_GPT2_COMPARE2 0x118 0x35C 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_03_FLEXPWM1_PWM1_B 0x118 0x35C 0x510 0x4 0x1 +#define IOMUXC_GPIO_AD_03_GPIO_MUX3_IO02 0x118 0x35C 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_03_LPUART8_RXD 0x118 0x35C 0x634 0x6 0x0 +#define IOMUXC_GPIO_AD_03_FLEXIO2_D03 0x118 0x35C 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_03_VIDEO_MUX_EXT_DCIC2 0x118 0x35C 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_04_EMVSIM1_PD 0x11C 0x360 0x6A0 0x0 0x1 +#define IOMUXC_GPIO_AD_04_LPUART8_CTS_B 0x11C 0x360 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_04_ENET_1G_1588_EVENT3_IN 0x11C 0x360 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_04_GPT2_COMPARE3 0x11C 0x360 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_04_FLEXPWM1_PWM2_A 0x11C 0x360 0x508 0x4 0x1 +#define IOMUXC_GPIO_AD_04_GPIO_MUX3_IO03 0x11C 0x360 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_04_WDOG1_B 0x11C 0x360 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_04_FLEXIO2_D04 0x11C 0x360 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_04_TMR4_TIMER0 0x11C 0x360 0x660 0x9 0x1 +#define IOMUXC_GPIO_AD_04_GPIO9_IO03 0x11C 0x360 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_05_EMVSIM1_POWER_FAIL 0x120 0x364 0x6A4 0x0 0x1 +#define IOMUXC_GPIO_AD_05_LPUART8_RTS_B 0x120 0x364 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_05_ENET_1G_1588_EVENT3_OUT 0x120 0x364 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_05_GPT2_CLK 0x120 0x364 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_05_FLEXPWM1_PWM2_B 0x120 0x364 0x514 0x4 0x1 +#define IOMUXC_GPIO_AD_05_GPIO_MUX3_IO04 0x120 0x364 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_05_WDOG2_B 0x120 0x364 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_05_FLEXIO2_D05 0x120 0x364 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_05_TMR4_TIMER1 0x120 0x364 0x664 0x9 0x1 +#define IOMUXC_GPIO_AD_05_GPIO9_IO04 0x120 0x364 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_06_USB_OTG2_OC 0x124 0x368 0x6B8 0x0 0x0 +#define IOMUXC_GPIO_AD_06_FLEXCAN1_TX 0x124 0x368 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_06_EMVSIM2_IO 0x124 0x368 0x6A8 0x2 0x0 +#define IOMUXC_GPIO_AD_06_GPT3_CAPTURE1 0x124 0x368 0x590 0x3 0x1 +#define IOMUXC_GPIO_AD_06_VIDEO_MUX_CSI_DATA15 0x124 0x368 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_06_GPIO_MUX3_IO05 0x124 0x368 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_06_ENET_1588_EVENT1_IN 0x124 0x368 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_06_FLEXIO2_D06 0x124 0x368 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_06_TMR4_TIMER2 0x124 0x368 0x668 0x9 0x0 +#define IOMUXC_GPIO_AD_06_GPIO9_IO05 0x124 0x368 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_06_FLEXPWM1_PWM0_X 0x124 0x368 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_07_USB_OTG2_PWR 0x128 0x36C 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_07_FLEXCAN1_RX 0x128 0x36C 0x498 0x1 0x0 +#define IOMUXC_GPIO_AD_07_EMVSIM2_CLK 0x128 0x36C 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_07_GPT3_CAPTURE2 0x128 0x36C 0x594 0x3 0x1 +#define IOMUXC_GPIO_AD_07_VIDEO_MUX_CSI_DATA14 0x128 0x36C 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_07_GPIO_MUX3_IO06 0x128 0x36C 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_07_ENET_1588_EVENT1_OUT 0x128 0x36C 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_07_FLEXIO2_D07 0x128 0x36C 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_07_TMR4_TIMER3 0x128 0x36C 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_07_GPIO9_IO06 0x128 0x36C 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_07_FLEXPWM1_PWM1_X 0x128 0x36C 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_08_USBPHY2_OTG_ID 0x12C 0x370 0x6C4 0x0 0x0 +#define IOMUXC_GPIO_AD_08_LPI2C1_SCL 0x12C 0x370 0x5AC 0x1 0x0 +#define IOMUXC_GPIO_AD_08_EMVSIM2_RST 0x12C 0x370 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_08_GPT3_COMPARE1 0x12C 0x370 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_08_VIDEO_MUX_CSI_DATA13 0x12C 0x370 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_08_GPIO_MUX3_IO07 0x12C 0x370 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_08_ENET_1588_EVENT2_IN 0x12C 0x370 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_08_FLEXIO2_D08 0x12C 0x370 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_08_GPIO9_IO07 0x12C 0x370 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_08_FLEXPWM1_PWM2_X 0x12C 0x370 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_09_USBPHY1_OTG_ID 0x130 0x374 0x6C0 0x0 0x0 +#define IOMUXC_GPIO_AD_09_LPI2C1_SDA 0x130 0x374 0x5B0 0x1 0x0 +#define IOMUXC_GPIO_AD_09_EMVSIM2_SVEN 0x130 0x374 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_09_GPT3_COMPARE2 0x130 0x374 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_09_VIDEO_MUX_CSI_DATA12 0x130 0x374 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_09_GPIO_MUX3_IO08 0x130 0x374 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_09_ENET_1588_EVENT2_OUT 0x130 0x374 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_09_FLEXIO2_D09 0x130 0x374 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_09_GPIO9_IO08 0x130 0x374 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_09_FLEXPWM1_PWM3_X 0x130 0x374 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_10_USB_OTG1_PWR 0x134 0x378 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_10_LPI2C1_SCLS 0x134 0x378 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_10_EMVSIM2_PD 0x134 0x378 0x6AC 0x2 0x0 +#define IOMUXC_GPIO_AD_10_GPT3_COMPARE3 0x134 0x378 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_10_VIDEO_MUX_CSI_DATA11 0x134 0x378 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_10_GPIO_MUX3_IO09 0x134 0x378 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_10_ENET_1588_EVENT3_IN 0x134 0x378 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_10_FLEXIO2_D10 0x134 0x378 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_10_GPIO9_IO09 0x134 0x378 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_10_FLEXPWM2_PWM0_X 0x134 0x378 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_11_USB_OTG1_OC 0x138 0x37C 0x6BC 0x0 0x0 +#define IOMUXC_GPIO_AD_11_LPI2C1_SDAS 0x138 0x37C 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_11_EMVSIM2_POWER_FAIL 0x138 0x37C 0x6B0 0x2 0x0 +#define IOMUXC_GPIO_AD_11_GPT3_CLK 0x138 0x37C 0x598 0x3 0x1 +#define IOMUXC_GPIO_AD_11_VIDEO_MUX_CSI_DATA10 0x138 0x37C 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_11_GPIO_MUX3_IO10 0x138 0x37C 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_11_ENET_1588_EVENT3_OUT 0x138 0x37C 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_11_FLEXIO2_D11 0x138 0x37C 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_11_GPIO9_IO10 0x138 0x37C 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_11_FLEXPWM2_PWM1_X 0x138 0x37C 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_12_SPDIF_LOCK 0x13C 0x380 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_12_LPI2C1_HREQ 0x13C 0x380 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_12_GPT1_CAPTURE1 0x13C 0x380 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_12_FLEXSPI1_B_DATA03 0x13C 0x380 0x570 0x3 0x0 +#define IOMUXC_GPIO_AD_12_VIDEO_MUX_CSI_PIXCLK 0x13C 0x380 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_12_GPIO_MUX3_IO11 0x13C 0x380 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_12_ENET_TX_DATA03 0x13C 0x380 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_12_FLEXIO2_D12 0x13C 0x380 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_12_EWM_OUT_B 0x13C 0x380 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_12_GPIO9_IO11 0x13C 0x380 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_12_FLEXPWM2_PWM2_X 0x13C 0x380 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_13_SPDIF_SR_CLK 0x140 0x384 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_13_PIT1_TRIGGER0 0x140 0x384 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_13_GPT1_CAPTURE2 0x140 0x384 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_13_FLEXSPI1_B_DATA02 0x140 0x384 0x56C 0x3 0x0 +#define IOMUXC_GPIO_AD_13_VIDEO_MUX_CSI_MCLK 0x140 0x384 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_13_GPIO_MUX3_IO12 0x140 0x384 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_13_ENET_TX_DATA02 0x140 0x384 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_13_FLEXIO2_D13 0x140 0x384 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_13_REF_CLK_32K 0x140 0x384 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_13_GPIO9_IO12 0x140 0x384 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_13_FLEXPWM2_PWM3_X 0x140 0x384 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_14_SPDIF_EXT_CLK 0x144 0x388 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_14_REF_CLK_24M 0x144 0x388 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_14_GPT1_COMPARE1 0x144 0x388 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_14_FLEXSPI1_B_DATA01 0x144 0x388 0x568 0x3 0x0 +#define IOMUXC_GPIO_AD_14_VIDEO_MUX_CSI_VSYNC 0x144 0x388 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_14_GPIO_MUX3_IO13 0x144 0x388 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_14_ENET_RX_CLK 0x144 0x388 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_14_FLEXIO2_D14 0x144 0x388 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_14_CCM_ENET_REF_CLK_25M 0x144 0x388 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_14_GPIO9_IO13 0x144 0x388 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_14_FLEXPWM3_PWM0_X 0x144 0x388 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_15_GPIO9_IO14 0x148 0x38C 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_15_FLEXPWM3_PWM1_X 0x148 0x38C 0x0 0xB 0x0 +#define IOMUXC_GPIO_AD_15_SPDIF_IN 0x148 0x38C 0x6B4 0x0 0x1 +#define IOMUXC_GPIO_AD_15_LPUART10_TXD 0x148 0x38C 0x628 0x1 0x0 +#define IOMUXC_GPIO_AD_15_GPT1_COMPARE2 0x148 0x38C 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_15_FLEXSPI1_B_DATA00 0x148 0x38C 0x564 0x3 0x0 +#define IOMUXC_GPIO_AD_15_VIDEO_MUX_CSI_HSYNC 0x148 0x38C 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_15_GPIO_MUX3_IO14 0x148 0x38C 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_15_ENET_TX_ER 0x148 0x38C 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_15_FLEXIO2_D15 0x148 0x38C 0x0 0x8 0x0 + +#define IOMUXC_GPIO_AD_16_SPDIF_OUT 0x14C 0x390 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_16_LPUART10_RXD 0x14C 0x390 0x624 0x1 0x0 +#define IOMUXC_GPIO_AD_16_GPT1_COMPARE3 0x14C 0x390 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_16_FLEXSPI1_B_SCLK 0x14C 0x390 0x578 0x3 0x0 +#define IOMUXC_GPIO_AD_16_VIDEO_MUX_CSI_DATA09 0x14C 0x390 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_16_GPIO_MUX3_IO15 0x14C 0x390 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_16_ENET_RX_DATA03 0x14C 0x390 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_16_FLEXIO2_D16 0x14C 0x390 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_16_ENET_1G_MDC 0x14C 0x390 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_16_GPIO9_IO15 0x14C 0x390 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_16_FLEXPWM3_PWM2_X 0x14C 0x390 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_17_SAI1_MCLK 0x150 0x394 0x66C 0x0 0x0 +#define IOMUXC_GPIO_AD_17_ACMP1_OUT 0x150 0x394 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_17_GPT1_CLK 0x150 0x394 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_17_FLEXSPI1_A_DQS 0x150 0x394 0x550 0x3 0x1 +#define IOMUXC_GPIO_AD_17_VIDEO_MUX_CSI_DATA08 0x150 0x394 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_17_GPIO_MUX3_IO16 0x150 0x394 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_17_ENET_RX_DATA02 0x150 0x394 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_17_FLEXIO2_D17 0x150 0x394 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_17_ENET_1G_MDIO 0x150 0x394 0x4C8 0x9 0x2 +#define IOMUXC_GPIO_AD_17_GPIO9_IO16 0x150 0x394 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_17_FLEXPWM3_PWM3_X 0x150 0x394 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_18_GPIO9_IO17 0x154 0x398 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_18_FLEXPWM4_PWM0_X 0x154 0x398 0x0 0xB 0x0 +#define IOMUXC_GPIO_AD_18_SAI1_RX_SYNC 0x154 0x398 0x678 0x0 0x0 +#define IOMUXC_GPIO_AD_18_ACMP2_OUT 0x154 0x398 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_18_LPSPI1_PCS1 0x154 0x398 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_18_FLEXSPI1_A_SS0_B 0x154 0x398 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_18_VIDEO_MUX_CSI_DATA07 0x154 0x398 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_18_GPIO_MUX3_IO17 0x154 0x398 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_18_ENET_CRS 0x154 0x398 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_18_FLEXIO2_D18 0x154 0x398 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_18_LPI2C2_SCL 0x154 0x398 0x5B4 0x9 0x1 + +#define IOMUXC_GPIO_AD_19_SAI1_RX_BCLK 0x158 0x39C 0x670 0x0 0x0 +#define IOMUXC_GPIO_AD_19_ACMP3_OUT 0x158 0x39C 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_19_LPSPI1_PCS2 0x158 0x39C 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_19_FLEXSPI1_A_SCLK 0x158 0x39C 0x574 0x3 0x0 +#define IOMUXC_GPIO_AD_19_VIDEO_MUX_CSI_DATA06 0x158 0x39C 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_19_GPIO_MUX3_IO18 0x158 0x39C 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_19_ENET_COL 0x158 0x39C 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_19_FLEXIO2_D19 0x158 0x39C 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_19_LPI2C2_SDA 0x158 0x39C 0x5B8 0x9 0x1 +#define IOMUXC_GPIO_AD_19_GPIO9_IO18 0x158 0x39C 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_19_FLEXPWM4_PWM1_X 0x158 0x39C 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_20_SAI1_RX_DATA00 0x15C 0x3A0 0x674 0x0 0x0 +#define IOMUXC_GPIO_AD_20_ACMP4_OUT 0x15C 0x3A0 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_20_LPSPI1_PCS3 0x15C 0x3A0 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_20_FLEXSPI1_A_DATA00 0x15C 0x3A0 0x554 0x3 0x0 +#define IOMUXC_GPIO_AD_20_VIDEO_MUX_CSI_DATA05 0x15C 0x3A0 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_20_GPIO_MUX3_IO19 0x15C 0x3A0 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_20_KPP_ROW07 0x15C 0x3A0 0x5A8 0x6 0x0 +#define IOMUXC_GPIO_AD_20_FLEXIO2_D20 0x15C 0x3A0 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_20_ENET_QOS_1588_EVENT2_OUT 0x15C 0x3A0 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_20_GPIO9_IO19 0x15C 0x3A0 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_20_FLEXPWM4_PWM2_X 0x15C 0x3A0 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_21_SAI1_TX_DATA00 0x160 0x3A4 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_21_LPSPI2_PCS1 0x160 0x3A4 0x5E0 0x2 0x0 +#define IOMUXC_GPIO_AD_21_FLEXSPI1_A_DATA01 0x160 0x3A4 0x558 0x3 0x0 +#define IOMUXC_GPIO_AD_21_VIDEO_MUX_CSI_DATA04 0x160 0x3A4 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_21_GPIO_MUX3_IO20 0x160 0x3A4 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_21_KPP_COL07 0x160 0x3A4 0x5A0 0x6 0x0 +#define IOMUXC_GPIO_AD_21_FLEXIO2_D21 0x160 0x3A4 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_21_ENET_QOS_1588_EVENT2_IN 0x160 0x3A4 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_21_GPIO9_IO20 0x160 0x3A4 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_21_FLEXPWM4_PWM3_X 0x160 0x3A4 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_22_GPIO9_IO21 0x164 0x3A8 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_22_SAI1_TX_BCLK 0x164 0x3A8 0x67C 0x0 0x0 +#define IOMUXC_GPIO_AD_22_LPSPI2_PCS2 0x164 0x3A8 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_22_FLEXSPI1_A_DATA02 0x164 0x3A8 0x55C 0x3 0x0 +#define IOMUXC_GPIO_AD_22_VIDEO_MUX_CSI_DATA03 0x164 0x3A8 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_22_GPIO_MUX3_IO21 0x164 0x3A8 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_22_KPP_ROW06 0x164 0x3A8 0x5A4 0x6 0x0 +#define IOMUXC_GPIO_AD_22_FLEXIO2_D22 0x164 0x3A8 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_22_ENET_QOS_1588_EVENT3_OUT 0x164 0x3A8 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_23_SAI1_TX_SYNC 0x168 0x3AC 0x680 0x0 0x0 +#define IOMUXC_GPIO_AD_23_LPSPI2_PCS3 0x168 0x3AC 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_23_FLEXSPI1_A_DATA03 0x168 0x3AC 0x560 0x3 0x0 +#define IOMUXC_GPIO_AD_23_VIDEO_MUX_CSI_DATA02 0x168 0x3AC 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_23_GPIO_MUX3_IO22 0x168 0x3AC 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_23_KPP_COL06 0x168 0x3AC 0x59C 0x6 0x0 +#define IOMUXC_GPIO_AD_23_FLEXIO2_D23 0x168 0x3AC 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_23_ENET_QOS_1588_EVENT3_IN 0x168 0x3AC 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_23_GPIO9_IO22 0x168 0x3AC 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_24_LPUART1_TXD 0x16C 0x3B0 0x620 0x0 0x0 +#define IOMUXC_GPIO_AD_24_LPSPI2_SCK 0x16C 0x3B0 0x5E4 0x1 0x0 +#define IOMUXC_GPIO_AD_24_VIDEO_MUX_CSI_DATA00 0x16C 0x3B0 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_24_ENET_RX_EN 0x16C 0x3B0 0x4B8 0x3 0x0 +#define IOMUXC_GPIO_AD_24_FLEXPWM2_PWM0_A 0x16C 0x3B0 0x518 0x4 0x1 +#define IOMUXC_GPIO_AD_24_GPIO_MUX3_IO23 0x16C 0x3B0 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_24_KPP_ROW05 0x16C 0x3B0 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_24_FLEXIO2_D24 0x16C 0x3B0 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_24_LPI2C4_SCL 0x16C 0x3B0 0x5C4 0x9 0x0 +#define IOMUXC_GPIO_AD_24_GPIO9_IO23 0x16C 0x3B0 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_25_GPIO9_IO24 0x170 0x3B4 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_25_LPUART1_RXD 0x170 0x3B4 0x61C 0x0 0x0 +#define IOMUXC_GPIO_AD_25_LPSPI2_PCS0 0x170 0x3B4 0x5DC 0x1 0x0 +#define IOMUXC_GPIO_AD_25_VIDEO_MUX_CSI_DATA01 0x170 0x3B4 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_25_ENET_RX_ER 0x170 0x3B4 0x4BC 0x3 0x0 +#define IOMUXC_GPIO_AD_25_FLEXPWM2_PWM0_B 0x170 0x3B4 0x524 0x4 0x1 +#define IOMUXC_GPIO_AD_25_GPIO_MUX3_IO24 0x170 0x3B4 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_25_KPP_COL05 0x170 0x3B4 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_25_FLEXIO2_D25 0x170 0x3B4 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_25_LPI2C4_SDA 0x170 0x3B4 0x5C8 0x9 0x0 + +#define IOMUXC_GPIO_AD_26_LPUART1_CTS_B 0x174 0x3B8 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_26_LPSPI2_SOUT 0x174 0x3B8 0x5EC 0x1 0x0 +#define IOMUXC_GPIO_AD_26_SEMC_CSX01 0x174 0x3B8 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_26_ENET_RX_DATA00 0x174 0x3B8 0x4B0 0x3 0x0 +#define IOMUXC_GPIO_AD_26_FLEXPWM2_PWM1_A 0x174 0x3B8 0x51C 0x4 0x1 +#define IOMUXC_GPIO_AD_26_GPIO_MUX3_IO25 0x174 0x3B8 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_26_KPP_ROW04 0x174 0x3B8 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_26_FLEXIO2_D26 0x174 0x3B8 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_26_ENET_QOS_MDC 0x174 0x3B8 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_26_GPIO9_IO25 0x174 0x3B8 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_26_USDHC2_CD_B 0x174 0x3B8 0x6D0 0xB 0x1 + +#define IOMUXC_GPIO_AD_27_LPUART1_RTS_B 0x178 0x3BC 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_27_LPSPI2_SIN 0x178 0x3BC 0x5E8 0x1 0x0 +#define IOMUXC_GPIO_AD_27_SEMC_CSX02 0x178 0x3BC 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_27_ENET_RX_DATA01 0x178 0x3BC 0x4B4 0x3 0x0 +#define IOMUXC_GPIO_AD_27_FLEXPWM2_PWM1_B 0x178 0x3BC 0x528 0x4 0x1 +#define IOMUXC_GPIO_AD_27_GPIO_MUX3_IO26 0x178 0x3BC 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_27_KPP_COL04 0x178 0x3BC 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_27_FLEXIO2_D27 0x178 0x3BC 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_27_ENET_QOS_MDIO 0x178 0x3BC 0x4EC 0x9 0x1 +#define IOMUXC_GPIO_AD_27_GPIO9_IO26 0x178 0x3BC 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_27_USDHC2_WP 0x178 0x3BC 0x6D4 0xB 0x1 + +#define IOMUXC_GPIO_AD_28_GPIO9_IO27 0x17C 0x3C0 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_28_USDHC2_VSELECT 0x17C 0x3C0 0x0 0xB 0x0 +#define IOMUXC_GPIO_AD_28_LPSPI1_SCK 0x17C 0x3C0 0x5D0 0x0 0x1 +#define IOMUXC_GPIO_AD_28_LPUART5_TXD 0x17C 0x3C0 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_28_SEMC_CSX03 0x17C 0x3C0 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_28_ENET_TX_EN 0x17C 0x3C0 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_28_FLEXPWM2_PWM2_A 0x17C 0x3C0 0x520 0x4 0x1 +#define IOMUXC_GPIO_AD_28_GPIO_MUX3_IO27 0x17C 0x3C0 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_28_KPP_ROW03 0x17C 0x3C0 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_28_FLEXIO2_D28 0x17C 0x3C0 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_28_VIDEO_MUX_EXT_DCIC1 0x17C 0x3C0 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_29_LPSPI1_PCS0 0x180 0x3C4 0x5CC 0x0 0x1 +#define IOMUXC_GPIO_AD_29_LPUART5_RXD 0x180 0x3C4 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_29_ENET_REF_CLK 0x180 0x3C4 0x4A8 0x2 0x0 +#define IOMUXC_GPIO_AD_29_ENET_TX_CLK 0x180 0x3C4 0x4C0 0x3 0x0 +#define IOMUXC_GPIO_AD_29_FLEXPWM2_PWM2_B 0x180 0x3C4 0x52C 0x4 0x1 +#define IOMUXC_GPIO_AD_29_GPIO_MUX3_IO28 0x180 0x3C4 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_29_KPP_COL03 0x180 0x3C4 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_29_FLEXIO2_D29 0x180 0x3C4 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_29_VIDEO_MUX_EXT_DCIC2 0x180 0x3C4 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_29_GPIO9_IO28 0x180 0x3C4 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_29_USDHC2_RESET_B 0x180 0x3C4 0x0 0xB 0x0 + +#define IOMUXC_GPIO_AD_30_LPSPI1_SOUT 0x184 0x3C8 0x5D8 0x0 0x1 +#define IOMUXC_GPIO_AD_30_USB_OTG2_OC 0x184 0x3C8 0x6B8 0x1 0x1 +#define IOMUXC_GPIO_AD_30_FLEXCAN2_TX 0x184 0x3C8 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_30_ENET_TX_DATA00 0x184 0x3C8 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_30_LPUART3_TXD 0x184 0x3C8 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_30_GPIO_MUX3_IO29 0x184 0x3C8 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_30_KPP_ROW02 0x184 0x3C8 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_30_FLEXIO2_D30 0x184 0x3C8 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_30_WDOG2_RESET_B_DEB 0x184 0x3C8 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_30_GPIO9_IO29 0x184 0x3C8 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_31_LPSPI1_SIN 0x188 0x3CC 0x5D4 0x0 0x1 +#define IOMUXC_GPIO_AD_31_USB_OTG2_PWR 0x188 0x3CC 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_31_FLEXCAN2_RX 0x188 0x3CC 0x49C 0x2 0x1 +#define IOMUXC_GPIO_AD_31_ENET_TX_DATA01 0x188 0x3CC 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_31_LPUART3_RXD 0x188 0x3CC 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_31_GPIO_MUX3_IO30 0x188 0x3CC 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_31_KPP_COL02 0x188 0x3CC 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_31_FLEXIO2_D31 0x188 0x3CC 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_31_WDOG1_RESET_B_DEB 0x188 0x3CC 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_31_GPIO9_IO30 0x188 0x3CC 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_32_GPIO9_IO31 0x18C 0x3D0 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_32_LPI2C1_SCL 0x18C 0x3D0 0x5AC 0x0 0x1 +#define IOMUXC_GPIO_AD_32_USBPHY2_OTG_ID 0x18C 0x3D0 0x6C4 0x1 0x1 +#define IOMUXC_GPIO_AD_32_PGMC_PMIC_RDY 0x18C 0x3D0 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_32_ENET_MDC 0x18C 0x3D0 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_32_USDHC1_CD_B 0x18C 0x3D0 0x6C8 0x4 0x0 +#define IOMUXC_GPIO_AD_32_GPIO_MUX3_IO31 0x18C 0x3D0 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_32_KPP_ROW01 0x18C 0x3D0 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_32_LPUART10_TXD 0x18C 0x3D0 0x628 0x8 0x1 +#define IOMUXC_GPIO_AD_32_ENET_1G_MDC 0x18C 0x3D0 0x0 0x9 0x0 + +#define IOMUXC_GPIO_AD_33_LPI2C1_SDA 0x190 0x3D4 0x5B0 0x0 0x1 +#define IOMUXC_GPIO_AD_33_USBPHY1_OTG_ID 0x190 0x3D4 0x6C0 0x1 0x1 +#define IOMUXC_GPIO_AD_33_XBAR1_INOUT17 0x190 0x3D4 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_33_ENET_MDIO 0x190 0x3D4 0x4AC 0x3 0x1 +#define IOMUXC_GPIO_AD_33_USDHC1_WP 0x190 0x3D4 0x6CC 0x4 0x0 +#define IOMUXC_GPIO_AD_33_GPIO_MUX4_IO00 0x190 0x3D4 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_33_KPP_COL01 0x190 0x3D4 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_33_LPUART10_RXD 0x190 0x3D4 0x624 0x8 0x1 +#define IOMUXC_GPIO_AD_33_ENET_1G_MDIO 0x190 0x3D4 0x4C8 0x9 0x3 +#define IOMUXC_GPIO_AD_33_GPIO10_IO00 0x190 0x3D4 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_34_ENET_1G_1588_EVENT0_IN 0x194 0x3D8 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_34_USB_OTG1_PWR 0x194 0x3D8 0x0 0x1 0x0 +#define IOMUXC_GPIO_AD_34_XBAR1_INOUT18 0x194 0x3D8 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_34_ENET_1588_EVENT0_IN 0x194 0x3D8 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_34_USDHC1_VSELECT 0x194 0x3D8 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_34_GPIO_MUX4_IO01 0x194 0x3D8 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_34_KPP_ROW00 0x194 0x3D8 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_34_LPUART10_CTS_B 0x194 0x3D8 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_34_WDOG1_ANY 0x194 0x3D8 0x0 0x9 0x0 +#define IOMUXC_GPIO_AD_34_GPIO10_IO01 0x194 0x3D8 0x0 0xA 0x0 + +#define IOMUXC_GPIO_AD_35_GPIO10_IO02 0x198 0x3DC 0x0 0xA 0x0 +#define IOMUXC_GPIO_AD_35_ENET_1G_1588_EVENT0_OUT 0x198 0x3DC 0x0 0x0 0x0 +#define IOMUXC_GPIO_AD_35_USB_OTG1_OC 0x198 0x3DC 0x6BC 0x1 0x1 +#define IOMUXC_GPIO_AD_35_XBAR1_INOUT19 0x198 0x3DC 0x0 0x2 0x0 +#define IOMUXC_GPIO_AD_35_ENET_1588_EVENT0_OUT 0x198 0x3DC 0x0 0x3 0x0 +#define IOMUXC_GPIO_AD_35_USDHC1_RESET_B 0x198 0x3DC 0x0 0x4 0x0 +#define IOMUXC_GPIO_AD_35_GPIO_MUX4_IO02 0x198 0x3DC 0x0 0x5 0x0 +#define IOMUXC_GPIO_AD_35_KPP_COL00 0x198 0x3DC 0x0 0x6 0x0 +#define IOMUXC_GPIO_AD_35_LPUART10_RTS_B 0x198 0x3DC 0x0 0x8 0x0 +#define IOMUXC_GPIO_AD_35_FLEXSPI1_B_SS1_B 0x198 0x3DC 0x0 0x9 0x0 + +#define IOMUXC_GPIO_SD_B1_00_USDHC1_CMD 0x19C 0x3E0 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B1_00_XBAR1_INOUT20 0x19C 0x3E0 0x6D8 0x2 0x1 +#define IOMUXC_GPIO_SD_B1_00_GPT4_CAPTURE1 0x19C 0x3E0 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B1_00_GPIO_MUX4_IO03 0x19C 0x3E0 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B1_00_FLEXSPI2_A_SS0_B 0x19C 0x3E0 0x0 0x6 0x0 +#define IOMUXC_GPIO_SD_B1_00_KPP_ROW07 0x19C 0x3E0 0x5A8 0x8 0x1 +#define IOMUXC_GPIO_SD_B1_00_GPIO10_IO03 0x19C 0x3E0 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B1_01_USDHC1_CLK 0x1A0 0x3E4 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B1_01_XBAR1_INOUT21 0x1A0 0x3E4 0x6DC 0x2 0x1 +#define IOMUXC_GPIO_SD_B1_01_GPT4_CAPTURE2 0x1A0 0x3E4 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B1_01_GPIO_MUX4_IO04 0x1A0 0x3E4 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B1_01_FLEXSPI2_A_SCLK 0x1A0 0x3E4 0x58C 0x6 0x1 +#define IOMUXC_GPIO_SD_B1_01_KPP_COL07 0x1A0 0x3E4 0x5A0 0x8 0x1 +#define IOMUXC_GPIO_SD_B1_01_GPIO10_IO04 0x1A0 0x3E4 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B1_02_GPIO10_IO05 0x1A4 0x3E8 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B1_02_USDHC1_DATA0 0x1A4 0x3E8 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B1_02_XBAR1_INOUT22 0x1A4 0x3E8 0x6E0 0x2 0x1 +#define IOMUXC_GPIO_SD_B1_02_GPT4_COMPARE1 0x1A4 0x3E8 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B1_02_GPIO_MUX4_IO05 0x1A4 0x3E8 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B1_02_FLEXSPI2_A_DATA00 0x1A4 0x3E8 0x57C 0x6 0x1 +#define IOMUXC_GPIO_SD_B1_02_KPP_ROW06 0x1A4 0x3E8 0x5A4 0x8 0x1 +#define IOMUXC_GPIO_SD_B1_02_FLEXSPI1_A_SS1_B 0x1A4 0x3E8 0x0 0x9 0x0 + +#define IOMUXC_GPIO_SD_B1_03_USDHC1_DATA1 0x1A8 0x3EC 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B1_03_XBAR1_INOUT23 0x1A8 0x3EC 0x6E4 0x2 0x1 +#define IOMUXC_GPIO_SD_B1_03_GPT4_COMPARE2 0x1A8 0x3EC 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B1_03_GPIO_MUX4_IO06 0x1A8 0x3EC 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B1_03_FLEXSPI2_A_DATA01 0x1A8 0x3EC 0x580 0x6 0x1 +#define IOMUXC_GPIO_SD_B1_03_KPP_COL06 0x1A8 0x3EC 0x59C 0x8 0x1 +#define IOMUXC_GPIO_SD_B1_03_FLEXSPI1_B_SS1_B 0x1A8 0x3EC 0x0 0x9 0x0 +#define IOMUXC_GPIO_SD_B1_03_GPIO10_IO06 0x1A8 0x3EC 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B1_04_USDHC1_DATA2 0x1AC 0x3F0 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B1_04_XBAR1_INOUT24 0x1AC 0x3F0 0x6E8 0x2 0x1 +#define IOMUXC_GPIO_SD_B1_04_GPT4_COMPARE3 0x1AC 0x3F0 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B1_04_GPIO_MUX4_IO07 0x1AC 0x3F0 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B1_04_FLEXSPI2_A_DATA02 0x1AC 0x3F0 0x584 0x6 0x1 +#define IOMUXC_GPIO_SD_B1_04_FLEXSPI1_B_SS0_B 0x1AC 0x3F0 0x0 0x8 0x0 +#define IOMUXC_GPIO_SD_B1_04_ENET_QOS_1588_EVENT2_AUX_IN 0x1AC 0x3F0 0x0 0x9 0x0 +#define IOMUXC_GPIO_SD_B1_04_GPIO10_IO07 0x1AC 0x3F0 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B1_05_GPIO10_IO08 0x1B0 0x3F4 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B1_05_USDHC1_DATA3 0x1B0 0x3F4 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B1_05_XBAR1_INOUT25 0x1B0 0x3F4 0x6EC 0x2 0x1 +#define IOMUXC_GPIO_SD_B1_05_GPT4_CLK 0x1B0 0x3F4 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B1_05_GPIO_MUX4_IO08 0x1B0 0x3F4 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B1_05_FLEXSPI2_A_DATA03 0x1B0 0x3F4 0x588 0x6 0x1 +#define IOMUXC_GPIO_SD_B1_05_FLEXSPI1_B_DQS 0x1B0 0x3F4 0x0 0x8 0x0 +#define IOMUXC_GPIO_SD_B1_05_ENET_QOS_1588_EVENT3_AUX_IN 0x1B0 0x3F4 0x0 0x9 0x0 + +#define IOMUXC_GPIO_SD_B2_00_GPIO10_IO09 0x1B4 0x3F8 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_00_USDHC2_DATA3 0x1B4 0x3F8 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_00_FLEXSPI1_B_DATA03 0x1B4 0x3F8 0x570 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_00_ENET_1G_RX_EN 0x1B4 0x3F8 0x4E0 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_00_LPUART9_TXD 0x1B4 0x3F8 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_00_LPSPI4_SCK 0x1B4 0x3F8 0x610 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_00_GPIO_MUX4_IO09 0x1B4 0x3F8 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SD_B2_01_USDHC2_DATA2 0x1B8 0x3FC 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_01_FLEXSPI1_B_DATA02 0x1B8 0x3FC 0x56C 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_01_ENET_1G_RX_CLK 0x1B8 0x3FC 0x4CC 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_01_LPUART9_RXD 0x1B8 0x3FC 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_01_LPSPI4_PCS0 0x1B8 0x3FC 0x60C 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_01_GPIO_MUX4_IO10 0x1B8 0x3FC 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_01_GPIO10_IO10 0x1B8 0x3FC 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B2_02_GPIO10_IO11 0x1BC 0x400 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_02_USDHC2_DATA1 0x1BC 0x400 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_02_FLEXSPI1_B_DATA01 0x1BC 0x400 0x568 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_02_ENET_1G_RX_DATA00 0x1BC 0x400 0x4D0 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_02_LPUART9_CTS_B 0x1BC 0x400 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_02_LPSPI4_SOUT 0x1BC 0x400 0x618 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_02_GPIO_MUX4_IO11 0x1BC 0x400 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SD_B2_03_GPIO10_IO12 0x1C0 0x404 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_03_USDHC2_DATA0 0x1C0 0x404 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_03_FLEXSPI1_B_DATA00 0x1C0 0x404 0x564 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_03_ENET_1G_RX_DATA01 0x1C0 0x404 0x4D4 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_03_LPUART9_RTS_B 0x1C0 0x404 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_03_LPSPI4_SIN 0x1C0 0x404 0x614 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_03_GPIO_MUX4_IO12 0x1C0 0x404 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SD_B2_04_USDHC2_CLK 0x1C4 0x408 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_04_FLEXSPI1_B_SCLK 0x1C4 0x408 0x578 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_04_ENET_1G_RX_DATA02 0x1C4 0x408 0x4D8 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_04_FLEXSPI1_A_SS1_B 0x1C4 0x408 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_04_LPSPI4_PCS1 0x1C4 0x408 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_04_GPIO_MUX4_IO13 0x1C4 0x408 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_04_GPIO10_IO13 0x1C4 0x408 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B2_05_GPIO10_IO14 0x1C8 0x40C 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_05_USDHC2_CMD 0x1C8 0x40C 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_05_FLEXSPI1_A_DQS 0x1C8 0x40C 0x550 0x1 0x2 +#define IOMUXC_GPIO_SD_B2_05_ENET_1G_RX_DATA03 0x1C8 0x40C 0x4DC 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_05_FLEXSPI1_B_SS0_B 0x1C8 0x40C 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_05_LPSPI4_PCS2 0x1C8 0x40C 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_05_GPIO_MUX4_IO14 0x1C8 0x40C 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SD_B2_06_GPIO10_IO15 0x1CC 0x410 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_06_USDHC2_RESET_B 0x1CC 0x410 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_06_FLEXSPI1_A_SS0_B 0x1CC 0x410 0x0 0x1 0x0 +#define IOMUXC_GPIO_SD_B2_06_ENET_1G_TX_DATA03 0x1CC 0x410 0x0 0x2 0x0 +#define IOMUXC_GPIO_SD_B2_06_LPSPI4_PCS3 0x1CC 0x410 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_06_GPT6_CAPTURE1 0x1CC 0x410 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_06_GPIO_MUX4_IO15 0x1CC 0x410 0x0 0x5 0x0 + +#define IOMUXC_GPIO_SD_B2_07_USDHC2_STROBE 0x1D0 0x414 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_07_FLEXSPI1_A_SCLK 0x1D0 0x414 0x574 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_07_ENET_1G_TX_DATA02 0x1D0 0x414 0x0 0x2 0x0 +#define IOMUXC_GPIO_SD_B2_07_LPUART3_CTS_B 0x1D0 0x414 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_07_GPT6_CAPTURE2 0x1D0 0x414 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_07_GPIO_MUX4_IO16 0x1D0 0x414 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_07_LPSPI2_SCK 0x1D0 0x414 0x5E4 0x6 0x1 +#define IOMUXC_GPIO_SD_B2_07_ENET_TX_ER 0x1D0 0x414 0x0 0x8 0x0 +#define IOMUXC_GPIO_SD_B2_07_ENET_QOS_REF_CLK 0x1D0 0x414 0x4A0 0x9 0x1 +#define IOMUXC_GPIO_SD_B2_07_GPIO10_IO16 0x1D0 0x414 0x0 0xA 0x0 + +#define IOMUXC_GPIO_SD_B2_08_GPIO10_IO17 0x1D4 0x418 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_08_USDHC2_DATA4 0x1D4 0x418 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_08_FLEXSPI1_A_DATA00 0x1D4 0x418 0x554 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_08_ENET_1G_TX_DATA01 0x1D4 0x418 0x0 0x2 0x0 +#define IOMUXC_GPIO_SD_B2_08_LPUART3_RTS_B 0x1D4 0x418 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_08_GPT6_COMPARE1 0x1D4 0x418 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_08_GPIO_MUX4_IO17 0x1D4 0x418 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_08_LPSPI2_PCS0 0x1D4 0x418 0x5DC 0x6 0x1 + +#define IOMUXC_GPIO_SD_B2_09_GPIO10_IO18 0x1D8 0x41C 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_09_USDHC2_DATA5 0x1D8 0x41C 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_09_FLEXSPI1_A_DATA01 0x1D8 0x41C 0x558 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_09_ENET_1G_TX_DATA00 0x1D8 0x41C 0x0 0x2 0x0 +#define IOMUXC_GPIO_SD_B2_09_LPUART5_CTS_B 0x1D8 0x41C 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_09_GPT6_COMPARE2 0x1D8 0x41C 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_09_GPIO_MUX4_IO18 0x1D8 0x41C 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_09_LPSPI2_SOUT 0x1D8 0x41C 0x5EC 0x6 0x1 + +#define IOMUXC_GPIO_SD_B2_10_GPIO10_IO19 0x1DC 0x420 0x0 0xA 0x0 +#define IOMUXC_GPIO_SD_B2_10_USDHC2_DATA6 0x1DC 0x420 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_10_FLEXSPI1_A_DATA02 0x1DC 0x420 0x55C 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_10_ENET_1G_TX_EN 0x1DC 0x420 0x0 0x2 0x0 +#define IOMUXC_GPIO_SD_B2_10_LPUART5_RTS_B 0x1DC 0x420 0x0 0x3 0x0 +#define IOMUXC_GPIO_SD_B2_10_GPT6_COMPARE3 0x1DC 0x420 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_10_GPIO_MUX4_IO19 0x1DC 0x420 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_10_LPSPI2_SIN 0x1DC 0x420 0x5E8 0x6 0x1 + +#define IOMUXC_GPIO_SD_B2_11_USDHC2_DATA7 0x1E0 0x424 0x0 0x0 0x0 +#define IOMUXC_GPIO_SD_B2_11_FLEXSPI1_A_DATA03 0x1E0 0x424 0x560 0x1 0x1 +#define IOMUXC_GPIO_SD_B2_11_ENET_1G_TX_CLK_IO 0x1E0 0x424 0x4E8 0x2 0x1 +#define IOMUXC_GPIO_SD_B2_11_ENET_1G_REF_CLK 0x1E0 0x424 0x4C4 0x3 0x1 +#define IOMUXC_GPIO_SD_B2_11_GPT6_CLK 0x1E0 0x424 0x0 0x4 0x0 +#define IOMUXC_GPIO_SD_B2_11_GPIO_MUX4_IO20 0x1E0 0x424 0x0 0x5 0x0 +#define IOMUXC_GPIO_SD_B2_11_LPSPI2_PCS1 0x1E0 0x424 0x5E0 0x6 0x1 +#define IOMUXC_GPIO_SD_B2_11_GPIO10_IO20 0x1E0 0x424 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_00_VIDEO_MUX_LCDIF_CLK 0x1E4 0x428 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_00_ENET_1G_RX_EN 0x1E4 0x428 0x4E0 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_00_TMR1_TIMER0 0x1E4 0x428 0x63C 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_00_XBAR1_INOUT26 0x1E4 0x428 0x6F0 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_00_GPIO_MUX4_IO21 0x1E4 0x428 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_00_ENET_QOS_RX_EN 0x1E4 0x428 0x4F8 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_00_GPIO10_IO21 0x1E4 0x428 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_01_VIDEO_MUX_LCDIF_ENABLE 0x1E8 0x42C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_01_ENET_1G_RX_CLK 0x1E8 0x42C 0x4CC 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_01_ENET_1G_RX_ER 0x1E8 0x42C 0x4E4 0x2 0x1 +#define IOMUXC_GPIO_DISP_B1_01_TMR1_TIMER1 0x1E8 0x42C 0x640 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_01_XBAR1_INOUT27 0x1E8 0x42C 0x6F4 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_01_GPIO_MUX4_IO22 0x1E8 0x42C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_01_ENET_QOS_RX_CLK 0x1E8 0x42C 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_01_ENET_QOS_RX_ER 0x1E8 0x42C 0x4FC 0x9 0x0 +#define IOMUXC_GPIO_DISP_B1_01_GPIO10_IO22 0x1E8 0x42C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_02_GPIO10_IO23 0x1EC 0x430 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B1_02_VIDEO_MUX_LCDIF_HSYNC 0x1EC 0x430 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_02_ENET_1G_RX_DATA00 0x1EC 0x430 0x4D0 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_02_LPI2C3_SCL 0x1EC 0x430 0x5BC 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_02_TMR1_TIMER2 0x1EC 0x430 0x644 0x3 0x1 +#define IOMUXC_GPIO_DISP_B1_02_XBAR1_INOUT28 0x1EC 0x430 0x6F8 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_02_GPIO_MUX4_IO23 0x1EC 0x430 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_02_ENET_QOS_RX_DATA00 0x1EC 0x430 0x4F0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_02_LPUART1_TXD 0x1EC 0x430 0x620 0x9 0x1 + +#define IOMUXC_GPIO_DISP_B1_03_VIDEO_MUX_LCDIF_VSYNC 0x1F0 0x434 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_03_ENET_1G_RX_DATA01 0x1F0 0x434 0x4D4 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_03_LPI2C3_SDA 0x1F0 0x434 0x5C0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_03_TMR2_TIMER0 0x1F0 0x434 0x648 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_03_XBAR1_INOUT29 0x1F0 0x434 0x6FC 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_03_GPIO_MUX4_IO24 0x1F0 0x434 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_03_ENET_QOS_RX_DATA01 0x1F0 0x434 0x4F4 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_03_LPUART1_RXD 0x1F0 0x434 0x61C 0x9 0x1 +#define IOMUXC_GPIO_DISP_B1_03_GPIO10_IO24 0x1F0 0x434 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_04_VIDEO_MUX_LCDIF_DATA00 0x1F4 0x438 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_04_ENET_1G_RX_DATA02 0x1F4 0x438 0x4D8 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_04_LPUART4_RXD 0x1F4 0x438 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_04_TMR2_TIMER1 0x1F4 0x438 0x64C 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_04_XBAR1_INOUT30 0x1F4 0x438 0x700 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_04_GPIO_MUX4_IO25 0x1F4 0x438 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_04_ENET_QOS_RX_DATA02 0x1F4 0x438 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_04_LPSPI3_SCK 0x1F4 0x438 0x600 0x9 0x1 +#define IOMUXC_GPIO_DISP_B1_04_GPIO10_IO25 0x1F4 0x438 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_05_GPIO10_IO26 0x1F8 0x43C 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B1_05_VIDEO_MUX_LCDIF_DATA01 0x1F8 0x43C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_05_ENET_1G_RX_DATA03 0x1F8 0x43C 0x4DC 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_05_LPUART4_CTS_B 0x1F8 0x43C 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_05_TMR2_TIMER2 0x1F8 0x43C 0x650 0x3 0x1 +#define IOMUXC_GPIO_DISP_B1_05_XBAR1_INOUT31 0x1F8 0x43C 0x704 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_05_GPIO_MUX4_IO26 0x1F8 0x43C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_05_ENET_QOS_RX_DATA03 0x1F8 0x43C 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_05_LPSPI3_SIN 0x1F8 0x43C 0x604 0x9 0x1 + +#define IOMUXC_GPIO_DISP_B1_06_VIDEO_MUX_LCDIF_DATA02 0x1FC 0x440 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_06_ENET_1G_TX_DATA03 0x1FC 0x440 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B1_06_LPUART4_TXD 0x1FC 0x440 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_06_TMR3_TIMER0 0x1FC 0x440 0x654 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_06_XBAR1_INOUT32 0x1FC 0x440 0x708 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_06_GPIO_MUX4_IO27 0x1FC 0x440 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_06_SRC_BT_CFG00 0x1FC 0x440 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B1_06_ENET_QOS_TX_DATA03 0x1FC 0x440 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_06_LPSPI3_SOUT 0x1FC 0x440 0x608 0x9 0x1 +#define IOMUXC_GPIO_DISP_B1_06_GPIO10_IO27 0x1FC 0x440 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_07_VIDEO_MUX_LCDIF_DATA03 0x200 0x444 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_07_ENET_1G_TX_DATA02 0x200 0x444 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B1_07_LPUART4_RTS_B 0x200 0x444 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_07_TMR3_TIMER1 0x200 0x444 0x658 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_07_XBAR1_INOUT33 0x200 0x444 0x70C 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_07_GPIO_MUX4_IO28 0x200 0x444 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_07_SRC_BT_CFG01 0x200 0x444 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B1_07_ENET_QOS_TX_DATA02 0x200 0x444 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_07_LPSPI3_PCS0 0x200 0x444 0x5F0 0x9 0x1 +#define IOMUXC_GPIO_DISP_B1_07_GPIO10_IO28 0x200 0x444 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_08_GPIO10_IO29 0x204 0x448 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B1_08_VIDEO_MUX_LCDIF_DATA04 0x204 0x448 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_08_ENET_1G_TX_DATA01 0x204 0x448 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B1_08_USDHC1_CD_B 0x204 0x448 0x6C8 0x2 0x1 +#define IOMUXC_GPIO_DISP_B1_08_TMR3_TIMER2 0x204 0x448 0x65C 0x3 0x1 +#define IOMUXC_GPIO_DISP_B1_08_XBAR1_INOUT34 0x204 0x448 0x710 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_08_GPIO_MUX4_IO29 0x204 0x448 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_08_SRC_BT_CFG02 0x204 0x448 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B1_08_ENET_QOS_TX_DATA01 0x204 0x448 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_08_LPSPI3_PCS1 0x204 0x448 0x5F4 0x9 0x1 + +#define IOMUXC_GPIO_DISP_B1_09_VIDEO_MUX_LCDIF_DATA05 0x208 0x44C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_09_ENET_1G_TX_DATA00 0x208 0x44C 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B1_09_USDHC1_WP 0x208 0x44C 0x6CC 0x2 0x1 +#define IOMUXC_GPIO_DISP_B1_09_TMR4_TIMER0 0x208 0x44C 0x660 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_09_XBAR1_INOUT35 0x208 0x44C 0x714 0x4 0x1 +#define IOMUXC_GPIO_DISP_B1_09_GPIO_MUX4_IO30 0x208 0x44C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_09_SRC_BT_CFG03 0x208 0x44C 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B1_09_ENET_QOS_TX_DATA00 0x208 0x44C 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_09_LPSPI3_PCS2 0x208 0x44C 0x5F8 0x9 0x1 +#define IOMUXC_GPIO_DISP_B1_09_GPIO10_IO30 0x208 0x44C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_10_VIDEO_MUX_LCDIF_DATA06 0x20C 0x450 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_10_ENET_1G_TX_EN 0x20C 0x450 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B1_10_USDHC1_RESET_B 0x20C 0x450 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B1_10_TMR4_TIMER1 0x20C 0x450 0x664 0x3 0x2 +#define IOMUXC_GPIO_DISP_B1_10_XBAR1_INOUT36 0x20C 0x450 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B1_10_GPIO_MUX4_IO31 0x20C 0x450 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_10_SRC_BT_CFG04 0x20C 0x450 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B1_10_ENET_QOS_TX_EN 0x20C 0x450 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_10_LPSPI3_PCS3 0x20C 0x450 0x5FC 0x9 0x1 +#define IOMUXC_GPIO_DISP_B1_10_GPIO10_IO31 0x20C 0x450 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B1_11_VIDEO_MUX_LCDIF_DATA07 0x210 0x454 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B1_11_ENET_1G_TX_CLK_IO 0x210 0x454 0x4E8 0x1 0x2 +#define IOMUXC_GPIO_DISP_B1_11_ENET_1G_REF_CLK 0x210 0x454 0x4C4 0x2 0x2 +#define IOMUXC_GPIO_DISP_B1_11_TMR4_TIMER2 0x210 0x454 0x668 0x3 0x1 +#define IOMUXC_GPIO_DISP_B1_11_XBAR1_INOUT37 0x210 0x454 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B1_11_GPIO_MUX5_IO00 0x210 0x454 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B1_11_SRC_BT_CFG05 0x210 0x454 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B1_11_ENET_QOS_TX_CLK 0x210 0x454 0x4A4 0x8 0x0 +#define IOMUXC_GPIO_DISP_B1_11_ENET_QOS_REF_CLK 0x210 0x454 0x4A0 0x9 0x2 +#define IOMUXC_GPIO_DISP_B1_11_GPIO11_IO00 0x210 0x454 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B2_00_GPIO11_IO01 0x214 0x458 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_00_VIDEO_MUX_LCDIF_DATA08 0x214 0x458 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_00_WDOG1_B 0x214 0x458 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_00_MQS_RIGHT 0x214 0x458 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_00_ENET_1G_TX_ER 0x214 0x458 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_00_SAI1_TX_DATA03 0x214 0x458 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_00_GPIO_MUX5_IO01 0x214 0x458 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_00_SRC_BT_CFG06 0x214 0x458 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_00_ENET_QOS_TX_ER 0x214 0x458 0x0 0x8 0x0 + +#define IOMUXC_GPIO_DISP_B2_01_VIDEO_MUX_LCDIF_DATA09 0x218 0x45C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_01_USDHC1_VSELECT 0x218 0x45C 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_01_MQS_LEFT 0x218 0x45C 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_01_WDOG2_B 0x218 0x45C 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_01_SAI1_TX_DATA02 0x218 0x45C 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_01_GPIO_MUX5_IO02 0x218 0x45C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_01_SRC_BT_CFG07 0x218 0x45C 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_01_EWM_OUT_B 0x218 0x45C 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_01_CCM_ENET_REF_CLK_25M 0x218 0x45C 0x0 0x9 0x0 +#define IOMUXC_GPIO_DISP_B2_01_GPIO11_IO02 0x218 0x45C 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B2_02_GPIO11_IO03 0x21C 0x460 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_02_VIDEO_MUX_LCDIF_DATA10 0x21C 0x460 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_02_ENET_TX_DATA00 0x21C 0x460 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_02_PIT1_TRIGGER3 0x21C 0x460 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_02_ARM_TRACE00 0x21C 0x460 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_02_SAI1_TX_DATA01 0x21C 0x460 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_02_GPIO_MUX5_IO03 0x21C 0x460 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_02_SRC_BT_CFG08 0x21C 0x460 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_02_ENET_QOS_TX_DATA00 0x21C 0x460 0x0 0x8 0x0 + +#define IOMUXC_GPIO_DISP_B2_03_GPIO11_IO04 0x220 0x464 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_03_VIDEO_MUX_LCDIF_DATA11 0x220 0x464 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_03_ENET_TX_DATA01 0x220 0x464 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_03_PIT1_TRIGGER2 0x220 0x464 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_03_ARM_TRACE01 0x220 0x464 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_03_SAI1_MCLK 0x220 0x464 0x66C 0x4 0x1 +#define IOMUXC_GPIO_DISP_B2_03_GPIO_MUX5_IO04 0x220 0x464 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_03_SRC_BT_CFG09 0x220 0x464 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_03_ENET_QOS_TX_DATA01 0x220 0x464 0x0 0x8 0x0 + +#define IOMUXC_GPIO_DISP_B2_04_VIDEO_MUX_LCDIF_DATA12 0x224 0x468 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_04_ENET_TX_EN 0x224 0x468 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_04_PIT1_TRIGGER1 0x224 0x468 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_04_ARM_TRACE02 0x224 0x468 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_04_SAI1_RX_SYNC 0x224 0x468 0x678 0x4 0x1 +#define IOMUXC_GPIO_DISP_B2_04_GPIO_MUX5_IO05 0x224 0x468 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_04_SRC_BT_CFG10 0x224 0x468 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_04_ENET_QOS_TX_EN 0x224 0x468 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_04_GPIO11_IO05 0x224 0x468 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B2_05_GPIO11_IO06 0x228 0x46C 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_05_VIDEO_MUX_LCDIF_DATA13 0x228 0x46C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_05_ENET_TX_CLK 0x228 0x46C 0x4C0 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_05_ENET_REF_CLK 0x228 0x46C 0x4A8 0x2 0x1 +#define IOMUXC_GPIO_DISP_B2_05_ARM_TRACE03 0x228 0x46C 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_05_SAI1_RX_BCLK 0x228 0x46C 0x670 0x4 0x1 +#define IOMUXC_GPIO_DISP_B2_05_GPIO_MUX5_IO06 0x228 0x46C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_05_SRC_BT_CFG11 0x228 0x46C 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_05_ENET_QOS_TX_CLK 0x228 0x46C 0x4A4 0x8 0x1 + +#define IOMUXC_GPIO_DISP_B2_06_GPIO11_IO07 0x22C 0x470 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_06_VIDEO_MUX_LCDIF_DATA14 0x22C 0x470 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_06_ENET_RX_DATA00 0x22C 0x470 0x4B0 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_06_LPUART7_TXD 0x22C 0x470 0x630 0x2 0x1 +#define IOMUXC_GPIO_DISP_B2_06_ARM_TRACE_CLK 0x22C 0x470 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_06_SAI1_RX_DATA00 0x22C 0x470 0x674 0x4 0x1 +#define IOMUXC_GPIO_DISP_B2_06_GPIO_MUX5_IO07 0x22C 0x470 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_06_ENET_QOS_RX_DATA00 0x22C 0x470 0x4F0 0x8 0x1 + +#define IOMUXC_GPIO_DISP_B2_07_VIDEO_MUX_LCDIF_DATA15 0x230 0x474 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_07_ENET_RX_DATA01 0x230 0x474 0x4B4 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_07_LPUART7_RXD 0x230 0x474 0x62C 0x2 0x1 +#define IOMUXC_GPIO_DISP_B2_07_ARM_TRACE_SWO 0x230 0x474 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_07_SAI1_TX_DATA00 0x230 0x474 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_07_GPIO_MUX5_IO08 0x230 0x474 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_07_ENET_QOS_RX_DATA01 0x230 0x474 0x4F4 0x8 0x1 +#define IOMUXC_GPIO_DISP_B2_07_GPIO11_IO08 0x230 0x474 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B2_08_GPIO11_IO09 0x234 0x478 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_08_VIDEO_MUX_LCDIF_DATA16 0x234 0x478 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_08_ENET_RX_EN 0x234 0x478 0x4B8 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_08_LPUART8_TXD 0x234 0x478 0x638 0x2 0x1 +#define IOMUXC_GPIO_DISP_B2_08_ARM_CM7_EVENTO 0x234 0x478 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_08_SAI1_TX_BCLK 0x234 0x478 0x67C 0x4 0x1 +#define IOMUXC_GPIO_DISP_B2_08_GPIO_MUX5_IO09 0x234 0x478 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_08_ENET_QOS_RX_EN 0x234 0x478 0x4F8 0x8 0x1 +#define IOMUXC_GPIO_DISP_B2_08_LPUART1_TXD 0x234 0x478 0x620 0x9 0x2 + +#define IOMUXC_GPIO_DISP_B2_09_GPIO11_IO10 0x238 0x47C 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_09_VIDEO_MUX_LCDIF_DATA17 0x238 0x47C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_09_ENET_RX_ER 0x238 0x47C 0x4BC 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_09_LPUART8_RXD 0x238 0x47C 0x634 0x2 0x1 +#define IOMUXC_GPIO_DISP_B2_09_ARM_CM7_EVENTI 0x238 0x47C 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_09_SAI1_TX_SYNC 0x238 0x47C 0x680 0x4 0x1 +#define IOMUXC_GPIO_DISP_B2_09_GPIO_MUX5_IO10 0x238 0x47C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_09_ENET_QOS_RX_ER 0x238 0x47C 0x4FC 0x8 0x1 +#define IOMUXC_GPIO_DISP_B2_09_LPUART1_RXD 0x238 0x47C 0x61C 0x9 0x2 + +#define IOMUXC_GPIO_DISP_B2_10_GPIO11_IO11 0x23C 0x480 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_10_VIDEO_MUX_LCDIF_DATA18 0x23C 0x480 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_10_EMVSIM2_IO 0x23C 0x480 0x6A8 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_10_LPUART2_TXD 0x23C 0x480 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_10_WDOG2_RESET_B_DEB 0x23C 0x480 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_10_XBAR1_INOUT38 0x23C 0x480 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_10_GPIO_MUX5_IO11 0x23C 0x480 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_10_LPI2C3_SCL 0x23C 0x480 0x5BC 0x6 0x1 +#define IOMUXC_GPIO_DISP_B2_10_ENET_QOS_RX_ER 0x23C 0x480 0x4FC 0x8 0x2 +#define IOMUXC_GPIO_DISP_B2_10_SPDIF_IN 0x23C 0x480 0x6B4 0x9 0x2 + +#define IOMUXC_GPIO_DISP_B2_11_VIDEO_MUX_LCDIF_DATA19 0x240 0x484 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_11_EMVSIM2_CLK 0x240 0x484 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_11_LPUART2_RXD 0x240 0x484 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_11_WDOG1_RESET_B_DEB 0x240 0x484 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_11_XBAR1_INOUT39 0x240 0x484 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_11_GPIO_MUX5_IO12 0x240 0x484 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_11_LPI2C3_SDA 0x240 0x484 0x5C0 0x6 0x1 +#define IOMUXC_GPIO_DISP_B2_11_ENET_QOS_CRS 0x240 0x484 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_11_SPDIF_OUT 0x240 0x484 0x0 0x9 0x0 +#define IOMUXC_GPIO_DISP_B2_11_GPIO11_IO12 0x240 0x484 0x0 0xA 0x0 + +#define IOMUXC_GPIO_DISP_B2_12_GPIO11_IO13 0x244 0x488 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_12_VIDEO_MUX_LCDIF_DATA20 0x244 0x488 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_12_EMVSIM2_RST 0x244 0x488 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_12_FLEXCAN1_TX 0x244 0x488 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_12_LPUART2_CTS_B 0x244 0x488 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_12_XBAR1_INOUT40 0x244 0x488 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_12_GPIO_MUX5_IO13 0x244 0x488 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_12_LPI2C4_SCL 0x244 0x488 0x5C4 0x6 0x1 +#define IOMUXC_GPIO_DISP_B2_12_ENET_QOS_COL 0x244 0x488 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_12_LPSPI4_SCK 0x244 0x488 0x610 0x9 0x1 + +#define IOMUXC_GPIO_DISP_B2_13_GPIO11_IO14 0x248 0x48C 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_13_VIDEO_MUX_LCDIF_DATA21 0x248 0x48C 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_13_EMVSIM2_SVEN 0x248 0x48C 0x0 0x1 0x0 +#define IOMUXC_GPIO_DISP_B2_13_FLEXCAN1_RX 0x248 0x48C 0x498 0x2 0x1 +#define IOMUXC_GPIO_DISP_B2_13_LPUART2_RTS_B 0x248 0x48C 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_13_ENET_REF_CLK 0x248 0x48C 0x4A8 0x4 0x2 +#define IOMUXC_GPIO_DISP_B2_13_GPIO_MUX5_IO14 0x248 0x48C 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_13_LPI2C4_SDA 0x248 0x48C 0x5C8 0x6 0x1 +#define IOMUXC_GPIO_DISP_B2_13_ENET_QOS_1588_EVENT0_OUT 0x248 0x48C 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_13_LPSPI4_SIN 0x248 0x48C 0x614 0x9 0x1 + +#define IOMUXC_GPIO_DISP_B2_14_GPIO_MUX5_IO15 0x24C 0x490 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_14_FLEXCAN1_TX 0x24C 0x490 0x0 0x6 0x0 +#define IOMUXC_GPIO_DISP_B2_14_ENET_QOS_1588_EVENT0_IN 0x24C 0x490 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_14_LPSPI4_SOUT 0x24C 0x490 0x618 0x9 0x1 +#define IOMUXC_GPIO_DISP_B2_14_GPIO11_IO15 0x24C 0x490 0x0 0xA 0x0 +#define IOMUXC_GPIO_DISP_B2_14_VIDEO_MUX_LCDIF_DATA22 0x24C 0x490 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_14_EMVSIM2_PD 0x24C 0x490 0x6AC 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_14_WDOG2_B 0x24C 0x490 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_14_VIDEO_MUX_EXT_DCIC1 0x24C 0x490 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_14_ENET_1G_REF_CLK 0x24C 0x490 0x4C4 0x4 0x3 + +#define IOMUXC_GPIO_DISP_B2_15_VIDEO_MUX_LCDIF_DATA23 0x250 0x494 0x0 0x0 0x0 +#define IOMUXC_GPIO_DISP_B2_15_EMVSIM2_POWER_FAIL 0x250 0x494 0x6B0 0x1 0x1 +#define IOMUXC_GPIO_DISP_B2_15_WDOG1_B 0x250 0x494 0x0 0x2 0x0 +#define IOMUXC_GPIO_DISP_B2_15_VIDEO_MUX_EXT_DCIC2 0x250 0x494 0x0 0x3 0x0 +#define IOMUXC_GPIO_DISP_B2_15_PIT1_TRIGGER0 0x250 0x494 0x0 0x4 0x0 +#define IOMUXC_GPIO_DISP_B2_15_GPIO_MUX5_IO16 0x250 0x494 0x0 0x5 0x0 +#define IOMUXC_GPIO_DISP_B2_15_FLEXCAN1_RX 0x250 0x494 0x498 0x6 0x2 +#define IOMUXC_GPIO_DISP_B2_15_ENET_QOS_1588_EVENT0_AUX_IN 0x250 0x494 0x0 0x8 0x0 +#define IOMUXC_GPIO_DISP_B2_15_LPSPI4_PCS0 0x250 0x494 0x60C 0x9 0x1 +#define IOMUXC_GPIO_DISP_B2_15_GPIO11_IO16 0x250 0x494 0x0 0xA 0x0 + +#endif /* _DT_BINDINGS_PINCTRL_IMXRT1170_PINFUNC_H */ diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 70e634b37aae..6cdadba6a3ac 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -1389,7 +1389,6 @@ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; clocks = <&apb0_gates 0>, <&osc24M>, <&rtc CLK_OSC32K>; clock-names = "apb", "hosc", "losc"; - resets = <&apb0_rst 0>; gpio-controller; interrupt-controller; #interrupt-cells = <3>; diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 1a262a05fdcb..f630ab55bb6a 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -814,7 +814,6 @@ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; clocks = <&apb0_gates 0>, <&osc24M>, <&rtc CLK_OSC32K>; clock-names = "apb", "hosc", "losc"; - resets = <&apb0_rst 0>; gpio-controller; interrupt-controller; #interrupt-cells = <3>; diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index ce4fa6706d06..7d3f3300f431 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -1218,7 +1218,6 @@ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; clocks = <&apbs_gates 0>, <&osc24M>, <&osc32k>; clock-names = "apb", "hosc", "losc"; - resets = <&apbs_rst 0>; gpio-controller; interrupt-controller; #interrupt-cells = <3>; diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c index fc4f710e9820..5f9379b3c8c8 100644 --- a/arch/arm64/mm/flush.c +++ b/arch/arm64/mm/flush.c @@ -76,17 +76,10 @@ EXPORT_SYMBOL_GPL(__sync_icache_dcache); void flush_dcache_page(struct page *page) { /* - * Only the head page's flags of HugeTLB can be cleared since the tail - * vmemmap pages associated with each HugeTLB page are mapped with - * read-only when CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP is enabled (more - * details can refer to vmemmap_remap_pte()). Although - * __sync_icache_dcache() only set PG_dcache_clean flag on the head - * page struct, there is more than one page struct with PG_dcache_clean - * associated with the HugeTLB page since the head vmemmap page frame - * is reused (more details can refer to the comments above - * page_fixed_fake_head()). + * HugeTLB pages are always fully mapped and only head page will be + * set PG_dcache_clean (see comments in __sync_icache_dcache()). */ - if (hugetlb_optimize_vmemmap_enabled() && PageHuge(page)) + if (PageHuge(page)) page = compound_head(page); if (test_bit(PG_dcache_clean, &page->flags)) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 7b0d286bf9ba..01772e79fd93 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -55,6 +55,7 @@ int memory_add_physaddr_to_nid(u64 start) { return hot_add_scn_to_nid(start); } +EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); #endif int __weak create_section_mapping(unsigned long start, unsigned long end, diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 509408da0da1..6b3033845c6d 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -30,9 +30,15 @@ int pmd_huge(pmd_t pmd) (pmd_val(pmd) & (_PAGE_PRESENT|_PAGE_PSE)) != _PAGE_PRESENT; } +/* + * pud_huge() returns 1 if @pud is hugetlb related entry, that is normal + * hugetlb entry or non-present (migration or hwpoisoned) hugetlb entry. + * Otherwise, returns 0. + */ int pud_huge(pud_t pud) { - return !!(pud_val(pud) & _PAGE_PSE); + return !pud_none(pud) && + (pud_val(pud) & (_PAGE_PRESENT|_PAGE_PSE)) != _PAGE_PRESENT; } #ifdef CONFIG_HUGETLB_PAGE diff --git a/certs/Makefile b/certs/Makefile index 88a73b28d254..9486ed924731 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -4,24 +4,22 @@ # obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o -obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o +obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o blacklist_hashes.o obj-$(CONFIG_SYSTEM_REVOCATION_LIST) += revocation_certificates.o -ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),) $(obj)/blacklist_hashes.o: $(obj)/blacklist_hash_list CFLAGS_blacklist_hashes.o := -I $(obj) quiet_cmd_check_and_copy_blacklist_hash_list = GEN $@ cmd_check_and_copy_blacklist_hash_list = \ - $(AWK) -f $(srctree)/scripts/check-blacklist-hashes.awk $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) >&2; \ - cat $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) > $@ + $(if $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST), \ + $(AWK) -f $(srctree)/$(src)/check-blacklist-hashes.awk $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) >&2; \ + { cat $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST); echo $(comma) NULL; } > $@, \ + echo NULL > $@) $(obj)/blacklist_hash_list: $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) FORCE $(call if_changed,check_and_copy_blacklist_hash_list) -obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o -else -obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o -endif + targets += blacklist_hash_list quiet_cmd_extract_certs = CERT $@ diff --git a/certs/blacklist_hashes.c b/certs/blacklist_hashes.c index 86d66fe11348..0c5476abebd9 100644 --- a/certs/blacklist_hashes.c +++ b/certs/blacklist_hashes.c @@ -3,5 +3,4 @@ const char __initconst *const blacklist_hashes[] = { #include "blacklist_hash_list" - , NULL }; diff --git a/certs/blacklist_nohashes.c b/certs/blacklist_nohashes.c deleted file mode 100644 index 753b703ef0ef..000000000000 --- a/certs/blacklist_nohashes.c +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "blacklist.h" - -const char __initconst *const blacklist_hashes[] = { - NULL -}; diff --git a/scripts/check-blacklist-hashes.awk b/certs/check-blacklist-hashes.awk index 107c1d3204d4..107c1d3204d4 100755 --- a/scripts/check-blacklist-hashes.awk +++ b/certs/check-blacklist-hashes.awk diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index f64e3984689f..768ced3d6fe8 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig @@ -2,6 +2,7 @@ menuconfig CXL_BUS tristate "CXL (Compute Express Link) Devices Support" depends on PCI + select PCI_DOE help CXL is a bus that is electrically compatible with PCI Express, but layers three protocols on that signalling (CXL.io, CXL.cache, and @@ -102,4 +103,12 @@ config CXL_SUSPEND def_bool y depends on SUSPEND && CXL_MEM +config CXL_REGION + bool + default CXL_BUS + # For MAX_PHYSMEM_BITS + depends on SPARSEMEM + select MEMREGION + select GET_FREE_REGION + endif diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index 40286f5df812..fb649683dd3a 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -9,10 +9,6 @@ #include "cxlpci.h" #include "cxl.h" -/* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */ -#define CFMWS_INTERLEAVE_WAYS(x) (1 << (x)->interleave_ways) -#define CFMWS_INTERLEAVE_GRANULARITY(x) ((x)->granularity + 8) - static unsigned long cfmws_to_decoder_flags(int restrictions) { unsigned long flags = CXL_DECODER_F_ENABLE; @@ -34,7 +30,8 @@ static unsigned long cfmws_to_decoder_flags(int restrictions) static int cxl_acpi_cfmws_verify(struct device *dev, struct acpi_cedt_cfmws *cfmws) { - int expected_len; + int rc, expected_len; + unsigned int ways; if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO) { dev_err(dev, "CFMWS Unsupported Interleave Arithmetic\n"); @@ -51,14 +48,14 @@ static int cxl_acpi_cfmws_verify(struct device *dev, return -EINVAL; } - if (CFMWS_INTERLEAVE_WAYS(cfmws) > CXL_DECODER_MAX_INTERLEAVE) { - dev_err(dev, "CFMWS Interleave Ways (%d) too large\n", - CFMWS_INTERLEAVE_WAYS(cfmws)); + rc = cxl_to_ways(cfmws->interleave_ways, &ways); + if (rc) { + dev_err(dev, "CFMWS Interleave Ways (%d) invalid\n", + cfmws->interleave_ways); return -EINVAL; } - expected_len = struct_size((cfmws), interleave_targets, - CFMWS_INTERLEAVE_WAYS(cfmws)); + expected_len = struct_size(cfmws, interleave_targets, ways); if (cfmws->header.length < expected_len) { dev_err(dev, "CFMWS length %d less than expected %d\n", @@ -76,6 +73,8 @@ static int cxl_acpi_cfmws_verify(struct device *dev, struct cxl_cfmws_context { struct device *dev; struct cxl_port *root_port; + struct resource *cxl_res; + int id; }; static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, @@ -84,10 +83,14 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, int target_map[CXL_DECODER_MAX_INTERLEAVE]; struct cxl_cfmws_context *ctx = arg; struct cxl_port *root_port = ctx->root_port; + struct resource *cxl_res = ctx->cxl_res; + struct cxl_root_decoder *cxlrd; struct device *dev = ctx->dev; struct acpi_cedt_cfmws *cfmws; struct cxl_decoder *cxld; - int rc, i; + unsigned int ways, i, ig; + struct resource *res; + int rc; cfmws = (struct acpi_cedt_cfmws *) header; @@ -99,19 +102,51 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, return 0; } - for (i = 0; i < CFMWS_INTERLEAVE_WAYS(cfmws); i++) + rc = cxl_to_ways(cfmws->interleave_ways, &ways); + if (rc) + return rc; + rc = cxl_to_granularity(cfmws->granularity, &ig); + if (rc) + return rc; + for (i = 0; i < ways; i++) target_map[i] = cfmws->interleave_targets[i]; - cxld = cxl_root_decoder_alloc(root_port, CFMWS_INTERLEAVE_WAYS(cfmws)); - if (IS_ERR(cxld)) + res = kzalloc(sizeof(*res), GFP_KERNEL); + if (!res) + return -ENOMEM; + + res->name = kasprintf(GFP_KERNEL, "CXL Window %d", ctx->id++); + if (!res->name) + goto err_name; + + res->start = cfmws->base_hpa; + res->end = cfmws->base_hpa + cfmws->window_size - 1; + res->flags = IORESOURCE_MEM; + + /* add to the local resource tracking to establish a sort order */ + rc = insert_resource(cxl_res, res); + if (rc) + goto err_insert; + + cxlrd = cxl_root_decoder_alloc(root_port, ways); + if (IS_ERR(cxlrd)) return 0; + cxld = &cxlrd->cxlsd.cxld; cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions); cxld->target_type = CXL_DECODER_EXPANDER; - cxld->platform_res = (struct resource)DEFINE_RES_MEM(cfmws->base_hpa, - cfmws->window_size); - cxld->interleave_ways = CFMWS_INTERLEAVE_WAYS(cfmws); - cxld->interleave_granularity = CFMWS_INTERLEAVE_GRANULARITY(cfmws); + cxld->hpa_range = (struct range) { + .start = res->start, + .end = res->end, + }; + cxld->interleave_ways = ways; + /* + * Minimize the x1 granularity to advertise support for any + * valid region granularity + */ + if (ways == 1) + ig = CXL_DECODER_MIN_GRANULARITY; + cxld->interleave_granularity = ig; rc = cxl_decoder_add(cxld, target_map); if (rc) @@ -119,15 +154,22 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, else rc = cxl_decoder_autoremove(dev, cxld); if (rc) { - dev_err(dev, "Failed to add decoder for %pr\n", - &cxld->platform_res); + dev_err(dev, "Failed to add decode range [%#llx - %#llx]\n", + cxld->hpa_range.start, cxld->hpa_range.end); return 0; } - dev_dbg(dev, "add: %s node: %d range %pr\n", dev_name(&cxld->dev), - phys_to_target_node(cxld->platform_res.start), - &cxld->platform_res); + dev_dbg(dev, "add: %s node: %d range [%#llx - %#llx]\n", + dev_name(&cxld->dev), + phys_to_target_node(cxld->hpa_range.start), + cxld->hpa_range.start, cxld->hpa_range.end); return 0; + +err_insert: + kfree(res->name); +err_name: + kfree(res); + return -ENOMEM; } __mock struct acpi_device *to_cxl_host_bridge(struct device *host, @@ -175,8 +217,7 @@ static int add_host_bridge_uport(struct device *match, void *arg) if (rc) return rc; - port = devm_cxl_add_port(host, match, dport->component_reg_phys, - root_port); + port = devm_cxl_add_port(host, match, dport->component_reg_phys, dport); if (IS_ERR(port)) return PTR_ERR(port); dev_dbg(host, "%s: add: %s\n", dev_name(match), dev_name(&port->dev)); @@ -282,9 +323,127 @@ static void cxl_acpi_lock_reset_class(void *dev) device_lock_reset_class(dev); } +static void del_cxl_resource(struct resource *res) +{ + kfree(res->name); + kfree(res); +} + +static void cxl_set_public_resource(struct resource *priv, struct resource *pub) +{ + priv->desc = (unsigned long) pub; +} + +static struct resource *cxl_get_public_resource(struct resource *priv) +{ + return (struct resource *) priv->desc; +} + +static void remove_cxl_resources(void *data) +{ + struct resource *res, *next, *cxl = data; + + for (res = cxl->child; res; res = next) { + struct resource *victim = cxl_get_public_resource(res); + + next = res->sibling; + remove_resource(res); + + if (victim) { + remove_resource(victim); + kfree(victim); + } + + del_cxl_resource(res); + } +} + +/** + * add_cxl_resources() - reflect CXL fixed memory windows in iomem_resource + * @cxl_res: A standalone resource tree where each CXL window is a sibling + * + * Walk each CXL window in @cxl_res and add it to iomem_resource potentially + * expanding its boundaries to ensure that any conflicting resources become + * children. If a window is expanded it may then conflict with a another window + * entry and require the window to be truncated or trimmed. Consider this + * situation: + * + * |-- "CXL Window 0" --||----- "CXL Window 1" -----| + * |--------------- "System RAM" -------------| + * + * ...where platform firmware has established as System RAM resource across 2 + * windows, but has left some portion of window 1 for dynamic CXL region + * provisioning. In this case "Window 0" will span the entirety of the "System + * RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end + * of that "System RAM" resource. + */ +static int add_cxl_resources(struct resource *cxl_res) +{ + struct resource *res, *new, *next; + + for (res = cxl_res->child; res; res = next) { + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return -ENOMEM; + new->name = res->name; + new->start = res->start; + new->end = res->end; + new->flags = IORESOURCE_MEM; + new->desc = IORES_DESC_CXL; + + /* + * Record the public resource in the private cxl_res tree for + * later removal. + */ + cxl_set_public_resource(res, new); + + insert_resource_expand_to_fit(&iomem_resource, new); + + next = res->sibling; + while (next && resource_overlaps(new, next)) { + if (resource_contains(new, next)) { + struct resource *_next = next->sibling; + + remove_resource(next); + del_cxl_resource(next); + next = _next; + } else + next->start = new->end + 1; + } + } + return 0; +} + +static int pair_cxl_resource(struct device *dev, void *data) +{ + struct resource *cxl_res = data; + struct resource *p; + + if (!is_root_decoder(dev)) + return 0; + + for (p = cxl_res->child; p; p = p->sibling) { + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld; + struct resource res = { + .start = cxld->hpa_range.start, + .end = cxld->hpa_range.end, + .flags = IORESOURCE_MEM, + }; + + if (resource_contains(p, &res)) { + cxlrd->res = cxl_get_public_resource(p); + break; + } + } + + return 0; +} + static int cxl_acpi_probe(struct platform_device *pdev) { int rc; + struct resource *cxl_res; struct cxl_port *root_port; struct device *host = &pdev->dev; struct acpi_device *adev = ACPI_COMPANION(host); @@ -296,6 +455,14 @@ static int cxl_acpi_probe(struct platform_device *pdev) if (rc) return rc; + cxl_res = devm_kzalloc(host, sizeof(*cxl_res), GFP_KERNEL); + if (!cxl_res) + return -ENOMEM; + cxl_res->name = "CXL mem"; + cxl_res->start = 0; + cxl_res->end = -1; + cxl_res->flags = IORESOURCE_MEM; + root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL); if (IS_ERR(root_port)) return PTR_ERR(root_port); @@ -306,11 +473,28 @@ static int cxl_acpi_probe(struct platform_device *pdev) if (rc < 0) return rc; + rc = devm_add_action_or_reset(host, remove_cxl_resources, cxl_res); + if (rc) + return rc; + ctx = (struct cxl_cfmws_context) { .dev = host, .root_port = root_port, + .cxl_res = cxl_res, }; - acpi_table_parse_cedt(ACPI_CEDT_TYPE_CFMWS, cxl_parse_cfmws, &ctx); + rc = acpi_table_parse_cedt(ACPI_CEDT_TYPE_CFMWS, cxl_parse_cfmws, &ctx); + if (rc < 0) + return -ENXIO; + + rc = add_cxl_resources(cxl_res); + if (rc) + return rc; + + /* + * Populate the root decoders with their related iomem resource, + * if present + */ + device_for_each_child(&root_port->dev, cxl_res, pair_cxl_resource); /* * Root level scanned with host-bridge as dports, now scan host-bridges @@ -337,12 +521,19 @@ static const struct acpi_device_id cxl_acpi_ids[] = { }; MODULE_DEVICE_TABLE(acpi, cxl_acpi_ids); +static const struct platform_device_id cxl_test_ids[] = { + { "cxl_acpi" }, + { }, +}; +MODULE_DEVICE_TABLE(platform, cxl_test_ids); + static struct platform_driver cxl_acpi_driver = { .probe = cxl_acpi_probe, .driver = { .name = KBUILD_MODNAME, .acpi_match_table = cxl_acpi_ids, }, + .id_table = cxl_test_ids, }; module_platform_driver(cxl_acpi_driver); diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index 9d35085d25af..79c7257f4107 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile @@ -10,3 +10,4 @@ cxl_core-y += memdev.o cxl_core-y += mbox.o cxl_core-y += pci.o cxl_core-y += hdm.o +cxl_core-$(CONFIG_CXL_REGION) += region.o diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 1a50c0fc399c..1d8f87be283f 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h @@ -9,6 +9,36 @@ extern const struct device_type cxl_nvdimm_type; extern struct attribute_group cxl_base_attribute_group; +#ifdef CONFIG_CXL_REGION +extern struct device_attribute dev_attr_create_pmem_region; +extern struct device_attribute dev_attr_delete_region; +extern struct device_attribute dev_attr_region; +extern const struct device_type cxl_pmem_region_type; +extern const struct device_type cxl_region_type; +void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled); +#define CXL_REGION_ATTR(x) (&dev_attr_##x.attr) +#define CXL_REGION_TYPE(x) (&cxl_region_type) +#define SET_CXL_REGION_ATTR(x) (&dev_attr_##x.attr), +#define CXL_PMEM_REGION_TYPE(x) (&cxl_pmem_region_type) +int cxl_region_init(void); +void cxl_region_exit(void); +#else +static inline void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled) +{ +} +static inline int cxl_region_init(void) +{ + return 0; +} +static inline void cxl_region_exit(void) +{ +} +#define CXL_REGION_ATTR(x) NULL +#define CXL_REGION_TYPE(x) NULL +#define SET_CXL_REGION_ATTR(x) +#define CXL_PMEM_REGION_TYPE(x) NULL +#endif + struct cxl_send_command; struct cxl_mem_query_commands; int cxl_query_cmd(struct cxl_memdev *cxlmd, @@ -17,9 +47,28 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s); void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr, resource_size_t length); +struct dentry *cxl_debugfs_create_dir(const char *dir); +int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled, + enum cxl_decoder_mode mode); +int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size); +int cxl_dpa_free(struct cxl_endpoint_decoder *cxled); +resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled); +resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled); +extern struct rw_semaphore cxl_dpa_rwsem; + +bool is_switch_decoder(struct device *dev); +struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev); +static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port, + struct cxl_memdev *cxlmd) +{ + if (!port) + return NULL; + + return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev); +} + int cxl_memdev_init(void); void cxl_memdev_exit(void); void cxl_mbox_init(void); -void cxl_mbox_exit(void); #endif /* __CXL_CORE_H__ */ diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index bfc8ee876278..d1d2caea5c62 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2022 Intel Corporation. All rights reserved. */ #include <linux/io-64-nonatomic-hi-lo.h> +#include <linux/seq_file.h> #include <linux/device.h> #include <linux/delay.h> @@ -16,6 +17,8 @@ * for enumerating these registers and capabilities. */ +DECLARE_RWSEM(cxl_dpa_rwsem); + static int add_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, int *target_map) { @@ -46,20 +49,22 @@ static int add_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, */ int devm_cxl_add_passthrough_decoder(struct cxl_port *port) { - struct cxl_decoder *cxld; - struct cxl_dport *dport; + struct cxl_switch_decoder *cxlsd; + struct cxl_dport *dport = NULL; int single_port_map[1]; + unsigned long index; - cxld = cxl_switch_decoder_alloc(port, 1); - if (IS_ERR(cxld)) - return PTR_ERR(cxld); + cxlsd = cxl_switch_decoder_alloc(port, 1); + if (IS_ERR(cxlsd)) + return PTR_ERR(cxlsd); device_lock_assert(&port->dev); - dport = list_first_entry(&port->dports, typeof(*dport), list); + xa_for_each(&port->dports, index, dport) + break; single_port_map[0] = dport->port_id; - return add_hdm_decoder(port, cxld, single_port_map); + return add_hdm_decoder(port, &cxlsd->cxld, single_port_map); } EXPORT_SYMBOL_NS_GPL(devm_cxl_add_passthrough_decoder, CXL); @@ -124,47 +129,577 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port) return ERR_PTR(-ENXIO); } + dev_set_drvdata(dev, cxlhdm); + return cxlhdm; } EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_hdm, CXL); -static int to_interleave_granularity(u32 ctrl) +static void __cxl_dpa_debug(struct seq_file *file, struct resource *r, int depth) +{ + unsigned long long start = r->start, end = r->end; + + seq_printf(file, "%*s%08llx-%08llx : %s\n", depth * 2, "", start, end, + r->name); +} + +void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds) +{ + struct resource *p1, *p2; + + down_read(&cxl_dpa_rwsem); + for (p1 = cxlds->dpa_res.child; p1; p1 = p1->sibling) { + __cxl_dpa_debug(file, p1, 0); + for (p2 = p1->child; p2; p2 = p2->sibling) + __cxl_dpa_debug(file, p2, 1); + } + up_read(&cxl_dpa_rwsem); +} +EXPORT_SYMBOL_NS_GPL(cxl_dpa_debug, CXL); + +/* + * Must be called in a context that synchronizes against this decoder's + * port ->remove() callback (like an endpoint decoder sysfs attribute) + */ +static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_port *port = cxled_to_port(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct resource *res = cxled->dpa_res; + resource_size_t skip_start; + + lockdep_assert_held_write(&cxl_dpa_rwsem); + + /* save @skip_start, before @res is released */ + skip_start = res->start - cxled->skip; + __release_region(&cxlds->dpa_res, res->start, resource_size(res)); + if (cxled->skip) + __release_region(&cxlds->dpa_res, skip_start, cxled->skip); + cxled->skip = 0; + cxled->dpa_res = NULL; + put_device(&cxled->cxld.dev); + port->hdm_end--; +} + +static void cxl_dpa_release(void *cxled) +{ + down_write(&cxl_dpa_rwsem); + __cxl_dpa_release(cxled); + up_write(&cxl_dpa_rwsem); +} + +/* + * Must be called from context that will not race port device + * unregistration, like decoder sysfs attribute methods + */ +static void devm_cxl_dpa_release(struct cxl_endpoint_decoder *cxled) +{ + struct cxl_port *port = cxled_to_port(cxled); + + lockdep_assert_held_write(&cxl_dpa_rwsem); + devm_remove_action(&port->dev, cxl_dpa_release, cxled); + __cxl_dpa_release(cxled); +} + +static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, + resource_size_t base, resource_size_t len, + resource_size_t skipped) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_port *port = cxled_to_port(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct device *dev = &port->dev; + struct resource *res; + + lockdep_assert_held_write(&cxl_dpa_rwsem); + + if (!len) + goto success; + + if (cxled->dpa_res) { + dev_dbg(dev, "decoder%d.%d: existing allocation %pr assigned\n", + port->id, cxled->cxld.id, cxled->dpa_res); + return -EBUSY; + } + + if (port->hdm_end + 1 != cxled->cxld.id) { + /* + * Assumes alloc and commit order is always in hardware instance + * order per expectations from 8.2.5.12.20 Committing Decoder + * Programming that enforce decoder[m] committed before + * decoder[m+1] commit start. + */ + dev_dbg(dev, "decoder%d.%d: expected decoder%d.%d\n", port->id, + cxled->cxld.id, port->id, port->hdm_end + 1); + return -EBUSY; + } + + if (skipped) { + res = __request_region(&cxlds->dpa_res, base - skipped, skipped, + dev_name(&cxled->cxld.dev), 0); + if (!res) { + dev_dbg(dev, + "decoder%d.%d: failed to reserve skipped space\n", + port->id, cxled->cxld.id); + return -EBUSY; + } + } + res = __request_region(&cxlds->dpa_res, base, len, + dev_name(&cxled->cxld.dev), 0); + if (!res) { + dev_dbg(dev, "decoder%d.%d: failed to reserve allocation\n", + port->id, cxled->cxld.id); + if (skipped) + __release_region(&cxlds->dpa_res, base - skipped, + skipped); + return -EBUSY; + } + cxled->dpa_res = res; + cxled->skip = skipped; + + if (resource_contains(&cxlds->pmem_res, res)) + cxled->mode = CXL_DECODER_PMEM; + else if (resource_contains(&cxlds->ram_res, res)) + cxled->mode = CXL_DECODER_RAM; + else { + dev_dbg(dev, "decoder%d.%d: %pr mixed\n", port->id, + cxled->cxld.id, cxled->dpa_res); + cxled->mode = CXL_DECODER_MIXED; + } + +success: + port->hdm_end++; + get_device(&cxled->cxld.dev); + return 0; +} + +static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, + resource_size_t base, resource_size_t len, + resource_size_t skipped) { - int val = FIELD_GET(CXL_HDM_DECODER0_CTRL_IG_MASK, ctrl); + struct cxl_port *port = cxled_to_port(cxled); + int rc; + + down_write(&cxl_dpa_rwsem); + rc = __cxl_dpa_reserve(cxled, base, len, skipped); + up_write(&cxl_dpa_rwsem); + + if (rc) + return rc; - return 256 << val; + return devm_add_action_or_reset(&port->dev, cxl_dpa_release, cxled); } -static int to_interleave_ways(u32 ctrl) +resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled) { - int val = FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl); + resource_size_t size = 0; + + down_read(&cxl_dpa_rwsem); + if (cxled->dpa_res) + size = resource_size(cxled->dpa_res); + up_read(&cxl_dpa_rwsem); - switch (val) { - case 0 ... 4: - return 1 << val; - case 8 ... 10: - return 3 << (val - 8); + return size; +} + +resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled) +{ + resource_size_t base = -1; + + down_read(&cxl_dpa_rwsem); + if (cxled->dpa_res) + base = cxled->dpa_res->start; + up_read(&cxl_dpa_rwsem); + + return base; +} + +int cxl_dpa_free(struct cxl_endpoint_decoder *cxled) +{ + struct cxl_port *port = cxled_to_port(cxled); + struct device *dev = &cxled->cxld.dev; + int rc; + + down_write(&cxl_dpa_rwsem); + if (!cxled->dpa_res) { + rc = 0; + goto out; + } + if (cxled->cxld.region) { + dev_dbg(dev, "decoder assigned to: %s\n", + dev_name(&cxled->cxld.region->dev)); + rc = -EBUSY; + goto out; + } + if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) { + dev_dbg(dev, "decoder enabled\n"); + rc = -EBUSY; + goto out; + } + if (cxled->cxld.id != port->hdm_end) { + dev_dbg(dev, "expected decoder%d.%d\n", port->id, + port->hdm_end); + rc = -EBUSY; + goto out; + } + devm_cxl_dpa_release(cxled); + rc = 0; +out: + up_write(&cxl_dpa_rwsem); + return rc; +} + +int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled, + enum cxl_decoder_mode mode) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct device *dev = &cxled->cxld.dev; + int rc; + + switch (mode) { + case CXL_DECODER_RAM: + case CXL_DECODER_PMEM: + break; default: + dev_dbg(dev, "unsupported mode: %d\n", mode); + return -EINVAL; + } + + down_write(&cxl_dpa_rwsem); + if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) { + rc = -EBUSY; + goto out; + } + + /* + * Only allow modes that are supported by the current partition + * configuration + */ + if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) { + dev_dbg(dev, "no available pmem capacity\n"); + rc = -ENXIO; + goto out; + } + if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) { + dev_dbg(dev, "no available ram capacity\n"); + rc = -ENXIO; + goto out; + } + + cxled->mode = mode; + rc = 0; +out: + up_write(&cxl_dpa_rwsem); + + return rc; +} + +int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + resource_size_t free_ram_start, free_pmem_start; + struct cxl_port *port = cxled_to_port(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct device *dev = &cxled->cxld.dev; + resource_size_t start, avail, skip; + struct resource *p, *last; + int rc; + + down_write(&cxl_dpa_rwsem); + if (cxled->cxld.region) { + dev_dbg(dev, "decoder attached to %s\n", + dev_name(&cxled->cxld.region->dev)); + rc = -EBUSY; + goto out; + } + + if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) { + dev_dbg(dev, "decoder enabled\n"); + rc = -EBUSY; + goto out; + } + + for (p = cxlds->ram_res.child, last = NULL; p; p = p->sibling) + last = p; + if (last) + free_ram_start = last->end + 1; + else + free_ram_start = cxlds->ram_res.start; + + for (p = cxlds->pmem_res.child, last = NULL; p; p = p->sibling) + last = p; + if (last) + free_pmem_start = last->end + 1; + else + free_pmem_start = cxlds->pmem_res.start; + + if (cxled->mode == CXL_DECODER_RAM) { + start = free_ram_start; + avail = cxlds->ram_res.end - start + 1; + skip = 0; + } else if (cxled->mode == CXL_DECODER_PMEM) { + resource_size_t skip_start, skip_end; + + start = free_pmem_start; + avail = cxlds->pmem_res.end - start + 1; + skip_start = free_ram_start; + + /* + * If some pmem is already allocated, then that allocation + * already handled the skip. + */ + if (cxlds->pmem_res.child && + skip_start == cxlds->pmem_res.child->start) + skip_end = skip_start - 1; + else + skip_end = start - 1; + skip = skip_end - skip_start + 1; + } else { + dev_dbg(dev, "mode not set\n"); + rc = -EINVAL; + goto out; + } + + if (size > avail) { + dev_dbg(dev, "%pa exceeds available %s capacity: %pa\n", &size, + cxled->mode == CXL_DECODER_RAM ? "ram" : "pmem", + &avail); + rc = -ENOSPC; + goto out; + } + + rc = __cxl_dpa_reserve(cxled, start, size, skip); +out: + up_write(&cxl_dpa_rwsem); + + if (rc) + return rc; + + return devm_add_action_or_reset(&port->dev, cxl_dpa_release, cxled); +} + +static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl) +{ + u16 eig; + u8 eiw; + + /* + * Input validation ensures these warns never fire, but otherwise + * suppress unititalized variable usage warnings. + */ + if (WARN_ONCE(ways_to_cxl(cxld->interleave_ways, &eiw), + "invalid interleave_ways: %d\n", cxld->interleave_ways)) + return; + if (WARN_ONCE(granularity_to_cxl(cxld->interleave_granularity, &eig), + "invalid interleave_granularity: %d\n", + cxld->interleave_granularity)) + return; + + u32p_replace_bits(ctrl, eig, CXL_HDM_DECODER0_CTRL_IG_MASK); + u32p_replace_bits(ctrl, eiw, CXL_HDM_DECODER0_CTRL_IW_MASK); + *ctrl |= CXL_HDM_DECODER0_CTRL_COMMIT; +} + +static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl) +{ + u32p_replace_bits(ctrl, !!(cxld->target_type == 3), + CXL_HDM_DECODER0_CTRL_TYPE); +} + +static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt) +{ + struct cxl_dport **t = &cxlsd->target[0]; + int ways = cxlsd->cxld.interleave_ways; + + if (dev_WARN_ONCE(&cxlsd->cxld.dev, + ways > 8 || ways > cxlsd->nr_targets, + "ways: %d overflows targets: %d\n", ways, + cxlsd->nr_targets)) + return -ENXIO; + + *tgt = FIELD_PREP(GENMASK(7, 0), t[0]->port_id); + if (ways > 1) + *tgt |= FIELD_PREP(GENMASK(15, 8), t[1]->port_id); + if (ways > 2) + *tgt |= FIELD_PREP(GENMASK(23, 16), t[2]->port_id); + if (ways > 3) + *tgt |= FIELD_PREP(GENMASK(31, 24), t[3]->port_id); + if (ways > 4) + *tgt |= FIELD_PREP(GENMASK_ULL(39, 32), t[4]->port_id); + if (ways > 5) + *tgt |= FIELD_PREP(GENMASK_ULL(47, 40), t[5]->port_id); + if (ways > 6) + *tgt |= FIELD_PREP(GENMASK_ULL(55, 48), t[6]->port_id); + if (ways > 7) + *tgt |= FIELD_PREP(GENMASK_ULL(63, 56), t[7]->port_id); + + return 0; +} + +/* + * Per CXL 2.0 8.2.5.12.20 Committing Decoder Programming, hardware must set + * committed or error within 10ms, but just be generous with 20ms to account for + * clock skew and other marginal behavior + */ +#define COMMIT_TIMEOUT_MS 20 +static int cxld_await_commit(void __iomem *hdm, int id) +{ + u32 ctrl; + int i; + + for (i = 0; i < COMMIT_TIMEOUT_MS; i++) { + ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMIT_ERROR, ctrl)) { + ctrl &= ~CXL_HDM_DECODER0_CTRL_COMMIT; + writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); + return -EIO; + } + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl)) + return 0; + fsleep(1000); + } + + return -ETIMEDOUT; +} + +static int cxl_decoder_commit(struct cxl_decoder *cxld) +{ + struct cxl_port *port = to_cxl_port(cxld->dev.parent); + struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); + void __iomem *hdm = cxlhdm->regs.hdm_decoder; + int id = cxld->id, rc; + u64 base, size; + u32 ctrl; + + if (cxld->flags & CXL_DECODER_F_ENABLE) + return 0; + + if (port->commit_end + 1 != id) { + dev_dbg(&port->dev, + "%s: out of order commit, expected decoder%d.%d\n", + dev_name(&cxld->dev), port->id, port->commit_end + 1); + return -EBUSY; + } + + down_read(&cxl_dpa_rwsem); + /* common decoder settings */ + ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(cxld->id)); + cxld_set_interleave(cxld, &ctrl); + cxld_set_type(cxld, &ctrl); + base = cxld->hpa_range.start; + size = range_len(&cxld->hpa_range); + + writel(upper_32_bits(base), hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(id)); + writel(lower_32_bits(base), hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(id)); + writel(upper_32_bits(size), hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(id)); + writel(lower_32_bits(size), hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(id)); + + if (is_switch_decoder(&cxld->dev)) { + struct cxl_switch_decoder *cxlsd = + to_cxl_switch_decoder(&cxld->dev); + void __iomem *tl_hi = hdm + CXL_HDM_DECODER0_TL_HIGH(id); + void __iomem *tl_lo = hdm + CXL_HDM_DECODER0_TL_LOW(id); + u64 targets; + + rc = cxlsd_set_targets(cxlsd, &targets); + if (rc) { + dev_dbg(&port->dev, "%s: target configuration error\n", + dev_name(&cxld->dev)); + goto err; + } + + writel(upper_32_bits(targets), tl_hi); + writel(lower_32_bits(targets), tl_lo); + } else { + struct cxl_endpoint_decoder *cxled = + to_cxl_endpoint_decoder(&cxld->dev); + void __iomem *sk_hi = hdm + CXL_HDM_DECODER0_SKIP_HIGH(id); + void __iomem *sk_lo = hdm + CXL_HDM_DECODER0_SKIP_LOW(id); + + writel(upper_32_bits(cxled->skip), sk_hi); + writel(lower_32_bits(cxled->skip), sk_lo); + } + + writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); + up_read(&cxl_dpa_rwsem); + + port->commit_end++; + rc = cxld_await_commit(hdm, cxld->id); +err: + if (rc) { + dev_dbg(&port->dev, "%s: error %d committing decoder\n", + dev_name(&cxld->dev), rc); + cxld->reset(cxld); + return rc; + } + cxld->flags |= CXL_DECODER_F_ENABLE; + + return 0; +} + +static int cxl_decoder_reset(struct cxl_decoder *cxld) +{ + struct cxl_port *port = to_cxl_port(cxld->dev.parent); + struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); + void __iomem *hdm = cxlhdm->regs.hdm_decoder; + int id = cxld->id; + u32 ctrl; + + if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0) return 0; + + if (port->commit_end != id) { + dev_dbg(&port->dev, + "%s: out of order reset, expected decoder%d.%d\n", + dev_name(&cxld->dev), port->id, port->commit_end); + return -EBUSY; } + + down_read(&cxl_dpa_rwsem); + ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); + ctrl &= ~CXL_HDM_DECODER0_CTRL_COMMIT; + writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); + + writel(0, hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(id)); + writel(0, hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(id)); + writel(0, hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(id)); + writel(0, hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(id)); + up_read(&cxl_dpa_rwsem); + + port->commit_end--; + cxld->flags &= ~CXL_DECODER_F_ENABLE; + + return 0; } static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, - int *target_map, void __iomem *hdm, int which) + int *target_map, void __iomem *hdm, int which, + u64 *dpa_base) { - u64 size, base; + struct cxl_endpoint_decoder *cxled = NULL; + u64 size, base, skip, dpa_size; + bool committed; + u32 remainder; + int i, rc; u32 ctrl; - int i; union { u64 value; unsigned char target_id[8]; } target_list; + if (is_endpoint_decoder(&cxld->dev)) + cxled = to_cxl_endpoint_decoder(&cxld->dev); + ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which)); base = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which)); size = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(which)); + committed = !!(ctrl & CXL_HDM_DECODER0_CTRL_COMMITTED); + cxld->commit = cxl_decoder_commit; + cxld->reset = cxl_decoder_reset; - if (!(ctrl & CXL_HDM_DECODER0_CTRL_COMMITTED)) + if (!committed) size = 0; if (base == U64_MAX || size == U64_MAX) { dev_warn(&port->dev, "decoder%d.%d: Invalid resource range\n", @@ -172,39 +707,77 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, return -ENXIO; } - cxld->decoder_range = (struct range) { + cxld->hpa_range = (struct range) { .start = base, .end = base + size - 1, }; - /* switch decoders are always enabled if committed */ - if (ctrl & CXL_HDM_DECODER0_CTRL_COMMITTED) { + /* decoders are enabled if committed */ + if (committed) { cxld->flags |= CXL_DECODER_F_ENABLE; if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK) cxld->flags |= CXL_DECODER_F_LOCK; + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl)) + cxld->target_type = CXL_DECODER_EXPANDER; + else + cxld->target_type = CXL_DECODER_ACCELERATOR; + if (cxld->id != port->commit_end + 1) { + dev_warn(&port->dev, + "decoder%d.%d: Committed out of order\n", + port->id, cxld->id); + return -ENXIO; + } + port->commit_end = cxld->id; + } else { + /* unless / until type-2 drivers arrive, assume type-3 */ + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) { + ctrl |= CXL_HDM_DECODER0_CTRL_TYPE; + writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which)); + } + cxld->target_type = CXL_DECODER_EXPANDER; } - cxld->interleave_ways = to_interleave_ways(ctrl); - if (!cxld->interleave_ways) { + rc = cxl_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl), + &cxld->interleave_ways); + if (rc) { dev_warn(&port->dev, "decoder%d.%d: Invalid interleave ways (ctrl: %#x)\n", port->id, cxld->id, ctrl); - return -ENXIO; + return rc; } - cxld->interleave_granularity = to_interleave_granularity(ctrl); + rc = cxl_to_granularity(FIELD_GET(CXL_HDM_DECODER0_CTRL_IG_MASK, ctrl), + &cxld->interleave_granularity); + if (rc) + return rc; - if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl)) - cxld->target_type = CXL_DECODER_EXPANDER; - else - cxld->target_type = CXL_DECODER_ACCELERATOR; + if (!cxled) { + target_list.value = + ioread64_hi_lo(hdm + CXL_HDM_DECODER0_TL_LOW(which)); + for (i = 0; i < cxld->interleave_ways; i++) + target_map[i] = target_list.target_id[i]; - if (is_endpoint_decoder(&cxld->dev)) return 0; + } - target_list.value = - ioread64_hi_lo(hdm + CXL_HDM_DECODER0_TL_LOW(which)); - for (i = 0; i < cxld->interleave_ways; i++) - target_map[i] = target_list.target_id[i]; + if (!committed) + return 0; + dpa_size = div_u64_rem(size, cxld->interleave_ways, &remainder); + if (remainder) { + dev_err(&port->dev, + "decoder%d.%d: invalid committed configuration size: %#llx ways: %d\n", + port->id, cxld->id, size, cxld->interleave_ways); + return -ENXIO; + } + skip = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SKIP_LOW(which)); + rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip); + if (rc) { + dev_err(&port->dev, + "decoder%d.%d: Failed to reserve DPA range %#llx - %#llx\n (%d)", + port->id, cxld->id, *dpa_base, + *dpa_base + dpa_size + skip - 1, rc); + return rc; + } + *dpa_base += dpa_size + skip; return 0; } @@ -216,7 +789,8 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) { void __iomem *hdm = cxlhdm->regs.hdm_decoder; struct cxl_port *port = cxlhdm->port; - int i, committed, failed; + int i, committed; + u64 dpa_base = 0; u32 ctrl; /* @@ -236,27 +810,37 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) if (committed != cxlhdm->decoder_count) msleep(20); - for (i = 0, failed = 0; i < cxlhdm->decoder_count; i++) { + for (i = 0; i < cxlhdm->decoder_count; i++) { int target_map[CXL_DECODER_MAX_INTERLEAVE] = { 0 }; int rc, target_count = cxlhdm->target_count; struct cxl_decoder *cxld; - if (is_cxl_endpoint(port)) - cxld = cxl_endpoint_decoder_alloc(port); - else - cxld = cxl_switch_decoder_alloc(port, target_count); - if (IS_ERR(cxld)) { - dev_warn(&port->dev, - "Failed to allocate the decoder\n"); - return PTR_ERR(cxld); + if (is_cxl_endpoint(port)) { + struct cxl_endpoint_decoder *cxled; + + cxled = cxl_endpoint_decoder_alloc(port); + if (IS_ERR(cxled)) { + dev_warn(&port->dev, + "Failed to allocate the decoder\n"); + return PTR_ERR(cxled); + } + cxld = &cxled->cxld; + } else { + struct cxl_switch_decoder *cxlsd; + + cxlsd = cxl_switch_decoder_alloc(port, target_count); + if (IS_ERR(cxlsd)) { + dev_warn(&port->dev, + "Failed to allocate the decoder\n"); + return PTR_ERR(cxlsd); + } + cxld = &cxlsd->cxld; } - rc = init_hdm_decoder(port, cxld, target_map, - cxlhdm->regs.hdm_decoder, i); + rc = init_hdm_decoder(port, cxld, target_map, hdm, i, &dpa_base); if (rc) { put_device(&cxld->dev); - failed++; - continue; + return rc; } rc = add_hdm_decoder(port, cxld, target_map); if (rc) { @@ -266,11 +850,6 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) } } - if (failed == cxlhdm->decoder_count) { - dev_err(&port->dev, "No valid decoders found\n"); - return -ENXIO; - } - return 0; } EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_decoders, CXL); diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index cbf23beebebe..16176b9278b4 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -718,12 +718,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_enumerate_cmds, CXL); */ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) { - struct cxl_mbox_get_partition_info { - __le64 active_volatile_cap; - __le64 active_persistent_cap; - __le64 next_volatile_cap; - __le64 next_persistent_cap; - } __packed pi; + struct cxl_mbox_get_partition_info pi; int rc; rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_PARTITION_INFO, NULL, 0, @@ -773,15 +768,6 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) cxlds->partition_align_bytes = le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER; - dev_dbg(cxlds->dev, - "Identify Memory Device\n" - " total_bytes = %#llx\n" - " volatile_only_bytes = %#llx\n" - " persistent_only_bytes = %#llx\n" - " partition_align_bytes = %#llx\n", - cxlds->total_bytes, cxlds->volatile_only_bytes, - cxlds->persistent_only_bytes, cxlds->partition_align_bytes); - cxlds->lsa_size = le32_to_cpu(id.lsa_size); memcpy(cxlds->firmware_version, id.fw_revision, sizeof(id.fw_revision)); @@ -789,42 +775,63 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) } EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL); -int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) +static int add_dpa_res(struct device *dev, struct resource *parent, + struct resource *res, resource_size_t start, + resource_size_t size, const char *type) { int rc; - if (cxlds->partition_align_bytes == 0) { - cxlds->ram_range.start = 0; - cxlds->ram_range.end = cxlds->volatile_only_bytes - 1; - cxlds->pmem_range.start = cxlds->volatile_only_bytes; - cxlds->pmem_range.end = cxlds->volatile_only_bytes + - cxlds->persistent_only_bytes - 1; + res->name = type; + res->start = start; + res->end = start + size - 1; + res->flags = IORESOURCE_MEM; + if (resource_size(res) == 0) { + dev_dbg(dev, "DPA(%s): no capacity\n", res->name); return 0; } - - rc = cxl_mem_get_partition_info(cxlds); + rc = request_resource(parent, res); if (rc) { - dev_err(cxlds->dev, "Failed to query partition information\n"); + dev_err(dev, "DPA(%s): failed to track %pr (%d)\n", res->name, + res, rc); return rc; } - dev_dbg(cxlds->dev, - "Get Partition Info\n" - " active_volatile_bytes = %#llx\n" - " active_persistent_bytes = %#llx\n" - " next_volatile_bytes = %#llx\n" - " next_persistent_bytes = %#llx\n", - cxlds->active_volatile_bytes, cxlds->active_persistent_bytes, - cxlds->next_volatile_bytes, cxlds->next_persistent_bytes); + dev_dbg(dev, "DPA(%s): %pr\n", res->name, res); + + return 0; +} - cxlds->ram_range.start = 0; - cxlds->ram_range.end = cxlds->active_volatile_bytes - 1; +int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) +{ + struct device *dev = cxlds->dev; + int rc; - cxlds->pmem_range.start = cxlds->active_volatile_bytes; - cxlds->pmem_range.end = - cxlds->active_volatile_bytes + cxlds->active_persistent_bytes - 1; + cxlds->dpa_res = + (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes); - return 0; + if (cxlds->partition_align_bytes == 0) { + rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, + cxlds->volatile_only_bytes, "ram"); + if (rc) + return rc; + return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, + cxlds->volatile_only_bytes, + cxlds->persistent_only_bytes, "pmem"); + } + + rc = cxl_mem_get_partition_info(cxlds); + if (rc) { + dev_err(dev, "Failed to query partition information\n"); + return rc; + } + + rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, + cxlds->active_volatile_bytes, "ram"); + if (rc) + return rc; + return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, + cxlds->active_volatile_bytes, + cxlds->active_persistent_bytes, "pmem"); } EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL); @@ -845,19 +852,11 @@ struct cxl_dev_state *cxl_dev_state_create(struct device *dev) } EXPORT_SYMBOL_NS_GPL(cxl_dev_state_create, CXL); -static struct dentry *cxl_debugfs; - void __init cxl_mbox_init(void) { struct dentry *mbox_debugfs; - cxl_debugfs = debugfs_create_dir("cxl", NULL); - mbox_debugfs = debugfs_create_dir("mbox", cxl_debugfs); + mbox_debugfs = cxl_debugfs_create_dir("mbox"); debugfs_create_bool("raw_allow_all", 0600, mbox_debugfs, &cxl_raw_allow_all); } - -void cxl_mbox_exit(void) -{ - debugfs_remove_recursive(cxl_debugfs); -} diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index f7cdcd33504a..20ce488a7754 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -68,7 +68,7 @@ static ssize_t ram_size_show(struct device *dev, struct device_attribute *attr, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - unsigned long long len = range_len(&cxlds->ram_range); + unsigned long long len = resource_size(&cxlds->ram_res); return sysfs_emit(buf, "%#llx\n", len); } @@ -81,7 +81,7 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - unsigned long long len = range_len(&cxlds->pmem_range); + unsigned long long len = resource_size(&cxlds->pmem_res); return sysfs_emit(buf, "%#llx\n", len); } diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index c4c99ff7b55e..9240df53ed87 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -4,6 +4,7 @@ #include <linux/device.h> #include <linux/delay.h> #include <linux/pci.h> +#include <linux/pci-doe.h> #include <cxlpci.h> #include <cxlmem.h> #include <cxl.h> @@ -225,7 +226,6 @@ static int dvsec_range_allowed(struct device *dev, void *arg) { struct range *dev_range = arg; struct cxl_decoder *cxld; - struct range root_range; if (!is_root_decoder(dev)) return 0; @@ -237,12 +237,7 @@ static int dvsec_range_allowed(struct device *dev, void *arg) if (!(cxld->flags & CXL_DECODER_F_RAM)) return 0; - root_range = (struct range) { - .start = cxld->platform_res.start, - .end = cxld->platform_res.end, - }; - - return range_contains(&root_range, dev_range); + return range_contains(&cxld->hpa_range, dev_range); } static void disable_hdm(void *_cxlhdm) @@ -458,3 +453,175 @@ hdm_init: return 0; } EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL); + +#define CXL_DOE_TABLE_ACCESS_REQ_CODE 0x000000ff +#define CXL_DOE_TABLE_ACCESS_REQ_CODE_READ 0 +#define CXL_DOE_TABLE_ACCESS_TABLE_TYPE 0x0000ff00 +#define CXL_DOE_TABLE_ACCESS_TABLE_TYPE_CDATA 0 +#define CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE 0xffff0000 +#define CXL_DOE_TABLE_ACCESS_LAST_ENTRY 0xffff +#define CXL_DOE_PROTOCOL_TABLE_ACCESS 2 + +static struct pci_doe_mb *find_cdat_doe(struct device *uport) +{ + struct cxl_memdev *cxlmd; + struct cxl_dev_state *cxlds; + unsigned long index; + void *entry; + + cxlmd = to_cxl_memdev(uport); + cxlds = cxlmd->cxlds; + + xa_for_each(&cxlds->doe_mbs, index, entry) { + struct pci_doe_mb *cur = entry; + + if (pci_doe_supports_prot(cur, PCI_DVSEC_VENDOR_ID_CXL, + CXL_DOE_PROTOCOL_TABLE_ACCESS)) + return cur; + } + + return NULL; +} + +#define CDAT_DOE_REQ(entry_handle) \ + (FIELD_PREP(CXL_DOE_TABLE_ACCESS_REQ_CODE, \ + CXL_DOE_TABLE_ACCESS_REQ_CODE_READ) | \ + FIELD_PREP(CXL_DOE_TABLE_ACCESS_TABLE_TYPE, \ + CXL_DOE_TABLE_ACCESS_TABLE_TYPE_CDATA) | \ + FIELD_PREP(CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE, (entry_handle))) + +static void cxl_doe_task_complete(struct pci_doe_task *task) +{ + complete(task->private); +} + +struct cdat_doe_task { + u32 request_pl; + u32 response_pl[32]; + struct completion c; + struct pci_doe_task task; +}; + +#define DECLARE_CDAT_DOE_TASK(req, cdt) \ +struct cdat_doe_task cdt = { \ + .c = COMPLETION_INITIALIZER_ONSTACK(cdt.c), \ + .request_pl = req, \ + .task = { \ + .prot.vid = PCI_DVSEC_VENDOR_ID_CXL, \ + .prot.type = CXL_DOE_PROTOCOL_TABLE_ACCESS, \ + .request_pl = &cdt.request_pl, \ + .request_pl_sz = sizeof(cdt.request_pl), \ + .response_pl = cdt.response_pl, \ + .response_pl_sz = sizeof(cdt.response_pl), \ + .complete = cxl_doe_task_complete, \ + .private = &cdt.c, \ + } \ +} + +static int cxl_cdat_get_length(struct device *dev, + struct pci_doe_mb *cdat_doe, + size_t *length) +{ + DECLARE_CDAT_DOE_TASK(CDAT_DOE_REQ(0), t); + int rc; + + rc = pci_doe_submit_task(cdat_doe, &t.task); + if (rc < 0) { + dev_err(dev, "DOE submit failed: %d", rc); + return rc; + } + wait_for_completion(&t.c); + if (t.task.rv < sizeof(u32)) + return -EIO; + + *length = t.response_pl[1]; + dev_dbg(dev, "CDAT length %zu\n", *length); + + return 0; +} + +static int cxl_cdat_read_table(struct device *dev, + struct pci_doe_mb *cdat_doe, + struct cxl_cdat *cdat) +{ + size_t length = cdat->length; + u32 *data = cdat->table; + int entry_handle = 0; + + do { + DECLARE_CDAT_DOE_TASK(CDAT_DOE_REQ(entry_handle), t); + size_t entry_dw; + u32 *entry; + int rc; + + rc = pci_doe_submit_task(cdat_doe, &t.task); + if (rc < 0) { + dev_err(dev, "DOE submit failed: %d", rc); + return rc; + } + wait_for_completion(&t.c); + /* 1 DW header + 1 DW data min */ + if (t.task.rv < (2 * sizeof(u32))) + return -EIO; + + /* Get the CXL table access header entry handle */ + entry_handle = FIELD_GET(CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE, + t.response_pl[0]); + entry = t.response_pl + 1; + entry_dw = t.task.rv / sizeof(u32); + /* Skip Header */ + entry_dw -= 1; + entry_dw = min(length / sizeof(u32), entry_dw); + /* Prevent length < 1 DW from causing a buffer overflow */ + if (entry_dw) { + memcpy(data, entry, entry_dw * sizeof(u32)); + length -= entry_dw * sizeof(u32); + data += entry_dw; + } + } while (entry_handle != CXL_DOE_TABLE_ACCESS_LAST_ENTRY); + + return 0; +} + +/** + * read_cdat_data - Read the CDAT data on this port + * @port: Port to read data from + * + * This call will sleep waiting for responses from the DOE mailbox. + */ +void read_cdat_data(struct cxl_port *port) +{ + struct pci_doe_mb *cdat_doe; + struct device *dev = &port->dev; + struct device *uport = port->uport; + size_t cdat_length; + int rc; + + cdat_doe = find_cdat_doe(uport); + if (!cdat_doe) { + dev_dbg(dev, "No CDAT mailbox\n"); + return; + } + + port->cdat_available = true; + + if (cxl_cdat_get_length(dev, cdat_doe, &cdat_length)) { + dev_dbg(dev, "No CDAT length\n"); + return; + } + + port->cdat.table = devm_kzalloc(dev, cdat_length, GFP_KERNEL); + if (!port->cdat.table) + return; + + port->cdat.length = cdat_length; + rc = cxl_cdat_read_table(dev, cdat_doe, &port->cdat); + if (rc) { + /* Don't leave table data allocated on error */ + devm_kfree(dev, port->cdat.table); + port->cdat.table = NULL; + port->cdat.length = 0; + dev_err(dev, "CDAT data read error\n"); + } +} +EXPORT_SYMBOL_NS_GPL(read_cdat_data, CXL); diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c index bec7cfb54ebf..1d12a8206444 100644 --- a/drivers/cxl/core/pmem.c +++ b/drivers/cxl/core/pmem.c @@ -62,9 +62,9 @@ static int match_nvdimm_bridge(struct device *dev, void *data) return is_cxl_nvdimm_bridge(dev); } -struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_nvdimm *cxl_nvd) +struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct device *start) { - struct cxl_port *port = find_cxl_root(&cxl_nvd->dev); + struct cxl_port *port = find_cxl_root(start); struct device *dev; if (!port) diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index dbce99bdffab..bffde862de0b 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ #include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/memregion.h> #include <linux/workqueue.h> +#include <linux/debugfs.h> #include <linux/device.h> #include <linux/module.h> #include <linux/pci.h> @@ -42,6 +44,8 @@ static int cxl_device_id(struct device *dev) return CXL_DEVICE_NVDIMM_BRIDGE; if (dev->type == &cxl_nvdimm_type) return CXL_DEVICE_NVDIMM; + if (dev->type == CXL_PMEM_REGION_TYPE()) + return CXL_DEVICE_PMEM_REGION; if (is_cxl_port(dev)) { if (is_cxl_root(to_cxl_port(dev))) return CXL_DEVICE_ROOT; @@ -49,6 +53,8 @@ static int cxl_device_id(struct device *dev) } if (is_cxl_memdev(dev)) return CXL_DEVICE_MEMORY_EXPANDER; + if (dev->type == CXL_REGION_TYPE()) + return CXL_DEVICE_REGION; return 0; } @@ -73,14 +79,8 @@ static ssize_t start_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_decoder *cxld = to_cxl_decoder(dev); - u64 start; - if (is_root_decoder(dev)) - start = cxld->platform_res.start; - else - start = cxld->decoder_range.start; - - return sysfs_emit(buf, "%#llx\n", start); + return sysfs_emit(buf, "%#llx\n", cxld->hpa_range.start); } static DEVICE_ATTR_ADMIN_RO(start); @@ -88,14 +88,8 @@ static ssize_t size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_decoder *cxld = to_cxl_decoder(dev); - u64 size; - - if (is_root_decoder(dev)) - size = resource_size(&cxld->platform_res); - else - size = range_len(&cxld->decoder_range); - return sysfs_emit(buf, "%#llx\n", size); + return sysfs_emit(buf, "%#llx\n", range_len(&cxld->hpa_range)); } static DEVICE_ATTR_RO(size); @@ -131,20 +125,21 @@ static ssize_t target_type_show(struct device *dev, } static DEVICE_ATTR_RO(target_type); -static ssize_t emit_target_list(struct cxl_decoder *cxld, char *buf) +static ssize_t emit_target_list(struct cxl_switch_decoder *cxlsd, char *buf) { + struct cxl_decoder *cxld = &cxlsd->cxld; ssize_t offset = 0; int i, rc = 0; for (i = 0; i < cxld->interleave_ways; i++) { - struct cxl_dport *dport = cxld->target[i]; + struct cxl_dport *dport = cxlsd->target[i]; struct cxl_dport *next = NULL; if (!dport) break; if (i + 1 < cxld->interleave_ways) - next = cxld->target[i + 1]; + next = cxlsd->target[i + 1]; rc = sysfs_emit_at(buf, offset, "%d%s", dport->port_id, next ? "," : ""); if (rc < 0) @@ -158,15 +153,15 @@ static ssize_t emit_target_list(struct cxl_decoder *cxld, char *buf) static ssize_t target_list_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct cxl_decoder *cxld = to_cxl_decoder(dev); + struct cxl_switch_decoder *cxlsd = to_cxl_switch_decoder(dev); ssize_t offset; unsigned int seq; int rc; do { - seq = read_seqbegin(&cxld->target_lock); - rc = emit_target_list(cxld, buf); - } while (read_seqretry(&cxld->target_lock, seq)); + seq = read_seqbegin(&cxlsd->target_lock); + rc = emit_target_list(cxlsd, buf); + } while (read_seqretry(&cxlsd->target_lock, seq)); if (rc < 0) return rc; @@ -180,10 +175,121 @@ static ssize_t target_list_show(struct device *dev, } static DEVICE_ATTR_RO(target_list); +static ssize_t mode_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + + switch (cxled->mode) { + case CXL_DECODER_RAM: + return sysfs_emit(buf, "ram\n"); + case CXL_DECODER_PMEM: + return sysfs_emit(buf, "pmem\n"); + case CXL_DECODER_NONE: + return sysfs_emit(buf, "none\n"); + case CXL_DECODER_MIXED: + default: + return sysfs_emit(buf, "mixed\n"); + } +} + +static ssize_t mode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + enum cxl_decoder_mode mode; + ssize_t rc; + + if (sysfs_streq(buf, "pmem")) + mode = CXL_DECODER_PMEM; + else if (sysfs_streq(buf, "ram")) + mode = CXL_DECODER_RAM; + else + return -EINVAL; + + rc = cxl_dpa_set_mode(cxled, mode); + if (rc) + return rc; + + return len; +} +static DEVICE_ATTR_RW(mode); + +static ssize_t dpa_resource_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + u64 base = cxl_dpa_resource_start(cxled); + + return sysfs_emit(buf, "%#llx\n", base); +} +static DEVICE_ATTR_RO(dpa_resource); + +static ssize_t dpa_size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + resource_size_t size = cxl_dpa_size(cxled); + + return sysfs_emit(buf, "%pa\n", &size); +} + +static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + unsigned long long size; + ssize_t rc; + + rc = kstrtoull(buf, 0, &size); + if (rc) + return rc; + + if (!IS_ALIGNED(size, SZ_256M)) + return -EINVAL; + + rc = cxl_dpa_free(cxled); + if (rc) + return rc; + + if (size == 0) + return len; + + rc = cxl_dpa_alloc(cxled, size); + if (rc) + return rc; + + return len; +} +static DEVICE_ATTR_RW(dpa_size); + +static ssize_t interleave_granularity_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + + return sysfs_emit(buf, "%d\n", cxld->interleave_granularity); +} + +static DEVICE_ATTR_RO(interleave_granularity); + +static ssize_t interleave_ways_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + + return sysfs_emit(buf, "%d\n", cxld->interleave_ways); +} + +static DEVICE_ATTR_RO(interleave_ways); + static struct attribute *cxl_decoder_base_attrs[] = { &dev_attr_start.attr, &dev_attr_size.attr, &dev_attr_locked.attr, + &dev_attr_interleave_granularity.attr, + &dev_attr_interleave_ways.attr, NULL, }; @@ -197,11 +303,35 @@ static struct attribute *cxl_decoder_root_attrs[] = { &dev_attr_cap_type2.attr, &dev_attr_cap_type3.attr, &dev_attr_target_list.attr, + SET_CXL_REGION_ATTR(create_pmem_region) + SET_CXL_REGION_ATTR(delete_region) NULL, }; +static bool can_create_pmem(struct cxl_root_decoder *cxlrd) +{ + unsigned long flags = CXL_DECODER_F_TYPE3 | CXL_DECODER_F_PMEM; + + return (cxlrd->cxlsd.cxld.flags & flags) == flags; +} + +static umode_t cxl_root_decoder_visible(struct kobject *kobj, struct attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); + + if (a == CXL_REGION_ATTR(create_pmem_region) && !can_create_pmem(cxlrd)) + return 0; + + if (a == CXL_REGION_ATTR(delete_region) && !can_create_pmem(cxlrd)) + return 0; + + return a->mode; +} + static struct attribute_group cxl_decoder_root_attribute_group = { .attrs = cxl_decoder_root_attrs, + .is_visible = cxl_root_decoder_visible, }; static const struct attribute_group *cxl_decoder_root_attribute_groups[] = { @@ -214,6 +344,7 @@ static const struct attribute_group *cxl_decoder_root_attribute_groups[] = { static struct attribute *cxl_decoder_switch_attrs[] = { &dev_attr_target_type.attr, &dev_attr_target_list.attr, + SET_CXL_REGION_ATTR(region) NULL, }; @@ -230,6 +361,10 @@ static const struct attribute_group *cxl_decoder_switch_attribute_groups[] = { static struct attribute *cxl_decoder_endpoint_attrs[] = { &dev_attr_target_type.attr, + &dev_attr_mode.attr, + &dev_attr_dpa_size.attr, + &dev_attr_dpa_resource.attr, + SET_CXL_REGION_ATTR(region) NULL, }; @@ -244,31 +379,64 @@ static const struct attribute_group *cxl_decoder_endpoint_attribute_groups[] = { NULL, }; -static void cxl_decoder_release(struct device *dev) +static void __cxl_decoder_release(struct cxl_decoder *cxld) { - struct cxl_decoder *cxld = to_cxl_decoder(dev); - struct cxl_port *port = to_cxl_port(dev->parent); + struct cxl_port *port = to_cxl_port(cxld->dev.parent); ida_free(&port->decoder_ida, cxld->id); - kfree(cxld); put_device(&port->dev); } +static void cxl_endpoint_decoder_release(struct device *dev) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + + __cxl_decoder_release(&cxled->cxld); + kfree(cxled); +} + +static void cxl_switch_decoder_release(struct device *dev) +{ + struct cxl_switch_decoder *cxlsd = to_cxl_switch_decoder(dev); + + __cxl_decoder_release(&cxlsd->cxld); + kfree(cxlsd); +} + +struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev) +{ + if (dev_WARN_ONCE(dev, !is_root_decoder(dev), + "not a cxl_root_decoder device\n")) + return NULL; + return container_of(dev, struct cxl_root_decoder, cxlsd.cxld.dev); +} +EXPORT_SYMBOL_NS_GPL(to_cxl_root_decoder, CXL); + +static void cxl_root_decoder_release(struct device *dev) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); + + if (atomic_read(&cxlrd->region_id) >= 0) + memregion_free(atomic_read(&cxlrd->region_id)); + __cxl_decoder_release(&cxlrd->cxlsd.cxld); + kfree(cxlrd); +} + static const struct device_type cxl_decoder_endpoint_type = { .name = "cxl_decoder_endpoint", - .release = cxl_decoder_release, + .release = cxl_endpoint_decoder_release, .groups = cxl_decoder_endpoint_attribute_groups, }; static const struct device_type cxl_decoder_switch_type = { .name = "cxl_decoder_switch", - .release = cxl_decoder_release, + .release = cxl_switch_decoder_release, .groups = cxl_decoder_switch_attribute_groups, }; static const struct device_type cxl_decoder_root_type = { .name = "cxl_decoder_root", - .release = cxl_decoder_release, + .release = cxl_root_decoder_release, .groups = cxl_decoder_root_attribute_groups, }; @@ -283,39 +451,63 @@ bool is_root_decoder(struct device *dev) } EXPORT_SYMBOL_NS_GPL(is_root_decoder, CXL); -bool is_cxl_decoder(struct device *dev) +bool is_switch_decoder(struct device *dev) { - return dev->type && dev->type->release == cxl_decoder_release; + return is_root_decoder(dev) || dev->type == &cxl_decoder_switch_type; } -EXPORT_SYMBOL_NS_GPL(is_cxl_decoder, CXL); struct cxl_decoder *to_cxl_decoder(struct device *dev) { - if (dev_WARN_ONCE(dev, dev->type->release != cxl_decoder_release, + if (dev_WARN_ONCE(dev, + !is_switch_decoder(dev) && !is_endpoint_decoder(dev), "not a cxl_decoder device\n")) return NULL; return container_of(dev, struct cxl_decoder, dev); } EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, CXL); +struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev) +{ + if (dev_WARN_ONCE(dev, !is_endpoint_decoder(dev), + "not a cxl_endpoint_decoder device\n")) + return NULL; + return container_of(dev, struct cxl_endpoint_decoder, cxld.dev); +} +EXPORT_SYMBOL_NS_GPL(to_cxl_endpoint_decoder, CXL); + +struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev) +{ + if (dev_WARN_ONCE(dev, !is_switch_decoder(dev), + "not a cxl_switch_decoder device\n")) + return NULL; + return container_of(dev, struct cxl_switch_decoder, cxld.dev); +} + static void cxl_ep_release(struct cxl_ep *ep) { - if (!ep) - return; - list_del(&ep->list); put_device(ep->ep); kfree(ep); } +static void cxl_ep_remove(struct cxl_port *port, struct cxl_ep *ep) +{ + if (!ep) + return; + xa_erase(&port->endpoints, (unsigned long) ep->ep); + cxl_ep_release(ep); +} + static void cxl_port_release(struct device *dev) { struct cxl_port *port = to_cxl_port(dev); - struct cxl_ep *ep, *_e; + unsigned long index; + struct cxl_ep *ep; - device_lock(dev); - list_for_each_entry_safe(ep, _e, &port->endpoints, list) - cxl_ep_release(ep); - device_unlock(dev); + xa_for_each(&port->endpoints, index, ep) + cxl_ep_remove(port, ep); + xa_destroy(&port->endpoints); + xa_destroy(&port->dports); + xa_destroy(&port->regions); ida_free(&cxl_port_ida, port->id); kfree(port); } @@ -370,7 +562,7 @@ static void unregister_port(void *_port) lock_dev = &parent->dev; device_lock_assert(lock_dev); - port->uport = NULL; + port->dead = true; device_unregister(&port->dev); } @@ -395,7 +587,7 @@ static struct lock_class_key cxl_port_key; static struct cxl_port *cxl_port_alloc(struct device *uport, resource_size_t component_reg_phys, - struct cxl_port *parent_port) + struct cxl_dport *parent_dport) { struct cxl_port *port; struct device *dev; @@ -409,6 +601,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (rc < 0) goto err; port->id = rc; + port->uport = uport; /* * The top-level cxl_port "cxl_root" does not have a cxl_port as @@ -417,17 +610,37 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, * description. */ dev = &port->dev; - if (parent_port) { + if (parent_dport) { + struct cxl_port *parent_port = parent_dport->port; + struct cxl_port *iter; + dev->parent = &parent_port->dev; port->depth = parent_port->depth + 1; + port->parent_dport = parent_dport; + + /* + * walk to the host bridge, or the first ancestor that knows + * the host bridge + */ + iter = port; + while (!iter->host_bridge && + !is_cxl_root(to_cxl_port(iter->dev.parent))) + iter = to_cxl_port(iter->dev.parent); + if (iter->host_bridge) + port->host_bridge = iter->host_bridge; + else + port->host_bridge = iter->uport; + dev_dbg(uport, "host-bridge: %s\n", dev_name(port->host_bridge)); } else dev->parent = uport; - port->uport = uport; port->component_reg_phys = component_reg_phys; ida_init(&port->decoder_ida); - INIT_LIST_HEAD(&port->dports); - INIT_LIST_HEAD(&port->endpoints); + port->hdm_end = -1; + port->commit_end = -1; + xa_init(&port->dports); + xa_init(&port->endpoints); + xa_init(&port->regions); device_initialize(dev); lockdep_set_class_and_subclass(&dev->mutex, &cxl_port_key, port->depth); @@ -447,24 +660,24 @@ err: * @host: host device for devm operations * @uport: "physical" device implementing this upstream port * @component_reg_phys: (optional) for configurable cxl_port instances - * @parent_port: next hop up in the CXL memory decode hierarchy + * @parent_dport: next hop up in the CXL memory decode hierarchy */ struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, resource_size_t component_reg_phys, - struct cxl_port *parent_port) + struct cxl_dport *parent_dport) { struct cxl_port *port; struct device *dev; int rc; - port = cxl_port_alloc(uport, component_reg_phys, parent_port); + port = cxl_port_alloc(uport, component_reg_phys, parent_dport); if (IS_ERR(port)) return port; dev = &port->dev; if (is_cxl_memdev(uport)) rc = dev_set_name(dev, "endpoint%d", port->id); - else if (parent_port) + else if (parent_dport) rc = dev_set_name(dev, "port%d", port->id); else rc = dev_set_name(dev, "root%d", port->id); @@ -556,17 +769,13 @@ static int match_root_child(struct device *dev, const void *match) return 0; port = to_cxl_port(dev); - device_lock(dev); - list_for_each_entry(dport, &port->dports, list) { - iter = match; - while (iter) { - if (iter == dport->dport) - goto out; - iter = iter->parent; - } + iter = match; + while (iter) { + dport = cxl_find_dport_by_dev(port, iter); + if (dport) + break; + iter = iter->parent; } -out: - device_unlock(dev); return !!iter; } @@ -590,9 +799,10 @@ EXPORT_SYMBOL_NS_GPL(find_cxl_root, CXL); static struct cxl_dport *find_dport(struct cxl_port *port, int id) { struct cxl_dport *dport; + unsigned long index; device_lock_assert(&port->dev); - list_for_each_entry (dport, &port->dports, list) + xa_for_each(&port->dports, index, dport) if (dport->port_id == id) return dport; return NULL; @@ -604,15 +814,15 @@ static int add_dport(struct cxl_port *port, struct cxl_dport *new) device_lock_assert(&port->dev); dup = find_dport(port, new->port_id); - if (dup) + if (dup) { dev_err(&port->dev, "unable to add dport%d-%s non-unique port id (%s)\n", new->port_id, dev_name(new->dport), dev_name(dup->dport)); - else - list_add_tail(&new->list, &port->dports); - - return dup ? -EEXIST : 0; + return -EBUSY; + } + return xa_insert(&port->dports, (unsigned long)new->dport, new, + GFP_KERNEL); } /* @@ -639,10 +849,8 @@ static void cxl_dport_remove(void *data) struct cxl_dport *dport = data; struct cxl_port *port = dport->port; + xa_erase(&port->dports, (unsigned long) dport->dport); put_device(dport->dport); - cond_cxl_root_lock(port); - list_del(&dport->list); - cond_cxl_root_unlock(port); } static void cxl_dport_unlink(void *data) @@ -694,7 +902,6 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, if (!dport) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&dport->list); dport->dport = dport_dev; dport->port_id = port_id; dport->component_reg_phys = component_reg_phys; @@ -723,44 +930,33 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, } EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL); -static struct cxl_ep *find_ep(struct cxl_port *port, struct device *ep_dev) -{ - struct cxl_ep *ep; - - device_lock_assert(&port->dev); - list_for_each_entry(ep, &port->endpoints, list) - if (ep->ep == ep_dev) - return ep; - return NULL; -} - -static int add_ep(struct cxl_port *port, struct cxl_ep *new) +static int add_ep(struct cxl_ep *new) { - struct cxl_ep *dup; + struct cxl_port *port = new->dport->port; + int rc; device_lock(&port->dev); if (port->dead) { device_unlock(&port->dev); return -ENXIO; } - dup = find_ep(port, new->ep); - if (!dup) - list_add_tail(&new->list, &port->endpoints); + rc = xa_insert(&port->endpoints, (unsigned long)new->ep, new, + GFP_KERNEL); device_unlock(&port->dev); - return dup ? -EEXIST : 0; + return rc; } /** * cxl_add_ep - register an endpoint's interest in a port - * @port: a port in the endpoint's topology ancestry + * @dport: the dport that routes to @ep_dev * @ep_dev: device representing the endpoint * * Intermediate CXL ports are scanned based on the arrival of endpoints. * When those endpoints depart the port can be destroyed once all * endpoints that care about that port have been removed. */ -static int cxl_add_ep(struct cxl_port *port, struct device *ep_dev) +static int cxl_add_ep(struct cxl_dport *dport, struct device *ep_dev) { struct cxl_ep *ep; int rc; @@ -769,10 +965,10 @@ static int cxl_add_ep(struct cxl_port *port, struct device *ep_dev) if (!ep) return -ENOMEM; - INIT_LIST_HEAD(&ep->list); ep->ep = get_device(ep_dev); + ep->dport = dport; - rc = add_ep(port, ep); + rc = add_ep(ep); if (rc) cxl_ep_release(ep); return rc; @@ -781,11 +977,13 @@ static int cxl_add_ep(struct cxl_port *port, struct device *ep_dev) struct cxl_find_port_ctx { const struct device *dport_dev; const struct cxl_port *parent_port; + struct cxl_dport **dport; }; static int match_port_by_dport(struct device *dev, const void *data) { const struct cxl_find_port_ctx *ctx = data; + struct cxl_dport *dport; struct cxl_port *port; if (!is_cxl_port(dev)) @@ -794,7 +992,10 @@ static int match_port_by_dport(struct device *dev, const void *data) return 0; port = to_cxl_port(dev); - return cxl_find_dport_by_dev(port, ctx->dport_dev) != NULL; + dport = cxl_find_dport_by_dev(port, ctx->dport_dev); + if (ctx->dport) + *ctx->dport = dport; + return dport != NULL; } static struct cxl_port *__find_cxl_port(struct cxl_find_port_ctx *ctx) @@ -810,24 +1011,32 @@ static struct cxl_port *__find_cxl_port(struct cxl_find_port_ctx *ctx) return NULL; } -static struct cxl_port *find_cxl_port(struct device *dport_dev) +static struct cxl_port *find_cxl_port(struct device *dport_dev, + struct cxl_dport **dport) { struct cxl_find_port_ctx ctx = { .dport_dev = dport_dev, + .dport = dport, }; + struct cxl_port *port; - return __find_cxl_port(&ctx); + port = __find_cxl_port(&ctx); + return port; } static struct cxl_port *find_cxl_port_at(struct cxl_port *parent_port, - struct device *dport_dev) + struct device *dport_dev, + struct cxl_dport **dport) { struct cxl_find_port_ctx ctx = { .dport_dev = dport_dev, .parent_port = parent_port, + .dport = dport, }; + struct cxl_port *port; - return __find_cxl_port(&ctx); + port = __find_cxl_port(&ctx); + return port; } /* @@ -851,13 +1060,13 @@ static void delete_endpoint(void *data) struct cxl_port *parent_port; struct device *parent; - parent_port = cxl_mem_find_port(cxlmd); + parent_port = cxl_mem_find_port(cxlmd, NULL); if (!parent_port) goto out; parent = &parent_port->dev; device_lock(parent); - if (parent->driver && endpoint->uport) { + if (parent->driver && !endpoint->dead) { devm_release_action(parent, cxl_unlink_uport, endpoint); devm_release_action(parent, unregister_port, endpoint); } @@ -883,21 +1092,70 @@ EXPORT_SYMBOL_NS_GPL(cxl_endpoint_autoremove, CXL); * for a port to be unregistered is when all memdevs beneath that port have gone * through ->remove(). This "bottom-up" removal selectively removes individual * child ports manually. This depends on devm_cxl_add_port() to not change is - * devm action registration order. + * devm action registration order, and for dports to have already been + * destroyed by reap_dports(). */ -static void delete_switch_port(struct cxl_port *port, struct list_head *dports) +static void delete_switch_port(struct cxl_port *port) +{ + devm_release_action(port->dev.parent, cxl_unlink_uport, port); + devm_release_action(port->dev.parent, unregister_port, port); +} + +static void reap_dports(struct cxl_port *port) { - struct cxl_dport *dport, *_d; + struct cxl_dport *dport; + unsigned long index; + + device_lock_assert(&port->dev); - list_for_each_entry_safe(dport, _d, dports, list) { + xa_for_each(&port->dports, index, dport) { devm_release_action(&port->dev, cxl_dport_unlink, dport); devm_release_action(&port->dev, cxl_dport_remove, dport); devm_kfree(&port->dev, dport); } - devm_release_action(port->dev.parent, cxl_unlink_uport, port); - devm_release_action(port->dev.parent, unregister_port, port); } +int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd, + struct cxl_dport *parent_dport) +{ + struct cxl_port *parent_port = parent_dport->port; + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_port *endpoint, *iter, *down; + int rc; + + /* + * Now that the path to the root is established record all the + * intervening ports in the chain. + */ + for (iter = parent_port, down = NULL; !is_cxl_root(iter); + down = iter, iter = to_cxl_port(iter->dev.parent)) { + struct cxl_ep *ep; + + ep = cxl_ep_load(iter, cxlmd); + ep->next = down; + } + + endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev, + cxlds->component_reg_phys, parent_dport); + if (IS_ERR(endpoint)) + return PTR_ERR(endpoint); + + dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev)); + + rc = cxl_endpoint_autoremove(cxlmd, endpoint); + if (rc) + return rc; + + if (!endpoint->dev.driver) { + dev_err(&cxlmd->dev, "%s failed probe\n", + dev_name(&endpoint->dev)); + return -ENXIO; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(devm_cxl_add_endpoint, CXL); + static void cxl_detach_ep(void *data) { struct cxl_memdev *cxlmd = data; @@ -906,13 +1164,13 @@ static void cxl_detach_ep(void *data) for (iter = &cxlmd->dev; iter; iter = grandparent(iter)) { struct device *dport_dev = grandparent(iter); struct cxl_port *port, *parent_port; - LIST_HEAD(reap_dports); struct cxl_ep *ep; + bool died = false; if (!dport_dev) break; - port = find_cxl_port(dport_dev); + port = find_cxl_port(dport_dev, NULL); if (!port) continue; @@ -936,26 +1194,27 @@ static void cxl_detach_ep(void *data) } device_lock(&port->dev); - ep = find_ep(port, &cxlmd->dev); + ep = cxl_ep_load(port, cxlmd); dev_dbg(&cxlmd->dev, "disconnect %s from %s\n", ep ? dev_name(ep->ep) : "", dev_name(&port->dev)); - cxl_ep_release(ep); - if (ep && !port->dead && list_empty(&port->endpoints) && + cxl_ep_remove(port, ep); + if (ep && !port->dead && xa_empty(&port->endpoints) && !is_cxl_root(parent_port)) { /* * This was the last ep attached to a dynamically * enumerated port. Block new cxl_add_ep() and garbage * collect the port. */ + died = true; port->dead = true; - list_splice_init(&port->dports, &reap_dports); + reap_dports(port); } device_unlock(&port->dev); - if (!list_empty(&reap_dports)) { + if (died) { dev_dbg(&cxlmd->dev, "delete %s\n", dev_name(&port->dev)); - delete_switch_port(port, &reap_dports); + delete_switch_port(port); } put_device(&port->dev); device_unlock(&parent_port->dev); @@ -986,6 +1245,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd, { struct device *dparent = grandparent(dport_dev); struct cxl_port *port, *parent_port = NULL; + struct cxl_dport *dport, *parent_dport; resource_size_t component_reg_phys; int rc; @@ -1000,7 +1260,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd, return -ENXIO; } - parent_port = find_cxl_port(dparent); + parent_port = find_cxl_port(dparent, &parent_dport); if (!parent_port) { /* iterate to create this parent_port */ return -EAGAIN; @@ -1015,13 +1275,14 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd, goto out; } - port = find_cxl_port_at(parent_port, dport_dev); + port = find_cxl_port_at(parent_port, dport_dev, &dport); if (!port) { component_reg_phys = find_component_registers(uport_dev); port = devm_cxl_add_port(&parent_port->dev, uport_dev, - component_reg_phys, parent_port); + component_reg_phys, parent_dport); + /* retry find to pick up the new dport information */ if (!IS_ERR(port)) - get_device(&port->dev); + port = find_cxl_port_at(parent_port, dport_dev, &dport); } out: device_unlock(&parent_port->dev); @@ -1031,8 +1292,8 @@ out: else { dev_dbg(&cxlmd->dev, "add to new port %s:%s\n", dev_name(&port->dev), dev_name(port->uport)); - rc = cxl_add_ep(port, &cxlmd->dev); - if (rc == -EEXIST) { + rc = cxl_add_ep(dport, &cxlmd->dev); + if (rc == -EBUSY) { /* * "can't" happen, but this error code means * something to the caller, so translate it. @@ -1065,6 +1326,7 @@ retry: for (iter = dev; iter; iter = grandparent(iter)) { struct device *dport_dev = grandparent(iter); struct device *uport_dev; + struct cxl_dport *dport; struct cxl_port *port; if (!dport_dev) @@ -1080,12 +1342,12 @@ retry: dev_dbg(dev, "scan: iter: %s dport_dev: %s parent: %s\n", dev_name(iter), dev_name(dport_dev), dev_name(uport_dev)); - port = find_cxl_port(dport_dev); + port = find_cxl_port(dport_dev, &dport); if (port) { dev_dbg(&cxlmd->dev, "found already registered port %s:%s\n", dev_name(&port->dev), dev_name(port->uport)); - rc = cxl_add_ep(port, &cxlmd->dev); + rc = cxl_add_ep(dport, &cxlmd->dev); /* * If the endpoint already exists in the port's list, @@ -1094,7 +1356,7 @@ retry: * the parent_port lock as the current port may be being * reaped. */ - if (rc && rc != -EEXIST) { + if (rc && rc != -EBUSY) { put_device(&port->dev); return rc; } @@ -1124,30 +1386,14 @@ retry: } EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL); -struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd) +struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, + struct cxl_dport **dport) { - return find_cxl_port(grandparent(&cxlmd->dev)); + return find_cxl_port(grandparent(&cxlmd->dev), dport); } EXPORT_SYMBOL_NS_GPL(cxl_mem_find_port, CXL); -struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port, - const struct device *dev) -{ - struct cxl_dport *dport; - - device_lock(&port->dev); - list_for_each_entry(dport, &port->dports, list) - if (dport->dport == dev) { - device_unlock(&port->dev); - return dport; - } - - device_unlock(&port->dev); - return NULL; -} -EXPORT_SYMBOL_NS_GPL(cxl_find_dport_by_dev, CXL); - -static int decoder_populate_targets(struct cxl_decoder *cxld, +static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd, struct cxl_port *port, int *target_map) { int i, rc = 0; @@ -1157,88 +1403,92 @@ static int decoder_populate_targets(struct cxl_decoder *cxld, device_lock_assert(&port->dev); - if (list_empty(&port->dports)) + if (xa_empty(&port->dports)) return -EINVAL; - write_seqlock(&cxld->target_lock); - for (i = 0; i < cxld->nr_targets; i++) { + write_seqlock(&cxlsd->target_lock); + for (i = 0; i < cxlsd->nr_targets; i++) { struct cxl_dport *dport = find_dport(port, target_map[i]); if (!dport) { rc = -ENXIO; break; } - cxld->target[i] = dport; + cxlsd->target[i] = dport; } - write_sequnlock(&cxld->target_lock); + write_sequnlock(&cxlsd->target_lock); return rc; } +static struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos) +{ + struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd; + struct cxl_decoder *cxld = &cxlsd->cxld; + int iw; + + iw = cxld->interleave_ways; + if (dev_WARN_ONCE(&cxld->dev, iw != cxlsd->nr_targets, + "misconfigured root decoder\n")) + return NULL; + + return cxlrd->cxlsd.target[pos % iw]; +} + static struct lock_class_key cxl_decoder_key; /** - * cxl_decoder_alloc - Allocate a new CXL decoder + * cxl_decoder_init - Common decoder setup / initialization * @port: owning port of this decoder - * @nr_targets: downstream targets accessible by this decoder. All upstream - * ports and root ports must have at least 1 target. Endpoint - * devices will have 0 targets. Callers wishing to register an - * endpoint device should specify 0. - * - * A port should contain one or more decoders. Each of those decoders enable - * some address space for CXL.mem utilization. A decoder is expected to be - * configured by the caller before registering. + * @cxld: common decoder properties to initialize * - * Return: A new cxl decoder to be registered by cxl_decoder_add(). The decoder - * is initialized to be a "passthrough" decoder. + * A port may contain one or more decoders. Each of those decoders + * enable some address space for CXL.mem utilization. A decoder is + * expected to be configured by the caller before registering via + * cxl_decoder_add() */ -static struct cxl_decoder *cxl_decoder_alloc(struct cxl_port *port, - unsigned int nr_targets) +static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld) { - struct cxl_decoder *cxld; struct device *dev; - int rc = 0; - - if (nr_targets > CXL_DECODER_MAX_INTERLEAVE) - return ERR_PTR(-EINVAL); - - cxld = kzalloc(struct_size(cxld, target, nr_targets), GFP_KERNEL); - if (!cxld) - return ERR_PTR(-ENOMEM); + int rc; rc = ida_alloc(&port->decoder_ida, GFP_KERNEL); if (rc < 0) - goto err; + return rc; /* need parent to stick around to release the id */ get_device(&port->dev); cxld->id = rc; - cxld->nr_targets = nr_targets; - seqlock_init(&cxld->target_lock); dev = &cxld->dev; device_initialize(dev); lockdep_set_class(&dev->mutex, &cxl_decoder_key); device_set_pm_not_required(dev); dev->parent = &port->dev; dev->bus = &cxl_bus_type; - if (is_cxl_root(port)) - cxld->dev.type = &cxl_decoder_root_type; - else if (is_cxl_endpoint(port)) - cxld->dev.type = &cxl_decoder_endpoint_type; - else - cxld->dev.type = &cxl_decoder_switch_type; /* Pre initialize an "empty" decoder */ cxld->interleave_ways = 1; cxld->interleave_granularity = PAGE_SIZE; cxld->target_type = CXL_DECODER_EXPANDER; - cxld->platform_res = (struct resource)DEFINE_RES_MEM(0, 0); + cxld->hpa_range = (struct range) { + .start = 0, + .end = -1, + }; - return cxld; -err: - kfree(cxld); - return ERR_PTR(rc); + return 0; +} + +static int cxl_switch_decoder_init(struct cxl_port *port, + struct cxl_switch_decoder *cxlsd, + int nr_targets) +{ + if (nr_targets > CXL_DECODER_MAX_INTERLEAVE) + return -EINVAL; + + cxlsd->nr_targets = nr_targets; + seqlock_init(&cxlsd->target_lock); + return cxl_decoder_init(port, &cxlsd->cxld); } /** @@ -1251,13 +1501,46 @@ err: * firmware description of CXL resources into a CXL standard decode * topology. */ -struct cxl_decoder *cxl_root_decoder_alloc(struct cxl_port *port, - unsigned int nr_targets) +struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port, + unsigned int nr_targets) { + struct cxl_root_decoder *cxlrd; + struct cxl_switch_decoder *cxlsd; + struct cxl_decoder *cxld; + int rc; + if (!is_cxl_root(port)) return ERR_PTR(-EINVAL); - return cxl_decoder_alloc(port, nr_targets); + cxlrd = kzalloc(struct_size(cxlrd, cxlsd.target, nr_targets), + GFP_KERNEL); + if (!cxlrd) + return ERR_PTR(-ENOMEM); + + cxlsd = &cxlrd->cxlsd; + rc = cxl_switch_decoder_init(port, cxlsd, nr_targets); + if (rc) { + kfree(cxlrd); + return ERR_PTR(rc); + } + + cxlrd->calc_hb = cxl_hb_modulo; + + cxld = &cxlsd->cxld; + cxld->dev.type = &cxl_decoder_root_type; + /* + * cxl_root_decoder_release() special cases negative ids to + * detect memregion_alloc() failures. + */ + atomic_set(&cxlrd->region_id, -1); + rc = memregion_alloc(GFP_KERNEL); + if (rc < 0) { + put_device(&cxld->dev); + return ERR_PTR(rc); + } + + atomic_set(&cxlrd->region_id, rc); + return cxlrd; } EXPORT_SYMBOL_NS_GPL(cxl_root_decoder_alloc, CXL); @@ -1272,13 +1555,29 @@ EXPORT_SYMBOL_NS_GPL(cxl_root_decoder_alloc, CXL); * that sit between Switch Upstream Ports / Switch Downstream Ports and * Host Bridges / Root Ports. */ -struct cxl_decoder *cxl_switch_decoder_alloc(struct cxl_port *port, - unsigned int nr_targets) +struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port, + unsigned int nr_targets) { + struct cxl_switch_decoder *cxlsd; + struct cxl_decoder *cxld; + int rc; + if (is_cxl_root(port) || is_cxl_endpoint(port)) return ERR_PTR(-EINVAL); - return cxl_decoder_alloc(port, nr_targets); + cxlsd = kzalloc(struct_size(cxlsd, target, nr_targets), GFP_KERNEL); + if (!cxlsd) + return ERR_PTR(-ENOMEM); + + rc = cxl_switch_decoder_init(port, cxlsd, nr_targets); + if (rc) { + kfree(cxlsd); + return ERR_PTR(rc); + } + + cxld = &cxlsd->cxld; + cxld->dev.type = &cxl_decoder_switch_type; + return cxlsd; } EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL); @@ -1288,18 +1587,35 @@ EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL); * * Return: A new cxl decoder to be registered by cxl_decoder_add() */ -struct cxl_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port) +struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port) { + struct cxl_endpoint_decoder *cxled; + struct cxl_decoder *cxld; + int rc; + if (!is_cxl_endpoint(port)) return ERR_PTR(-EINVAL); - return cxl_decoder_alloc(port, 0); + cxled = kzalloc(sizeof(*cxled), GFP_KERNEL); + if (!cxled) + return ERR_PTR(-ENOMEM); + + cxled->pos = -1; + cxld = &cxled->cxld; + rc = cxl_decoder_init(port, cxld); + if (rc) { + kfree(cxled); + return ERR_PTR(rc); + } + + cxld->dev.type = &cxl_decoder_endpoint_type; + return cxled; } EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_alloc, CXL); /** * cxl_decoder_add_locked - Add a decoder with targets - * @cxld: The cxl decoder allocated by cxl_decoder_alloc() + * @cxld: The cxl decoder allocated by cxl_<type>_decoder_alloc() * @target_map: A list of downstream ports that this decoder can direct memory * traffic to. These numbers should correspond with the port number * in the PCIe Link Capabilities structure. @@ -1335,7 +1651,9 @@ int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map) port = to_cxl_port(cxld->dev.parent); if (!is_endpoint_decoder(dev)) { - rc = decoder_populate_targets(cxld, port, target_map); + struct cxl_switch_decoder *cxlsd = to_cxl_switch_decoder(dev); + + rc = decoder_populate_targets(cxlsd, port, target_map); if (rc && (cxld->flags & CXL_DECODER_F_ENABLE)) { dev_err(&port->dev, "Failed to populate active decoder targets\n"); @@ -1347,20 +1665,13 @@ int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map) if (rc) return rc; - /* - * Platform decoder resources should show up with a reasonable name. All - * other resources are just sub ranges within the main decoder resource. - */ - if (is_root_decoder(dev)) - cxld->platform_res.name = dev_name(dev); - return device_add(dev); } EXPORT_SYMBOL_NS_GPL(cxl_decoder_add_locked, CXL); /** * cxl_decoder_add - Add a decoder with targets - * @cxld: The cxl decoder allocated by cxl_decoder_alloc() + * @cxld: The cxl decoder allocated by cxl_<type>_decoder_alloc() * @target_map: A list of downstream ports that this decoder can direct memory * traffic to. These numbers should correspond with the port number * in the PCIe Link Capabilities structure. @@ -1394,6 +1705,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_decoder_add, CXL); static void cxld_unregister(void *dev) { + struct cxl_endpoint_decoder *cxled; + + if (is_endpoint_decoder(dev)) { + cxled = to_cxl_endpoint_decoder(dev); + cxl_decoder_kill_region(cxled); + } + device_unregister(dev); } @@ -1521,10 +1839,20 @@ struct bus_type cxl_bus_type = { }; EXPORT_SYMBOL_NS_GPL(cxl_bus_type, CXL); +static struct dentry *cxl_debugfs; + +struct dentry *cxl_debugfs_create_dir(const char *dir) +{ + return debugfs_create_dir(dir, cxl_debugfs); +} +EXPORT_SYMBOL_NS_GPL(cxl_debugfs_create_dir, CXL); + static __init int cxl_core_init(void) { int rc; + cxl_debugfs = debugfs_create_dir("cxl", NULL); + cxl_mbox_init(); rc = cxl_memdev_init(); @@ -1541,22 +1869,28 @@ static __init int cxl_core_init(void) if (rc) goto err_bus; + rc = cxl_region_init(); + if (rc) + goto err_region; + return 0; +err_region: + bus_unregister(&cxl_bus_type); err_bus: destroy_workqueue(cxl_bus_wq); err_wq: cxl_memdev_exit(); - cxl_mbox_exit(); return rc; } static void cxl_core_exit(void) { + cxl_region_exit(); bus_unregister(&cxl_bus_type); destroy_workqueue(cxl_bus_wq); cxl_memdev_exit(); - cxl_mbox_exit(); + debugfs_remove_recursive(cxl_debugfs); } module_init(cxl_core_init); diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c new file mode 100644 index 000000000000..401148016978 --- /dev/null +++ b/drivers/cxl/core/region.c @@ -0,0 +1,1896 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2022 Intel Corporation. All rights reserved. */ +#include <linux/memregion.h> +#include <linux/genalloc.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/uuid.h> +#include <linux/idr.h> +#include <cxlmem.h> +#include <cxl.h> +#include "core.h" + +/** + * DOC: cxl core region + * + * CXL Regions represent mapped memory capacity in system physical address + * space. Whereas the CXL Root Decoders identify the bounds of potential CXL + * Memory ranges, Regions represent the active mapped capacity by the HDM + * Decoder Capability structures throughout the Host Bridges, Switches, and + * Endpoints in the topology. + * + * Region configuration has ordering constraints. UUID may be set at any time + * but is only visible for persistent regions. + * 1. Interleave granularity + * 2. Interleave size + * 3. Decoder targets + */ + +/* + * All changes to the interleave configuration occur with this lock held + * for write. + */ +static DECLARE_RWSEM(cxl_region_rwsem); + +static struct cxl_region *to_cxl_region(struct device *dev); + +static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + rc = sysfs_emit(buf, "%pUb\n", &p->uuid); + up_read(&cxl_region_rwsem); + + return rc; +} + +static int is_dup(struct device *match, void *data) +{ + struct cxl_region_params *p; + struct cxl_region *cxlr; + uuid_t *uuid = data; + + if (!is_cxl_region(match)) + return 0; + + lockdep_assert_held(&cxl_region_rwsem); + cxlr = to_cxl_region(match); + p = &cxlr->params; + + if (uuid_equal(&p->uuid, uuid)) { + dev_dbg(match, "already has uuid: %pUb\n", uuid); + return -EBUSY; + } + + return 0; +} + +static ssize_t uuid_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + uuid_t temp; + ssize_t rc; + + if (len != UUID_STRING_LEN + 1) + return -EINVAL; + + rc = uuid_parse(buf, &temp); + if (rc) + return rc; + + if (uuid_is_null(&temp)) + return -EINVAL; + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + return rc; + + if (uuid_equal(&p->uuid, &temp)) + goto out; + + rc = -EBUSY; + if (p->state >= CXL_CONFIG_ACTIVE) + goto out; + + rc = bus_for_each_dev(&cxl_bus_type, NULL, &temp, is_dup); + if (rc < 0) + goto out; + + uuid_copy(&p->uuid, &temp); +out: + up_write(&cxl_region_rwsem); + + if (rc) + return rc; + return len; +} +static DEVICE_ATTR_RW(uuid); + +static struct cxl_region_ref *cxl_rr_load(struct cxl_port *port, + struct cxl_region *cxlr) +{ + return xa_load(&port->regions, (unsigned long)cxlr); +} + +static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) +{ + struct cxl_region_params *p = &cxlr->params; + int i; + + for (i = count - 1; i >= 0; i--) { + struct cxl_endpoint_decoder *cxled = p->targets[i]; + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_port *iter = cxled_to_port(cxled); + struct cxl_ep *ep; + int rc; + + while (!is_cxl_root(to_cxl_port(iter->dev.parent))) + iter = to_cxl_port(iter->dev.parent); + + for (ep = cxl_ep_load(iter, cxlmd); iter; + iter = ep->next, ep = cxl_ep_load(iter, cxlmd)) { + struct cxl_region_ref *cxl_rr; + struct cxl_decoder *cxld; + + cxl_rr = cxl_rr_load(iter, cxlr); + cxld = cxl_rr->decoder; + rc = cxld->reset(cxld); + if (rc) + return rc; + } + + rc = cxled->cxld.reset(&cxled->cxld); + if (rc) + return rc; + } + + return 0; +} + +static int cxl_region_decode_commit(struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + int i, rc = 0; + + for (i = 0; i < p->nr_targets; i++) { + struct cxl_endpoint_decoder *cxled = p->targets[i]; + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_region_ref *cxl_rr; + struct cxl_decoder *cxld; + struct cxl_port *iter; + struct cxl_ep *ep; + + /* commit bottom up */ + for (iter = cxled_to_port(cxled); !is_cxl_root(iter); + iter = to_cxl_port(iter->dev.parent)) { + cxl_rr = cxl_rr_load(iter, cxlr); + cxld = cxl_rr->decoder; + rc = cxld->commit(cxld); + if (rc) + break; + } + + if (rc) { + /* programming @iter failed, teardown */ + for (ep = cxl_ep_load(iter, cxlmd); ep && iter; + iter = ep->next, ep = cxl_ep_load(iter, cxlmd)) { + cxl_rr = cxl_rr_load(iter, cxlr); + cxld = cxl_rr->decoder; + cxld->reset(cxld); + } + + cxled->cxld.reset(&cxled->cxld); + goto err; + } + } + + return 0; + +err: + /* undo the targets that were successfully committed */ + cxl_region_decode_reset(cxlr, i); + return rc; +} + +static ssize_t commit_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + bool commit; + ssize_t rc; + + rc = kstrtobool(buf, &commit); + if (rc) + return rc; + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + return rc; + + /* Already in the requested state? */ + if (commit && p->state >= CXL_CONFIG_COMMIT) + goto out; + if (!commit && p->state < CXL_CONFIG_COMMIT) + goto out; + + /* Not ready to commit? */ + if (commit && p->state < CXL_CONFIG_ACTIVE) { + rc = -ENXIO; + goto out; + } + + if (commit) + rc = cxl_region_decode_commit(cxlr); + else { + p->state = CXL_CONFIG_RESET_PENDING; + up_write(&cxl_region_rwsem); + device_release_driver(&cxlr->dev); + down_write(&cxl_region_rwsem); + + /* + * The lock was dropped, so need to revalidate that the reset is + * still pending. + */ + if (p->state == CXL_CONFIG_RESET_PENDING) + rc = cxl_region_decode_reset(cxlr, p->interleave_ways); + } + + if (rc) + goto out; + + if (commit) + p->state = CXL_CONFIG_COMMIT; + else if (p->state == CXL_CONFIG_RESET_PENDING) + p->state = CXL_CONFIG_ACTIVE; + +out: + up_write(&cxl_region_rwsem); + + if (rc) + return rc; + return len; +} + +static ssize_t commit_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + rc = sysfs_emit(buf, "%d\n", p->state >= CXL_CONFIG_COMMIT); + up_read(&cxl_region_rwsem); + + return rc; +} +static DEVICE_ATTR_RW(commit); + +static umode_t cxl_region_visible(struct kobject *kobj, struct attribute *a, + int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_region *cxlr = to_cxl_region(dev); + + if (a == &dev_attr_uuid.attr && cxlr->mode != CXL_DECODER_PMEM) + return 0; + return a->mode; +} + +static ssize_t interleave_ways_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + rc = sysfs_emit(buf, "%d\n", p->interleave_ways); + up_read(&cxl_region_rwsem); + + return rc; +} + +static const struct attribute_group *get_cxl_region_target_group(void); + +static ssize_t interleave_ways_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev->parent); + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld; + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + unsigned int val, save; + int rc; + u8 iw; + + rc = kstrtouint(buf, 0, &val); + if (rc) + return rc; + + rc = ways_to_cxl(val, &iw); + if (rc) + return rc; + + /* + * Even for x3, x9, and x12 interleaves the region interleave must be a + * power of 2 multiple of the host bridge interleave. + */ + if (!is_power_of_2(val / cxld->interleave_ways) || + (val % cxld->interleave_ways)) { + dev_dbg(&cxlr->dev, "invalid interleave: %d\n", val); + return -EINVAL; + } + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + return rc; + if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE) { + rc = -EBUSY; + goto out; + } + + save = p->interleave_ways; + p->interleave_ways = val; + rc = sysfs_update_group(&cxlr->dev.kobj, get_cxl_region_target_group()); + if (rc) + p->interleave_ways = save; +out: + up_write(&cxl_region_rwsem); + if (rc) + return rc; + return len; +} +static DEVICE_ATTR_RW(interleave_ways); + +static ssize_t interleave_granularity_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + rc = sysfs_emit(buf, "%d\n", p->interleave_granularity); + up_read(&cxl_region_rwsem); + + return rc; +} + +static ssize_t interleave_granularity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev->parent); + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld; + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + int rc, val; + u16 ig; + + rc = kstrtoint(buf, 0, &val); + if (rc) + return rc; + + rc = granularity_to_cxl(val, &ig); + if (rc) + return rc; + + /* + * When the host-bridge is interleaved, disallow region granularity != + * root granularity. Regions with a granularity less than the root + * interleave result in needing multiple endpoints to support a single + * slot in the interleave (possible to suport in the future). Regions + * with a granularity greater than the root interleave result in invalid + * DPA translations (invalid to support). + */ + if (cxld->interleave_ways > 1 && val != cxld->interleave_granularity) + return -EINVAL; + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + return rc; + if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE) { + rc = -EBUSY; + goto out; + } + + p->interleave_granularity = val; +out: + up_write(&cxl_region_rwsem); + if (rc) + return rc; + return len; +} +static DEVICE_ATTR_RW(interleave_granularity); + +static ssize_t resource_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + u64 resource = -1ULL; + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + if (p->res) + resource = p->res->start; + rc = sysfs_emit(buf, "%#llx\n", resource); + up_read(&cxl_region_rwsem); + + return rc; +} +static DEVICE_ATTR_RO(resource); + +static int alloc_hpa(struct cxl_region *cxlr, resource_size_t size) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent); + struct cxl_region_params *p = &cxlr->params; + struct resource *res; + u32 remainder = 0; + + lockdep_assert_held_write(&cxl_region_rwsem); + + /* Nothing to do... */ + if (p->res && resource_size(p->res) == size) + return 0; + + /* To change size the old size must be freed first */ + if (p->res) + return -EBUSY; + + if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE) + return -EBUSY; + + /* ways, granularity and uuid (if PMEM) need to be set before HPA */ + if (!p->interleave_ways || !p->interleave_granularity || + (cxlr->mode == CXL_DECODER_PMEM && uuid_is_null(&p->uuid))) + return -ENXIO; + + div_u64_rem(size, SZ_256M * p->interleave_ways, &remainder); + if (remainder) + return -EINVAL; + + res = alloc_free_mem_region(cxlrd->res, size, SZ_256M, + dev_name(&cxlr->dev)); + if (IS_ERR(res)) { + dev_dbg(&cxlr->dev, "failed to allocate HPA: %ld\n", + PTR_ERR(res)); + return PTR_ERR(res); + } + + p->res = res; + p->state = CXL_CONFIG_INTERLEAVE_ACTIVE; + + return 0; +} + +static void cxl_region_iomem_release(struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + + if (device_is_registered(&cxlr->dev)) + lockdep_assert_held_write(&cxl_region_rwsem); + if (p->res) { + remove_resource(p->res); + kfree(p->res); + p->res = NULL; + } +} + +static int free_hpa(struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + + lockdep_assert_held_write(&cxl_region_rwsem); + + if (!p->res) + return 0; + + if (p->state >= CXL_CONFIG_ACTIVE) + return -EBUSY; + + cxl_region_iomem_release(cxlr); + p->state = CXL_CONFIG_IDLE; + return 0; +} + +static ssize_t size_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + u64 val; + int rc; + + rc = kstrtou64(buf, 0, &val); + if (rc) + return rc; + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + return rc; + + if (val) + rc = alloc_hpa(cxlr, val); + else + rc = free_hpa(cxlr); + up_write(&cxl_region_rwsem); + + if (rc) + return rc; + + return len; +} + +static ssize_t size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + u64 size = 0; + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + if (p->res) + size = resource_size(p->res); + rc = sysfs_emit(buf, "%#llx\n", size); + up_read(&cxl_region_rwsem); + + return rc; +} +static DEVICE_ATTR_RW(size); + +static struct attribute *cxl_region_attrs[] = { + &dev_attr_uuid.attr, + &dev_attr_commit.attr, + &dev_attr_interleave_ways.attr, + &dev_attr_interleave_granularity.attr, + &dev_attr_resource.attr, + &dev_attr_size.attr, + NULL, +}; + +static const struct attribute_group cxl_region_group = { + .attrs = cxl_region_attrs, + .is_visible = cxl_region_visible, +}; + +static size_t show_targetN(struct cxl_region *cxlr, char *buf, int pos) +{ + struct cxl_region_params *p = &cxlr->params; + struct cxl_endpoint_decoder *cxled; + int rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + + if (pos >= p->interleave_ways) { + dev_dbg(&cxlr->dev, "position %d out of range %d\n", pos, + p->interleave_ways); + rc = -ENXIO; + goto out; + } + + cxled = p->targets[pos]; + if (!cxled) + rc = sysfs_emit(buf, "\n"); + else + rc = sysfs_emit(buf, "%s\n", dev_name(&cxled->cxld.dev)); +out: + up_read(&cxl_region_rwsem); + + return rc; +} + +static int match_free_decoder(struct device *dev, void *data) +{ + struct cxl_decoder *cxld; + int *id = data; + + if (!is_switch_decoder(dev)) + return 0; + + cxld = to_cxl_decoder(dev); + + /* enforce ordered allocation */ + if (cxld->id != *id) + return 0; + + if (!cxld->region) + return 1; + + (*id)++; + + return 0; +} + +static struct cxl_decoder *cxl_region_find_decoder(struct cxl_port *port, + struct cxl_region *cxlr) +{ + struct device *dev; + int id = 0; + + dev = device_find_child(&port->dev, &id, match_free_decoder); + if (!dev) + return NULL; + /* + * This decoder is pinned registered as long as the endpoint decoder is + * registered, and endpoint decoder unregistration holds the + * cxl_region_rwsem over unregister events, so no need to hold on to + * this extra reference. + */ + put_device(dev); + return to_cxl_decoder(dev); +} + +static struct cxl_region_ref *alloc_region_ref(struct cxl_port *port, + struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + struct cxl_region_ref *cxl_rr, *iter; + unsigned long index; + int rc; + + xa_for_each(&port->regions, index, iter) { + struct cxl_region_params *ip = &iter->region->params; + + if (ip->res->start > p->res->start) { + dev_dbg(&cxlr->dev, + "%s: HPA order violation %s:%pr vs %pr\n", + dev_name(&port->dev), + dev_name(&iter->region->dev), ip->res, p->res); + return ERR_PTR(-EBUSY); + } + } + + cxl_rr = kzalloc(sizeof(*cxl_rr), GFP_KERNEL); + if (!cxl_rr) + return ERR_PTR(-ENOMEM); + cxl_rr->port = port; + cxl_rr->region = cxlr; + cxl_rr->nr_targets = 1; + xa_init(&cxl_rr->endpoints); + + rc = xa_insert(&port->regions, (unsigned long)cxlr, cxl_rr, GFP_KERNEL); + if (rc) { + dev_dbg(&cxlr->dev, + "%s: failed to track region reference: %d\n", + dev_name(&port->dev), rc); + kfree(cxl_rr); + return ERR_PTR(rc); + } + + return cxl_rr; +} + +static void free_region_ref(struct cxl_region_ref *cxl_rr) +{ + struct cxl_port *port = cxl_rr->port; + struct cxl_region *cxlr = cxl_rr->region; + struct cxl_decoder *cxld = cxl_rr->decoder; + + dev_WARN_ONCE(&cxlr->dev, cxld->region != cxlr, "region mismatch\n"); + if (cxld->region == cxlr) { + cxld->region = NULL; + put_device(&cxlr->dev); + } + + xa_erase(&port->regions, (unsigned long)cxlr); + xa_destroy(&cxl_rr->endpoints); + kfree(cxl_rr); +} + +static int cxl_rr_ep_add(struct cxl_region_ref *cxl_rr, + struct cxl_endpoint_decoder *cxled) +{ + int rc; + struct cxl_port *port = cxl_rr->port; + struct cxl_region *cxlr = cxl_rr->region; + struct cxl_decoder *cxld = cxl_rr->decoder; + struct cxl_ep *ep = cxl_ep_load(port, cxled_to_memdev(cxled)); + + if (ep) { + rc = xa_insert(&cxl_rr->endpoints, (unsigned long)cxled, ep, + GFP_KERNEL); + if (rc) + return rc; + } + cxl_rr->nr_eps++; + + if (!cxld->region) { + cxld->region = cxlr; + get_device(&cxlr->dev); + } + + return 0; +} + +/** + * cxl_port_attach_region() - track a region's interest in a port by endpoint + * @port: port to add a new region reference 'struct cxl_region_ref' + * @cxlr: region to attach to @port + * @cxled: endpoint decoder used to create or further pin a region reference + * @pos: interleave position of @cxled in @cxlr + * + * The attach event is an opportunity to validate CXL decode setup + * constraints and record metadata needed for programming HDM decoders, + * in particular decoder target lists. + * + * The steps are: + * + * - validate that there are no other regions with a higher HPA already + * associated with @port + * - establish a region reference if one is not already present + * + * - additionally allocate a decoder instance that will host @cxlr on + * @port + * + * - pin the region reference by the endpoint + * - account for how many entries in @port's target list are needed to + * cover all of the added endpoints. + */ +static int cxl_port_attach_region(struct cxl_port *port, + struct cxl_region *cxlr, + struct cxl_endpoint_decoder *cxled, int pos) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_ep *ep = cxl_ep_load(port, cxlmd); + struct cxl_region_ref *cxl_rr; + bool nr_targets_inc = false; + struct cxl_decoder *cxld; + unsigned long index; + int rc = -EBUSY; + + lockdep_assert_held_write(&cxl_region_rwsem); + + cxl_rr = cxl_rr_load(port, cxlr); + if (cxl_rr) { + struct cxl_ep *ep_iter; + int found = 0; + + /* + * Walk the existing endpoints that have been attached to + * @cxlr at @port and see if they share the same 'next' port + * in the downstream direction. I.e. endpoints that share common + * upstream switch. + */ + xa_for_each(&cxl_rr->endpoints, index, ep_iter) { + if (ep_iter == ep) + continue; + if (ep_iter->next == ep->next) { + found++; + break; + } + } + + /* + * New target port, or @port is an endpoint port that always + * accounts its own local decode as a target. + */ + if (!found || !ep->next) { + cxl_rr->nr_targets++; + nr_targets_inc = true; + } + + /* + * The decoder for @cxlr was allocated when the region was first + * attached to @port. + */ + cxld = cxl_rr->decoder; + } else { + cxl_rr = alloc_region_ref(port, cxlr); + if (IS_ERR(cxl_rr)) { + dev_dbg(&cxlr->dev, + "%s: failed to allocate region reference\n", + dev_name(&port->dev)); + return PTR_ERR(cxl_rr); + } + nr_targets_inc = true; + + if (port == cxled_to_port(cxled)) + cxld = &cxled->cxld; + else + cxld = cxl_region_find_decoder(port, cxlr); + if (!cxld) { + dev_dbg(&cxlr->dev, "%s: no decoder available\n", + dev_name(&port->dev)); + goto out_erase; + } + + if (cxld->region) { + dev_dbg(&cxlr->dev, "%s: %s already attached to %s\n", + dev_name(&port->dev), dev_name(&cxld->dev), + dev_name(&cxld->region->dev)); + rc = -EBUSY; + goto out_erase; + } + + cxl_rr->decoder = cxld; + } + + rc = cxl_rr_ep_add(cxl_rr, cxled); + if (rc) { + dev_dbg(&cxlr->dev, + "%s: failed to track endpoint %s:%s reference\n", + dev_name(&port->dev), dev_name(&cxlmd->dev), + dev_name(&cxld->dev)); + goto out_erase; + } + + dev_dbg(&cxlr->dev, + "%s:%s %s add: %s:%s @ %d next: %s nr_eps: %d nr_targets: %d\n", + dev_name(port->uport), dev_name(&port->dev), + dev_name(&cxld->dev), dev_name(&cxlmd->dev), + dev_name(&cxled->cxld.dev), pos, + ep ? ep->next ? dev_name(ep->next->uport) : + dev_name(&cxlmd->dev) : + "none", + cxl_rr->nr_eps, cxl_rr->nr_targets); + + return 0; +out_erase: + if (nr_targets_inc) + cxl_rr->nr_targets--; + if (cxl_rr->nr_eps == 0) + free_region_ref(cxl_rr); + return rc; +} + +static void cxl_port_detach_region(struct cxl_port *port, + struct cxl_region *cxlr, + struct cxl_endpoint_decoder *cxled) +{ + struct cxl_region_ref *cxl_rr; + struct cxl_ep *ep = NULL; + + lockdep_assert_held_write(&cxl_region_rwsem); + + cxl_rr = cxl_rr_load(port, cxlr); + if (!cxl_rr) + return; + + /* + * Endpoint ports do not carry cxl_ep references, and they + * never target more than one endpoint by definition + */ + if (cxl_rr->decoder == &cxled->cxld) + cxl_rr->nr_eps--; + else + ep = xa_erase(&cxl_rr->endpoints, (unsigned long)cxled); + if (ep) { + struct cxl_ep *ep_iter; + unsigned long index; + int found = 0; + + cxl_rr->nr_eps--; + xa_for_each(&cxl_rr->endpoints, index, ep_iter) { + if (ep_iter->next == ep->next) { + found++; + break; + } + } + if (!found) + cxl_rr->nr_targets--; + } + + if (cxl_rr->nr_eps == 0) + free_region_ref(cxl_rr); +} + +static int check_last_peer(struct cxl_endpoint_decoder *cxled, + struct cxl_ep *ep, struct cxl_region_ref *cxl_rr, + int distance) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_region *cxlr = cxl_rr->region; + struct cxl_region_params *p = &cxlr->params; + struct cxl_endpoint_decoder *cxled_peer; + struct cxl_port *port = cxl_rr->port; + struct cxl_memdev *cxlmd_peer; + struct cxl_ep *ep_peer; + int pos = cxled->pos; + + /* + * If this position wants to share a dport with the last endpoint mapped + * then that endpoint, at index 'position - distance', must also be + * mapped by this dport. + */ + if (pos < distance) { + dev_dbg(&cxlr->dev, "%s:%s: cannot host %s:%s at %d\n", + dev_name(port->uport), dev_name(&port->dev), + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); + return -ENXIO; + } + cxled_peer = p->targets[pos - distance]; + cxlmd_peer = cxled_to_memdev(cxled_peer); + ep_peer = cxl_ep_load(port, cxlmd_peer); + if (ep->dport != ep_peer->dport) { + dev_dbg(&cxlr->dev, + "%s:%s: %s:%s pos %d mismatched peer %s:%s\n", + dev_name(port->uport), dev_name(&port->dev), + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos, + dev_name(&cxlmd_peer->dev), + dev_name(&cxled_peer->cxld.dev)); + return -ENXIO; + } + + return 0; +} + +static int cxl_port_setup_targets(struct cxl_port *port, + struct cxl_region *cxlr, + struct cxl_endpoint_decoder *cxled) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent); + int parent_iw, parent_ig, ig, iw, rc, inc = 0, pos = cxled->pos; + struct cxl_port *parent_port = to_cxl_port(port->dev.parent); + struct cxl_region_ref *cxl_rr = cxl_rr_load(port, cxlr); + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_ep *ep = cxl_ep_load(port, cxlmd); + struct cxl_region_params *p = &cxlr->params; + struct cxl_decoder *cxld = cxl_rr->decoder; + struct cxl_switch_decoder *cxlsd; + u16 eig, peig; + u8 eiw, peiw; + + /* + * While root level decoders support x3, x6, x12, switch level + * decoders only support powers of 2 up to x16. + */ + if (!is_power_of_2(cxl_rr->nr_targets)) { + dev_dbg(&cxlr->dev, "%s:%s: invalid target count %d\n", + dev_name(port->uport), dev_name(&port->dev), + cxl_rr->nr_targets); + return -EINVAL; + } + + cxlsd = to_cxl_switch_decoder(&cxld->dev); + if (cxl_rr->nr_targets_set) { + int i, distance; + + distance = p->nr_targets / cxl_rr->nr_targets; + for (i = 0; i < cxl_rr->nr_targets_set; i++) + if (ep->dport == cxlsd->target[i]) { + rc = check_last_peer(cxled, ep, cxl_rr, + distance); + if (rc) + return rc; + goto out_target_set; + } + goto add_target; + } + + if (is_cxl_root(parent_port)) { + parent_ig = cxlrd->cxlsd.cxld.interleave_granularity; + parent_iw = cxlrd->cxlsd.cxld.interleave_ways; + /* + * For purposes of address bit routing, use power-of-2 math for + * switch ports. + */ + if (!is_power_of_2(parent_iw)) + parent_iw /= 3; + } else { + struct cxl_region_ref *parent_rr; + struct cxl_decoder *parent_cxld; + + parent_rr = cxl_rr_load(parent_port, cxlr); + parent_cxld = parent_rr->decoder; + parent_ig = parent_cxld->interleave_granularity; + parent_iw = parent_cxld->interleave_ways; + } + + rc = granularity_to_cxl(parent_ig, &peig); + if (rc) { + dev_dbg(&cxlr->dev, "%s:%s: invalid parent granularity: %d\n", + dev_name(parent_port->uport), + dev_name(&parent_port->dev), parent_ig); + return rc; + } + + rc = ways_to_cxl(parent_iw, &peiw); + if (rc) { + dev_dbg(&cxlr->dev, "%s:%s: invalid parent interleave: %d\n", + dev_name(parent_port->uport), + dev_name(&parent_port->dev), parent_iw); + return rc; + } + + iw = cxl_rr->nr_targets; + rc = ways_to_cxl(iw, &eiw); + if (rc) { + dev_dbg(&cxlr->dev, "%s:%s: invalid port interleave: %d\n", + dev_name(port->uport), dev_name(&port->dev), iw); + return rc; + } + + /* + * If @parent_port is masking address bits, pick the next unused address + * bit to route @port's targets. + */ + if (parent_iw > 1 && cxl_rr->nr_targets > 1) { + u32 address_bit = max(peig + peiw, eiw + peig); + + eig = address_bit - eiw + 1; + } else { + eiw = peiw; + eig = peig; + } + + rc = cxl_to_granularity(eig, &ig); + if (rc) { + dev_dbg(&cxlr->dev, "%s:%s: invalid interleave: %d\n", + dev_name(port->uport), dev_name(&port->dev), + 256 << eig); + return rc; + } + + cxld->interleave_ways = iw; + cxld->interleave_granularity = ig; + cxld->hpa_range = (struct range) { + .start = p->res->start, + .end = p->res->end, + }; + dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport), + dev_name(&port->dev), iw, ig); +add_target: + if (cxl_rr->nr_targets_set == cxl_rr->nr_targets) { + dev_dbg(&cxlr->dev, + "%s:%s: targets full trying to add %s:%s at %d\n", + dev_name(port->uport), dev_name(&port->dev), + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); + return -ENXIO; + } + cxlsd->target[cxl_rr->nr_targets_set] = ep->dport; + inc = 1; +out_target_set: + cxl_rr->nr_targets_set += inc; + dev_dbg(&cxlr->dev, "%s:%s target[%d] = %s for %s:%s @ %d\n", + dev_name(port->uport), dev_name(&port->dev), + cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport), + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); + + return 0; +} + +static void cxl_port_reset_targets(struct cxl_port *port, + struct cxl_region *cxlr) +{ + struct cxl_region_ref *cxl_rr = cxl_rr_load(port, cxlr); + struct cxl_decoder *cxld; + + /* + * After the last endpoint has been detached the entire cxl_rr may now + * be gone. + */ + if (!cxl_rr) + return; + cxl_rr->nr_targets_set = 0; + + cxld = cxl_rr->decoder; + cxld->hpa_range = (struct range) { + .start = 0, + .end = -1, + }; +} + +static void cxl_region_teardown_targets(struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + struct cxl_endpoint_decoder *cxled; + struct cxl_memdev *cxlmd; + struct cxl_port *iter; + struct cxl_ep *ep; + int i; + + for (i = 0; i < p->nr_targets; i++) { + cxled = p->targets[i]; + cxlmd = cxled_to_memdev(cxled); + + iter = cxled_to_port(cxled); + while (!is_cxl_root(to_cxl_port(iter->dev.parent))) + iter = to_cxl_port(iter->dev.parent); + + for (ep = cxl_ep_load(iter, cxlmd); iter; + iter = ep->next, ep = cxl_ep_load(iter, cxlmd)) + cxl_port_reset_targets(iter, cxlr); + } +} + +static int cxl_region_setup_targets(struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + struct cxl_endpoint_decoder *cxled; + struct cxl_memdev *cxlmd; + struct cxl_port *iter; + struct cxl_ep *ep; + int i, rc; + + for (i = 0; i < p->nr_targets; i++) { + cxled = p->targets[i]; + cxlmd = cxled_to_memdev(cxled); + + iter = cxled_to_port(cxled); + while (!is_cxl_root(to_cxl_port(iter->dev.parent))) + iter = to_cxl_port(iter->dev.parent); + + /* + * Descend the topology tree programming targets while + * looking for conflicts. + */ + for (ep = cxl_ep_load(iter, cxlmd); iter; + iter = ep->next, ep = cxl_ep_load(iter, cxlmd)) { + rc = cxl_port_setup_targets(iter, cxlr, cxled); + if (rc) { + cxl_region_teardown_targets(cxlr); + return rc; + } + } + } + + return 0; +} + +static int cxl_region_attach(struct cxl_region *cxlr, + struct cxl_endpoint_decoder *cxled, int pos) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent); + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_port *ep_port, *root_port, *iter; + struct cxl_region_params *p = &cxlr->params; + struct cxl_dport *dport; + int i, rc = -ENXIO; + + if (cxled->mode == CXL_DECODER_DEAD) { + dev_dbg(&cxlr->dev, "%s dead\n", dev_name(&cxled->cxld.dev)); + return -ENODEV; + } + + /* all full of members, or interleave config not established? */ + if (p->state > CXL_CONFIG_INTERLEAVE_ACTIVE) { + dev_dbg(&cxlr->dev, "region already active\n"); + return -EBUSY; + } else if (p->state < CXL_CONFIG_INTERLEAVE_ACTIVE) { + dev_dbg(&cxlr->dev, "interleave config missing\n"); + return -ENXIO; + } + + if (pos < 0 || pos >= p->interleave_ways) { + dev_dbg(&cxlr->dev, "position %d out of range %d\n", pos, + p->interleave_ways); + return -ENXIO; + } + + if (p->targets[pos] == cxled) + return 0; + + if (p->targets[pos]) { + struct cxl_endpoint_decoder *cxled_target = p->targets[pos]; + struct cxl_memdev *cxlmd_target = cxled_to_memdev(cxled_target); + + dev_dbg(&cxlr->dev, "position %d already assigned to %s:%s\n", + pos, dev_name(&cxlmd_target->dev), + dev_name(&cxled_target->cxld.dev)); + return -EBUSY; + } + + for (i = 0; i < p->interleave_ways; i++) { + struct cxl_endpoint_decoder *cxled_target; + struct cxl_memdev *cxlmd_target; + + cxled_target = p->targets[pos]; + if (!cxled_target) + continue; + + cxlmd_target = cxled_to_memdev(cxled_target); + if (cxlmd_target == cxlmd) { + dev_dbg(&cxlr->dev, + "%s already specified at position %d via: %s\n", + dev_name(&cxlmd->dev), pos, + dev_name(&cxled_target->cxld.dev)); + return -EBUSY; + } + } + + ep_port = cxled_to_port(cxled); + root_port = cxlrd_to_port(cxlrd); + dport = cxl_find_dport_by_dev(root_port, ep_port->host_bridge); + if (!dport) { + dev_dbg(&cxlr->dev, "%s:%s invalid target for %s\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), + dev_name(cxlr->dev.parent)); + return -ENXIO; + } + + if (cxlrd->calc_hb(cxlrd, pos) != dport) { + dev_dbg(&cxlr->dev, "%s:%s invalid target position for %s\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), + dev_name(&cxlrd->cxlsd.cxld.dev)); + return -ENXIO; + } + + if (cxled->cxld.target_type != cxlr->type) { + dev_dbg(&cxlr->dev, "%s:%s type mismatch: %d vs %d\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), + cxled->cxld.target_type, cxlr->type); + return -ENXIO; + } + + if (!cxled->dpa_res) { + dev_dbg(&cxlr->dev, "%s:%s: missing DPA allocation.\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev)); + return -ENXIO; + } + + if (resource_size(cxled->dpa_res) * p->interleave_ways != + resource_size(p->res)) { + dev_dbg(&cxlr->dev, + "%s:%s: decoder-size-%#llx * ways-%d != region-size-%#llx\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), + (u64)resource_size(cxled->dpa_res), p->interleave_ways, + (u64)resource_size(p->res)); + return -EINVAL; + } + + for (iter = ep_port; !is_cxl_root(iter); + iter = to_cxl_port(iter->dev.parent)) { + rc = cxl_port_attach_region(iter, cxlr, cxled, pos); + if (rc) + goto err; + } + + p->targets[pos] = cxled; + cxled->pos = pos; + p->nr_targets++; + + if (p->nr_targets == p->interleave_ways) { + rc = cxl_region_setup_targets(cxlr); + if (rc) + goto err_decrement; + p->state = CXL_CONFIG_ACTIVE; + } + + cxled->cxld.interleave_ways = p->interleave_ways; + cxled->cxld.interleave_granularity = p->interleave_granularity; + cxled->cxld.hpa_range = (struct range) { + .start = p->res->start, + .end = p->res->end, + }; + + return 0; + +err_decrement: + p->nr_targets--; +err: + for (iter = ep_port; !is_cxl_root(iter); + iter = to_cxl_port(iter->dev.parent)) + cxl_port_detach_region(iter, cxlr, cxled); + return rc; +} + +static int cxl_region_detach(struct cxl_endpoint_decoder *cxled) +{ + struct cxl_port *iter, *ep_port = cxled_to_port(cxled); + struct cxl_region *cxlr = cxled->cxld.region; + struct cxl_region_params *p; + int rc = 0; + + lockdep_assert_held_write(&cxl_region_rwsem); + + if (!cxlr) + return 0; + + p = &cxlr->params; + get_device(&cxlr->dev); + + if (p->state > CXL_CONFIG_ACTIVE) { + /* + * TODO: tear down all impacted regions if a device is + * removed out of order + */ + rc = cxl_region_decode_reset(cxlr, p->interleave_ways); + if (rc) + goto out; + p->state = CXL_CONFIG_ACTIVE; + } + + for (iter = ep_port; !is_cxl_root(iter); + iter = to_cxl_port(iter->dev.parent)) + cxl_port_detach_region(iter, cxlr, cxled); + + if (cxled->pos < 0 || cxled->pos >= p->interleave_ways || + p->targets[cxled->pos] != cxled) { + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + + dev_WARN_ONCE(&cxlr->dev, 1, "expected %s:%s at position %d\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), + cxled->pos); + goto out; + } + + if (p->state == CXL_CONFIG_ACTIVE) { + p->state = CXL_CONFIG_INTERLEAVE_ACTIVE; + cxl_region_teardown_targets(cxlr); + } + p->targets[cxled->pos] = NULL; + p->nr_targets--; + cxled->cxld.hpa_range = (struct range) { + .start = 0, + .end = -1, + }; + + /* notify the region driver that one of its targets has departed */ + up_write(&cxl_region_rwsem); + device_release_driver(&cxlr->dev); + down_write(&cxl_region_rwsem); +out: + put_device(&cxlr->dev); + return rc; +} + +void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled) +{ + down_write(&cxl_region_rwsem); + cxled->mode = CXL_DECODER_DEAD; + cxl_region_detach(cxled); + up_write(&cxl_region_rwsem); +} + +static int attach_target(struct cxl_region *cxlr, const char *decoder, int pos) +{ + struct device *dev; + int rc; + + dev = bus_find_device_by_name(&cxl_bus_type, NULL, decoder); + if (!dev) + return -ENODEV; + + if (!is_endpoint_decoder(dev)) { + put_device(dev); + return -EINVAL; + } + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + goto out; + down_read(&cxl_dpa_rwsem); + rc = cxl_region_attach(cxlr, to_cxl_endpoint_decoder(dev), pos); + up_read(&cxl_dpa_rwsem); + up_write(&cxl_region_rwsem); +out: + put_device(dev); + return rc; +} + +static int detach_target(struct cxl_region *cxlr, int pos) +{ + struct cxl_region_params *p = &cxlr->params; + int rc; + + rc = down_write_killable(&cxl_region_rwsem); + if (rc) + return rc; + + if (pos >= p->interleave_ways) { + dev_dbg(&cxlr->dev, "position %d out of range %d\n", pos, + p->interleave_ways); + rc = -ENXIO; + goto out; + } + + if (!p->targets[pos]) { + rc = 0; + goto out; + } + + rc = cxl_region_detach(p->targets[pos]); +out: + up_write(&cxl_region_rwsem); + return rc; +} + +static size_t store_targetN(struct cxl_region *cxlr, const char *buf, int pos, + size_t len) +{ + int rc; + + if (sysfs_streq(buf, "\n")) + rc = detach_target(cxlr, pos); + else + rc = attach_target(cxlr, buf, pos); + + if (rc < 0) + return rc; + return len; +} + +#define TARGET_ATTR_RW(n) \ +static ssize_t target##n##_show( \ + struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + return show_targetN(to_cxl_region(dev), buf, (n)); \ +} \ +static ssize_t target##n##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t len) \ +{ \ + return store_targetN(to_cxl_region(dev), buf, (n), len); \ +} \ +static DEVICE_ATTR_RW(target##n) + +TARGET_ATTR_RW(0); +TARGET_ATTR_RW(1); +TARGET_ATTR_RW(2); +TARGET_ATTR_RW(3); +TARGET_ATTR_RW(4); +TARGET_ATTR_RW(5); +TARGET_ATTR_RW(6); +TARGET_ATTR_RW(7); +TARGET_ATTR_RW(8); +TARGET_ATTR_RW(9); +TARGET_ATTR_RW(10); +TARGET_ATTR_RW(11); +TARGET_ATTR_RW(12); +TARGET_ATTR_RW(13); +TARGET_ATTR_RW(14); +TARGET_ATTR_RW(15); + +static struct attribute *target_attrs[] = { + &dev_attr_target0.attr, + &dev_attr_target1.attr, + &dev_attr_target2.attr, + &dev_attr_target3.attr, + &dev_attr_target4.attr, + &dev_attr_target5.attr, + &dev_attr_target6.attr, + &dev_attr_target7.attr, + &dev_attr_target8.attr, + &dev_attr_target9.attr, + &dev_attr_target10.attr, + &dev_attr_target11.attr, + &dev_attr_target12.attr, + &dev_attr_target13.attr, + &dev_attr_target14.attr, + &dev_attr_target15.attr, + NULL, +}; + +static umode_t cxl_region_target_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + + if (n < p->interleave_ways) + return a->mode; + return 0; +} + +static const struct attribute_group cxl_region_target_group = { + .attrs = target_attrs, + .is_visible = cxl_region_target_visible, +}; + +static const struct attribute_group *get_cxl_region_target_group(void) +{ + return &cxl_region_target_group; +} + +static const struct attribute_group *region_groups[] = { + &cxl_base_attribute_group, + &cxl_region_group, + &cxl_region_target_group, + NULL, +}; + +static void cxl_region_release(struct device *dev) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + + memregion_free(cxlr->id); + kfree(cxlr); +} + +const struct device_type cxl_region_type = { + .name = "cxl_region", + .release = cxl_region_release, + .groups = region_groups +}; + +bool is_cxl_region(struct device *dev) +{ + return dev->type == &cxl_region_type; +} +EXPORT_SYMBOL_NS_GPL(is_cxl_region, CXL); + +static struct cxl_region *to_cxl_region(struct device *dev) +{ + if (dev_WARN_ONCE(dev, dev->type != &cxl_region_type, + "not a cxl_region device\n")) + return NULL; + + return container_of(dev, struct cxl_region, dev); +} + +static void unregister_region(void *dev) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + + device_del(dev); + cxl_region_iomem_release(cxlr); + put_device(dev); +} + +static struct lock_class_key cxl_region_key; + +static struct cxl_region *cxl_region_alloc(struct cxl_root_decoder *cxlrd, int id) +{ + struct cxl_region *cxlr; + struct device *dev; + + cxlr = kzalloc(sizeof(*cxlr), GFP_KERNEL); + if (!cxlr) { + memregion_free(id); + return ERR_PTR(-ENOMEM); + } + + dev = &cxlr->dev; + device_initialize(dev); + lockdep_set_class(&dev->mutex, &cxl_region_key); + dev->parent = &cxlrd->cxlsd.cxld.dev; + device_set_pm_not_required(dev); + dev->bus = &cxl_bus_type; + dev->type = &cxl_region_type; + cxlr->id = id; + + return cxlr; +} + +/** + * devm_cxl_add_region - Adds a region to a decoder + * @cxlrd: root decoder + * @id: memregion id to create, or memregion_free() on failure + * @mode: mode for the endpoint decoders of this region + * @type: select whether this is an expander or accelerator (type-2 or type-3) + * + * This is the second step of region initialization. Regions exist within an + * address space which is mapped by a @cxlrd. + * + * Return: 0 if the region was added to the @cxlrd, else returns negative error + * code. The region will be named "regionZ" where Z is the unique region number. + */ +static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, + int id, + enum cxl_decoder_mode mode, + enum cxl_decoder_type type) +{ + struct cxl_port *port = to_cxl_port(cxlrd->cxlsd.cxld.dev.parent); + struct cxl_region *cxlr; + struct device *dev; + int rc; + + cxlr = cxl_region_alloc(cxlrd, id); + if (IS_ERR(cxlr)) + return cxlr; + cxlr->mode = mode; + cxlr->type = type; + + dev = &cxlr->dev; + rc = dev_set_name(dev, "region%d", id); + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + rc = devm_add_action_or_reset(port->uport, unregister_region, cxlr); + if (rc) + return ERR_PTR(rc); + + dev_dbg(port->uport, "%s: created %s\n", + dev_name(&cxlrd->cxlsd.cxld.dev), dev_name(dev)); + return cxlr; + +err: + put_device(dev); + return ERR_PTR(rc); +} + +static ssize_t create_pmem_region_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); + + return sysfs_emit(buf, "region%u\n", atomic_read(&cxlrd->region_id)); +} + +static ssize_t create_pmem_region_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); + struct cxl_region *cxlr; + int id, rc; + + rc = sscanf(buf, "region%d\n", &id); + if (rc != 1) + return -EINVAL; + + rc = memregion_alloc(GFP_KERNEL); + if (rc < 0) + return rc; + + if (atomic_cmpxchg(&cxlrd->region_id, id, rc) != id) { + memregion_free(rc); + return -EBUSY; + } + + cxlr = devm_cxl_add_region(cxlrd, id, CXL_DECODER_PMEM, + CXL_DECODER_EXPANDER); + if (IS_ERR(cxlr)) + return PTR_ERR(cxlr); + + return len; +} +DEVICE_ATTR_RW(create_pmem_region); + +static ssize_t region_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + ssize_t rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) + return rc; + + if (cxld->region) + rc = sysfs_emit(buf, "%s\n", dev_name(&cxld->region->dev)); + else + rc = sysfs_emit(buf, "\n"); + up_read(&cxl_region_rwsem); + + return rc; +} +DEVICE_ATTR_RO(region); + +static struct cxl_region * +cxl_find_region_by_name(struct cxl_root_decoder *cxlrd, const char *name) +{ + struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld; + struct device *region_dev; + + region_dev = device_find_child_by_name(&cxld->dev, name); + if (!region_dev) + return ERR_PTR(-ENODEV); + + return to_cxl_region(region_dev); +} + +static ssize_t delete_region_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); + struct cxl_port *port = to_cxl_port(dev->parent); + struct cxl_region *cxlr; + + cxlr = cxl_find_region_by_name(cxlrd, buf); + if (IS_ERR(cxlr)) + return PTR_ERR(cxlr); + + devm_release_action(port->uport, unregister_region, cxlr); + put_device(&cxlr->dev); + + return len; +} +DEVICE_ATTR_WO(delete_region); + +static void cxl_pmem_region_release(struct device *dev) +{ + struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev); + int i; + + for (i = 0; i < cxlr_pmem->nr_mappings; i++) { + struct cxl_memdev *cxlmd = cxlr_pmem->mapping[i].cxlmd; + + put_device(&cxlmd->dev); + } + + kfree(cxlr_pmem); +} + +static const struct attribute_group *cxl_pmem_region_attribute_groups[] = { + &cxl_base_attribute_group, + NULL, +}; + +const struct device_type cxl_pmem_region_type = { + .name = "cxl_pmem_region", + .release = cxl_pmem_region_release, + .groups = cxl_pmem_region_attribute_groups, +}; + +bool is_cxl_pmem_region(struct device *dev) +{ + return dev->type == &cxl_pmem_region_type; +} +EXPORT_SYMBOL_NS_GPL(is_cxl_pmem_region, CXL); + +struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev) +{ + if (dev_WARN_ONCE(dev, !is_cxl_pmem_region(dev), + "not a cxl_pmem_region device\n")) + return NULL; + return container_of(dev, struct cxl_pmem_region, dev); +} +EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, CXL); + +static struct lock_class_key cxl_pmem_region_key; + +static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr) +{ + struct cxl_region_params *p = &cxlr->params; + struct cxl_pmem_region *cxlr_pmem; + struct device *dev; + int i; + + down_read(&cxl_region_rwsem); + if (p->state != CXL_CONFIG_COMMIT) { + cxlr_pmem = ERR_PTR(-ENXIO); + goto out; + } + + cxlr_pmem = kzalloc(struct_size(cxlr_pmem, mapping, p->nr_targets), + GFP_KERNEL); + if (!cxlr_pmem) { + cxlr_pmem = ERR_PTR(-ENOMEM); + goto out; + } + + cxlr_pmem->hpa_range.start = p->res->start; + cxlr_pmem->hpa_range.end = p->res->end; + + /* Snapshot the region configuration underneath the cxl_region_rwsem */ + cxlr_pmem->nr_mappings = p->nr_targets; + for (i = 0; i < p->nr_targets; i++) { + struct cxl_endpoint_decoder *cxled = p->targets[i]; + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i]; + + m->cxlmd = cxlmd; + get_device(&cxlmd->dev); + m->start = cxled->dpa_res->start; + m->size = resource_size(cxled->dpa_res); + m->position = i; + } + + dev = &cxlr_pmem->dev; + cxlr_pmem->cxlr = cxlr; + device_initialize(dev); + lockdep_set_class(&dev->mutex, &cxl_pmem_region_key); + device_set_pm_not_required(dev); + dev->parent = &cxlr->dev; + dev->bus = &cxl_bus_type; + dev->type = &cxl_pmem_region_type; +out: + up_read(&cxl_region_rwsem); + + return cxlr_pmem; +} + +static void cxlr_pmem_unregister(void *dev) +{ + device_unregister(dev); +} + +/** + * devm_cxl_add_pmem_region() - add a cxl_region-to-nd_region bridge + * @cxlr: parent CXL region for this pmem region bridge device + * + * Return: 0 on success negative error code on failure. + */ +static int devm_cxl_add_pmem_region(struct cxl_region *cxlr) +{ + struct cxl_pmem_region *cxlr_pmem; + struct device *dev; + int rc; + + cxlr_pmem = cxl_pmem_region_alloc(cxlr); + if (IS_ERR(cxlr_pmem)) + return PTR_ERR(cxlr_pmem); + + dev = &cxlr_pmem->dev; + rc = dev_set_name(dev, "pmem_region%d", cxlr->id); + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + dev_dbg(&cxlr->dev, "%s: register %s\n", dev_name(dev->parent), + dev_name(dev)); + + return devm_add_action_or_reset(&cxlr->dev, cxlr_pmem_unregister, dev); + +err: + put_device(dev); + return rc; +} + +static int cxl_region_probe(struct device *dev) +{ + struct cxl_region *cxlr = to_cxl_region(dev); + struct cxl_region_params *p = &cxlr->params; + int rc; + + rc = down_read_interruptible(&cxl_region_rwsem); + if (rc) { + dev_dbg(&cxlr->dev, "probe interrupted\n"); + return rc; + } + + if (p->state < CXL_CONFIG_COMMIT) { + dev_dbg(&cxlr->dev, "config state: %d\n", p->state); + rc = -ENXIO; + } + + /* + * From this point on any path that changes the region's state away from + * CXL_CONFIG_COMMIT is also responsible for releasing the driver. + */ + up_read(&cxl_region_rwsem); + + switch (cxlr->mode) { + case CXL_DECODER_PMEM: + return devm_cxl_add_pmem_region(cxlr); + default: + dev_dbg(&cxlr->dev, "unsupported region mode: %d\n", + cxlr->mode); + return -ENXIO; + } +} + +static struct cxl_driver cxl_region_driver = { + .name = "cxl_region", + .probe = cxl_region_probe, + .id = CXL_DEVICE_REGION, +}; + +int cxl_region_init(void) +{ + return cxl_driver_register(&cxl_region_driver); +} + +void cxl_region_exit(void) +{ + cxl_driver_unregister(&cxl_region_driver); +} + +MODULE_IMPORT_NS(CXL); +MODULE_ALIAS_CXL(CXL_DEVICE_REGION); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 6799b27c7db2..f680450f0b16 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -7,6 +7,7 @@ #include <linux/libnvdimm.h> #include <linux/bitfield.h> #include <linux/bitops.h> +#include <linux/log2.h> #include <linux/io.h> /** @@ -53,9 +54,12 @@ #define CXL_HDM_DECODER0_CTRL_LOCK BIT(8) #define CXL_HDM_DECODER0_CTRL_COMMIT BIT(9) #define CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10) +#define CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11) #define CXL_HDM_DECODER0_CTRL_TYPE BIT(12) #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24) #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28) +#define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i) +#define CXL_HDM_DECODER0_SKIP_HIGH(i) CXL_HDM_DECODER0_TL_HIGH(i) static inline int cxl_hdm_decoder_count(u32 cap_hdr) { @@ -64,6 +68,57 @@ static inline int cxl_hdm_decoder_count(u32 cap_hdr) return val ? val * 2 : 1; } +/* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */ +static inline int cxl_to_granularity(u16 ig, unsigned int *val) +{ + if (ig > 6) + return -EINVAL; + *val = 256 << ig; + return 0; +} + +/* Encode defined in CXL ECN "3, 6, 12 and 16-way memory Interleaving" */ +static inline int cxl_to_ways(u8 eniw, unsigned int *val) +{ + switch (eniw) { + case 0 ... 4: + *val = 1 << eniw; + break; + case 8 ... 10: + *val = 3 << (eniw - 8); + break; + default: + return -EINVAL; + } + + return 0; +} + +static inline int granularity_to_cxl(int g, u16 *ig) +{ + if (g > SZ_16K || g < 256 || !is_power_of_2(g)) + return -EINVAL; + *ig = ilog2(g) - 8; + return 0; +} + +static inline int ways_to_cxl(unsigned int ways, u8 *iw) +{ + if (ways > 16) + return -EINVAL; + if (is_power_of_2(ways)) { + *iw = ilog2(ways); + return 0; + } + if (ways % 3) + return -EINVAL; + ways /= 3; + if (!is_power_of_2(ways)) + return -EINVAL; + *iw = ilog2(ways) + 8; + return 0; +} + /* CXL 2.0 8.2.8.1 Device Capabilities Array Register */ #define CXLDEV_CAP_ARRAY_OFFSET 0x0 #define CXLDEV_CAP_ARRAY_CAP_ID 0 @@ -193,31 +248,77 @@ enum cxl_decoder_type { */ #define CXL_DECODER_MAX_INTERLEAVE 16 +#define CXL_DECODER_MIN_GRANULARITY 256 + /** - * struct cxl_decoder - CXL address range decode configuration + * struct cxl_decoder - Common CXL HDM Decoder Attributes * @dev: this decoder's device * @id: kernel device name id - * @platform_res: address space resources considered by root decoder - * @decoder_range: address space resources considered by midlevel decoder + * @hpa_range: Host physical address range mapped by this decoder * @interleave_ways: number of cxl_dports in this decode * @interleave_granularity: data stride per dport * @target_type: accelerator vs expander (type2 vs type3) selector + * @region: currently assigned region for this decoder * @flags: memory type capabilities and locking - * @target_lock: coordinate coherent reads of the target list - * @nr_targets: number of elements in @target - * @target: active ordered target list in current decoder configuration - */ + * @commit: device/decoder-type specific callback to commit settings to hw + * @reset: device/decoder-type specific callback to reset hw settings +*/ struct cxl_decoder { struct device dev; int id; - union { - struct resource platform_res; - struct range decoder_range; - }; + struct range hpa_range; int interleave_ways; int interleave_granularity; enum cxl_decoder_type target_type; + struct cxl_region *region; unsigned long flags; + int (*commit)(struct cxl_decoder *cxld); + int (*reset)(struct cxl_decoder *cxld); +}; + +/* + * CXL_DECODER_DEAD prevents endpoints from being reattached to regions + * while cxld_unregister() is running + */ +enum cxl_decoder_mode { + CXL_DECODER_NONE, + CXL_DECODER_RAM, + CXL_DECODER_PMEM, + CXL_DECODER_MIXED, + CXL_DECODER_DEAD, +}; + +/** + * struct cxl_endpoint_decoder - Endpoint / SPA to DPA decoder + * @cxld: base cxl_decoder_object + * @dpa_res: actively claimed DPA span of this decoder + * @skip: offset into @dpa_res where @cxld.hpa_range maps + * @mode: which memory type / access-mode-partition this decoder targets + * @pos: interleave position in @cxld.region + */ +struct cxl_endpoint_decoder { + struct cxl_decoder cxld; + struct resource *dpa_res; + resource_size_t skip; + enum cxl_decoder_mode mode; + int pos; +}; + +/** + * struct cxl_switch_decoder - Switch specific CXL HDM Decoder + * @cxld: base cxl_decoder object + * @target_lock: coordinate coherent reads of the target list + * @nr_targets: number of elements in @target + * @target: active ordered target list in current decoder configuration + * + * The 'switch' decoder type represents the decoder instances of cxl_port's that + * route from the root of a CXL memory decode topology to the endpoints. They + * come in two flavors, root-level decoders, statically defined by platform + * firmware, and mid-level decoders, where interleave-granularity, + * interleave-width, and the target list are mutable. + */ +struct cxl_switch_decoder { + struct cxl_decoder cxld; seqlock_t target_lock; int nr_targets; struct cxl_dport *target[]; @@ -225,6 +326,76 @@ struct cxl_decoder { /** + * struct cxl_root_decoder - Static platform CXL address decoder + * @res: host / parent resource for region allocations + * @region_id: region id for next region provisioning event + * @calc_hb: which host bridge covers the n'th position by granularity + * @cxlsd: base cxl switch decoder + */ +struct cxl_root_decoder { + struct resource *res; + atomic_t region_id; + struct cxl_dport *(*calc_hb)(struct cxl_root_decoder *cxlrd, int pos); + struct cxl_switch_decoder cxlsd; +}; + +/* + * enum cxl_config_state - State machine for region configuration + * @CXL_CONFIG_IDLE: Any sysfs attribute can be written freely + * @CXL_CONFIG_INTERLEAVE_ACTIVE: region size has been set, no more + * changes to interleave_ways or interleave_granularity + * @CXL_CONFIG_ACTIVE: All targets have been added the region is now + * active + * @CXL_CONFIG_RESET_PENDING: see commit_store() + * @CXL_CONFIG_COMMIT: Soft-config has been committed to hardware + */ +enum cxl_config_state { + CXL_CONFIG_IDLE, + CXL_CONFIG_INTERLEAVE_ACTIVE, + CXL_CONFIG_ACTIVE, + CXL_CONFIG_RESET_PENDING, + CXL_CONFIG_COMMIT, +}; + +/** + * struct cxl_region_params - region settings + * @state: allow the driver to lockdown further parameter changes + * @uuid: unique id for persistent regions + * @interleave_ways: number of endpoints in the region + * @interleave_granularity: capacity each endpoint contributes to a stripe + * @res: allocated iomem capacity for this region + * @targets: active ordered targets in current decoder configuration + * @nr_targets: number of targets + * + * State transitions are protected by the cxl_region_rwsem + */ +struct cxl_region_params { + enum cxl_config_state state; + uuid_t uuid; + int interleave_ways; + int interleave_granularity; + struct resource *res; + struct cxl_endpoint_decoder *targets[CXL_DECODER_MAX_INTERLEAVE]; + int nr_targets; +}; + +/** + * struct cxl_region - CXL region + * @dev: This region's device + * @id: This region's id. Id is globally unique across all regions + * @mode: Endpoint decoder allocation / access mode + * @type: Endpoint decoder target type + * @params: active + config params for the region + */ +struct cxl_region { + struct device dev; + int id; + enum cxl_decoder_mode mode; + enum cxl_decoder_type type; + struct cxl_region_params params; +}; + +/** * enum cxl_nvdimm_brige_state - state machine for managing bus rescans * @CXL_NVB_NEW: Set at bridge create and after cxl_pmem_wq is destroyed * @CXL_NVB_DEAD: Set at brige unregistration to preclude async probing @@ -251,7 +422,26 @@ struct cxl_nvdimm_bridge { struct cxl_nvdimm { struct device dev; struct cxl_memdev *cxlmd; - struct nvdimm *nvdimm; + struct cxl_nvdimm_bridge *bridge; + struct cxl_pmem_region *region; +}; + +struct cxl_pmem_region_mapping { + struct cxl_memdev *cxlmd; + struct cxl_nvdimm *cxl_nvd; + u64 start; + u64 size; + int position; +}; + +struct cxl_pmem_region { + struct device dev; + struct cxl_region *cxlr; + struct nd_region *nd_region; + struct cxl_nvdimm_bridge *bridge; + struct range hpa_range; + int nr_mappings; + struct cxl_pmem_region_mapping mapping[]; }; /** @@ -260,50 +450,94 @@ struct cxl_nvdimm { * decode hierarchy. * @dev: this port's device * @uport: PCI or platform device implementing the upstream port capability + * @host_bridge: Shortcut to the platform attach point for this port * @id: id for port device-name * @dports: cxl_dport instances referenced by decoders * @endpoints: cxl_ep instances, endpoints that are a descendant of this port + * @regions: cxl_region_ref instances, regions mapped by this port + * @parent_dport: dport that points to this port in the parent * @decoder_ida: allocator for decoder ids + * @hdm_end: track last allocated HDM decoder instance for allocation ordering + * @commit_end: cursor to track highest committed decoder for commit ordering * @component_reg_phys: component register capability base address (optional) * @dead: last ep has been removed, force port re-creation * @depth: How deep this port is relative to the root. depth 0 is the root. + * @cdat: Cached CDAT data + * @cdat_available: Should a CDAT attribute be available in sysfs */ struct cxl_port { struct device dev; struct device *uport; + struct device *host_bridge; int id; - struct list_head dports; - struct list_head endpoints; + struct xarray dports; + struct xarray endpoints; + struct xarray regions; + struct cxl_dport *parent_dport; struct ida decoder_ida; + int hdm_end; + int commit_end; resource_size_t component_reg_phys; bool dead; unsigned int depth; + struct cxl_cdat { + void *table; + size_t length; + } cdat; + bool cdat_available; }; +static inline struct cxl_dport * +cxl_find_dport_by_dev(struct cxl_port *port, const struct device *dport_dev) +{ + return xa_load(&port->dports, (unsigned long)dport_dev); +} + /** * struct cxl_dport - CXL downstream port * @dport: PCI bridge or firmware device representing the downstream link * @port_id: unique hardware identifier for dport in decoder target list * @component_reg_phys: downstream port component registers * @port: reference to cxl_port that contains this downstream port - * @list: node for a cxl_port's list of cxl_dport instances */ struct cxl_dport { struct device *dport; int port_id; resource_size_t component_reg_phys; struct cxl_port *port; - struct list_head list; }; /** * struct cxl_ep - track an endpoint's interest in a port * @ep: device that hosts a generic CXL endpoint (expander or accelerator) - * @list: node on port->endpoints list + * @dport: which dport routes to this endpoint on @port + * @next: cxl switch port across the link attached to @dport NULL if + * attached to an endpoint */ struct cxl_ep { struct device *ep; - struct list_head list; + struct cxl_dport *dport; + struct cxl_port *next; +}; + +/** + * struct cxl_region_ref - track a region's interest in a port + * @port: point in topology to install this reference + * @decoder: decoder assigned for @region in @port + * @region: region for this reference + * @endpoints: cxl_ep references for region members beneath @port + * @nr_targets_set: track how many targets have been programmed during setup + * @nr_eps: number of endpoints beneath @port + * @nr_targets: number of distinct targets needed to reach @nr_eps + */ +struct cxl_region_ref { + struct cxl_port *port; + struct cxl_decoder *decoder; + struct cxl_region *region; + struct xarray endpoints; + int nr_targets_set; + int nr_eps; + int nr_targets; }; /* @@ -325,29 +559,31 @@ int devm_cxl_register_pci_bus(struct device *host, struct device *uport, struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port); struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, resource_size_t component_reg_phys, - struct cxl_port *parent_port); + struct cxl_dport *parent_dport); +int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd, + struct cxl_dport *parent_dport); struct cxl_port *find_cxl_root(struct device *dev); int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd); int cxl_bus_rescan(void); -struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd); +struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, + struct cxl_dport **dport); bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd); struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, struct device *dport, int port_id, resource_size_t component_reg_phys); -struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port, - const struct device *dev); struct cxl_decoder *to_cxl_decoder(struct device *dev); +struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev); +struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev); bool is_root_decoder(struct device *dev); bool is_endpoint_decoder(struct device *dev); -bool is_cxl_decoder(struct device *dev); -struct cxl_decoder *cxl_root_decoder_alloc(struct cxl_port *port, - unsigned int nr_targets); -struct cxl_decoder *cxl_switch_decoder_alloc(struct cxl_port *port, - unsigned int nr_targets); +struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port, + unsigned int nr_targets); +struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port, + unsigned int nr_targets); int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map); -struct cxl_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port); +struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port); int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map); int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld); int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint); @@ -357,6 +593,8 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port); int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm); int devm_cxl_add_passthrough_decoder(struct cxl_port *port); +bool is_cxl_region(struct device *dev); + extern struct bus_type cxl_bus_type; struct cxl_driver { @@ -385,6 +623,8 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv); #define CXL_DEVICE_PORT 3 #define CXL_DEVICE_ROOT 4 #define CXL_DEVICE_MEMORY_EXPANDER 5 +#define CXL_DEVICE_REGION 6 +#define CXL_DEVICE_PMEM_REGION 7 #define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*") #define CXL_MODALIAS_FMT "cxl:t%d" @@ -396,7 +636,21 @@ struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev); bool is_cxl_nvdimm(struct device *dev); bool is_cxl_nvdimm_bridge(struct device *dev); int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd); -struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_nvdimm *cxl_nvd); +struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct device *dev); + +#ifdef CONFIG_CXL_REGION +bool is_cxl_pmem_region(struct device *dev); +struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev); +#else +static inline bool is_cxl_pmem_region(struct device *dev) +{ + return false; +} +static inline struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev) +{ + return NULL; +} +#endif /* * Unit test builds overrides this to __weak, find the 'strong' version diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 7df0b053373a..88e3a8e54b6a 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -50,6 +50,24 @@ static inline struct cxl_memdev *to_cxl_memdev(struct device *dev) return container_of(dev, struct cxl_memdev, dev); } +static inline struct cxl_port *cxled_to_port(struct cxl_endpoint_decoder *cxled) +{ + return to_cxl_port(cxled->cxld.dev.parent); +} + +static inline struct cxl_port *cxlrd_to_port(struct cxl_root_decoder *cxlrd) +{ + return to_cxl_port(cxlrd->cxlsd.cxld.dev.parent); +} + +static inline struct cxl_memdev * +cxled_to_memdev(struct cxl_endpoint_decoder *cxled) +{ + struct cxl_port *port = to_cxl_port(cxled->cxld.dev.parent); + + return to_cxl_memdev(port->uport); +} + bool is_cxl_memdev(struct device *dev); static inline bool is_cxl_endpoint(struct cxl_port *port) { @@ -178,8 +196,9 @@ struct cxl_endpoint_dvsec_info { * @firmware_version: Firmware version for the memory device. * @enabled_cmds: Hardware commands found enabled in CEL. * @exclusive_cmds: Commands that are kernel-internal only - * @pmem_range: Active Persistent memory capacity configuration - * @ram_range: Active Volatile memory capacity configuration + * @dpa_res: Overall DPA resource tree for the device + * @pmem_res: Active Persistent memory capacity configuration + * @ram_res: Active Volatile memory capacity configuration * @total_bytes: sum of all possible capacities * @volatile_only_bytes: hard volatile capacity * @persistent_only_bytes: hard persistent capacity @@ -191,6 +210,7 @@ struct cxl_endpoint_dvsec_info { * @component_reg_phys: register base of component registers * @info: Cached DVSEC information about the device. * @serial: PCIe Device Serial Number + * @doe_mbs: PCI DOE mailbox array * @mbox_send: @dev specific transport for transmitting mailbox commands * * See section 8.2.9.5.2 Capacity Configuration and Label Storage for @@ -209,8 +229,9 @@ struct cxl_dev_state { DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX); DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); - struct range pmem_range; - struct range ram_range; + struct resource dpa_res; + struct resource pmem_res; + struct resource ram_res; u64 total_bytes; u64 volatile_only_bytes; u64 persistent_only_bytes; @@ -224,6 +245,8 @@ struct cxl_dev_state { resource_size_t component_reg_phys; u64 serial; + struct xarray doe_mbs; + int (*mbox_send)(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd); }; @@ -299,6 +322,13 @@ struct cxl_mbox_identify { u8 qos_telemetry_caps; } __packed; +struct cxl_mbox_get_partition_info { + __le64 active_volatile_cap; + __le64 active_persistent_cap; + __le64 next_volatile_cap; + __le64 next_persistent_cap; +} __packed; + struct cxl_mbox_get_lsa { __le32 offset; __le32 length; @@ -370,4 +400,8 @@ struct cxl_hdm { unsigned int interleave_mask; struct cxl_port *port; }; + +struct seq_file; +struct dentry *cxl_debugfs_create_dir(const char *dir); +void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds); #endif /* __CXL_MEM_H__ */ diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index fce1c11729c2..eec597dbe763 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h @@ -74,4 +74,5 @@ static inline resource_size_t cxl_regmap_to_base(struct pci_dev *pdev, int devm_cxl_port_enumerate_dports(struct cxl_port *port); struct cxl_dev_state; int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm); +void read_cdat_data(struct cxl_port *port); #endif /* __CXL_PCI_H__ */ diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index a979d0b484d5..64ccf053d32c 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2022 Intel Corporation. All rights reserved. */ +#include <linux/debugfs.h> #include <linux/device.h> #include <linux/module.h> #include <linux/pci.h> @@ -24,42 +25,32 @@ * in higher level operations. */ -static int create_endpoint(struct cxl_memdev *cxlmd, - struct cxl_port *parent_port) +static void enable_suspend(void *data) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; - struct cxl_port *endpoint; - int rc; + cxl_mem_active_dec(); +} - endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev, - cxlds->component_reg_phys, parent_port); - if (IS_ERR(endpoint)) - return PTR_ERR(endpoint); +static void remove_debugfs(void *dentry) +{ + debugfs_remove_recursive(dentry); +} - dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev)); +static int cxl_mem_dpa_show(struct seq_file *file, void *data) +{ + struct device *dev = file->private; + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); - rc = cxl_endpoint_autoremove(cxlmd, endpoint); - if (rc) - return rc; - - if (!endpoint->dev.driver) { - dev_err(&cxlmd->dev, "%s failed probe\n", - dev_name(&endpoint->dev)); - return -ENXIO; - } + cxl_dpa_debug(file, cxlmd->cxlds); return 0; } -static void enable_suspend(void *data) -{ - cxl_mem_active_dec(); -} - static int cxl_mem_probe(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_port *parent_port; + struct cxl_dport *dport; + struct dentry *dentry; int rc; /* @@ -73,11 +64,17 @@ static int cxl_mem_probe(struct device *dev) if (work_pending(&cxlmd->detach_work)) return -EBUSY; + dentry = cxl_debugfs_create_dir(dev_name(dev)); + debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show); + rc = devm_add_action_or_reset(dev, remove_debugfs, dentry); + if (rc) + return rc; + rc = devm_cxl_enumerate_ports(cxlmd); if (rc) return rc; - parent_port = cxl_mem_find_port(cxlmd); + parent_port = cxl_mem_find_port(cxlmd, &dport); if (!parent_port) { dev_err(dev, "CXL port topology not found\n"); return -ENXIO; @@ -91,7 +88,7 @@ static int cxl_mem_probe(struct device *dev) goto unlock; } - rc = create_endpoint(cxlmd, parent_port); + rc = devm_cxl_add_endpoint(cxlmd, dport); unlock: device_unlock(&parent_port->dev); put_device(&parent_port->dev); diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 5a0ae46d4989..faeb5d9d7a7a 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -8,6 +8,7 @@ #include <linux/mutex.h> #include <linux/list.h> #include <linux/pci.h> +#include <linux/pci-doe.h> #include <linux/io.h> #include "cxlmem.h" #include "cxlpci.h" @@ -386,6 +387,47 @@ static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, return rc; } +static void cxl_pci_destroy_doe(void *mbs) +{ + xa_destroy(mbs); +} + +static void devm_cxl_pci_create_doe(struct cxl_dev_state *cxlds) +{ + struct device *dev = cxlds->dev; + struct pci_dev *pdev = to_pci_dev(dev); + u16 off = 0; + + xa_init(&cxlds->doe_mbs); + if (devm_add_action(&pdev->dev, cxl_pci_destroy_doe, &cxlds->doe_mbs)) { + dev_err(dev, "Failed to create XArray for DOE's\n"); + return; + } + + /* + * Mailbox creation is best effort. Higher layers must determine if + * the lack of a mailbox for their protocol is a device failure or not. + */ + pci_doe_for_each_off(pdev, off) { + struct pci_doe_mb *doe_mb; + + doe_mb = pcim_doe_create_mb(pdev, off); + if (IS_ERR(doe_mb)) { + dev_err(dev, "Failed to create MB object for MB @ %x\n", + off); + continue; + } + + if (xa_insert(&cxlds->doe_mbs, off, doe_mb, GFP_KERNEL)) { + dev_err(dev, "xa_insert failed to insert MB @ %x\n", + off); + continue; + } + + dev_dbg(dev, "Created DOE mailbox @%x\n", off); + } +} + static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct cxl_register_map map; @@ -434,6 +476,8 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) cxlds->component_reg_phys = cxl_regmap_to_base(pdev, &map); + devm_cxl_pci_create_doe(cxlds); + rc = cxl_pci_setup_mailbox(cxlds); if (rc) return rc; @@ -454,7 +498,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); - if (range_len(&cxlds->pmem_range) && IS_ENABLED(CONFIG_CXL_PMEM)) + if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) rc = devm_cxl_add_nvdimm(&pdev->dev, cxlmd); return rc; diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 0aaa70b4e0f7..7dc0a2fa1a6b 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -7,6 +7,7 @@ #include <linux/ndctl.h> #include <linux/async.h> #include <linux/slab.h> +#include <linux/nd.h> #include "cxlmem.h" #include "cxl.h" @@ -26,7 +27,23 @@ static void clear_exclusive(void *cxlds) static void unregister_nvdimm(void *nvdimm) { + struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); + struct cxl_nvdimm_bridge *cxl_nvb = cxl_nvd->bridge; + struct cxl_pmem_region *cxlr_pmem; + + device_lock(&cxl_nvb->dev); + cxlr_pmem = cxl_nvd->region; + dev_set_drvdata(&cxl_nvd->dev, NULL); + cxl_nvd->region = NULL; + device_unlock(&cxl_nvb->dev); + + if (cxlr_pmem) { + device_release_driver(&cxlr_pmem->dev); + put_device(&cxlr_pmem->dev); + } + nvdimm_delete(nvdimm); + cxl_nvd->bridge = NULL; } static int cxl_nvdimm_probe(struct device *dev) @@ -39,7 +56,7 @@ static int cxl_nvdimm_probe(struct device *dev) struct nvdimm *nvdimm; int rc; - cxl_nvb = cxl_find_nvdimm_bridge(cxl_nvd); + cxl_nvb = cxl_find_nvdimm_bridge(dev); if (!cxl_nvb) return -ENXIO; @@ -66,6 +83,7 @@ static int cxl_nvdimm_probe(struct device *dev) } dev_set_drvdata(dev, nvdimm); + cxl_nvd->bridge = cxl_nvb; rc = devm_add_action_or_reset(dev, unregister_nvdimm, nvdimm); out: device_unlock(&cxl_nvb->dev); @@ -204,15 +222,38 @@ static bool online_nvdimm_bus(struct cxl_nvdimm_bridge *cxl_nvb) return cxl_nvb->nvdimm_bus != NULL; } -static int cxl_nvdimm_release_driver(struct device *dev, void *data) +static int cxl_nvdimm_release_driver(struct device *dev, void *cxl_nvb) { + struct cxl_nvdimm *cxl_nvd; + if (!is_cxl_nvdimm(dev)) return 0; + + cxl_nvd = to_cxl_nvdimm(dev); + if (cxl_nvd->bridge != cxl_nvb) + return 0; + device_release_driver(dev); return 0; } -static void offline_nvdimm_bus(struct nvdimm_bus *nvdimm_bus) +static int cxl_pmem_region_release_driver(struct device *dev, void *cxl_nvb) +{ + struct cxl_pmem_region *cxlr_pmem; + + if (!is_cxl_pmem_region(dev)) + return 0; + + cxlr_pmem = to_cxl_pmem_region(dev); + if (cxlr_pmem->bridge != cxl_nvb) + return 0; + + device_release_driver(dev); + return 0; +} + +static void offline_nvdimm_bus(struct cxl_nvdimm_bridge *cxl_nvb, + struct nvdimm_bus *nvdimm_bus) { if (!nvdimm_bus) return; @@ -222,7 +263,10 @@ static void offline_nvdimm_bus(struct nvdimm_bus *nvdimm_bus) * nvdimm_bus_unregister() rips the nvdimm objects out from * underneath them. */ - bus_for_each_dev(&cxl_bus_type, NULL, NULL, cxl_nvdimm_release_driver); + bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb, + cxl_pmem_region_release_driver); + bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb, + cxl_nvdimm_release_driver); nvdimm_bus_unregister(nvdimm_bus); } @@ -260,7 +304,7 @@ static void cxl_nvb_update_state(struct work_struct *work) dev_dbg(&cxl_nvb->dev, "rescan: %d\n", rc); } - offline_nvdimm_bus(victim_bus); + offline_nvdimm_bus(cxl_nvb, victim_bus); put_device(&cxl_nvb->dev); } @@ -315,6 +359,203 @@ static struct cxl_driver cxl_nvdimm_bridge_driver = { .id = CXL_DEVICE_NVDIMM_BRIDGE, }; +static int match_cxl_nvdimm(struct device *dev, void *data) +{ + return is_cxl_nvdimm(dev); +} + +static void unregister_nvdimm_region(void *nd_region) +{ + struct cxl_nvdimm_bridge *cxl_nvb; + struct cxl_pmem_region *cxlr_pmem; + int i; + + cxlr_pmem = nd_region_provider_data(nd_region); + cxl_nvb = cxlr_pmem->bridge; + device_lock(&cxl_nvb->dev); + for (i = 0; i < cxlr_pmem->nr_mappings; i++) { + struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i]; + struct cxl_nvdimm *cxl_nvd = m->cxl_nvd; + + if (cxl_nvd->region) { + put_device(&cxlr_pmem->dev); + cxl_nvd->region = NULL; + } + } + device_unlock(&cxl_nvb->dev); + + nvdimm_region_delete(nd_region); +} + +static void cxlr_pmem_remove_resource(void *res) +{ + remove_resource(res); +} + +struct cxl_pmem_region_info { + u64 offset; + u64 serial; +}; + +static int cxl_pmem_region_probe(struct device *dev) +{ + struct nd_mapping_desc mappings[CXL_DECODER_MAX_INTERLEAVE]; + struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev); + struct cxl_region *cxlr = cxlr_pmem->cxlr; + struct cxl_pmem_region_info *info = NULL; + struct cxl_nvdimm_bridge *cxl_nvb; + struct nd_interleave_set *nd_set; + struct nd_region_desc ndr_desc; + struct cxl_nvdimm *cxl_nvd; + struct nvdimm *nvdimm; + struct resource *res; + int rc, i = 0; + + cxl_nvb = cxl_find_nvdimm_bridge(&cxlr_pmem->mapping[0].cxlmd->dev); + if (!cxl_nvb) { + dev_dbg(dev, "bridge not found\n"); + return -ENXIO; + } + cxlr_pmem->bridge = cxl_nvb; + + device_lock(&cxl_nvb->dev); + if (!cxl_nvb->nvdimm_bus) { + dev_dbg(dev, "nvdimm bus not found\n"); + rc = -ENXIO; + goto err; + } + + memset(&mappings, 0, sizeof(mappings)); + memset(&ndr_desc, 0, sizeof(ndr_desc)); + + res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); + if (!res) { + rc = -ENOMEM; + goto err; + } + + res->name = "Persistent Memory"; + res->start = cxlr_pmem->hpa_range.start; + res->end = cxlr_pmem->hpa_range.end; + res->flags = IORESOURCE_MEM; + res->desc = IORES_DESC_PERSISTENT_MEMORY; + + rc = insert_resource(&iomem_resource, res); + if (rc) + goto err; + + rc = devm_add_action_or_reset(dev, cxlr_pmem_remove_resource, res); + if (rc) + goto err; + + ndr_desc.res = res; + ndr_desc.provider_data = cxlr_pmem; + + ndr_desc.numa_node = memory_add_physaddr_to_nid(res->start); + ndr_desc.target_node = phys_to_target_node(res->start); + if (ndr_desc.target_node == NUMA_NO_NODE) { + ndr_desc.target_node = ndr_desc.numa_node; + dev_dbg(&cxlr->dev, "changing target node from %d to %d", + NUMA_NO_NODE, ndr_desc.target_node); + } + + nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL); + if (!nd_set) { + rc = -ENOMEM; + goto err; + } + + ndr_desc.memregion = cxlr->id; + set_bit(ND_REGION_CXL, &ndr_desc.flags); + set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags); + + info = kmalloc_array(cxlr_pmem->nr_mappings, sizeof(*info), GFP_KERNEL); + if (!info) { + rc = -ENOMEM; + goto err; + } + + for (i = 0; i < cxlr_pmem->nr_mappings; i++) { + struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i]; + struct cxl_memdev *cxlmd = m->cxlmd; + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct device *d; + + d = device_find_child(&cxlmd->dev, NULL, match_cxl_nvdimm); + if (!d) { + dev_dbg(dev, "[%d]: %s: no cxl_nvdimm found\n", i, + dev_name(&cxlmd->dev)); + rc = -ENODEV; + goto err; + } + + /* safe to drop ref now with bridge lock held */ + put_device(d); + + cxl_nvd = to_cxl_nvdimm(d); + nvdimm = dev_get_drvdata(&cxl_nvd->dev); + if (!nvdimm) { + dev_dbg(dev, "[%d]: %s: no nvdimm found\n", i, + dev_name(&cxlmd->dev)); + rc = -ENODEV; + goto err; + } + cxl_nvd->region = cxlr_pmem; + get_device(&cxlr_pmem->dev); + m->cxl_nvd = cxl_nvd; + mappings[i] = (struct nd_mapping_desc) { + .nvdimm = nvdimm, + .start = m->start, + .size = m->size, + .position = i, + }; + info[i].offset = m->start; + info[i].serial = cxlds->serial; + } + ndr_desc.num_mappings = cxlr_pmem->nr_mappings; + ndr_desc.mapping = mappings; + + /* + * TODO enable CXL labels which skip the need for 'interleave-set cookie' + */ + nd_set->cookie1 = + nd_fletcher64(info, sizeof(*info) * cxlr_pmem->nr_mappings, 0); + nd_set->cookie2 = nd_set->cookie1; + ndr_desc.nd_set = nd_set; + + cxlr_pmem->nd_region = + nvdimm_pmem_region_create(cxl_nvb->nvdimm_bus, &ndr_desc); + if (!cxlr_pmem->nd_region) { + rc = -ENOMEM; + goto err; + } + + rc = devm_add_action_or_reset(dev, unregister_nvdimm_region, + cxlr_pmem->nd_region); +out: + kfree(info); + device_unlock(&cxl_nvb->dev); + put_device(&cxl_nvb->dev); + + return rc; + +err: + dev_dbg(dev, "failed to create nvdimm region\n"); + for (i--; i >= 0; i--) { + nvdimm = mappings[i].nvdimm; + cxl_nvd = nvdimm_provider_data(nvdimm); + put_device(&cxl_nvd->region->dev); + cxl_nvd->region = NULL; + } + goto out; +} + +static struct cxl_driver cxl_pmem_region_driver = { + .name = "cxl_pmem_region", + .probe = cxl_pmem_region_probe, + .id = CXL_DEVICE_PMEM_REGION, +}; + /* * Return all bridges to the CXL_NVB_NEW state to invalidate any * ->state_work referring to the now destroyed cxl_pmem_wq. @@ -359,8 +600,14 @@ static __init int cxl_pmem_init(void) if (rc) goto err_nvdimm; + rc = cxl_driver_register(&cxl_pmem_region_driver); + if (rc) + goto err_region; + return 0; +err_region: + cxl_driver_unregister(&cxl_nvdimm_driver); err_nvdimm: cxl_driver_unregister(&cxl_nvdimm_bridge_driver); err_bridge: @@ -370,6 +617,7 @@ err_bridge: static __exit void cxl_pmem_exit(void) { + cxl_driver_unregister(&cxl_pmem_region_driver); cxl_driver_unregister(&cxl_nvdimm_driver); cxl_driver_unregister(&cxl_nvdimm_bridge_driver); destroy_cxl_pmem_wq(); @@ -381,3 +629,4 @@ module_exit(cxl_pmem_exit); MODULE_IMPORT_NS(CXL); MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM_BRIDGE); MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM); +MODULE_ALIAS_CXL(CXL_DEVICE_PMEM_REGION); diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index 3cf308f114c4..5453771bf330 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -53,6 +53,9 @@ static int cxl_port_probe(struct device *dev) struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); struct cxl_dev_state *cxlds = cxlmd->cxlds; + /* Cache the data early to ensure is_visible() works */ + read_cdat_data(port); + get_device(&cxlmd->dev); rc = devm_add_action_or_reset(dev, schedule_detach, cxlmd); if (rc) @@ -78,10 +81,60 @@ static int cxl_port_probe(struct device *dev) return 0; } +static ssize_t CDAT_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t offset, size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_port *port = to_cxl_port(dev); + + if (!port->cdat_available) + return -ENXIO; + + if (!port->cdat.table) + return 0; + + return memory_read_from_buffer(buf, count, &offset, + port->cdat.table, + port->cdat.length); +} + +static BIN_ATTR_ADMIN_RO(CDAT, 0); + +static umode_t cxl_port_bin_attr_is_visible(struct kobject *kobj, + struct bin_attribute *attr, int i) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_port *port = to_cxl_port(dev); + + if ((attr == &bin_attr_CDAT) && port->cdat_available) + return attr->attr.mode; + + return 0; +} + +static struct bin_attribute *cxl_cdat_bin_attributes[] = { + &bin_attr_CDAT, + NULL, +}; + +static struct attribute_group cxl_cdat_attribute_group = { + .bin_attrs = cxl_cdat_bin_attributes, + .is_bin_visible = cxl_port_bin_attr_is_visible, +}; + +static const struct attribute_group *cxl_port_attribute_groups[] = { + &cxl_cdat_attribute_group, + NULL, +}; + static struct cxl_driver cxl_port_driver = { .name = "cxl_port", .probe = cxl_port_probe, .id = CXL_DEVICE_PORT, + .drv = { + .dev_groups = cxl_port_attribute_groups, + }, }; module_cxl_driver(cxl_port_driver); diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index d976260eca7a..473a71bbd9c9 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -133,7 +133,8 @@ static void nd_region_release(struct device *dev) put_device(&nvdimm->dev); } free_percpu(nd_region->lane); - memregion_free(nd_region->id); + if (!test_bit(ND_REGION_CXL, &nd_region->flags)) + memregion_free(nd_region->id); kfree(nd_region); } @@ -982,9 +983,14 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, if (!nd_region) return NULL; - nd_region->id = memregion_alloc(GFP_KERNEL); - if (nd_region->id < 0) - goto err_id; + /* CXL pre-assigns memregion ids before creating nvdimm regions */ + if (test_bit(ND_REGION_CXL, &ndr_desc->flags)) { + nd_region->id = ndr_desc->memregion; + } else { + nd_region->id = memregion_alloc(GFP_KERNEL); + if (nd_region->id < 0) + goto err_id; + } nd_region->lane = alloc_percpu(struct nd_percpu_lane); if (!nd_region->lane) @@ -1043,9 +1049,10 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, return nd_region; - err_percpu: - memregion_free(nd_region->id); - err_id: +err_percpu: + if (!test_bit(ND_REGION_CXL, &ndr_desc->flags)) + memregion_free(nd_region->id); +err_id: kfree(nd_region); return NULL; } @@ -1068,6 +1075,13 @@ struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus, } EXPORT_SYMBOL_GPL(nvdimm_volatile_region_create); +void nvdimm_region_delete(struct nd_region *nd_region) +{ + if (nd_region) + nd_device_unregister(&nd_region->dev, ND_SYNC); +} +EXPORT_SYMBOL_GPL(nvdimm_region_delete); + int nvdimm_flush(struct nd_region *nd_region, struct bio *bio) { int rc = 0; diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 5cc7cba1941f..55c028af4bd9 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -121,6 +121,9 @@ config XEN_PCIDEV_FRONTEND config PCI_ATS bool +config PCI_DOE + bool + config PCI_ECAM bool diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 0da6b1ebc694..2680e4c92f0a 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_PCI_ECAM) += ecam.o obj-$(CONFIG_PCI_P2PDMA) += p2pdma.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-$(CONFIG_VGA_ARB) += vgaarb.o +obj-$(CONFIG_PCI_DOE) += doe.o # Endpoint library must be initialized before its users obj-$(CONFIG_PCI_ENDPOINT) += endpoint/ diff --git a/drivers/pci/doe.c b/drivers/pci/doe.c new file mode 100644 index 000000000000..e402f05068a5 --- /dev/null +++ b/drivers/pci/doe.c @@ -0,0 +1,536 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Data Object Exchange + * PCIe r6.0, sec 6.30 DOE + * + * Copyright (C) 2021 Huawei + * Jonathan Cameron <[email protected]> + * + * Copyright (C) 2022 Intel Corporation + * Ira Weiny <[email protected]> + */ + +#define dev_fmt(fmt) "DOE: " fmt + +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> +#include <linux/pci.h> +#include <linux/pci-doe.h> +#include <linux/workqueue.h> + +#define PCI_DOE_PROTOCOL_DISCOVERY 0 + +/* Timeout of 1 second from 6.30.2 Operation, PCI Spec r6.0 */ +#define PCI_DOE_TIMEOUT HZ +#define PCI_DOE_POLL_INTERVAL (PCI_DOE_TIMEOUT / 128) + +#define PCI_DOE_FLAG_CANCEL 0 +#define PCI_DOE_FLAG_DEAD 1 + +/** + * struct pci_doe_mb - State for a single DOE mailbox + * + * This state is used to manage a single DOE mailbox capability. All fields + * should be considered opaque to the consumers and the structure passed into + * the helpers below after being created by devm_pci_doe_create() + * + * @pdev: PCI device this mailbox belongs to + * @cap_offset: Capability offset + * @prots: Array of protocols supported (encoded as long values) + * @wq: Wait queue for work item + * @work_queue: Queue of pci_doe_work items + * @flags: Bit array of PCI_DOE_FLAG_* flags + */ +struct pci_doe_mb { + struct pci_dev *pdev; + u16 cap_offset; + struct xarray prots; + + wait_queue_head_t wq; + struct workqueue_struct *work_queue; + unsigned long flags; +}; + +static int pci_doe_wait(struct pci_doe_mb *doe_mb, unsigned long timeout) +{ + if (wait_event_timeout(doe_mb->wq, + test_bit(PCI_DOE_FLAG_CANCEL, &doe_mb->flags), + timeout)) + return -EIO; + return 0; +} + +static void pci_doe_write_ctrl(struct pci_doe_mb *doe_mb, u32 val) +{ + struct pci_dev *pdev = doe_mb->pdev; + int offset = doe_mb->cap_offset; + + pci_write_config_dword(pdev, offset + PCI_DOE_CTRL, val); +} + +static int pci_doe_abort(struct pci_doe_mb *doe_mb) +{ + struct pci_dev *pdev = doe_mb->pdev; + int offset = doe_mb->cap_offset; + unsigned long timeout_jiffies; + + pci_dbg(pdev, "[%x] Issuing Abort\n", offset); + + timeout_jiffies = jiffies + PCI_DOE_TIMEOUT; + pci_doe_write_ctrl(doe_mb, PCI_DOE_CTRL_ABORT); + + do { + int rc; + u32 val; + + rc = pci_doe_wait(doe_mb, PCI_DOE_POLL_INTERVAL); + if (rc) + return rc; + pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + + /* Abort success! */ + if (!FIELD_GET(PCI_DOE_STATUS_ERROR, val) && + !FIELD_GET(PCI_DOE_STATUS_BUSY, val)) + return 0; + + } while (!time_after(jiffies, timeout_jiffies)); + + /* Abort has timed out and the MB is dead */ + pci_err(pdev, "[%x] ABORT timed out\n", offset); + return -EIO; +} + +static int pci_doe_send_req(struct pci_doe_mb *doe_mb, + struct pci_doe_task *task) +{ + struct pci_dev *pdev = doe_mb->pdev; + int offset = doe_mb->cap_offset; + u32 val; + int i; + + /* + * Check the DOE busy bit is not set. If it is set, this could indicate + * someone other than Linux (e.g. firmware) is using the mailbox. Note + * it is expected that firmware and OS will negotiate access rights via + * an, as yet to be defined, method. + */ + pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + if (FIELD_GET(PCI_DOE_STATUS_BUSY, val)) + return -EBUSY; + + if (FIELD_GET(PCI_DOE_STATUS_ERROR, val)) + return -EIO; + + /* Write DOE Header */ + val = FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_1_VID, task->prot.vid) | + FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_1_TYPE, task->prot.type); + pci_write_config_dword(pdev, offset + PCI_DOE_WRITE, val); + /* Length is 2 DW of header + length of payload in DW */ + pci_write_config_dword(pdev, offset + PCI_DOE_WRITE, + FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH, + 2 + task->request_pl_sz / + sizeof(u32))); + for (i = 0; i < task->request_pl_sz / sizeof(u32); i++) + pci_write_config_dword(pdev, offset + PCI_DOE_WRITE, + task->request_pl[i]); + + pci_doe_write_ctrl(doe_mb, PCI_DOE_CTRL_GO); + + return 0; +} + +static bool pci_doe_data_obj_ready(struct pci_doe_mb *doe_mb) +{ + struct pci_dev *pdev = doe_mb->pdev; + int offset = doe_mb->cap_offset; + u32 val; + + pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + if (FIELD_GET(PCI_DOE_STATUS_DATA_OBJECT_READY, val)) + return true; + return false; +} + +static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *task) +{ + struct pci_dev *pdev = doe_mb->pdev; + int offset = doe_mb->cap_offset; + size_t length, payload_length; + u32 val; + int i; + + /* Read the first dword to get the protocol */ + pci_read_config_dword(pdev, offset + PCI_DOE_READ, &val); + if ((FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_VID, val) != task->prot.vid) || + (FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_TYPE, val) != task->prot.type)) { + dev_err_ratelimited(&pdev->dev, "[%x] expected [VID, Protocol] = [%04x, %02x], got [%04x, %02x]\n", + doe_mb->cap_offset, task->prot.vid, task->prot.type, + FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_VID, val), + FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_TYPE, val)); + return -EIO; + } + + pci_write_config_dword(pdev, offset + PCI_DOE_READ, 0); + /* Read the second dword to get the length */ + pci_read_config_dword(pdev, offset + PCI_DOE_READ, &val); + pci_write_config_dword(pdev, offset + PCI_DOE_READ, 0); + + length = FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH, val); + if (length > SZ_1M || length < 2) + return -EIO; + + /* First 2 dwords have already been read */ + length -= 2; + payload_length = min(length, task->response_pl_sz / sizeof(u32)); + /* Read the rest of the response payload */ + for (i = 0; i < payload_length; i++) { + pci_read_config_dword(pdev, offset + PCI_DOE_READ, + &task->response_pl[i]); + /* Prior to the last ack, ensure Data Object Ready */ + if (i == (payload_length - 1) && !pci_doe_data_obj_ready(doe_mb)) + return -EIO; + pci_write_config_dword(pdev, offset + PCI_DOE_READ, 0); + } + + /* Flush excess length */ + for (; i < length; i++) { + pci_read_config_dword(pdev, offset + PCI_DOE_READ, &val); + pci_write_config_dword(pdev, offset + PCI_DOE_READ, 0); + } + + /* Final error check to pick up on any since Data Object Ready */ + pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + if (FIELD_GET(PCI_DOE_STATUS_ERROR, val)) + return -EIO; + + return min(length, task->response_pl_sz / sizeof(u32)) * sizeof(u32); +} + +static void signal_task_complete(struct pci_doe_task *task, int rv) +{ + task->rv = rv; + task->complete(task); +} + +static void signal_task_abort(struct pci_doe_task *task, int rv) +{ + struct pci_doe_mb *doe_mb = task->doe_mb; + struct pci_dev *pdev = doe_mb->pdev; + + if (pci_doe_abort(doe_mb)) { + /* + * If the device can't process an abort; set the mailbox dead + * - no more submissions + */ + pci_err(pdev, "[%x] Abort failed marking mailbox dead\n", + doe_mb->cap_offset); + set_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags); + } + signal_task_complete(task, rv); +} + +static void doe_statemachine_work(struct work_struct *work) +{ + struct pci_doe_task *task = container_of(work, struct pci_doe_task, + work); + struct pci_doe_mb *doe_mb = task->doe_mb; + struct pci_dev *pdev = doe_mb->pdev; + int offset = doe_mb->cap_offset; + unsigned long timeout_jiffies; + u32 val; + int rc; + + if (test_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags)) { + signal_task_complete(task, -EIO); + return; + } + + /* Send request */ + rc = pci_doe_send_req(doe_mb, task); + if (rc) { + /* + * The specification does not provide any guidance on how to + * resolve conflicting requests from other entities. + * Furthermore, it is likely that busy will not be detected + * most of the time. Flag any detection of status busy with an + * error. + */ + if (rc == -EBUSY) + dev_err_ratelimited(&pdev->dev, "[%x] busy detected; another entity is sending conflicting requests\n", + offset); + signal_task_abort(task, rc); + return; + } + + timeout_jiffies = jiffies + PCI_DOE_TIMEOUT; + /* Poll for response */ +retry_resp: + pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + if (FIELD_GET(PCI_DOE_STATUS_ERROR, val)) { + signal_task_abort(task, -EIO); + return; + } + + if (!FIELD_GET(PCI_DOE_STATUS_DATA_OBJECT_READY, val)) { + if (time_after(jiffies, timeout_jiffies)) { + signal_task_abort(task, -EIO); + return; + } + rc = pci_doe_wait(doe_mb, PCI_DOE_POLL_INTERVAL); + if (rc) { + signal_task_abort(task, rc); + return; + } + goto retry_resp; + } + + rc = pci_doe_recv_resp(doe_mb, task); + if (rc < 0) { + signal_task_abort(task, rc); + return; + } + + signal_task_complete(task, rc); +} + +static void pci_doe_task_complete(struct pci_doe_task *task) +{ + complete(task->private); +} + +static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid, + u8 *protocol) +{ + u32 request_pl = FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX, + *index); + u32 response_pl; + DECLARE_COMPLETION_ONSTACK(c); + struct pci_doe_task task = { + .prot.vid = PCI_VENDOR_ID_PCI_SIG, + .prot.type = PCI_DOE_PROTOCOL_DISCOVERY, + .request_pl = &request_pl, + .request_pl_sz = sizeof(request_pl), + .response_pl = &response_pl, + .response_pl_sz = sizeof(response_pl), + .complete = pci_doe_task_complete, + .private = &c, + }; + int rc; + + rc = pci_doe_submit_task(doe_mb, &task); + if (rc < 0) + return rc; + + wait_for_completion(&c); + + if (task.rv != sizeof(response_pl)) + return -EIO; + + *vid = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID, response_pl); + *protocol = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL, + response_pl); + *index = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX, + response_pl); + + return 0; +} + +static void *pci_doe_xa_prot_entry(u16 vid, u8 prot) +{ + return xa_mk_value((vid << 8) | prot); +} + +static int pci_doe_cache_protocols(struct pci_doe_mb *doe_mb) +{ + u8 index = 0; + u8 xa_idx = 0; + + do { + int rc; + u16 vid; + u8 prot; + + rc = pci_doe_discovery(doe_mb, &index, &vid, &prot); + if (rc) + return rc; + + pci_dbg(doe_mb->pdev, + "[%x] Found protocol %d vid: %x prot: %x\n", + doe_mb->cap_offset, xa_idx, vid, prot); + + rc = xa_insert(&doe_mb->prots, xa_idx++, + pci_doe_xa_prot_entry(vid, prot), GFP_KERNEL); + if (rc) + return rc; + } while (index); + + return 0; +} + +static void pci_doe_xa_destroy(void *mb) +{ + struct pci_doe_mb *doe_mb = mb; + + xa_destroy(&doe_mb->prots); +} + +static void pci_doe_destroy_workqueue(void *mb) +{ + struct pci_doe_mb *doe_mb = mb; + + destroy_workqueue(doe_mb->work_queue); +} + +static void pci_doe_flush_mb(void *mb) +{ + struct pci_doe_mb *doe_mb = mb; + + /* Stop all pending work items from starting */ + set_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags); + + /* Cancel an in progress work item, if necessary */ + set_bit(PCI_DOE_FLAG_CANCEL, &doe_mb->flags); + wake_up(&doe_mb->wq); + + /* Flush all work items */ + flush_workqueue(doe_mb->work_queue); +} + +/** + * pcim_doe_create_mb() - Create a DOE mailbox object + * + * @pdev: PCI device to create the DOE mailbox for + * @cap_offset: Offset of the DOE mailbox + * + * Create a single mailbox object to manage the mailbox protocol at the + * cap_offset specified. + * + * RETURNS: created mailbox object on success + * ERR_PTR(-errno) on failure + */ +struct pci_doe_mb *pcim_doe_create_mb(struct pci_dev *pdev, u16 cap_offset) +{ + struct pci_doe_mb *doe_mb; + struct device *dev = &pdev->dev; + int rc; + + doe_mb = devm_kzalloc(dev, sizeof(*doe_mb), GFP_KERNEL); + if (!doe_mb) + return ERR_PTR(-ENOMEM); + + doe_mb->pdev = pdev; + doe_mb->cap_offset = cap_offset; + init_waitqueue_head(&doe_mb->wq); + + xa_init(&doe_mb->prots); + rc = devm_add_action(dev, pci_doe_xa_destroy, doe_mb); + if (rc) + return ERR_PTR(rc); + + doe_mb->work_queue = alloc_ordered_workqueue("%s %s DOE [%x]", 0, + dev_driver_string(&pdev->dev), + pci_name(pdev), + doe_mb->cap_offset); + if (!doe_mb->work_queue) { + pci_err(pdev, "[%x] failed to allocate work queue\n", + doe_mb->cap_offset); + return ERR_PTR(-ENOMEM); + } + rc = devm_add_action_or_reset(dev, pci_doe_destroy_workqueue, doe_mb); + if (rc) + return ERR_PTR(rc); + + /* Reset the mailbox by issuing an abort */ + rc = pci_doe_abort(doe_mb); + if (rc) { + pci_err(pdev, "[%x] failed to reset mailbox with abort command : %d\n", + doe_mb->cap_offset, rc); + return ERR_PTR(rc); + } + + /* + * The state machine and the mailbox should be in sync now; + * Set up mailbox flush prior to using the mailbox to query protocols. + */ + rc = devm_add_action_or_reset(dev, pci_doe_flush_mb, doe_mb); + if (rc) + return ERR_PTR(rc); + + rc = pci_doe_cache_protocols(doe_mb); + if (rc) { + pci_err(pdev, "[%x] failed to cache protocols : %d\n", + doe_mb->cap_offset, rc); + return ERR_PTR(rc); + } + + return doe_mb; +} +EXPORT_SYMBOL_GPL(pcim_doe_create_mb); + +/** + * pci_doe_supports_prot() - Return if the DOE instance supports the given + * protocol + * @doe_mb: DOE mailbox capability to query + * @vid: Protocol Vendor ID + * @type: Protocol type + * + * RETURNS: True if the DOE mailbox supports the protocol specified + */ +bool pci_doe_supports_prot(struct pci_doe_mb *doe_mb, u16 vid, u8 type) +{ + unsigned long index; + void *entry; + + /* The discovery protocol must always be supported */ + if (vid == PCI_VENDOR_ID_PCI_SIG && type == PCI_DOE_PROTOCOL_DISCOVERY) + return true; + + xa_for_each(&doe_mb->prots, index, entry) + if (entry == pci_doe_xa_prot_entry(vid, type)) + return true; + + return false; +} +EXPORT_SYMBOL_GPL(pci_doe_supports_prot); + +/** + * pci_doe_submit_task() - Submit a task to be processed by the state machine + * + * @doe_mb: DOE mailbox capability to submit to + * @task: task to be queued + * + * Submit a DOE task (request/response) to the DOE mailbox to be processed. + * Returns upon queueing the task object. If the queue is full this function + * will sleep until there is room in the queue. + * + * task->complete will be called when the state machine is done processing this + * task. + * + * Excess data will be discarded. + * + * RETURNS: 0 when task has been successfully queued, -ERRNO on error + */ +int pci_doe_submit_task(struct pci_doe_mb *doe_mb, struct pci_doe_task *task) +{ + if (!pci_doe_supports_prot(doe_mb, task->prot.vid, task->prot.type)) + return -EINVAL; + + /* + * DOE requests must be a whole number of DW and the response needs to + * be big enough for at least 1 DW + */ + if (task->request_pl_sz % sizeof(u32) || + task->response_pl_sz < sizeof(u32)) + return -EINVAL; + + if (test_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags)) + return -EIO; + + task->doe_mb = doe_mb; + INIT_WORK(&task->work, doe_statemachine_work); + queue_work(doe_mb->work_queue, &task->work); + return 0; +} +EXPORT_SYMBOL_GPL(pci_doe_submit_task); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 9884d8b29d3b..c5286b027f00 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2315,7 +2315,7 @@ EXPORT_SYMBOL(pci_alloc_dev); static bool pci_bus_crs_vendor_id(u32 l) { - return (l & 0xffff) == 0x0001; + return (l & 0xffff) == PCI_VENDOR_ID_PCI_SIG; } static bool pci_bus_wait_crs(struct pci_bus *bus, int devfn, u32 *l, diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index bff144c97e66..1cf74b0c42e5 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -311,7 +311,7 @@ config PINCTRL_MICROCHIP_SGPIO LED controller. config PINCTRL_OCELOT - bool "Pinctrl driver for the Microsemi Ocelot and Jaguar2 SoCs" + tristate "Pinctrl driver for the Microsemi Ocelot and Jaguar2 SoCs" depends on OF depends on HAS_IOMEM select GPIOLIB diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.h b/drivers/pinctrl/aspeed/pinmux-aspeed.h index 4d7548686f39..aaa78a613196 100644 --- a/drivers/pinctrl/aspeed/pinmux-aspeed.h +++ b/drivers/pinctrl/aspeed/pinmux-aspeed.h @@ -632,7 +632,7 @@ struct aspeed_pin_desc { SIG_EXPR_LIST_ALIAS(pin, sig, group) /** - * Similar to the above, but for pins with a dual expressions (DE) and + * Similar to the above, but for pins with a dual expressions (DE) * and a single group (SG) of pins. * * @pin: The pin the signal will be routed to diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index dad453054776..7857e612a100 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -507,7 +507,7 @@ static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, } } -static void bcm2835_gpio_irq_enable(struct irq_data *data) +static void bcm2835_gpio_irq_unmask(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); @@ -516,13 +516,15 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data) unsigned bank = GPIO_REG_OFFSET(gpio); unsigned long flags; + gpiochip_enable_irq(chip, gpio); + raw_spin_lock_irqsave(&pc->irq_lock[bank], flags); set_bit(offset, &pc->enabled_irq_map[bank]); bcm2835_gpio_irq_config(pc, gpio, true); raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags); } -static void bcm2835_gpio_irq_disable(struct irq_data *data) +static void bcm2835_gpio_irq_mask(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); @@ -537,6 +539,8 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data) bcm2835_gpio_set_bit(pc, GPEDS0, gpio); clear_bit(offset, &pc->enabled_irq_map[bank]); raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags); + + gpiochip_disable_irq(chip, gpio); } static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc, @@ -693,16 +697,15 @@ static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on) return ret; } -static struct irq_chip bcm2835_gpio_irq_chip = { +static const struct irq_chip bcm2835_gpio_irq_chip = { .name = MODULE_NAME, - .irq_enable = bcm2835_gpio_irq_enable, - .irq_disable = bcm2835_gpio_irq_disable, .irq_set_type = bcm2835_gpio_irq_set_type, .irq_ack = bcm2835_gpio_irq_ack, - .irq_mask = bcm2835_gpio_irq_disable, - .irq_unmask = bcm2835_gpio_irq_enable, + .irq_mask = bcm2835_gpio_irq_mask, + .irq_unmask = bcm2835_gpio_irq_unmask, .irq_set_wake = bcm2835_gpio_irq_set_wake, - .flags = IRQCHIP_MASK_ON_SUSPEND, + .flags = (IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE), + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) @@ -1280,7 +1283,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); girq = &pc->gpio_chip.irq; - girq->chip = &bcm2835_gpio_irq_chip; + gpio_irq_chip_set_chip(girq, &bcm2835_gpio_irq_chip); girq->parent_handler = bcm2835_gpio_irq_handler; girq->num_parents = BCM2835_NUM_IRQS; girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index ffe39336fcac..9e57f4c62e60 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -126,7 +126,7 @@ struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np) mutex_lock(&pinctrldev_list_mutex); list_for_each_entry(pctldev, &pinctrldev_list, node) - if (pctldev->dev->of_node == np) { + if (device_match_of_node(pctldev->dev, np)) { mutex_unlock(&pinctrldev_list_mutex); return pctldev; } diff --git a/drivers/pinctrl/freescale/pinctrl-imx93.c b/drivers/pinctrl/freescale/pinctrl-imx93.c index 417e41b37a6f..91b3ee1e6fa9 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx93.c +++ b/drivers/pinctrl/freescale/pinctrl-imx93.c @@ -247,6 +247,7 @@ static const struct of_device_id imx93_pinctrl_of_match[] = { { .compatible = "fsl,imx93-iomuxc", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx93_pinctrl_of_match); static int imx93_pinctrl_probe(struct platform_device *pdev) { diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig index e5ec8b8956da..078eec8af4a4 100644 --- a/drivers/pinctrl/intel/Kconfig +++ b/drivers/pinctrl/intel/Kconfig @@ -151,6 +151,14 @@ config PINCTRL_LEWISBURG This pinctrl driver provides an interface that allows configuring of Intel Lewisburg pins and using them as GPIOs. +config PINCTRL_METEORLAKE + tristate "Intel Meteor Lake pinctrl and GPIO driver" + depends on ACPI + select PINCTRL_INTEL + help + This pinctrl driver provides an interface that allows configuring + of Intel Meteor Lake pins and using them as GPIOs. + config PINCTRL_SUNRISEPOINT tristate "Intel Sunrisepoint pinctrl and GPIO driver" depends on ACPI diff --git a/drivers/pinctrl/intel/Makefile b/drivers/pinctrl/intel/Makefile index 181ffcf34d62..bb87e7bc7b20 100644 --- a/drivers/pinctrl/intel/Makefile +++ b/drivers/pinctrl/intel/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_PINCTRL_ICELAKE) += pinctrl-icelake.o obj-$(CONFIG_PINCTRL_JASPERLAKE) += pinctrl-jasperlake.o obj-$(CONFIG_PINCTRL_LAKEFIELD) += pinctrl-lakefield.o obj-$(CONFIG_PINCTRL_LEWISBURG) += pinctrl-lewisburg.o +obj-$(CONFIG_PINCTRL_METEORLAKE) += pinctrl-meteorlake.o obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o obj-$(CONFIG_PINCTRL_TIGERLAKE) += pinctrl-tigerlake.o diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 31f8f271628c..67db79f38051 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -603,7 +603,7 @@ static const char *byt_get_group_name(struct pinctrl_dev *pctldev, { struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); - return vg->soc->groups[selector].name; + return vg->soc->groups[selector].grp.name; } static int byt_get_group_pins(struct pinctrl_dev *pctldev, @@ -613,8 +613,8 @@ static int byt_get_group_pins(struct pinctrl_dev *pctldev, { struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); - *pins = vg->soc->groups[selector].pins; - *num_pins = vg->soc->groups[selector].npins; + *pins = vg->soc->groups[selector].grp.pins; + *num_pins = vg->soc->groups[selector].grp.npins; return 0; } @@ -662,15 +662,15 @@ static void byt_set_group_simple_mux(struct intel_pinctrl *vg, raw_spin_lock_irqsave(&byt_lock, flags); - for (i = 0; i < group.npins; i++) { + for (i = 0; i < group.grp.npins; i++) { void __iomem *padcfg0; u32 value; - padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG); + padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); if (!padcfg0) { dev_warn(vg->dev, "Group %s, pin %i not muxed (no padcfg0)\n", - group.name, i); + group.grp.name, i); continue; } @@ -692,15 +692,15 @@ static void byt_set_group_mixed_mux(struct intel_pinctrl *vg, raw_spin_lock_irqsave(&byt_lock, flags); - for (i = 0; i < group.npins; i++) { + for (i = 0; i < group.grp.npins; i++) { void __iomem *padcfg0; u32 value; - padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG); + padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); if (!padcfg0) { dev_warn(vg->dev, "Group %s, pin %i not muxed (no padcfg0)\n", - group.name, i); + group.grp.name, i); continue; } diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 26b2a425d201..5c4fd16e5b01 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -627,7 +627,7 @@ static const char *chv_get_group_name(struct pinctrl_dev *pctldev, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->soc->groups[group].name; + return pctrl->soc->groups[group].grp.name; } static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, @@ -635,8 +635,8 @@ static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - *pins = pctrl->soc->groups[group].pins; - *npins = pctrl->soc->groups[group].npins; + *pins = pctrl->soc->groups[group].grp.pins; + *npins = pctrl->soc->groups[group].grp.npins; return 0; } @@ -721,16 +721,16 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, raw_spin_lock_irqsave(&chv_lock, flags); /* Check first that the pad is not locked */ - for (i = 0; i < grp->npins; i++) { - if (chv_pad_locked(pctrl, grp->pins[i])) { + for (i = 0; i < grp->grp.npins; i++) { + if (chv_pad_locked(pctrl, grp->grp.pins[i])) { raw_spin_unlock_irqrestore(&chv_lock, flags); - dev_warn(dev, "unable to set mode for locked pin %u\n", grp->pins[i]); + dev_warn(dev, "unable to set mode for locked pin %u\n", grp->grp.pins[i]); return -EBUSY; } } - for (i = 0; i < grp->npins; i++) { - int pin = grp->pins[i]; + for (i = 0; i < grp->grp.npins; i++) { + int pin = grp->grp.pins[i]; unsigned int mode; bool invert_oe; u32 value; diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index fd093e36c3a8..52ecd66ce357 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -279,7 +279,7 @@ static const char *intel_get_group_name(struct pinctrl_dev *pctldev, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->soc->groups[group].name; + return pctrl->soc->groups[group].grp.name; } static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, @@ -287,8 +287,8 @@ static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - *pins = pctrl->soc->groups[group].pins; - *npins = pctrl->soc->groups[group].npins; + *pins = pctrl->soc->groups[group].grp.pins; + *npins = pctrl->soc->groups[group].grp.npins; return 0; } @@ -391,19 +391,19 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, * All pins in the groups needs to be accessible and writable * before we can enable the mux for this group. */ - for (i = 0; i < grp->npins; i++) { - if (!intel_pad_usable(pctrl, grp->pins[i])) { + for (i = 0; i < grp->grp.npins; i++) { + if (!intel_pad_usable(pctrl, grp->grp.pins[i])) { raw_spin_unlock_irqrestore(&pctrl->lock, flags); return -EBUSY; } } /* Now enable the mux setting for each pin in the group */ - for (i = 0; i < grp->npins; i++) { + for (i = 0; i < grp->grp.npins; i++) { void __iomem *padcfg0; u32 value; - padcfg0 = intel_get_padcfg(pctrl, grp->pins[i], PADCFG0); + padcfg0 = intel_get_padcfg(pctrl, grp->grp.pins[i], PADCFG0); value = readl(padcfg0); value &= ~PADCFG0_PMODE_MASK; diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index 710341bb67cc..65628423bf63 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -24,17 +24,12 @@ struct device; /** * struct intel_pingroup - Description about group of pins - * @name: Name of the groups - * @pins: All pins in this group - * @npins: Number of pins in this groups - * @mode: Native mode in which the group is muxed out @pins. Used if @modes - * is %NULL. + * @grp: Generic data of the pin group (name and pins) + * @mode: Native mode in which the group is muxed out @pins. Used if @modes is %NULL. * @modes: If not %NULL this will hold mode for each pin in @pins */ struct intel_pingroup { - const char *name; - const unsigned int *pins; - size_t npins; + struct pingroup grp; unsigned short mode; const unsigned int *modes; }; @@ -156,15 +151,11 @@ struct intel_community { * a single integer or an array of integers in which case mode is per * pin. */ -#define PIN_GROUP(n, p, m) \ - { \ - .name = (n), \ - .pins = (p), \ - .npins = ARRAY_SIZE((p)), \ - .mode = __builtin_choose_expr( \ - __builtin_constant_p((m)), (m), 0), \ - .modes = __builtin_choose_expr( \ - __builtin_constant_p((m)), NULL, (m)), \ +#define PIN_GROUP(n, p, m) \ + { \ + .grp = PINCTRL_PINGROUP((n), (p), ARRAY_SIZE((p))), \ + .mode = __builtin_choose_expr(__builtin_constant_p((m)), (m), 0), \ + .modes = __builtin_choose_expr(__builtin_constant_p((m)), NULL, (m)), \ } #define FUNCTION(n, g) \ diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index 4fb39eb30902..5d1abee30f8f 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -282,7 +282,7 @@ static const char *lp_get_group_name(struct pinctrl_dev *pctldev, { struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); - return lg->soc->groups[selector].name; + return lg->soc->groups[selector].grp.name; } static int lp_get_group_pins(struct pinctrl_dev *pctldev, @@ -292,8 +292,8 @@ static int lp_get_group_pins(struct pinctrl_dev *pctldev, { struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); - *pins = lg->soc->groups[selector].pins; - *num_pins = lg->soc->groups[selector].npins; + *pins = lg->soc->groups[selector].grp.pins; + *num_pins = lg->soc->groups[selector].grp.npins; return 0; } @@ -366,8 +366,8 @@ static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev, raw_spin_lock_irqsave(&lg->lock, flags); /* Now enable the mux setting for each pin in the group */ - for (i = 0; i < grp->npins; i++) { - void __iomem *reg = lp_gpio_reg(&lg->chip, grp->pins[i], LP_CONFIG1); + for (i = 0; i < grp->grp.npins; i++) { + void __iomem *reg = lp_gpio_reg(&lg->chip, grp->grp.pins[i], LP_CONFIG1); u32 value; value = ioread32(reg); diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 3ae141e0b421..5e752818adb4 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -520,7 +520,7 @@ static const char *mrfld_get_group_name(struct pinctrl_dev *pctldev, { struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev); - return mp->groups[group].name; + return mp->groups[group].grp.name; } static int mrfld_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, @@ -528,8 +528,8 @@ static int mrfld_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, { struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev); - *pins = mp->groups[group].pins; - *npins = mp->groups[group].npins; + *pins = mp->groups[group].grp.pins; + *npins = mp->groups[group].grp.npins; return 0; } @@ -604,15 +604,15 @@ static int mrfld_pinmux_set_mux(struct pinctrl_dev *pctldev, * All pins in the groups needs to be accessible and writable * before we can enable the mux for this group. */ - for (i = 0; i < grp->npins; i++) { - if (!mrfld_buf_available(mp, grp->pins[i])) + for (i = 0; i < grp->grp.npins; i++) { + if (!mrfld_buf_available(mp, grp->grp.pins[i])) return -EBUSY; } /* Now enable the mux setting for each pin in the group */ raw_spin_lock_irqsave(&mp->lock, flags); - for (i = 0; i < grp->npins; i++) - mrfld_update_bufcfg(mp, grp->pins[i], bits, mask); + for (i = 0; i < grp->grp.npins; i++) + mrfld_update_bufcfg(mp, grp->grp.pins[i], bits, mask); raw_spin_unlock_irqrestore(&mp->lock, flags); return 0; diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c new file mode 100644 index 000000000000..9576dcd1cb29 --- /dev/null +++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Intel Meteor Lake PCH pinctrl/GPIO driver + * + * Copyright (C) 2022, Intel Corporation + * Author: Andy Shevchenko <[email protected]> + */ + +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-intel.h" + +#define MTL_PAD_OWN 0x0b0 +#define MTL_PADCFGLOCK 0x110 +#define MTL_HOSTSW_OWN 0x140 +#define MTL_GPI_IS 0x200 +#define MTL_GPI_IE 0x210 + +#define MTL_GPP(r, s, e, g) \ + { \ + .reg_num = (r), \ + .base = (s), \ + .size = ((e) - (s) + 1), \ + .gpio_base = (g), \ + } + +#define MTL_COMMUNITY(b, s, e, g) \ + { \ + .barno = (b), \ + .padown_offset = MTL_PAD_OWN, \ + .padcfglock_offset = MTL_PADCFGLOCK, \ + .hostown_offset = MTL_HOSTSW_OWN, \ + .is_offset = MTL_GPI_IS, \ + .ie_offset = MTL_GPI_IE, \ + .pin_base = (s), \ + .npins = ((e) - (s) + 1), \ + .gpps = (g), \ + .ngpps = ARRAY_SIZE(g), \ + } + +/* Meteor Lake-P */ +static const struct pinctrl_pin_desc mtlp_pins[] = { + /* CPU */ + PINCTRL_PIN(0, "PECI"), + PINCTRL_PIN(1, "UFS_RESET_B"), + PINCTRL_PIN(2, "VIDSOUT"), + PINCTRL_PIN(3, "VIDSCK"), + PINCTRL_PIN(4, "VIDALERT_B"), + /* GPP_V */ + PINCTRL_PIN(5, "BATLOW_B"), + PINCTRL_PIN(6, "AC_PRESENT"), + PINCTRL_PIN(7, "SOC_WAKE_B"), + PINCTRL_PIN(8, "PWRBTN_B"), + PINCTRL_PIN(9, "SLP_S3_B"), + PINCTRL_PIN(10, "SLP_S4_B"), + PINCTRL_PIN(11, "SLP_A_B"), + PINCTRL_PIN(12, "GPP_V_7"), + PINCTRL_PIN(13, "SUSCLK"), + PINCTRL_PIN(14, "SLP_WLAN_B"), + PINCTRL_PIN(15, "SLP_S5_B"), + PINCTRL_PIN(16, "LANPHYPC"), + PINCTRL_PIN(17, "SLP_LAN_B"), + PINCTRL_PIN(18, "GPP_V_13"), + PINCTRL_PIN(19, "WAKE_B"), + PINCTRL_PIN(20, "GPP_V_15"), + PINCTRL_PIN(21, "GPP_V_16"), + PINCTRL_PIN(22, "GPP_V_17"), + PINCTRL_PIN(23, "GPP_V_18"), + PINCTRL_PIN(24, "CATERR_B"), + PINCTRL_PIN(25, "PROCHOT_B"), + PINCTRL_PIN(26, "THERMTRIP_B"), + PINCTRL_PIN(27, "DSI_DE_TE_2_GENLOCK_REF"), + PINCTRL_PIN(28, "DSI_DE_TE_1_DISP_UTILS"), + /* GPP_C */ + PINCTRL_PIN(29, "SMBCLK"), + PINCTRL_PIN(30, "SMBDATA"), + PINCTRL_PIN(31, "SMBALERT_B"), + PINCTRL_PIN(32, "SML0CLK"), + PINCTRL_PIN(33, "SML0DATA"), + PINCTRL_PIN(34, "GPP_C_5"), + PINCTRL_PIN(35, "GPP_C_6"), + PINCTRL_PIN(36, "GPP_C_7"), + PINCTRL_PIN(37, "GPP_C_8"), + PINCTRL_PIN(38, "GPP_C_9"), + PINCTRL_PIN(39, "GPP_C_10"), + PINCTRL_PIN(40, "GPP_C_11"), + PINCTRL_PIN(41, "GPP_C_12"), + PINCTRL_PIN(42, "GPP_C_13"), + PINCTRL_PIN(43, "GPP_C_14"), + PINCTRL_PIN(44, "GPP_C_15"), + PINCTRL_PIN(45, "GPP_C_16"), + PINCTRL_PIN(46, "GPP_C_17"), + PINCTRL_PIN(47, "GPP_C_18"), + PINCTRL_PIN(48, "GPP_C_19"), + PINCTRL_PIN(49, "GPP_C_20"), + PINCTRL_PIN(50, "GPP_C_21"), + PINCTRL_PIN(51, "GPP_C_22"), + PINCTRL_PIN(52, "GPP_C_23"), + /* GPP_A */ + PINCTRL_PIN(53, "ESPI_IO_0"), + PINCTRL_PIN(54, "ESPI_IO_1"), + PINCTRL_PIN(55, "ESPI_IO_2"), + PINCTRL_PIN(56, "ESPI_IO_3"), + PINCTRL_PIN(57, "ESPI_CS0_B"), + PINCTRL_PIN(58, "ESPI_CLK"), + PINCTRL_PIN(59, "ESPI_RESET_B"), + PINCTRL_PIN(60, "GPP_A_7"), + PINCTRL_PIN(61, "GPP_A_8"), + PINCTRL_PIN(62, "GPP_A_9"), + PINCTRL_PIN(63, "GPP_A_10"), + PINCTRL_PIN(64, "GPP_A_11"), + PINCTRL_PIN(65, "GPP_A_12"), + PINCTRL_PIN(66, "ESPI_CS1_B"), + PINCTRL_PIN(67, "ESPI_CS2_B"), + PINCTRL_PIN(68, "ESPI_CS3_B"), + PINCTRL_PIN(69, "ESPI_ALERT0_B"), + PINCTRL_PIN(70, "ESPI_ALERT1_B"), + PINCTRL_PIN(71, "ESPI_ALERT2_B"), + PINCTRL_PIN(72, "ESPI_ALERT3_B"), + PINCTRL_PIN(73, "GPP_A_20"), + PINCTRL_PIN(74, "GPP_A_21"), + PINCTRL_PIN(75, "GPP_A_22"), + PINCTRL_PIN(76, "GPP_A_23"), + PINCTRL_PIN(77, "ESPI_CLK_LOOPBK"), + /* GPP_E */ + PINCTRL_PIN(78, "GPP_E_0"), + PINCTRL_PIN(79, "GPP_E_1"), + PINCTRL_PIN(80, "GPP_E_2"), + PINCTRL_PIN(81, "GPP_E_3"), + PINCTRL_PIN(82, "GPP_E_4"), + PINCTRL_PIN(83, "GPP_E_5"), + PINCTRL_PIN(84, "GPP_E_6"), + PINCTRL_PIN(85, "GPP_E_7"), + PINCTRL_PIN(86, "GPP_E_8"), + PINCTRL_PIN(87, "GPP_E_9"), + PINCTRL_PIN(88, "GPP_E_10"), + PINCTRL_PIN(89, "GPP_E_11"), + PINCTRL_PIN(90, "GPP_E_12"), + PINCTRL_PIN(91, "GPP_E_13"), + PINCTRL_PIN(92, "GPP_E_14"), + PINCTRL_PIN(93, "SLP_DRAM_B"), + PINCTRL_PIN(94, "GPP_E_16"), + PINCTRL_PIN(95, "GPP_E_17"), + PINCTRL_PIN(96, "GPP_E_18"), + PINCTRL_PIN(97, "GPP_E_19"), + PINCTRL_PIN(98, "GPP_E_20"), + PINCTRL_PIN(99, "GPP_E_21"), + PINCTRL_PIN(100, "DNX_FORCE_RELOAD"), + PINCTRL_PIN(101, "GPP_E_23"), + PINCTRL_PIN(102, "THC0_GSPI0_CLK_LOOPBK"), + /* GPP_H */ + PINCTRL_PIN(103, "GPP_H_0"), + PINCTRL_PIN(104, "GPP_H_1"), + PINCTRL_PIN(105, "GPP_H_2"), + PINCTRL_PIN(106, "GPP_H_3"), + PINCTRL_PIN(107, "GPP_H_4"), + PINCTRL_PIN(108, "GPP_H_5"), + PINCTRL_PIN(109, "GPP_H_6"), + PINCTRL_PIN(110, "GPP_H_7"), + PINCTRL_PIN(111, "GPP_H_8"), + PINCTRL_PIN(112, "GPP_H_9"), + PINCTRL_PIN(113, "GPP_H_10"), + PINCTRL_PIN(114, "GPP_H_11"), + PINCTRL_PIN(115, "GPP_H_12"), + PINCTRL_PIN(116, "CPU_C10_GATE_B"), + PINCTRL_PIN(117, "GPP_H_14"), + PINCTRL_PIN(118, "GPP_H_15"), + PINCTRL_PIN(119, "GPP_H_16"), + PINCTRL_PIN(120, "GPP_H_17"), + PINCTRL_PIN(121, "GPP_H_18"), + PINCTRL_PIN(122, "GPP_H_19"), + PINCTRL_PIN(123, "GPP_H_20"), + PINCTRL_PIN(124, "GPP_H_21"), + PINCTRL_PIN(125, "GPP_H_22"), + PINCTRL_PIN(126, "GPP_H_23"), + PINCTRL_PIN(127, "LPI3C1_CLK_LOOPBK"), + PINCTRL_PIN(128, "I3C0_CLK_LOOPBK"), + /* GPP_F */ + PINCTRL_PIN(129, "CNV_BRI_DT"), + PINCTRL_PIN(130, "CNV_BRI_RSP"), + PINCTRL_PIN(131, "CNV_RGI_DT"), + PINCTRL_PIN(132, "CNV_RGI_RSP"), + PINCTRL_PIN(133, "CNV_RF_RESET_B"), + PINCTRL_PIN(134, "CRF_CLKREQ"), + PINCTRL_PIN(135, "GPP_F_6"), + PINCTRL_PIN(136, "FUSA_DIAGTEST_EN"), + PINCTRL_PIN(137, "FUSA_DIAGTEST_MODE"), + PINCTRL_PIN(138, "BOOTMPC"), + PINCTRL_PIN(139, "GPP_F_10"), + PINCTRL_PIN(140, "GPP_F_11"), + PINCTRL_PIN(141, "GSXDOUT"), + PINCTRL_PIN(142, "GSXSLOAD"), + PINCTRL_PIN(143, "GSXDIN"), + PINCTRL_PIN(144, "GSXSRESETB"), + PINCTRL_PIN(145, "GSXCLK"), + PINCTRL_PIN(146, "GMII_MDC_0"), + PINCTRL_PIN(147, "GMII_MDIO_0"), + PINCTRL_PIN(148, "GPP_F_19"), + PINCTRL_PIN(149, "GPP_F_20"), + PINCTRL_PIN(150, "GPP_F_21"), + PINCTRL_PIN(151, "GPP_F_22"), + PINCTRL_PIN(152, "GPP_F_23"), + PINCTRL_PIN(153, "THC1_GSPI1_CLK_LOOPBK"), + PINCTRL_PIN(154, "GSPI0A_CLK_LOOPBK"), + /* SPI0 */ + PINCTRL_PIN(155, "SPI0_IO_2"), + PINCTRL_PIN(156, "SPI0_IO_3"), + PINCTRL_PIN(157, "SPI0_MOSI_IO_0"), + PINCTRL_PIN(158, "SPI0_MISO_IO_1"), + PINCTRL_PIN(159, "SPI0_TPM_CS_B"), + PINCTRL_PIN(160, "SPI0_FLASH_0_CS_B"), + PINCTRL_PIN(161, "SPI0_FLASH_1_CS_B"), + PINCTRL_PIN(162, "SPI0_CLK"), + PINCTRL_PIN(163, "L_BKLTEN"), + PINCTRL_PIN(164, "L_BKLTCTL"), + PINCTRL_PIN(165, "L_VDDEN"), + PINCTRL_PIN(166, "SYS_PWROK"), + PINCTRL_PIN(167, "SYS_RESET_B"), + PINCTRL_PIN(168, "MLK_RST_B"), + PINCTRL_PIN(169, "SPI0_CLK_LOOPBK"), + /* vGPIO_3 */ + PINCTRL_PIN(170, "ESPI_USB_OCB_0"), + PINCTRL_PIN(171, "ESPI_USB_OCB_1"), + PINCTRL_PIN(172, "ESPI_USB_OCB_2"), + PINCTRL_PIN(173, "ESPI_USB_OCB_3"), + PINCTRL_PIN(174, "USB_CPU_OCB_0"), + PINCTRL_PIN(175, "USB_CPU_OCB_1"), + PINCTRL_PIN(176, "USB_CPU_OCB_2"), + PINCTRL_PIN(177, "USB_CPU_OCB_3"), + PINCTRL_PIN(178, "TS0_IN_INT"), + PINCTRL_PIN(179, "TS1_IN_INT"), + PINCTRL_PIN(180, "THC0_WOT_INT"), + PINCTRL_PIN(181, "THC1_WOT_INT"), + PINCTRL_PIN(182, "THC0_WHC_INT"), + PINCTRL_PIN(183, "THC1_WHC_INT"), + /* GPP_S */ + PINCTRL_PIN(184, "GPP_S_0"), + PINCTRL_PIN(185, "GPP_S_1"), + PINCTRL_PIN(186, "GPP_S_2"), + PINCTRL_PIN(187, "GPP_S_3"), + PINCTRL_PIN(188, "GPP_S_4"), + PINCTRL_PIN(189, "GPP_S_5"), + PINCTRL_PIN(190, "GPP_S_6"), + PINCTRL_PIN(191, "GPP_S_7"), + /* JTAG */ + PINCTRL_PIN(192, "JTAG_MBPB0"), + PINCTRL_PIN(193, "JTAG_MBPB1"), + PINCTRL_PIN(194, "JTAG_MBPB2"), + PINCTRL_PIN(195, "JTAG_MBPB3"), + PINCTRL_PIN(196, "JTAG_TDO"), + PINCTRL_PIN(197, "PRDY_B"), + PINCTRL_PIN(198, "PREQ_B"), + PINCTRL_PIN(199, "JTAG_TDI"), + PINCTRL_PIN(200, "JTAG_TMS"), + PINCTRL_PIN(201, "JTAG_TCK"), + PINCTRL_PIN(202, "DBG_PMODE"), + PINCTRL_PIN(203, "JTAG_TRST_B"), + /* GPP_B */ + PINCTRL_PIN(204, "ADM_VID_0"), + PINCTRL_PIN(205, "ADM_VID_1"), + PINCTRL_PIN(206, "GPP_B_2"), + PINCTRL_PIN(207, "GPP_B_3"), + PINCTRL_PIN(208, "GPP_B_4"), + PINCTRL_PIN(209, "GPP_B_5"), + PINCTRL_PIN(210, "GPP_B_6"), + PINCTRL_PIN(211, "GPP_B_7"), + PINCTRL_PIN(212, "GPP_B_8"), + PINCTRL_PIN(213, "GPP_B_9"), + PINCTRL_PIN(214, "GPP_B_10"), + PINCTRL_PIN(215, "GPP_B_11"), + PINCTRL_PIN(216, "SLP_S0_B"), + PINCTRL_PIN(217, "PLTRST_B"), + PINCTRL_PIN(218, "GPP_B_14"), + PINCTRL_PIN(219, "GPP_B_15"), + PINCTRL_PIN(220, "GPP_B_16"), + PINCTRL_PIN(221, "GPP_B_17"), + PINCTRL_PIN(222, "GPP_B_18"), + PINCTRL_PIN(223, "GPP_B_19"), + PINCTRL_PIN(224, "GPP_B_20"), + PINCTRL_PIN(225, "GPP_B_21"), + PINCTRL_PIN(226, "GPP_B_22"), + PINCTRL_PIN(227, "GPP_B_23"), + PINCTRL_PIN(228, "ISH_I3C0_CLK_LOOPBK"), + /* GPP_D */ + PINCTRL_PIN(229, "GPP_D_0"), + PINCTRL_PIN(230, "GPP_D_1"), + PINCTRL_PIN(231, "GPP_D_2"), + PINCTRL_PIN(232, "GPP_D_3"), + PINCTRL_PIN(233, "GPP_D_4"), + PINCTRL_PIN(234, "GPP_D_5"), + PINCTRL_PIN(235, "GPP_D_6"), + PINCTRL_PIN(236, "GPP_D_7"), + PINCTRL_PIN(237, "GPP_D_8"), + PINCTRL_PIN(238, "GPP_D_9"), + PINCTRL_PIN(239, "HDA_BCLK"), + PINCTRL_PIN(240, "HDA_SYNC"), + PINCTRL_PIN(241, "HDA_SDO"), + PINCTRL_PIN(242, "HDA_SDI_0"), + PINCTRL_PIN(243, "GPP_D_14"), + PINCTRL_PIN(244, "GPP_D_15"), + PINCTRL_PIN(245, "GPP_D_16"), + PINCTRL_PIN(246, "HDA_RST_B"), + PINCTRL_PIN(247, "GPP_D_18"), + PINCTRL_PIN(248, "GPP_D_19"), + PINCTRL_PIN(249, "GPP_D_20"), + PINCTRL_PIN(250, "UFS_REFCLK"), + PINCTRL_PIN(251, "BPKI3C_SDA"), + PINCTRL_PIN(252, "BPKI3C_SCL"), + PINCTRL_PIN(253, "BOOTHALT_B"), + /* vGPIO */ + PINCTRL_PIN(254, "CNV_BTEN"), + PINCTRL_PIN(255, "CNV_BT_HOST_WAKEB"), + PINCTRL_PIN(256, "CNV_BT_IF_SELECT"), + PINCTRL_PIN(257, "vCNV_BT_UART_TXD"), + PINCTRL_PIN(258, "vCNV_BT_UART_RXD"), + PINCTRL_PIN(259, "vCNV_BT_UART_CTS_B"), + PINCTRL_PIN(260, "vCNV_BT_UART_RTS_B"), + PINCTRL_PIN(261, "vCNV_MFUART1_TXD"), + PINCTRL_PIN(262, "vCNV_MFUART1_RXD"), + PINCTRL_PIN(263, "vCNV_MFUART1_CTS_B"), + PINCTRL_PIN(264, "vCNV_MFUART1_RTS_B"), + PINCTRL_PIN(265, "vUART0_TXD"), + PINCTRL_PIN(266, "vUART0_RXD"), + PINCTRL_PIN(267, "vUART0_CTS_B"), + PINCTRL_PIN(268, "vUART0_RTS_B"), + PINCTRL_PIN(269, "vISH_UART0_TXD"), + PINCTRL_PIN(270, "vISH_UART0_RXD"), + PINCTRL_PIN(271, "vISH_UART0_CTS_B"), + PINCTRL_PIN(272, "vISH_UART0_RTS_B"), + PINCTRL_PIN(273, "vCNV_BT_I2S_BCLK"), + PINCTRL_PIN(274, "vCNV_BT_I2S_WS_SYNC"), + PINCTRL_PIN(275, "vCNV_BT_I2S_SDO"), + PINCTRL_PIN(276, "vCNV_BT_I2S_SDI"), + PINCTRL_PIN(277, "vI2S2_SCLK"), + PINCTRL_PIN(278, "vI2S2_SFRM"), + PINCTRL_PIN(279, "vI2S2_TXD"), + PINCTRL_PIN(280, "vI2S2_RXD"), + PINCTRL_PIN(281, "vCNV_BT_I2S_BCLK_2"), + PINCTRL_PIN(282, "vCNV_BT_I2S_WS_SYNC_2"), + PINCTRL_PIN(283, "vCNV_BT_I2S_SDO_2"), + PINCTRL_PIN(284, "vCNV_BT_I2S_SDI_2"), + PINCTRL_PIN(285, "vI2S2_SCLK_2"), + PINCTRL_PIN(286, "vI2S2_SFRM_2"), + PINCTRL_PIN(287, "vI2S2_TXD_2"), + PINCTRL_PIN(288, "vI2S2_RXD_2"), +}; + +static const struct intel_padgroup mtlp_community0_gpps[] = { + MTL_GPP(0, 0, 4, 0), /* CPU */ + MTL_GPP(1, 5, 28, 32), /* GPP_V */ + MTL_GPP(2, 29, 52, 64), /* GPP_C */ +}; + +static const struct intel_padgroup mtlp_community1_gpps[] = { + MTL_GPP(0, 53, 77, 96), /* GPP_A */ + MTL_GPP(1, 78, 102, 128), /* GPP_E */ +}; + +static const struct intel_padgroup mtlp_community3_gpps[] = { + MTL_GPP(0, 103, 128, 160), /* GPP_H */ + MTL_GPP(1, 129, 154, 192), /* GPP_F */ + MTL_GPP(2, 155, 169, 224), /* SPI0 */ + MTL_GPP(3, 170, 183, 256), /* vGPIO_3 */ +}; + +static const struct intel_padgroup mtlp_community4_gpps[] = { + MTL_GPP(0, 184, 191, 288), /* GPP_S */ + MTL_GPP(1, 192, 203, 320), /* JTAG */ +}; + +static const struct intel_padgroup mtlp_community5_gpps[] = { + MTL_GPP(0, 204, 228, 352), /* GPP_B */ + MTL_GPP(1, 229, 253, 384), /* GPP_D */ + MTL_GPP(2, 254, 285, 416), /* vGPIO_0 */ + MTL_GPP(3, 286, 288, 448), /* vGPIO_1 */ +}; + +static const struct intel_community mtlp_communities[] = { + MTL_COMMUNITY(0, 0, 52, mtlp_community0_gpps), + MTL_COMMUNITY(1, 53, 102, mtlp_community1_gpps), + MTL_COMMUNITY(2, 103, 183, mtlp_community3_gpps), + MTL_COMMUNITY(3, 184, 203, mtlp_community4_gpps), + MTL_COMMUNITY(4, 204, 288, mtlp_community5_gpps), +}; + +static const struct intel_pinctrl_soc_data mtlp_soc_data = { + .pins = mtlp_pins, + .npins = ARRAY_SIZE(mtlp_pins), + .communities = mtlp_communities, + .ncommunities = ARRAY_SIZE(mtlp_communities), +}; + +static const struct acpi_device_id mtl_pinctrl_acpi_match[] = { + { "INTC1083", (kernel_ulong_t)&mtlp_soc_data }, + { } +}; +MODULE_DEVICE_TABLE(acpi, mtl_pinctrl_acpi_match); + +static INTEL_PINCTRL_PM_OPS(mtl_pinctrl_pm_ops); + +static struct platform_driver mtl_pinctrl_driver = { + .probe = intel_pinctrl_probe_by_hid, + .driver = { + .name = "meteorlake-pinctrl", + .acpi_match_table = mtl_pinctrl_acpi_match, + .pm = &mtl_pinctrl_pm_ops, + }, +}; +module_platform_driver(mtl_pinctrl_driver); + +MODULE_AUTHOR("Andy Shevchenko <[email protected]>"); +MODULE_DESCRIPTION("Intel Meteor Lake PCH pinctrl/GPIO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8192.c b/drivers/pinctrl/mediatek/pinctrl-mt8192.c index acccde9262ba..78c02b7c81f0 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8192.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8192.c @@ -1107,24 +1107,10 @@ static const struct mtk_pin_field_calc mt8192_pin_pupd_range[] = { PIN_FIELD_BASE(54, 54, 1, 0x0060, 0x10, 2, 1), PIN_FIELD_BASE(55, 55, 1, 0x0060, 0x10, 4, 1), PIN_FIELD_BASE(56, 56, 1, 0x0060, 0x10, 3, 1), - PIN_FIELD_BASE(118, 118, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(119, 119, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(120, 120, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(121, 121, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(122, 122, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(123, 123, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(124, 124, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(125, 125, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(139, 139, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(140, 140, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(141, 141, 4, 0x00e0, 0x10, 31, 1), - PIN_FIELD_BASE(142, 142, 4, 0x00e0, 0x10, 31, 1), PIN_FIELD_BASE(152, 152, 7, 0x0090, 0x10, 3, 1), PIN_FIELD_BASE(153, 153, 7, 0x0090, 0x10, 2, 1), PIN_FIELD_BASE(154, 154, 7, 0x0090, 0x10, 0, 1), PIN_FIELD_BASE(155, 155, 7, 0x0090, 0x10, 1, 1), - PIN_FIELD_BASE(160, 160, 7, 0x00f0, 0x10, 31, 1), - PIN_FIELD_BASE(161, 161, 7, 0x00f0, 0x10, 31, 1), PIN_FIELD_BASE(183, 183, 9, 0x0030, 0x10, 1, 1), PIN_FIELD_BASE(184, 184, 9, 0x0030, 0x10, 2, 1), PIN_FIELD_BASE(185, 185, 9, 0x0030, 0x10, 4, 1), @@ -1137,12 +1123,6 @@ static const struct mtk_pin_field_calc mt8192_pin_pupd_range[] = { PIN_FIELD_BASE(192, 192, 9, 0x0030, 0x10, 0, 1), PIN_FIELD_BASE(193, 193, 9, 0x0030, 0x10, 5, 1), PIN_FIELD_BASE(194, 194, 9, 0x0030, 0x10, 11, 1), - PIN_FIELD_BASE(200, 200, 8, 0x0070, 0x10, 31, 1), - PIN_FIELD_BASE(201, 201, 8, 0x0070, 0x10, 31, 1), - PIN_FIELD_BASE(202, 202, 5, 0x0070, 0x10, 31, 1), - PIN_FIELD_BASE(203, 203, 5, 0x0070, 0x10, 31, 1), - PIN_FIELD_BASE(204, 204, 8, 0x0070, 0x10, 31, 1), - PIN_FIELD_BASE(205, 205, 8, 0x0070, 0x10, 31, 1), }; static const struct mtk_pin_field_calc mt8192_pin_r0_range[] = { @@ -1164,24 +1144,10 @@ static const struct mtk_pin_field_calc mt8192_pin_r0_range[] = { PIN_FIELD_BASE(54, 54, 1, 0x0080, 0x10, 2, 1), PIN_FIELD_BASE(55, 55, 1, 0x0080, 0x10, 4, 1), PIN_FIELD_BASE(56, 56, 1, 0x0080, 0x10, 3, 1), - PIN_FIELD_BASE(118, 118, 4, 0x00e0, 0x10, 0, 1), - PIN_FIELD_BASE(119, 119, 4, 0x00e0, 0x10, 12, 1), - PIN_FIELD_BASE(120, 120, 4, 0x00e0, 0x10, 10, 1), - PIN_FIELD_BASE(121, 121, 4, 0x00e0, 0x10, 22, 1), - PIN_FIELD_BASE(122, 122, 4, 0x00e0, 0x10, 8, 1), - PIN_FIELD_BASE(123, 123, 4, 0x00e0, 0x10, 20, 1), - PIN_FIELD_BASE(124, 124, 4, 0x00e0, 0x10, 6, 1), - PIN_FIELD_BASE(125, 125, 4, 0x00e0, 0x10, 18, 1), - PIN_FIELD_BASE(139, 139, 4, 0x00e0, 0x10, 4, 1), - PIN_FIELD_BASE(140, 140, 4, 0x00e0, 0x10, 16, 1), - PIN_FIELD_BASE(141, 141, 4, 0x00e0, 0x10, 2, 1), - PIN_FIELD_BASE(142, 142, 4, 0x00e0, 0x10, 14, 1), PIN_FIELD_BASE(152, 152, 7, 0x00c0, 0x10, 3, 1), PIN_FIELD_BASE(153, 153, 7, 0x00c0, 0x10, 2, 1), PIN_FIELD_BASE(154, 154, 7, 0x00c0, 0x10, 0, 1), PIN_FIELD_BASE(155, 155, 7, 0x00c0, 0x10, 1, 1), - PIN_FIELD_BASE(160, 160, 7, 0x00f0, 0x10, 0, 1), - PIN_FIELD_BASE(161, 161, 7, 0x00f0, 0x10, 2, 1), PIN_FIELD_BASE(183, 183, 9, 0x0040, 0x10, 1, 1), PIN_FIELD_BASE(184, 184, 9, 0x0040, 0x10, 2, 1), PIN_FIELD_BASE(185, 185, 9, 0x0040, 0x10, 4, 1), @@ -1194,12 +1160,6 @@ static const struct mtk_pin_field_calc mt8192_pin_r0_range[] = { PIN_FIELD_BASE(192, 192, 9, 0x0040, 0x10, 0, 1), PIN_FIELD_BASE(193, 193, 9, 0x0040, 0x10, 5, 1), PIN_FIELD_BASE(194, 194, 9, 0x0040, 0x10, 11, 1), - PIN_FIELD_BASE(200, 200, 8, 0x0070, 0x10, 2, 1), - PIN_FIELD_BASE(201, 201, 8, 0x0070, 0x10, 6, 1), - PIN_FIELD_BASE(202, 202, 5, 0x0070, 0x10, 0, 1), - PIN_FIELD_BASE(203, 203, 5, 0x0070, 0x10, 2, 1), - PIN_FIELD_BASE(204, 204, 8, 0x0070, 0x10, 0, 1), - PIN_FIELD_BASE(205, 205, 8, 0x0070, 0x10, 4, 1), }; static const struct mtk_pin_field_calc mt8192_pin_r1_range[] = { @@ -1221,24 +1181,10 @@ static const struct mtk_pin_field_calc mt8192_pin_r1_range[] = { PIN_FIELD_BASE(54, 54, 1, 0x0090, 0x10, 2, 1), PIN_FIELD_BASE(55, 55, 1, 0x0090, 0x10, 4, 1), PIN_FIELD_BASE(56, 56, 1, 0x0090, 0x10, 3, 1), - PIN_FIELD_BASE(118, 118, 4, 0x00e0, 0x10, 1, 1), - PIN_FIELD_BASE(119, 119, 4, 0x00e0, 0x10, 13, 1), - PIN_FIELD_BASE(120, 120, 4, 0x00e0, 0x10, 11, 1), - PIN_FIELD_BASE(121, 121, 4, 0x00e0, 0x10, 23, 1), - PIN_FIELD_BASE(122, 122, 4, 0x00e0, 0x10, 9, 1), - PIN_FIELD_BASE(123, 123, 4, 0x00e0, 0x10, 21, 1), - PIN_FIELD_BASE(124, 124, 4, 0x00e0, 0x10, 7, 1), - PIN_FIELD_BASE(125, 125, 4, 0x00e0, 0x10, 19, 1), - PIN_FIELD_BASE(139, 139, 4, 0x00e0, 0x10, 5, 1), - PIN_FIELD_BASE(140, 140, 4, 0x00e0, 0x10, 17, 1), - PIN_FIELD_BASE(141, 141, 4, 0x00e0, 0x10, 3, 1), - PIN_FIELD_BASE(142, 142, 4, 0x00e0, 0x10, 15, 1), PIN_FIELD_BASE(152, 152, 7, 0x00d0, 0x10, 3, 1), PIN_FIELD_BASE(153, 153, 7, 0x00d0, 0x10, 2, 1), PIN_FIELD_BASE(154, 154, 7, 0x00d0, 0x10, 0, 1), PIN_FIELD_BASE(155, 155, 7, 0x00d0, 0x10, 1, 1), - PIN_FIELD_BASE(160, 160, 7, 0x00f0, 0x10, 1, 1), - PIN_FIELD_BASE(161, 161, 7, 0x00f0, 0x10, 3, 1), PIN_FIELD_BASE(183, 183, 9, 0x0050, 0x10, 1, 1), PIN_FIELD_BASE(184, 184, 9, 0x0050, 0x10, 2, 1), PIN_FIELD_BASE(185, 185, 9, 0x0050, 0x10, 4, 1), @@ -1251,83 +1197,169 @@ static const struct mtk_pin_field_calc mt8192_pin_r1_range[] = { PIN_FIELD_BASE(192, 192, 9, 0x0050, 0x10, 0, 1), PIN_FIELD_BASE(193, 193, 9, 0x0050, 0x10, 5, 1), PIN_FIELD_BASE(194, 194, 9, 0x0050, 0x10, 11, 1), - PIN_FIELD_BASE(200, 200, 8, 0x0070, 0x10, 3, 1), - PIN_FIELD_BASE(201, 201, 8, 0x0070, 0x10, 7, 1), - PIN_FIELD_BASE(202, 202, 5, 0x0070, 0x10, 1, 1), - PIN_FIELD_BASE(203, 203, 5, 0x0070, 0x10, 3, 1), - PIN_FIELD_BASE(204, 204, 8, 0x0070, 0x10, 1, 1), - PIN_FIELD_BASE(205, 205, 8, 0x0070, 0x10, 5, 1), }; -static const struct mtk_pin_field_calc mt8192_pin_e1e0en_range[] = { - PIN_FIELD_BASE(118, 118, 4, 0x0040, 0x10, 0, 1), - PIN_FIELD_BASE(119, 119, 4, 0x0040, 0x10, 18, 1), - PIN_FIELD_BASE(120, 120, 4, 0x0040, 0x10, 15, 1), - PIN_FIELD_BASE(121, 121, 4, 0x0050, 0x10, 3, 1), - PIN_FIELD_BASE(122, 122, 4, 0x0040, 0x10, 12, 1), - PIN_FIELD_BASE(123, 123, 4, 0x0050, 0x10, 0, 1), - PIN_FIELD_BASE(124, 124, 4, 0x0040, 0x10, 9, 1), - PIN_FIELD_BASE(125, 125, 4, 0x0040, 0x10, 27, 1), - PIN_FIELD_BASE(139, 139, 4, 0x0040, 0x10, 6, 1), - PIN_FIELD_BASE(140, 140, 4, 0x0040, 0x10, 24, 1), - PIN_FIELD_BASE(141, 141, 4, 0x0040, 0x10, 3, 1), - PIN_FIELD_BASE(142, 142, 4, 0x0040, 0x10, 21, 1), - PIN_FIELD_BASE(160, 160, 7, 0x0030, 0x10, 0, 1), - PIN_FIELD_BASE(161, 161, 7, 0x0030, 0x10, 3, 1), - PIN_FIELD_BASE(200, 200, 8, 0x0010, 0x10, 3, 1), - PIN_FIELD_BASE(201, 201, 8, 0x0010, 0x10, 9, 1), - PIN_FIELD_BASE(202, 202, 5, 0x0020, 0x10, 0, 1), - PIN_FIELD_BASE(203, 203, 5, 0x0020, 0x10, 3, 1), - PIN_FIELD_BASE(204, 204, 8, 0x0010, 0x10, 0, 1), - PIN_FIELD_BASE(205, 205, 8, 0x0010, 0x10, 6, 1), -}; +static const struct mtk_pin_field_calc mt8192_pin_drv_adv_range[] = { + PIN_FIELD_BASE(89, 89, 2, 0x0040, 0x10, 0, 5), + PIN_FIELD_BASE(90, 90, 2, 0x0040, 0x10, 5, 5), -static const struct mtk_pin_field_calc mt8192_pin_e0_range[] = { - PIN_FIELD_BASE(118, 118, 4, 0x0040, 0x10, 1, 1), - PIN_FIELD_BASE(119, 119, 4, 0x0040, 0x10, 19, 1), - PIN_FIELD_BASE(120, 120, 4, 0x0040, 0x10, 16, 1), - PIN_FIELD_BASE(121, 121, 4, 0x0050, 0x10, 4, 1), - PIN_FIELD_BASE(122, 122, 4, 0x0040, 0x10, 13, 1), - PIN_FIELD_BASE(123, 123, 4, 0x0050, 0x10, 1, 1), - PIN_FIELD_BASE(124, 124, 4, 0x0040, 0x10, 10, 1), - PIN_FIELD_BASE(125, 125, 4, 0x0040, 0x10, 28, 1), - PIN_FIELD_BASE(139, 139, 4, 0x0040, 0x10, 7, 1), - PIN_FIELD_BASE(140, 140, 4, 0x0040, 0x10, 25, 1), - PIN_FIELD_BASE(141, 141, 4, 0x0040, 0x10, 4, 1), - PIN_FIELD_BASE(142, 142, 4, 0x0040, 0x10, 22, 1), - PIN_FIELD_BASE(160, 160, 7, 0x0030, 0x10, 1, 1), - PIN_FIELD_BASE(161, 161, 7, 0x0030, 0x10, 4, 1), - PIN_FIELD_BASE(200, 200, 8, 0x0010, 0x10, 4, 1), - PIN_FIELD_BASE(201, 201, 8, 0x0010, 0x10, 10, 1), - PIN_FIELD_BASE(202, 202, 5, 0x0020, 0x10, 1, 1), - PIN_FIELD_BASE(203, 203, 5, 0x0020, 0x10, 4, 1), - PIN_FIELD_BASE(204, 204, 8, 0x0010, 0x10, 1, 1), - PIN_FIELD_BASE(205, 205, 8, 0x0010, 0x10, 7, 1), + PIN_FIELD_BASE(118, 118, 4, 0x0040, 0x10, 0, 3), + PIN_FIELD_BASE(119, 119, 4, 0x0040, 0x10, 18, 3), + PIN_FIELD_BASE(120, 120, 4, 0x0040, 0x10, 15, 3), + PIN_FIELD_BASE(121, 121, 4, 0x0050, 0x10, 3, 3), + PIN_FIELD_BASE(122, 122, 4, 0x0040, 0x10, 12, 3), + PIN_FIELD_BASE(123, 123, 4, 0x0050, 0x10, 0, 3), + PIN_FIELD_BASE(124, 124, 4, 0x0040, 0x10, 9, 3), + PIN_FIELD_BASE(125, 125, 4, 0x0040, 0x10, 27, 3), + PIN_FIELD_BASE(139, 139, 4, 0x0040, 0x10, 6, 3), + PIN_FIELD_BASE(140, 140, 4, 0x0040, 0x10, 24, 3), + PIN_FIELD_BASE(141, 141, 4, 0x0040, 0x10, 3, 3), + PIN_FIELD_BASE(142, 142, 4, 0x0040, 0x10, 21, 3), + PIN_FIELD_BASE(160, 160, 7, 0x0030, 0x10, 0, 3), + PIN_FIELD_BASE(161, 161, 7, 0x0030, 0x10, 3, 3), + PIN_FIELD_BASE(200, 200, 8, 0x0010, 0x10, 3, 3), + PIN_FIELD_BASE(201, 201, 8, 0x0010, 0x10, 9, 3), + PIN_FIELD_BASE(202, 202, 5, 0x0020, 0x10, 0, 3), + PIN_FIELD_BASE(203, 203, 5, 0x0020, 0x10, 3, 3), + PIN_FIELD_BASE(204, 204, 8, 0x0010, 0x10, 0, 3), + PIN_FIELD_BASE(205, 205, 8, 0x0010, 0x10, 6, 3), }; -static const struct mtk_pin_field_calc mt8192_pin_e1_range[] = { - PIN_FIELD_BASE(118, 118, 4, 0x0040, 0x10, 2, 1), - PIN_FIELD_BASE(119, 119, 4, 0x0040, 0x10, 20, 1), - PIN_FIELD_BASE(120, 120, 4, 0x0040, 0x10, 17, 1), - PIN_FIELD_BASE(121, 121, 4, 0x0050, 0x10, 5, 1), - PIN_FIELD_BASE(122, 122, 4, 0x0040, 0x10, 14, 1), - PIN_FIELD_BASE(123, 123, 4, 0x0050, 0x10, 2, 1), - PIN_FIELD_BASE(124, 124, 4, 0x0040, 0x10, 11, 1), - PIN_FIELD_BASE(125, 125, 4, 0x0040, 0x10, 29, 1), - PIN_FIELD_BASE(139, 139, 4, 0x0040, 0x10, 8, 1), - PIN_FIELD_BASE(140, 140, 4, 0x0040, 0x10, 26, 1), - PIN_FIELD_BASE(141, 141, 4, 0x0040, 0x10, 5, 1), - PIN_FIELD_BASE(142, 142, 4, 0x0040, 0x10, 23, 1), - PIN_FIELD_BASE(160, 160, 7, 0x0030, 0x10, 2, 1), - PIN_FIELD_BASE(161, 161, 7, 0x0030, 0x10, 5, 1), - PIN_FIELD_BASE(200, 200, 8, 0x0010, 0x10, 5, 1), - PIN_FIELD_BASE(201, 201, 8, 0x0010, 0x10, 11, 1), - PIN_FIELD_BASE(202, 202, 5, 0x0020, 0x10, 2, 1), - PIN_FIELD_BASE(203, 203, 5, 0x0020, 0x10, 5, 1), - PIN_FIELD_BASE(204, 204, 8, 0x0010, 0x10, 2, 1), - PIN_FIELD_BASE(205, 205, 8, 0x0010, 0x10, 8, 1), +static const struct mtk_pin_field_calc mt8192_pin_rsel_range[] = { + PIN_FIELD_BASE(118, 118, 4, 0x00e0, 0x10, 0, 2), + PIN_FIELD_BASE(119, 119, 4, 0x00e0, 0x10, 12, 2), + PIN_FIELD_BASE(120, 120, 4, 0x00e0, 0x10, 10, 2), + PIN_FIELD_BASE(121, 121, 4, 0x00e0, 0x10, 22, 2), + PIN_FIELD_BASE(122, 122, 4, 0x00e0, 0x10, 8, 2), + PIN_FIELD_BASE(123, 123, 4, 0x00e0, 0x10, 20, 2), + PIN_FIELD_BASE(124, 124, 4, 0x00e0, 0x10, 6, 2), + PIN_FIELD_BASE(125, 125, 4, 0x00e0, 0x10, 18, 2), + PIN_FIELD_BASE(139, 139, 4, 0x00e0, 0x10, 4, 2), + PIN_FIELD_BASE(140, 140, 4, 0x00e0, 0x10, 16, 2), + PIN_FIELD_BASE(141, 141, 4, 0x00e0, 0x10, 2, 2), + PIN_FIELD_BASE(142, 142, 4, 0x00e0, 0x10, 14, 2), + PIN_FIELD_BASE(160, 160, 7, 0x00f0, 0x10, 0, 2), + PIN_FIELD_BASE(161, 161, 7, 0x00f0, 0x10, 2, 2), + PIN_FIELD_BASE(200, 200, 8, 0x0070, 0x10, 2, 2), + PIN_FIELD_BASE(201, 201, 8, 0x0070, 0x10, 6, 2), + PIN_FIELD_BASE(202, 202, 5, 0x0070, 0x10, 0, 2), + PIN_FIELD_BASE(203, 203, 5, 0x0070, 0x10, 2, 2), + PIN_FIELD_BASE(204, 204, 8, 0x0070, 0x10, 0, 2), + PIN_FIELD_BASE(205, 205, 8, 0x0070, 0x10, 4, 2), }; +static const unsigned int mt8192_pull_type[] = { + MTK_PULL_PU_PD_TYPE,/*0*/ MTK_PULL_PU_PD_TYPE,/*1*/ + MTK_PULL_PU_PD_TYPE,/*2*/ MTK_PULL_PU_PD_TYPE,/*3*/ + MTK_PULL_PU_PD_TYPE,/*4*/ MTK_PULL_PU_PD_TYPE,/*5*/ + MTK_PULL_PU_PD_TYPE,/*6*/ MTK_PULL_PU_PD_TYPE,/*7*/ + MTK_PULL_PU_PD_TYPE,/*8*/ MTK_PULL_PU_PD_TYPE,/*9*/ + MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ + MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ + MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ + MTK_PULL_PU_PD_TYPE,/*16*/ MTK_PULL_PU_PD_TYPE,/*17*/ + MTK_PULL_PU_PD_TYPE,/*18*/ MTK_PULL_PU_PD_TYPE,/*19*/ + MTK_PULL_PU_PD_TYPE,/*20*/ MTK_PULL_PU_PD_TYPE,/*21*/ + MTK_PULL_PU_PD_TYPE,/*22*/ MTK_PULL_PU_PD_TYPE,/*23*/ + MTK_PULL_PU_PD_TYPE,/*24*/ MTK_PULL_PU_PD_TYPE,/*25*/ + MTK_PULL_PU_PD_TYPE,/*26*/ MTK_PULL_PU_PD_TYPE,/*27*/ + MTK_PULL_PU_PD_TYPE,/*28*/ MTK_PULL_PU_PD_TYPE,/*29*/ + MTK_PULL_PU_PD_TYPE,/*30*/ MTK_PULL_PU_PD_TYPE,/*31*/ + MTK_PULL_PU_PD_TYPE,/*32*/ MTK_PULL_PU_PD_TYPE,/*33*/ + MTK_PULL_PU_PD_TYPE,/*34*/ MTK_PULL_PU_PD_TYPE,/*35*/ + MTK_PULL_PU_PD_TYPE,/*36*/ MTK_PULL_PU_PD_TYPE,/*37*/ + MTK_PULL_PU_PD_TYPE,/*38*/ MTK_PULL_PU_PD_TYPE,/*39*/ + MTK_PULL_PU_PD_TYPE,/*40*/ MTK_PULL_PU_PD_TYPE,/*41*/ + MTK_PULL_PU_PD_TYPE,/*42*/ MTK_PULL_PU_PD_TYPE,/*43*/ + MTK_PULL_PU_PD_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ + MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ + MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ + MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ + MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ + MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ + MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PU_PD_TYPE,/*57*/ + MTK_PULL_PU_PD_TYPE,/*58*/ MTK_PULL_PU_PD_TYPE,/*59*/ + MTK_PULL_PU_PD_TYPE,/*60*/ MTK_PULL_PU_PD_TYPE,/*61*/ + MTK_PULL_PU_PD_TYPE,/*62*/ MTK_PULL_PU_PD_TYPE,/*63*/ + MTK_PULL_PU_PD_TYPE,/*64*/ MTK_PULL_PU_PD_TYPE,/*65*/ + MTK_PULL_PU_PD_TYPE,/*66*/ MTK_PULL_PU_PD_TYPE,/*67*/ + MTK_PULL_PU_PD_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ + MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ + MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ + MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ + MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ + MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ + MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ + MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ + MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ + MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ + MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ + MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ + MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ + MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ + MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ + MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ + MTK_PULL_PU_PD_TYPE,/*100*/ MTK_PULL_PU_PD_TYPE,/*101*/ + MTK_PULL_PU_PD_TYPE,/*102*/ MTK_PULL_PU_PD_TYPE,/*103*/ + MTK_PULL_PU_PD_TYPE,/*104*/ MTK_PULL_PU_PD_TYPE,/*105*/ + MTK_PULL_PU_PD_TYPE,/*106*/ MTK_PULL_PU_PD_TYPE,/*107*/ + MTK_PULL_PU_PD_TYPE,/*108*/ MTK_PULL_PU_PD_TYPE,/*109*/ + MTK_PULL_PU_PD_TYPE,/*110*/ MTK_PULL_PU_PD_TYPE,/*111*/ + MTK_PULL_PU_PD_TYPE,/*112*/ MTK_PULL_PU_PD_TYPE,/*113*/ + MTK_PULL_PU_PD_TYPE,/*114*/ MTK_PULL_PU_PD_TYPE,/*115*/ + MTK_PULL_PU_PD_TYPE,/*116*/ MTK_PULL_PU_PD_TYPE,/*117*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*118*/ MTK_PULL_PU_PD_RSEL_TYPE,/*119*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*120*/ MTK_PULL_PU_PD_RSEL_TYPE,/*121*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*122*/ MTK_PULL_PU_PD_RSEL_TYPE,/*123*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*124*/ MTK_PULL_PU_PD_RSEL_TYPE,/*125*/ + MTK_PULL_PU_PD_TYPE,/*126*/ MTK_PULL_PU_PD_TYPE,/*127*/ + MTK_PULL_PU_PD_TYPE,/*128*/ MTK_PULL_PU_PD_TYPE,/*129*/ + MTK_PULL_PU_PD_TYPE,/*130*/ MTK_PULL_PU_PD_TYPE,/*131*/ + MTK_PULL_PU_PD_TYPE,/*132*/ MTK_PULL_PU_PD_TYPE,/*133*/ + MTK_PULL_PU_PD_TYPE,/*134*/ MTK_PULL_PU_PD_TYPE,/*135*/ + MTK_PULL_PU_PD_TYPE,/*136*/ MTK_PULL_PU_PD_TYPE,/*137*/ + MTK_PULL_PU_PD_TYPE,/*138*/ MTK_PULL_PU_PD_RSEL_TYPE,/*139*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*140*/ MTK_PULL_PU_PD_RSEL_TYPE,/*141*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*142*/ MTK_PULL_PU_PD_TYPE,/*143*/ + MTK_PULL_PU_PD_TYPE,/*144*/ MTK_PULL_PU_PD_TYPE,/*145*/ + MTK_PULL_PU_PD_TYPE,/*146*/ MTK_PULL_PU_PD_TYPE,/*147*/ + MTK_PULL_PU_PD_TYPE,/*148*/ MTK_PULL_PU_PD_TYPE,/*149*/ + MTK_PULL_PU_PD_TYPE,/*150*/ MTK_PULL_PU_PD_TYPE,/*151*/ + MTK_PULL_PUPD_R1R0_TYPE,/*152*/ MTK_PULL_PUPD_R1R0_TYPE,/*153*/ + MTK_PULL_PUPD_R1R0_TYPE,/*154*/ MTK_PULL_PUPD_R1R0_TYPE,/*155*/ + MTK_PULL_PU_PD_TYPE,/*156*/ MTK_PULL_PU_PD_TYPE,/*157*/ + MTK_PULL_PU_PD_TYPE,/*158*/ MTK_PULL_PU_PD_TYPE,/*159*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*160*/ MTK_PULL_PU_PD_RSEL_TYPE,/*161*/ + MTK_PULL_PU_PD_TYPE,/*162*/ MTK_PULL_PU_PD_TYPE,/*163*/ + MTK_PULL_PU_PD_TYPE,/*164*/ MTK_PULL_PU_PD_TYPE,/*165*/ + MTK_PULL_PU_PD_TYPE,/*166*/ MTK_PULL_PU_PD_TYPE,/*167*/ + MTK_PULL_PU_PD_TYPE,/*168*/ MTK_PULL_PU_PD_TYPE,/*169*/ + MTK_PULL_PU_PD_TYPE,/*170*/ MTK_PULL_PU_PD_TYPE,/*171*/ + MTK_PULL_PU_PD_TYPE,/*172*/ MTK_PULL_PU_PD_TYPE,/*173*/ + MTK_PULL_PU_PD_TYPE,/*174*/ MTK_PULL_PU_PD_TYPE,/*175*/ + MTK_PULL_PU_PD_TYPE,/*176*/ MTK_PULL_PU_PD_TYPE,/*177*/ + MTK_PULL_PU_PD_TYPE,/*178*/ MTK_PULL_PU_PD_TYPE,/*179*/ + MTK_PULL_PU_PD_TYPE,/*180*/ MTK_PULL_PU_PD_TYPE,/*181*/ + MTK_PULL_PU_PD_TYPE,/*182*/ MTK_PULL_PUPD_R1R0_TYPE,/*183*/ + MTK_PULL_PUPD_R1R0_TYPE,/*184*/ MTK_PULL_PUPD_R1R0_TYPE,/*185*/ + MTK_PULL_PUPD_R1R0_TYPE,/*186*/ MTK_PULL_PUPD_R1R0_TYPE,/*187*/ + MTK_PULL_PUPD_R1R0_TYPE,/*188*/ MTK_PULL_PUPD_R1R0_TYPE,/*189*/ + MTK_PULL_PUPD_R1R0_TYPE,/*190*/ MTK_PULL_PUPD_R1R0_TYPE,/*191*/ + MTK_PULL_PUPD_R1R0_TYPE,/*192*/ MTK_PULL_PUPD_R1R0_TYPE,/*193*/ + MTK_PULL_PUPD_R1R0_TYPE,/*194*/ MTK_PULL_PU_PD_TYPE,/*195*/ + MTK_PULL_PU_PD_TYPE,/*196*/ MTK_PULL_PU_PD_TYPE,/*197*/ + MTK_PULL_PU_PD_TYPE,/*198*/ MTK_PULL_PU_PD_TYPE,/*199*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*200*/ MTK_PULL_PU_PD_RSEL_TYPE,/*201*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*202*/ MTK_PULL_PU_PD_RSEL_TYPE,/*203*/ + MTK_PULL_PU_PD_RSEL_TYPE,/*204*/ MTK_PULL_PU_PD_RSEL_TYPE,/*205*/ + MTK_PULL_PU_PD_TYPE,/*206*/ MTK_PULL_PU_PD_TYPE,/*207*/ + MTK_PULL_PU_PD_TYPE,/*208*/ MTK_PULL_PU_PD_TYPE,/*209*/ + MTK_PULL_PU_PD_TYPE,/*210*/ MTK_PULL_PU_PD_TYPE,/*211*/ + MTK_PULL_PU_PD_TYPE,/*212*/ MTK_PULL_PU_PD_TYPE,/*213*/ + MTK_PULL_PU_PD_TYPE,/*214*/ MTK_PULL_PU_PD_TYPE,/*215*/ + MTK_PULL_PU_PD_TYPE,/*216*/ MTK_PULL_PU_PD_TYPE,/*217*/ + MTK_PULL_PU_PD_TYPE,/*218*/ MTK_PULL_PU_PD_TYPE,/*219*/ +}; static const char * const mt8192_pinctrl_register_base_names[] = { "iocfg0", "iocfg_rm", "iocfg_bm", "iocfg_bl", "iocfg_br", @@ -1355,9 +1387,8 @@ static const struct mtk_pin_reg_calc mt8192_reg_cals[PINCTRL_PIN_REG_MAX] = { [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt8192_pin_pupd_range), [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt8192_pin_r0_range), [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt8192_pin_r1_range), - [PINCTRL_PIN_REG_DRV_EN] = MTK_RANGE(mt8192_pin_e1e0en_range), - [PINCTRL_PIN_REG_DRV_E0] = MTK_RANGE(mt8192_pin_e0_range), - [PINCTRL_PIN_REG_DRV_E1] = MTK_RANGE(mt8192_pin_e1_range), + [PINCTRL_PIN_REG_DRV_ADV] = MTK_RANGE(mt8192_pin_drv_adv_range), + [PINCTRL_PIN_REG_RSEL] = MTK_RANGE(mt8192_pin_rsel_range), }; static const struct mtk_pin_soc mt8192_data = { @@ -1367,17 +1398,16 @@ static const struct mtk_pin_soc mt8192_data = { .ngrps = ARRAY_SIZE(mtk_pins_mt8192), .base_names = mt8192_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt8192_pinctrl_register_base_names), + .pull_type = mt8192_pull_type, .eint_hw = &mt8192_eint_hw, .nfuncs = 8, .gpio_m = 0, .bias_set_combo = mtk_pinconf_bias_set_combo, .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_raw, - .drive_get = mtk_pinconf_drive_get_raw, - .adv_pull_get = mtk_pinconf_adv_pull_get, - .adv_pull_set = mtk_pinconf_adv_pull_set, - .adv_drive_get = mtk_pinconf_adv_drive_get, - .adv_drive_set = mtk_pinconf_adv_drive_set, + .drive_set = mtk_pinconf_drive_set_rev1, + .drive_get = mtk_pinconf_drive_get_rev1, + .adv_drive_get = mtk_pinconf_adv_drive_get_raw, + .adv_drive_set = mtk_pinconf_adv_drive_set_raw, }; static const struct of_device_id mt8192_pinctrl_of_match[] = { diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index a1f93859e7ca..8ef0a97d2bf5 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -96,10 +96,12 @@ static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name( struct mvebu_pinctrl *pctl, const char *name) { unsigned n; + for (n = 0; n < pctl->num_groups; n++) { if (strcmp(name, pctl->groups[n].name) == 0) return &pctl->groups[n]; } + return NULL; } @@ -108,6 +110,7 @@ static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val( unsigned long config) { unsigned n; + for (n = 0; n < grp->num_settings; n++) { if (config == grp->settings[n].val) { if (!pctl->variant || (pctl->variant & @@ -115,6 +118,7 @@ static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val( return &grp->settings[n]; } } + return NULL; } @@ -123,6 +127,7 @@ static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name( const char *name) { unsigned n; + for (n = 0; n < grp->num_settings; n++) { if (strcmp(name, grp->settings[n].name) == 0) { if (!pctl->variant || (pctl->variant & @@ -130,6 +135,7 @@ static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name( return &grp->settings[n]; } } + return NULL; } @@ -137,6 +143,7 @@ static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting( struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp) { unsigned n; + for (n = 0; n < grp->num_settings; n++) { if (grp->settings[n].flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { @@ -145,6 +152,7 @@ static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting( return &grp->settings[n]; } } + return NULL; } @@ -152,10 +160,12 @@ static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name( struct mvebu_pinctrl *pctl, const char *name) { unsigned n; + for (n = 0; n < pctl->num_functions; n++) { if (strcmp(name, pctl->functions[n].name) == 0) return &pctl->functions[n]; } + return NULL; } diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 640e50d94f27..f5014d09d81a 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -1421,8 +1421,10 @@ static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, has_config = nmk_pinctrl_dt_get_config(np, &configs); np_config = of_parse_phandle(np, "ste,config", 0); - if (np_config) + if (np_config) { has_config |= nmk_pinctrl_dt_get_config(np_config, &configs); + of_node_put(np_config); + } if (has_config) { const char *gpio_name; const char *pin; diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 0645c2c24f50..4691a33bc374 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -6,8 +6,6 @@ * Authors: Ken Xue <[email protected]> * Wu, Jeff <[email protected]> * - * Contact Information: Nehal Shah <[email protected]> - * Shyam Sundar S K <[email protected]> */ #include <linux/err.h> @@ -31,6 +29,7 @@ #include <linux/bitops.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinmux.h> #include "core.h" #include "pinctrl-utils.h" @@ -203,8 +202,6 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) struct amd_gpio *gpio_dev = gpiochip_get_data(gc); bool tmr_out_unit; - unsigned int time; - unsigned int unit; bool tmr_large; char *level_trig; @@ -218,13 +215,13 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) char *pull_up_sel; char *pull_up_enable; char *pull_down_enable; - char *output_value; - char *output_enable; + char *orientation; char debounce_value[40]; char *debounce_enable; for (bank = 0; bank < gpio_dev->hwbank_num; bank++) { - seq_printf(s, "GPIO bank%d\t", bank); + unsigned int time = 0; + unsigned int unit = 0; switch (bank) { case 0: @@ -247,8 +244,9 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) /* Illegal bank number, ignore */ continue; } + seq_printf(s, "GPIO bank%d\n", bank); for (; i < pin_num; i++) { - seq_printf(s, "pin%d\t", i); + seq_printf(s, "📌%d\t", i); raw_spin_lock_irqsave(&gpio_dev->lock, flags); pin_reg = readl(gpio_dev->base + i * 4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); @@ -256,84 +254,91 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) if (pin_reg & BIT(INTERRUPT_ENABLE_OFF)) { u8 level = (pin_reg >> ACTIVE_LEVEL_OFF) & ACTIVE_LEVEL_MASK; - interrupt_enable = "interrupt is enabled|"; + interrupt_enable = "+"; if (level == ACTIVE_LEVEL_HIGH) - active_level = "Active high|"; + active_level = "↑"; else if (level == ACTIVE_LEVEL_LOW) - active_level = "Active low|"; + active_level = "↓"; else if (!(pin_reg & BIT(LEVEL_TRIG_OFF)) && level == ACTIVE_LEVEL_BOTH) - active_level = "Active on both|"; + active_level = "b"; else - active_level = "Unknown Active level|"; + active_level = "?"; if (pin_reg & BIT(LEVEL_TRIG_OFF)) - level_trig = "Level trigger|"; + level_trig = "level"; else - level_trig = "Edge trigger|"; + level_trig = " edge"; } else { - interrupt_enable = - "interrupt is disabled|"; - active_level = " "; - level_trig = " "; + interrupt_enable = "∅"; + active_level = "∅"; + level_trig = " ∅"; } if (pin_reg & BIT(INTERRUPT_MASK_OFF)) - interrupt_mask = - "interrupt is unmasked|"; + interrupt_mask = "-"; else - interrupt_mask = - "interrupt is masked|"; + interrupt_mask = "+"; + seq_printf(s, "int %s (🎭 %s)| active-%s| %s-🔫| ", + interrupt_enable, + interrupt_mask, + active_level, + level_trig); if (pin_reg & BIT(WAKE_CNTRL_OFF_S0I3)) - wake_cntrl0 = "enable wakeup in S0i3 state|"; + wake_cntrl0 = "+"; else - wake_cntrl0 = "disable wakeup in S0i3 state|"; + wake_cntrl0 = "∅"; + seq_printf(s, "S0i3 🌅 %s| ", wake_cntrl0); if (pin_reg & BIT(WAKE_CNTRL_OFF_S3)) - wake_cntrl1 = "enable wakeup in S3 state|"; + wake_cntrl1 = "+"; else - wake_cntrl1 = "disable wakeup in S3 state|"; + wake_cntrl1 = "∅"; + seq_printf(s, "S3 🌅 %s| ", wake_cntrl1); if (pin_reg & BIT(WAKE_CNTRL_OFF_S4)) - wake_cntrl2 = "enable wakeup in S4/S5 state|"; + wake_cntrl2 = "+"; else - wake_cntrl2 = "disable wakeup in S4/S5 state|"; + wake_cntrl2 = "∅"; + seq_printf(s, "S4/S5 🌅 %s| ", wake_cntrl2); if (pin_reg & BIT(PULL_UP_ENABLE_OFF)) { - pull_up_enable = "pull-up is enabled|"; + pull_up_enable = "+"; if (pin_reg & BIT(PULL_UP_SEL_OFF)) - pull_up_sel = "8k pull-up|"; + pull_up_sel = "8k"; else - pull_up_sel = "4k pull-up|"; + pull_up_sel = "4k"; } else { - pull_up_enable = "pull-up is disabled|"; - pull_up_sel = " "; + pull_up_enable = "∅"; + pull_up_sel = " "; } + seq_printf(s, "pull-↑ %s (%s)| ", + pull_up_enable, + pull_up_sel); if (pin_reg & BIT(PULL_DOWN_ENABLE_OFF)) - pull_down_enable = "pull-down is enabled|"; + pull_down_enable = "+"; else - pull_down_enable = "Pull-down is disabled|"; + pull_down_enable = "∅"; + seq_printf(s, "pull-↓ %s| ", pull_down_enable); if (pin_reg & BIT(OUTPUT_ENABLE_OFF)) { - pin_sts = " "; - output_enable = "output is enabled|"; + pin_sts = "output"; if (pin_reg & BIT(OUTPUT_VALUE_OFF)) - output_value = "output is high|"; + orientation = "↑"; else - output_value = "output is low|"; + orientation = "↓"; } else { - output_enable = "output is disabled|"; - output_value = " "; - + pin_sts = "input "; if (pin_reg & BIT(PIN_STS_OFF)) - pin_sts = "input is high|"; + orientation = "↑"; else - pin_sts = "input is low|"; + orientation = "↓"; } + seq_printf(s, "%s %s| ", pin_sts, orientation); db_cntrl = (DB_CNTRl_MASK << DB_CNTRL_OFF) & pin_reg; if (db_cntrl) { @@ -352,27 +357,18 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) unit = 61; } if ((DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF) == db_cntrl) - debounce_enable = "debouncing filter (high and low) enabled|"; + debounce_enable = "b +"; else if ((DB_TYPE_PRESERVE_LOW_GLITCH << DB_CNTRL_OFF) == db_cntrl) - debounce_enable = "debouncing filter (low) enabled|"; + debounce_enable = "↓ +"; else - debounce_enable = "debouncing filter (high) enabled|"; + debounce_enable = "↑ +"; - snprintf(debounce_value, sizeof(debounce_value), - "debouncing timeout is %u (us)|", time * unit); } else { - debounce_enable = "debouncing filter disabled|"; - snprintf(debounce_value, sizeof(debounce_value), " "); + debounce_enable = " ∅"; } - - seq_printf(s, "%s %s %s %s %s %s\n" - " %s %s %s %s %s %s %s %s %s 0x%x\n", - level_trig, active_level, interrupt_enable, - interrupt_mask, wake_cntrl0, wake_cntrl1, - wake_cntrl2, pin_sts, pull_up_sel, - pull_up_enable, pull_down_enable, - output_value, output_enable, - debounce_enable, debounce_value, pin_reg); + snprintf(debounce_value, sizeof(debounce_value), "%u", time * unit); + seq_printf(s, "debounce %s (⏰ %sus)| ", debounce_enable, debounce_value); + seq_printf(s, " 0x%x\n", pin_reg); } } } @@ -917,6 +913,7 @@ static int amd_gpio_suspend(struct device *dev) { struct amd_gpio *gpio_dev = dev_get_drvdata(dev); struct pinctrl_desc *desc = gpio_dev->pctrl->desc; + unsigned long flags; int i; for (i = 0; i < desc->npins; i++) { @@ -925,7 +922,9 @@ static int amd_gpio_suspend(struct device *dev) if (!amd_gpio_should_save(gpio_dev, pin)) continue; - gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4); + raw_spin_lock_irqsave(&gpio_dev->lock, flags); + gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin * 4) & ~PIN_IRQ_PENDING; + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } return 0; @@ -935,6 +934,7 @@ static int amd_gpio_resume(struct device *dev) { struct amd_gpio *gpio_dev = dev_get_drvdata(dev); struct pinctrl_desc *desc = gpio_dev->pctrl->desc; + unsigned long flags; int i; for (i = 0; i < desc->npins; i++) { @@ -943,7 +943,10 @@ static int amd_gpio_resume(struct device *dev) if (!amd_gpio_should_save(gpio_dev, pin)) continue; - writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4); + raw_spin_lock_irqsave(&gpio_dev->lock, flags); + gpio_dev->saved_regs[i] |= readl(gpio_dev->base + pin * 4) & PIN_IRQ_PENDING; + writel(gpio_dev->saved_regs[i], gpio_dev->base + pin * 4); + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } return 0; @@ -955,14 +958,115 @@ static const struct dev_pm_ops amd_gpio_pm_ops = { }; #endif +static int amd_get_functions_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(pmx_functions); +} + +static const char *amd_get_fname(struct pinctrl_dev *pctrldev, unsigned int selector) +{ + return pmx_functions[selector].name; +} + +static int amd_get_groups(struct pinctrl_dev *pctrldev, unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctrldev); + + if (!gpio_dev->iomux_base) { + dev_err(&gpio_dev->pdev->dev, "iomux function %d group not supported\n", selector); + return -EINVAL; + } + + *groups = pmx_functions[selector].groups; + *num_groups = pmx_functions[selector].ngroups; + return 0; +} + +static int amd_set_mux(struct pinctrl_dev *pctrldev, unsigned int function, unsigned int group) +{ + struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctrldev); + struct device *dev = &gpio_dev->pdev->dev; + struct pin_desc *pd; + int ind, index; + + if (!gpio_dev->iomux_base) + return -EINVAL; + + for (index = 0; index < NSELECTS; index++) { + if (strcmp(gpio_dev->groups[group].name, pmx_functions[function].groups[index])) + continue; + + if (readb(gpio_dev->iomux_base + pmx_functions[function].index) == + FUNCTION_INVALID) { + dev_err(dev, "IOMUX_GPIO 0x%x not present or supported\n", + pmx_functions[function].index); + return -EINVAL; + } + + writeb(index, gpio_dev->iomux_base + pmx_functions[function].index); + + if (index != (readb(gpio_dev->iomux_base + pmx_functions[function].index) & + FUNCTION_MASK)) { + dev_err(dev, "IOMUX_GPIO 0x%x not present or supported\n", + pmx_functions[function].index); + return -EINVAL; + } + + for (ind = 0; ind < gpio_dev->groups[group].npins; ind++) { + if (strncmp(gpio_dev->groups[group].name, "IMX_F", strlen("IMX_F"))) + continue; + + pd = pin_desc_get(gpio_dev->pctrl, gpio_dev->groups[group].pins[ind]); + pd->mux_owner = gpio_dev->groups[group].name; + } + break; + } + + return 0; +} + +static const struct pinmux_ops amd_pmxops = { + .get_functions_count = amd_get_functions_count, + .get_function_name = amd_get_fname, + .get_function_groups = amd_get_groups, + .set_mux = amd_set_mux, +}; + static struct pinctrl_desc amd_pinctrl_desc = { .pins = kerncz_pins, .npins = ARRAY_SIZE(kerncz_pins), .pctlops = &amd_pinctrl_ops, + .pmxops = &amd_pmxops, .confops = &amd_pinconf_ops, .owner = THIS_MODULE, }; +static void amd_get_iomux_res(struct amd_gpio *gpio_dev) +{ + struct pinctrl_desc *desc = &amd_pinctrl_desc; + struct device *dev = &gpio_dev->pdev->dev; + int index; + + index = device_property_match_string(dev, "pinctrl-resource-names", "iomux"); + if (index < 0) { + dev_warn(dev, "failed to get iomux index\n"); + goto out_no_pinmux; + } + + gpio_dev->iomux_base = devm_platform_ioremap_resource(gpio_dev->pdev, index); + if (IS_ERR(gpio_dev->iomux_base)) { + dev_warn(dev, "Failed to get iomux %d io resource\n", index); + goto out_no_pinmux; + } + + return; + +out_no_pinmux: + desc->pmxops = NULL; +} + static int amd_gpio_probe(struct platform_device *pdev) { int ret = 0; @@ -977,17 +1081,12 @@ static int amd_gpio_probe(struct platform_device *pdev) raw_spin_lock_init(&gpio_dev->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { + gpio_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(gpio_dev->base)) { dev_err(&pdev->dev, "Failed to get gpio io resource.\n"); - return -EINVAL; + return PTR_ERR(gpio_dev->base); } - gpio_dev->base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!gpio_dev->base) - return -ENOMEM; - gpio_dev->irq = platform_get_irq(pdev, 0); if (gpio_dev->irq < 0) return gpio_dev->irq; @@ -1020,6 +1119,7 @@ static int amd_gpio_probe(struct platform_device *pdev) gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups); amd_pinctrl_desc.name = dev_name(&pdev->dev); + amd_get_iomux_res(gpio_dev); gpio_dev->pctrl = devm_pinctrl_register(&pdev->dev, &amd_pinctrl_desc, gpio_dev); if (IS_ERR(gpio_dev->pctrl)) { diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h index 1d4317073654..c8635998465d 100644 --- a/drivers/pinctrl/pinctrl-amd.h +++ b/drivers/pinctrl/pinctrl-amd.h @@ -74,23 +74,24 @@ #define CLR_INTR_STAT 0x1UL -struct amd_pingroup { - const char *name; - const unsigned *pins; - unsigned npins; -}; +#define NSELECTS 0x4 + +#define FUNCTION_MASK GENMASK(1, 0) +#define FUNCTION_INVALID GENMASK(7, 0) struct amd_function { const char *name; - const char * const *groups; + const char * const groups[NSELECTS]; unsigned ngroups; + int index; }; struct amd_gpio { raw_spinlock_t lock; void __iomem *base; + void __iomem *iomux_base; - const struct amd_pingroup *groups; + const struct pingroup *groups; u32 ngroups; struct pinctrl_dev *pctrl; struct gpio_chip gc; @@ -288,45 +289,1332 @@ static const struct pinctrl_pin_desc kerncz_pins[] = { PINCTRL_PIN(183, "GPIO_183"), }; -static const unsigned i2c0_pins[] = {145, 146}; -static const unsigned i2c1_pins[] = {147, 148}; -static const unsigned i2c2_pins[] = {113, 114}; -static const unsigned i2c3_pins[] = {19, 20}; +#define AMD_PINS(...) (const unsigned int []){__VA_ARGS__} + +enum amd_functions { + IMX_F0_GPIO0, + IMX_F1_GPIO0, + IMX_F2_GPIO0, + IMX_F3_GPIO0, + IMX_F0_GPIO1, + IMX_F1_GPIO1, + IMX_F2_GPIO1, + IMX_F3_GPIO1, + IMX_F0_GPIO2, + IMX_F1_GPIO2, + IMX_F2_GPIO2, + IMX_F3_GPIO2, + IMX_F0_GPIO3, + IMX_F1_GPIO3, + IMX_F2_GPIO3, + IMX_F3_GPIO3, + IMX_F0_GPIO4, + IMX_F1_GPIO4, + IMX_F2_GPIO4, + IMX_F3_GPIO4, + IMX_F0_GPIO5, + IMX_F1_GPIO5, + IMX_F2_GPIO5, + IMX_F3_GPIO5, + IMX_F0_GPIO6, + IMX_F1_GPIO6, + IMX_F2_GPIO6, + IMX_F3_GPIO6, + IMX_F0_GPIO7, + IMX_F1_GPIO7, + IMX_F2_GPIO7, + IMX_F3_GPIO7, + IMX_F0_GPIO8, + IMX_F1_GPIO8, + IMX_F2_GPIO8, + IMX_F3_GPIO8, + IMX_F0_GPIO9, + IMX_F1_GPIO9, + IMX_F2_GPIO9, + IMX_F3_GPIO9, + IMX_F0_GPIO10, + IMX_F1_GPIO10, + IMX_F2_GPIO10, + IMX_F3_GPIO10, + IMX_F0_GPIO11, + IMX_F1_GPIO11, + IMX_F2_GPIO11, + IMX_F3_GPIO11, + IMX_F0_GPIO12, + IMX_F1_GPIO12, + IMX_F2_GPIO12, + IMX_F3_GPIO12, + IMX_F0_GPIO13, + IMX_F1_GPIO13, + IMX_F2_GPIO13, + IMX_F3_GPIO13, + IMX_F0_GPIO14, + IMX_F1_GPIO14, + IMX_F2_GPIO14, + IMX_F3_GPIO14, + IMX_F0_GPIO15, + IMX_F1_GPIO15, + IMX_F2_GPIO15, + IMX_F3_GPIO15, + IMX_F0_GPIO16, + IMX_F1_GPIO16, + IMX_F2_GPIO16, + IMX_F3_GPIO16, + IMX_F0_GPIO17, + IMX_F1_GPIO17, + IMX_F2_GPIO17, + IMX_F3_GPIO17, + IMX_F0_GPIO18, + IMX_F1_GPIO18, + IMX_F2_GPIO18, + IMX_F3_GPIO18, + IMX_F0_GPIO19, + IMX_F1_GPIO19, + IMX_F2_GPIO19, + IMX_F3_GPIO19, + IMX_F0_GPIO20, + IMX_F1_GPIO20, + IMX_F2_GPIO20, + IMX_F3_GPIO20, + IMX_F0_GPIO21, + IMX_F1_GPIO21, + IMX_F2_GPIO21, + IMX_F3_GPIO21, + IMX_F0_GPIO22, + IMX_F1_GPIO22, + IMX_F2_GPIO22, + IMX_F3_GPIO22, + IMX_F0_GPIO23, + IMX_F1_GPIO23, + IMX_F2_GPIO23, + IMX_F3_GPIO23, + IMX_F0_GPIO24, + IMX_F1_GPIO24, + IMX_F2_GPIO24, + IMX_F3_GPIO24, + IMX_F0_GPIO25, + IMX_F1_GPIO25, + IMX_F2_GPIO25, + IMX_F3_GPIO25, + IMX_F0_GPIO26, + IMX_F1_GPIO26, + IMX_F2_GPIO26, + IMX_F3_GPIO26, + IMX_F0_GPIO27, + IMX_F1_GPIO27, + IMX_F2_GPIO27, + IMX_F3_GPIO27, + IMX_F0_GPIO28, + IMX_F1_GPIO28, + IMX_F2_GPIO28, + IMX_F3_GPIO28, + IMX_F0_GPIO29, + IMX_F1_GPIO29, + IMX_F2_GPIO29, + IMX_F3_GPIO29, + IMX_F0_GPIO30, + IMX_F1_GPIO30, + IMX_F2_GPIO30, + IMX_F3_GPIO30, + IMX_F0_GPIO31, + IMX_F1_GPIO31, + IMX_F2_GPIO31, + IMX_F3_GPIO31, + IMX_F0_GPIO32, + IMX_F1_GPIO32, + IMX_F2_GPIO32, + IMX_F3_GPIO32, + IMX_F0_GPIO33, + IMX_F1_GPIO33, + IMX_F2_GPIO33, + IMX_F3_GPIO33, + IMX_F0_GPIO34, + IMX_F1_GPIO34, + IMX_F2_GPIO34, + IMX_F3_GPIO34, + IMX_F0_GPIO35, + IMX_F1_GPIO35, + IMX_F2_GPIO35, + IMX_F3_GPIO35, + IMX_F0_GPIO36, + IMX_F1_GPIO36, + IMX_F2_GPIO36, + IMX_F3_GPIO36, + IMX_F0_GPIO37, + IMX_F1_GPIO37, + IMX_F2_GPIO37, + IMX_F3_GPIO37, + IMX_F0_GPIO38, + IMX_F1_GPIO38, + IMX_F2_GPIO38, + IMX_F3_GPIO38, + IMX_F0_GPIO39, + IMX_F1_GPIO39, + IMX_F2_GPIO39, + IMX_F3_GPIO39, + IMX_F0_GPIO40, + IMX_F1_GPIO40, + IMX_F2_GPIO40, + IMX_F3_GPIO40, + IMX_F0_GPIO41, + IMX_F1_GPIO41, + IMX_F2_GPIO41, + IMX_F3_GPIO41, + IMX_F0_GPIO42, + IMX_F1_GPIO42, + IMX_F2_GPIO42, + IMX_F3_GPIO42, + IMX_F0_GPIO43, + IMX_F1_GPIO43, + IMX_F2_GPIO43, + IMX_F3_GPIO43, + IMX_F0_GPIO44, + IMX_F1_GPIO44, + IMX_F2_GPIO44, + IMX_F3_GPIO44, + IMX_F0_GPIO45, + IMX_F1_GPIO45, + IMX_F2_GPIO45, + IMX_F3_GPIO45, + IMX_F0_GPIO46, + IMX_F1_GPIO46, + IMX_F2_GPIO46, + IMX_F3_GPIO46, + IMX_F0_GPIO47, + IMX_F1_GPIO47, + IMX_F2_GPIO47, + IMX_F3_GPIO47, + IMX_F0_GPIO48, + IMX_F1_GPIO48, + IMX_F2_GPIO48, + IMX_F3_GPIO48, + IMX_F0_GPIO49, + IMX_F1_GPIO49, + IMX_F2_GPIO49, + IMX_F3_GPIO49, + IMX_F0_GPIO50, + IMX_F1_GPIO50, + IMX_F2_GPIO50, + IMX_F3_GPIO50, + IMX_F0_GPIO51, + IMX_F1_GPIO51, + IMX_F2_GPIO51, + IMX_F3_GPIO51, + IMX_F0_GPIO52, + IMX_F1_GPIO52, + IMX_F2_GPIO52, + IMX_F3_GPIO52, + IMX_F0_GPIO53, + IMX_F1_GPIO53, + IMX_F2_GPIO53, + IMX_F3_GPIO53, + IMX_F0_GPIO54, + IMX_F1_GPIO54, + IMX_F2_GPIO54, + IMX_F3_GPIO54, + IMX_F0_GPIO55, + IMX_F1_GPIO55, + IMX_F2_GPIO55, + IMX_F3_GPIO55, + IMX_F0_GPIO56, + IMX_F1_GPIO56, + IMX_F2_GPIO56, + IMX_F3_GPIO56, + IMX_F0_GPIO57, + IMX_F1_GPIO57, + IMX_F2_GPIO57, + IMX_F3_GPIO57, + IMX_F0_GPIO58, + IMX_F1_GPIO58, + IMX_F2_GPIO58, + IMX_F3_GPIO58, + IMX_F0_GPIO59, + IMX_F1_GPIO59, + IMX_F2_GPIO59, + IMX_F3_GPIO59, + IMX_F0_GPIO60, + IMX_F1_GPIO60, + IMX_F2_GPIO60, + IMX_F3_GPIO60, + IMX_F0_GPIO61, + IMX_F1_GPIO61, + IMX_F2_GPIO61, + IMX_F3_GPIO61, + IMX_F0_GPIO62, + IMX_F1_GPIO62, + IMX_F2_GPIO62, + IMX_F3_GPIO62, + IMX_F0_GPIO64, + IMX_F1_GPIO64, + IMX_F2_GPIO64, + IMX_F3_GPIO64, + IMX_F0_GPIO65, + IMX_F1_GPIO65, + IMX_F2_GPIO65, + IMX_F3_GPIO65, + IMX_F0_GPIO66, + IMX_F1_GPIO66, + IMX_F2_GPIO66, + IMX_F3_GPIO66, + IMX_F0_GPIO67, + IMX_F1_GPIO67, + IMX_F2_GPIO67, + IMX_F3_GPIO67, + IMX_F0_GPIO68, + IMX_F1_GPIO68, + IMX_F2_GPIO68, + IMX_F3_GPIO68, + IMX_F0_GPIO69, + IMX_F1_GPIO69, + IMX_F2_GPIO69, + IMX_F3_GPIO69, + IMX_F0_GPIO70, + IMX_F1_GPIO70, + IMX_F2_GPIO70, + IMX_F3_GPIO70, + IMX_F0_GPIO71, + IMX_F1_GPIO71, + IMX_F2_GPIO71, + IMX_F3_GPIO71, + IMX_F0_GPIO72, + IMX_F1_GPIO72, + IMX_F2_GPIO72, + IMX_F3_GPIO72, + IMX_F0_GPIO73, + IMX_F1_GPIO73, + IMX_F2_GPIO73, + IMX_F3_GPIO73, + IMX_F0_GPIO74, + IMX_F1_GPIO74, + IMX_F2_GPIO74, + IMX_F3_GPIO74, + IMX_F0_GPIO75, + IMX_F1_GPIO75, + IMX_F2_GPIO75, + IMX_F3_GPIO75, + IMX_F0_GPIO76, + IMX_F1_GPIO76, + IMX_F2_GPIO76, + IMX_F3_GPIO76, + IMX_F0_GPIO77, + IMX_F1_GPIO77, + IMX_F2_GPIO77, + IMX_F3_GPIO77, + IMX_F0_GPIO78, + IMX_F1_GPIO78, + IMX_F2_GPIO78, + IMX_F3_GPIO78, + IMX_F0_GPIO79, + IMX_F1_GPIO79, + IMX_F2_GPIO79, + IMX_F3_GPIO79, + IMX_F0_GPIO80, + IMX_F1_GPIO80, + IMX_F2_GPIO80, + IMX_F3_GPIO80, + IMX_F0_GPIO81, + IMX_F1_GPIO81, + IMX_F2_GPIO81, + IMX_F3_GPIO81, + IMX_F0_GPIO82, + IMX_F1_GPIO82, + IMX_F2_GPIO82, + IMX_F3_GPIO82, + IMX_F0_GPIO83, + IMX_F1_GPIO83, + IMX_F2_GPIO83, + IMX_F3_GPIO83, + IMX_F0_GPIO84, + IMX_F1_GPIO84, + IMX_F2_GPIO84, + IMX_F3_GPIO84, + IMX_F0_GPIO85, + IMX_F1_GPIO85, + IMX_F2_GPIO85, + IMX_F3_GPIO85, + IMX_F0_GPIO86, + IMX_F1_GPIO86, + IMX_F2_GPIO86, + IMX_F3_GPIO86, + IMX_F0_GPIO87, + IMX_F1_GPIO87, + IMX_F2_GPIO87, + IMX_F3_GPIO87, + IMX_F0_GPIO88, + IMX_F1_GPIO88, + IMX_F2_GPIO88, + IMX_F3_GPIO88, + IMX_F0_GPIO89, + IMX_F1_GPIO89, + IMX_F2_GPIO89, + IMX_F3_GPIO89, + IMX_F0_GPIO90, + IMX_F1_GPIO90, + IMX_F2_GPIO90, + IMX_F3_GPIO90, + IMX_F0_GPIO91, + IMX_F1_GPIO91, + IMX_F2_GPIO91, + IMX_F3_GPIO91, + IMX_F0_GPIO92, + IMX_F1_GPIO92, + IMX_F2_GPIO92, + IMX_F3_GPIO92, + IMX_F0_GPIO93, + IMX_F1_GPIO93, + IMX_F2_GPIO93, + IMX_F3_GPIO93, + IMX_F0_GPIO94, + IMX_F1_GPIO94, + IMX_F2_GPIO94, + IMX_F3_GPIO94, + IMX_F0_GPIO95, + IMX_F1_GPIO95, + IMX_F2_GPIO95, + IMX_F3_GPIO95, + IMX_F0_GPIO96, + IMX_F1_GPIO96, + IMX_F2_GPIO96, + IMX_F3_GPIO96, + IMX_F0_GPIO97, + IMX_F1_GPIO97, + IMX_F2_GPIO97, + IMX_F3_GPIO97, + IMX_F0_GPIO98, + IMX_F1_GPIO98, + IMX_F2_GPIO98, + IMX_F3_GPIO98, + IMX_F0_GPIO99, + IMX_F1_GPIO99, + IMX_F2_GPIO99, + IMX_F3_GPIO99, + IMX_F0_GPIO100, + IMX_F1_GPIO100, + IMX_F2_GPIO100, + IMX_F3_GPIO100, + IMX_F0_GPIO101, + IMX_F1_GPIO101, + IMX_F2_GPIO101, + IMX_F3_GPIO101, + IMX_F0_GPIO102, + IMX_F1_GPIO102, + IMX_F2_GPIO102, + IMX_F3_GPIO102, + IMX_F0_GPIO103, + IMX_F1_GPIO103, + IMX_F2_GPIO103, + IMX_F3_GPIO103, + IMX_F0_GPIO104, + IMX_F1_GPIO104, + IMX_F2_GPIO104, + IMX_F3_GPIO104, + IMX_F0_GPIO105, + IMX_F1_GPIO105, + IMX_F2_GPIO105, + IMX_F3_GPIO105, + IMX_F0_GPIO106, + IMX_F1_GPIO106, + IMX_F2_GPIO106, + IMX_F3_GPIO106, + IMX_F0_GPIO107, + IMX_F1_GPIO107, + IMX_F2_GPIO107, + IMX_F3_GPIO107, + IMX_F0_GPIO108, + IMX_F1_GPIO108, + IMX_F2_GPIO108, + IMX_F3_GPIO108, + IMX_F0_GPIO109, + IMX_F1_GPIO109, + IMX_F2_GPIO109, + IMX_F3_GPIO109, + IMX_F0_GPIO110, + IMX_F1_GPIO110, + IMX_F2_GPIO110, + IMX_F3_GPIO110, + IMX_F0_GPIO111, + IMX_F1_GPIO111, + IMX_F2_GPIO111, + IMX_F3_GPIO111, + IMX_F0_GPIO112, + IMX_F1_GPIO112, + IMX_F2_GPIO112, + IMX_F3_GPIO112, + IMX_F0_GPIO113, + IMX_F1_GPIO113, + IMX_F2_GPIO113, + IMX_F3_GPIO113, + IMX_F0_GPIO114, + IMX_F1_GPIO114, + IMX_F2_GPIO114, + IMX_F3_GPIO114, + IMX_F0_GPIO115, + IMX_F1_GPIO115, + IMX_F2_GPIO115, + IMX_F3_GPIO115, + IMX_F0_GPIO116, + IMX_F1_GPIO116, + IMX_F2_GPIO116, + IMX_F3_GPIO116, + IMX_F0_GPIO117, + IMX_F1_GPIO117, + IMX_F2_GPIO117, + IMX_F3_GPIO117, + IMX_F0_GPIO118, + IMX_F1_GPIO118, + IMX_F2_GPIO118, + IMX_F3_GPIO118, + IMX_F0_GPIO119, + IMX_F1_GPIO119, + IMX_F2_GPIO119, + IMX_F3_GPIO119, + IMX_F0_GPIO120, + IMX_F1_GPIO120, + IMX_F2_GPIO120, + IMX_F3_GPIO120, + IMX_F0_GPIO121, + IMX_F1_GPIO121, + IMX_F2_GPIO121, + IMX_F3_GPIO121, + IMX_F0_GPIO122, + IMX_F1_GPIO122, + IMX_F2_GPIO122, + IMX_F3_GPIO122, + IMX_F0_GPIO123, + IMX_F1_GPIO123, + IMX_F2_GPIO123, + IMX_F3_GPIO123, + IMX_F0_GPIO124, + IMX_F1_GPIO124, + IMX_F2_GPIO124, + IMX_F3_GPIO124, + IMX_F0_GPIO125, + IMX_F1_GPIO125, + IMX_F2_GPIO125, + IMX_F3_GPIO125, + IMX_F0_GPIO126, + IMX_F1_GPIO126, + IMX_F2_GPIO126, + IMX_F3_GPIO126, + IMX_F0_GPIO127, + IMX_F1_GPIO127, + IMX_F2_GPIO127, + IMX_F3_GPIO127, + IMX_F0_GPIO128, + IMX_F1_GPIO128, + IMX_F2_GPIO128, + IMX_F3_GPIO128, + IMX_F0_GPIO129, + IMX_F1_GPIO129, + IMX_F2_GPIO129, + IMX_F3_GPIO129, + IMX_F0_GPIO130, + IMX_F1_GPIO130, + IMX_F2_GPIO130, + IMX_F3_GPIO130, + IMX_F0_GPIO131, + IMX_F1_GPIO131, + IMX_F2_GPIO131, + IMX_F3_GPIO131, + IMX_F0_GPIO132, + IMX_F1_GPIO132, + IMX_F2_GPIO132, + IMX_F3_GPIO132, + IMX_F0_GPIO133, + IMX_F1_GPIO133, + IMX_F2_GPIO133, + IMX_F3_GPIO133, + IMX_F0_GPIO134, + IMX_F1_GPIO134, + IMX_F2_GPIO134, + IMX_F3_GPIO134, + IMX_F0_GPIO135, + IMX_F1_GPIO135, + IMX_F2_GPIO135, + IMX_F3_GPIO135, + IMX_F0_GPIO136, + IMX_F1_GPIO136, + IMX_F2_GPIO136, + IMX_F3_GPIO136, + IMX_F0_GPIO137, + IMX_F1_GPIO137, + IMX_F2_GPIO137, + IMX_F3_GPIO137, + IMX_F0_GPIO138, + IMX_F1_GPIO138, + IMX_F2_GPIO138, + IMX_F3_GPIO138, + IMX_F0_GPIO139, + IMX_F1_GPIO139, + IMX_F2_GPIO139, + IMX_F3_GPIO139, + IMX_F0_GPIO140, + IMX_F1_GPIO140, + IMX_F2_GPIO140, + IMX_F3_GPIO140, + IMX_F0_GPIO141, + IMX_F1_GPIO141, + IMX_F2_GPIO141, + IMX_F3_GPIO141, + IMX_F0_GPIO142, + IMX_F1_GPIO142, + IMX_F2_GPIO142, + IMX_F3_GPIO142, + IMX_F0_GPIO143, + IMX_F1_GPIO143, + IMX_F2_GPIO143, + IMX_F3_GPIO143, + IMX_F0_GPIO144, + IMX_F1_GPIO144, + IMX_F2_GPIO144, + IMX_F3_GPIO144, +}; + +#define AMD_PINCTRL_FUNC_GRP(_number, _func) \ + [IMX_F##_func##_GPIO##_number] = \ + PINCTRL_PINGROUP("IMX_F"#_func "_GPIO"#_number, AMD_PINS(_number), 1) + +static const struct pingroup kerncz_groups[] = { + AMD_PINCTRL_FUNC_GRP(0, 0), + AMD_PINCTRL_FUNC_GRP(0, 1), + AMD_PINCTRL_FUNC_GRP(0, 2), + AMD_PINCTRL_FUNC_GRP(0, 3), + AMD_PINCTRL_FUNC_GRP(1, 0), + AMD_PINCTRL_FUNC_GRP(1, 1), + AMD_PINCTRL_FUNC_GRP(1, 2), + AMD_PINCTRL_FUNC_GRP(1, 3), + AMD_PINCTRL_FUNC_GRP(2, 0), + AMD_PINCTRL_FUNC_GRP(2, 1), + AMD_PINCTRL_FUNC_GRP(2, 2), + AMD_PINCTRL_FUNC_GRP(2, 3), + AMD_PINCTRL_FUNC_GRP(3, 0), + AMD_PINCTRL_FUNC_GRP(3, 1), + AMD_PINCTRL_FUNC_GRP(3, 2), + AMD_PINCTRL_FUNC_GRP(3, 3), + AMD_PINCTRL_FUNC_GRP(4, 0), + AMD_PINCTRL_FUNC_GRP(4, 1), + AMD_PINCTRL_FUNC_GRP(4, 2), + AMD_PINCTRL_FUNC_GRP(4, 3), + AMD_PINCTRL_FUNC_GRP(5, 0), + AMD_PINCTRL_FUNC_GRP(5, 1), + AMD_PINCTRL_FUNC_GRP(5, 2), + AMD_PINCTRL_FUNC_GRP(5, 3), + AMD_PINCTRL_FUNC_GRP(6, 0), + AMD_PINCTRL_FUNC_GRP(6, 1), + AMD_PINCTRL_FUNC_GRP(6, 2), + AMD_PINCTRL_FUNC_GRP(6, 3), + AMD_PINCTRL_FUNC_GRP(7, 0), + AMD_PINCTRL_FUNC_GRP(7, 1), + AMD_PINCTRL_FUNC_GRP(7, 2), + AMD_PINCTRL_FUNC_GRP(7, 3), + AMD_PINCTRL_FUNC_GRP(8, 0), + AMD_PINCTRL_FUNC_GRP(8, 1), + AMD_PINCTRL_FUNC_GRP(8, 2), + AMD_PINCTRL_FUNC_GRP(8, 3), + AMD_PINCTRL_FUNC_GRP(9, 0), + AMD_PINCTRL_FUNC_GRP(9, 1), + AMD_PINCTRL_FUNC_GRP(9, 2), + AMD_PINCTRL_FUNC_GRP(9, 3), + AMD_PINCTRL_FUNC_GRP(10, 0), + AMD_PINCTRL_FUNC_GRP(10, 1), + AMD_PINCTRL_FUNC_GRP(10, 2), + AMD_PINCTRL_FUNC_GRP(10, 3), + AMD_PINCTRL_FUNC_GRP(11, 0), + AMD_PINCTRL_FUNC_GRP(11, 1), + AMD_PINCTRL_FUNC_GRP(11, 2), + AMD_PINCTRL_FUNC_GRP(11, 3), + AMD_PINCTRL_FUNC_GRP(12, 0), + AMD_PINCTRL_FUNC_GRP(12, 1), + AMD_PINCTRL_FUNC_GRP(12, 2), + AMD_PINCTRL_FUNC_GRP(12, 3), + AMD_PINCTRL_FUNC_GRP(13, 0), + AMD_PINCTRL_FUNC_GRP(13, 1), + AMD_PINCTRL_FUNC_GRP(13, 2), + AMD_PINCTRL_FUNC_GRP(13, 3), + AMD_PINCTRL_FUNC_GRP(14, 0), + AMD_PINCTRL_FUNC_GRP(14, 1), + AMD_PINCTRL_FUNC_GRP(14, 2), + AMD_PINCTRL_FUNC_GRP(14, 3), + AMD_PINCTRL_FUNC_GRP(15, 0), + AMD_PINCTRL_FUNC_GRP(15, 1), + AMD_PINCTRL_FUNC_GRP(15, 2), + AMD_PINCTRL_FUNC_GRP(15, 3), + AMD_PINCTRL_FUNC_GRP(16, 0), + AMD_PINCTRL_FUNC_GRP(16, 1), + AMD_PINCTRL_FUNC_GRP(16, 2), + AMD_PINCTRL_FUNC_GRP(16, 3), + AMD_PINCTRL_FUNC_GRP(17, 0), + AMD_PINCTRL_FUNC_GRP(17, 1), + AMD_PINCTRL_FUNC_GRP(17, 2), + AMD_PINCTRL_FUNC_GRP(17, 3), + AMD_PINCTRL_FUNC_GRP(18, 0), + AMD_PINCTRL_FUNC_GRP(18, 1), + AMD_PINCTRL_FUNC_GRP(18, 2), + AMD_PINCTRL_FUNC_GRP(18, 3), + AMD_PINCTRL_FUNC_GRP(19, 0), + AMD_PINCTRL_FUNC_GRP(19, 1), + AMD_PINCTRL_FUNC_GRP(19, 2), + AMD_PINCTRL_FUNC_GRP(19, 3), + AMD_PINCTRL_FUNC_GRP(20, 0), + AMD_PINCTRL_FUNC_GRP(20, 1), + AMD_PINCTRL_FUNC_GRP(20, 2), + AMD_PINCTRL_FUNC_GRP(20, 3), + AMD_PINCTRL_FUNC_GRP(21, 0), + AMD_PINCTRL_FUNC_GRP(21, 1), + AMD_PINCTRL_FUNC_GRP(21, 2), + AMD_PINCTRL_FUNC_GRP(21, 3), + AMD_PINCTRL_FUNC_GRP(22, 0), + AMD_PINCTRL_FUNC_GRP(22, 1), + AMD_PINCTRL_FUNC_GRP(22, 2), + AMD_PINCTRL_FUNC_GRP(22, 3), + AMD_PINCTRL_FUNC_GRP(23, 0), + AMD_PINCTRL_FUNC_GRP(23, 1), + AMD_PINCTRL_FUNC_GRP(23, 2), + AMD_PINCTRL_FUNC_GRP(23, 3), + AMD_PINCTRL_FUNC_GRP(24, 0), + AMD_PINCTRL_FUNC_GRP(24, 1), + AMD_PINCTRL_FUNC_GRP(24, 2), + AMD_PINCTRL_FUNC_GRP(24, 3), + AMD_PINCTRL_FUNC_GRP(25, 0), + AMD_PINCTRL_FUNC_GRP(25, 1), + AMD_PINCTRL_FUNC_GRP(25, 2), + AMD_PINCTRL_FUNC_GRP(25, 3), + AMD_PINCTRL_FUNC_GRP(26, 0), + AMD_PINCTRL_FUNC_GRP(26, 1), + AMD_PINCTRL_FUNC_GRP(26, 2), + AMD_PINCTRL_FUNC_GRP(26, 3), + AMD_PINCTRL_FUNC_GRP(27, 0), + AMD_PINCTRL_FUNC_GRP(27, 1), + AMD_PINCTRL_FUNC_GRP(27, 2), + AMD_PINCTRL_FUNC_GRP(27, 3), + AMD_PINCTRL_FUNC_GRP(28, 0), + AMD_PINCTRL_FUNC_GRP(28, 1), + AMD_PINCTRL_FUNC_GRP(28, 2), + AMD_PINCTRL_FUNC_GRP(28, 3), + AMD_PINCTRL_FUNC_GRP(29, 0), + AMD_PINCTRL_FUNC_GRP(29, 1), + AMD_PINCTRL_FUNC_GRP(29, 2), + AMD_PINCTRL_FUNC_GRP(29, 3), + AMD_PINCTRL_FUNC_GRP(30, 0), + AMD_PINCTRL_FUNC_GRP(30, 1), + AMD_PINCTRL_FUNC_GRP(30, 2), + AMD_PINCTRL_FUNC_GRP(30, 3), + AMD_PINCTRL_FUNC_GRP(31, 0), + AMD_PINCTRL_FUNC_GRP(31, 1), + AMD_PINCTRL_FUNC_GRP(31, 2), + AMD_PINCTRL_FUNC_GRP(31, 3), + AMD_PINCTRL_FUNC_GRP(32, 0), + AMD_PINCTRL_FUNC_GRP(32, 1), + AMD_PINCTRL_FUNC_GRP(32, 2), + AMD_PINCTRL_FUNC_GRP(32, 3), + AMD_PINCTRL_FUNC_GRP(33, 0), + AMD_PINCTRL_FUNC_GRP(33, 1), + AMD_PINCTRL_FUNC_GRP(33, 2), + AMD_PINCTRL_FUNC_GRP(33, 3), + AMD_PINCTRL_FUNC_GRP(34, 0), + AMD_PINCTRL_FUNC_GRP(34, 1), + AMD_PINCTRL_FUNC_GRP(34, 2), + AMD_PINCTRL_FUNC_GRP(34, 3), + AMD_PINCTRL_FUNC_GRP(35, 0), + AMD_PINCTRL_FUNC_GRP(35, 1), + AMD_PINCTRL_FUNC_GRP(35, 2), + AMD_PINCTRL_FUNC_GRP(35, 3), + AMD_PINCTRL_FUNC_GRP(36, 0), + AMD_PINCTRL_FUNC_GRP(36, 1), + AMD_PINCTRL_FUNC_GRP(36, 2), + AMD_PINCTRL_FUNC_GRP(36, 3), + AMD_PINCTRL_FUNC_GRP(37, 0), + AMD_PINCTRL_FUNC_GRP(37, 1), + AMD_PINCTRL_FUNC_GRP(37, 2), + AMD_PINCTRL_FUNC_GRP(37, 3), + AMD_PINCTRL_FUNC_GRP(38, 0), + AMD_PINCTRL_FUNC_GRP(38, 1), + AMD_PINCTRL_FUNC_GRP(38, 2), + AMD_PINCTRL_FUNC_GRP(38, 3), + AMD_PINCTRL_FUNC_GRP(39, 0), + AMD_PINCTRL_FUNC_GRP(39, 1), + AMD_PINCTRL_FUNC_GRP(39, 2), + AMD_PINCTRL_FUNC_GRP(39, 3), + AMD_PINCTRL_FUNC_GRP(40, 0), + AMD_PINCTRL_FUNC_GRP(40, 1), + AMD_PINCTRL_FUNC_GRP(40, 2), + AMD_PINCTRL_FUNC_GRP(40, 3), + AMD_PINCTRL_FUNC_GRP(41, 0), + AMD_PINCTRL_FUNC_GRP(41, 1), + AMD_PINCTRL_FUNC_GRP(41, 2), + AMD_PINCTRL_FUNC_GRP(41, 3), + AMD_PINCTRL_FUNC_GRP(42, 0), + AMD_PINCTRL_FUNC_GRP(42, 1), + AMD_PINCTRL_FUNC_GRP(42, 2), + AMD_PINCTRL_FUNC_GRP(42, 3), + AMD_PINCTRL_FUNC_GRP(43, 0), + AMD_PINCTRL_FUNC_GRP(43, 1), + AMD_PINCTRL_FUNC_GRP(43, 2), + AMD_PINCTRL_FUNC_GRP(43, 3), + AMD_PINCTRL_FUNC_GRP(44, 0), + AMD_PINCTRL_FUNC_GRP(44, 1), + AMD_PINCTRL_FUNC_GRP(44, 2), + AMD_PINCTRL_FUNC_GRP(44, 3), + AMD_PINCTRL_FUNC_GRP(45, 0), + AMD_PINCTRL_FUNC_GRP(45, 1), + AMD_PINCTRL_FUNC_GRP(45, 2), + AMD_PINCTRL_FUNC_GRP(45, 3), + AMD_PINCTRL_FUNC_GRP(46, 0), + AMD_PINCTRL_FUNC_GRP(46, 1), + AMD_PINCTRL_FUNC_GRP(46, 2), + AMD_PINCTRL_FUNC_GRP(46, 3), + AMD_PINCTRL_FUNC_GRP(47, 0), + AMD_PINCTRL_FUNC_GRP(47, 1), + AMD_PINCTRL_FUNC_GRP(47, 2), + AMD_PINCTRL_FUNC_GRP(47, 3), + AMD_PINCTRL_FUNC_GRP(48, 0), + AMD_PINCTRL_FUNC_GRP(48, 1), + AMD_PINCTRL_FUNC_GRP(48, 2), + AMD_PINCTRL_FUNC_GRP(48, 3), + AMD_PINCTRL_FUNC_GRP(49, 0), + AMD_PINCTRL_FUNC_GRP(49, 1), + AMD_PINCTRL_FUNC_GRP(49, 2), + AMD_PINCTRL_FUNC_GRP(49, 3), + AMD_PINCTRL_FUNC_GRP(50, 0), + AMD_PINCTRL_FUNC_GRP(50, 1), + AMD_PINCTRL_FUNC_GRP(50, 2), + AMD_PINCTRL_FUNC_GRP(50, 3), + AMD_PINCTRL_FUNC_GRP(51, 0), + AMD_PINCTRL_FUNC_GRP(51, 1), + AMD_PINCTRL_FUNC_GRP(51, 2), + AMD_PINCTRL_FUNC_GRP(51, 3), + AMD_PINCTRL_FUNC_GRP(52, 0), + AMD_PINCTRL_FUNC_GRP(52, 1), + AMD_PINCTRL_FUNC_GRP(52, 2), + AMD_PINCTRL_FUNC_GRP(52, 3), + AMD_PINCTRL_FUNC_GRP(53, 0), + AMD_PINCTRL_FUNC_GRP(53, 1), + AMD_PINCTRL_FUNC_GRP(53, 2), + AMD_PINCTRL_FUNC_GRP(53, 3), + AMD_PINCTRL_FUNC_GRP(54, 0), + AMD_PINCTRL_FUNC_GRP(54, 1), + AMD_PINCTRL_FUNC_GRP(54, 2), + AMD_PINCTRL_FUNC_GRP(54, 3), + AMD_PINCTRL_FUNC_GRP(55, 0), + AMD_PINCTRL_FUNC_GRP(55, 1), + AMD_PINCTRL_FUNC_GRP(55, 2), + AMD_PINCTRL_FUNC_GRP(55, 3), + AMD_PINCTRL_FUNC_GRP(56, 0), + AMD_PINCTRL_FUNC_GRP(56, 1), + AMD_PINCTRL_FUNC_GRP(56, 2), + AMD_PINCTRL_FUNC_GRP(56, 3), + AMD_PINCTRL_FUNC_GRP(57, 0), + AMD_PINCTRL_FUNC_GRP(57, 1), + AMD_PINCTRL_FUNC_GRP(57, 2), + AMD_PINCTRL_FUNC_GRP(57, 3), + AMD_PINCTRL_FUNC_GRP(58, 0), + AMD_PINCTRL_FUNC_GRP(58, 1), + AMD_PINCTRL_FUNC_GRP(58, 2), + AMD_PINCTRL_FUNC_GRP(58, 3), + AMD_PINCTRL_FUNC_GRP(59, 0), + AMD_PINCTRL_FUNC_GRP(59, 1), + AMD_PINCTRL_FUNC_GRP(59, 2), + AMD_PINCTRL_FUNC_GRP(59, 3), + AMD_PINCTRL_FUNC_GRP(60, 0), + AMD_PINCTRL_FUNC_GRP(60, 1), + AMD_PINCTRL_FUNC_GRP(60, 2), + AMD_PINCTRL_FUNC_GRP(60, 3), + AMD_PINCTRL_FUNC_GRP(61, 0), + AMD_PINCTRL_FUNC_GRP(61, 1), + AMD_PINCTRL_FUNC_GRP(61, 2), + AMD_PINCTRL_FUNC_GRP(61, 3), + AMD_PINCTRL_FUNC_GRP(62, 0), + AMD_PINCTRL_FUNC_GRP(62, 1), + AMD_PINCTRL_FUNC_GRP(62, 2), + AMD_PINCTRL_FUNC_GRP(62, 3), + AMD_PINCTRL_FUNC_GRP(64, 0), + AMD_PINCTRL_FUNC_GRP(64, 1), + AMD_PINCTRL_FUNC_GRP(64, 2), + AMD_PINCTRL_FUNC_GRP(64, 3), + AMD_PINCTRL_FUNC_GRP(65, 0), + AMD_PINCTRL_FUNC_GRP(65, 1), + AMD_PINCTRL_FUNC_GRP(65, 2), + AMD_PINCTRL_FUNC_GRP(65, 3), + AMD_PINCTRL_FUNC_GRP(66, 0), + AMD_PINCTRL_FUNC_GRP(66, 1), + AMD_PINCTRL_FUNC_GRP(66, 2), + AMD_PINCTRL_FUNC_GRP(66, 3), + AMD_PINCTRL_FUNC_GRP(67, 0), + AMD_PINCTRL_FUNC_GRP(67, 1), + AMD_PINCTRL_FUNC_GRP(67, 2), + AMD_PINCTRL_FUNC_GRP(67, 3), + AMD_PINCTRL_FUNC_GRP(68, 0), + AMD_PINCTRL_FUNC_GRP(68, 1), + AMD_PINCTRL_FUNC_GRP(68, 2), + AMD_PINCTRL_FUNC_GRP(68, 3), + AMD_PINCTRL_FUNC_GRP(69, 0), + AMD_PINCTRL_FUNC_GRP(69, 1), + AMD_PINCTRL_FUNC_GRP(69, 2), + AMD_PINCTRL_FUNC_GRP(69, 3), + AMD_PINCTRL_FUNC_GRP(70, 0), + AMD_PINCTRL_FUNC_GRP(70, 1), + AMD_PINCTRL_FUNC_GRP(70, 2), + AMD_PINCTRL_FUNC_GRP(70, 3), + AMD_PINCTRL_FUNC_GRP(71, 0), + AMD_PINCTRL_FUNC_GRP(71, 1), + AMD_PINCTRL_FUNC_GRP(71, 2), + AMD_PINCTRL_FUNC_GRP(71, 3), + AMD_PINCTRL_FUNC_GRP(72, 0), + AMD_PINCTRL_FUNC_GRP(72, 1), + AMD_PINCTRL_FUNC_GRP(72, 2), + AMD_PINCTRL_FUNC_GRP(72, 3), + AMD_PINCTRL_FUNC_GRP(73, 0), + AMD_PINCTRL_FUNC_GRP(73, 1), + AMD_PINCTRL_FUNC_GRP(73, 2), + AMD_PINCTRL_FUNC_GRP(73, 3), + AMD_PINCTRL_FUNC_GRP(74, 0), + AMD_PINCTRL_FUNC_GRP(74, 1), + AMD_PINCTRL_FUNC_GRP(74, 2), + AMD_PINCTRL_FUNC_GRP(74, 3), + AMD_PINCTRL_FUNC_GRP(75, 0), + AMD_PINCTRL_FUNC_GRP(75, 1), + AMD_PINCTRL_FUNC_GRP(75, 2), + AMD_PINCTRL_FUNC_GRP(75, 3), + AMD_PINCTRL_FUNC_GRP(76, 0), + AMD_PINCTRL_FUNC_GRP(76, 1), + AMD_PINCTRL_FUNC_GRP(76, 2), + AMD_PINCTRL_FUNC_GRP(76, 3), + AMD_PINCTRL_FUNC_GRP(77, 0), + AMD_PINCTRL_FUNC_GRP(77, 1), + AMD_PINCTRL_FUNC_GRP(77, 2), + AMD_PINCTRL_FUNC_GRP(77, 3), + AMD_PINCTRL_FUNC_GRP(78, 0), + AMD_PINCTRL_FUNC_GRP(78, 1), + AMD_PINCTRL_FUNC_GRP(78, 2), + AMD_PINCTRL_FUNC_GRP(78, 3), + AMD_PINCTRL_FUNC_GRP(79, 0), + AMD_PINCTRL_FUNC_GRP(79, 1), + AMD_PINCTRL_FUNC_GRP(79, 2), + AMD_PINCTRL_FUNC_GRP(79, 3), + AMD_PINCTRL_FUNC_GRP(80, 0), + AMD_PINCTRL_FUNC_GRP(80, 1), + AMD_PINCTRL_FUNC_GRP(80, 2), + AMD_PINCTRL_FUNC_GRP(80, 3), + AMD_PINCTRL_FUNC_GRP(81, 0), + AMD_PINCTRL_FUNC_GRP(81, 1), + AMD_PINCTRL_FUNC_GRP(81, 2), + AMD_PINCTRL_FUNC_GRP(81, 3), + AMD_PINCTRL_FUNC_GRP(82, 0), + AMD_PINCTRL_FUNC_GRP(82, 1), + AMD_PINCTRL_FUNC_GRP(82, 2), + AMD_PINCTRL_FUNC_GRP(82, 3), + AMD_PINCTRL_FUNC_GRP(83, 0), + AMD_PINCTRL_FUNC_GRP(83, 1), + AMD_PINCTRL_FUNC_GRP(83, 2), + AMD_PINCTRL_FUNC_GRP(83, 3), + AMD_PINCTRL_FUNC_GRP(84, 0), + AMD_PINCTRL_FUNC_GRP(84, 1), + AMD_PINCTRL_FUNC_GRP(84, 2), + AMD_PINCTRL_FUNC_GRP(84, 3), + AMD_PINCTRL_FUNC_GRP(85, 0), + AMD_PINCTRL_FUNC_GRP(85, 1), + AMD_PINCTRL_FUNC_GRP(85, 2), + AMD_PINCTRL_FUNC_GRP(85, 3), + AMD_PINCTRL_FUNC_GRP(86, 0), + AMD_PINCTRL_FUNC_GRP(86, 1), + AMD_PINCTRL_FUNC_GRP(86, 2), + AMD_PINCTRL_FUNC_GRP(86, 3), + AMD_PINCTRL_FUNC_GRP(87, 0), + AMD_PINCTRL_FUNC_GRP(87, 1), + AMD_PINCTRL_FUNC_GRP(87, 2), + AMD_PINCTRL_FUNC_GRP(87, 3), + AMD_PINCTRL_FUNC_GRP(88, 0), + AMD_PINCTRL_FUNC_GRP(88, 1), + AMD_PINCTRL_FUNC_GRP(88, 2), + AMD_PINCTRL_FUNC_GRP(88, 3), + AMD_PINCTRL_FUNC_GRP(89, 0), + AMD_PINCTRL_FUNC_GRP(89, 1), + AMD_PINCTRL_FUNC_GRP(89, 2), + AMD_PINCTRL_FUNC_GRP(89, 3), + AMD_PINCTRL_FUNC_GRP(90, 0), + AMD_PINCTRL_FUNC_GRP(90, 1), + AMD_PINCTRL_FUNC_GRP(90, 2), + AMD_PINCTRL_FUNC_GRP(90, 3), + AMD_PINCTRL_FUNC_GRP(91, 0), + AMD_PINCTRL_FUNC_GRP(91, 1), + AMD_PINCTRL_FUNC_GRP(91, 2), + AMD_PINCTRL_FUNC_GRP(91, 3), + AMD_PINCTRL_FUNC_GRP(92, 0), + AMD_PINCTRL_FUNC_GRP(92, 1), + AMD_PINCTRL_FUNC_GRP(92, 2), + AMD_PINCTRL_FUNC_GRP(92, 3), + AMD_PINCTRL_FUNC_GRP(93, 0), + AMD_PINCTRL_FUNC_GRP(93, 1), + AMD_PINCTRL_FUNC_GRP(93, 2), + AMD_PINCTRL_FUNC_GRP(93, 3), + AMD_PINCTRL_FUNC_GRP(94, 0), + AMD_PINCTRL_FUNC_GRP(94, 1), + AMD_PINCTRL_FUNC_GRP(94, 2), + AMD_PINCTRL_FUNC_GRP(94, 3), + AMD_PINCTRL_FUNC_GRP(95, 0), + AMD_PINCTRL_FUNC_GRP(95, 1), + AMD_PINCTRL_FUNC_GRP(95, 2), + AMD_PINCTRL_FUNC_GRP(95, 3), + AMD_PINCTRL_FUNC_GRP(96, 0), + AMD_PINCTRL_FUNC_GRP(96, 1), + AMD_PINCTRL_FUNC_GRP(96, 2), + AMD_PINCTRL_FUNC_GRP(96, 3), + AMD_PINCTRL_FUNC_GRP(97, 0), + AMD_PINCTRL_FUNC_GRP(97, 1), + AMD_PINCTRL_FUNC_GRP(97, 2), + AMD_PINCTRL_FUNC_GRP(97, 3), + AMD_PINCTRL_FUNC_GRP(98, 0), + AMD_PINCTRL_FUNC_GRP(98, 1), + AMD_PINCTRL_FUNC_GRP(98, 2), + AMD_PINCTRL_FUNC_GRP(98, 3), + AMD_PINCTRL_FUNC_GRP(99, 0), + AMD_PINCTRL_FUNC_GRP(99, 1), + AMD_PINCTRL_FUNC_GRP(99, 2), + AMD_PINCTRL_FUNC_GRP(99, 3), + AMD_PINCTRL_FUNC_GRP(100, 0), + AMD_PINCTRL_FUNC_GRP(100, 1), + AMD_PINCTRL_FUNC_GRP(100, 2), + AMD_PINCTRL_FUNC_GRP(100, 3), + AMD_PINCTRL_FUNC_GRP(101, 0), + AMD_PINCTRL_FUNC_GRP(101, 1), + AMD_PINCTRL_FUNC_GRP(101, 2), + AMD_PINCTRL_FUNC_GRP(101, 3), + AMD_PINCTRL_FUNC_GRP(102, 0), + AMD_PINCTRL_FUNC_GRP(102, 1), + AMD_PINCTRL_FUNC_GRP(102, 2), + AMD_PINCTRL_FUNC_GRP(102, 3), + AMD_PINCTRL_FUNC_GRP(103, 0), + AMD_PINCTRL_FUNC_GRP(103, 1), + AMD_PINCTRL_FUNC_GRP(103, 2), + AMD_PINCTRL_FUNC_GRP(103, 3), + AMD_PINCTRL_FUNC_GRP(104, 0), + AMD_PINCTRL_FUNC_GRP(104, 1), + AMD_PINCTRL_FUNC_GRP(104, 2), + AMD_PINCTRL_FUNC_GRP(104, 3), + AMD_PINCTRL_FUNC_GRP(105, 0), + AMD_PINCTRL_FUNC_GRP(105, 1), + AMD_PINCTRL_FUNC_GRP(105, 2), + AMD_PINCTRL_FUNC_GRP(105, 3), + AMD_PINCTRL_FUNC_GRP(106, 0), + AMD_PINCTRL_FUNC_GRP(106, 1), + AMD_PINCTRL_FUNC_GRP(106, 2), + AMD_PINCTRL_FUNC_GRP(106, 3), + AMD_PINCTRL_FUNC_GRP(107, 0), + AMD_PINCTRL_FUNC_GRP(107, 1), + AMD_PINCTRL_FUNC_GRP(107, 2), + AMD_PINCTRL_FUNC_GRP(107, 3), + AMD_PINCTRL_FUNC_GRP(108, 0), + AMD_PINCTRL_FUNC_GRP(108, 1), + AMD_PINCTRL_FUNC_GRP(108, 2), + AMD_PINCTRL_FUNC_GRP(108, 3), + AMD_PINCTRL_FUNC_GRP(109, 0), + AMD_PINCTRL_FUNC_GRP(109, 1), + AMD_PINCTRL_FUNC_GRP(109, 2), + AMD_PINCTRL_FUNC_GRP(109, 3), + AMD_PINCTRL_FUNC_GRP(110, 0), + AMD_PINCTRL_FUNC_GRP(110, 1), + AMD_PINCTRL_FUNC_GRP(110, 2), + AMD_PINCTRL_FUNC_GRP(110, 3), + AMD_PINCTRL_FUNC_GRP(111, 0), + AMD_PINCTRL_FUNC_GRP(111, 1), + AMD_PINCTRL_FUNC_GRP(111, 2), + AMD_PINCTRL_FUNC_GRP(111, 3), + AMD_PINCTRL_FUNC_GRP(112, 0), + AMD_PINCTRL_FUNC_GRP(112, 1), + AMD_PINCTRL_FUNC_GRP(112, 2), + AMD_PINCTRL_FUNC_GRP(112, 3), + AMD_PINCTRL_FUNC_GRP(113, 0), + AMD_PINCTRL_FUNC_GRP(113, 1), + AMD_PINCTRL_FUNC_GRP(113, 2), + AMD_PINCTRL_FUNC_GRP(113, 3), + AMD_PINCTRL_FUNC_GRP(114, 0), + AMD_PINCTRL_FUNC_GRP(114, 1), + AMD_PINCTRL_FUNC_GRP(114, 2), + AMD_PINCTRL_FUNC_GRP(114, 3), + AMD_PINCTRL_FUNC_GRP(115, 0), + AMD_PINCTRL_FUNC_GRP(115, 1), + AMD_PINCTRL_FUNC_GRP(115, 2), + AMD_PINCTRL_FUNC_GRP(115, 3), + AMD_PINCTRL_FUNC_GRP(116, 0), + AMD_PINCTRL_FUNC_GRP(116, 1), + AMD_PINCTRL_FUNC_GRP(116, 2), + AMD_PINCTRL_FUNC_GRP(116, 3), + AMD_PINCTRL_FUNC_GRP(117, 0), + AMD_PINCTRL_FUNC_GRP(117, 1), + AMD_PINCTRL_FUNC_GRP(117, 2), + AMD_PINCTRL_FUNC_GRP(117, 3), + AMD_PINCTRL_FUNC_GRP(118, 0), + AMD_PINCTRL_FUNC_GRP(118, 1), + AMD_PINCTRL_FUNC_GRP(118, 2), + AMD_PINCTRL_FUNC_GRP(118, 3), + AMD_PINCTRL_FUNC_GRP(119, 0), + AMD_PINCTRL_FUNC_GRP(119, 1), + AMD_PINCTRL_FUNC_GRP(119, 2), + AMD_PINCTRL_FUNC_GRP(119, 3), + AMD_PINCTRL_FUNC_GRP(120, 0), + AMD_PINCTRL_FUNC_GRP(120, 1), + AMD_PINCTRL_FUNC_GRP(120, 2), + AMD_PINCTRL_FUNC_GRP(120, 3), + AMD_PINCTRL_FUNC_GRP(121, 0), + AMD_PINCTRL_FUNC_GRP(121, 1), + AMD_PINCTRL_FUNC_GRP(121, 2), + AMD_PINCTRL_FUNC_GRP(121, 3), + AMD_PINCTRL_FUNC_GRP(122, 0), + AMD_PINCTRL_FUNC_GRP(122, 1), + AMD_PINCTRL_FUNC_GRP(122, 2), + AMD_PINCTRL_FUNC_GRP(122, 3), + AMD_PINCTRL_FUNC_GRP(123, 0), + AMD_PINCTRL_FUNC_GRP(123, 1), + AMD_PINCTRL_FUNC_GRP(123, 2), + AMD_PINCTRL_FUNC_GRP(123, 3), + AMD_PINCTRL_FUNC_GRP(124, 0), + AMD_PINCTRL_FUNC_GRP(124, 1), + AMD_PINCTRL_FUNC_GRP(124, 2), + AMD_PINCTRL_FUNC_GRP(124, 3), + AMD_PINCTRL_FUNC_GRP(125, 0), + AMD_PINCTRL_FUNC_GRP(125, 1), + AMD_PINCTRL_FUNC_GRP(125, 2), + AMD_PINCTRL_FUNC_GRP(125, 3), + AMD_PINCTRL_FUNC_GRP(126, 0), + AMD_PINCTRL_FUNC_GRP(126, 1), + AMD_PINCTRL_FUNC_GRP(126, 2), + AMD_PINCTRL_FUNC_GRP(126, 3), + AMD_PINCTRL_FUNC_GRP(127, 0), + AMD_PINCTRL_FUNC_GRP(127, 1), + AMD_PINCTRL_FUNC_GRP(127, 2), + AMD_PINCTRL_FUNC_GRP(127, 3), + AMD_PINCTRL_FUNC_GRP(128, 0), + AMD_PINCTRL_FUNC_GRP(128, 1), + AMD_PINCTRL_FUNC_GRP(128, 2), + AMD_PINCTRL_FUNC_GRP(128, 3), + AMD_PINCTRL_FUNC_GRP(129, 0), + AMD_PINCTRL_FUNC_GRP(129, 1), + AMD_PINCTRL_FUNC_GRP(129, 2), + AMD_PINCTRL_FUNC_GRP(129, 3), + AMD_PINCTRL_FUNC_GRP(130, 0), + AMD_PINCTRL_FUNC_GRP(130, 1), + AMD_PINCTRL_FUNC_GRP(130, 2), + AMD_PINCTRL_FUNC_GRP(130, 3), + AMD_PINCTRL_FUNC_GRP(131, 0), + AMD_PINCTRL_FUNC_GRP(131, 1), + AMD_PINCTRL_FUNC_GRP(131, 2), + AMD_PINCTRL_FUNC_GRP(131, 3), + AMD_PINCTRL_FUNC_GRP(132, 0), + AMD_PINCTRL_FUNC_GRP(132, 1), + AMD_PINCTRL_FUNC_GRP(132, 2), + AMD_PINCTRL_FUNC_GRP(132, 3), + AMD_PINCTRL_FUNC_GRP(133, 0), + AMD_PINCTRL_FUNC_GRP(133, 1), + AMD_PINCTRL_FUNC_GRP(133, 2), + AMD_PINCTRL_FUNC_GRP(133, 3), + AMD_PINCTRL_FUNC_GRP(134, 0), + AMD_PINCTRL_FUNC_GRP(134, 1), + AMD_PINCTRL_FUNC_GRP(134, 2), + AMD_PINCTRL_FUNC_GRP(134, 3), + AMD_PINCTRL_FUNC_GRP(135, 0), + AMD_PINCTRL_FUNC_GRP(135, 1), + AMD_PINCTRL_FUNC_GRP(135, 2), + AMD_PINCTRL_FUNC_GRP(135, 3), + AMD_PINCTRL_FUNC_GRP(136, 0), + AMD_PINCTRL_FUNC_GRP(136, 1), + AMD_PINCTRL_FUNC_GRP(136, 2), + AMD_PINCTRL_FUNC_GRP(136, 3), + AMD_PINCTRL_FUNC_GRP(137, 0), + AMD_PINCTRL_FUNC_GRP(137, 1), + AMD_PINCTRL_FUNC_GRP(137, 2), + AMD_PINCTRL_FUNC_GRP(137, 3), + AMD_PINCTRL_FUNC_GRP(138, 0), + AMD_PINCTRL_FUNC_GRP(138, 1), + AMD_PINCTRL_FUNC_GRP(138, 2), + AMD_PINCTRL_FUNC_GRP(138, 3), + AMD_PINCTRL_FUNC_GRP(139, 0), + AMD_PINCTRL_FUNC_GRP(139, 1), + AMD_PINCTRL_FUNC_GRP(139, 2), + AMD_PINCTRL_FUNC_GRP(139, 3), + AMD_PINCTRL_FUNC_GRP(140, 0), + AMD_PINCTRL_FUNC_GRP(140, 1), + AMD_PINCTRL_FUNC_GRP(140, 2), + AMD_PINCTRL_FUNC_GRP(140, 3), + AMD_PINCTRL_FUNC_GRP(141, 0), + AMD_PINCTRL_FUNC_GRP(141, 1), + AMD_PINCTRL_FUNC_GRP(141, 2), + AMD_PINCTRL_FUNC_GRP(141, 3), + AMD_PINCTRL_FUNC_GRP(142, 0), + AMD_PINCTRL_FUNC_GRP(142, 1), + AMD_PINCTRL_FUNC_GRP(142, 2), + AMD_PINCTRL_FUNC_GRP(142, 3), + AMD_PINCTRL_FUNC_GRP(143, 0), + AMD_PINCTRL_FUNC_GRP(143, 1), + AMD_PINCTRL_FUNC_GRP(143, 2), + AMD_PINCTRL_FUNC_GRP(143, 3), + AMD_PINCTRL_FUNC_GRP(144, 0), + AMD_PINCTRL_FUNC_GRP(144, 1), + AMD_PINCTRL_FUNC_GRP(144, 2), + AMD_PINCTRL_FUNC_GRP(144, 3), + + PINCTRL_PINGROUP("i2c0", AMD_PINS(145, 146), 2), + PINCTRL_PINGROUP("i2c1", AMD_PINS(147, 148), 2), + PINCTRL_PINGROUP("i2c2", AMD_PINS(113, 114), 2), + PINCTRL_PINGROUP("i2c3", AMD_PINS(19, 20), 2), + PINCTRL_PINGROUP("uart0", AMD_PINS(135, 136, 137, 138, 139), 5), + PINCTRL_PINGROUP("uart1", AMD_PINS(140, 141, 142, 143, 144), 5), +}; -static const unsigned uart0_pins[] = {135, 136, 137, 138, 139}; -static const unsigned uart1_pins[] = {140, 141, 142, 143, 144}; +#define AMD_PMUX_FUNC(_number) { \ + .name = "iomux_gpio_"#_number, \ + .groups = { \ + "IMX_F0_GPIO"#_number, "IMX_F1_GPIO"#_number, \ + "IMX_F2_GPIO"#_number, "IMX_F3_GPIO"#_number, \ + }, \ + .index = _number, \ + .ngroups = NSELECTS, \ +} -static const struct amd_pingroup kerncz_groups[] = { - { - .name = "i2c0", - .pins = i2c0_pins, - .npins = 2, - }, - { - .name = "i2c1", - .pins = i2c1_pins, - .npins = 2, - }, - { - .name = "i2c2", - .pins = i2c2_pins, - .npins = 2, - }, - { - .name = "i2c3", - .pins = i2c3_pins, - .npins = 2, - }, - { - .name = "uart0", - .pins = uart0_pins, - .npins = 5, - }, - { - .name = "uart1", - .pins = uart1_pins, - .npins = 5, - }, +static const struct amd_function pmx_functions[] = { + AMD_PMUX_FUNC(0), + AMD_PMUX_FUNC(1), + AMD_PMUX_FUNC(2), + AMD_PMUX_FUNC(3), + AMD_PMUX_FUNC(4), + AMD_PMUX_FUNC(5), + AMD_PMUX_FUNC(6), + AMD_PMUX_FUNC(7), + AMD_PMUX_FUNC(8), + AMD_PMUX_FUNC(9), + AMD_PMUX_FUNC(10), + AMD_PMUX_FUNC(11), + AMD_PMUX_FUNC(12), + AMD_PMUX_FUNC(13), + AMD_PMUX_FUNC(14), + AMD_PMUX_FUNC(15), + AMD_PMUX_FUNC(16), + AMD_PMUX_FUNC(17), + AMD_PMUX_FUNC(18), + AMD_PMUX_FUNC(19), + AMD_PMUX_FUNC(20), + AMD_PMUX_FUNC(21), + AMD_PMUX_FUNC(22), + AMD_PMUX_FUNC(23), + AMD_PMUX_FUNC(24), + AMD_PMUX_FUNC(25), + AMD_PMUX_FUNC(26), + AMD_PMUX_FUNC(27), + AMD_PMUX_FUNC(28), + AMD_PMUX_FUNC(29), + AMD_PMUX_FUNC(30), + AMD_PMUX_FUNC(31), + AMD_PMUX_FUNC(32), + AMD_PMUX_FUNC(33), + AMD_PMUX_FUNC(34), + AMD_PMUX_FUNC(35), + AMD_PMUX_FUNC(36), + AMD_PMUX_FUNC(37), + AMD_PMUX_FUNC(38), + AMD_PMUX_FUNC(39), + AMD_PMUX_FUNC(40), + AMD_PMUX_FUNC(41), + AMD_PMUX_FUNC(42), + AMD_PMUX_FUNC(43), + AMD_PMUX_FUNC(44), + AMD_PMUX_FUNC(45), + AMD_PMUX_FUNC(46), + AMD_PMUX_FUNC(47), + AMD_PMUX_FUNC(48), + AMD_PMUX_FUNC(49), + AMD_PMUX_FUNC(50), + AMD_PMUX_FUNC(51), + AMD_PMUX_FUNC(52), + AMD_PMUX_FUNC(53), + AMD_PMUX_FUNC(54), + AMD_PMUX_FUNC(55), + AMD_PMUX_FUNC(56), + AMD_PMUX_FUNC(57), + AMD_PMUX_FUNC(58), + AMD_PMUX_FUNC(59), + AMD_PMUX_FUNC(60), + AMD_PMUX_FUNC(61), + AMD_PMUX_FUNC(62), + AMD_PMUX_FUNC(64), + AMD_PMUX_FUNC(65), + AMD_PMUX_FUNC(66), + AMD_PMUX_FUNC(67), + AMD_PMUX_FUNC(68), + AMD_PMUX_FUNC(69), + AMD_PMUX_FUNC(70), + AMD_PMUX_FUNC(71), + AMD_PMUX_FUNC(72), + AMD_PMUX_FUNC(73), + AMD_PMUX_FUNC(74), + AMD_PMUX_FUNC(75), + AMD_PMUX_FUNC(76), + AMD_PMUX_FUNC(77), + AMD_PMUX_FUNC(78), + AMD_PMUX_FUNC(79), + AMD_PMUX_FUNC(80), + AMD_PMUX_FUNC(81), + AMD_PMUX_FUNC(82), + AMD_PMUX_FUNC(83), + AMD_PMUX_FUNC(84), + AMD_PMUX_FUNC(85), + AMD_PMUX_FUNC(86), + AMD_PMUX_FUNC(87), + AMD_PMUX_FUNC(88), + AMD_PMUX_FUNC(89), + AMD_PMUX_FUNC(90), + AMD_PMUX_FUNC(91), + AMD_PMUX_FUNC(92), + AMD_PMUX_FUNC(93), + AMD_PMUX_FUNC(94), + AMD_PMUX_FUNC(95), + AMD_PMUX_FUNC(96), + AMD_PMUX_FUNC(97), + AMD_PMUX_FUNC(98), + AMD_PMUX_FUNC(99), + AMD_PMUX_FUNC(100), + AMD_PMUX_FUNC(101), + AMD_PMUX_FUNC(102), + AMD_PMUX_FUNC(103), + AMD_PMUX_FUNC(104), + AMD_PMUX_FUNC(105), + AMD_PMUX_FUNC(106), + AMD_PMUX_FUNC(107), + AMD_PMUX_FUNC(108), + AMD_PMUX_FUNC(109), + AMD_PMUX_FUNC(110), + AMD_PMUX_FUNC(111), + AMD_PMUX_FUNC(112), + AMD_PMUX_FUNC(113), + AMD_PMUX_FUNC(114), + AMD_PMUX_FUNC(115), + AMD_PMUX_FUNC(116), + AMD_PMUX_FUNC(117), + AMD_PMUX_FUNC(118), + AMD_PMUX_FUNC(119), + AMD_PMUX_FUNC(120), + AMD_PMUX_FUNC(121), + AMD_PMUX_FUNC(122), + AMD_PMUX_FUNC(123), + AMD_PMUX_FUNC(124), + AMD_PMUX_FUNC(125), + AMD_PMUX_FUNC(126), + AMD_PMUX_FUNC(127), + AMD_PMUX_FUNC(128), + AMD_PMUX_FUNC(129), + AMD_PMUX_FUNC(130), + AMD_PMUX_FUNC(131), + AMD_PMUX_FUNC(132), + AMD_PMUX_FUNC(133), + AMD_PMUX_FUNC(134), + AMD_PMUX_FUNC(135), + AMD_PMUX_FUNC(136), + AMD_PMUX_FUNC(137), + AMD_PMUX_FUNC(138), + AMD_PMUX_FUNC(139), + AMD_PMUX_FUNC(140), + AMD_PMUX_FUNC(141), + AMD_PMUX_FUNC(142), + AMD_PMUX_FUNC(143), + AMD_PMUX_FUNC(144), }; #endif diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 517f2a6330ad..82b921fd630d 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -237,8 +237,6 @@ static void atmel_gpio_irq_unmask(struct irq_data *d) BIT(pin->line)); } -#ifdef CONFIG_PM_SLEEP - static int atmel_gpio_irq_set_wake(struct irq_data *d, unsigned int on) { struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); @@ -255,9 +253,6 @@ static int atmel_gpio_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } -#else -#define atmel_gpio_irq_set_wake NULL -#endif /* CONFIG_PM_SLEEP */ static struct irq_chip atmel_gpio_irq_chip = { .name = "GPIO", @@ -265,7 +260,7 @@ static struct irq_chip atmel_gpio_irq_chip = { .irq_mask = atmel_gpio_irq_mask, .irq_unmask = atmel_gpio_irq_unmask, .irq_set_type = atmel_gpio_irq_set_type, - .irq_set_wake = atmel_gpio_irq_set_wake, + .irq_set_wake = pm_sleep_ptr(atmel_gpio_irq_set_wake), }; static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index d91a010e65f5..5634fa063ebf 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1615,8 +1615,6 @@ static void gpio_irq_ack(struct irq_data *d) /* the interrupt is already cleared before by reading ISR */ } -#ifdef CONFIG_PM - static u32 wakeups[MAX_GPIO_BANKS]; static u32 backups[MAX_GPIO_BANKS]; @@ -1683,10 +1681,6 @@ void at91_pinctrl_gpio_resume(void) } } -#else -#define gpio_irq_set_wake NULL -#endif /* CONFIG_PM */ - static void gpio_irq_handler(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); @@ -1741,14 +1735,14 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev, gpio_irqchip->irq_disable = gpio_irq_mask; gpio_irqchip->irq_mask = gpio_irq_mask; gpio_irqchip->irq_unmask = gpio_irq_unmask; - gpio_irqchip->irq_set_wake = gpio_irq_set_wake; + gpio_irqchip->irq_set_wake = pm_ptr(gpio_irq_set_wake); gpio_irqchip->irq_set_type = at91_gpio->ops->irq_type; /* Disable irqs of this PIO controller */ writel_relaxed(~0, at91_gpio->regbase + PIO_IDR); /* - * Let the generic code handle this edge IRQ, the the chained + * Let the generic code handle this edge IRQ, the chained * handler will perform the actual work of handling the parent * interrupt. */ diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index 207cbae3a7bf..7ab20ac15391 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -73,7 +73,7 @@ static const struct pinctrl_pin_desc axp209_pins[] = { PINCTRL_PIN(2, "GPIO2"), }; -static const struct pinctrl_pin_desc axp813_pins[] = { +static const struct pinctrl_pin_desc axp22x_pins[] = { PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"), }; @@ -87,9 +87,16 @@ static const struct axp20x_pctrl_desc axp20x_data = { .adc_mux = AXP20X_MUX_ADC, }; +static const struct axp20x_pctrl_desc axp22x_data = { + .pins = axp22x_pins, + .npins = ARRAY_SIZE(axp22x_pins), + .ldo_mask = BIT(0) | BIT(1), + .gpio_status_offset = 0, +}; + static const struct axp20x_pctrl_desc axp813_data = { - .pins = axp813_pins, - .npins = ARRAY_SIZE(axp813_pins), + .pins = axp22x_pins, + .npins = ARRAY_SIZE(axp22x_pins), .ldo_mask = BIT(0) | BIT(1), .adc_mask = BIT(0), .gpio_status_offset = 0, @@ -388,6 +395,7 @@ static int axp20x_build_funcs_groups(struct platform_device *pdev) static const struct of_device_id axp20x_pctl_match[] = { { .compatible = "x-powers,axp209-gpio", .data = &axp20x_data, }, + { .compatible = "x-powers,axp221-gpio", .data = &axp22x_data, }, { .compatible = "x-powers,axp813-gpio", .data = &axp813_data, }, { } }; diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 1ca11616db74..3a9ee9c8af11 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -21,6 +21,7 @@ #include <linux/pinctrl/pinconf-generic.h> #include <linux/platform_device.h> #include <linux/regmap.h> +#include <linux/seq_file.h> #include <linux/slab.h> #include "core.h" @@ -135,7 +136,6 @@ struct ingenic_pinctrl { struct ingenic_gpio_chip { struct ingenic_pinctrl *jzpc; struct gpio_chip gc; - struct irq_chip irq_chip; unsigned int irq, reg_base; }; @@ -3393,7 +3393,7 @@ static void ingenic_gpio_irq_mask(struct irq_data *irqd) { struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); - int irq = irqd->hwirq; + irq_hw_number_t irq = irqd_to_hwirq(irqd); if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, GPIO_MSK, irq, true); @@ -3405,7 +3405,7 @@ static void ingenic_gpio_irq_unmask(struct irq_data *irqd) { struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); - int irq = irqd->hwirq; + irq_hw_number_t irq = irqd_to_hwirq(irqd); if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, GPIO_MSK, irq, false); @@ -3417,7 +3417,9 @@ static void ingenic_gpio_irq_enable(struct irq_data *irqd) { struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); - int irq = irqd->hwirq; + irq_hw_number_t irq = irqd_to_hwirq(irqd); + + gpiochip_enable_irq(gc, irq); if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, true); @@ -3433,7 +3435,7 @@ static void ingenic_gpio_irq_disable(struct irq_data *irqd) { struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); - int irq = irqd->hwirq; + irq_hw_number_t irq = irqd_to_hwirq(irqd); ingenic_gpio_irq_mask(irqd); @@ -3443,13 +3445,15 @@ static void ingenic_gpio_irq_disable(struct irq_data *irqd) ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_GPIER, irq, false); + + gpiochip_disable_irq(gc, irq); } static void ingenic_gpio_irq_ack(struct irq_data *irqd) { struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); - int irq = irqd->hwirq; + irq_hw_number_t irq = irqd_to_hwirq(irqd); bool high; if ((irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) && @@ -3477,6 +3481,7 @@ static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); + irq_hw_number_t irq = irqd_to_hwirq(irqd); switch (type) { case IRQ_TYPE_EDGE_BOTH: @@ -3498,12 +3503,12 @@ static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) * best we can do is to set up a single-edge interrupt and then * switch to the opposing edge when ACKing the interrupt. */ - bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq); + bool high = ingenic_gpio_get_value(jzgc, irq); type = high ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_LEVEL_HIGH; } - irq_set_type(jzgc, irqd->hwirq, type); + irq_set_type(jzgc, irq, type); return 0; } @@ -3668,22 +3673,45 @@ static const struct pinctrl_ops ingenic_pctlops = { static int ingenic_gpio_irq_request(struct irq_data *data) { struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); + irq_hw_number_t irq = irqd_to_hwirq(data); int ret; - ret = ingenic_gpio_direction_input(gpio_chip, data->hwirq); + ret = ingenic_gpio_direction_input(gpio_chip, irq); if (ret) return ret; - return gpiochip_reqres_irq(gpio_chip, data->hwirq); + return gpiochip_reqres_irq(gpio_chip, irq); } static void ingenic_gpio_irq_release(struct irq_data *data) { struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); + irq_hw_number_t irq = irqd_to_hwirq(data); + + return gpiochip_relres_irq(gpio_chip, irq); +} + +static void ingenic_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p) +{ + struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); - return gpiochip_relres_irq(gpio_chip, data->hwirq); + seq_printf(p, "%s", gpio_chip->label); } +static const struct irq_chip ingenic_gpio_irqchip = { + .irq_enable = ingenic_gpio_irq_enable, + .irq_disable = ingenic_gpio_irq_disable, + .irq_unmask = ingenic_gpio_irq_unmask, + .irq_mask = ingenic_gpio_irq_mask, + .irq_ack = ingenic_gpio_irq_ack, + .irq_set_type = ingenic_gpio_irq_set_type, + .irq_set_wake = ingenic_gpio_irq_set_wake, + .irq_request_resources = ingenic_gpio_irq_request, + .irq_release_resources = ingenic_gpio_irq_release, + .irq_print_chip = ingenic_gpio_irq_print_chip, + .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, +}; + static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc, int pin, int func) { @@ -4172,20 +4200,8 @@ static int __init ingenic_gpio_probe(struct ingenic_pinctrl *jzpc, if (!jzgc->irq) return -EINVAL; - jzgc->irq_chip.name = jzgc->gc.label; - jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable; - jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable; - jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask; - jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask; - jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack; - jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type; - jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake; - jzgc->irq_chip.irq_request_resources = ingenic_gpio_irq_request; - jzgc->irq_chip.irq_release_resources = ingenic_gpio_irq_release; - jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND; - girq = &jzgc->gc.irq; - girq->chip = &jzgc->irq_chip; + gpio_irq_chip_set_chip(girq, &ingenic_gpio_irqchip); girq->parent_handler = ingenic_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index 771dd1f4fbe0..c5fd154990c8 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -1944,6 +1944,7 @@ static const struct of_device_id ocelot_pinctrl_of_match[] = { { .compatible = "microchip,lan966x-pinctrl", .data = &lan966x_desc }, {}, }; +MODULE_DEVICE_TABLE(of, ocelot_pinctrl_of_match); static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev, const struct ocelot_pinctrl *info) @@ -2050,4 +2051,5 @@ static struct platform_driver ocelot_pinctrl_driver = { }, .probe = ocelot_pinctrl_probe, }; -builtin_platform_driver(ocelot_pinctrl_driver); +module_platform_driver(ocelot_pinctrl_driver); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/pinctrl/pinctrl-starfive.c b/drivers/pinctrl/pinctrl-starfive.c index 2a86c1035cc8..3eb40e230d98 100644 --- a/drivers/pinctrl/pinctrl-starfive.c +++ b/drivers/pinctrl/pinctrl-starfive.c @@ -207,6 +207,7 @@ struct starfive_pinctrl { void __iomem *base; void __iomem *padctl; struct pinctrl_dev *pctl; + struct mutex mutex; /* serialize adding groups and functions */ }; static inline unsigned int starfive_pin_to_gpio(const struct starfive_pinctrl *sfp, @@ -522,6 +523,7 @@ static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev, nmaps = 0; ngroups = 0; + mutex_lock(&sfp->mutex); for_each_child_of_node(np, child) { int npins; int i; @@ -615,12 +617,14 @@ static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev, *maps = map; *num_maps = nmaps; + mutex_unlock(&sfp->mutex); return 0; put_child: of_node_put(child); free_map: pinctrl_utils_free_map(pctldev, map, nmaps); + mutex_unlock(&sfp->mutex); return ret; } @@ -1267,6 +1271,7 @@ static int starfive_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sfp); sfp->gc.parent = dev; raw_spin_lock_init(&sfp->lock); + mutex_init(&sfp->mutex); ret = devm_pinctrl_register_and_init(dev, &starfive_desc, sfp, &sfp->pctl); if (ret) diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c index e14012209992..7d2fbf8a02cd 100644 --- a/drivers/pinctrl/pinctrl-zynqmp.c +++ b/drivers/pinctrl/pinctrl-zynqmp.c @@ -163,6 +163,8 @@ static const char *zynqmp_pmux_get_function_name(struct pinctrl_dev *pctldev, * @num_groups: Number of function groups. * * Get function's group count and group names. + * + * Return: 0 */ static int zynqmp_pmux_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector, @@ -410,6 +412,10 @@ static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + param = PM_PINCTRL_CONFIG_TRI_STATE; + arg = PM_PINCTRL_TRI_STATE_ENABLE; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; case PIN_CONFIG_MODE_LOW_POWER: /* * These cases are mentioned in dts but configurable @@ -418,6 +424,11 @@ static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, */ ret = 0; break; + case PIN_CONFIG_OUTPUT_ENABLE: + param = PM_PINCTRL_CONFIG_TRI_STATE; + arg = PM_PINCTRL_TRI_STATE_DISABLE; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; default: dev_warn(pctldev->dev, "unsupported configuration parameter '%u'\n", diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 3daeb9772391..f415c13caae0 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -113,6 +113,14 @@ config PINCTRL_MSM8X74 This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found in the Qualcomm 8974 platform. +config PINCTRL_MSM8909 + tristate "Qualcomm 8909 pin controller driver" + depends on OF + depends on PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8909 platform. + config PINCTRL_MSM8916 tristate "Qualcomm 8916 pin controller driver" depends on OF @@ -320,6 +328,15 @@ config PINCTRL_SM6350 Qualcomm Technologies Inc TLMM block found on the Qualcomm Technologies Inc SM6350 platform. +config PINCTRL_SM6375 + tristate "Qualcomm Technologies Inc SM6375 pin controller driver" + depends on GPIOLIB && OF + depends on PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6375 platform. + config PINCTRL_SDX65 tristate "Qualcomm Technologies Inc SDX65 pin controller driver" depends on GPIOLIB && OF @@ -367,7 +384,7 @@ config PINCTRL_SM8350 config PINCTRL_SM8450 tristate "Qualcomm Technologies Inc SM8450 pin controller driver" depends on GPIOLIB && OF - select PINCTRL_MSM + depends on PINCTRL_MSM help This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm Technologies Inc TLMM block found on the Qualcomm diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 4f0ee7597f81..fbd64853a24d 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_PINCTRL_MSM8226) += pinctrl-msm8226.o obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o +obj-$(CONFIG_PINCTRL_MSM8909) += pinctrl-msm8909.o obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o obj-$(CONFIG_PINCTRL_MSM8953) += pinctrl-msm8953.o obj-$(CONFIG_PINCTRL_MSM8976) += pinctrl-msm8976.o @@ -37,6 +38,7 @@ obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o obj-$(CONFIG_PINCTRL_SM6115) += pinctrl-sm6115.o obj-$(CONFIG_PINCTRL_SM6125) += pinctrl-sm6125.o obj-$(CONFIG_PINCTRL_SM6350) += pinctrl-sm6350.o +obj-$(CONFIG_PINCTRL_SM6375) += pinctrl-sm6375.o obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c index 74810ec4df44..e97ce45b6d53 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c @@ -401,7 +401,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(pctrl->slew_base), "Slew resource not provided\n"); - if (data->is_clk_optional) + if (of_property_read_bool(dev->of_node, "qcom,adsp-bypass-mode")) ret = devm_clk_bulk_get_optional(dev, MAX_LPI_NUM_CLKS, pctrl->clks); else ret = devm_clk_bulk_get(dev, MAX_LPI_NUM_CLKS, pctrl->clks); diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h index 759d5d8da562..afbac2a6c82c 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h @@ -77,7 +77,6 @@ struct lpi_pinctrl_variant_data { int ngroups; const struct lpi_function *functions; int nfunctions; - bool is_clk_optional; }; int lpi_pinctrl_probe(struct platform_device *pdev); diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c new file mode 100644 index 000000000000..6dd15b910632 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c @@ -0,0 +1,956 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2022, Kernkonzept GmbH. + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [msm_mux_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + }, \ + .nfuncs = 10, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = 0x8 + REG_SIZE * id, \ + .intr_status_reg = 0xc + REG_SIZE * id, \ + .intr_target_reg = 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 4, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } +static const struct pinctrl_pin_desc msm8909_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "SDC1_CLK"), + PINCTRL_PIN(114, "SDC1_CMD"), + PINCTRL_PIN(115, "SDC1_DATA"), + PINCTRL_PIN(116, "SDC2_CLK"), + PINCTRL_PIN(117, "SDC2_CMD"), + PINCTRL_PIN(118, "SDC2_DATA"), + PINCTRL_PIN(119, "QDSD_CLK"), + PINCTRL_PIN(120, "QDSD_CMD"), + PINCTRL_PIN(121, "QDSD_DATA0"), + PINCTRL_PIN(122, "QDSD_DATA1"), + PINCTRL_PIN(123, "QDSD_DATA2"), + PINCTRL_PIN(124, "QDSD_DATA3"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); + +static const unsigned int sdc1_clk_pins[] = { 113 }; +static const unsigned int sdc1_cmd_pins[] = { 114 }; +static const unsigned int sdc1_data_pins[] = { 115 }; +static const unsigned int sdc2_clk_pins[] = { 116 }; +static const unsigned int sdc2_cmd_pins[] = { 117 }; +static const unsigned int sdc2_data_pins[] = { 118 }; +static const unsigned int qdsd_clk_pins[] = { 119 }; +static const unsigned int qdsd_cmd_pins[] = { 120 }; +static const unsigned int qdsd_data0_pins[] = { 121 }; +static const unsigned int qdsd_data1_pins[] = { 122 }; +static const unsigned int qdsd_data2_pins[] = { 123 }; +static const unsigned int qdsd_data3_pins[] = { 124 }; + +enum msm8909_functions { + msm_mux_gpio, + msm_mux_adsp_ext, + msm_mux_atest_bbrx0, + msm_mux_atest_bbrx1, + msm_mux_atest_char, + msm_mux_atest_char0, + msm_mux_atest_char1, + msm_mux_atest_char2, + msm_mux_atest_char3, + msm_mux_atest_combodac, + msm_mux_atest_gpsadc0, + msm_mux_atest_gpsadc1, + msm_mux_atest_wlan0, + msm_mux_atest_wlan1, + msm_mux_bimc_dte0, + msm_mux_bimc_dte1, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi3_cs1, + msm_mux_blsp_spi3_cs2, + msm_mux_blsp_spi3_cs3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_cam_mclk, + msm_mux_cci_async, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cdc_pdm0, + msm_mux_dbg_out, + msm_mux_dmic0_clk, + msm_mux_dmic0_data, + msm_mux_ebi0_wrcdc, + msm_mux_ebi2_a, + msm_mux_ebi2_lcd, + msm_mux_ext_lpass, + msm_mux_gcc_gp1_clk_a, + msm_mux_gcc_gp1_clk_b, + msm_mux_gcc_gp2_clk_a, + msm_mux_gcc_gp2_clk_b, + msm_mux_gcc_gp3_clk_a, + msm_mux_gcc_gp3_clk_b, + msm_mux_gcc_plltest, + msm_mux_gsm0_tx, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_m_voc, + msm_mux_mdp_vsync, + msm_mux_modem_tsync, + msm_mux_nav_pps, + msm_mux_nav_tsync, + msm_mux_pa_indicator, + msm_mux_pbs0, + msm_mux_pbs1, + msm_mux_pbs2, + msm_mux_pri_mi2s_data0_a, + msm_mux_pri_mi2s_data0_b, + msm_mux_pri_mi2s_data1_a, + msm_mux_pri_mi2s_data1_b, + msm_mux_pri_mi2s_mclk_a, + msm_mux_pri_mi2s_mclk_b, + msm_mux_pri_mi2s_sck_a, + msm_mux_pri_mi2s_sck_b, + msm_mux_pri_mi2s_ws_a, + msm_mux_pri_mi2s_ws_b, + msm_mux_prng_rosc, + msm_mux_pwr_crypto_enabled_a, + msm_mux_pwr_crypto_enabled_b, + msm_mux_pwr_modem_enabled_a, + msm_mux_pwr_modem_enabled_b, + msm_mux_pwr_nav_enabled_a, + msm_mux_pwr_nav_enabled_b, + msm_mux_qdss_cti_trig_in_a0, + msm_mux_qdss_cti_trig_in_a1, + msm_mux_qdss_cti_trig_in_b0, + msm_mux_qdss_cti_trig_in_b1, + msm_mux_qdss_cti_trig_out_a0, + msm_mux_qdss_cti_trig_out_a1, + msm_mux_qdss_cti_trig_out_b0, + msm_mux_qdss_cti_trig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_sd_write, + msm_mux_sec_mi2s, + msm_mux_smb_int, + msm_mux_ssbi0, + msm_mux_ssbi1, + msm_mux_uim1_clk, + msm_mux_uim1_data, + msm_mux_uim1_present, + msm_mux_uim1_reset, + msm_mux_uim2_clk, + msm_mux_uim2_data, + msm_mux_uim2_present, + msm_mux_uim2_reset, + msm_mux_uim3_clk, + msm_mux_uim3_data, + msm_mux_uim3_present, + msm_mux_uim3_reset, + msm_mux_uim_batt, + msm_mux_wcss_bt, + msm_mux_wcss_fm, + msm_mux_wcss_wlan, + msm_mux__, +}; + +static const char * const adsp_ext_groups[] = { "gpio38" }; +static const char * const atest_bbrx0_groups[] = { "gpio37" }; +static const char * const atest_bbrx1_groups[] = { "gpio36" }; +static const char * const atest_char0_groups[] = { "gpio62" }; +static const char * const atest_char1_groups[] = { "gpio61" }; +static const char * const atest_char2_groups[] = { "gpio60" }; +static const char * const atest_char3_groups[] = { "gpio59" }; +static const char * const atest_char_groups[] = { "gpio63" }; +static const char * const atest_combodac_groups[] = { + "gpio32", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", + "gpio44", "gpio45", "gpio47", "gpio48", "gpio66", "gpio81", "gpio83", + "gpio84", "gpio85", "gpio86", "gpio94", "gpio95", "gpio110" +}; +static const char * const atest_gpsadc0_groups[] = { "gpio65" }; +static const char * const atest_gpsadc1_groups[] = { "gpio79" }; +static const char * const atest_wlan0_groups[] = { "gpio96" }; +static const char * const atest_wlan1_groups[] = { "gpio97" }; +static const char * const bimc_dte0_groups[] = { "gpio6", "gpio59" }; +static const char * const bimc_dte1_groups[] = { "gpio7", "gpio60" }; +static const char * const blsp_i2c1_groups[] = { "gpio6", "gpio7" }; +static const char * const blsp_i2c2_groups[] = { "gpio111", "gpio112" }; +static const char * const blsp_i2c3_groups[] = { "gpio29", "gpio30" }; +static const char * const blsp_i2c4_groups[] = { "gpio14", "gpio15" }; +static const char * const blsp_i2c5_groups[] = { "gpio18", "gpio19" }; +static const char * const blsp_i2c6_groups[] = { "gpio10", "gpio11" }; +static const char * const blsp_spi1_cs1_groups[] = { "gpio97" }; +static const char * const blsp_spi1_cs2_groups[] = { "gpio37" }; +static const char * const blsp_spi1_cs3_groups[] = { "gpio65" }; +static const char * const blsp_spi1_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_spi2_cs1_groups[] = { "gpio98" }; +static const char * const blsp_spi2_cs2_groups[] = { "gpio17" }; +static const char * const blsp_spi2_cs3_groups[] = { "gpio5" }; +static const char * const blsp_spi2_groups[] = { + "gpio20", "gpio21", "gpio111", "gpio112" +}; +static const char * const blsp_spi3_cs1_groups[] = { "gpio95" }; +static const char * const blsp_spi3_cs2_groups[] = { "gpio65" }; +static const char * const blsp_spi3_cs3_groups[] = { "gpio4" }; +static const char * const blsp_spi3_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_spi4_groups[] = { + "gpio12", "gpio13", "gpio14", "gpio15" +}; +static const char * const blsp_spi5_groups[] = { + "gpio16", "gpio17", "gpio18", "gpio19" +}; +static const char * const blsp_spi6_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11" +}; +static const char * const blsp_uart1_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_uart2_groups[] = { + "gpio20", "gpio21", "gpio111", "gpio112" +}; +static const char * const blsp_uim1_groups[] = { "gpio4", "gpio5" }; +static const char * const blsp_uim2_groups[] = { "gpio20", "gpio21" }; +static const char * const cam_mclk_groups[] = { "gpio26", "gpio27" }; +static const char * const cci_async_groups[] = { "gpio33" }; +static const char * const cci_timer0_groups[] = { "gpio31" }; +static const char * const cci_timer1_groups[] = { "gpio32" }; +static const char * const cci_timer2_groups[] = { "gpio38" }; +static const char * const cdc_pdm0_groups[] = { + "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", "gpio64" +}; +static const char * const dbg_out_groups[] = { "gpio10" }; +static const char * const dmic0_clk_groups[] = { "gpio4" }; +static const char * const dmic0_data_groups[] = { "gpio5" }; +static const char * const ebi0_wrcdc_groups[] = { "gpio64" }; +static const char * const ebi2_a_groups[] = { "gpio99" }; +static const char * const ebi2_lcd_groups[] = { + "gpio24", "gpio24", "gpio25", "gpio95" +}; +static const char * const ext_lpass_groups[] = { "gpio45" }; +static const char * const gcc_gp1_clk_a_groups[] = { "gpio49" }; +static const char * const gcc_gp1_clk_b_groups[] = { "gpio14" }; +static const char * const gcc_gp2_clk_a_groups[] = { "gpio50" }; +static const char * const gcc_gp2_clk_b_groups[] = { "gpio12" }; +static const char * const gcc_gp3_clk_a_groups[] = { "gpio51" }; +static const char * const gcc_gp3_clk_b_groups[] = { "gpio13" }; +static const char * const gcc_plltest_groups[] = { "gpio66", "gpio67" }; +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", + "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112" +}; +static const char * const gsm0_tx_groups[] = { "gpio85" }; +static const char * const ldo_en_groups[] = { "gpio99" }; +static const char * const ldo_update_groups[] = { "gpio98" }; +static const char * const m_voc_groups[] = { "gpio8", "gpio95" }; +static const char * const mdp_vsync_groups[] = { "gpio24", "gpio25" }; +static const char * const modem_tsync_groups[] = { "gpio83" }; +static const char * const nav_pps_groups[] = { "gpio83" }; +static const char * const nav_tsync_groups[] = { "gpio83" }; +static const char * const pa_indicator_groups[] = { "gpio82" }; +static const char * const pbs0_groups[] = { "gpio90" }; +static const char * const pbs1_groups[] = { "gpio91" }; +static const char * const pbs2_groups[] = { "gpio92" }; +static const char * const pri_mi2s_data0_a_groups[] = { "gpio62" }; +static const char * const pri_mi2s_data0_b_groups[] = { "gpio95" }; +static const char * const pri_mi2s_data1_a_groups[] = { "gpio63" }; +static const char * const pri_mi2s_data1_b_groups[] = { "gpio96" }; +static const char * const pri_mi2s_mclk_a_groups[] = { "gpio59" }; +static const char * const pri_mi2s_mclk_b_groups[] = { "gpio98" }; +static const char * const pri_mi2s_sck_a_groups[] = { "gpio60" }; +static const char * const pri_mi2s_sck_b_groups[] = { "gpio94" }; +static const char * const pri_mi2s_ws_a_groups[] = { "gpio61" }; +static const char * const pri_mi2s_ws_b_groups[] = { "gpio110" }; +static const char * const prng_rosc_groups[] = { "gpio43" }; +static const char * const pwr_crypto_enabled_a_groups[] = { "gpio35" }; +static const char * const pwr_crypto_enabled_b_groups[] = { "gpio96" }; +static const char * const pwr_modem_enabled_a_groups[] = { "gpio28" }; +static const char * const pwr_modem_enabled_b_groups[] = { "gpio94" }; +static const char * const pwr_nav_enabled_a_groups[] = { "gpio34" }; +static const char * const pwr_nav_enabled_b_groups[] = { "gpio95" }; +static const char * const qdss_cti_trig_in_a0_groups[] = { "gpio20" }; +static const char * const qdss_cti_trig_in_a1_groups[] = { "gpio49" }; +static const char * const qdss_cti_trig_in_b0_groups[] = { "gpio21" }; +static const char * const qdss_cti_trig_in_b1_groups[] = { "gpio50" }; +static const char * const qdss_cti_trig_out_a0_groups[] = { "gpio23" }; +static const char * const qdss_cti_trig_out_a1_groups[] = { "gpio52" }; +static const char * const qdss_cti_trig_out_b0_groups[] = { "gpio22" }; +static const char * const qdss_cti_trig_out_b1_groups[] = { "gpio51" }; +static const char * const qdss_traceclk_a_groups[] = { "gpio46" }; +static const char * const qdss_tracectl_a_groups[] = { "gpio45" }; +static const char * const qdss_tracedata_a_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio47", "gpio48", "gpio58", "gpio65", "gpio94", "gpio96", + "gpio97" +}; +static const char * const qdss_tracedata_b_groups[] = { + "gpio14", "gpio16", "gpio17", "gpio29", "gpio30", "gpio31", "gpio32", + "gpio33", "gpio34", "gpio35", "gpio36", "gpio37", "gpio93" +}; +static const char * const sd_write_groups[] = { "gpio99" }; +static const char * const sec_mi2s_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio98" +}; +static const char * const smb_int_groups[] = { "gpio58" }; +static const char * const ssbi0_groups[] = { "gpio88" }; +static const char * const ssbi1_groups[] = { "gpio89" }; +static const char * const uim1_clk_groups[] = { "gpio54" }; +static const char * const uim1_data_groups[] = { "gpio53" }; +static const char * const uim1_present_groups[] = { "gpio56" }; +static const char * const uim1_reset_groups[] = { "gpio55" }; +static const char * const uim2_clk_groups[] = { "gpio50" }; +static const char * const uim2_data_groups[] = { "gpio49" }; +static const char * const uim2_present_groups[] = { "gpio52" }; +static const char * const uim2_reset_groups[] = { "gpio51" }; +static const char * const uim3_clk_groups[] = { "gpio23" }; +static const char * const uim3_data_groups[] = { "gpio20" }; +static const char * const uim3_present_groups[] = { "gpio21" }; +static const char * const uim3_reset_groups[] = { "gpio22" }; +static const char * const uim_batt_groups[] = { "gpio57" }; +static const char * const wcss_bt_groups[] = { "gpio39", "gpio47", "gpio48" }; +static const char * const wcss_fm_groups[] = { "gpio45", "gpio46" }; +static const char * const wcss_wlan_groups[] = { + "gpio40", "gpio41", "gpio42", "gpio43", "gpio44" +}; + +static const struct msm_function msm8909_functions[] = { + FUNCTION(adsp_ext), + FUNCTION(atest_bbrx0), + FUNCTION(atest_bbrx1), + FUNCTION(atest_char), + FUNCTION(atest_char0), + FUNCTION(atest_char1), + FUNCTION(atest_char2), + FUNCTION(atest_char3), + FUNCTION(atest_combodac), + FUNCTION(atest_gpsadc0), + FUNCTION(atest_gpsadc1), + FUNCTION(atest_wlan0), + FUNCTION(atest_wlan1), + FUNCTION(bimc_dte0), + FUNCTION(bimc_dte1), + FUNCTION(blsp_i2c1), + FUNCTION(blsp_i2c2), + FUNCTION(blsp_i2c3), + FUNCTION(blsp_i2c4), + FUNCTION(blsp_i2c5), + FUNCTION(blsp_i2c6), + FUNCTION(blsp_spi1), + FUNCTION(blsp_spi1_cs1), + FUNCTION(blsp_spi1_cs2), + FUNCTION(blsp_spi1_cs3), + FUNCTION(blsp_spi2), + FUNCTION(blsp_spi2_cs1), + FUNCTION(blsp_spi2_cs2), + FUNCTION(blsp_spi2_cs3), + FUNCTION(blsp_spi3), + FUNCTION(blsp_spi3_cs1), + FUNCTION(blsp_spi3_cs2), + FUNCTION(blsp_spi3_cs3), + FUNCTION(blsp_spi4), + FUNCTION(blsp_spi5), + FUNCTION(blsp_spi6), + FUNCTION(blsp_uart1), + FUNCTION(blsp_uart2), + FUNCTION(blsp_uim1), + FUNCTION(blsp_uim2), + FUNCTION(cam_mclk), + FUNCTION(cci_async), + FUNCTION(cci_timer0), + FUNCTION(cci_timer1), + FUNCTION(cci_timer2), + FUNCTION(cdc_pdm0), + FUNCTION(dbg_out), + FUNCTION(dmic0_clk), + FUNCTION(dmic0_data), + FUNCTION(ebi0_wrcdc), + FUNCTION(ebi2_a), + FUNCTION(ebi2_lcd), + FUNCTION(ext_lpass), + FUNCTION(gcc_gp1_clk_a), + FUNCTION(gcc_gp1_clk_b), + FUNCTION(gcc_gp2_clk_a), + FUNCTION(gcc_gp2_clk_b), + FUNCTION(gcc_gp3_clk_a), + FUNCTION(gcc_gp3_clk_b), + FUNCTION(gcc_plltest), + FUNCTION(gpio), + FUNCTION(gsm0_tx), + FUNCTION(ldo_en), + FUNCTION(ldo_update), + FUNCTION(m_voc), + FUNCTION(mdp_vsync), + FUNCTION(modem_tsync), + FUNCTION(nav_pps), + FUNCTION(nav_tsync), + FUNCTION(pa_indicator), + FUNCTION(pbs0), + FUNCTION(pbs1), + FUNCTION(pbs2), + FUNCTION(pri_mi2s_data0_a), + FUNCTION(pri_mi2s_data0_b), + FUNCTION(pri_mi2s_data1_a), + FUNCTION(pri_mi2s_data1_b), + FUNCTION(pri_mi2s_mclk_a), + FUNCTION(pri_mi2s_mclk_b), + FUNCTION(pri_mi2s_sck_a), + FUNCTION(pri_mi2s_sck_b), + FUNCTION(pri_mi2s_ws_a), + FUNCTION(pri_mi2s_ws_b), + FUNCTION(prng_rosc), + FUNCTION(pwr_crypto_enabled_a), + FUNCTION(pwr_crypto_enabled_b), + FUNCTION(pwr_modem_enabled_a), + FUNCTION(pwr_modem_enabled_b), + FUNCTION(pwr_nav_enabled_a), + FUNCTION(pwr_nav_enabled_b), + FUNCTION(qdss_cti_trig_in_a0), + FUNCTION(qdss_cti_trig_in_a1), + FUNCTION(qdss_cti_trig_in_b0), + FUNCTION(qdss_cti_trig_in_b1), + FUNCTION(qdss_cti_trig_out_a0), + FUNCTION(qdss_cti_trig_out_a1), + FUNCTION(qdss_cti_trig_out_b0), + FUNCTION(qdss_cti_trig_out_b1), + FUNCTION(qdss_traceclk_a), + FUNCTION(qdss_tracectl_a), + FUNCTION(qdss_tracedata_a), + FUNCTION(qdss_tracedata_b), + FUNCTION(sd_write), + FUNCTION(sec_mi2s), + FUNCTION(smb_int), + FUNCTION(ssbi0), + FUNCTION(ssbi1), + FUNCTION(uim1_clk), + FUNCTION(uim1_data), + FUNCTION(uim1_present), + FUNCTION(uim1_reset), + FUNCTION(uim2_clk), + FUNCTION(uim2_data), + FUNCTION(uim2_present), + FUNCTION(uim2_reset), + FUNCTION(uim3_clk), + FUNCTION(uim3_data), + FUNCTION(uim3_present), + FUNCTION(uim3_reset), + FUNCTION(uim_batt), + FUNCTION(wcss_bt), + FUNCTION(wcss_fm), + FUNCTION(wcss_wlan), +}; + +static const struct msm_pingroup msm8909_groups[] = { + PINGROUP(0, blsp_spi3, sec_mi2s, _, _, _, _, _, _, _), + PINGROUP(1, blsp_spi3, sec_mi2s, _, _, _, _, _, _, _), + PINGROUP(2, blsp_spi3, sec_mi2s, _, _, _, _, _, _, _), + PINGROUP(3, blsp_spi3, sec_mi2s, _, _, _, _, _, _, _), + PINGROUP(4, blsp_spi1, blsp_uart1, blsp_uim1, blsp_spi3_cs3, dmic0_clk, _, _, _, _), + PINGROUP(5, blsp_spi1, blsp_uart1, blsp_uim1, blsp_spi2_cs3, dmic0_data, _, _, _, _), + PINGROUP(6, blsp_spi1, blsp_uart1, blsp_i2c1, _, _, _, _, _, bimc_dte0), + PINGROUP(7, blsp_spi1, blsp_uart1, blsp_i2c1, _, _, _, _, _, bimc_dte1), + PINGROUP(8, blsp_spi6, m_voc, _, _, _, _, _, qdss_tracedata_a, _), + PINGROUP(9, blsp_spi6, _, _, _, _, _, qdss_tracedata_a, _, _), + PINGROUP(10, blsp_spi6, blsp_i2c6, dbg_out, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(11, blsp_spi6, blsp_i2c6, _, _, _, _, _, _, _), + PINGROUP(12, blsp_spi4, gcc_gp2_clk_b, _, _, _, _, _, _, _), + PINGROUP(13, blsp_spi4, gcc_gp3_clk_b, _, _, _, _, _, _, _), + PINGROUP(14, blsp_spi4, blsp_i2c4, gcc_gp1_clk_b, _, _, _, _, _, qdss_tracedata_b), + PINGROUP(15, blsp_spi4, blsp_i2c4, _, _, _, _, _, _, _), + PINGROUP(16, blsp_spi5, _, _, _, _, _, qdss_tracedata_b, _, _), + PINGROUP(17, blsp_spi5, blsp_spi2_cs2, _, _, _, _, _, qdss_tracedata_b, _), + PINGROUP(18, blsp_spi5, blsp_i2c5, _, _, _, _, _, _, _), + PINGROUP(19, blsp_spi5, blsp_i2c5, _, _, _, _, _, _, _), + PINGROUP(20, uim3_data, blsp_spi2, blsp_uart2, blsp_uim2, _, qdss_cti_trig_in_a0, _, _, _), + PINGROUP(21, uim3_present, blsp_spi2, blsp_uart2, blsp_uim2, _, qdss_cti_trig_in_b0, _, _, _), + PINGROUP(22, uim3_reset, _, qdss_cti_trig_out_b0, _, _, _, _, _, _), + PINGROUP(23, uim3_clk, qdss_cti_trig_out_a0, _, _, _, _, _, _, _), + PINGROUP(24, mdp_vsync, ebi2_lcd, ebi2_lcd, _, _, _, _, _, _), + PINGROUP(25, mdp_vsync, ebi2_lcd, _, _, _, _, _, _, _), + PINGROUP(26, cam_mclk, _, _, _, _, _, _, _, _), + PINGROUP(27, cam_mclk, _, _, _, _, _, _, _, _), + PINGROUP(28, _, pwr_modem_enabled_a, _, _, _, _, _, _, _), + PINGROUP(29, blsp_i2c3, _, _, _, _, _, qdss_tracedata_b, _, _), + PINGROUP(30, blsp_i2c3, _, _, _, _, _, qdss_tracedata_b, _, _), + PINGROUP(31, cci_timer0, _, _, _, _, _, _, qdss_tracedata_b, _), + PINGROUP(32, cci_timer1, _, qdss_tracedata_b, _, atest_combodac, _, _, _, _), + PINGROUP(33, cci_async, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(34, pwr_nav_enabled_a, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(35, pwr_crypto_enabled_a, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(36, qdss_tracedata_b, _, atest_bbrx1, _, _, _, _, _, _), + PINGROUP(37, blsp_spi1_cs2, qdss_tracedata_b, _, atest_bbrx0, _, _, _, _, _), + PINGROUP(38, cci_timer2, adsp_ext, _, atest_combodac, _, _, _, _, _), + PINGROUP(39, wcss_bt, qdss_tracedata_a, _, atest_combodac, _, _, _, _, _), + PINGROUP(40, wcss_wlan, qdss_tracedata_a, _, atest_combodac, _, _, _, _, _), + PINGROUP(41, wcss_wlan, qdss_tracedata_a, _, atest_combodac, _, _, _, _, _), + PINGROUP(42, wcss_wlan, qdss_tracedata_a, _, atest_combodac, _, _, _, _, _), + PINGROUP(43, wcss_wlan, prng_rosc, qdss_tracedata_a, _, atest_combodac, _, _, _, _), + PINGROUP(44, wcss_wlan, _, atest_combodac, _, _, _, _, _, _), + PINGROUP(45, wcss_fm, ext_lpass, qdss_tracectl_a, _, atest_combodac, _, _, _, _), + PINGROUP(46, wcss_fm, qdss_traceclk_a, _, _, _, _, _, _, _), + PINGROUP(47, wcss_bt, qdss_tracedata_a, _, atest_combodac, _, _, _, _, _), + PINGROUP(48, wcss_bt, qdss_tracedata_a, _, atest_combodac, _, _, _, _, _), + PINGROUP(49, uim2_data, gcc_gp1_clk_a, qdss_cti_trig_in_a1, _, _, _, _, _, _), + PINGROUP(50, uim2_clk, gcc_gp2_clk_a, qdss_cti_trig_in_b1, _, _, _, _, _, _), + PINGROUP(51, uim2_reset, gcc_gp3_clk_a, qdss_cti_trig_out_b1, _, _, _, _, _, _), + PINGROUP(52, uim2_present, qdss_cti_trig_out_a1, _, _, _, _, _, _, _), + PINGROUP(53, uim1_data, _, _, _, _, _, _, _, _), + PINGROUP(54, uim1_clk, _, _, _, _, _, _, _, _), + PINGROUP(55, uim1_reset, _, _, _, _, _, _, _, _), + PINGROUP(56, uim1_present, _, _, _, _, _, _, _, _), + PINGROUP(57, uim_batt, _, _, _, _, _, _, _, _), + PINGROUP(58, qdss_tracedata_a, smb_int, _, _, _, _, _, _, _), + PINGROUP(59, cdc_pdm0, pri_mi2s_mclk_a, atest_char3, _, _, _, _, _, bimc_dte0), + PINGROUP(60, cdc_pdm0, pri_mi2s_sck_a, atest_char2, _, _, _, _, _, bimc_dte1), + PINGROUP(61, cdc_pdm0, pri_mi2s_ws_a, atest_char1, _, _, _, _, _, _), + PINGROUP(62, cdc_pdm0, pri_mi2s_data0_a, atest_char0, _, _, _, _, _, _), + PINGROUP(63, cdc_pdm0, pri_mi2s_data1_a, atest_char, _, _, _, _, _, _), + PINGROUP(64, cdc_pdm0, _, _, _, _, _, ebi0_wrcdc, _, _), + PINGROUP(65, blsp_spi3_cs2, blsp_spi1_cs3, qdss_tracedata_a, _, atest_gpsadc0, _, _, _, _), + PINGROUP(66, _, gcc_plltest, _, atest_combodac, _, _, _, _, _), + PINGROUP(67, _, gcc_plltest, _, _, _, _, _, _, _), + PINGROUP(68, _, _, _, _, _, _, _, _, _), + PINGROUP(69, _, _, _, _, _, _, _, _, _), + PINGROUP(70, _, _, _, _, _, _, _, _, _), + PINGROUP(71, _, _, _, _, _, _, _, _, _), + PINGROUP(72, _, _, _, _, _, _, _, _, _), + PINGROUP(73, _, _, _, _, _, _, _, _, _), + PINGROUP(74, _, _, _, _, _, _, _, _, _), + PINGROUP(75, _, _, _, _, _, _, _, _, _), + PINGROUP(76, _, _, _, _, _, _, _, _, _), + PINGROUP(77, _, _, _, _, _, _, _, _, _), + PINGROUP(78, _, _, _, _, _, _, _, _, _), + PINGROUP(79, _, _, atest_gpsadc1, _, _, _, _, _, _), + PINGROUP(80, _, _, _, _, _, _, _, _, _), + PINGROUP(81, _, _, _, atest_combodac, _, _, _, _, _), + PINGROUP(82, _, pa_indicator, _, _, _, _, _, _, _), + PINGROUP(83, _, modem_tsync, nav_tsync, nav_pps, _, atest_combodac, _, _, _), + PINGROUP(84, _, _, atest_combodac, _, _, _, _, _, _), + PINGROUP(85, gsm0_tx, _, _, atest_combodac, _, _, _, _, _), + PINGROUP(86, _, _, atest_combodac, _, _, _, _, _, _), + PINGROUP(87, _, _, _, _, _, _, _, _, _), + PINGROUP(88, _, ssbi0, _, _, _, _, _, _, _), + PINGROUP(89, _, ssbi1, _, _, _, _, _, _, _), + PINGROUP(90, pbs0, _, _, _, _, _, _, _, _), + PINGROUP(91, pbs1, _, _, _, _, _, _, _, _), + PINGROUP(92, pbs2, _, _, _, _, _, _, _, _), + PINGROUP(93, qdss_tracedata_b, _, _, _, _, _, _, _, _), + PINGROUP(94, pri_mi2s_sck_b, pwr_modem_enabled_b, qdss_tracedata_a, _, atest_combodac, _, _, _, _), + PINGROUP(95, blsp_spi3_cs1, pri_mi2s_data0_b, ebi2_lcd, m_voc, pwr_nav_enabled_b, _, atest_combodac, _, _), + PINGROUP(96, pri_mi2s_data1_b, _, pwr_crypto_enabled_b, qdss_tracedata_a, _, atest_wlan0, _, _, _), + PINGROUP(97, blsp_spi1_cs1, qdss_tracedata_a, _, atest_wlan1, _, _, _, _, _), + PINGROUP(98, sec_mi2s, pri_mi2s_mclk_b, blsp_spi2_cs1, ldo_update, _, _, _, _, _), + PINGROUP(99, ebi2_a, sd_write, ldo_en, _, _, _, _, _, _), + PINGROUP(100, _, _, _, _, _, _, _, _, _), + PINGROUP(101, _, _, _, _, _, _, _, _, _), + PINGROUP(102, _, _, _, _, _, _, _, _, _), + PINGROUP(103, _, _, _, _, _, _, _, _, _), + PINGROUP(104, _, _, _, _, _, _, _, _, _), + PINGROUP(105, _, _, _, _, _, _, _, _, _), + PINGROUP(106, _, _, _, _, _, _, _, _, _), + PINGROUP(107, _, _, _, _, _, _, _, _, _), + PINGROUP(108, _, _, _, _, _, _, _, _, _), + PINGROUP(109, _, _, _, _, _, _, _, _, _), + PINGROUP(110, pri_mi2s_ws_b, _, atest_combodac, _, _, _, _, _, _), + PINGROUP(111, blsp_spi2, blsp_uart2, blsp_i2c2, _, _, _, _, _, _), + PINGROUP(112, blsp_spi2, blsp_uart2, blsp_i2c2, _, _, _, _, _, _), + SDC_QDSD_PINGROUP(sdc1_clk, 0x10a000, 13, 6), + SDC_QDSD_PINGROUP(sdc1_cmd, 0x10a000, 11, 3), + SDC_QDSD_PINGROUP(sdc1_data, 0x10a000, 9, 0), + SDC_QDSD_PINGROUP(sdc2_clk, 0x109000, 14, 6), + SDC_QDSD_PINGROUP(sdc2_cmd, 0x109000, 11, 3), + SDC_QDSD_PINGROUP(sdc2_data, 0x109000, 9, 0), + SDC_QDSD_PINGROUP(qdsd_clk, 0x19c000, 3, 0), + SDC_QDSD_PINGROUP(qdsd_cmd, 0x19c000, 8, 5), + SDC_QDSD_PINGROUP(qdsd_data0, 0x19c000, 13, 10), + SDC_QDSD_PINGROUP(qdsd_data1, 0x19c000, 18, 15), + SDC_QDSD_PINGROUP(qdsd_data2, 0x19c000, 23, 20), + SDC_QDSD_PINGROUP(qdsd_data3, 0x19c000, 28, 25), +}; + +static const struct msm_gpio_wakeirq_map msm8909_mpm_map[] = { + { 65, 3 }, { 5, 4 }, { 11, 5 }, { 12, 6 }, { 64, 7 }, { 58, 8 }, + { 50, 9 }, { 13, 10 }, { 49, 11 }, { 20, 12 }, { 21, 13 }, { 25, 14 }, + { 46, 15 }, { 45, 16 }, { 28, 17 }, { 44, 18 }, { 31, 19 }, { 43, 20 }, + { 42, 21 }, { 34, 22 }, { 35, 23 }, { 36, 24 }, { 37, 25 }, { 38, 26 }, + { 39, 27 }, { 40, 28 }, { 41, 29 }, { 90, 30 }, { 91, 32 }, { 92, 33 }, + { 94, 34 }, { 95, 35 }, { 96, 36 }, { 97, 37 }, { 98, 38 }, + { 110, 39 }, { 111, 40 }, { 112, 41 }, { 105, 42 }, { 107, 43 }, + { 47, 50 }, { 48, 51 }, +}; + +static const struct msm_pinctrl_soc_data msm8909_pinctrl = { + .pins = msm8909_pins, + .npins = ARRAY_SIZE(msm8909_pins), + .functions = msm8909_functions, + .nfunctions = ARRAY_SIZE(msm8909_functions), + .groups = msm8909_groups, + .ngroups = ARRAY_SIZE(msm8909_groups), + .ngpios = 113, + .wakeirq_map = msm8909_mpm_map, + .nwakeirq_map = ARRAY_SIZE(msm8909_mpm_map), +}; + +static int msm8909_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &msm8909_pinctrl); +} + +static const struct of_device_id msm8909_pinctrl_of_match[] = { + { .compatible = "qcom,msm8909-tlmm", }, + { }, +}; +MODULE_DEVICE_TABLE(of, msm8909_pinctrl_of_match); + +static struct platform_driver msm8909_pinctrl_driver = { + .driver = { + .name = "msm8909-pinctrl", + .of_match_table = msm8909_pinctrl_of_match, + }, + .probe = msm8909_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init msm8909_pinctrl_init(void) +{ + return platform_driver_register(&msm8909_pinctrl_driver); +} +arch_initcall(msm8909_pinctrl_init); + +static void __exit msm8909_pinctrl_exit(void) +{ + platform_driver_unregister(&msm8909_pinctrl_driver); +} +module_exit(msm8909_pinctrl_exit); + +MODULE_DESCRIPTION("Qualcomm MSM8909 TLMM pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c index 396db12ae904..bf68913ba821 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8916.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c @@ -844,8 +844,8 @@ static const struct msm_pingroup msm8916_groups[] = { PINGROUP(28, pwr_modem_enabled_a, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, atest_combodac), PINGROUP(29, cci_i2c, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, atest_combodac), PINGROUP(30, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b), - PINGROUP(31, cci_timer0, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(32, cci_timer1, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(31, cci_timer0, flash_strobe, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(32, cci_timer1, flash_strobe, NA, NA, NA, NA, NA, NA, NA), PINGROUP(33, cci_async, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b), PINGROUP(34, pwr_nav_enabled_a, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b), PINGROUP(35, pwr_crypto_enabled_a, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b), diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c index 2add9a4520c2..d615b6c55b89 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c @@ -141,7 +141,6 @@ static const struct lpi_pinctrl_variant_data sc7280_lpi_data = { .ngroups = ARRAY_SIZE(sc7280_groups), .functions = sc7280_functions, .nfunctions = ARRAY_SIZE(sc7280_functions), - .is_clk_optional = true, }; static const struct of_device_id lpi_pinctrl_of_match[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c new file mode 100644 index 000000000000..1138e683e6f4 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c @@ -0,0 +1,1544 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Konrad Dybcio <[email protected]> + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [msm_mux_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define REG_BASE 0x100000 +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + }, \ + .nfuncs = 10, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = REG_SIZE * id + 0x4, \ + .intr_cfg_reg = REG_SIZE * id + 0x8, \ + .intr_status_reg = REG_SIZE * id + 0xc, \ + .intr_target_reg = REG_SIZE * id + 0x8, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .egpio_enable = 12, \ + .egpio_present = 11, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +#define UFS_RESET(pg_name, offset) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = offset, \ + .io_reg = offset + 0x4, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = 3, \ + .drv_bit = 0, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = 0, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +static const struct pinctrl_pin_desc sm6375_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + PINCTRL_PIN(146, "GPIO_146"), + PINCTRL_PIN(147, "GPIO_147"), + PINCTRL_PIN(148, "GPIO_148"), + PINCTRL_PIN(149, "GPIO_149"), + PINCTRL_PIN(150, "GPIO_150"), + PINCTRL_PIN(151, "GPIO_151"), + PINCTRL_PIN(152, "GPIO_152"), + PINCTRL_PIN(153, "GPIO_153"), + PINCTRL_PIN(154, "GPIO_154"), + PINCTRL_PIN(155, "GPIO_155"), + PINCTRL_PIN(156, "UFS_RESET"), + PINCTRL_PIN(157, "SDC1_RCLK"), + PINCTRL_PIN(158, "SDC1_CLK"), + PINCTRL_PIN(159, "SDC1_CMD"), + PINCTRL_PIN(160, "SDC1_DATA"), + PINCTRL_PIN(161, "SDC2_CLK"), + PINCTRL_PIN(162, "SDC2_CMD"), + PINCTRL_PIN(163, "SDC2_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); +DECLARE_MSM_GPIO_PINS(146); +DECLARE_MSM_GPIO_PINS(147); +DECLARE_MSM_GPIO_PINS(148); +DECLARE_MSM_GPIO_PINS(149); +DECLARE_MSM_GPIO_PINS(150); +DECLARE_MSM_GPIO_PINS(151); +DECLARE_MSM_GPIO_PINS(152); +DECLARE_MSM_GPIO_PINS(153); +DECLARE_MSM_GPIO_PINS(154); +DECLARE_MSM_GPIO_PINS(155); + + +static const unsigned int sdc1_rclk_pins[] = { 157 }; +static const unsigned int sdc1_clk_pins[] = { 158 }; +static const unsigned int sdc1_cmd_pins[] = { 159 }; +static const unsigned int sdc1_data_pins[] = { 160 }; +static const unsigned int sdc2_clk_pins[] = { 161 }; +static const unsigned int sdc2_cmd_pins[] = { 162 }; +static const unsigned int sdc2_data_pins[] = { 163 }; +static const unsigned int ufs_reset_pins[] = { 156 }; + +enum sm6375_functions { + msm_mux_adsp_ext, + msm_mux_agera_pll, + msm_mux_atest_char, + msm_mux_atest_char0, + msm_mux_atest_char1, + msm_mux_atest_char2, + msm_mux_atest_char3, + msm_mux_atest_tsens, + msm_mux_atest_tsens2, + msm_mux_atest_usb1, + msm_mux_atest_usb10, + msm_mux_atest_usb11, + msm_mux_atest_usb12, + msm_mux_atest_usb13, + msm_mux_atest_usb2, + msm_mux_atest_usb20, + msm_mux_atest_usb21, + msm_mux_atest_usb22, + msm_mux_atest_usb23, + msm_mux_audio_ref, + msm_mux_btfm_slimbus, + msm_mux_cam_mclk, + msm_mux_cci_async, + msm_mux_cci_i2c, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cci_timer3, + msm_mux_cci_timer4, + msm_mux_cri_trng, + msm_mux_dbg_out, + msm_mux_ddr_bist, + msm_mux_ddr_pxi0, + msm_mux_ddr_pxi1, + msm_mux_ddr_pxi2, + msm_mux_ddr_pxi3, + msm_mux_dp_hot, + msm_mux_edp_lcd, + msm_mux_gcc_gp1, + msm_mux_gcc_gp2, + msm_mux_gcc_gp3, + msm_mux_gp_pdm0, + msm_mux_gp_pdm1, + msm_mux_gp_pdm2, + msm_mux_gpio, + msm_mux_gps_tx, + msm_mux_ibi_i3c, + msm_mux_jitter_bist, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_lpass_ext, + msm_mux_m_voc, + msm_mux_mclk, + msm_mux_mdp_vsync, + msm_mux_mdp_vsync0, + msm_mux_mdp_vsync1, + msm_mux_mdp_vsync2, + msm_mux_mdp_vsync3, + msm_mux_mi2s_0, + msm_mux_mi2s_1, + msm_mux_mi2s_2, + msm_mux_mss_lte, + msm_mux_nav_gpio, + msm_mux_nav_pps, + msm_mux_pa_indicator, + msm_mux_phase_flag0, + msm_mux_phase_flag1, + msm_mux_phase_flag10, + msm_mux_phase_flag11, + msm_mux_phase_flag12, + msm_mux_phase_flag13, + msm_mux_phase_flag14, + msm_mux_phase_flag15, + msm_mux_phase_flag16, + msm_mux_phase_flag17, + msm_mux_phase_flag18, + msm_mux_phase_flag19, + msm_mux_phase_flag2, + msm_mux_phase_flag20, + msm_mux_phase_flag21, + msm_mux_phase_flag22, + msm_mux_phase_flag23, + msm_mux_phase_flag24, + msm_mux_phase_flag25, + msm_mux_phase_flag26, + msm_mux_phase_flag27, + msm_mux_phase_flag28, + msm_mux_phase_flag29, + msm_mux_phase_flag3, + msm_mux_phase_flag30, + msm_mux_phase_flag31, + msm_mux_phase_flag4, + msm_mux_phase_flag5, + msm_mux_phase_flag6, + msm_mux_phase_flag7, + msm_mux_phase_flag8, + msm_mux_phase_flag9, + msm_mux_pll_bist, + msm_mux_pll_bypassnl, + msm_mux_pll_clk, + msm_mux_pll_reset, + msm_mux_prng_rosc0, + msm_mux_prng_rosc1, + msm_mux_prng_rosc2, + msm_mux_prng_rosc3, + msm_mux_qdss_cti, + msm_mux_qdss_gpio, + msm_mux_qdss_gpio0, + msm_mux_qdss_gpio1, + msm_mux_qdss_gpio10, + msm_mux_qdss_gpio11, + msm_mux_qdss_gpio12, + msm_mux_qdss_gpio13, + msm_mux_qdss_gpio14, + msm_mux_qdss_gpio15, + msm_mux_qdss_gpio2, + msm_mux_qdss_gpio3, + msm_mux_qdss_gpio4, + msm_mux_qdss_gpio5, + msm_mux_qdss_gpio6, + msm_mux_qdss_gpio7, + msm_mux_qdss_gpio8, + msm_mux_qdss_gpio9, + msm_mux_qlink0_enable, + msm_mux_qlink0_request, + msm_mux_qlink0_wmss, + msm_mux_qlink1_enable, + msm_mux_qlink1_request, + msm_mux_qlink1_wmss, + msm_mux_qup00, + msm_mux_qup01, + msm_mux_qup02, + msm_mux_qup10, + msm_mux_qup11_f1, + msm_mux_qup11_f2, + msm_mux_qup12, + msm_mux_qup13_f1, + msm_mux_qup13_f2, + msm_mux_qup14, + msm_mux_sd_write, + msm_mux_sdc1_tb, + msm_mux_sdc2_tb, + msm_mux_sp_cmu, + msm_mux_tgu_ch0, + msm_mux_tgu_ch1, + msm_mux_tgu_ch2, + msm_mux_tgu_ch3, + msm_mux_tsense_pwm1, + msm_mux_tsense_pwm2, + msm_mux_uim1_clk, + msm_mux_uim1_data, + msm_mux_uim1_present, + msm_mux_uim1_reset, + msm_mux_uim2_clk, + msm_mux_uim2_data, + msm_mux_uim2_present, + msm_mux_uim2_reset, + msm_mux_usb2phy_ac, + msm_mux_usb_phy, + msm_mux_vfr_1, + msm_mux_vsense_trigger, + msm_mux_wlan1_adc0, + msm_mux_wlan1_adc1, + msm_mux_wlan2_adc0, + msm_mux_wlan2_adc1, + msm_mux__, +}; + +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15", + "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", + "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", + "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", + "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", + "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", "gpio50", + "gpio51", "gpio52", "gpio53", "gpio56", "gpio57", "gpio58", "gpio59", + "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65", "gpio66", + "gpio67", "gpio68", "gpio69", "gpio75", "gpio76", "gpio77", "gpio78", + "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", "gpio85", + "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", "gpio92", + "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", "gpio99", + "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", "gpio105", + "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", "gpio111", + "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", "gpio117", + "gpio118", "gpio119", "gpio120", "gpio124", "gpio125", "gpio126", + "gpio127", "gpio128", "gpio129", "gpio130", "gpio131", "gpio132", + "gpio133", "gpio134", "gpio135", "gpio136", "gpio141", "gpio142", + "gpio143", "gpio150", "gpio151", "gpio152", "gpio153", "gpio154", + "gpio155", +}; +static const char * const agera_pll_groups[] = { + "gpio89", +}; +static const char * const cci_async_groups[] = { + "gpio35", "gpio36", "gpio48", "gpio52", "gpio53", +}; +static const char * const cci_i2c_groups[] = { + "gpio2", "gpio3", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", + "gpio44", +}; +static const char * const gps_tx_groups[] = { + "gpio101", "gpio102", "gpio107", "gpio108", +}; +static const char * const gp_pdm0_groups[] = { + "gpio37", "gpio68", +}; +static const char * const gp_pdm1_groups[] = { + "gpio8", "gpio52", +}; +static const char * const gp_pdm2_groups[] = { + "gpio57", +}; +static const char * const jitter_bist_groups[] = { + "gpio90", +}; +static const char * const mclk_groups[] = { + "gpio93", +}; +static const char * const mdp_vsync_groups[] = { + "gpio6", "gpio23", "gpio24", "gpio27", "gpio28", +}; +static const char * const mss_lte_groups[] = { + "gpio65", "gpio66", +}; +static const char * const nav_pps_groups[] = { + "gpio101", "gpio101", "gpio102", "gpio102", +}; +static const char * const pll_bist_groups[] = { + "gpio27", +}; +static const char * const qlink0_wmss_groups[] = { + "gpio103", +}; +static const char * const qlink1_wmss_groups[] = { + "gpio106", +}; +static const char * const usb_phy_groups[] = { + "gpio124", +}; +static const char * const adsp_ext_groups[] = { + "gpio87", +}; +static const char * const atest_char_groups[] = { + "gpio95", +}; +static const char * const atest_char0_groups[] = { + "gpio96", +}; +static const char * const atest_char1_groups[] = { + "gpio97", +}; +static const char * const atest_char2_groups[] = { + "gpio98", +}; +static const char * const atest_char3_groups[] = { + "gpio99", +}; +static const char * const atest_tsens_groups[] = { + "gpio92", +}; +static const char * const atest_tsens2_groups[] = { + "gpio93", +}; +static const char * const atest_usb1_groups[] = { + "gpio83", +}; +static const char * const atest_usb10_groups[] = { + "gpio84", +}; +static const char * const atest_usb11_groups[] = { + "gpio85", +}; +static const char * const atest_usb12_groups[] = { + "gpio86", +}; +static const char * const atest_usb13_groups[] = { + "gpio87", +}; +static const char * const atest_usb2_groups[] = { + "gpio88", +}; +static const char * const atest_usb20_groups[] = { + "gpio89", +}; +static const char * const atest_usb21_groups[] = { + "gpio90", +}; +static const char * const atest_usb22_groups[] = { + "gpio91", +}; +static const char * const atest_usb23_groups[] = { + "gpio92", +}; +static const char * const audio_ref_groups[] = { + "gpio60", +}; +static const char * const btfm_slimbus_groups[] = { + "gpio67", "gpio68", "gpio86", "gpio87", +}; +static const char * const cam_mclk_groups[] = { + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", +}; +static const char * const cci_timer0_groups[] = { + "gpio34", +}; +static const char * const cci_timer1_groups[] = { + "gpio35", +}; +static const char * const cci_timer2_groups[] = { + "gpio36", +}; +static const char * const cci_timer3_groups[] = { + "gpio37", +}; +static const char * const cci_timer4_groups[] = { + "gpio38", +}; +static const char * const cri_trng_groups[] = { + "gpio0", "gpio1", "gpio2", +}; +static const char * const dbg_out_groups[] = { + "gpio3", +}; +static const char * const ddr_bist_groups[] = { + "gpio19", "gpio20", "gpio21", "gpio22", +}; +static const char * const ddr_pxi0_groups[] = { + "gpio86", "gpio90", +}; +static const char * const ddr_pxi1_groups[] = { + "gpio87", "gpio91", +}; +static const char * const ddr_pxi2_groups[] = { + "gpio88", "gpio92", +}; +static const char * const ddr_pxi3_groups[] = { + "gpio89", "gpio93", +}; +static const char * const dp_hot_groups[] = { + "gpio12", "gpio118", +}; +static const char * const edp_lcd_groups[] = { + "gpio23", +}; +static const char * const gcc_gp1_groups[] = { + "gpio48", "gpio58", +}; +static const char * const gcc_gp2_groups[] = { + "gpio21", +}; +static const char * const gcc_gp3_groups[] = { + "gpio22", +}; +static const char * const ibi_i3c_groups[] = { + "gpio0", "gpio1", +}; +static const char * const ldo_en_groups[] = { + "gpio95", +}; +static const char * const ldo_update_groups[] = { + "gpio96", +}; +static const char * const lpass_ext_groups[] = { + "gpio60", "gpio93", +}; +static const char * const m_voc_groups[] = { + "gpio12", +}; +static const char * const mdp_vsync0_groups[] = { + "gpio47", +}; +static const char * const mdp_vsync1_groups[] = { + "gpio48", +}; +static const char * const mdp_vsync2_groups[] = { + "gpio56", +}; +static const char * const mdp_vsync3_groups[] = { + "gpio57", +}; +static const char * const mi2s_0_groups[] = { + "gpio88", "gpio89", "gpio90", "gpio91", +}; +static const char * const mi2s_1_groups[] = { + "gpio67", "gpio68", "gpio86", "gpio87", +}; +static const char * const mi2s_2_groups[] = { + "gpio60", +}; +static const char * const nav_gpio_groups[] = { + "gpio101", "gpio102", +}; +static const char * const pa_indicator_groups[] = { + "gpio118", +}; +static const char * const phase_flag0_groups[] = { + "gpio12", +}; +static const char * const phase_flag1_groups[] = { + "gpio17", +}; +static const char * const phase_flag10_groups[] = { + "gpio41", +}; +static const char * const phase_flag11_groups[] = { + "gpio42", +}; +static const char * const phase_flag12_groups[] = { + "gpio43", +}; +static const char * const phase_flag13_groups[] = { + "gpio44", +}; +static const char * const phase_flag14_groups[] = { + "gpio45", +}; +static const char * const phase_flag15_groups[] = { + "gpio46", +}; +static const char * const phase_flag16_groups[] = { + "gpio47", +}; +static const char * const phase_flag17_groups[] = { + "gpio48", +}; +static const char * const phase_flag18_groups[] = { + "gpio49", +}; +static const char * const phase_flag19_groups[] = { + "gpio50", +}; +static const char * const phase_flag2_groups[] = { + "gpio18", +}; +static const char * const phase_flag20_groups[] = { + "gpio51", +}; +static const char * const phase_flag21_groups[] = { + "gpio52", +}; +static const char * const phase_flag22_groups[] = { + "gpio53", +}; +static const char * const phase_flag23_groups[] = { + "gpio56", +}; +static const char * const phase_flag24_groups[] = { + "gpio57", +}; +static const char * const phase_flag25_groups[] = { + "gpio60", +}; +static const char * const phase_flag26_groups[] = { + "gpio61", +}; +static const char * const phase_flag27_groups[] = { + "gpio62", +}; +static const char * const phase_flag28_groups[] = { + "gpio63", +}; +static const char * const phase_flag29_groups[] = { + "gpio64", +}; +static const char * const phase_flag3_groups[] = { + "gpio34", +}; +static const char * const phase_flag30_groups[] = { + "gpio67", +}; +static const char * const phase_flag31_groups[] = { + "gpio68", +}; +static const char * const phase_flag4_groups[] = { + "gpio35", +}; +static const char * const phase_flag5_groups[] = { + "gpio36", +}; +static const char * const phase_flag6_groups[] = { + "gpio37", +}; +static const char * const phase_flag7_groups[] = { + "gpio38", +}; +static const char * const phase_flag8_groups[] = { + "gpio39", +}; +static const char * const phase_flag9_groups[] = { + "gpio40", +}; +static const char * const pll_bypassnl_groups[] = { + "gpio13", +}; +static const char * const pll_clk_groups[] = { + "gpio98", +}; +static const char * const pll_reset_groups[] = { + "gpio14", +}; +static const char * const prng_rosc0_groups[] = { + "gpio97", +}; +static const char * const prng_rosc1_groups[] = { + "gpio98", +}; +static const char * const prng_rosc2_groups[] = { + "gpio99", +}; +static const char * const prng_rosc3_groups[] = { + "gpio100", +}; +static const char * const qdss_cti_groups[] = { + "gpio2", "gpio3", "gpio6", "gpio7", "gpio61", "gpio62", "gpio86", + "gpio87", +}; +static const char * const qdss_gpio_groups[] = { + "gpio8", "gpio9", "gpio63", "gpio64", +}; +static const char * const qdss_gpio0_groups[] = { + "gpio39", "gpio65", +}; +static const char * const qdss_gpio1_groups[] = { + "gpio40", "gpio66", +}; +static const char * const qdss_gpio10_groups[] = { + "gpio50", "gpio56", +}; +static const char * const qdss_gpio11_groups[] = { + "gpio51", "gpio57", +}; +static const char * const qdss_gpio12_groups[] = { + "gpio34", "gpio52", +}; +static const char * const qdss_gpio13_groups[] = { + "gpio35", "gpio53", +}; +static const char * const qdss_gpio14_groups[] = { + "gpio27", "gpio36", +}; +static const char * const qdss_gpio15_groups[] = { + "gpio28", "gpio37", +}; +static const char * const qdss_gpio2_groups[] = { + "gpio38", "gpio41", +}; +static const char * const qdss_gpio3_groups[] = { + "gpio42", "gpio47", +}; +static const char * const qdss_gpio4_groups[] = { + "gpio43", "gpio88", +}; +static const char * const qdss_gpio5_groups[] = { + "gpio44", "gpio89", +}; +static const char * const qdss_gpio6_groups[] = { + "gpio45", "gpio90", +}; +static const char * const qdss_gpio7_groups[] = { + "gpio46", "gpio91", +}; +static const char * const qdss_gpio8_groups[] = { + "gpio48", "gpio92", +}; +static const char * const qdss_gpio9_groups[] = { + "gpio49", "gpio93", +}; +static const char * const qlink0_enable_groups[] = { + "gpio105", +}; +static const char * const qlink0_request_groups[] = { + "gpio104", +}; +static const char * const qlink1_enable_groups[] = { + "gpio108", +}; +static const char * const qlink1_request_groups[] = { + "gpio107", +}; +static const char * const qup00_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", +}; +static const char * const qup01_groups[] = { + "gpio61", "gpio62", "gpio63", "gpio64", +}; +static const char * const qup02_groups[] = { + "gpio45", "gpio46", "gpio48", "gpio56", "gpio57", +}; +static const char * const qup10_groups[] = { + "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", +}; +static const char * const qup11_f1_groups[] = { + "gpio27", "gpio28", +}; +static const char * const qup11_f2_groups[] = { + "gpio27", "gpio28", +}; + +static const char * const qup12_groups[] = { + "gpio19", "gpio19", "gpio20", "gpio20", +}; +static const char * const qup13_f1_groups[] = { + "gpio25", "gpio26", +}; +static const char * const qup13_f2_groups[] = { + "gpio25", "gpio26", +}; +static const char * const qup14_groups[] = { + "gpio4", "gpio4", "gpio5", "gpio5", +}; +static const char * const sd_write_groups[] = { + "gpio85", +}; +static const char * const sdc1_tb_groups[] = { + "gpio4", +}; +static const char * const sdc2_tb_groups[] = { + "gpio5", +}; +static const char * const sp_cmu_groups[] = { + "gpio3", +}; +static const char * const tgu_ch0_groups[] = { + "gpio61", +}; +static const char * const tgu_ch1_groups[] = { + "gpio62", +}; +static const char * const tgu_ch2_groups[] = { + "gpio63", +}; +static const char * const tgu_ch3_groups[] = { + "gpio64", +}; +static const char * const tsense_pwm1_groups[] = { + "gpio88", +}; +static const char * const tsense_pwm2_groups[] = { + "gpio88", +}; +static const char * const uim1_clk_groups[] = { + "gpio80", +}; +static const char * const uim1_data_groups[] = { + "gpio79", +}; +static const char * const uim1_present_groups[] = { + "gpio82", +}; +static const char * const uim1_reset_groups[] = { + "gpio81", +}; +static const char * const uim2_clk_groups[] = { + "gpio76", +}; +static const char * const uim2_data_groups[] = { + "gpio75", +}; +static const char * const uim2_present_groups[] = { + "gpio78", +}; +static const char * const uim2_reset_groups[] = { + "gpio77", +}; +static const char * const usb2phy_ac_groups[] = { + "gpio47", +}; +static const char * const vfr_1_groups[] = { + "gpio49", +}; +static const char * const vsense_trigger_groups[] = { + "gpio89", +}; +static const char * const wlan1_adc0_groups[] = { + "gpio90", +}; +static const char * const wlan1_adc1_groups[] = { + "gpio92", +}; +static const char * const wlan2_adc0_groups[] = { + "gpio91", +}; +static const char * const wlan2_adc1_groups[] = { + "gpio93", +}; + +static const struct msm_function sm6375_functions[] = { + FUNCTION(adsp_ext), + FUNCTION(agera_pll), + FUNCTION(atest_char), + FUNCTION(atest_char0), + FUNCTION(atest_char1), + FUNCTION(atest_char2), + FUNCTION(atest_char3), + FUNCTION(atest_tsens), + FUNCTION(atest_tsens2), + FUNCTION(atest_usb1), + FUNCTION(atest_usb10), + FUNCTION(atest_usb11), + FUNCTION(atest_usb12), + FUNCTION(atest_usb13), + FUNCTION(atest_usb2), + FUNCTION(atest_usb20), + FUNCTION(atest_usb21), + FUNCTION(atest_usb22), + FUNCTION(atest_usb23), + FUNCTION(audio_ref), + FUNCTION(btfm_slimbus), + FUNCTION(cam_mclk), + FUNCTION(cci_async), + FUNCTION(cci_i2c), + FUNCTION(cci_timer0), + FUNCTION(cci_timer1), + FUNCTION(cci_timer2), + FUNCTION(cci_timer3), + FUNCTION(cci_timer4), + FUNCTION(cri_trng), + FUNCTION(dbg_out), + FUNCTION(ddr_bist), + FUNCTION(ddr_pxi0), + FUNCTION(ddr_pxi1), + FUNCTION(ddr_pxi2), + FUNCTION(ddr_pxi3), + FUNCTION(dp_hot), + FUNCTION(edp_lcd), + FUNCTION(gcc_gp1), + FUNCTION(gcc_gp2), + FUNCTION(gcc_gp3), + FUNCTION(gp_pdm0), + FUNCTION(gp_pdm1), + FUNCTION(gp_pdm2), + FUNCTION(gpio), + FUNCTION(gps_tx), + FUNCTION(ibi_i3c), + FUNCTION(jitter_bist), + FUNCTION(ldo_en), + FUNCTION(ldo_update), + FUNCTION(lpass_ext), + FUNCTION(m_voc), + FUNCTION(mclk), + FUNCTION(mdp_vsync), + FUNCTION(mdp_vsync0), + FUNCTION(mdp_vsync1), + FUNCTION(mdp_vsync2), + FUNCTION(mdp_vsync3), + FUNCTION(mi2s_0), + FUNCTION(mi2s_1), + FUNCTION(mi2s_2), + FUNCTION(mss_lte), + FUNCTION(nav_gpio), + FUNCTION(nav_pps), + FUNCTION(pa_indicator), + FUNCTION(phase_flag0), + FUNCTION(phase_flag1), + FUNCTION(phase_flag10), + FUNCTION(phase_flag11), + FUNCTION(phase_flag12), + FUNCTION(phase_flag13), + FUNCTION(phase_flag14), + FUNCTION(phase_flag15), + FUNCTION(phase_flag16), + FUNCTION(phase_flag17), + FUNCTION(phase_flag18), + FUNCTION(phase_flag19), + FUNCTION(phase_flag2), + FUNCTION(phase_flag20), + FUNCTION(phase_flag21), + FUNCTION(phase_flag22), + FUNCTION(phase_flag23), + FUNCTION(phase_flag24), + FUNCTION(phase_flag25), + FUNCTION(phase_flag26), + FUNCTION(phase_flag27), + FUNCTION(phase_flag28), + FUNCTION(phase_flag29), + FUNCTION(phase_flag3), + FUNCTION(phase_flag30), + FUNCTION(phase_flag31), + FUNCTION(phase_flag4), + FUNCTION(phase_flag5), + FUNCTION(phase_flag6), + FUNCTION(phase_flag7), + FUNCTION(phase_flag8), + FUNCTION(phase_flag9), + FUNCTION(pll_bist), + FUNCTION(pll_bypassnl), + FUNCTION(pll_clk), + FUNCTION(pll_reset), + FUNCTION(prng_rosc0), + FUNCTION(prng_rosc1), + FUNCTION(prng_rosc2), + FUNCTION(prng_rosc3), + FUNCTION(qdss_cti), + FUNCTION(qdss_gpio), + FUNCTION(qdss_gpio0), + FUNCTION(qdss_gpio1), + FUNCTION(qdss_gpio10), + FUNCTION(qdss_gpio11), + FUNCTION(qdss_gpio12), + FUNCTION(qdss_gpio13), + FUNCTION(qdss_gpio14), + FUNCTION(qdss_gpio15), + FUNCTION(qdss_gpio2), + FUNCTION(qdss_gpio3), + FUNCTION(qdss_gpio4), + FUNCTION(qdss_gpio5), + FUNCTION(qdss_gpio6), + FUNCTION(qdss_gpio7), + FUNCTION(qdss_gpio8), + FUNCTION(qdss_gpio9), + FUNCTION(qlink0_enable), + FUNCTION(qlink0_request), + FUNCTION(qlink0_wmss), + FUNCTION(qlink1_enable), + FUNCTION(qlink1_request), + FUNCTION(qlink1_wmss), + FUNCTION(qup00), + FUNCTION(qup01), + FUNCTION(qup02), + FUNCTION(qup10), + FUNCTION(qup11_f1), + FUNCTION(qup11_f2), + FUNCTION(qup12), + FUNCTION(qup13_f1), + FUNCTION(qup13_f2), + FUNCTION(qup14), + FUNCTION(sd_write), + FUNCTION(sdc1_tb), + FUNCTION(sdc2_tb), + FUNCTION(sp_cmu), + FUNCTION(tgu_ch0), + FUNCTION(tgu_ch1), + FUNCTION(tgu_ch2), + FUNCTION(tgu_ch3), + FUNCTION(tsense_pwm1), + FUNCTION(tsense_pwm2), + FUNCTION(uim1_clk), + FUNCTION(uim1_data), + FUNCTION(uim1_present), + FUNCTION(uim1_reset), + FUNCTION(uim2_clk), + FUNCTION(uim2_data), + FUNCTION(uim2_present), + FUNCTION(uim2_reset), + FUNCTION(usb2phy_ac), + FUNCTION(usb_phy), + FUNCTION(vfr_1), + FUNCTION(vsense_trigger), + FUNCTION(wlan1_adc0), + FUNCTION(wlan1_adc1), + FUNCTION(wlan2_adc0), + FUNCTION(wlan2_adc1), +}; + +/* + * Every pin is maintained as a single group, and missing or non-existing pin + * would be maintained as dummy group to synchronize pin group index with + * pin descriptor registered with pinctrl core. + * Clients would not be able to request these dummy pin groups. + */ +static const struct msm_pingroup sm6375_groups[] = { + [0] = PINGROUP(0, ibi_i3c, qup00, cri_trng, _, _, _, _, _, _), + [1] = PINGROUP(1, ibi_i3c, qup00, cri_trng, _, _, _, _, _, _), + [2] = PINGROUP(2, qup00, cci_i2c, cri_trng, qdss_cti, _, _, _, _, _), + [3] = PINGROUP(3, qup00, cci_i2c, sp_cmu, dbg_out, qdss_cti, _, _, _, _), + [4] = PINGROUP(4, qup14, qup14, sdc1_tb, _, _, _, _, _, _), + [5] = PINGROUP(5, qup14, qup14, sdc2_tb, _, _, _, _, _, _), + [6] = PINGROUP(6, mdp_vsync, qdss_cti, _, _, _, _, _, _, _), + [7] = PINGROUP(7, qdss_cti, _, _, _, _, _, _, _, _), + [8] = PINGROUP(8, gp_pdm1, qdss_gpio, _, _, _, _, _, _, _), + [9] = PINGROUP(9, qdss_gpio, _, _, _, _, _, _, _, _), + [10] = PINGROUP(10, _, _, _, _, _, _, _, _, _), + [11] = PINGROUP(11, _, _, _, _, _, _, _, _, _), + [12] = PINGROUP(12, m_voc, dp_hot, _, phase_flag0, _, _, _, _, _), + [13] = PINGROUP(13, qup10, pll_bypassnl, _, _, _, _, _, _, _), + [14] = PINGROUP(14, qup10, pll_reset, _, _, _, _, _, _, _), + [15] = PINGROUP(15, qup10, _, _, _, _, _, _, _, _), + [16] = PINGROUP(16, qup10, _, _, _, _, _, _, _, _), + [17] = PINGROUP(17, _, phase_flag1, qup10, _, _, _, _, _, _), + [18] = PINGROUP(18, _, phase_flag2, _, _, _, _, _, _, _), + [19] = PINGROUP(19, qup12, qup12, ddr_bist, _, _, _, _, _, _), + [20] = PINGROUP(20, qup12, qup12, ddr_bist, _, _, _, _, _, _), + [21] = PINGROUP(21, gcc_gp2, ddr_bist, _, _, _, _, _, _, _), + [22] = PINGROUP(22, gcc_gp3, ddr_bist, _, _, _, _, _, _, _), + [23] = PINGROUP(23, mdp_vsync, edp_lcd, _, _, _, _, _, _, _), + [24] = PINGROUP(24, mdp_vsync, _, _, _, _, _, _, _, _), + [25] = PINGROUP(25, qup13_f1, qup13_f2, _, _, _, _, _, _, _), + [26] = PINGROUP(26, qup13_f1, qup13_f2, _, _, _, _, _, _, _), + [27] = PINGROUP(27, qup11_f1, qup11_f2, mdp_vsync, pll_bist, _, qdss_gpio14, _, _, _), + [28] = PINGROUP(28, qup11_f1, qup11_f2, mdp_vsync, _, qdss_gpio15, _, _, _, _), + [29] = PINGROUP(29, cam_mclk, _, _, _, _, _, _, _, _), + [30] = PINGROUP(30, cam_mclk, _, _, _, _, _, _, _, _), + [31] = PINGROUP(31, cam_mclk, _, _, _, _, _, _, _, _), + [32] = PINGROUP(32, cam_mclk, _, _, _, _, _, _, _, _), + [33] = PINGROUP(33, cam_mclk, _, _, _, _, _, _, _, _), + [34] = PINGROUP(34, cci_timer0, _, phase_flag3, qdss_gpio12, _, _, _, _, _), + [35] = PINGROUP(35, cci_timer1, cci_async, _, phase_flag4, qdss_gpio13, _, _, _, _), + [36] = PINGROUP(36, cci_timer2, cci_async, _, phase_flag5, qdss_gpio14, _, _, _, _), + [37] = PINGROUP(37, cci_timer3, gp_pdm0, _, phase_flag6, qdss_gpio15, _, _, _, _), + [38] = PINGROUP(38, cci_timer4, _, phase_flag7, qdss_gpio2, _, _, _, _, _), + [39] = PINGROUP(39, cci_i2c, _, phase_flag8, qdss_gpio0, _, _, _, _, _), + [40] = PINGROUP(40, cci_i2c, _, phase_flag9, qdss_gpio1, _, _, _, _, _), + [41] = PINGROUP(41, cci_i2c, _, phase_flag10, qdss_gpio2, _, _, _, _, _), + [42] = PINGROUP(42, cci_i2c, _, phase_flag11, qdss_gpio3, _, _, _, _, _), + [43] = PINGROUP(43, cci_i2c, _, phase_flag12, qdss_gpio4, _, _, _, _, _), + [44] = PINGROUP(44, cci_i2c, _, phase_flag13, qdss_gpio5, _, _, _, _, _), + [45] = PINGROUP(45, qup02, _, phase_flag14, qdss_gpio6, _, _, _, _, _), + [46] = PINGROUP(46, qup02, _, phase_flag15, qdss_gpio7, _, _, _, _, _), + [47] = PINGROUP(47, mdp_vsync0, _, phase_flag16, qdss_gpio3, _, _, usb2phy_ac, _, _), + [48] = PINGROUP(48, cci_async, mdp_vsync1, gcc_gp1, _, phase_flag17, qdss_gpio8, qup02, + _, _), + [49] = PINGROUP(49, vfr_1, _, phase_flag18, qdss_gpio9, _, _, _, _, _), + [50] = PINGROUP(50, _, phase_flag19, qdss_gpio10, _, _, _, _, _, _), + [51] = PINGROUP(51, _, phase_flag20, qdss_gpio11, _, _, _, _, _, _), + [52] = PINGROUP(52, cci_async, gp_pdm1, _, phase_flag21, qdss_gpio12, _, _, _, _), + [53] = PINGROUP(53, cci_async, _, phase_flag22, qdss_gpio13, _, _, _, _, _), + [54] = PINGROUP(54, _, _, _, _, _, _, _, _, _), + [55] = PINGROUP(55, _, _, _, _, _, _, _, _, _), + [56] = PINGROUP(56, qup02, mdp_vsync2, _, phase_flag23, qdss_gpio10, _, _, _, _), + [57] = PINGROUP(57, qup02, mdp_vsync3, gp_pdm2, _, phase_flag24, qdss_gpio11, _, _, _), + [58] = PINGROUP(58, gcc_gp1, _, _, _, _, _, _, _, _), + [59] = PINGROUP(59, _, _, _, _, _, _, _, _, _), + [60] = PINGROUP(60, audio_ref, lpass_ext, mi2s_2, _, phase_flag25, _, _, _, _), + [61] = PINGROUP(61, qup01, tgu_ch0, _, phase_flag26, qdss_cti, _, _, _, _), + [62] = PINGROUP(62, qup01, tgu_ch1, _, phase_flag27, qdss_cti, _, _, _, _), + [63] = PINGROUP(63, qup01, tgu_ch2, _, phase_flag28, qdss_gpio, _, _, _, _), + [64] = PINGROUP(64, qup01, tgu_ch3, _, phase_flag29, qdss_gpio, _, _, _, _), + [65] = PINGROUP(65, mss_lte, _, qdss_gpio0, _, _, _, _, _, _), + [66] = PINGROUP(66, mss_lte, _, qdss_gpio1, _, _, _, _, _, _), + [67] = PINGROUP(67, btfm_slimbus, mi2s_1, _, phase_flag30, _, _, _, _, _), + [68] = PINGROUP(68, btfm_slimbus, mi2s_1, gp_pdm0, _, phase_flag31, _, _, _, _), + [69] = PINGROUP(69, _, _, _, _, _, _, _, _, _), + [70] = PINGROUP(70, _, _, _, _, _, _, _, _, _), + [71] = PINGROUP(71, _, _, _, _, _, _, _, _, _), + [72] = PINGROUP(72, _, _, _, _, _, _, _, _, _), + [73] = PINGROUP(73, _, _, _, _, _, _, _, _, _), + [74] = PINGROUP(74, _, _, _, _, _, _, _, _, _), + [75] = PINGROUP(75, uim2_data, _, _, _, _, _, _, _, _), + [76] = PINGROUP(76, uim2_clk, _, _, _, _, _, _, _, _), + [77] = PINGROUP(77, uim2_reset, _, _, _, _, _, _, _, _), + [78] = PINGROUP(78, uim2_present, _, _, _, _, _, _, _, _), + [79] = PINGROUP(79, uim1_data, _, _, _, _, _, _, _, _), + [80] = PINGROUP(80, uim1_clk, _, _, _, _, _, _, _, _), + [81] = PINGROUP(81, uim1_reset, _, _, _, _, _, _, _, _), + [82] = PINGROUP(82, uim1_present, _, _, _, _, _, _, _, _), + [83] = PINGROUP(83, atest_usb1, _, _, _, _, _, _, _, _), + [84] = PINGROUP(84, _, atest_usb10, _, _, _, _, _, _, _), + [85] = PINGROUP(85, sd_write, _, atest_usb11, _, _, _, _, _, _), + [86] = PINGROUP(86, btfm_slimbus, mi2s_1, _, qdss_cti, atest_usb12, ddr_pxi0, _, _, _), + [87] = PINGROUP(87, btfm_slimbus, mi2s_1, adsp_ext, _, qdss_cti, atest_usb13, ddr_pxi1, _, + _), + [88] = PINGROUP(88, mi2s_0, _, qdss_gpio4, _, atest_usb2, ddr_pxi2, tsense_pwm1, + tsense_pwm2, _), + [89] = PINGROUP(89, mi2s_0, agera_pll, _, qdss_gpio5, _, vsense_trigger, atest_usb20, + ddr_pxi3, _), + [90] = PINGROUP(90, mi2s_0, jitter_bist, _, qdss_gpio6, _, wlan1_adc0, atest_usb21, + ddr_pxi0, _), + [91] = PINGROUP(91, mi2s_0, _, qdss_gpio7, _, wlan2_adc0, atest_usb22, ddr_pxi1, _, _), + [92] = PINGROUP(92, _, qdss_gpio8, atest_tsens, wlan1_adc1, atest_usb23, ddr_pxi2, _, _, + _), + [93] = PINGROUP(93, mclk, lpass_ext, _, qdss_gpio9, atest_tsens2, wlan2_adc1, ddr_pxi3, + _, _), + [94] = PINGROUP(94, _, _, _, _, _, _, _, _, _), + [95] = PINGROUP(95, ldo_en, _, atest_char, _, _, _, _, _, _), + [96] = PINGROUP(96, ldo_update, _, atest_char0, _, _, _, _, _, _), + [97] = PINGROUP(97, prng_rosc0, _, atest_char1, _, _, _, _, _, _), + [98] = PINGROUP(98, _, atest_char2, _, _, prng_rosc1, pll_clk, _, _, _), + [99] = PINGROUP(99, _, atest_char3, _, _, prng_rosc2, _, _, _, _), + [100] = PINGROUP(100, _, _, prng_rosc3, _, _, _, _, _, _), + [101] = PINGROUP(101, nav_gpio, nav_pps, nav_pps, gps_tx, _, _, _, _, _), + [102] = PINGROUP(102, nav_gpio, nav_pps, nav_pps, gps_tx, _, _, _, _, _), + [103] = PINGROUP(103, qlink0_wmss, _, _, _, _, _, _, _, _), + [104] = PINGROUP(104, qlink0_request, _, _, _, _, _, _, _, _), + [105] = PINGROUP(105, qlink0_enable, _, _, _, _, _, _, _, _), + [106] = PINGROUP(106, qlink1_wmss, _, _, _, _, _, _, _, _), + [107] = PINGROUP(107, qlink1_request, gps_tx, _, _, _, _, _, _, _), + [108] = PINGROUP(108, qlink1_enable, gps_tx, _, _, _, _, _, _, _), + [109] = PINGROUP(109, _, _, _, _, _, _, _, _, _), + [110] = PINGROUP(110, _, _, _, _, _, _, _, _, _), + [111] = PINGROUP(111, _, _, _, _, _, _, _, _, _), + [112] = PINGROUP(112, _, _, _, _, _, _, _, _, _), + [113] = PINGROUP(113, _, _, _, _, _, _, _, _, _), + [114] = PINGROUP(114, _, _, _, _, _, _, _, _, _), + [115] = PINGROUP(115, _, _, _, _, _, _, _, _, _), + [116] = PINGROUP(116, _, _, _, _, _, _, _, _, _), + [117] = PINGROUP(117, _, _, _, _, _, _, _, _, _), + [118] = PINGROUP(118, _, _, pa_indicator, dp_hot, _, _, _, _, _), + [119] = PINGROUP(119, _, _, _, _, _, _, _, _, _), + [120] = PINGROUP(120, _, _, _, _, _, _, _, _, _), + [121] = PINGROUP(121, _, _, _, _, _, _, _, _, _), + [122] = PINGROUP(122, _, _, _, _, _, _, _, _, _), + [123] = PINGROUP(123, _, _, _, _, _, _, _, _, _), + [124] = PINGROUP(124, usb_phy, _, _, _, _, _, _, _, _), + [125] = PINGROUP(125, _, _, _, _, _, _, _, _, _), + [126] = PINGROUP(126, _, _, _, _, _, _, _, _, _), + [127] = PINGROUP(127, _, _, _, _, _, _, _, _, _), + [128] = PINGROUP(128, _, _, _, _, _, _, _, _, _), + [129] = PINGROUP(129, _, _, _, _, _, _, _, _, _), + [130] = PINGROUP(130, _, _, _, _, _, _, _, _, _), + [131] = PINGROUP(131, _, _, _, _, _, _, _, _, _), + [132] = PINGROUP(132, _, _, _, _, _, _, _, _, _), + [133] = PINGROUP(133, _, _, _, _, _, _, _, _, _), + [134] = PINGROUP(134, _, _, _, _, _, _, _, _, _), + [135] = PINGROUP(135, _, _, _, _, _, _, _, _, _), + [136] = PINGROUP(136, _, _, _, _, _, _, _, _, _), + [137] = PINGROUP(137, _, _, _, _, _, _, _, _, _), + [138] = PINGROUP(138, _, _, _, _, _, _, _, _, _), + [139] = PINGROUP(139, _, _, _, _, _, _, _, _, _), + [140] = PINGROUP(140, _, _, _, _, _, _, _, _, _), + [141] = PINGROUP(141, _, _, _, _, _, _, _, _, _), + [142] = PINGROUP(142, _, _, _, _, _, _, _, _, _), + [143] = PINGROUP(143, _, _, _, _, _, _, _, _, _), + [144] = PINGROUP(144, _, _, _, _, _, _, _, _, _), + [145] = PINGROUP(145, _, _, _, _, _, _, _, _, _), + [146] = PINGROUP(146, _, _, _, _, _, _, _, _, _), + [147] = PINGROUP(147, _, _, _, _, _, _, _, _, _), + [148] = PINGROUP(148, _, _, _, _, _, _, _, _, _), + [149] = PINGROUP(149, _, _, _, _, _, _, _, _, _), + [150] = PINGROUP(150, _, _, _, _, _, _, _, _, _), + [151] = PINGROUP(151, _, _, _, _, _, _, _, _, _), + [152] = PINGROUP(152, _, _, _, _, _, _, _, _, _), + [153] = PINGROUP(153, _, _, _, _, _, _, _, _, _), + [154] = PINGROUP(154, _, _, _, _, _, _, _, _, _), + [155] = PINGROUP(155, _, _, _, _, _, _, _, _, _), + [156] = UFS_RESET(ufs_reset, 0x1ae000), + [157] = SDC_PINGROUP(sdc1_rclk, 0x1a1000, 0, 0), + [158] = SDC_PINGROUP(sdc1_clk, 0x1a0000, 13, 6), + [159] = SDC_PINGROUP(sdc1_cmd, 0x1a0000, 11, 3), + [160] = SDC_PINGROUP(sdc1_data, 0x1a0000, 9, 0), + [161] = SDC_PINGROUP(sdc2_clk, 0x1a2000, 14, 6), + [162] = SDC_PINGROUP(sdc2_cmd, 0x1a2000, 11, 3), + [163] = SDC_PINGROUP(sdc2_data, 0x1a2000, 9, 0), +}; + +static const struct msm_gpio_wakeirq_map sm6375_mpm_map[] = { + { 0, 84 }, { 3, 6 }, { 4, 7 }, { 7, 8 }, { 8, 9 }, { 9, 10 }, { 11, 11 }, { 12, 13 }, + { 13, 14 }, { 16, 16 }, { 17, 17 }, { 18, 18 }, { 19, 19 }, { 21, 20 }, { 22, 21 }, + { 23, 23 }, { 24, 24 }, { 25, 25 }, { 27, 26 }, { 28, 27 }, { 37, 28 }, { 38, 29 }, + { 48, 30 }, { 50, 31 }, { 51, 32 }, { 52, 33 }, { 57, 34 }, { 59, 35 }, { 60, 37 }, + { 61, 38 }, { 62, 39 }, { 64, 40 }, { 66, 41 }, { 67, 42 }, { 68, 43 }, { 69, 44 }, + { 78, 45 }, { 82, 36 }, { 83, 47 }, { 84, 48 }, { 85, 49 }, { 87, 50 }, { 88, 51 }, + { 91, 52 }, { 94, 53 }, { 95, 54 }, { 96, 55 }, { 97, 56 }, { 98, 57 }, { 99, 58 }, + { 100, 59 }, { 104, 60 }, { 107, 61 }, { 118, 62 }, { 124, 63 }, { 125, 64 }, { 126, 65 }, + { 128, 66 }, { 129, 67 }, { 131, 69 }, { 133, 70 }, { 134, 71 }, { 136, 73 }, { 142, 74 }, + { 150, 75 }, { 153, 76 }, { 155, 77 }, +}; + +static const struct msm_pinctrl_soc_data sm6375_tlmm = { + .pins = sm6375_pins, + .npins = ARRAY_SIZE(sm6375_pins), + .functions = sm6375_functions, + .nfunctions = ARRAY_SIZE(sm6375_functions), + .groups = sm6375_groups, + .ngroups = ARRAY_SIZE(sm6375_groups), + .ngpios = 157, + .wakeirq_map = sm6375_mpm_map, + .nwakeirq_map = ARRAY_SIZE(sm6375_mpm_map), +}; + +static int sm6375_tlmm_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &sm6375_tlmm); +} + +static const struct of_device_id sm6375_tlmm_of_match[] = { + { .compatible = "qcom,sm6375-tlmm", }, + { }, +}; + +static struct platform_driver sm6375_tlmm_driver = { + .driver = { + .name = "sm6375-tlmm", + .of_match_table = sm6375_tlmm_of_match, + }, + .probe = sm6375_tlmm_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init sm6375_tlmm_init(void) +{ + return platform_driver_register(&sm6375_tlmm_driver); +} +arch_initcall(sm6375_tlmm_init); + +static void __exit sm6375_tlmm_exit(void) +{ + platform_driver_unregister(&sm6375_tlmm_driver); +} +module_exit(sm6375_tlmm_exit); + +MODULE_DESCRIPTION("QTI SM6375 TLMM driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, sm6375_tlmm_of_match); diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index af144e724bd9..3bd7f9fedcc3 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -1316,7 +1316,7 @@ static const struct msm_pingroup sm8250_groups[] = { static const struct msm_gpio_wakeirq_map sm8250_pdc_map[] = { { 0, 79 }, { 1, 84 }, { 2, 80 }, { 3, 82 }, { 4, 107 }, { 7, 43 }, { 11, 42 }, { 14, 44 }, { 15, 52 }, { 19, 67 }, { 23, 68 }, { 24, 105 }, - { 27, 92 }, { 28, 106 }, { 31, 69 }, { 35, 70 }, { 39, 37 }, + { 27, 92 }, { 28, 106 }, { 31, 69 }, { 35, 70 }, { 39, 73 }, { 40, 108 }, { 43, 71 }, { 45, 72 }, { 47, 83 }, { 51, 74 }, { 55, 77 }, { 59, 78 }, { 63, 75 }, { 64, 81 }, { 65, 87 }, { 66, 88 }, { 67, 89 }, { 68, 54 }, { 70, 85 }, { 77, 46 }, { 80, 90 }, { 81, 91 }, { 83, 97 }, diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 3be2a08ae3a6..ccaf40a9c0e6 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1159,6 +1159,7 @@ static const struct of_device_id pmic_gpio_of_match[] = { /* pm8150l has 12 GPIOs with holes on 7 */ { .compatible = "qcom,pm8150l-gpio", .data = (void *) 12 }, { .compatible = "qcom,pmc8180c-gpio", .data = (void *) 12 }, + { .compatible = "qcom,pm8226-gpio", .data = (void *) 8 }, { .compatible = "qcom,pm8350-gpio", .data = (void *) 10 }, { .compatible = "qcom,pm8350b-gpio", .data = (void *) 8 }, { .compatible = "qcom,pm8350c-gpio", .data = (void *) 9 }, @@ -1175,6 +1176,8 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 }, { .compatible = "qcom,pmk8350-gpio", .data = (void *) 4 }, { .compatible = "qcom,pmm8155au-gpio", .data = (void *) 10 }, + /* pmp8074 has 12 GPIOs with holes on 1 and 12 */ + { .compatible = "qcom,pmp8074-gpio", .data = (void *) 12 }, { .compatible = "qcom,pmr735a-gpio", .data = (void *) 4 }, { .compatible = "qcom,pmr735b-gpio", .data = (void *) 4 }, /* pms405 has 12 GPIOs with holes on 1, 9, and 10 */ diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig index 961007ce7b3a..0903a0a41831 100644 --- a/drivers/pinctrl/renesas/Kconfig +++ b/drivers/pinctrl/renesas/Kconfig @@ -38,7 +38,9 @@ config PINCTRL_RENESAS select PINCTRL_PFC_R8A77995 if ARCH_R8A77995 select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0 select PINCTRL_PFC_R8A779F0 if ARCH_R8A779F0 + select PINCTRL_PFC_R8A779G0 if ARCH_R8A779G0 select PINCTRL_RZG2L if ARCH_RZG2L + select PINCTRL_RZV2M if ARCH_R9A09G011 select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203 select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264 select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269 @@ -153,6 +155,10 @@ config PINCTRL_PFC_R8A779A0 bool "pin control support for R-Car V3U" if COMPILE_TEST select PINCTRL_SH_PFC +config PINCTRL_PFC_R8A779G0 + bool "pin control support for R-Car V4H" if COMPILE_TEST + select PINCTRL_SH_PFC + config PINCTRL_PFC_R8A7740 bool "pin control support for R-Mobile A1" if COMPILE_TEST select PINCTRL_SH_PFC_GPIO @@ -237,6 +243,18 @@ config PINCTRL_RZN1 help This selects pinctrl driver for Renesas RZ/N1 devices. +config PINCTRL_RZV2M + bool "pin control support for RZ/V2M" + depends on OF + depends on ARCH_R9A09G011 || COMPILE_TEST + select GPIOLIB + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + select GENERIC_PINCONF + help + This selects GPIO and pinctrl driver for Renesas RZ/V2M + platforms. + config PINCTRL_PFC_SH7203 bool "pin control support for SH7203" if COMPILE_TEST select PINCTRL_SH_FUNC_GPIO diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile index 5d936c154a6f..558b30ce0dec 100644 --- a/drivers/pinctrl/renesas/Makefile +++ b/drivers/pinctrl/renesas/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o obj-$(CONFIG_PINCTRL_PFC_R8A779A0) += pfc-r8a779a0.o obj-$(CONFIG_PINCTRL_PFC_R8A779F0) += pfc-r8a779f0.o +obj-$(CONFIG_PINCTRL_PFC_R8A779G0) += pfc-r8a779g0.o obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o @@ -49,6 +50,7 @@ obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o obj-$(CONFIG_PINCTRL_RZA2) += pinctrl-rza2.o obj-$(CONFIG_PINCTRL_RZG2L) += pinctrl-rzg2l.o obj-$(CONFIG_PINCTRL_RZN1) += pinctrl-rzn1.o +obj-$(CONFIG_PINCTRL_RZV2M) += pinctrl-rzv2m.o ifeq ($(CONFIG_COMPILE_TEST),y) CFLAGS_pfc-sh7203.o += -I$(srctree)/arch/sh/include/cpu-sh2a diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c index 8c14b2021bf0..c91102d3f1d1 100644 --- a/drivers/pinctrl/renesas/core.c +++ b/drivers/pinctrl/renesas/core.c @@ -644,6 +644,12 @@ static const struct of_device_id sh_pfc_of_table[] = { .data = &r8a779f0_pinmux_info, }, #endif +#ifdef CONFIG_PINCTRL_PFC_R8A779G0 + { + .compatible = "renesas,pfc-r8a779g0", + .data = &r8a779g0_pinmux_info, + }, +#endif #ifdef CONFIG_PINCTRL_PFC_SH73A0 { .compatible = "renesas,pfc-sh73a0", diff --git a/drivers/pinctrl/renesas/pfc-r8a779f0.c b/drivers/pinctrl/renesas/pfc-r8a779f0.c index aaca4ee2af55..417c357f16b1 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779f0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779f0.c @@ -1902,7 +1902,6 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = { enum ioctrl_regs { POC0, POC1, - POC2, POC3, TD0SEL1, }; @@ -1910,7 +1909,6 @@ enum ioctrl_regs { static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = { [POC0] = { 0xe60500a0, }, [POC1] = { 0xe60508a0, }, - [POC2] = { 0xe60510a0, }, [POC3] = { 0xe60518a0, }, [TD0SEL1] = { 0xe6050920, }, { /* sentinel */ }, diff --git a/drivers/pinctrl/renesas/pfc-r8a779g0.c b/drivers/pinctrl/renesas/pfc-r8a779g0.c new file mode 100644 index 000000000000..5dd1c2c7708a --- /dev/null +++ b/drivers/pinctrl/renesas/pfc-r8a779g0.c @@ -0,0 +1,4262 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * R8A779A0 processor support - PFC hardware block. + * + * Copyright (C) 2021 Renesas Electronics Corp. + * + * This file is based on the drivers/pinctrl/renesas/pfc-r8a779a0.c + */ + +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "sh_pfc.h" + +#define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN) + +#define CPU_ALL_GP(fn, sfx) \ + PORT_GP_CFG_19(0, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \ + PORT_GP_CFG_23(1, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \ + PORT_GP_CFG_1(1, 23, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(1, 24, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(1, 25, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(1, 26, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(1, 27, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(1, 28, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_20(2, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_13(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33), \ + PORT_GP_CFG_1(3, 13, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 14, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 15, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 16, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 17, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 18, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 19, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 20, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 21, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 22, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 23, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 24, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 25, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 26, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 27, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 28, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_1(3, 29, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_25(4, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_21(5, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_21(6, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_21(7, fn, sfx, CFG_FLAGS), \ + PORT_GP_CFG_14(8, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE_18_33) + +/* GPSR0 */ +#define GPSR0_18 F_(MSIOF2_RXD, IP2SR0_11_8) +#define GPSR0_17 F_(MSIOF2_SCK, IP2SR0_7_4) +#define GPSR0_16 F_(MSIOF2_TXD, IP2SR0_3_0) +#define GPSR0_15 F_(MSIOF2_SYNC, IP1SR0_31_28) +#define GPSR0_14 F_(MSIOF2_SS1, IP1SR0_27_24) +#define GPSR0_13 F_(MSIOF2_SS2, IP1SR0_23_20) +#define GPSR0_12 F_(MSIOF5_RXD, IP1SR0_19_16) +#define GPSR0_11 F_(MSIOF5_SCK, IP1SR0_15_12) +#define GPSR0_10 F_(MSIOF5_TXD, IP1SR0_11_8) +#define GPSR0_9 F_(MSIOF5_SYNC, IP1SR0_7_4) +#define GPSR0_8 F_(MSIOF5_SS1, IP1SR0_3_0) +#define GPSR0_7 F_(MSIOF5_SS2, IP0SR0_31_28) +#define GPSR0_6 F_(IRQ0, IP0SR0_27_24) +#define GPSR0_5 F_(IRQ1, IP0SR0_23_20) +#define GPSR0_4 F_(IRQ2, IP0SR0_19_16) +#define GPSR0_3 F_(IRQ3, IP0SR0_15_12) +#define GPSR0_2 F_(GP0_02, IP0SR0_11_8) +#define GPSR0_1 F_(GP0_01, IP0SR0_7_4) +#define GPSR0_0 F_(GP0_00, IP0SR0_3_0) + +/* GPSR1 */ +#define GPSR1_28 F_(HTX3, IP3SR1_19_16) +#define GPSR1_27 F_(HCTS3_N, IP3SR1_15_12) +#define GPSR1_26 F_(HRTS3_N, IP3SR1_11_8) +#define GPSR1_25 F_(HSCK3, IP3SR1_7_4) +#define GPSR1_24 F_(HRX3, IP3SR1_3_0) +#define GPSR1_23 F_(GP1_23, IP2SR1_31_28) +#define GPSR1_22 F_(AUDIO_CLKIN, IP2SR1_27_24) +#define GPSR1_21 F_(AUDIO_CLKOUT, IP2SR1_23_20) +#define GPSR1_20 F_(SSI_SD, IP2SR1_19_16) +#define GPSR1_19 F_(SSI_WS, IP2SR1_15_12) +#define GPSR1_18 F_(SSI_SCK, IP2SR1_11_8) +#define GPSR1_17 F_(SCIF_CLK, IP2SR1_7_4) +#define GPSR1_16 F_(HRX0, IP2SR1_3_0) +#define GPSR1_15 F_(HSCK0, IP1SR1_31_28) +#define GPSR1_14 F_(HRTS0_N, IP1SR1_27_24) +#define GPSR1_13 F_(HCTS0_N, IP1SR1_23_20) +#define GPSR1_12 F_(HTX0, IP1SR1_19_16) +#define GPSR1_11 F_(MSIOF0_RXD, IP1SR1_15_12) +#define GPSR1_10 F_(MSIOF0_SCK, IP1SR1_11_8) +#define GPSR1_9 F_(MSIOF0_TXD, IP1SR1_7_4) +#define GPSR1_8 F_(MSIOF0_SYNC, IP1SR1_3_0) +#define GPSR1_7 F_(MSIOF0_SS1, IP0SR1_31_28) +#define GPSR1_6 F_(MSIOF0_SS2, IP0SR1_27_24) +#define GPSR1_5 F_(MSIOF1_RXD, IP0SR1_23_20) +#define GPSR1_4 F_(MSIOF1_TXD, IP0SR1_19_16) +#define GPSR1_3 F_(MSIOF1_SCK, IP0SR1_15_12) +#define GPSR1_2 F_(MSIOF1_SYNC, IP0SR1_11_8) +#define GPSR1_1 F_(MSIOF1_SS1, IP0SR1_7_4) +#define GPSR1_0 F_(MSIOF1_SS2, IP0SR1_3_0) + +/* GPSR2 */ +#define GPSR2_19 F_(CANFD7_RX, IP2SR2_15_12) +#define GPSR2_18 F_(CANFD7_TX, IP2SR2_11_8) +#define GPSR2_17 F_(CANFD4_RX, IP2SR2_7_4) +#define GPSR2_16 F_(CANFD4_TX, IP2SR2_3_0) +#define GPSR2_15 F_(CANFD3_RX, IP1SR2_31_28) +#define GPSR2_14 F_(CANFD3_TX, IP1SR2_27_24) +#define GPSR2_13 F_(CANFD2_RX, IP1SR2_23_20) +#define GPSR2_12 F_(CANFD2_TX, IP1SR2_19_16) +#define GPSR2_11 F_(CANFD0_RX, IP1SR2_15_12) +#define GPSR2_10 F_(CANFD0_TX, IP1SR2_11_8) +#define GPSR2_9 F_(CAN_CLK, IP1SR2_7_4) +#define GPSR2_8 F_(TPU0TO0, IP1SR2_3_0) +#define GPSR2_7 F_(TPU0TO1, IP0SR2_31_28) +#define GPSR2_6 F_(FXR_TXDB, IP0SR2_27_24) +#define GPSR2_5 F_(FXR_TXENB_N, IP0SR2_23_20) +#define GPSR2_4 F_(RXDB_EXTFXR, IP0SR2_19_16) +#define GPSR2_3 F_(CLK_EXTFXR, IP0SR2_15_12) +#define GPSR2_2 F_(RXDA_EXTFXR, IP0SR2_11_8) +#define GPSR2_1 F_(FXR_TXENA_N, IP0SR2_7_4) +#define GPSR2_0 F_(FXR_TXDA, IP0SR2_3_0) + +/* GPSR3 */ +#define GPSR3_29 F_(RPC_INT_N, IP3SR3_23_20) +#define GPSR3_28 F_(RPC_WP_N, IP3SR3_19_16) +#define GPSR3_27 F_(RPC_RESET_N, IP3SR3_15_12) +#define GPSR3_26 F_(QSPI1_IO3, IP3SR3_11_8) +#define GPSR3_25 F_(QSPI1_SSL, IP3SR3_7_4) +#define GPSR3_24 F_(QSPI1_IO2, IP3SR3_3_0) +#define GPSR3_23 F_(QSPI1_MISO_IO1, IP2SR3_31_28) +#define GPSR3_22 F_(QSPI1_SPCLK, IP2SR3_27_24) +#define GPSR3_21 F_(QSPI1_MOSI_IO0, IP2SR3_23_20) +#define GPSR3_20 F_(QSPI0_SPCLK, IP2SR3_19_16) +#define GPSR3_19 F_(QSPI0_MOSI_IO0, IP2SR3_15_12) +#define GPSR3_18 F_(QSPI0_MISO_IO1, IP2SR3_11_8) +#define GPSR3_17 F_(QSPI0_IO2, IP2SR3_7_4) +#define GPSR3_16 F_(QSPI0_IO3, IP2SR3_3_0) +#define GPSR3_15 F_(QSPI0_SSL, IP1SR3_31_28) +#define GPSR3_14 F_(IPC_CLKOUT, IP1SR3_27_24) +#define GPSR3_13 F_(IPC_CLKIN, IP1SR3_23_20) +#define GPSR3_12 F_(SD_WP, IP1SR3_19_16) +#define GPSR3_11 F_(SD_CD, IP1SR3_15_12) +#define GPSR3_10 F_(MMC_SD_CMD, IP1SR3_11_8) +#define GPSR3_9 F_(MMC_D6, IP1SR3_7_4) +#define GPSR3_8 F_(MMC_D7, IP1SR3_3_0) +#define GPSR3_7 F_(MMC_D4, IP0SR3_31_28) +#define GPSR3_6 F_(MMC_D5, IP0SR3_27_24) +#define GPSR3_5 F_(MMC_SD_D3, IP0SR3_23_20) +#define GPSR3_4 F_(MMC_DS, IP0SR3_19_16) +#define GPSR3_3 F_(MMC_SD_CLK, IP0SR3_15_12) +#define GPSR3_2 F_(MMC_SD_D2, IP0SR3_11_8) +#define GPSR3_1 F_(MMC_SD_D0, IP0SR3_7_4) +#define GPSR3_0 F_(MMC_SD_D1, IP0SR3_3_0) + +/* GPSR4 */ +#define GPSR4_24 FM(AVS1) +#define GPSR4_23 FM(AVS0) +#define GPSR4_22 FM(PCIE1_CLKREQ_N) +#define GPSR4_21 FM(PCIE0_CLKREQ_N) +#define GPSR4_20 FM(TSN0_TXCREFCLK) +#define GPSR4_19 FM(TSN0_TD2) +#define GPSR4_18 FM(TSN0_TD3) +#define GPSR4_17 FM(TSN0_RD2) +#define GPSR4_16 FM(TSN0_RD3) +#define GPSR4_15 FM(TSN0_TD0) +#define GPSR4_14 FM(TSN0_TD1) +#define GPSR4_13 FM(TSN0_RD1) +#define GPSR4_12 FM(TSN0_TXC) +#define GPSR4_11 FM(TSN0_RXC) +#define GPSR4_10 FM(TSN0_RD0) +#define GPSR4_9 FM(TSN0_TX_CTL) +#define GPSR4_8 FM(TSN0_AVTP_PPS0) +#define GPSR4_7 FM(TSN0_RX_CTL) +#define GPSR4_6 FM(TSN0_AVTP_CAPTURE) +#define GPSR4_5 FM(TSN0_AVTP_MATCH) +#define GPSR4_4 FM(TSN0_LINK) +#define GPSR4_3 FM(TSN0_PHY_INT) +#define GPSR4_2 FM(TSN0_AVTP_PPS1) +#define GPSR4_1 FM(TSN0_MDC) +#define GPSR4_0 FM(TSN0_MDIO) + +/* GPSR 5 */ +#define GPSR5_20 FM(AVB2_RX_CTL) +#define GPSR5_19 FM(AVB2_TX_CTL) +#define GPSR5_18 FM(AVB2_RXC) +#define GPSR5_17 FM(AVB2_RD0) +#define GPSR5_16 FM(AVB2_TXC) +#define GPSR5_15 FM(AVB2_TD0) +#define GPSR5_14 FM(AVB2_RD1) +#define GPSR5_13 FM(AVB2_RD2) +#define GPSR5_12 FM(AVB2_TD1) +#define GPSR5_11 FM(AVB2_TD2) +#define GPSR5_10 FM(AVB2_MDIO) +#define GPSR5_9 FM(AVB2_RD3) +#define GPSR5_8 FM(AVB2_TD3) +#define GPSR5_7 FM(AVB2_TXCREFCLK) +#define GPSR5_6 FM(AVB2_MDC) +#define GPSR5_5 FM(AVB2_MAGIC) +#define GPSR5_4 FM(AVB2_PHY_INT) +#define GPSR5_3 FM(AVB2_LINK) +#define GPSR5_2 FM(AVB2_AVTP_MATCH) +#define GPSR5_1 FM(AVB2_AVTP_CAPTURE) +#define GPSR5_0 FM(AVB2_AVTP_PPS) + +/* GPSR 6 */ +#define GPSR6_20 F_(AVB1_TXCREFCLK, IP2SR6_19_16) +#define GPSR6_19 F_(AVB1_RD3, IP2SR6_15_12) +#define GPSR6_18 F_(AVB1_TD3, IP2SR6_11_8) +#define GPSR6_17 F_(AVB1_RD2, IP2SR6_7_4) +#define GPSR6_16 F_(AVB1_TD2, IP2SR6_3_0) +#define GPSR6_15 F_(AVB1_RD0, IP1SR6_31_28) +#define GPSR6_14 F_(AVB1_RD1, IP1SR6_27_24) +#define GPSR6_13 F_(AVB1_TD0, IP1SR6_23_20) +#define GPSR6_12 F_(AVB1_TD1, IP1SR6_19_16) +#define GPSR6_11 F_(AVB1_AVTP_CAPTURE, IP1SR6_15_12) +#define GPSR6_10 F_(AVB1_AVTP_PPS, IP1SR6_11_8) +#define GPSR6_9 F_(AVB1_RX_CTL, IP1SR6_7_4) +#define GPSR6_8 F_(AVB1_RXC, IP1SR6_3_0) +#define GPSR6_7 F_(AVB1_TX_CTL, IP0SR6_31_28) +#define GPSR6_6 F_(AVB1_TXC, IP0SR6_27_24) +#define GPSR6_5 F_(AVB1_AVTP_MATCH, IP0SR6_23_20) +#define GPSR6_4 F_(AVB1_LINK, IP0SR6_19_16) +#define GPSR6_3 F_(AVB1_PHY_INT, IP0SR6_15_12) +#define GPSR6_2 F_(AVB1_MDC, IP0SR6_11_8) +#define GPSR6_1 F_(AVB1_MAGIC, IP0SR6_7_4) +#define GPSR6_0 F_(AVB1_MDIO, IP0SR6_3_0) + +/* GPSR7 */ +#define GPSR7_20 F_(AVB0_RX_CTL, IP2SR7_19_16) +#define GPSR7_19 F_(AVB0_RXC, IP2SR7_15_12) +#define GPSR7_18 F_(AVB0_RD0, IP2SR7_11_8) +#define GPSR7_17 F_(AVB0_RD1, IP2SR7_7_4) +#define GPSR7_16 F_(AVB0_TX_CTL, IP2SR7_3_0) +#define GPSR7_15 F_(AVB0_TXC, IP1SR7_31_28) +#define GPSR7_14 F_(AVB0_MDIO, IP1SR7_27_24) +#define GPSR7_13 F_(AVB0_MDC, IP1SR7_23_20) +#define GPSR7_12 F_(AVB0_RD2, IP1SR7_19_16) +#define GPSR7_11 F_(AVB0_TD0, IP1SR7_15_12) +#define GPSR7_10 F_(AVB0_MAGIC, IP1SR7_11_8) +#define GPSR7_9 F_(AVB0_TXCREFCLK, IP1SR7_7_4) +#define GPSR7_8 F_(AVB0_RD3, IP1SR7_3_0) +#define GPSR7_7 F_(AVB0_TD1, IP0SR7_31_28) +#define GPSR7_6 F_(AVB0_TD2, IP0SR7_27_24) +#define GPSR7_5 F_(AVB0_PHY_INT, IP0SR7_23_20) +#define GPSR7_4 F_(AVB0_LINK, IP0SR7_19_16) +#define GPSR7_3 F_(AVB0_TD3, IP0SR7_15_12) +#define GPSR7_2 F_(AVB0_AVTP_MATCH, IP0SR7_11_8) +#define GPSR7_1 F_(AVB0_AVTP_CAPTURE, IP0SR7_7_4) +#define GPSR7_0 F_(AVB0_AVTP_PPS, IP0SR7_3_0) + +/* GPSR8 */ +#define GPSR8_13 F_(GP8_13, IP1SR8_23_20) +#define GPSR8_12 F_(GP8_12, IP1SR8_19_16) +#define GPSR8_11 F_(SDA5, IP1SR8_15_12) +#define GPSR8_10 F_(SCL5, IP1SR8_11_8) +#define GPSR8_9 F_(SDA4, IP1SR8_7_4) +#define GPSR8_8 F_(SCL4, IP1SR8_3_0) +#define GPSR8_7 F_(SDA3, IP0SR8_31_28) +#define GPSR8_6 F_(SCL3, IP0SR8_27_24) +#define GPSR8_5 F_(SDA2, IP0SR8_23_20) +#define GPSR8_4 F_(SCL2, IP0SR8_19_16) +#define GPSR8_3 F_(SDA1, IP0SR8_15_12) +#define GPSR8_2 F_(SCL1, IP0SR8_11_8) +#define GPSR8_1 F_(SDA0, IP0SR8_7_4) +#define GPSR8_0 F_(SCL0, IP0SR8_3_0) + +/* SR0 */ +/* IP0SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR0_3_0 F_(0, 0) FM(ERROROUTC_B) FM(TCLK2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_7_4 F_(0, 0) FM(MSIOF3_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_11_8 F_(0, 0) FM(MSIOF3_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_15_12 FM(IRQ3) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_19_16 FM(IRQ2) FM(MSIOF3_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_23_20 FM(IRQ1) FM(MSIOF3_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_27_24 FM(IRQ0) FM(MSIOF3_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR0_31_28 FM(MSIOF5_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR0_3_0 FM(MSIOF5_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_7_4 FM(MSIOF5_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_11_8 FM(MSIOF5_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_15_12 FM(MSIOF5_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_19_16 FM(MSIOF5_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_23_20 FM(MSIOF2_SS2) FM(TCLK1) FM(IRQ2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_27_24 FM(MSIOF2_SS1) FM(HTX1) FM(TX1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR0_31_28 FM(MSIOF2_SYNC) FM(HRX1) FM(RX1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP2SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP2SR0_3_0 FM(MSIOF2_TXD) FM(HCTS1_N) FM(CTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR0_7_4 FM(MSIOF2_SCK) FM(HRTS1_N) FM(RTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR0_11_8 FM(MSIOF2_RXD) FM(HSCK1) FM(SCK1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* SR1 */ +/* IP0SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR1_3_0 FM(MSIOF1_SS2) FM(HTX3_A) FM(TX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_7_4 FM(MSIOF1_SS1) FM(HCTS3_N_A) FM(RX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_11_8 FM(MSIOF1_SYNC) FM(HRTS3_N_A) FM(RTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_15_12 FM(MSIOF1_SCK) FM(HSCK3_A) FM(CTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_19_16 FM(MSIOF1_TXD) FM(HRX3_A) FM(SCK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_23_20 FM(MSIOF1_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_27_24 FM(MSIOF0_SS2) FM(HTX1_X) FM(TX1_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR1_31_28 FM(MSIOF0_SS1) FM(HRX1_X) FM(RX1_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR1_3_0 FM(MSIOF0_SYNC) FM(HCTS1_N_X) FM(CTS1_N_X) FM(CANFD5_TX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_7_4 FM(MSIOF0_TXD) FM(HRTS1_N_X) FM(RTS1_N_X) FM(CANFD5_RX_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_11_8 FM(MSIOF0_SCK) FM(HSCK1_X) FM(SCK1_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_15_12 FM(MSIOF0_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_19_16 FM(HTX0) FM(TX0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_23_20 FM(HCTS0_N) FM(CTS0_N) FM(PWM8_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_27_24 FM(HRTS0_N) FM(RTS0_N) FM(PWM9_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR1_31_28 FM(HSCK0) FM(SCK0) FM(PWM0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP2SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP2SR1_3_0 FM(HRX0) FM(RX0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_7_4 FM(SCIF_CLK) FM(IRQ4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_11_8 FM(SSI_SCK) FM(TCLK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_15_12 FM(SSI_WS) FM(TCLK4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_19_16 FM(SSI_SD) FM(IRQ0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_23_20 FM(AUDIO_CLKOUT) FM(IRQ1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_27_24 FM(AUDIO_CLKIN) FM(PWM3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR1_31_28 F_(0, 0) FM(TCLK2) FM(MSIOF4_SS1) FM(IRQ3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP3SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP3SR1_3_0 FM(HRX3) FM(SCK3_A) FM(MSIOF4_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR1_7_4 FM(HSCK3) FM(CTS3_N_A) FM(MSIOF4_SCK) FM(TPU0TO0_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR1_11_8 FM(HRTS3_N) FM(RTS3_N_A) FM(MSIOF4_TXD) FM(TPU0TO1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR1_15_12 FM(HCTS3_N) FM(RX3_A) FM(MSIOF4_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR1_19_16 FM(HTX3) FM(TX3_A) FM(MSIOF4_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* SR2 */ +/* IP0SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR2_3_0 FM(FXR_TXDA) FM(CANFD1_TX) FM(TPU0TO2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_7_4 FM(FXR_TXENA_N) FM(CANFD1_RX) FM(TPU0TO3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_11_8 FM(RXDA_EXTFXR) FM(CANFD5_TX) FM(IRQ5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_15_12 FM(CLK_EXTFXR) FM(CANFD5_RX) FM(IRQ4_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_19_16 FM(RXDB_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_23_20 FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_27_24 FM(FXR_TXDB) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR2_31_28 FM(TPU0TO1) FM(CANFD6_TX) F_(0, 0) FM(TCLK2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR2_3_0 FM(TPU0TO0) FM(CANFD6_RX) F_(0, 0) FM(TCLK1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_7_4 FM(CAN_CLK) FM(FXR_TXENA_N_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_11_8 FM(CANFD0_TX) FM(FXR_TXENB_N_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_15_12 FM(CANFD0_RX) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_19_16 FM(CANFD2_TX) FM(TPU0TO2) F_(0, 0) FM(TCLK3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_23_20 FM(CANFD2_RX) FM(TPU0TO3) FM(PWM1_B) FM(TCLK4_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_27_24 FM(CANFD3_TX) F_(0, 0) FM(PWM2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR2_31_28 FM(CANFD3_RX) F_(0, 0) FM(PWM3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP2SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP2SR2_3_0 FM(CANFD4_TX) F_(0, 0) FM(PWM4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR2_7_4 FM(CANFD4_RX) F_(0, 0) FM(PWM5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR2_11_8 FM(CANFD7_TX) F_(0, 0) FM(PWM6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR2_15_12 FM(CANFD7_RX) F_(0, 0) FM(PWM7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* SR3 */ +/* IP0SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR3_3_0 FM(MMC_SD_D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_7_4 FM(MMC_SD_D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_11_8 FM(MMC_SD_D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_15_12 FM(MMC_SD_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_19_16 FM(MMC_DS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_23_20 FM(MMC_SD_D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_27_24 FM(MMC_D5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR3_31_28 FM(MMC_D4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR3_3_0 FM(MMC_D7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_7_4 FM(MMC_D6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_11_8 FM(MMC_SD_CMD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_15_12 FM(SD_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_19_16 FM(SD_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_23_20 FM(IPC_CLKIN) FM(IPC_CLKEN_IN) FM(PWM1_A) FM(TCLK3_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_27_24 FM(IPC_CLKOUT) FM(IPC_CLKEN_OUT) FM(ERROROUTC_A) FM(TCLK4_X) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR3_31_28 FM(QSPI0_SSL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP2SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP2SR3_3_0 FM(QSPI0_IO3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_7_4 FM(QSPI0_IO2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_11_8 FM(QSPI0_MISO_IO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_15_12 FM(QSPI0_MOSI_IO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_19_16 FM(QSPI0_SPCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_23_20 FM(QSPI1_MOSI_IO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_27_24 FM(QSPI1_SPCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR3_31_28 FM(QSPI1_MISO_IO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP3SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP3SR3_3_0 FM(QSPI1_IO2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR3_7_4 FM(QSPI1_SSL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR3_11_8 FM(QSPI1_IO3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR3_15_12 FM(RPC_RESET_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR3_19_16 FM(RPC_WP_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP3SR3_23_20 FM(RPC_INT_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* SR6 */ +/* IP0SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR6_3_0 FM(AVB1_MDIO) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_7_4 FM(AVB1_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_11_8 FM(AVB1_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_15_12 FM(AVB1_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_19_16 FM(AVB1_LINK) FM(AVB1_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_23_20 FM(AVB1_AVTP_MATCH) FM(AVB1_MII_RX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_27_24 FM(AVB1_TXC) FM(AVB1_MII_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR6_31_28 FM(AVB1_TX_CTL) FM(AVB1_MII_TX_EN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR6_3_0 FM(AVB1_RXC) FM(AVB1_MII_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_7_4 FM(AVB1_RX_CTL) FM(AVB1_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_11_8 FM(AVB1_AVTP_PPS) FM(AVB1_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_15_12 FM(AVB1_AVTP_CAPTURE) FM(AVB1_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_19_16 FM(AVB1_TD1) FM(AVB1_MII_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_23_20 FM(AVB1_TD0) FM(AVB1_MII_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_27_24 FM(AVB1_RD1) FM(AVB1_MII_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR6_31_28 FM(AVB1_RD0) FM(AVB1_MII_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP2SR6 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP2SR6_3_0 FM(AVB1_TD2) FM(AVB1_MII_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_7_4 FM(AVB1_RD2) FM(AVB1_MII_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_11_8 FM(AVB1_TD3) FM(AVB1_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_15_12 FM(AVB1_RD3) FM(AVB1_MII_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR6_19_16 FM(AVB1_TXCREFCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* SR7 */ +/* IP0SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR7_3_0 FM(AVB0_AVTP_PPS) FM(AVB0_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_7_4 FM(AVB0_AVTP_CAPTURE) FM(AVB0_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_11_8 FM(AVB0_AVTP_MATCH) FM(AVB0_MII_RX_ER) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_15_12 FM(AVB0_TD3) FM(AVB0_MII_TD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_19_16 FM(AVB0_LINK) FM(AVB0_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_23_20 FM(AVB0_PHY_INT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_27_24 FM(AVB0_TD2) FM(AVB0_MII_TD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR7_31_28 FM(AVB0_TD1) FM(AVB0_MII_TD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR7_3_0 FM(AVB0_RD3) FM(AVB0_MII_RD3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_7_4 FM(AVB0_TXCREFCLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_11_8 FM(AVB0_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_15_12 FM(AVB0_TD0) FM(AVB0_MII_TD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_19_16 FM(AVB0_RD2) FM(AVB0_MII_RD2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_23_20 FM(AVB0_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_27_24 FM(AVB0_MDIO) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR7_31_28 FM(AVB0_TXC) FM(AVB0_MII_TXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP2SR7 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP2SR7_3_0 FM(AVB0_TX_CTL) FM(AVB0_MII_TX_EN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_7_4 FM(AVB0_RD1) FM(AVB0_MII_RD1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_11_8 FM(AVB0_RD0) FM(AVB0_MII_RD0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_15_12 FM(AVB0_RXC) FM(AVB0_MII_RXC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP2SR7_19_16 FM(AVB0_RX_CTL) FM(AVB0_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* SR8 */ +/* IP0SR8 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP0SR8_3_0 FM(SCL0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_7_4 FM(SDA0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_11_8 FM(SCL1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_15_12 FM(SDA1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_19_16 FM(SCL2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_23_20 FM(SDA2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_27_24 FM(SCL3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP0SR8_31_28 FM(SDA3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +/* IP1SR8 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +#define IP1SR8_3_0 FM(SCL4) FM(HRX2) FM(SCK4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR8_7_4 FM(SDA4) FM(HTX2) FM(CTS4_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR8_11_8 FM(SCL5) FM(HRTS2_N) FM(RTS4_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR8_15_12 FM(SDA5) FM(SCIF_CLK2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR8_19_16 F_(0, 0) FM(HCTS2_N) FM(TX4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1SR8_23_20 F_(0, 0) FM(HSCK2) FM(RX4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + +#define PINMUX_GPSR \ + GPSR3_29 \ + GPSR1_28 GPSR3_28 \ + GPSR1_27 GPSR3_27 \ + GPSR1_26 GPSR3_26 \ + GPSR1_25 GPSR3_25 \ + GPSR1_24 GPSR3_24 GPSR4_24 \ + GPSR1_23 GPSR3_23 GPSR4_23 \ + GPSR1_22 GPSR3_22 GPSR4_22 \ + GPSR1_21 GPSR3_21 GPSR4_21 \ + GPSR1_20 GPSR3_20 GPSR4_20 GPSR5_20 GPSR6_20 GPSR7_20 \ + GPSR1_19 GPSR2_19 GPSR3_19 GPSR4_19 GPSR5_19 GPSR6_19 GPSR7_19 \ +GPSR0_18 GPSR1_18 GPSR2_18 GPSR3_18 GPSR4_18 GPSR5_18 GPSR6_18 GPSR7_18 \ +GPSR0_17 GPSR1_17 GPSR2_17 GPSR3_17 GPSR4_17 GPSR5_17 GPSR6_17 GPSR7_17 \ +GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 GPSR4_16 GPSR5_16 GPSR6_16 GPSR7_16 \ +GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 GPSR4_15 GPSR5_15 GPSR6_15 GPSR7_15 \ +GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR4_14 GPSR5_14 GPSR6_14 GPSR7_14 \ +GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR4_13 GPSR5_13 GPSR6_13 GPSR7_13 GPSR8_13 \ +GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR4_12 GPSR5_12 GPSR6_12 GPSR7_12 GPSR8_12 \ +GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR4_11 GPSR5_11 GPSR6_11 GPSR7_11 GPSR8_11 \ +GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR4_10 GPSR5_10 GPSR6_10 GPSR7_10 GPSR8_10 \ +GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR4_9 GPSR5_9 GPSR6_9 GPSR7_9 GPSR8_9 \ +GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR4_8 GPSR5_8 GPSR6_8 GPSR7_8 GPSR8_8 \ +GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR4_7 GPSR5_7 GPSR6_7 GPSR7_7 GPSR8_7 \ +GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR4_6 GPSR5_6 GPSR6_6 GPSR7_6 GPSR8_6 \ +GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 GPSR6_5 GPSR7_5 GPSR8_5 \ +GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 GPSR6_4 GPSR7_4 GPSR8_4 \ +GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 GPSR6_3 GPSR7_3 GPSR8_3 \ +GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 GPSR6_2 GPSR7_2 GPSR8_2 \ +GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 GPSR6_1 GPSR7_1 GPSR8_1 \ +GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0 GPSR6_0 GPSR7_0 GPSR8_0 + +#define PINMUX_IPSR \ +\ +FM(IP0SR0_3_0) IP0SR0_3_0 FM(IP1SR0_3_0) IP1SR0_3_0 FM(IP2SR0_3_0) IP2SR0_3_0 \ +FM(IP0SR0_7_4) IP0SR0_7_4 FM(IP1SR0_7_4) IP1SR0_7_4 FM(IP2SR0_7_4) IP2SR0_7_4 \ +FM(IP0SR0_11_8) IP0SR0_11_8 FM(IP1SR0_11_8) IP1SR0_11_8 FM(IP2SR0_11_8) IP2SR0_11_8 \ +FM(IP0SR0_15_12) IP0SR0_15_12 FM(IP1SR0_15_12) IP1SR0_15_12 \ +FM(IP0SR0_19_16) IP0SR0_19_16 FM(IP1SR0_19_16) IP1SR0_19_16 \ +FM(IP0SR0_23_20) IP0SR0_23_20 FM(IP1SR0_23_20) IP1SR0_23_20 \ +FM(IP0SR0_27_24) IP0SR0_27_24 FM(IP1SR0_27_24) IP1SR0_27_24 \ +FM(IP0SR0_31_28) IP0SR0_31_28 FM(IP1SR0_31_28) IP1SR0_31_28 \ +\ +FM(IP0SR1_3_0) IP0SR1_3_0 FM(IP1SR1_3_0) IP1SR1_3_0 FM(IP2SR1_3_0) IP2SR1_3_0 FM(IP3SR1_3_0) IP3SR1_3_0 \ +FM(IP0SR1_7_4) IP0SR1_7_4 FM(IP1SR1_7_4) IP1SR1_7_4 FM(IP2SR1_7_4) IP2SR1_7_4 FM(IP3SR1_7_4) IP3SR1_7_4 \ +FM(IP0SR1_11_8) IP0SR1_11_8 FM(IP1SR1_11_8) IP1SR1_11_8 FM(IP2SR1_11_8) IP2SR1_11_8 FM(IP3SR1_11_8) IP3SR1_11_8 \ +FM(IP0SR1_15_12) IP0SR1_15_12 FM(IP1SR1_15_12) IP1SR1_15_12 FM(IP2SR1_15_12) IP2SR1_15_12 FM(IP3SR1_15_12) IP3SR1_15_12 \ +FM(IP0SR1_19_16) IP0SR1_19_16 FM(IP1SR1_19_16) IP1SR1_19_16 FM(IP2SR1_19_16) IP2SR1_19_16 FM(IP3SR1_19_16) IP3SR1_19_16 \ +FM(IP0SR1_23_20) IP0SR1_23_20 FM(IP1SR1_23_20) IP1SR1_23_20 FM(IP2SR1_23_20) IP2SR1_23_20 \ +FM(IP0SR1_27_24) IP0SR1_27_24 FM(IP1SR1_27_24) IP1SR1_27_24 FM(IP2SR1_27_24) IP2SR1_27_24 \ +FM(IP0SR1_31_28) IP0SR1_31_28 FM(IP1SR1_31_28) IP1SR1_31_28 FM(IP2SR1_31_28) IP2SR1_31_28 \ +\ +FM(IP0SR2_3_0) IP0SR2_3_0 FM(IP1SR2_3_0) IP1SR2_3_0 FM(IP2SR2_3_0) IP2SR2_3_0 \ +FM(IP0SR2_7_4) IP0SR2_7_4 FM(IP1SR2_7_4) IP1SR2_7_4 FM(IP2SR2_7_4) IP2SR2_7_4 \ +FM(IP0SR2_11_8) IP0SR2_11_8 FM(IP1SR2_11_8) IP1SR2_11_8 FM(IP2SR2_11_8) IP2SR2_11_8 \ +FM(IP0SR2_15_12) IP0SR2_15_12 FM(IP1SR2_15_12) IP1SR2_15_12 FM(IP2SR2_15_12) IP2SR2_15_12 \ +FM(IP0SR2_19_16) IP0SR2_19_16 FM(IP1SR2_19_16) IP1SR2_19_16 \ +FM(IP0SR2_23_20) IP0SR2_23_20 FM(IP1SR2_23_20) IP1SR2_23_20 \ +FM(IP0SR2_27_24) IP0SR2_27_24 FM(IP1SR2_27_24) IP1SR2_27_24 \ +FM(IP0SR2_31_28) IP0SR2_31_28 FM(IP1SR2_31_28) IP1SR2_31_28 \ +\ +FM(IP0SR3_3_0) IP0SR3_3_0 FM(IP1SR3_3_0) IP1SR3_3_0 FM(IP2SR3_3_0) IP2SR3_3_0 FM(IP3SR3_3_0) IP3SR3_3_0 \ +FM(IP0SR3_7_4) IP0SR3_7_4 FM(IP1SR3_7_4) IP1SR3_7_4 FM(IP2SR3_7_4) IP2SR3_7_4 FM(IP3SR3_7_4) IP3SR3_7_4 \ +FM(IP0SR3_11_8) IP0SR3_11_8 FM(IP1SR3_11_8) IP1SR3_11_8 FM(IP2SR3_11_8) IP2SR3_11_8 FM(IP3SR3_11_8) IP3SR3_11_8 \ +FM(IP0SR3_15_12) IP0SR3_15_12 FM(IP1SR3_15_12) IP1SR3_15_12 FM(IP2SR3_15_12) IP2SR3_15_12 FM(IP3SR3_15_12) IP3SR3_15_12 \ +FM(IP0SR3_19_16) IP0SR3_19_16 FM(IP1SR3_19_16) IP1SR3_19_16 FM(IP2SR3_19_16) IP2SR3_19_16 FM(IP3SR3_19_16) IP3SR3_19_16 \ +FM(IP0SR3_23_20) IP0SR3_23_20 FM(IP1SR3_23_20) IP1SR3_23_20 FM(IP2SR3_23_20) IP2SR3_23_20 FM(IP3SR3_23_20) IP3SR3_23_20 \ +FM(IP0SR3_27_24) IP0SR3_27_24 FM(IP1SR3_27_24) IP1SR3_27_24 FM(IP2SR3_27_24) IP2SR3_27_24 \ +FM(IP0SR3_31_28) IP0SR3_31_28 FM(IP1SR3_31_28) IP1SR3_31_28 FM(IP2SR3_31_28) IP2SR3_31_28 \ +\ +FM(IP0SR6_3_0) IP0SR6_3_0 FM(IP1SR6_3_0) IP1SR6_3_0 FM(IP2SR6_3_0) IP2SR6_3_0 \ +FM(IP0SR6_7_4) IP0SR6_7_4 FM(IP1SR6_7_4) IP1SR6_7_4 FM(IP2SR6_7_4) IP2SR6_7_4 \ +FM(IP0SR6_11_8) IP0SR6_11_8 FM(IP1SR6_11_8) IP1SR6_11_8 FM(IP2SR6_11_8) IP2SR6_11_8 \ +FM(IP0SR6_15_12) IP0SR6_15_12 FM(IP1SR6_15_12) IP1SR6_15_12 FM(IP2SR6_15_12) IP2SR6_15_12 \ +FM(IP0SR6_19_16) IP0SR6_19_16 FM(IP1SR6_19_16) IP1SR6_19_16 FM(IP2SR6_19_16) IP2SR6_19_16 \ +FM(IP0SR6_23_20) IP0SR6_23_20 FM(IP1SR6_23_20) IP1SR6_23_20 \ +FM(IP0SR6_27_24) IP0SR6_27_24 FM(IP1SR6_27_24) IP1SR6_27_24 \ +FM(IP0SR6_31_28) IP0SR6_31_28 FM(IP1SR6_31_28) IP1SR6_31_28 \ +\ +FM(IP0SR7_3_0) IP0SR7_3_0 FM(IP1SR7_3_0) IP1SR7_3_0 FM(IP2SR7_3_0) IP2SR7_3_0 \ +FM(IP0SR7_7_4) IP0SR7_7_4 FM(IP1SR7_7_4) IP1SR7_7_4 FM(IP2SR7_7_4) IP2SR7_7_4 \ +FM(IP0SR7_11_8) IP0SR7_11_8 FM(IP1SR7_11_8) IP1SR7_11_8 FM(IP2SR7_11_8) IP2SR7_11_8 \ +FM(IP0SR7_15_12) IP0SR7_15_12 FM(IP1SR7_15_12) IP1SR7_15_12 FM(IP2SR7_15_12) IP2SR7_15_12 \ +FM(IP0SR7_19_16) IP0SR7_19_16 FM(IP1SR7_19_16) IP1SR7_19_16 FM(IP2SR7_19_16) IP2SR7_19_16 \ +FM(IP0SR7_23_20) IP0SR7_23_20 FM(IP1SR7_23_20) IP1SR7_23_20 \ +FM(IP0SR7_27_24) IP0SR7_27_24 FM(IP1SR7_27_24) IP1SR7_27_24 \ +FM(IP0SR7_31_28) IP0SR7_31_28 FM(IP1SR7_31_28) IP1SR7_31_28 \ +\ +FM(IP0SR8_3_0) IP0SR8_3_0 FM(IP1SR8_3_0) IP1SR8_3_0 \ +FM(IP0SR8_7_4) IP0SR8_7_4 FM(IP1SR8_7_4) IP1SR8_7_4 \ +FM(IP0SR8_11_8) IP0SR8_11_8 FM(IP1SR8_11_8) IP1SR8_11_8 \ +FM(IP0SR8_15_12) IP0SR8_15_12 FM(IP1SR8_15_12) IP1SR8_15_12 \ +FM(IP0SR8_19_16) IP0SR8_19_16 FM(IP1SR8_19_16) IP1SR8_19_16 \ +FM(IP0SR8_23_20) IP0SR8_23_20 FM(IP1SR8_23_20) IP1SR8_23_20 \ +FM(IP0SR8_27_24) IP0SR8_27_24 \ +FM(IP0SR8_31_28) IP0SR8_31_28 + +/* MOD_SEL4 */ /* 0 */ /* 1 */ +#define MOD_SEL4_19 FM(SEL_TSN0_TD2_0) FM(SEL_TSN0_TD2_1) +#define MOD_SEL4_18 FM(SEL_TSN0_TD3_0) FM(SEL_TSN0_TD3_1) +#define MOD_SEL4_15 FM(SEL_TSN0_TD0_0) FM(SEL_TSN0_TD0_1) +#define MOD_SEL4_14 FM(SEL_TSN0_TD1_0) FM(SEL_TSN0_TD1_1) +#define MOD_SEL4_12 FM(SEL_TSN0_TXC_0) FM(SEL_TSN0_TXC_1) +#define MOD_SEL4_9 FM(SEL_TSN0_TX_CTL_0) FM(SEL_TSN0_TX_CTL_1) +#define MOD_SEL4_8 FM(SEL_TSN0_AVTP_PPS0_0) FM(SEL_TSN0_AVTP_PPS0_1) +#define MOD_SEL4_5 FM(SEL_TSN0_AVTP_MATCH_0) FM(SEL_TSN0_AVTP_MATCH_1) +#define MOD_SEL4_2 FM(SEL_TSN0_AVTP_PPS1_0) FM(SEL_TSN0_AVTP_PPS1_1) +#define MOD_SEL4_1 FM(SEL_TSN0_MDC_0) FM(SEL_TSN0_MDC_1) + +/* MOD_SEL5 */ /* 0 */ /* 1 */ +#define MOD_SEL5_19 FM(SEL_AVB2_TX_CTL_0) FM(SEL_AVB2_TX_CTL_1) +#define MOD_SEL5_16 FM(SEL_AVB2_TXC_0) FM(SEL_AVB2_TXC_1) +#define MOD_SEL5_15 FM(SEL_AVB2_TD0_0) FM(SEL_AVB2_TD0_1) +#define MOD_SEL5_12 FM(SEL_AVB2_TD1_0) FM(SEL_AVB2_TD1_1) +#define MOD_SEL5_11 FM(SEL_AVB2_TD2_0) FM(SEL_AVB2_TD2_1) +#define MOD_SEL5_8 FM(SEL_AVB2_TD3_0) FM(SEL_AVB2_TD3_1) +#define MOD_SEL5_6 FM(SEL_AVB2_MDC_0) FM(SEL_AVB2_MDC_1) +#define MOD_SEL5_5 FM(SEL_AVB2_MAGIC_0) FM(SEL_AVB2_MAGIC_1) +#define MOD_SEL5_2 FM(SEL_AVB2_AVTP_MATCH_0) FM(SEL_AVB2_AVTP_MATCH_1) +#define MOD_SEL5_0 FM(SEL_AVB2_AVTP_PPS_0) FM(SEL_AVB2_AVTP_PPS_1) + +/* MOD_SEL6 */ /* 0 */ /* 1 */ +#define MOD_SEL6_18 FM(SEL_AVB1_TD3_0) FM(SEL_AVB1_TD3_1) +#define MOD_SEL6_16 FM(SEL_AVB1_TD2_0) FM(SEL_AVB1_TD2_1) +#define MOD_SEL6_13 FM(SEL_AVB1_TD0_0) FM(SEL_AVB1_TD0_1) +#define MOD_SEL6_12 FM(SEL_AVB1_TD1_0) FM(SEL_AVB1_TD1_1) +#define MOD_SEL6_10 FM(SEL_AVB1_AVTP_PPS_0) FM(SEL_AVB1_AVTP_PPS_1) +#define MOD_SEL6_7 FM(SEL_AVB1_TX_CTL_0) FM(SEL_AVB1_TX_CTL_1) +#define MOD_SEL6_6 FM(SEL_AVB1_TXC_0) FM(SEL_AVB1_TXC_1) +#define MOD_SEL6_5 FM(SEL_AVB1_AVTP_MATCH_0) FM(SEL_AVB1_AVTP_MATCH_1) +#define MOD_SEL6_2 FM(SEL_AVB1_MDC_0) FM(SEL_AVB1_MDC_1) +#define MOD_SEL6_1 FM(SEL_AVB1_MAGIC_0) FM(SEL_AVB1_MAGIC_1) + +/* MOD_SEL7 */ /* 0 */ /* 1 */ +#define MOD_SEL7_16 FM(SEL_AVB0_TX_CTL_0) FM(SEL_AVB0_TX_CTL_1) +#define MOD_SEL7_15 FM(SEL_AVB0_TXC_0) FM(SEL_AVB0_TXC_1) +#define MOD_SEL7_13 FM(SEL_AVB0_MDC_0) FM(SEL_AVB0_MDC_1) +#define MOD_SEL7_11 FM(SEL_AVB0_TD0_0) FM(SEL_AVB0_TD0_1) +#define MOD_SEL7_10 FM(SEL_AVB0_MAGIC_0) FM(SEL_AVB0_MAGIC_1) +#define MOD_SEL7_7 FM(SEL_AVB0_TD1_0) FM(SEL_AVB0_TD1_1) +#define MOD_SEL7_6 FM(SEL_AVB0_TD2_0) FM(SEL_AVB0_TD2_1) +#define MOD_SEL7_3 FM(SEL_AVB0_TD3_0) FM(SEL_AVB0_TD3_1) +#define MOD_SEL7_2 FM(SEL_AVB0_AVTP_MATCH_0) FM(SEL_AVB0_AVTP_MATCH_1) +#define MOD_SEL7_0 FM(SEL_AVB0_AVTP_PPS_0) FM(SEL_AVB0_AVTP_PPS_1) + +/* MOD_SEL8 */ /* 0 */ /* 1 */ +#define MOD_SEL8_11 FM(SEL_SDA5_0) FM(SEL_SDA5_1) +#define MOD_SEL8_10 FM(SEL_SCL5_0) FM(SEL_SCL5_1) +#define MOD_SEL8_9 FM(SEL_SDA4_0) FM(SEL_SDA4_1) +#define MOD_SEL8_8 FM(SEL_SCL4_0) FM(SEL_SCL4_1) +#define MOD_SEL8_7 FM(SEL_SDA3_0) FM(SEL_SDA3_1) +#define MOD_SEL8_6 FM(SEL_SCL3_0) FM(SEL_SCL3_1) +#define MOD_SEL8_5 FM(SEL_SDA2_0) FM(SEL_SDA2_1) +#define MOD_SEL8_4 FM(SEL_SCL2_0) FM(SEL_SCL2_1) +#define MOD_SEL8_3 FM(SEL_SDA1_0) FM(SEL_SDA1_1) +#define MOD_SEL8_2 FM(SEL_SCL1_0) FM(SEL_SCL1_1) +#define MOD_SEL8_1 FM(SEL_SDA0_0) FM(SEL_SDA0_1) +#define MOD_SEL8_0 FM(SEL_SCL0_0) FM(SEL_SCL0_1) + +#define PINMUX_MOD_SELS \ +\ +MOD_SEL4_19 MOD_SEL5_19 \ +MOD_SEL4_18 MOD_SEL6_18 \ + \ + MOD_SEL5_16 MOD_SEL6_16 MOD_SEL7_16 \ +MOD_SEL4_15 MOD_SEL5_15 MOD_SEL7_15 \ +MOD_SEL4_14 \ + MOD_SEL6_13 MOD_SEL7_13 \ +MOD_SEL4_12 MOD_SEL5_12 MOD_SEL6_12 \ + MOD_SEL5_11 MOD_SEL7_11 MOD_SEL8_11 \ + MOD_SEL6_10 MOD_SEL7_10 MOD_SEL8_10 \ +MOD_SEL4_9 MOD_SEL8_9 \ +MOD_SEL4_8 MOD_SEL5_8 MOD_SEL8_8 \ + MOD_SEL6_7 MOD_SEL7_7 MOD_SEL8_7 \ + MOD_SEL5_6 MOD_SEL6_6 MOD_SEL7_6 MOD_SEL8_6 \ +MOD_SEL4_5 MOD_SEL5_5 MOD_SEL6_5 MOD_SEL8_5 \ + MOD_SEL8_4 \ + MOD_SEL7_3 MOD_SEL8_3 \ +MOD_SEL4_2 MOD_SEL5_2 MOD_SEL6_2 MOD_SEL7_2 MOD_SEL8_2 \ +MOD_SEL4_1 MOD_SEL6_1 MOD_SEL8_1 \ + MOD_SEL5_0 MOD_SEL7_0 MOD_SEL8_0 + +enum { + PINMUX_RESERVED = 0, + + PINMUX_DATA_BEGIN, + GP_ALL(DATA), + PINMUX_DATA_END, + +#define F_(x, y) +#define FM(x) FN_##x, + PINMUX_FUNCTION_BEGIN, + GP_ALL(FN), + PINMUX_GPSR + PINMUX_IPSR + PINMUX_MOD_SELS + PINMUX_FUNCTION_END, +#undef F_ +#undef FM + +#define F_(x, y) +#define FM(x) x##_MARK, + PINMUX_MARK_BEGIN, + PINMUX_GPSR + PINMUX_IPSR + PINMUX_MOD_SELS + PINMUX_MARK_END, +#undef F_ +#undef FM +}; + +static const u16 pinmux_data[] = { + PINMUX_DATA_GP_ALL(), + + PINMUX_SINGLE(AVS1), + PINMUX_SINGLE(AVS0), + PINMUX_SINGLE(PCIE1_CLKREQ_N), + PINMUX_SINGLE(PCIE0_CLKREQ_N), + + /* TSN0 without MODSEL4 */ + PINMUX_SINGLE(TSN0_TXCREFCLK), + PINMUX_SINGLE(TSN0_RD2), + PINMUX_SINGLE(TSN0_RD3), + PINMUX_SINGLE(TSN0_RD1), + PINMUX_SINGLE(TSN0_RXC), + PINMUX_SINGLE(TSN0_RD0), + PINMUX_SINGLE(TSN0_RX_CTL), + PINMUX_SINGLE(TSN0_AVTP_CAPTURE), + PINMUX_SINGLE(TSN0_LINK), + PINMUX_SINGLE(TSN0_PHY_INT), + PINMUX_SINGLE(TSN0_MDIO), + /* TSN0 with MODSEL4 */ + PINMUX_IPSR_NOGM(0, TSN0_TD2, SEL_TSN0_TD2_1), + PINMUX_IPSR_NOGM(0, TSN0_TD3, SEL_TSN0_TD3_1), + PINMUX_IPSR_NOGM(0, TSN0_TD0, SEL_TSN0_TD0_1), + PINMUX_IPSR_NOGM(0, TSN0_TD1, SEL_TSN0_TD1_1), + PINMUX_IPSR_NOGM(0, TSN0_TXC, SEL_TSN0_TXC_1), + PINMUX_IPSR_NOGM(0, TSN0_TX_CTL, SEL_TSN0_TX_CTL_1), + PINMUX_IPSR_NOGM(0, TSN0_AVTP_PPS0, SEL_TSN0_AVTP_PPS0_1), + PINMUX_IPSR_NOGM(0, TSN0_AVTP_MATCH, SEL_TSN0_AVTP_MATCH_1), + PINMUX_IPSR_NOGM(0, TSN0_AVTP_PPS1, SEL_TSN0_AVTP_PPS1_1), + PINMUX_IPSR_NOGM(0, TSN0_MDC, SEL_TSN0_MDC_1), + + /* TSN0 without MODSEL5 */ + PINMUX_SINGLE(AVB2_RX_CTL), + PINMUX_SINGLE(AVB2_RXC), + PINMUX_SINGLE(AVB2_RD0), + PINMUX_SINGLE(AVB2_RD1), + PINMUX_SINGLE(AVB2_RD2), + PINMUX_SINGLE(AVB2_MDIO), + PINMUX_SINGLE(AVB2_RD3), + PINMUX_SINGLE(AVB2_TXCREFCLK), + PINMUX_SINGLE(AVB2_PHY_INT), + PINMUX_SINGLE(AVB2_LINK), + PINMUX_SINGLE(AVB2_AVTP_CAPTURE), + /* TSN0 with MODSEL5 */ + PINMUX_IPSR_NOGM(0, AVB2_TX_CTL, SEL_AVB2_TX_CTL_1), + PINMUX_IPSR_NOGM(0, AVB2_TXC, SEL_AVB2_TXC_1), + PINMUX_IPSR_NOGM(0, AVB2_TD0, SEL_AVB2_TD0_1), + PINMUX_IPSR_NOGM(0, AVB2_TD1, SEL_AVB2_TD1_1), + PINMUX_IPSR_NOGM(0, AVB2_TD2, SEL_AVB2_TD2_1), + PINMUX_IPSR_NOGM(0, AVB2_TD3, SEL_AVB2_TD3_1), + PINMUX_IPSR_NOGM(0, AVB2_MDC, SEL_AVB2_MDC_1), + PINMUX_IPSR_NOGM(0, AVB2_MAGIC, SEL_AVB2_MAGIC_1), + PINMUX_IPSR_NOGM(0, AVB2_AVTP_MATCH, SEL_AVB2_AVTP_MATCH_1), + PINMUX_IPSR_NOGM(0, AVB2_AVTP_PPS, SEL_AVB2_AVTP_PPS_1), + + /* IP0SR0 */ + PINMUX_IPSR_GPSR(IP0SR0_3_0, ERROROUTC_B), + PINMUX_IPSR_GPSR(IP0SR0_3_0, TCLK2_A), + + PINMUX_IPSR_GPSR(IP0SR0_7_4, MSIOF3_SS1), + + PINMUX_IPSR_GPSR(IP0SR0_11_8, MSIOF3_SS2), + + PINMUX_IPSR_GPSR(IP0SR0_15_12, IRQ3), + PINMUX_IPSR_GPSR(IP0SR0_15_12, MSIOF3_SCK), + + PINMUX_IPSR_GPSR(IP0SR0_19_16, IRQ2), + PINMUX_IPSR_GPSR(IP0SR0_19_16, MSIOF3_TXD), + + PINMUX_IPSR_GPSR(IP0SR0_23_20, IRQ1), + PINMUX_IPSR_GPSR(IP0SR0_23_20, MSIOF3_RXD), + + PINMUX_IPSR_GPSR(IP0SR0_27_24, IRQ0), + PINMUX_IPSR_GPSR(IP0SR0_27_24, MSIOF3_SYNC), + + PINMUX_IPSR_GPSR(IP0SR0_31_28, MSIOF5_SS2), + + /* IP1SR0 */ + PINMUX_IPSR_GPSR(IP1SR0_3_0, MSIOF5_SS1), + + PINMUX_IPSR_GPSR(IP1SR0_7_4, MSIOF5_SYNC), + + PINMUX_IPSR_GPSR(IP1SR0_11_8, MSIOF5_TXD), + + PINMUX_IPSR_GPSR(IP1SR0_15_12, MSIOF5_SCK), + + PINMUX_IPSR_GPSR(IP1SR0_19_16, MSIOF5_RXD), + + PINMUX_IPSR_GPSR(IP1SR0_23_20, MSIOF2_SS2), + PINMUX_IPSR_GPSR(IP1SR0_23_20, TCLK1), + PINMUX_IPSR_GPSR(IP1SR0_23_20, IRQ2_A), + + PINMUX_IPSR_GPSR(IP1SR0_27_24, MSIOF2_SS1), + PINMUX_IPSR_GPSR(IP1SR0_27_24, HTX1), + PINMUX_IPSR_GPSR(IP1SR0_27_24, TX1), + + PINMUX_IPSR_GPSR(IP1SR0_31_28, MSIOF2_SYNC), + PINMUX_IPSR_GPSR(IP1SR0_31_28, HRX1), + PINMUX_IPSR_GPSR(IP1SR0_31_28, RX1), + + /* IP2SR0 */ + PINMUX_IPSR_GPSR(IP2SR0_3_0, MSIOF2_TXD), + PINMUX_IPSR_GPSR(IP2SR0_3_0, HCTS1_N), + PINMUX_IPSR_GPSR(IP2SR0_3_0, CTS1_N), + + PINMUX_IPSR_GPSR(IP2SR0_7_4, MSIOF2_SCK), + PINMUX_IPSR_GPSR(IP2SR0_7_4, HRTS1_N), + PINMUX_IPSR_GPSR(IP2SR0_7_4, RTS1_N), + + PINMUX_IPSR_GPSR(IP2SR0_11_8, MSIOF2_RXD), + PINMUX_IPSR_GPSR(IP2SR0_11_8, HSCK1), + PINMUX_IPSR_GPSR(IP2SR0_11_8, SCK1), + + /* IP0SR1 */ + PINMUX_IPSR_GPSR(IP0SR1_3_0, MSIOF1_SS2), + PINMUX_IPSR_GPSR(IP0SR1_3_0, HTX3_A), + PINMUX_IPSR_GPSR(IP0SR1_3_0, TX3), + + PINMUX_IPSR_GPSR(IP0SR1_7_4, MSIOF1_SS1), + PINMUX_IPSR_GPSR(IP0SR1_7_4, HCTS3_N_A), + PINMUX_IPSR_GPSR(IP0SR1_7_4, RX3), + + PINMUX_IPSR_GPSR(IP0SR1_11_8, MSIOF1_SYNC), + PINMUX_IPSR_GPSR(IP0SR1_11_8, HRTS3_N_A), + PINMUX_IPSR_GPSR(IP0SR1_11_8, RTS3_N), + + PINMUX_IPSR_GPSR(IP0SR1_15_12, MSIOF1_SCK), + PINMUX_IPSR_GPSR(IP0SR1_15_12, HSCK3_A), + PINMUX_IPSR_GPSR(IP0SR1_15_12, CTS3_N), + + PINMUX_IPSR_GPSR(IP0SR1_19_16, MSIOF1_TXD), + PINMUX_IPSR_GPSR(IP0SR1_19_16, HRX3_A), + PINMUX_IPSR_GPSR(IP0SR1_19_16, SCK3), + + PINMUX_IPSR_GPSR(IP0SR1_23_20, MSIOF1_RXD), + + PINMUX_IPSR_GPSR(IP0SR1_27_24, MSIOF0_SS2), + PINMUX_IPSR_GPSR(IP0SR1_27_24, HTX1_X), + PINMUX_IPSR_GPSR(IP0SR1_27_24, TX1_X), + + PINMUX_IPSR_GPSR(IP0SR1_31_28, MSIOF0_SS1), + PINMUX_IPSR_GPSR(IP0SR1_31_28, HRX1_X), + PINMUX_IPSR_GPSR(IP0SR1_31_28, RX1_X), + + /* IP1SR1 */ + PINMUX_IPSR_GPSR(IP1SR1_3_0, MSIOF0_SYNC), + PINMUX_IPSR_GPSR(IP1SR1_3_0, HCTS1_N_X), + PINMUX_IPSR_GPSR(IP1SR1_3_0, CTS1_N_X), + PINMUX_IPSR_GPSR(IP1SR1_3_0, CANFD5_TX_B), + + PINMUX_IPSR_GPSR(IP1SR1_7_4, MSIOF0_TXD), + PINMUX_IPSR_GPSR(IP1SR1_7_4, HRTS1_N_X), + PINMUX_IPSR_GPSR(IP1SR1_7_4, RTS1_N_X), + PINMUX_IPSR_GPSR(IP1SR1_7_4, CANFD5_RX_B), + + PINMUX_IPSR_GPSR(IP1SR1_11_8, MSIOF0_SCK), + PINMUX_IPSR_GPSR(IP1SR1_11_8, HSCK1_X), + PINMUX_IPSR_GPSR(IP1SR1_11_8, SCK1_X), + + PINMUX_IPSR_GPSR(IP1SR1_15_12, MSIOF0_RXD), + + PINMUX_IPSR_GPSR(IP1SR1_19_16, HTX0), + PINMUX_IPSR_GPSR(IP1SR1_19_16, TX0), + + PINMUX_IPSR_GPSR(IP1SR1_23_20, HCTS0_N), + PINMUX_IPSR_GPSR(IP1SR1_23_20, CTS0_N), + PINMUX_IPSR_GPSR(IP1SR1_23_20, PWM8_A), + + PINMUX_IPSR_GPSR(IP1SR1_27_24, HRTS0_N), + PINMUX_IPSR_GPSR(IP1SR1_27_24, RTS0_N), + PINMUX_IPSR_GPSR(IP1SR1_27_24, PWM9_A), + + PINMUX_IPSR_GPSR(IP1SR1_31_28, HSCK0), + PINMUX_IPSR_GPSR(IP1SR1_31_28, SCK0), + PINMUX_IPSR_GPSR(IP1SR1_31_28, PWM0_A), + + /* IP2SR1 */ + PINMUX_IPSR_GPSR(IP2SR1_3_0, HRX0), + PINMUX_IPSR_GPSR(IP2SR1_3_0, RX0), + + PINMUX_IPSR_GPSR(IP2SR1_7_4, SCIF_CLK), + PINMUX_IPSR_GPSR(IP2SR1_7_4, IRQ4_A), + + PINMUX_IPSR_GPSR(IP2SR1_11_8, SSI_SCK), + PINMUX_IPSR_GPSR(IP2SR1_11_8, TCLK3), + + PINMUX_IPSR_GPSR(IP2SR1_15_12, SSI_WS), + PINMUX_IPSR_GPSR(IP2SR1_15_12, TCLK4), + + PINMUX_IPSR_GPSR(IP2SR1_19_16, SSI_SD), + PINMUX_IPSR_GPSR(IP2SR1_19_16, IRQ0_A), + + PINMUX_IPSR_GPSR(IP2SR1_23_20, AUDIO_CLKOUT), + PINMUX_IPSR_GPSR(IP2SR1_23_20, IRQ1_A), + + PINMUX_IPSR_GPSR(IP2SR1_27_24, AUDIO_CLKIN), + PINMUX_IPSR_GPSR(IP2SR1_27_24, PWM3_A), + + PINMUX_IPSR_GPSR(IP2SR1_31_28, TCLK2), + PINMUX_IPSR_GPSR(IP2SR1_31_28, MSIOF4_SS1), + PINMUX_IPSR_GPSR(IP2SR1_31_28, IRQ3_B), + + /* IP3SR1 */ + PINMUX_IPSR_GPSR(IP3SR1_3_0, HRX3), + PINMUX_IPSR_GPSR(IP3SR1_3_0, SCK3_A), + PINMUX_IPSR_GPSR(IP3SR1_3_0, MSIOF4_SS2), + + PINMUX_IPSR_GPSR(IP3SR1_7_4, HSCK3), + PINMUX_IPSR_GPSR(IP3SR1_7_4, CTS3_N_A), + PINMUX_IPSR_GPSR(IP3SR1_7_4, MSIOF4_SCK), + PINMUX_IPSR_GPSR(IP3SR1_7_4, TPU0TO0_A), + + PINMUX_IPSR_GPSR(IP3SR1_11_8, HRTS3_N), + PINMUX_IPSR_GPSR(IP3SR1_11_8, RTS3_N_A), + PINMUX_IPSR_GPSR(IP3SR1_11_8, MSIOF4_TXD), + PINMUX_IPSR_GPSR(IP3SR1_11_8, TPU0TO1_A), + + PINMUX_IPSR_GPSR(IP3SR1_15_12, HCTS3_N), + PINMUX_IPSR_GPSR(IP3SR1_15_12, RX3_A), + PINMUX_IPSR_GPSR(IP3SR1_15_12, MSIOF4_RXD), + + PINMUX_IPSR_GPSR(IP3SR1_19_16, HTX3), + PINMUX_IPSR_GPSR(IP3SR1_19_16, TX3_A), + PINMUX_IPSR_GPSR(IP3SR1_19_16, MSIOF4_SYNC), + + /* IP0SR2 */ + PINMUX_IPSR_GPSR(IP0SR2_3_0, FXR_TXDA), + PINMUX_IPSR_GPSR(IP0SR2_3_0, CANFD1_TX), + PINMUX_IPSR_GPSR(IP0SR2_3_0, TPU0TO2_A), + + PINMUX_IPSR_GPSR(IP0SR2_7_4, FXR_TXENA_N), + PINMUX_IPSR_GPSR(IP0SR2_7_4, CANFD1_RX), + PINMUX_IPSR_GPSR(IP0SR2_7_4, TPU0TO3_A), + + PINMUX_IPSR_GPSR(IP0SR2_11_8, RXDA_EXTFXR), + PINMUX_IPSR_GPSR(IP0SR2_11_8, CANFD5_TX), + PINMUX_IPSR_GPSR(IP0SR2_11_8, IRQ5), + + PINMUX_IPSR_GPSR(IP0SR2_15_12, CLK_EXTFXR), + PINMUX_IPSR_GPSR(IP0SR2_15_12, CANFD5_RX), + PINMUX_IPSR_GPSR(IP0SR2_15_12, IRQ4_B), + + PINMUX_IPSR_GPSR(IP0SR2_19_16, RXDB_EXTFXR), + + PINMUX_IPSR_GPSR(IP0SR2_23_20, FXR_TXENB_N), + + PINMUX_IPSR_GPSR(IP0SR2_27_24, FXR_TXDB), + + PINMUX_IPSR_GPSR(IP0SR2_31_28, TPU0TO1), + PINMUX_IPSR_GPSR(IP0SR2_31_28, CANFD6_TX), + PINMUX_IPSR_GPSR(IP0SR2_31_28, TCLK2_B), + + /* IP1SR2 */ + PINMUX_IPSR_GPSR(IP1SR2_3_0, TPU0TO0), + PINMUX_IPSR_GPSR(IP1SR2_3_0, CANFD6_RX), + PINMUX_IPSR_GPSR(IP1SR2_3_0, TCLK1_A), + + PINMUX_IPSR_GPSR(IP1SR2_7_4, CAN_CLK), + PINMUX_IPSR_GPSR(IP1SR2_7_4, FXR_TXENA_N_X), + + PINMUX_IPSR_GPSR(IP1SR2_11_8, CANFD0_TX), + PINMUX_IPSR_GPSR(IP1SR2_11_8, FXR_TXENB_N_X), + + PINMUX_IPSR_GPSR(IP1SR2_15_12, CANFD0_RX), + PINMUX_IPSR_GPSR(IP1SR2_15_12, STPWT_EXTFXR), + + PINMUX_IPSR_GPSR(IP1SR2_19_16, CANFD2_TX), + PINMUX_IPSR_GPSR(IP1SR2_19_16, TPU0TO2), + PINMUX_IPSR_GPSR(IP1SR2_19_16, TCLK3_A), + + PINMUX_IPSR_GPSR(IP1SR2_23_20, CANFD2_RX), + PINMUX_IPSR_GPSR(IP1SR2_23_20, TPU0TO3), + PINMUX_IPSR_GPSR(IP1SR2_23_20, PWM1_B), + PINMUX_IPSR_GPSR(IP1SR2_23_20, TCLK4_A), + + PINMUX_IPSR_GPSR(IP1SR2_27_24, CANFD3_TX), + PINMUX_IPSR_GPSR(IP1SR2_27_24, PWM2_B), + + PINMUX_IPSR_GPSR(IP1SR2_31_28, CANFD3_RX), + PINMUX_IPSR_GPSR(IP1SR2_31_28, PWM3_B), + + /* IP2SR2 */ + PINMUX_IPSR_GPSR(IP2SR2_3_0, CANFD4_TX), + PINMUX_IPSR_GPSR(IP2SR2_3_0, PWM4), + + PINMUX_IPSR_GPSR(IP2SR2_7_4, CANFD4_RX), + PINMUX_IPSR_GPSR(IP2SR2_7_4, PWM5), + + PINMUX_IPSR_GPSR(IP2SR2_11_8, CANFD7_TX), + PINMUX_IPSR_GPSR(IP2SR2_11_8, PWM6), + + PINMUX_IPSR_GPSR(IP2SR2_15_12, CANFD7_RX), + PINMUX_IPSR_GPSR(IP2SR2_15_12, PWM7), + + /* IP0SR3 */ + PINMUX_IPSR_GPSR(IP0SR3_3_0, MMC_SD_D1), + PINMUX_IPSR_GPSR(IP0SR3_7_4, MMC_SD_D0), + PINMUX_IPSR_GPSR(IP0SR3_11_8, MMC_SD_D2), + PINMUX_IPSR_GPSR(IP0SR3_15_12, MMC_SD_CLK), + PINMUX_IPSR_GPSR(IP0SR3_19_16, MMC_DS), + PINMUX_IPSR_GPSR(IP0SR3_23_20, MMC_SD_D3), + PINMUX_IPSR_GPSR(IP0SR3_27_24, MMC_D5), + PINMUX_IPSR_GPSR(IP0SR3_31_28, MMC_D4), + + /* IP1SR3 */ + PINMUX_IPSR_GPSR(IP1SR3_3_0, MMC_D7), + + PINMUX_IPSR_GPSR(IP1SR3_7_4, MMC_D6), + + PINMUX_IPSR_GPSR(IP1SR3_11_8, MMC_SD_CMD), + + PINMUX_IPSR_GPSR(IP1SR3_15_12, SD_CD), + + PINMUX_IPSR_GPSR(IP1SR3_19_16, SD_WP), + + PINMUX_IPSR_GPSR(IP1SR3_23_20, IPC_CLKIN), + PINMUX_IPSR_GPSR(IP1SR3_23_20, IPC_CLKEN_IN), + PINMUX_IPSR_GPSR(IP1SR3_23_20, PWM1_A), + PINMUX_IPSR_GPSR(IP1SR3_23_20, TCLK3_X), + + PINMUX_IPSR_GPSR(IP1SR3_27_24, IPC_CLKOUT), + PINMUX_IPSR_GPSR(IP1SR3_27_24, IPC_CLKEN_OUT), + PINMUX_IPSR_GPSR(IP1SR3_27_24, ERROROUTC_A), + PINMUX_IPSR_GPSR(IP1SR3_27_24, TCLK4_X), + + PINMUX_IPSR_GPSR(IP1SR3_31_28, QSPI0_SSL), + + /* IP2SR3 */ + PINMUX_IPSR_GPSR(IP2SR3_3_0, QSPI0_IO3), + PINMUX_IPSR_GPSR(IP2SR3_7_4, QSPI0_IO2), + PINMUX_IPSR_GPSR(IP2SR3_11_8, QSPI0_MISO_IO1), + PINMUX_IPSR_GPSR(IP2SR3_15_12, QSPI0_MOSI_IO0), + PINMUX_IPSR_GPSR(IP2SR3_19_16, QSPI0_SPCLK), + PINMUX_IPSR_GPSR(IP2SR3_23_20, QSPI1_MOSI_IO0), + PINMUX_IPSR_GPSR(IP2SR3_27_24, QSPI1_SPCLK), + PINMUX_IPSR_GPSR(IP2SR3_31_28, QSPI1_MISO_IO1), + + /* IP3SR3 */ + PINMUX_IPSR_GPSR(IP3SR3_3_0, QSPI1_IO2), + PINMUX_IPSR_GPSR(IP3SR3_7_4, QSPI1_SSL), + PINMUX_IPSR_GPSR(IP3SR3_11_8, QSPI1_IO3), + PINMUX_IPSR_GPSR(IP3SR3_15_12, RPC_RESET_N), + PINMUX_IPSR_GPSR(IP3SR3_19_16, RPC_WP_N), + PINMUX_IPSR_GPSR(IP3SR3_23_20, RPC_INT_N), + + /* IP0SR6 */ + PINMUX_IPSR_GPSR(IP0SR6_3_0, AVB1_MDIO), + + PINMUX_IPSR_MSEL(IP0SR6_7_4, AVB1_MAGIC, SEL_AVB1_MAGIC_1), + + PINMUX_IPSR_MSEL(IP0SR6_11_8, AVB1_MDC, SEL_AVB1_MDC_1), + + PINMUX_IPSR_GPSR(IP0SR6_15_12, AVB1_PHY_INT), + + PINMUX_IPSR_GPSR(IP0SR6_19_16, AVB1_LINK), + PINMUX_IPSR_GPSR(IP0SR6_19_16, AVB1_MII_TX_ER), + + PINMUX_IPSR_MSEL(IP0SR6_23_20, AVB1_AVTP_MATCH, SEL_AVB1_AVTP_MATCH_1), + PINMUX_IPSR_MSEL(IP0SR6_23_20, AVB1_MII_RX_ER, SEL_AVB1_AVTP_MATCH_0), + + PINMUX_IPSR_MSEL(IP0SR6_27_24, AVB1_TXC, SEL_AVB1_TXC_1), + PINMUX_IPSR_MSEL(IP0SR6_27_24, AVB1_MII_TXC, SEL_AVB1_TXC_0), + + PINMUX_IPSR_MSEL(IP0SR6_31_28, AVB1_TX_CTL, SEL_AVB1_TX_CTL_1), + PINMUX_IPSR_MSEL(IP0SR6_31_28, AVB1_MII_TX_EN, SEL_AVB1_TX_CTL_0), + + /* IP1SR6 */ + PINMUX_IPSR_GPSR(IP1SR6_3_0, AVB1_RXC), + PINMUX_IPSR_GPSR(IP1SR6_3_0, AVB1_MII_RXC), + + PINMUX_IPSR_GPSR(IP1SR6_7_4, AVB1_RX_CTL), + PINMUX_IPSR_GPSR(IP1SR6_7_4, AVB1_MII_RX_DV), + + PINMUX_IPSR_MSEL(IP1SR6_11_8, AVB1_AVTP_PPS, SEL_AVB1_AVTP_PPS_1), + PINMUX_IPSR_MSEL(IP1SR6_11_8, AVB1_MII_COL, SEL_AVB1_AVTP_PPS_0), + + PINMUX_IPSR_GPSR(IP1SR6_15_12, AVB1_AVTP_CAPTURE), + PINMUX_IPSR_GPSR(IP1SR6_15_12, AVB1_MII_CRS), + + PINMUX_IPSR_MSEL(IP1SR6_19_16, AVB1_TD1, SEL_AVB1_TD1_1), + PINMUX_IPSR_MSEL(IP1SR6_19_16, AVB1_MII_TD1, SEL_AVB1_TD1_0), + + PINMUX_IPSR_MSEL(IP1SR6_23_20, AVB1_TD0, SEL_AVB1_TD0_1), + PINMUX_IPSR_MSEL(IP1SR6_23_20, AVB1_MII_TD0, SEL_AVB1_TD0_0), + + PINMUX_IPSR_GPSR(IP1SR6_27_24, AVB1_RD1), + PINMUX_IPSR_GPSR(IP1SR6_27_24, AVB1_MII_RD1), + + PINMUX_IPSR_GPSR(IP1SR6_31_28, AVB1_RD0), + PINMUX_IPSR_GPSR(IP1SR6_31_28, AVB1_MII_RD0), + + /* IP2SR6 */ + PINMUX_IPSR_MSEL(IP2SR6_3_0, AVB1_TD2, SEL_AVB1_TD2_1), + PINMUX_IPSR_MSEL(IP2SR6_3_0, AVB1_MII_TD2, SEL_AVB1_TD2_0), + + PINMUX_IPSR_GPSR(IP2SR6_7_4, AVB1_RD2), + PINMUX_IPSR_GPSR(IP2SR6_7_4, AVB1_MII_RD2), + + PINMUX_IPSR_MSEL(IP2SR6_11_8, AVB1_TD3, SEL_AVB1_TD3_1), + PINMUX_IPSR_MSEL(IP2SR6_11_8, AVB1_MII_TD3, SEL_AVB1_TD3_0), + + PINMUX_IPSR_GPSR(IP2SR6_15_12, AVB1_RD3), + PINMUX_IPSR_GPSR(IP2SR6_15_12, AVB1_MII_RD3), + + PINMUX_IPSR_GPSR(IP2SR6_19_16, AVB1_TXCREFCLK), + + /* IP0SR7 */ + PINMUX_IPSR_MSEL(IP0SR7_3_0, AVB0_AVTP_PPS, SEL_AVB0_AVTP_PPS_1), + PINMUX_IPSR_MSEL(IP0SR7_3_0, AVB0_MII_COL, SEL_AVB0_AVTP_PPS_0), + + PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_AVTP_CAPTURE), + PINMUX_IPSR_GPSR(IP0SR7_7_4, AVB0_MII_CRS), + + PINMUX_IPSR_MSEL(IP0SR7_11_8, AVB0_AVTP_MATCH, SEL_AVB0_AVTP_MATCH_1), + PINMUX_IPSR_MSEL(IP0SR7_11_8, AVB0_MII_RX_ER, SEL_AVB0_AVTP_MATCH_0), + PINMUX_IPSR_MSEL(IP0SR7_11_8, CC5_OSCOUT, SEL_AVB0_AVTP_MATCH_0), + + PINMUX_IPSR_MSEL(IP0SR7_15_12, AVB0_TD3, SEL_AVB0_TD3_1), + PINMUX_IPSR_MSEL(IP0SR7_15_12, AVB0_MII_TD3, SEL_AVB0_TD3_0), + + PINMUX_IPSR_GPSR(IP0SR7_19_16, AVB0_LINK), + PINMUX_IPSR_GPSR(IP0SR7_19_16, AVB0_MII_TX_ER), + + PINMUX_IPSR_GPSR(IP0SR7_23_20, AVB0_PHY_INT), + + PINMUX_IPSR_MSEL(IP0SR7_27_24, AVB0_TD2, SEL_AVB0_TD2_1), + PINMUX_IPSR_MSEL(IP0SR7_27_24, AVB0_MII_TD2, SEL_AVB0_TD2_0), + + PINMUX_IPSR_MSEL(IP0SR7_31_28, AVB0_TD1, SEL_AVB0_TD1_1), + PINMUX_IPSR_MSEL(IP0SR7_31_28, AVB0_MII_TD1, SEL_AVB0_TD1_0), + + /* IP1SR7 */ + PINMUX_IPSR_GPSR(IP1SR7_3_0, AVB0_RD3), + PINMUX_IPSR_GPSR(IP1SR7_3_0, AVB0_MII_RD3), + + PINMUX_IPSR_GPSR(IP1SR7_7_4, AVB0_TXCREFCLK), + + PINMUX_IPSR_MSEL(IP1SR7_11_8, AVB0_MAGIC, SEL_AVB0_MAGIC_1), + + PINMUX_IPSR_MSEL(IP1SR7_15_12, AVB0_TD0, SEL_AVB0_TD0_1), + PINMUX_IPSR_MSEL(IP1SR7_15_12, AVB0_MII_TD0, SEL_AVB0_TD0_0), + + PINMUX_IPSR_GPSR(IP1SR7_19_16, AVB0_RD2), + PINMUX_IPSR_GPSR(IP1SR7_19_16, AVB0_MII_RD2), + + PINMUX_IPSR_MSEL(IP1SR7_23_20, AVB0_MDC, SEL_AVB0_MDC_1), + + PINMUX_IPSR_GPSR(IP1SR7_27_24, AVB0_MDIO), + + PINMUX_IPSR_MSEL(IP1SR7_31_28, AVB0_TXC, SEL_AVB0_TXC_1), + PINMUX_IPSR_MSEL(IP1SR7_31_28, AVB0_MII_TXC, SEL_AVB0_TXC_0), + + /* IP2SR7 */ + PINMUX_IPSR_MSEL(IP2SR7_3_0, AVB0_TX_CTL, SEL_AVB0_TX_CTL_1), + PINMUX_IPSR_MSEL(IP2SR7_3_0, AVB0_MII_TX_EN, SEL_AVB0_TX_CTL_0), + + PINMUX_IPSR_GPSR(IP2SR7_7_4, AVB0_RD1), + PINMUX_IPSR_GPSR(IP2SR7_7_4, AVB0_MII_RD1), + + PINMUX_IPSR_GPSR(IP2SR7_11_8, AVB0_RD0), + PINMUX_IPSR_GPSR(IP2SR7_11_8, AVB0_MII_RD0), + + PINMUX_IPSR_GPSR(IP2SR7_15_12, AVB0_RXC), + PINMUX_IPSR_GPSR(IP2SR7_15_12, AVB0_MII_RXC), + + PINMUX_IPSR_GPSR(IP2SR7_19_16, AVB0_RX_CTL), + PINMUX_IPSR_GPSR(IP2SR7_19_16, AVB0_MII_RX_DV), + + /* IP0SR8 */ + PINMUX_IPSR_MSEL(IP0SR8_3_0, SCL0, SEL_SCL0_0), + PINMUX_IPSR_MSEL(IP0SR8_7_4, SDA0, SEL_SDA0_0), + PINMUX_IPSR_MSEL(IP0SR8_11_8, SCL1, SEL_SCL1_0), + PINMUX_IPSR_MSEL(IP0SR8_15_12, SDA1, SEL_SDA1_0), + PINMUX_IPSR_MSEL(IP0SR8_19_16, SCL2, SEL_SCL2_0), + PINMUX_IPSR_MSEL(IP0SR8_23_20, SDA2, SEL_SDA2_0), + PINMUX_IPSR_MSEL(IP0SR8_27_24, SCL3, SEL_SCL3_0), + PINMUX_IPSR_MSEL(IP0SR8_31_28, SDA3, SEL_SDA3_0), + + /* IP1SR8 */ + PINMUX_IPSR_MSEL(IP1SR8_3_0, SCL4, SEL_SCL4_0), + PINMUX_IPSR_MSEL(IP1SR8_3_0, HRX2, SEL_SCL4_0), + PINMUX_IPSR_MSEL(IP1SR8_3_0, SCK4, SEL_SCL4_0), + + PINMUX_IPSR_MSEL(IP1SR8_7_4, SDA4, SEL_SDA4_0), + PINMUX_IPSR_MSEL(IP1SR8_7_4, HTX2, SEL_SDA4_0), + PINMUX_IPSR_MSEL(IP1SR8_7_4, CTS4_N, SEL_SDA4_0), + + PINMUX_IPSR_MSEL(IP1SR8_11_8, SCL5, SEL_SCL5_0), + PINMUX_IPSR_MSEL(IP1SR8_11_8, HRTS2_N, SEL_SCL5_0), + PINMUX_IPSR_MSEL(IP1SR8_11_8, RTS4_N, SEL_SCL5_0), + + PINMUX_IPSR_MSEL(IP1SR8_15_12, SDA5, SEL_SDA5_0), + PINMUX_IPSR_MSEL(IP1SR8_15_12, SCIF_CLK2, SEL_SDA5_0), + + PINMUX_IPSR_GPSR(IP1SR8_19_16, HCTS2_N), + PINMUX_IPSR_GPSR(IP1SR8_19_16, TX4), + + PINMUX_IPSR_GPSR(IP1SR8_23_20, HSCK2), + PINMUX_IPSR_GPSR(IP1SR8_23_20, RX4), +}; + +/* + * Pins not associated with a GPIO port. + */ +enum { + GP_ASSIGN_LAST(), +}; + +static const struct sh_pfc_pin pinmux_pins[] = { + PINMUX_GPIO_GP_ALL(), +}; + +/* - AVB0 ------------------------------------------------ */ +static const unsigned int avb0_link_pins[] = { + /* AVB0_LINK */ + RCAR_GP_PIN(7, 4), +}; +static const unsigned int avb0_link_mux[] = { + AVB0_LINK_MARK, +}; +static const unsigned int avb0_magic_pins[] = { + /* AVB0_MAGIC */ + RCAR_GP_PIN(7, 10), +}; +static const unsigned int avb0_magic_mux[] = { + AVB0_MAGIC_MARK, +}; +static const unsigned int avb0_phy_int_pins[] = { + /* AVB0_PHY_INT */ + RCAR_GP_PIN(7, 5), +}; +static const unsigned int avb0_phy_int_mux[] = { + AVB0_PHY_INT_MARK, +}; +static const unsigned int avb0_mdio_pins[] = { + /* AVB0_MDC, AVB0_MDIO */ + RCAR_GP_PIN(7, 13), RCAR_GP_PIN(7, 14), +}; +static const unsigned int avb0_mdio_mux[] = { + AVB0_MDC_MARK, AVB0_MDIO_MARK, +}; +static const unsigned int avb0_rgmii_pins[] = { + /* + * AVB0_TX_CTL, AVB0_TXC, AVB0_TD0, AVB0_TD1, AVB0_TD2, AVB0_TD3, + * AVB0_RX_CTL, AVB0_RXC, AVB0_RD0, AVB0_RD1, AVB0_RD2, AVB0_RD3, + */ + RCAR_GP_PIN(7, 16), RCAR_GP_PIN(7, 15), + RCAR_GP_PIN(7, 11), RCAR_GP_PIN(7, 7), + RCAR_GP_PIN(7, 6), RCAR_GP_PIN(7, 3), + RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 19), + RCAR_GP_PIN(7, 18), RCAR_GP_PIN(7, 17), + RCAR_GP_PIN(7, 12), RCAR_GP_PIN(7, 8), +}; +static const unsigned int avb0_rgmii_mux[] = { + AVB0_TX_CTL_MARK, AVB0_TXC_MARK, + AVB0_TD0_MARK, AVB0_TD1_MARK, + AVB0_TD2_MARK, AVB0_TD3_MARK, + AVB0_RX_CTL_MARK, AVB0_RXC_MARK, + AVB0_RD0_MARK, AVB0_RD1_MARK, + AVB0_RD2_MARK, AVB0_RD3_MARK, +}; +static const unsigned int avb0_txcrefclk_pins[] = { + /* AVB0_TXCREFCLK */ + RCAR_GP_PIN(7, 9), +}; +static const unsigned int avb0_txcrefclk_mux[] = { + AVB0_TXCREFCLK_MARK, +}; +static const unsigned int avb0_avtp_pps_pins[] = { + /* AVB0_AVTP_PPS */ + RCAR_GP_PIN(7, 0), +}; +static const unsigned int avb0_avtp_pps_mux[] = { + AVB0_AVTP_PPS_MARK, +}; +static const unsigned int avb0_avtp_capture_pins[] = { + /* AVB0_AVTP_CAPTURE */ + RCAR_GP_PIN(7, 1), +}; +static const unsigned int avb0_avtp_capture_mux[] = { + AVB0_AVTP_CAPTURE_MARK, +}; +static const unsigned int avb0_avtp_match_pins[] = { + /* AVB0_AVTP_MATCH */ + RCAR_GP_PIN(7, 2), +}; +static const unsigned int avb0_avtp_match_mux[] = { + AVB0_AVTP_MATCH_MARK, +}; + +/* - AVB1 ------------------------------------------------ */ +static const unsigned int avb1_link_pins[] = { + /* AVB1_LINK */ + RCAR_GP_PIN(6, 4), +}; +static const unsigned int avb1_link_mux[] = { + AVB1_LINK_MARK, +}; +static const unsigned int avb1_magic_pins[] = { + /* AVB1_MAGIC */ + RCAR_GP_PIN(6, 1), +}; +static const unsigned int avb1_magic_mux[] = { + AVB1_MAGIC_MARK, +}; +static const unsigned int avb1_phy_int_pins[] = { + /* AVB1_PHY_INT */ + RCAR_GP_PIN(6, 3), +}; +static const unsigned int avb1_phy_int_mux[] = { + AVB1_PHY_INT_MARK, +}; +static const unsigned int avb1_mdio_pins[] = { + /* AVB1_MDC, AVB1_MDIO */ + RCAR_GP_PIN(6, 2), RCAR_GP_PIN(6, 0), +}; +static const unsigned int avb1_mdio_mux[] = { + AVB1_MDC_MARK, AVB1_MDIO_MARK, +}; +static const unsigned int avb1_rgmii_pins[] = { + /* + * AVB1_TX_CTL, AVB1_TXC, AVB1_TD0, AVB1_TD1, AVB1_TD2, AVB1_TD3, + * AVB1_RX_CTL, AVB1_RXC, AVB1_RD0, AVB1_RD1, AVB1_RD2, AVB1_RD3, + */ + RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6), + RCAR_GP_PIN(6, 13), RCAR_GP_PIN(6, 12), + RCAR_GP_PIN(6, 16), RCAR_GP_PIN(6, 18), + RCAR_GP_PIN(6, 9), RCAR_GP_PIN(6, 8), + RCAR_GP_PIN(6, 15), RCAR_GP_PIN(6, 14), + RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 19), +}; +static const unsigned int avb1_rgmii_mux[] = { + AVB1_TX_CTL_MARK, AVB1_TXC_MARK, + AVB1_TD0_MARK, AVB1_TD1_MARK, + AVB1_TD2_MARK, AVB1_TD3_MARK, + AVB1_RX_CTL_MARK, AVB1_RXC_MARK, + AVB1_RD0_MARK, AVB1_RD1_MARK, + AVB1_RD2_MARK, AVB1_RD3_MARK, +}; +static const unsigned int avb1_txcrefclk_pins[] = { + /* AVB1_TXCREFCLK */ + RCAR_GP_PIN(6, 20), +}; +static const unsigned int avb1_txcrefclk_mux[] = { + AVB1_TXCREFCLK_MARK, +}; +static const unsigned int avb1_avtp_pps_pins[] = { + /* AVB1_AVTP_PPS */ + RCAR_GP_PIN(6, 10), +}; +static const unsigned int avb1_avtp_pps_mux[] = { + AVB1_AVTP_PPS_MARK, +}; +static const unsigned int avb1_avtp_capture_pins[] = { + /* AVB1_AVTP_CAPTURE */ + RCAR_GP_PIN(6, 11), +}; +static const unsigned int avb1_avtp_capture_mux[] = { + AVB1_AVTP_CAPTURE_MARK, +}; +static const unsigned int avb1_avtp_match_pins[] = { + /* AVB1_AVTP_MATCH */ + RCAR_GP_PIN(6, 5), +}; +static const unsigned int avb1_avtp_match_mux[] = { + AVB1_AVTP_MATCH_MARK, +}; + +/* - AVB2 ------------------------------------------------ */ +static const unsigned int avb2_link_pins[] = { + /* AVB2_LINK */ + RCAR_GP_PIN(5, 3), +}; +static const unsigned int avb2_link_mux[] = { + AVB2_LINK_MARK, +}; +static const unsigned int avb2_magic_pins[] = { + /* AVB2_MAGIC */ + RCAR_GP_PIN(5, 5), +}; +static const unsigned int avb2_magic_mux[] = { + AVB2_MAGIC_MARK, +}; +static const unsigned int avb2_phy_int_pins[] = { + /* AVB2_PHY_INT */ + RCAR_GP_PIN(5, 4), +}; +static const unsigned int avb2_phy_int_mux[] = { + AVB2_PHY_INT_MARK, +}; +static const unsigned int avb2_mdio_pins[] = { + /* AVB2_MDC, AVB2_MDIO */ + RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 10), +}; +static const unsigned int avb2_mdio_mux[] = { + AVB2_MDC_MARK, AVB2_MDIO_MARK, +}; +static const unsigned int avb2_rgmii_pins[] = { + /* + * AVB2_TX_CTL, AVB2_TXC, AVB2_TD0, AVB2_TD1, AVB2_TD2, AVB2_TD3, + * AVB2_RX_CTL, AVB2_RXC, AVB2_RD0, AVB2_RD1, AVB2_RD2, AVB2_RD3, + */ + RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 16), + RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 12), + RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 8), + RCAR_GP_PIN(5, 20), RCAR_GP_PIN(5, 18), + RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 14), + RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 9), +}; +static const unsigned int avb2_rgmii_mux[] = { + AVB2_TX_CTL_MARK, AVB2_TXC_MARK, + AVB2_TD0_MARK, AVB2_TD1_MARK, + AVB2_TD2_MARK, AVB2_TD3_MARK, + AVB2_RX_CTL_MARK, AVB2_RXC_MARK, + AVB2_RD0_MARK, AVB2_RD1_MARK, + AVB2_RD2_MARK, AVB2_RD3_MARK, +}; +static const unsigned int avb2_txcrefclk_pins[] = { + /* AVB2_TXCREFCLK */ + RCAR_GP_PIN(5, 7), +}; +static const unsigned int avb2_txcrefclk_mux[] = { + AVB2_TXCREFCLK_MARK, +}; +static const unsigned int avb2_avtp_pps_pins[] = { + /* AVB2_AVTP_PPS */ + RCAR_GP_PIN(5, 0), +}; +static const unsigned int avb2_avtp_pps_mux[] = { + AVB2_AVTP_PPS_MARK, +}; +static const unsigned int avb2_avtp_capture_pins[] = { + /* AVB2_AVTP_CAPTURE */ + RCAR_GP_PIN(5, 1), +}; +static const unsigned int avb2_avtp_capture_mux[] = { + AVB2_AVTP_CAPTURE_MARK, +}; +static const unsigned int avb2_avtp_match_pins[] = { + /* AVB2_AVTP_MATCH */ + RCAR_GP_PIN(5, 2), +}; +static const unsigned int avb2_avtp_match_mux[] = { + AVB2_AVTP_MATCH_MARK, +}; + +/* - CANFD0 ----------------------------------------------------------------- */ +static const unsigned int canfd0_data_pins[] = { + /* CANFD0_TX, CANFD0_RX */ + RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), +}; +static const unsigned int canfd0_data_mux[] = { + CANFD0_TX_MARK, CANFD0_RX_MARK, +}; + +/* - CANFD1 ----------------------------------------------------------------- */ +static const unsigned int canfd1_data_pins[] = { + /* CANFD1_TX, CANFD1_RX */ + RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1), +}; +static const unsigned int canfd1_data_mux[] = { + CANFD1_TX_MARK, CANFD1_RX_MARK, +}; + +/* - CANFD2 ----------------------------------------------------------------- */ +static const unsigned int canfd2_data_pins[] = { + /* CANFD2_TX, CANFD2_RX */ + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), +}; +static const unsigned int canfd2_data_mux[] = { + CANFD2_TX_MARK, CANFD2_RX_MARK, +}; + +/* - CANFD3 ----------------------------------------------------------------- */ +static const unsigned int canfd3_data_pins[] = { + /* CANFD3_TX, CANFD3_RX */ + RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), +}; +static const unsigned int canfd3_data_mux[] = { + CANFD3_TX_MARK, CANFD3_RX_MARK, +}; + +/* - CANFD4 ----------------------------------------------------------------- */ +static const unsigned int canfd4_data_pins[] = { + /* CANFD4_TX, CANFD4_RX */ + RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17), +}; +static const unsigned int canfd4_data_mux[] = { + CANFD4_TX_MARK, CANFD4_RX_MARK, +}; + +/* - CANFD5 ----------------------------------------------------------------- */ +static const unsigned int canfd5_data_pins[] = { + /* CANFD5_TX, CANFD5_RX */ + RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3), +}; +static const unsigned int canfd5_data_mux[] = { + CANFD5_TX_MARK, CANFD5_RX_MARK, +}; + +/* - CANFD5_B ----------------------------------------------------------------- */ +static const unsigned int canfd5_data_b_pins[] = { + /* CANFD5_TX_B, CANFD5_RX_B */ + RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 9), +}; +static const unsigned int canfd5_data_b_mux[] = { + CANFD5_TX_B_MARK, CANFD5_RX_B_MARK, +}; + +/* - CANFD6 ----------------------------------------------------------------- */ +static const unsigned int canfd6_data_pins[] = { + /* CANFD6_TX, CANFD6_RX */ + RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), +}; +static const unsigned int canfd6_data_mux[] = { + CANFD6_TX_MARK, CANFD6_RX_MARK, +}; + +/* - CANFD7 ----------------------------------------------------------------- */ +static const unsigned int canfd7_data_pins[] = { + /* CANFD7_TX, CANFD7_RX */ + RCAR_GP_PIN(2, 18), RCAR_GP_PIN(2, 19), +}; +static const unsigned int canfd7_data_mux[] = { + CANFD7_TX_MARK, CANFD7_RX_MARK, +}; + +/* - CANFD Clock ------------------------------------------------------------ */ +static const unsigned int can_clk_pins[] = { + /* CAN_CLK */ + RCAR_GP_PIN(2, 9), +}; +static const unsigned int can_clk_mux[] = { + CAN_CLK_MARK, +}; + +/* - HSCIF0 ----------------------------------------------------------------- */ +static const unsigned int hscif0_data_pins[] = { + /* HRX0, HTX0 */ + RCAR_GP_PIN(1, 16), RCAR_GP_PIN(1, 12), +}; +static const unsigned int hscif0_data_mux[] = { + HRX0_MARK, HTX0_MARK, +}; +static const unsigned int hscif0_clk_pins[] = { + /* HSCK0 */ + RCAR_GP_PIN(1, 15), +}; +static const unsigned int hscif0_clk_mux[] = { + HSCK0_MARK, +}; +static const unsigned int hscif0_ctrl_pins[] = { + /* HRTS0_N, HCTS0_N */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13), +}; +static const unsigned int hscif0_ctrl_mux[] = { + HRTS0_N_MARK, HCTS0_N_MARK, +}; + +/* - HSCIF1 ----------------------------------------------------------------- */ +static const unsigned int hscif1_data_pins[] = { + /* HRX1, HTX1 */ + RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), +}; +static const unsigned int hscif1_data_mux[] = { + HRX1_MARK, HTX1_MARK, +}; +static const unsigned int hscif1_clk_pins[] = { + /* HSCK1 */ + RCAR_GP_PIN(0, 18), +}; +static const unsigned int hscif1_clk_mux[] = { + HSCK1_MARK, +}; +static const unsigned int hscif1_ctrl_pins[] = { + /* HRTS1_N, HCTS1_N */ + RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), +}; +static const unsigned int hscif1_ctrl_mux[] = { + HRTS1_N_MARK, HCTS1_N_MARK, +}; + +/* - HSCIF1_X---------------------------------------------------------------- */ +static const unsigned int hscif1_data_x_pins[] = { + /* HRX1_X, HTX1_X */ + RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6), +}; +static const unsigned int hscif1_data_x_mux[] = { + HRX1_X_MARK, HTX1_X_MARK, +}; +static const unsigned int hscif1_clk_x_pins[] = { + /* HSCK1_X */ + RCAR_GP_PIN(1, 10), +}; +static const unsigned int hscif1_clk_x_mux[] = { + HSCK1_X_MARK, +}; +static const unsigned int hscif1_ctrl_x_pins[] = { + /* HRTS1_N_X, HCTS1_N_X */ + RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8), +}; +static const unsigned int hscif1_ctrl_x_mux[] = { + HRTS1_N_X_MARK, HCTS1_N_X_MARK, +}; + +/* - HSCIF2 ----------------------------------------------------------------- */ +static const unsigned int hscif2_data_pins[] = { + /* HRX2, HTX2 */ + RCAR_GP_PIN(8, 8), RCAR_GP_PIN(8, 9), +}; +static const unsigned int hscif2_data_mux[] = { + HRX2_MARK, HTX2_MARK, +}; +static const unsigned int hscif2_clk_pins[] = { + /* HSCK2 */ + RCAR_GP_PIN(8, 13), +}; +static const unsigned int hscif2_clk_mux[] = { + HSCK2_MARK, +}; +static const unsigned int hscif2_ctrl_pins[] = { + /* HRTS2_N, HCTS2_N */ + RCAR_GP_PIN(8, 10), RCAR_GP_PIN(8, 12), +}; +static const unsigned int hscif2_ctrl_mux[] = { + HRTS2_N_MARK, HCTS2_N_MARK, +}; + +/* - HSCIF3 ----------------------------------------------------------------- */ +static const unsigned int hscif3_data_pins[] = { + /* HRX3, HTX3 */ + RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 28), +}; +static const unsigned int hscif3_data_mux[] = { + HRX3_MARK, HTX3_MARK, +}; +static const unsigned int hscif3_clk_pins[] = { + /* HSCK3 */ + RCAR_GP_PIN(1, 25), +}; +static const unsigned int hscif3_clk_mux[] = { + HSCK3_MARK, +}; +static const unsigned int hscif3_ctrl_pins[] = { + /* HRTS3_N, HCTS3_N */ + RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 27), +}; +static const unsigned int hscif3_ctrl_mux[] = { + HRTS3_N_MARK, HCTS3_N_MARK, +}; + +/* - HSCIF3_A ----------------------------------------------------------------- */ +static const unsigned int hscif3_data_a_pins[] = { + /* HRX3_A, HTX3_A */ + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 0), +}; +static const unsigned int hscif3_data_a_mux[] = { + HRX3_A_MARK, HTX3_A_MARK, +}; +static const unsigned int hscif3_clk_a_pins[] = { + /* HSCK3_A */ + RCAR_GP_PIN(1, 3), +}; +static const unsigned int hscif3_clk_a_mux[] = { + HSCK3_A_MARK, +}; +static const unsigned int hscif3_ctrl_a_pins[] = { + /* HRTS3_N_A, HCTS3_N_A */ + RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 1), +}; +static const unsigned int hscif3_ctrl_a_mux[] = { + HRTS3_N_A_MARK, HCTS3_N_A_MARK, +}; + +/* - I2C0 ------------------------------------------------------------------- */ +static const unsigned int i2c0_pins[] = { + /* SDA0, SCL0 */ + RCAR_GP_PIN(8, 1), RCAR_GP_PIN(8, 0), +}; +static const unsigned int i2c0_mux[] = { + SDA0_MARK, SCL0_MARK, +}; + +/* - I2C1 ------------------------------------------------------------------- */ +static const unsigned int i2c1_pins[] = { + /* SDA1, SCL1 */ + RCAR_GP_PIN(8, 3), RCAR_GP_PIN(8, 2), +}; +static const unsigned int i2c1_mux[] = { + SDA1_MARK, SCL1_MARK, +}; + +/* - I2C2 ------------------------------------------------------------------- */ +static const unsigned int i2c2_pins[] = { + /* SDA2, SCL2 */ + RCAR_GP_PIN(8, 5), RCAR_GP_PIN(8, 4), +}; +static const unsigned int i2c2_mux[] = { + SDA2_MARK, SCL2_MARK, +}; + +/* - I2C3 ------------------------------------------------------------------- */ +static const unsigned int i2c3_pins[] = { + /* SDA3, SCL3 */ + RCAR_GP_PIN(8, 7), RCAR_GP_PIN(8, 6), +}; +static const unsigned int i2c3_mux[] = { + SDA3_MARK, SCL3_MARK, +}; + +/* - I2C4 ------------------------------------------------------------------- */ +static const unsigned int i2c4_pins[] = { + /* SDA4, SCL4 */ + RCAR_GP_PIN(8, 9), RCAR_GP_PIN(8, 8), +}; +static const unsigned int i2c4_mux[] = { + SDA4_MARK, SCL4_MARK, +}; + +/* - I2C5 ------------------------------------------------------------------- */ +static const unsigned int i2c5_pins[] = { + /* SDA5, SCL5 */ + RCAR_GP_PIN(8, 11), RCAR_GP_PIN(8, 10), +}; +static const unsigned int i2c5_mux[] = { + SDA5_MARK, SCL5_MARK, +}; + +/* - MMC -------------------------------------------------------------------- */ +static const unsigned int mmc_data_pins[] = { + /* MMC_SD_D[0:3], MMC_D[4:7] */ + RCAR_GP_PIN(3, 1), RCAR_GP_PIN(3, 0), + RCAR_GP_PIN(3, 2), RCAR_GP_PIN(3, 5), + RCAR_GP_PIN(3, 7), RCAR_GP_PIN(3, 6), + RCAR_GP_PIN(3, 9), RCAR_GP_PIN(3, 8), +}; +static const unsigned int mmc_data_mux[] = { + MMC_SD_D0_MARK, MMC_SD_D1_MARK, + MMC_SD_D2_MARK, MMC_SD_D3_MARK, + MMC_D4_MARK, MMC_D5_MARK, + MMC_D6_MARK, MMC_D7_MARK, +}; +static const unsigned int mmc_ctrl_pins[] = { + /* MMC_SD_CLK, MMC_SD_CMD */ + RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 10), +}; +static const unsigned int mmc_ctrl_mux[] = { + MMC_SD_CLK_MARK, MMC_SD_CMD_MARK, +}; +static const unsigned int mmc_cd_pins[] = { + /* SD_CD */ + RCAR_GP_PIN(3, 11), +}; +static const unsigned int mmc_cd_mux[] = { + SD_CD_MARK, +}; +static const unsigned int mmc_wp_pins[] = { + /* SD_WP */ + RCAR_GP_PIN(3, 12), +}; +static const unsigned int mmc_wp_mux[] = { + SD_WP_MARK, +}; +static const unsigned int mmc_ds_pins[] = { + /* MMC_DS */ + RCAR_GP_PIN(3, 4), +}; +static const unsigned int mmc_ds_mux[] = { + MMC_DS_MARK, +}; + +/* - MSIOF0 ----------------------------------------------------------------- */ +static const unsigned int msiof0_clk_pins[] = { + /* MSIOF0_SCK */ + RCAR_GP_PIN(1, 10), +}; +static const unsigned int msiof0_clk_mux[] = { + MSIOF0_SCK_MARK, +}; +static const unsigned int msiof0_sync_pins[] = { + /* MSIOF0_SYNC */ + RCAR_GP_PIN(1, 8), +}; +static const unsigned int msiof0_sync_mux[] = { + MSIOF0_SYNC_MARK, +}; +static const unsigned int msiof0_ss1_pins[] = { + /* MSIOF0_SS1 */ + RCAR_GP_PIN(1, 7), +}; +static const unsigned int msiof0_ss1_mux[] = { + MSIOF0_SS1_MARK, +}; +static const unsigned int msiof0_ss2_pins[] = { + /* MSIOF0_SS2 */ + RCAR_GP_PIN(1, 6), +}; +static const unsigned int msiof0_ss2_mux[] = { + MSIOF0_SS2_MARK, +}; +static const unsigned int msiof0_txd_pins[] = { + /* MSIOF0_TXD */ + RCAR_GP_PIN(1, 9), +}; +static const unsigned int msiof0_txd_mux[] = { + MSIOF0_TXD_MARK, +}; +static const unsigned int msiof0_rxd_pins[] = { + /* MSIOF0_RXD */ + RCAR_GP_PIN(1, 11), +}; +static const unsigned int msiof0_rxd_mux[] = { + MSIOF0_RXD_MARK, +}; + +/* - MSIOF1 ----------------------------------------------------------------- */ +static const unsigned int msiof1_clk_pins[] = { + /* MSIOF1_SCK */ + RCAR_GP_PIN(1, 3), +}; +static const unsigned int msiof1_clk_mux[] = { + MSIOF1_SCK_MARK, +}; +static const unsigned int msiof1_sync_pins[] = { + /* MSIOF1_SYNC */ + RCAR_GP_PIN(1, 2), +}; +static const unsigned int msiof1_sync_mux[] = { + MSIOF1_SYNC_MARK, +}; +static const unsigned int msiof1_ss1_pins[] = { + /* MSIOF1_SS1 */ + RCAR_GP_PIN(1, 1), +}; +static const unsigned int msiof1_ss1_mux[] = { + MSIOF1_SS1_MARK, +}; +static const unsigned int msiof1_ss2_pins[] = { + /* MSIOF1_SS2 */ + RCAR_GP_PIN(1, 0), +}; +static const unsigned int msiof1_ss2_mux[] = { + MSIOF1_SS2_MARK, +}; +static const unsigned int msiof1_txd_pins[] = { + /* MSIOF1_TXD */ + RCAR_GP_PIN(1, 4), +}; +static const unsigned int msiof1_txd_mux[] = { + MSIOF1_TXD_MARK, +}; +static const unsigned int msiof1_rxd_pins[] = { + /* MSIOF1_RXD */ + RCAR_GP_PIN(1, 5), +}; +static const unsigned int msiof1_rxd_mux[] = { + MSIOF1_RXD_MARK, +}; + +/* - MSIOF2 ----------------------------------------------------------------- */ +static const unsigned int msiof2_clk_pins[] = { + /* MSIOF2_SCK */ + RCAR_GP_PIN(0, 17), +}; +static const unsigned int msiof2_clk_mux[] = { + MSIOF2_SCK_MARK, +}; +static const unsigned int msiof2_sync_pins[] = { + /* MSIOF2_SYNC */ + RCAR_GP_PIN(0, 15), +}; +static const unsigned int msiof2_sync_mux[] = { + MSIOF2_SYNC_MARK, +}; +static const unsigned int msiof2_ss1_pins[] = { + /* MSIOF2_SS1 */ + RCAR_GP_PIN(0, 14), +}; +static const unsigned int msiof2_ss1_mux[] = { + MSIOF2_SS1_MARK, +}; +static const unsigned int msiof2_ss2_pins[] = { + /* MSIOF2_SS2 */ + RCAR_GP_PIN(0, 13), +}; +static const unsigned int msiof2_ss2_mux[] = { + MSIOF2_SS2_MARK, +}; +static const unsigned int msiof2_txd_pins[] = { + /* MSIOF2_TXD */ + RCAR_GP_PIN(0, 16), +}; +static const unsigned int msiof2_txd_mux[] = { + MSIOF2_TXD_MARK, +}; +static const unsigned int msiof2_rxd_pins[] = { + /* MSIOF2_RXD */ + RCAR_GP_PIN(0, 18), +}; +static const unsigned int msiof2_rxd_mux[] = { + MSIOF2_RXD_MARK, +}; + +/* - MSIOF3 ----------------------------------------------------------------- */ +static const unsigned int msiof3_clk_pins[] = { + /* MSIOF3_SCK */ + RCAR_GP_PIN(0, 3), +}; +static const unsigned int msiof3_clk_mux[] = { + MSIOF3_SCK_MARK, +}; +static const unsigned int msiof3_sync_pins[] = { + /* MSIOF3_SYNC */ + RCAR_GP_PIN(0, 6), +}; +static const unsigned int msiof3_sync_mux[] = { + MSIOF3_SYNC_MARK, +}; +static const unsigned int msiof3_ss1_pins[] = { + /* MSIOF3_SS1 */ + RCAR_GP_PIN(0, 1), +}; +static const unsigned int msiof3_ss1_mux[] = { + MSIOF3_SS1_MARK, +}; +static const unsigned int msiof3_ss2_pins[] = { + /* MSIOF3_SS2 */ + RCAR_GP_PIN(0, 2), +}; +static const unsigned int msiof3_ss2_mux[] = { + MSIOF3_SS2_MARK, +}; +static const unsigned int msiof3_txd_pins[] = { + /* MSIOF3_TXD */ + RCAR_GP_PIN(0, 4), +}; +static const unsigned int msiof3_txd_mux[] = { + MSIOF3_TXD_MARK, +}; +static const unsigned int msiof3_rxd_pins[] = { + /* MSIOF3_RXD */ + RCAR_GP_PIN(0, 5), +}; +static const unsigned int msiof3_rxd_mux[] = { + MSIOF3_RXD_MARK, +}; + +/* - MSIOF4 ----------------------------------------------------------------- */ +static const unsigned int msiof4_clk_pins[] = { + /* MSIOF4_SCK */ + RCAR_GP_PIN(1, 25), +}; +static const unsigned int msiof4_clk_mux[] = { + MSIOF4_SCK_MARK, +}; +static const unsigned int msiof4_sync_pins[] = { + /* MSIOF4_SYNC */ + RCAR_GP_PIN(1, 28), +}; +static const unsigned int msiof4_sync_mux[] = { + MSIOF4_SYNC_MARK, +}; +static const unsigned int msiof4_ss1_pins[] = { + /* MSIOF4_SS1 */ + RCAR_GP_PIN(1, 23), +}; +static const unsigned int msiof4_ss1_mux[] = { + MSIOF4_SS1_MARK, +}; +static const unsigned int msiof4_ss2_pins[] = { + /* MSIOF4_SS2 */ + RCAR_GP_PIN(1, 24), +}; +static const unsigned int msiof4_ss2_mux[] = { + MSIOF4_SS2_MARK, +}; +static const unsigned int msiof4_txd_pins[] = { + /* MSIOF4_TXD */ + RCAR_GP_PIN(1, 26), +}; +static const unsigned int msiof4_txd_mux[] = { + MSIOF4_TXD_MARK, +}; +static const unsigned int msiof4_rxd_pins[] = { + /* MSIOF4_RXD */ + RCAR_GP_PIN(1, 27), +}; +static const unsigned int msiof4_rxd_mux[] = { + MSIOF4_RXD_MARK, +}; + +/* - MSIOF5 ----------------------------------------------------------------- */ +static const unsigned int msiof5_clk_pins[] = { + /* MSIOF5_SCK */ + RCAR_GP_PIN(0, 11), +}; +static const unsigned int msiof5_clk_mux[] = { + MSIOF5_SCK_MARK, +}; +static const unsigned int msiof5_sync_pins[] = { + /* MSIOF5_SYNC */ + RCAR_GP_PIN(0, 9), +}; +static const unsigned int msiof5_sync_mux[] = { + MSIOF5_SYNC_MARK, +}; +static const unsigned int msiof5_ss1_pins[] = { + /* MSIOF5_SS1 */ + RCAR_GP_PIN(0, 8), +}; +static const unsigned int msiof5_ss1_mux[] = { + MSIOF5_SS1_MARK, +}; +static const unsigned int msiof5_ss2_pins[] = { + /* MSIOF5_SS2 */ + RCAR_GP_PIN(0, 7), +}; +static const unsigned int msiof5_ss2_mux[] = { + MSIOF5_SS2_MARK, +}; +static const unsigned int msiof5_txd_pins[] = { + /* MSIOF5_TXD */ + RCAR_GP_PIN(0, 10), +}; +static const unsigned int msiof5_txd_mux[] = { + MSIOF5_TXD_MARK, +}; +static const unsigned int msiof5_rxd_pins[] = { + /* MSIOF5_RXD */ + RCAR_GP_PIN(0, 12), +}; +static const unsigned int msiof5_rxd_mux[] = { + MSIOF5_RXD_MARK, +}; + +/* - PCIE ------------------------------------------------------------------- */ +static const unsigned int pcie0_clkreq_n_pins[] = { + /* PCIE0_CLKREQ_N */ + RCAR_GP_PIN(4, 21), +}; + +static const unsigned int pcie0_clkreq_n_mux[] = { + PCIE0_CLKREQ_N_MARK, +}; + +static const unsigned int pcie1_clkreq_n_pins[] = { + /* PCIE1_CLKREQ_N */ + RCAR_GP_PIN(4, 22), +}; + +static const unsigned int pcie1_clkreq_n_mux[] = { + PCIE1_CLKREQ_N_MARK, +}; + +/* - PWM0_A ------------------------------------------------------------------- */ +static const unsigned int pwm0_a_pins[] = { + /* PWM0_A */ + RCAR_GP_PIN(1, 15), +}; +static const unsigned int pwm0_a_mux[] = { + PWM0_A_MARK, +}; + +/* - PWM1_A ------------------------------------------------------------------- */ +static const unsigned int pwm1_a_pins[] = { + /* PWM1_A */ + RCAR_GP_PIN(3, 13), +}; +static const unsigned int pwm1_a_mux[] = { + PWM1_A_MARK, +}; + +/* - PWM1_B ------------------------------------------------------------------- */ +static const unsigned int pwm1_b_pins[] = { + /* PWM1_B */ + RCAR_GP_PIN(2, 13), +}; +static const unsigned int pwm1_b_mux[] = { + PWM1_B_MARK, +}; + +/* - PWM2_B ------------------------------------------------------------------- */ +static const unsigned int pwm2_b_pins[] = { + /* PWM2_B */ + RCAR_GP_PIN(2, 14), +}; +static const unsigned int pwm2_b_mux[] = { + PWM2_B_MARK, +}; + +/* - PWM3_A ------------------------------------------------------------------- */ +static const unsigned int pwm3_a_pins[] = { + /* PWM3_A */ + RCAR_GP_PIN(1, 22), +}; +static const unsigned int pwm3_a_mux[] = { + PWM3_A_MARK, +}; + +/* - PWM3_B ------------------------------------------------------------------- */ +static const unsigned int pwm3_b_pins[] = { + /* PWM3_B */ + RCAR_GP_PIN(2, 15), +}; +static const unsigned int pwm3_b_mux[] = { + PWM3_B_MARK, +}; + +/* - PWM4 ------------------------------------------------------------------- */ +static const unsigned int pwm4_pins[] = { + /* PWM4 */ + RCAR_GP_PIN(2, 16), +}; +static const unsigned int pwm4_mux[] = { + PWM4_MARK, +}; + +/* - PWM5 ------------------------------------------------------------------- */ +static const unsigned int pwm5_pins[] = { + /* PWM5 */ + RCAR_GP_PIN(2, 17), +}; +static const unsigned int pwm5_mux[] = { + PWM5_MARK, +}; + +/* - PWM6 ------------------------------------------------------------------- */ +static const unsigned int pwm6_pins[] = { + /* PWM6 */ + RCAR_GP_PIN(2, 18), +}; +static const unsigned int pwm6_mux[] = { + PWM6_MARK, +}; + +/* - PWM7 ------------------------------------------------------------------- */ +static const unsigned int pwm7_pins[] = { + /* PWM7 */ + RCAR_GP_PIN(2, 19), +}; +static const unsigned int pwm7_mux[] = { + PWM7_MARK, +}; + +/* - PWM8_A ------------------------------------------------------------------- */ +static const unsigned int pwm8_a_pins[] = { + /* PWM8_A */ + RCAR_GP_PIN(1, 13), +}; +static const unsigned int pwm8_a_mux[] = { + PWM8_A_MARK, +}; + +/* - PWM9_A ------------------------------------------------------------------- */ +static const unsigned int pwm9_a_pins[] = { + /* PWM9_A */ + RCAR_GP_PIN(1, 14), +}; +static const unsigned int pwm9_a_mux[] = { + PWM9_A_MARK, +}; + +/* - QSPI0 ------------------------------------------------------------------ */ +static const unsigned int qspi0_ctrl_pins[] = { + /* SPCLK, SSL */ + RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 15), +}; +static const unsigned int qspi0_ctrl_mux[] = { + QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, +}; +static const unsigned int qspi0_data_pins[] = { + /* MOSI_IO0, MISO_IO1, IO2, IO3 */ + RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 18), + RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 16), +}; +static const unsigned int qspi0_data_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, + QSPI0_IO2_MARK, QSPI0_IO3_MARK +}; + +/* - QSPI1 ------------------------------------------------------------------ */ +static const unsigned int qspi1_ctrl_pins[] = { + /* SPCLK, SSL */ + RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 25), +}; +static const unsigned int qspi1_ctrl_mux[] = { + QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, +}; +static const unsigned int qspi1_data_pins[] = { + /* MOSI_IO0, MISO_IO1, IO2, IO3 */ + RCAR_GP_PIN(3, 21), RCAR_GP_PIN(3, 23), + RCAR_GP_PIN(3, 24), RCAR_GP_PIN(3, 26), +}; +static const unsigned int qspi1_data_mux[] = { + QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, + QSPI1_IO2_MARK, QSPI1_IO3_MARK +}; + +/* - SCIF0 ------------------------------------------------------------------ */ +static const unsigned int scif0_data_pins[] = { + /* RX0, TX0 */ + RCAR_GP_PIN(1, 16), RCAR_GP_PIN(1, 12), +}; +static const unsigned int scif0_data_mux[] = { + RX0_MARK, TX0_MARK, +}; +static const unsigned int scif0_clk_pins[] = { + /* SCK0 */ + RCAR_GP_PIN(1, 15), +}; +static const unsigned int scif0_clk_mux[] = { + SCK0_MARK, +}; +static const unsigned int scif0_ctrl_pins[] = { + /* RTS0_N, CTS0_N */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13), +}; +static const unsigned int scif0_ctrl_mux[] = { + RTS0_N_MARK, CTS0_N_MARK, +}; + +/* - SCIF1 ------------------------------------------------------------------ */ +static const unsigned int scif1_data_pins[] = { + /* RX1, TX1 */ + RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), +}; +static const unsigned int scif1_data_mux[] = { + RX1_MARK, TX1_MARK, +}; +static const unsigned int scif1_clk_pins[] = { + /* SCK1 */ + RCAR_GP_PIN(0, 18), +}; +static const unsigned int scif1_clk_mux[] = { + SCK1_MARK, +}; +static const unsigned int scif1_ctrl_pins[] = { + /* RTS1_N, CTS1_N */ + RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), +}; +static const unsigned int scif1_ctrl_mux[] = { + RTS1_N_MARK, CTS1_N_MARK, +}; + +/* - SCIF1_X ------------------------------------------------------------------ */ +static const unsigned int scif1_data_x_pins[] = { + /* RX1_X, TX1_X */ + RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6), +}; +static const unsigned int scif1_data_x_mux[] = { + RX1_X_MARK, TX1_X_MARK, +}; +static const unsigned int scif1_clk_x_pins[] = { + /* SCK1_X */ + RCAR_GP_PIN(1, 10), +}; +static const unsigned int scif1_clk_x_mux[] = { + SCK1_X_MARK, +}; +static const unsigned int scif1_ctrl_x_pins[] = { + /* RTS1_N_X, CTS1_N_X */ + RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8), +}; +static const unsigned int scif1_ctrl_x_mux[] = { + RTS1_N_X_MARK, CTS1_N_X_MARK, +}; + +/* - SCIF3 ------------------------------------------------------------------ */ +static const unsigned int scif3_data_pins[] = { + /* RX3, TX3 */ + RCAR_GP_PIN(1, 1), RCAR_GP_PIN(1, 0), +}; +static const unsigned int scif3_data_mux[] = { + RX3_MARK, TX3_MARK, +}; +static const unsigned int scif3_clk_pins[] = { + /* SCK3 */ + RCAR_GP_PIN(1, 4), +}; +static const unsigned int scif3_clk_mux[] = { + SCK3_MARK, +}; +static const unsigned int scif3_ctrl_pins[] = { + /* RTS3_N, CTS3_N */ + RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 3), +}; +static const unsigned int scif3_ctrl_mux[] = { + RTS3_N_MARK, CTS3_N_MARK, +}; + +/* - SCIF3_A ------------------------------------------------------------------ */ +static const unsigned int scif3_data_a_pins[] = { + /* RX3_A, TX3_A */ + RCAR_GP_PIN(1, 27), RCAR_GP_PIN(1, 28), +}; +static const unsigned int scif3_data_a_mux[] = { + RX3_A_MARK, TX3_A_MARK, +}; +static const unsigned int scif3_clk_a_pins[] = { + /* SCK3_A */ + RCAR_GP_PIN(1, 24), +}; +static const unsigned int scif3_clk_a_mux[] = { + SCK3_A_MARK, +}; +static const unsigned int scif3_ctrl_a_pins[] = { + /* RTS3_N_A, CTS3_N_A */ + RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25), +}; +static const unsigned int scif3_ctrl_a_mux[] = { + RTS3_N_A_MARK, CTS3_N_A_MARK, +}; + +/* - SCIF4 ------------------------------------------------------------------ */ +static const unsigned int scif4_data_pins[] = { + /* RX4, TX4 */ + RCAR_GP_PIN(8, 13), RCAR_GP_PIN(8, 12), +}; +static const unsigned int scif4_data_mux[] = { + RX4_MARK, TX4_MARK, +}; +static const unsigned int scif4_clk_pins[] = { + /* SCK4 */ + RCAR_GP_PIN(8, 8), +}; +static const unsigned int scif4_clk_mux[] = { + SCK4_MARK, +}; +static const unsigned int scif4_ctrl_pins[] = { + /* RTS4_N, CTS4_N */ + RCAR_GP_PIN(8, 10), RCAR_GP_PIN(8, 9), +}; +static const unsigned int scif4_ctrl_mux[] = { + RTS4_N_MARK, CTS4_N_MARK, +}; + +/* - SCIF Clock ------------------------------------------------------------- */ +static const unsigned int scif_clk_pins[] = { + /* SCIF_CLK */ + RCAR_GP_PIN(1, 17), +}; +static const unsigned int scif_clk_mux[] = { + SCIF_CLK_MARK, +}; + +/* - TPU ------------------------------------------------------------------- */ +static const unsigned int tpu_to0_pins[] = { + /* TPU0TO0 */ + RCAR_GP_PIN(2, 8), +}; +static const unsigned int tpu_to0_mux[] = { + TPU0TO0_MARK, +}; +static const unsigned int tpu_to1_pins[] = { + /* TPU0TO1 */ + RCAR_GP_PIN(2, 7), +}; +static const unsigned int tpu_to1_mux[] = { + TPU0TO1_MARK, +}; +static const unsigned int tpu_to2_pins[] = { + /* TPU0TO2 */ + RCAR_GP_PIN(2, 12), +}; +static const unsigned int tpu_to2_mux[] = { + TPU0TO2_MARK, +}; +static const unsigned int tpu_to3_pins[] = { + /* TPU0TO3 */ + RCAR_GP_PIN(2, 13), +}; +static const unsigned int tpu_to3_mux[] = { + TPU0TO3_MARK, +}; + +/* - TPU_A ------------------------------------------------------------------- */ +static const unsigned int tpu_to0_a_pins[] = { + /* TPU0TO0_A */ + RCAR_GP_PIN(1, 25), +}; +static const unsigned int tpu_to0_a_mux[] = { + TPU0TO0_A_MARK, +}; +static const unsigned int tpu_to1_a_pins[] = { + /* TPU0TO1_A */ + RCAR_GP_PIN(1, 26), +}; +static const unsigned int tpu_to1_a_mux[] = { + TPU0TO1_A_MARK, +}; +static const unsigned int tpu_to2_a_pins[] = { + /* TPU0TO2_A */ + RCAR_GP_PIN(2, 0), +}; +static const unsigned int tpu_to2_a_mux[] = { + TPU0TO2_A_MARK, +}; +static const unsigned int tpu_to3_a_pins[] = { + /* TPU0TO3_A */ + RCAR_GP_PIN(2, 1), +}; +static const unsigned int tpu_to3_a_mux[] = { + TPU0TO3_A_MARK, +}; + +/* - TSN0 ------------------------------------------------ */ +static const unsigned int tsn0_link_pins[] = { + /* TSN0_LINK */ + RCAR_GP_PIN(4, 4), +}; +static const unsigned int tsn0_link_mux[] = { + TSN0_LINK_MARK, +}; +static const unsigned int tsn0_phy_int_pins[] = { + /* TSN0_PHY_INT */ + RCAR_GP_PIN(4, 3), +}; +static const unsigned int tsn0_phy_int_mux[] = { + TSN0_PHY_INT_MARK, +}; +static const unsigned int tsn0_mdio_pins[] = { + /* TSN0_MDC, TSN0_MDIO */ + RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0), +}; +static const unsigned int tsn0_mdio_mux[] = { + TSN0_MDC_MARK, TSN0_MDIO_MARK, +}; +static const unsigned int tsn0_rgmii_pins[] = { + /* + * TSN0_TX_CTL, TSN0_TXC, TSN0_TD0, TSN0_TD1, TSN0_TD2, TSN0_TD3, + * TSN0_RX_CTL, TSN0_RXC, TSN0_RD0, TSN0_RD1, TSN0_RD2, TSN0_RD3, + */ + RCAR_GP_PIN(4, 9), RCAR_GP_PIN(4, 12), + RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 14), + RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 18), + RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 11), + RCAR_GP_PIN(4, 10), RCAR_GP_PIN(4, 13), + RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 16), +}; +static const unsigned int tsn0_rgmii_mux[] = { + TSN0_TX_CTL_MARK, TSN0_TXC_MARK, + TSN0_TD0_MARK, TSN0_TD1_MARK, + TSN0_TD2_MARK, TSN0_TD3_MARK, + TSN0_RX_CTL_MARK, TSN0_RXC_MARK, + TSN0_RD0_MARK, TSN0_RD1_MARK, + TSN0_RD2_MARK, TSN0_RD3_MARK, +}; +static const unsigned int tsn0_txcrefclk_pins[] = { + /* TSN0_TXCREFCLK */ + RCAR_GP_PIN(4, 20), +}; +static const unsigned int tsn0_txcrefclk_mux[] = { + TSN0_TXCREFCLK_MARK, +}; +static const unsigned int tsn0_avtp_pps_pins[] = { + /* TSN0_AVTP_PPS0, TSN0_AVTP_PPS1 */ + RCAR_GP_PIN(4, 8), RCAR_GP_PIN(4, 2), +}; +static const unsigned int tsn0_avtp_pps_mux[] = { + TSN0_AVTP_PPS0_MARK, TSN0_AVTP_PPS1_MARK, +}; +static const unsigned int tsn0_avtp_capture_pins[] = { + /* TSN0_AVTP_CAPTURE */ + RCAR_GP_PIN(4, 6), +}; +static const unsigned int tsn0_avtp_capture_mux[] = { + TSN0_AVTP_CAPTURE_MARK, +}; +static const unsigned int tsn0_avtp_match_pins[] = { + /* TSN0_AVTP_MATCH */ + RCAR_GP_PIN(4, 5), +}; +static const unsigned int tsn0_avtp_match_mux[] = { + TSN0_AVTP_MATCH_MARK, +}; + +static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(avb0_link), + SH_PFC_PIN_GROUP(avb0_magic), + SH_PFC_PIN_GROUP(avb0_phy_int), + SH_PFC_PIN_GROUP(avb0_mdio), + SH_PFC_PIN_GROUP(avb0_rgmii), + SH_PFC_PIN_GROUP(avb0_txcrefclk), + SH_PFC_PIN_GROUP(avb0_avtp_pps), + SH_PFC_PIN_GROUP(avb0_avtp_capture), + SH_PFC_PIN_GROUP(avb0_avtp_match), + + SH_PFC_PIN_GROUP(avb1_link), + SH_PFC_PIN_GROUP(avb1_magic), + SH_PFC_PIN_GROUP(avb1_phy_int), + SH_PFC_PIN_GROUP(avb1_mdio), + SH_PFC_PIN_GROUP(avb1_rgmii), + SH_PFC_PIN_GROUP(avb1_txcrefclk), + SH_PFC_PIN_GROUP(avb1_avtp_pps), + SH_PFC_PIN_GROUP(avb1_avtp_capture), + SH_PFC_PIN_GROUP(avb1_avtp_match), + + SH_PFC_PIN_GROUP(avb2_link), + SH_PFC_PIN_GROUP(avb2_magic), + SH_PFC_PIN_GROUP(avb2_phy_int), + SH_PFC_PIN_GROUP(avb2_mdio), + SH_PFC_PIN_GROUP(avb2_rgmii), + SH_PFC_PIN_GROUP(avb2_txcrefclk), + SH_PFC_PIN_GROUP(avb2_avtp_pps), + SH_PFC_PIN_GROUP(avb2_avtp_capture), + SH_PFC_PIN_GROUP(avb2_avtp_match), + + SH_PFC_PIN_GROUP(canfd0_data), + SH_PFC_PIN_GROUP(canfd1_data), + SH_PFC_PIN_GROUP(canfd2_data), + SH_PFC_PIN_GROUP(canfd3_data), + SH_PFC_PIN_GROUP(canfd4_data), + SH_PFC_PIN_GROUP(canfd5_data), /* suffix might be updated */ + SH_PFC_PIN_GROUP(canfd5_data_b), /* suffix might be updated */ + SH_PFC_PIN_GROUP(canfd6_data), + SH_PFC_PIN_GROUP(canfd7_data), + SH_PFC_PIN_GROUP(can_clk), + + SH_PFC_PIN_GROUP(hscif0_data), + SH_PFC_PIN_GROUP(hscif0_clk), + SH_PFC_PIN_GROUP(hscif0_ctrl), + SH_PFC_PIN_GROUP(hscif1_data), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif1_clk), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif1_ctrl), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif1_data_x), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif1_clk_x), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif1_ctrl_x), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif2_data), + SH_PFC_PIN_GROUP(hscif2_clk), + SH_PFC_PIN_GROUP(hscif2_ctrl), + SH_PFC_PIN_GROUP(hscif3_data), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif3_clk), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif3_ctrl), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif3_data_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif3_clk_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(hscif3_ctrl_a), /* suffix might be updated */ + + SH_PFC_PIN_GROUP(i2c0), + SH_PFC_PIN_GROUP(i2c1), + SH_PFC_PIN_GROUP(i2c2), + SH_PFC_PIN_GROUP(i2c3), + SH_PFC_PIN_GROUP(i2c4), + SH_PFC_PIN_GROUP(i2c5), + + BUS_DATA_PIN_GROUP(mmc_data, 1), + BUS_DATA_PIN_GROUP(mmc_data, 4), + BUS_DATA_PIN_GROUP(mmc_data, 8), + SH_PFC_PIN_GROUP(mmc_ctrl), + SH_PFC_PIN_GROUP(mmc_cd), + SH_PFC_PIN_GROUP(mmc_wp), + SH_PFC_PIN_GROUP(mmc_ds), + + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), + SH_PFC_PIN_GROUP(msiof0_ss2), + SH_PFC_PIN_GROUP(msiof0_txd), + SH_PFC_PIN_GROUP(msiof0_rxd), + + SH_PFC_PIN_GROUP(msiof1_clk), + SH_PFC_PIN_GROUP(msiof1_sync), + SH_PFC_PIN_GROUP(msiof1_ss1), + SH_PFC_PIN_GROUP(msiof1_ss2), + SH_PFC_PIN_GROUP(msiof1_txd), + SH_PFC_PIN_GROUP(msiof1_rxd), + + SH_PFC_PIN_GROUP(msiof2_clk), + SH_PFC_PIN_GROUP(msiof2_sync), + SH_PFC_PIN_GROUP(msiof2_ss1), + SH_PFC_PIN_GROUP(msiof2_ss2), + SH_PFC_PIN_GROUP(msiof2_txd), + SH_PFC_PIN_GROUP(msiof2_rxd), + + SH_PFC_PIN_GROUP(msiof3_clk), + SH_PFC_PIN_GROUP(msiof3_sync), + SH_PFC_PIN_GROUP(msiof3_ss1), + SH_PFC_PIN_GROUP(msiof3_ss2), + SH_PFC_PIN_GROUP(msiof3_txd), + SH_PFC_PIN_GROUP(msiof3_rxd), + + SH_PFC_PIN_GROUP(msiof4_clk), + SH_PFC_PIN_GROUP(msiof4_sync), + SH_PFC_PIN_GROUP(msiof4_ss1), + SH_PFC_PIN_GROUP(msiof4_ss2), + SH_PFC_PIN_GROUP(msiof4_txd), + SH_PFC_PIN_GROUP(msiof4_rxd), + + SH_PFC_PIN_GROUP(msiof5_clk), + SH_PFC_PIN_GROUP(msiof5_sync), + SH_PFC_PIN_GROUP(msiof5_ss1), + SH_PFC_PIN_GROUP(msiof5_ss2), + SH_PFC_PIN_GROUP(msiof5_txd), + SH_PFC_PIN_GROUP(msiof5_rxd), + + SH_PFC_PIN_GROUP(pcie0_clkreq_n), + SH_PFC_PIN_GROUP(pcie1_clkreq_n), + + SH_PFC_PIN_GROUP(pwm0_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(pwm1_a), + SH_PFC_PIN_GROUP(pwm1_b), + SH_PFC_PIN_GROUP(pwm2_b), /* suffix might be updated */ + SH_PFC_PIN_GROUP(pwm3_a), + SH_PFC_PIN_GROUP(pwm3_b), + SH_PFC_PIN_GROUP(pwm4), + SH_PFC_PIN_GROUP(pwm5), + SH_PFC_PIN_GROUP(pwm6), + SH_PFC_PIN_GROUP(pwm7), + SH_PFC_PIN_GROUP(pwm8_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(pwm9_a), /* suffix might be updated */ + + SH_PFC_PIN_GROUP(qspi0_ctrl), + BUS_DATA_PIN_GROUP(qspi0_data, 2), + BUS_DATA_PIN_GROUP(qspi0_data, 4), + SH_PFC_PIN_GROUP(qspi1_ctrl), + BUS_DATA_PIN_GROUP(qspi1_data, 2), + BUS_DATA_PIN_GROUP(qspi1_data, 4), + + SH_PFC_PIN_GROUP(scif0_data), + SH_PFC_PIN_GROUP(scif0_clk), + SH_PFC_PIN_GROUP(scif0_ctrl), + SH_PFC_PIN_GROUP(scif1_data), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif1_clk), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif1_ctrl), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif1_data_x), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif1_clk_x), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif1_ctrl_x), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif3_data), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif3_clk), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif3_ctrl), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif3_data_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif3_clk_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif3_ctrl_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(scif4_data), + SH_PFC_PIN_GROUP(scif4_clk), + SH_PFC_PIN_GROUP(scif4_ctrl), + SH_PFC_PIN_GROUP(scif_clk), + + SH_PFC_PIN_GROUP(tpu_to0), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to0_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to1), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to1_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to2), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to2_a), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to3), /* suffix might be updated */ + SH_PFC_PIN_GROUP(tpu_to3_a), /* suffix might be updated */ + + SH_PFC_PIN_GROUP(tsn0_link), + SH_PFC_PIN_GROUP(tsn0_phy_int), + SH_PFC_PIN_GROUP(tsn0_mdio), + SH_PFC_PIN_GROUP(tsn0_rgmii), + SH_PFC_PIN_GROUP(tsn0_txcrefclk), + SH_PFC_PIN_GROUP(tsn0_avtp_pps), + SH_PFC_PIN_GROUP(tsn0_avtp_capture), + SH_PFC_PIN_GROUP(tsn0_avtp_match), +}; + +static const char * const avb0_groups[] = { + "avb0_link", + "avb0_magic", + "avb0_phy_int", + "avb0_mdio", + "avb0_rgmii", + "avb0_txcrefclk", + "avb0_avtp_pps", + "avb0_avtp_capture", + "avb0_avtp_match", +}; + +static const char * const avb1_groups[] = { + "avb1_link", + "avb1_magic", + "avb1_phy_int", + "avb1_mdio", + "avb1_rgmii", + "avb1_txcrefclk", + "avb1_avtp_pps", + "avb1_avtp_capture", + "avb1_avtp_match", +}; + +static const char * const avb2_groups[] = { + "avb2_link", + "avb2_magic", + "avb2_phy_int", + "avb2_mdio", + "avb2_rgmii", + "avb2_txcrefclk", + "avb2_avtp_pps", + "avb2_avtp_capture", + "avb2_avtp_match", +}; + +static const char * const canfd0_groups[] = { + "canfd0_data", +}; + +static const char * const canfd1_groups[] = { + "canfd1_data", +}; + +static const char * const canfd2_groups[] = { + "canfd2_data", +}; + +static const char * const canfd3_groups[] = { + "canfd3_data", +}; + +static const char * const canfd4_groups[] = { + "canfd4_data", +}; + +static const char * const canfd5_groups[] = { + /* suffix might be updated */ + "canfd5_data", + "canfd5_data_b", +}; + +static const char * const canfd6_groups[] = { + "canfd6_data", +}; + +static const char * const canfd7_groups[] = { + "canfd7_data", +}; + +static const char * const can_clk_groups[] = { + "can_clk", +}; + +static const char * const hscif0_groups[] = { + "hscif0_data", + "hscif0_clk", + "hscif0_ctrl", +}; + +static const char * const hscif1_groups[] = { + /* suffix might be updated */ + "hscif1_data", + "hscif1_clk", + "hscif1_ctrl", + "hscif1_data_x", + "hscif1_clk_x", + "hscif1_ctrl_x", +}; + +static const char * const hscif2_groups[] = { + "hscif2_data", + "hscif2_clk", + "hscif2_ctrl", +}; + +static const char * const hscif3_groups[] = { + /* suffix might be updated */ + "hscif3_data", + "hscif3_clk", + "hscif3_ctrl", + "hscif3_data_a", + "hscif3_clk_a", + "hscif3_ctrl_a", +}; + +static const char * const i2c0_groups[] = { + "i2c0", +}; + +static const char * const i2c1_groups[] = { + "i2c1", +}; + +static const char * const i2c2_groups[] = { + "i2c2", +}; + +static const char * const i2c3_groups[] = { + "i2c3", +}; + +static const char * const i2c4_groups[] = { + "i2c4", +}; + +static const char * const i2c5_groups[] = { + "i2c5", +}; + +static const char * const mmc_groups[] = { + "mmc_data1", + "mmc_data4", + "mmc_data8", + "mmc_ctrl", + "mmc_cd", + "mmc_wp", + "mmc_ds", +}; + +static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", + "msiof0_ss1", + "msiof0_ss2", + "msiof0_txd", + "msiof0_rxd", +}; + +static const char * const msiof1_groups[] = { + "msiof1_clk", + "msiof1_sync", + "msiof1_ss1", + "msiof1_ss2", + "msiof1_txd", + "msiof1_rxd", +}; + +static const char * const msiof2_groups[] = { + "msiof2_clk", + "msiof2_sync", + "msiof2_ss1", + "msiof2_ss2", + "msiof2_txd", + "msiof2_rxd", +}; + +static const char * const msiof3_groups[] = { + "msiof3_clk", + "msiof3_sync", + "msiof3_ss1", + "msiof3_ss2", + "msiof3_txd", + "msiof3_rxd", +}; + +static const char * const msiof4_groups[] = { + "msiof4_clk", + "msiof4_sync", + "msiof4_ss1", + "msiof4_ss2", + "msiof4_txd", + "msiof4_rxd", +}; + +static const char * const msiof5_groups[] = { + "msiof5_clk", + "msiof5_sync", + "msiof5_ss1", + "msiof5_ss2", + "msiof5_txd", + "msiof5_rxd", +}; + +static const char * const pcie_groups[] = { + "pcie0_clkreq_n", + "pcie1_clkreq_n", +}; + +static const char * const pwm0_groups[] = { + /* suffix might be updated */ + "pwm0_a", +}; + +static const char * const pwm1_groups[] = { + "pwm1_a", + "pwm1_b", +}; + +static const char * const pwm2_groups[] = { + /* suffix might be updated */ + "pwm2_b", +}; + +static const char * const pwm3_groups[] = { + "pwm3_a", + "pwm3_b", +}; + +static const char * const pwm4_groups[] = { + "pwm4", +}; + +static const char * const pwm5_groups[] = { + "pwm5", +}; + +static const char * const pwm6_groups[] = { + "pwm6", +}; + +static const char * const pwm7_groups[] = { + "pwm7", +}; + +static const char * const pwm8_groups[] = { + /* suffix might be updated */ + "pwm8_a", +}; + +static const char * const pwm9_groups[] = { + /* suffix might be updated */ + "pwm9_a", +}; + +static const char * const qspi0_groups[] = { + "qspi0_ctrl", + "qspi0_data2", + "qspi0_data4", +}; + +static const char * const qspi1_groups[] = { + "qspi1_ctrl", + "qspi1_data2", + "qspi1_data4", +}; + +static const char * const scif0_groups[] = { + "scif0_data", + "scif0_clk", + "scif0_ctrl", +}; + +static const char * const scif1_groups[] = { + /* suffix might be updated */ + "scif1_data", + "scif1_clk", + "scif1_ctrl", + "scif1_data_x", + "scif1_clk_x", + "scif1_ctrl_x", +}; + +static const char * const scif3_groups[] = { + /* suffix might be updated */ + "scif3_data", + "scif3_clk", + "scif3_ctrl", + "scif3_data_a", + "scif3_clk_a", + "scif3_ctrl_a", +}; + +static const char * const scif4_groups[] = { + "scif4_data", + "scif4_clk", + "scif4_ctrl", +}; + +static const char * const scif_clk_groups[] = { + "scif_clk", +}; + +static const char * const tpu_groups[] = { + /* suffix might be updated */ + "tpu_to0", + "tpu_to0_a", + "tpu_to1", + "tpu_to1_a", + "tpu_to2", + "tpu_to2_a", + "tpu_to3", + "tpu_to3_a", +}; + +static const char * const tsn0_groups[] = { + "tsn0_link", + "tsn0_phy_int", + "tsn0_mdio", + "tsn0_rgmii", + "tsn0_txcrefclk", + "tsn0_avtp_pps", + "tsn0_avtp_capture", + "tsn0_avtp_match", +}; + +static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(avb0), + SH_PFC_FUNCTION(avb1), + SH_PFC_FUNCTION(avb2), + + SH_PFC_FUNCTION(canfd0), + SH_PFC_FUNCTION(canfd1), + SH_PFC_FUNCTION(canfd2), + SH_PFC_FUNCTION(canfd3), + SH_PFC_FUNCTION(canfd4), + SH_PFC_FUNCTION(canfd5), + SH_PFC_FUNCTION(canfd6), + SH_PFC_FUNCTION(canfd7), + SH_PFC_FUNCTION(can_clk), + + SH_PFC_FUNCTION(hscif0), + SH_PFC_FUNCTION(hscif1), + SH_PFC_FUNCTION(hscif2), + SH_PFC_FUNCTION(hscif3), + + SH_PFC_FUNCTION(i2c0), + SH_PFC_FUNCTION(i2c1), + SH_PFC_FUNCTION(i2c2), + SH_PFC_FUNCTION(i2c3), + SH_PFC_FUNCTION(i2c4), + SH_PFC_FUNCTION(i2c5), + + SH_PFC_FUNCTION(mmc), + + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), + SH_PFC_FUNCTION(msiof3), + SH_PFC_FUNCTION(msiof4), + SH_PFC_FUNCTION(msiof5), + + SH_PFC_FUNCTION(pcie), + + SH_PFC_FUNCTION(pwm0), + SH_PFC_FUNCTION(pwm1), + SH_PFC_FUNCTION(pwm2), + SH_PFC_FUNCTION(pwm3), + SH_PFC_FUNCTION(pwm4), + SH_PFC_FUNCTION(pwm5), + SH_PFC_FUNCTION(pwm6), + SH_PFC_FUNCTION(pwm7), + SH_PFC_FUNCTION(pwm8), + SH_PFC_FUNCTION(pwm9), + + SH_PFC_FUNCTION(qspi0), + SH_PFC_FUNCTION(qspi1), + + SH_PFC_FUNCTION(scif0), + SH_PFC_FUNCTION(scif1), + SH_PFC_FUNCTION(scif3), + SH_PFC_FUNCTION(scif4), + SH_PFC_FUNCTION(scif_clk), + + SH_PFC_FUNCTION(tpu), + + SH_PFC_FUNCTION(tsn0), +}; + +static const struct pinmux_cfg_reg pinmux_config_regs[] = { +#define F_(x, y) FN_##y +#define FM(x) FN_##x + { PINMUX_CFG_REG_VAR("GPSR0", 0xE6050040, 32, + GROUP(-13, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_19 RESERVED */ + GP_0_18_FN, GPSR0_18, + GP_0_17_FN, GPSR0_17, + GP_0_16_FN, GPSR0_16, + GP_0_15_FN, GPSR0_15, + GP_0_14_FN, GPSR0_14, + GP_0_13_FN, GPSR0_13, + GP_0_12_FN, GPSR0_12, + GP_0_11_FN, GPSR0_11, + GP_0_10_FN, GPSR0_10, + GP_0_9_FN, GPSR0_9, + GP_0_8_FN, GPSR0_8, + GP_0_7_FN, GPSR0_7, + GP_0_6_FN, GPSR0_6, + GP_0_5_FN, GPSR0_5, + GP_0_4_FN, GPSR0_4, + GP_0_3_FN, GPSR0_3, + GP_0_2_FN, GPSR0_2, + GP_0_1_FN, GPSR0_1, + GP_0_0_FN, GPSR0_0, )) + }, + { PINMUX_CFG_REG("GPSR1", 0xE6050840, 32, 1, GROUP( + 0, 0, + 0, 0, + 0, 0, + GP_1_28_FN, GPSR1_28, + GP_1_27_FN, GPSR1_27, + GP_1_26_FN, GPSR1_26, + GP_1_25_FN, GPSR1_25, + GP_1_24_FN, GPSR1_24, + GP_1_23_FN, GPSR1_23, + GP_1_22_FN, GPSR1_22, + GP_1_21_FN, GPSR1_21, + GP_1_20_FN, GPSR1_20, + GP_1_19_FN, GPSR1_19, + GP_1_18_FN, GPSR1_18, + GP_1_17_FN, GPSR1_17, + GP_1_16_FN, GPSR1_16, + GP_1_15_FN, GPSR1_15, + GP_1_14_FN, GPSR1_14, + GP_1_13_FN, GPSR1_13, + GP_1_12_FN, GPSR1_12, + GP_1_11_FN, GPSR1_11, + GP_1_10_FN, GPSR1_10, + GP_1_9_FN, GPSR1_9, + GP_1_8_FN, GPSR1_8, + GP_1_7_FN, GPSR1_7, + GP_1_6_FN, GPSR1_6, + GP_1_5_FN, GPSR1_5, + GP_1_4_FN, GPSR1_4, + GP_1_3_FN, GPSR1_3, + GP_1_2_FN, GPSR1_2, + GP_1_1_FN, GPSR1_1, + GP_1_0_FN, GPSR1_0, )) + }, + { PINMUX_CFG_REG_VAR("GPSR2", 0xE6058040, 32, + GROUP(-12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP2_31_20 RESERVED */ + GP_2_19_FN, GPSR2_19, + GP_2_18_FN, GPSR2_18, + GP_2_17_FN, GPSR2_17, + GP_2_16_FN, GPSR2_16, + GP_2_15_FN, GPSR2_15, + GP_2_14_FN, GPSR2_14, + GP_2_13_FN, GPSR2_13, + GP_2_12_FN, GPSR2_12, + GP_2_11_FN, GPSR2_11, + GP_2_10_FN, GPSR2_10, + GP_2_9_FN, GPSR2_9, + GP_2_8_FN, GPSR2_8, + GP_2_7_FN, GPSR2_7, + GP_2_6_FN, GPSR2_6, + GP_2_5_FN, GPSR2_5, + GP_2_4_FN, GPSR2_4, + GP_2_3_FN, GPSR2_3, + GP_2_2_FN, GPSR2_2, + GP_2_1_FN, GPSR2_1, + GP_2_0_FN, GPSR2_0, )) + }, + { PINMUX_CFG_REG("GPSR3", 0xE6058840, 32, 1, GROUP( + 0, 0, + 0, 0, + GP_3_29_FN, GPSR3_29, + GP_3_28_FN, GPSR3_28, + GP_3_27_FN, GPSR3_27, + GP_3_26_FN, GPSR3_26, + GP_3_25_FN, GPSR3_25, + GP_3_24_FN, GPSR3_24, + GP_3_23_FN, GPSR3_23, + GP_3_22_FN, GPSR3_22, + GP_3_21_FN, GPSR3_21, + GP_3_20_FN, GPSR3_20, + GP_3_19_FN, GPSR3_19, + GP_3_18_FN, GPSR3_18, + GP_3_17_FN, GPSR3_17, + GP_3_16_FN, GPSR3_16, + GP_3_15_FN, GPSR3_15, + GP_3_14_FN, GPSR3_14, + GP_3_13_FN, GPSR3_13, + GP_3_12_FN, GPSR3_12, + GP_3_11_FN, GPSR3_11, + GP_3_10_FN, GPSR3_10, + GP_3_9_FN, GPSR3_9, + GP_3_8_FN, GPSR3_8, + GP_3_7_FN, GPSR3_7, + GP_3_6_FN, GPSR3_6, + GP_3_5_FN, GPSR3_5, + GP_3_4_FN, GPSR3_4, + GP_3_3_FN, GPSR3_3, + GP_3_2_FN, GPSR3_2, + GP_3_1_FN, GPSR3_1, + GP_3_0_FN, GPSR3_0, )) + }, + { PINMUX_CFG_REG("GPSR4", 0xE6060040, 32, 1, GROUP( + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + GP_4_24_FN, GPSR4_24, + GP_4_23_FN, GPSR4_23, + GP_4_22_FN, GPSR4_22, + GP_4_21_FN, GPSR4_21, + GP_4_20_FN, GPSR4_20, + GP_4_19_FN, GPSR4_19, + GP_4_18_FN, GPSR4_18, + GP_4_17_FN, GPSR4_17, + GP_4_16_FN, GPSR4_16, + GP_4_15_FN, GPSR4_15, + GP_4_14_FN, GPSR4_14, + GP_4_13_FN, GPSR4_13, + GP_4_12_FN, GPSR4_12, + GP_4_11_FN, GPSR4_11, + GP_4_10_FN, GPSR4_10, + GP_4_9_FN, GPSR4_9, + GP_4_8_FN, GPSR4_8, + GP_4_7_FN, GPSR4_7, + GP_4_6_FN, GPSR4_6, + GP_4_5_FN, GPSR4_5, + GP_4_4_FN, GPSR4_4, + GP_4_3_FN, GPSR4_3, + GP_4_2_FN, GPSR4_2, + GP_4_1_FN, GPSR4_1, + GP_4_0_FN, GPSR4_0, )) + }, + { PINMUX_CFG_REG_VAR("GPSR5", 0xE6060840, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP5_31_21 RESERVED */ + GP_5_20_FN, GPSR5_20, + GP_5_19_FN, GPSR5_19, + GP_5_18_FN, GPSR5_18, + GP_5_17_FN, GPSR5_17, + GP_5_16_FN, GPSR5_16, + GP_5_15_FN, GPSR5_15, + GP_5_14_FN, GPSR5_14, + GP_5_13_FN, GPSR5_13, + GP_5_12_FN, GPSR5_12, + GP_5_11_FN, GPSR5_11, + GP_5_10_FN, GPSR5_10, + GP_5_9_FN, GPSR5_9, + GP_5_8_FN, GPSR5_8, + GP_5_7_FN, GPSR5_7, + GP_5_6_FN, GPSR5_6, + GP_5_5_FN, GPSR5_5, + GP_5_4_FN, GPSR5_4, + GP_5_3_FN, GPSR5_3, + GP_5_2_FN, GPSR5_2, + GP_5_1_FN, GPSR5_1, + GP_5_0_FN, GPSR5_0, )) + }, + { PINMUX_CFG_REG_VAR("GPSR6", 0xE6061040, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP6_31_21 RESERVED */ + GP_6_20_FN, GPSR6_20, + GP_6_19_FN, GPSR6_19, + GP_6_18_FN, GPSR6_18, + GP_6_17_FN, GPSR6_17, + GP_6_16_FN, GPSR6_16, + GP_6_15_FN, GPSR6_15, + GP_6_14_FN, GPSR6_14, + GP_6_13_FN, GPSR6_13, + GP_6_12_FN, GPSR6_12, + GP_6_11_FN, GPSR6_11, + GP_6_10_FN, GPSR6_10, + GP_6_9_FN, GPSR6_9, + GP_6_8_FN, GPSR6_8, + GP_6_7_FN, GPSR6_7, + GP_6_6_FN, GPSR6_6, + GP_6_5_FN, GPSR6_5, + GP_6_4_FN, GPSR6_4, + GP_6_3_FN, GPSR6_3, + GP_6_2_FN, GPSR6_2, + GP_6_1_FN, GPSR6_1, + GP_6_0_FN, GPSR6_0, )) + }, + { PINMUX_CFG_REG_VAR("GPSR7", 0xE6061840, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP7_31_21 RESERVED */ + GP_7_20_FN, GPSR7_20, + GP_7_19_FN, GPSR7_19, + GP_7_18_FN, GPSR7_18, + GP_7_17_FN, GPSR7_17, + GP_7_16_FN, GPSR7_16, + GP_7_15_FN, GPSR7_15, + GP_7_14_FN, GPSR7_14, + GP_7_13_FN, GPSR7_13, + GP_7_12_FN, GPSR7_12, + GP_7_11_FN, GPSR7_11, + GP_7_10_FN, GPSR7_10, + GP_7_9_FN, GPSR7_9, + GP_7_8_FN, GPSR7_8, + GP_7_7_FN, GPSR7_7, + GP_7_6_FN, GPSR7_6, + GP_7_5_FN, GPSR7_5, + GP_7_4_FN, GPSR7_4, + GP_7_3_FN, GPSR7_3, + GP_7_2_FN, GPSR7_2, + GP_7_1_FN, GPSR7_1, + GP_7_0_FN, GPSR7_0, )) + }, + { PINMUX_CFG_REG_VAR("GPSR8", 0xE6068040, 32, + GROUP(-18, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP8_31_14 RESERVED */ + GP_8_13_FN, GPSR8_13, + GP_8_12_FN, GPSR8_12, + GP_8_11_FN, GPSR8_11, + GP_8_10_FN, GPSR8_10, + GP_8_9_FN, GPSR8_9, + GP_8_8_FN, GPSR8_8, + GP_8_7_FN, GPSR8_7, + GP_8_6_FN, GPSR8_6, + GP_8_5_FN, GPSR8_5, + GP_8_4_FN, GPSR8_4, + GP_8_3_FN, GPSR8_3, + GP_8_2_FN, GPSR8_2, + GP_8_1_FN, GPSR8_1, + GP_8_0_FN, GPSR8_0, )) + }, +#undef F_ +#undef FM + +#define F_(x, y) x, +#define FM(x) FN_##x, + { PINMUX_CFG_REG("IP0SR0", 0xE6050060, 32, 4, GROUP( + IP0SR0_31_28 + IP0SR0_27_24 + IP0SR0_23_20 + IP0SR0_19_16 + IP0SR0_15_12 + IP0SR0_11_8 + IP0SR0_7_4 + IP0SR0_3_0)) + }, + { PINMUX_CFG_REG("IP1SR0", 0xE6050064, 32, 4, GROUP( + IP1SR0_31_28 + IP1SR0_27_24 + IP1SR0_23_20 + IP1SR0_19_16 + IP1SR0_15_12 + IP1SR0_11_8 + IP1SR0_7_4 + IP1SR0_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP2SR0", 0xE6050068, 32, + GROUP(-20, 4, 4, 4), + GROUP( + /* IP2SR0_31_12 RESERVED */ + IP2SR0_11_8 + IP2SR0_7_4 + IP2SR0_3_0)) + }, + { PINMUX_CFG_REG("IP0SR1", 0xE6050860, 32, 4, GROUP( + IP0SR1_31_28 + IP0SR1_27_24 + IP0SR1_23_20 + IP0SR1_19_16 + IP0SR1_15_12 + IP0SR1_11_8 + IP0SR1_7_4 + IP0SR1_3_0)) + }, + { PINMUX_CFG_REG("IP1SR1", 0xE6050864, 32, 4, GROUP( + IP1SR1_31_28 + IP1SR1_27_24 + IP1SR1_23_20 + IP1SR1_19_16 + IP1SR1_15_12 + IP1SR1_11_8 + IP1SR1_7_4 + IP1SR1_3_0)) + }, + { PINMUX_CFG_REG("IP2SR1", 0xE6050868, 32, 4, GROUP( + IP2SR1_31_28 + IP2SR1_27_24 + IP2SR1_23_20 + IP2SR1_19_16 + IP2SR1_15_12 + IP2SR1_11_8 + IP2SR1_7_4 + IP2SR1_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP3SR1", 0xE605086C, 32, + GROUP(-12, 4, 4, 4, 4, 4), + GROUP( + /* IP3SR1_31_20 RESERVED */ + IP3SR1_19_16 + IP3SR1_15_12 + IP3SR1_11_8 + IP3SR1_7_4 + IP3SR1_3_0)) + }, + { PINMUX_CFG_REG("IP0SR2", 0xE6058060, 32, 4, GROUP( + IP0SR2_31_28 + IP0SR2_27_24 + IP0SR2_23_20 + IP0SR2_19_16 + IP0SR2_15_12 + IP0SR2_11_8 + IP0SR2_7_4 + IP0SR2_3_0)) + }, + { PINMUX_CFG_REG("IP1SR2", 0xE6058064, 32, 4, GROUP( + IP1SR2_31_28 + IP1SR2_27_24 + IP1SR2_23_20 + IP1SR2_19_16 + IP1SR2_15_12 + IP1SR2_11_8 + IP1SR2_7_4 + IP1SR2_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP2SR2", 0xE6058068, 32, + GROUP(-16, 4, 4, 4, 4), + GROUP( + /* IP2SR2_31_16 RESERVED */ + IP2SR2_15_12 + IP2SR2_11_8 + IP2SR2_7_4 + IP2SR2_3_0)) + }, + { PINMUX_CFG_REG("IP0SR3", 0xE6058860, 32, 4, GROUP( + IP0SR3_31_28 + IP0SR3_27_24 + IP0SR3_23_20 + IP0SR3_19_16 + IP0SR3_15_12 + IP0SR3_11_8 + IP0SR3_7_4 + IP0SR3_3_0)) + }, + { PINMUX_CFG_REG("IP1SR3", 0xE6058864, 32, 4, GROUP( + IP1SR3_31_28 + IP1SR3_27_24 + IP1SR3_23_20 + IP1SR3_19_16 + IP1SR3_15_12 + IP1SR3_11_8 + IP1SR3_7_4 + IP1SR3_3_0)) + }, + { PINMUX_CFG_REG("IP2SR3", 0xE6058868, 32, 4, GROUP( + IP2SR3_31_28 + IP2SR3_27_24 + IP2SR3_23_20 + IP2SR3_19_16 + IP2SR3_15_12 + IP2SR3_11_8 + IP2SR3_7_4 + IP2SR3_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP3SR3", 0xE605886C, 32, + GROUP(-8, 4, 4, 4, 4, 4, 4), + GROUP( + /* IP3SR3_31_24 RESERVED */ + IP3SR3_23_20 + IP3SR3_19_16 + IP3SR3_15_12 + IP3SR3_11_8 + IP3SR3_7_4 + IP3SR3_3_0)) + }, + { PINMUX_CFG_REG("IP0SR6", 0xE6061060, 32, 4, GROUP( + IP0SR6_31_28 + IP0SR6_27_24 + IP0SR6_23_20 + IP0SR6_19_16 + IP0SR6_15_12 + IP0SR6_11_8 + IP0SR6_7_4 + IP0SR6_3_0)) + }, + { PINMUX_CFG_REG("IP1SR6", 0xE6061064, 32, 4, GROUP( + IP1SR6_31_28 + IP1SR6_27_24 + IP1SR6_23_20 + IP1SR6_19_16 + IP1SR6_15_12 + IP1SR6_11_8 + IP1SR6_7_4 + IP1SR6_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP2SR6", 0xE6061068, 32, + GROUP(-12, 4, 4, 4, 4, 4), + GROUP( + /* IP2SR6_31_20 RESERVED */ + IP2SR6_19_16 + IP2SR6_15_12 + IP2SR6_11_8 + IP2SR6_7_4 + IP2SR6_3_0)) + }, + { PINMUX_CFG_REG("IP0SR7", 0xE6061860, 32, 4, GROUP( + IP0SR7_31_28 + IP0SR7_27_24 + IP0SR7_23_20 + IP0SR7_19_16 + IP0SR7_15_12 + IP0SR7_11_8 + IP0SR7_7_4 + IP0SR7_3_0)) + }, + { PINMUX_CFG_REG("IP1SR7", 0xE6061864, 32, 4, GROUP( + IP1SR7_31_28 + IP1SR7_27_24 + IP1SR7_23_20 + IP1SR7_19_16 + IP1SR7_15_12 + IP1SR7_11_8 + IP1SR7_7_4 + IP1SR7_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP2SR7", 0xE6061868, 32, + GROUP(-12, 4, 4, 4, 4, 4), + GROUP( + /* IP2SR7_31_20 RESERVED */ + IP2SR7_19_16 + IP2SR7_15_12 + IP2SR7_11_8 + IP2SR7_7_4 + IP2SR7_3_0)) + }, + { PINMUX_CFG_REG("IP0SR8", 0xE6068060, 32, 4, GROUP( + IP0SR8_31_28 + IP0SR8_27_24 + IP0SR8_23_20 + IP0SR8_19_16 + IP0SR8_15_12 + IP0SR8_11_8 + IP0SR8_7_4 + IP0SR8_3_0)) + }, + { PINMUX_CFG_REG_VAR("IP1SR8", 0xE6068064, 32, + GROUP(-8, 4, 4, 4, 4, 4, 4), + GROUP( + /* IP1SR8_31_24 RESERVED */ + IP1SR8_23_20 + IP1SR8_19_16 + IP1SR8_15_12 + IP1SR8_11_8 + IP1SR8_7_4 + IP1SR8_3_0)) + }, +#undef F_ +#undef FM + +#define F_(x, y) x, +#define FM(x) FN_##x, + { PINMUX_CFG_REG_VAR("MOD_SEL4", 0xE6060100, 32, + GROUP(-12, 1, 1, -2, 1, 1, -1, 1, -2, 1, 1, -2, 1, + -2, 1, 1, -1), + GROUP( + /* RESERVED 31-20 */ + MOD_SEL4_19 + MOD_SEL4_18 + /* RESERVED 17-16 */ + MOD_SEL4_15 + MOD_SEL4_14 + /* RESERVED 13 */ + MOD_SEL4_12 + /* RESERVED 11-10 */ + MOD_SEL4_9 + MOD_SEL4_8 + /* RESERVED 7-6 */ + MOD_SEL4_5 + /* RESERVED 4-3 */ + MOD_SEL4_2 + MOD_SEL4_1 + /* RESERVED 0 */ + )) + }, + { PINMUX_CFG_REG_VAR("MOD_SEL5", 0xE6060900, 32, + GROUP(-12, 1, -2, 1, 1, -2, 1, 1, -2, 1, -1, + 1, 1, -2, 1, -1, 1), + GROUP( + /* RESERVED 31-20 */ + MOD_SEL5_19 + /* RESERVED 18-17 */ + MOD_SEL5_16 + MOD_SEL5_15 + /* RESERVED 14-13 */ + MOD_SEL5_12 + MOD_SEL5_11 + /* RESERVED 10-9 */ + MOD_SEL5_8 + /* RESERVED 7 */ + MOD_SEL5_6 + MOD_SEL5_5 + /* RESERVED 4-3 */ + MOD_SEL5_2 + /* RESERVED 1 */ + MOD_SEL5_0)) + }, + { PINMUX_CFG_REG_VAR("MOD_SEL6", 0xE6061100, 32, + GROUP(-13, 1, -1, 1, -2, 1, 1, + -1, 1, -2, 1, 1, 1, -2, 1, 1, -1), + GROUP( + /* RESERVED 31-19 */ + MOD_SEL6_18 + /* RESERVED 17 */ + MOD_SEL6_16 + /* RESERVED 15-14 */ + MOD_SEL6_13 + MOD_SEL6_12 + /* RESERVED 11 */ + MOD_SEL6_10 + /* RESERVED 9-8 */ + MOD_SEL6_7 + MOD_SEL6_6 + MOD_SEL6_5 + /* RESERVED 4-3 */ + MOD_SEL6_2 + MOD_SEL6_1 + /* RESERVED 0 */ + )) + }, + { PINMUX_CFG_REG_VAR("MOD_SEL7", 0xE6061900, 32, + GROUP(-15, 1, 1, -1, 1, -1, 1, 1, -2, 1, 1, + -2, 1, 1, -1, 1), + GROUP( + /* RESERVED 31-17 */ + MOD_SEL7_16 + MOD_SEL7_15 + /* RESERVED 14 */ + MOD_SEL7_13 + /* RESERVED 12 */ + MOD_SEL7_11 + MOD_SEL7_10 + /* RESERVED 9-8 */ + MOD_SEL7_7 + MOD_SEL7_6 + /* RESERVED 5-4 */ + MOD_SEL7_3 + MOD_SEL7_2 + /* RESERVED 1 */ + MOD_SEL7_0)) + }, + { PINMUX_CFG_REG_VAR("MOD_SEL8", 0xE6068100, 32, + GROUP(-20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED 31-12 */ + MOD_SEL8_11 + MOD_SEL8_10 + MOD_SEL8_9 + MOD_SEL8_8 + MOD_SEL8_7 + MOD_SEL8_6 + MOD_SEL8_5 + MOD_SEL8_4 + MOD_SEL8_3 + MOD_SEL8_2 + MOD_SEL8_1 + MOD_SEL8_0)) + }, + { }, +}; + +static const struct pinmux_drive_reg pinmux_drive_regs[] = { + { PINMUX_DRIVE_REG("DRV0CTRL0", 0xE6050080) { + { RCAR_GP_PIN(0, 7), 28, 3 }, /* MSIOF5_SS2 */ + { RCAR_GP_PIN(0, 6), 24, 3 }, /* IRQ0 */ + { RCAR_GP_PIN(0, 5), 20, 3 }, /* IRQ1 */ + { RCAR_GP_PIN(0, 4), 16, 3 }, /* IRQ2 */ + { RCAR_GP_PIN(0, 3), 12, 3 }, /* IRQ3 */ + { RCAR_GP_PIN(0, 2), 8, 3 }, /* GP0_02 */ + { RCAR_GP_PIN(0, 1), 4, 3 }, /* GP0_01 */ + { RCAR_GP_PIN(0, 0), 0, 3 }, /* GP0_00 */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL0", 0xE6050084) { + { RCAR_GP_PIN(0, 15), 28, 3 }, /* MSIOF2_SYNC */ + { RCAR_GP_PIN(0, 14), 24, 3 }, /* MSIOF2_SS1 */ + { RCAR_GP_PIN(0, 13), 20, 3 }, /* MSIOF2_SS2 */ + { RCAR_GP_PIN(0, 12), 16, 3 }, /* MSIOF5_RXD */ + { RCAR_GP_PIN(0, 11), 12, 3 }, /* MSIOF5_SCK */ + { RCAR_GP_PIN(0, 10), 8, 3 }, /* MSIOF5_TXD */ + { RCAR_GP_PIN(0, 9), 4, 3 }, /* MSIOF5_SYNC */ + { RCAR_GP_PIN(0, 8), 0, 3 }, /* MSIOF5_SS1 */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL0", 0xE6050088) { + { RCAR_GP_PIN(0, 18), 8, 3 }, /* MSIOF2_RXD */ + { RCAR_GP_PIN(0, 17), 4, 3 }, /* MSIOF2_SCK */ + { RCAR_GP_PIN(0, 16), 0, 3 }, /* MSIOF2_TXD */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL1", 0xE6050880) { + { RCAR_GP_PIN(1, 7), 28, 3 }, /* MSIOF0_SS1 */ + { RCAR_GP_PIN(1, 6), 24, 3 }, /* MSIOF0_SS2 */ + { RCAR_GP_PIN(1, 5), 20, 3 }, /* MSIOF1_RXD */ + { RCAR_GP_PIN(1, 4), 16, 3 }, /* MSIOF1_TXD */ + { RCAR_GP_PIN(1, 3), 12, 3 }, /* MSIOF1_SCK */ + { RCAR_GP_PIN(1, 2), 8, 3 }, /* MSIOF1_SYNC */ + { RCAR_GP_PIN(1, 1), 4, 3 }, /* MSIOF1_SS1 */ + { RCAR_GP_PIN(1, 0), 0, 3 }, /* MSIOF1_SS2 */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL1", 0xE6050884) { + { RCAR_GP_PIN(1, 15), 28, 3 }, /* HSCK0 */ + { RCAR_GP_PIN(1, 14), 24, 3 }, /* HRTS0_N */ + { RCAR_GP_PIN(1, 13), 20, 3 }, /* HCTS0_N */ + { RCAR_GP_PIN(1, 12), 16, 3 }, /* HTX0 */ + { RCAR_GP_PIN(1, 11), 12, 3 }, /* MSIOF0_RXD */ + { RCAR_GP_PIN(1, 10), 8, 3 }, /* MSIOF0_SCK */ + { RCAR_GP_PIN(1, 9), 4, 3 }, /* MSIOF0_TXD */ + { RCAR_GP_PIN(1, 8), 0, 3 }, /* MSIOF0_SYNC */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL1", 0xE6050888) { + { RCAR_GP_PIN(1, 23), 28, 3 }, /* GP1_23 */ + { RCAR_GP_PIN(1, 22), 24, 3 }, /* AUDIO_CLKIN */ + { RCAR_GP_PIN(1, 21), 20, 3 }, /* AUDIO_CLKOUT */ + { RCAR_GP_PIN(1, 20), 16, 3 }, /* SSI_SD */ + { RCAR_GP_PIN(1, 19), 12, 3 }, /* SSI_WS */ + { RCAR_GP_PIN(1, 18), 8, 3 }, /* SSI_SCK */ + { RCAR_GP_PIN(1, 17), 4, 3 }, /* SCIF_CLK */ + { RCAR_GP_PIN(1, 16), 0, 3 }, /* HRX0 */ + } }, + { PINMUX_DRIVE_REG("DRV3CTRL1", 0xE605088C) { + { RCAR_GP_PIN(1, 28), 16, 3 }, /* HTX3 */ + { RCAR_GP_PIN(1, 27), 12, 3 }, /* HCTS3_N */ + { RCAR_GP_PIN(1, 26), 8, 3 }, /* HRTS3_N */ + { RCAR_GP_PIN(1, 25), 4, 3 }, /* HSCK3 */ + { RCAR_GP_PIN(1, 24), 0, 3 }, /* HRX3 */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL2", 0xE6058080) { + { RCAR_GP_PIN(2, 7), 28, 3 }, /* TPU0TO1 */ + { RCAR_GP_PIN(2, 6), 24, 3 }, /* FXR_TXDB */ + { RCAR_GP_PIN(2, 5), 20, 3 }, /* FXR_TXENB_N */ + { RCAR_GP_PIN(2, 4), 16, 3 }, /* RXDB_EXTFXR */ + { RCAR_GP_PIN(2, 3), 12, 3 }, /* CLK_EXTFXR */ + { RCAR_GP_PIN(2, 2), 8, 3 }, /* RXDA_EXTFXR */ + { RCAR_GP_PIN(2, 1), 4, 3 }, /* FXR_TXENA_N */ + { RCAR_GP_PIN(2, 0), 0, 3 }, /* FXR_TXDA */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL2", 0xE6058084) { + { RCAR_GP_PIN(2, 15), 28, 3 }, /* CANFD3_RX */ + { RCAR_GP_PIN(2, 14), 24, 3 }, /* CANFD3_TX */ + { RCAR_GP_PIN(2, 13), 20, 3 }, /* CANFD2_RX */ + { RCAR_GP_PIN(2, 12), 16, 3 }, /* CANFD2_TX */ + { RCAR_GP_PIN(2, 11), 12, 3 }, /* CANFD0_RX */ + { RCAR_GP_PIN(2, 10), 8, 3 }, /* CANFD0_TX */ + { RCAR_GP_PIN(2, 9), 4, 3 }, /* CAN_CLK */ + { RCAR_GP_PIN(2, 8), 0, 3 }, /* TPU0TO0 */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL2", 0xE6058088) { + { RCAR_GP_PIN(2, 19), 12, 3 }, /* CANFD7_RX */ + { RCAR_GP_PIN(2, 18), 8, 3 }, /* CANFD7_TX */ + { RCAR_GP_PIN(2, 17), 4, 3 }, /* CANFD4_RX */ + { RCAR_GP_PIN(2, 16), 0, 3 }, /* CANFD4_TX */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL3", 0xE6058880) { + { RCAR_GP_PIN(3, 7), 28, 3 }, /* MMC_D4 */ + { RCAR_GP_PIN(3, 6), 24, 3 }, /* MMC_D5 */ + { RCAR_GP_PIN(3, 5), 20, 3 }, /* MMC_SD_D3 */ + { RCAR_GP_PIN(3, 4), 16, 3 }, /* MMC_DS */ + { RCAR_GP_PIN(3, 3), 12, 3 }, /* MMC_SD_CLK */ + { RCAR_GP_PIN(3, 2), 8, 3 }, /* MMC_SD_D2 */ + { RCAR_GP_PIN(3, 1), 4, 3 }, /* MMC_SD_D0 */ + { RCAR_GP_PIN(3, 0), 0, 3 }, /* MMC_SD_D1 */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL3", 0xE6058884) { + { RCAR_GP_PIN(3, 15), 28, 2 }, /* QSPI0_SSL */ + { RCAR_GP_PIN(3, 14), 24, 2 }, /* IPC_CLKOUT */ + { RCAR_GP_PIN(3, 13), 20, 2 }, /* IPC_CLKIN */ + { RCAR_GP_PIN(3, 12), 16, 3 }, /* SD_WP */ + { RCAR_GP_PIN(3, 11), 12, 3 }, /* SD_CD */ + { RCAR_GP_PIN(3, 10), 8, 3 }, /* MMC_SD_CMD */ + { RCAR_GP_PIN(3, 9), 4, 3 }, /* MMC_D6*/ + { RCAR_GP_PIN(3, 8), 0, 3 }, /* MMC_D7 */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL3", 0xE6058888) { + { RCAR_GP_PIN(3, 23), 28, 2 }, /* QSPI1_MISO_IO1 */ + { RCAR_GP_PIN(3, 22), 24, 2 }, /* QSPI1_SPCLK */ + { RCAR_GP_PIN(3, 21), 20, 2 }, /* QSPI1_MOSI_IO0 */ + { RCAR_GP_PIN(3, 20), 16, 2 }, /* QSPI0_SPCLK */ + { RCAR_GP_PIN(3, 19), 12, 2 }, /* QSPI0_MOSI_IO0 */ + { RCAR_GP_PIN(3, 18), 8, 2 }, /* QSPI0_MISO_IO1 */ + { RCAR_GP_PIN(3, 17), 4, 2 }, /* QSPI0_IO2 */ + { RCAR_GP_PIN(3, 16), 0, 2 }, /* QSPI0_IO3 */ + } }, + { PINMUX_DRIVE_REG("DRV3CTRL3", 0xE605888C) { + { RCAR_GP_PIN(3, 29), 20, 2 }, /* RPC_INT_N */ + { RCAR_GP_PIN(3, 28), 16, 2 }, /* RPC_WP_N */ + { RCAR_GP_PIN(3, 27), 12, 2 }, /* RPC_RESET_N */ + { RCAR_GP_PIN(3, 26), 8, 2 }, /* QSPI1_IO3 */ + { RCAR_GP_PIN(3, 25), 4, 2 }, /* QSPI1_SSL */ + { RCAR_GP_PIN(3, 24), 0, 2 }, /* QSPI1_IO2 */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL4", 0xE6060080) { + { RCAR_GP_PIN(4, 7), 28, 3 }, /* TSN0_RX_CTL */ + { RCAR_GP_PIN(4, 6), 24, 3 }, /* TSN0_AVTP_CAPTURE */ + { RCAR_GP_PIN(4, 5), 20, 3 }, /* TSN0_AVTP_MATCH */ + { RCAR_GP_PIN(4, 4), 16, 3 }, /* TSN0_LINK */ + { RCAR_GP_PIN(4, 3), 12, 3 }, /* TSN0_PHY_INT */ + { RCAR_GP_PIN(4, 2), 8, 3 }, /* TSN0_AVTP_PPS1 */ + { RCAR_GP_PIN(4, 1), 4, 3 }, /* TSN0_MDC */ + { RCAR_GP_PIN(4, 0), 0, 3 }, /* TSN0_MDIO */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL4", 0xE6060084) { + { RCAR_GP_PIN(4, 15), 28, 3 }, /* TSN0_TD0 */ + { RCAR_GP_PIN(4, 14), 24, 3 }, /* TSN0_TD1 */ + { RCAR_GP_PIN(4, 13), 20, 3 }, /* TSN0_RD1 */ + { RCAR_GP_PIN(4, 12), 16, 3 }, /* TSN0_TXC */ + { RCAR_GP_PIN(4, 11), 12, 3 }, /* TSN0_RXC */ + { RCAR_GP_PIN(4, 10), 8, 3 }, /* TSN0_RD0 */ + { RCAR_GP_PIN(4, 9), 4, 3 }, /* TSN0_TX_CTL */ + { RCAR_GP_PIN(4, 8), 0, 3 }, /* TSN0_AVTP_PPS0 */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL4", 0xE6060088) { + { RCAR_GP_PIN(4, 23), 28, 3 }, /* AVS0 */ + { RCAR_GP_PIN(4, 22), 24, 3 }, /* PCIE1_CLKREQ_N */ + { RCAR_GP_PIN(4, 21), 20, 3 }, /* PCIE0_CLKREQ_N */ + { RCAR_GP_PIN(4, 20), 16, 3 }, /* TSN0_TXCREFCLK */ + { RCAR_GP_PIN(4, 19), 12, 3 }, /* TSN0_TD2 */ + { RCAR_GP_PIN(4, 18), 8, 3 }, /* TSN0_TD3 */ + { RCAR_GP_PIN(4, 17), 4, 3 }, /* TSN0_RD2 */ + { RCAR_GP_PIN(4, 16), 0, 3 }, /* TSN0_RD3 */ + } }, + { PINMUX_DRIVE_REG("DRV3CTRL4", 0xE606008C) { + { RCAR_GP_PIN(4, 24), 0, 3 }, /* AVS1 */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL5", 0xE6060880) { + { RCAR_GP_PIN(5, 7), 28, 3 }, /* AVB2_TXCREFCLK */ + { RCAR_GP_PIN(5, 6), 24, 3 }, /* AVB2_MDC */ + { RCAR_GP_PIN(5, 5), 20, 3 }, /* AVB2_MAGIC */ + { RCAR_GP_PIN(5, 4), 16, 3 }, /* AVB2_PHY_INT */ + { RCAR_GP_PIN(5, 3), 12, 3 }, /* AVB2_LINK */ + { RCAR_GP_PIN(5, 2), 8, 3 }, /* AVB2_AVTP_MATCH */ + { RCAR_GP_PIN(5, 1), 4, 3 }, /* AVB2_AVTP_CAPTURE */ + { RCAR_GP_PIN(5, 0), 0, 3 }, /* AVB2_AVTP_PPS */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL5", 0xE6060884) { + { RCAR_GP_PIN(5, 15), 28, 3 }, /* AVB2_TD0 */ + { RCAR_GP_PIN(5, 14), 24, 3 }, /* AVB2_RD1 */ + { RCAR_GP_PIN(5, 13), 20, 3 }, /* AVB2_RD2 */ + { RCAR_GP_PIN(5, 12), 16, 3 }, /* AVB2_TD1 */ + { RCAR_GP_PIN(5, 11), 12, 3 }, /* AVB2_TD2 */ + { RCAR_GP_PIN(5, 10), 8, 3 }, /* AVB2_MDIO */ + { RCAR_GP_PIN(5, 9), 4, 3 }, /* AVB2_RD3 */ + { RCAR_GP_PIN(5, 8), 0, 3 }, /* AVB2_TD3 */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL5", 0xE6060888) { + { RCAR_GP_PIN(5, 20), 16, 3 }, /* AVB2_RX_CTL */ + { RCAR_GP_PIN(5, 19), 12, 3 }, /* AVB2_TX_CTL */ + { RCAR_GP_PIN(5, 18), 8, 3 }, /* AVB2_RXC */ + { RCAR_GP_PIN(5, 17), 4, 3 }, /* AVB2_RD0 */ + { RCAR_GP_PIN(5, 16), 0, 3 }, /* AVB2_TXC */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL6", 0xE6061080) { + { RCAR_GP_PIN(6, 7), 28, 3 }, /* AVB1_TX_CTL */ + { RCAR_GP_PIN(6, 6), 24, 3 }, /* AVB1_TXC */ + { RCAR_GP_PIN(6, 5), 20, 3 }, /* AVB1_AVTP_MATCH */ + { RCAR_GP_PIN(6, 4), 16, 3 }, /* AVB1_LINK */ + { RCAR_GP_PIN(6, 3), 12, 3 }, /* AVB1_PHY_INT */ + { RCAR_GP_PIN(6, 2), 8, 3 }, /* AVB1_MDC */ + { RCAR_GP_PIN(6, 1), 4, 3 }, /* AVB1_MAGIC */ + { RCAR_GP_PIN(6, 0), 0, 3 }, /* AVB1_MDIO */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL6", 0xE6061084) { + { RCAR_GP_PIN(6, 15), 28, 3 }, /* AVB1_RD0 */ + { RCAR_GP_PIN(6, 14), 24, 3 }, /* AVB1_RD1 */ + { RCAR_GP_PIN(6, 13), 20, 3 }, /* AVB1_TD0 */ + { RCAR_GP_PIN(6, 12), 16, 3 }, /* AVB1_TD1 */ + { RCAR_GP_PIN(6, 11), 12, 3 }, /* AVB1_AVTP_CAPTURE */ + { RCAR_GP_PIN(6, 10), 8, 3 }, /* AVB1_AVTP_PPS */ + { RCAR_GP_PIN(6, 9), 4, 3 }, /* AVB1_RX_CTL */ + { RCAR_GP_PIN(6, 8), 0, 3 }, /* AVB1_RXC */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL6", 0xE6061088) { + { RCAR_GP_PIN(6, 20), 16, 3 }, /* AVB1_TXCREFCLK */ + { RCAR_GP_PIN(6, 19), 12, 3 }, /* AVB1_RD3 */ + { RCAR_GP_PIN(6, 18), 8, 3 }, /* AVB1_TD3 */ + { RCAR_GP_PIN(6, 17), 4, 3 }, /* AVB1_RD2 */ + { RCAR_GP_PIN(6, 16), 0, 3 }, /* AVB1_TD2 */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL7", 0xE6061880) { + { RCAR_GP_PIN(7, 7), 28, 3 }, /* AVB0_TD1 */ + { RCAR_GP_PIN(7, 6), 24, 3 }, /* AVB0_TD2 */ + { RCAR_GP_PIN(7, 5), 20, 3 }, /* AVB0_PHY_INT */ + { RCAR_GP_PIN(7, 4), 16, 3 }, /* AVB0_LINK */ + { RCAR_GP_PIN(7, 3), 12, 3 }, /* AVB0_TD3 */ + { RCAR_GP_PIN(7, 2), 8, 3 }, /* AVB0_AVTP_MATCH */ + { RCAR_GP_PIN(7, 1), 4, 3 }, /* AVB0_AVTP_CAPTURE */ + { RCAR_GP_PIN(7, 0), 0, 3 }, /* AVB0_AVTP_PPS */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL7", 0xE6061884) { + { RCAR_GP_PIN(7, 15), 28, 3 }, /* AVB0_TXC */ + { RCAR_GP_PIN(7, 14), 24, 3 }, /* AVB0_MDIO */ + { RCAR_GP_PIN(7, 13), 20, 3 }, /* AVB0_MDC */ + { RCAR_GP_PIN(7, 12), 16, 3 }, /* AVB0_RD2 */ + { RCAR_GP_PIN(7, 11), 12, 3 }, /* AVB0_TD0 */ + { RCAR_GP_PIN(7, 10), 8, 3 }, /* AVB0_MAGIC */ + { RCAR_GP_PIN(7, 9), 4, 3 }, /* AVB0_TXCREFCLK */ + { RCAR_GP_PIN(7, 8), 0, 3 }, /* AVB0_RD3 */ + } }, + { PINMUX_DRIVE_REG("DRV2CTRL7", 0xE6061888) { + { RCAR_GP_PIN(7, 20), 16, 3 }, /* AVB0_RX_CTL */ + { RCAR_GP_PIN(7, 19), 12, 3 }, /* AVB0_RXC */ + { RCAR_GP_PIN(7, 18), 8, 3 }, /* AVB0_RD0 */ + { RCAR_GP_PIN(7, 17), 4, 3 }, /* AVB0_RD1 */ + { RCAR_GP_PIN(7, 16), 0, 3 }, /* AVB0_TX_CTL */ + } }, + { PINMUX_DRIVE_REG("DRV0CTRL8", 0xE6068080) { + { RCAR_GP_PIN(8, 7), 28, 3 }, /* SDA3 */ + { RCAR_GP_PIN(8, 6), 24, 3 }, /* SCL3 */ + { RCAR_GP_PIN(8, 5), 20, 3 }, /* SDA2 */ + { RCAR_GP_PIN(8, 4), 16, 3 }, /* SCL2 */ + { RCAR_GP_PIN(8, 3), 12, 3 }, /* SDA1 */ + { RCAR_GP_PIN(8, 2), 8, 3 }, /* SCL1 */ + { RCAR_GP_PIN(8, 1), 4, 3 }, /* SDA0 */ + { RCAR_GP_PIN(8, 0), 0, 3 }, /* SCL0 */ + } }, + { PINMUX_DRIVE_REG("DRV1CTRL8", 0xE6068084) { + { RCAR_GP_PIN(8, 13), 20, 3 }, /* GP8_13 */ + { RCAR_GP_PIN(8, 12), 16, 3 }, /* GP8_12 */ + { RCAR_GP_PIN(8, 11), 12, 3 }, /* SDA5 */ + { RCAR_GP_PIN(8, 10), 8, 3 }, /* SCL5 */ + { RCAR_GP_PIN(8, 9), 4, 3 }, /* SDA4 */ + { RCAR_GP_PIN(8, 8), 0, 3 }, /* SCL4 */ + } }, + { }, +}; + +enum ioctrl_regs { + POC0, + POC1, + POC3, + POC4, + POC5, + POC6, + POC7, + POC8, +}; + +static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = { + [POC0] = { 0xE60500A0, }, + [POC1] = { 0xE60508A0, }, + [POC3] = { 0xE60588A0, }, + [POC4] = { 0xE60600A0, }, + [POC5] = { 0xE60608A0, }, + [POC6] = { 0xE60610A0, }, + [POC7] = { 0xE60618A0, }, + [POC8] = { 0xE60680A0, }, + { /* sentinel */ }, +}; + +static int r8a779g0_pin_to_pocctrl(unsigned int pin, u32 *pocctrl) +{ + int bit = pin & 0x1f; + + *pocctrl = pinmux_ioctrl_regs[POC0].reg; + if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 18)) + return bit; + + *pocctrl = pinmux_ioctrl_regs[POC1].reg; + if (pin >= RCAR_GP_PIN(1, 0) && pin <= RCAR_GP_PIN(1, 22)) + return bit; + + *pocctrl = pinmux_ioctrl_regs[POC3].reg; + if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 12)) + return bit; + + *pocctrl = pinmux_ioctrl_regs[POC8].reg; + if (pin >= RCAR_GP_PIN(8, 0) && pin <= RCAR_GP_PIN(8, 13)) + return bit; + + return -EINVAL; +} + +static const struct pinmux_bias_reg pinmux_bias_regs[] = { + { PINMUX_BIAS_REG("PUEN0", 0xE60500C0, "PUD0", 0xE60500E0) { + [ 0] = RCAR_GP_PIN(0, 0), /* GP0_00 */ + [ 1] = RCAR_GP_PIN(0, 1), /* GP0_01 */ + [ 2] = RCAR_GP_PIN(0, 2), /* GP0_02 */ + [ 3] = RCAR_GP_PIN(0, 3), /* IRQ3 */ + [ 4] = RCAR_GP_PIN(0, 4), /* IRQ2 */ + [ 5] = RCAR_GP_PIN(0, 5), /* IRQ1 */ + [ 6] = RCAR_GP_PIN(0, 6), /* IRQ0 */ + [ 7] = RCAR_GP_PIN(0, 7), /* MSIOF5_SS2 */ + [ 8] = RCAR_GP_PIN(0, 8), /* MSIOF5_SS1 */ + [ 9] = RCAR_GP_PIN(0, 9), /* MSIOF5_SYNC */ + [10] = RCAR_GP_PIN(0, 10), /* MSIOF5_TXD */ + [11] = RCAR_GP_PIN(0, 11), /* MSIOF5_SCK */ + [12] = RCAR_GP_PIN(0, 12), /* MSIOF5_RXD */ + [13] = RCAR_GP_PIN(0, 13), /* MSIOF2_SS2 */ + [14] = RCAR_GP_PIN(0, 14), /* MSIOF2_SS1 */ + [15] = RCAR_GP_PIN(0, 15), /* MSIOF2_SYNC */ + [16] = RCAR_GP_PIN(0, 16), /* MSIOF2_TXD */ + [17] = RCAR_GP_PIN(0, 17), /* MSIOF2_SCK */ + [18] = RCAR_GP_PIN(0, 18), /* MSIOF2_RXD */ + [19] = SH_PFC_PIN_NONE, + [20] = SH_PFC_PIN_NONE, + [21] = SH_PFC_PIN_NONE, + [22] = SH_PFC_PIN_NONE, + [23] = SH_PFC_PIN_NONE, + [24] = SH_PFC_PIN_NONE, + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN1", 0xE60508C0, "PUD1", 0xE60508E0) { + [ 0] = RCAR_GP_PIN(1, 0), /* MSIOF1_SS2 */ + [ 1] = RCAR_GP_PIN(1, 1), /* MSIOF1_SS1 */ + [ 2] = RCAR_GP_PIN(1, 2), /* MSIOF1_SYNC */ + [ 3] = RCAR_GP_PIN(1, 3), /* MSIOF1_SCK */ + [ 4] = RCAR_GP_PIN(1, 4), /* MSIOF1_TXD */ + [ 5] = RCAR_GP_PIN(1, 5), /* MSIOF1_RXD */ + [ 6] = RCAR_GP_PIN(1, 6), /* MSIOF0_SS2 */ + [ 7] = RCAR_GP_PIN(1, 7), /* MSIOF0_SS1 */ + [ 8] = RCAR_GP_PIN(1, 8), /* MSIOF0_SYNC */ + [ 9] = RCAR_GP_PIN(1, 9), /* MSIOF0_TXD */ + [10] = RCAR_GP_PIN(1, 10), /* MSIOF0_SCK */ + [11] = RCAR_GP_PIN(1, 11), /* MSIOF0_RXD */ + [12] = RCAR_GP_PIN(1, 12), /* HTX0 */ + [13] = RCAR_GP_PIN(1, 13), /* HCTS0_N */ + [14] = RCAR_GP_PIN(1, 14), /* HRTS0_N */ + [15] = RCAR_GP_PIN(1, 15), /* HSCK0 */ + [16] = RCAR_GP_PIN(1, 16), /* HRX0 */ + [17] = RCAR_GP_PIN(1, 17), /* SCIF_CLK */ + [18] = RCAR_GP_PIN(1, 18), /* SSI_SCK */ + [19] = RCAR_GP_PIN(1, 19), /* SSI_WS */ + [20] = RCAR_GP_PIN(1, 20), /* SSI_SD */ + [21] = RCAR_GP_PIN(1, 21), /* AUDIO_CLKOUT */ + [22] = RCAR_GP_PIN(1, 22), /* AUDIO_CLKIN */ + [23] = RCAR_GP_PIN(1, 23), /* GP1_23 */ + [24] = RCAR_GP_PIN(1, 24), /* HRX3 */ + [25] = RCAR_GP_PIN(1, 25), /* HSCK3 */ + [26] = RCAR_GP_PIN(1, 26), /* HRTS3_N */ + [27] = RCAR_GP_PIN(1, 27), /* HCTS3_N */ + [28] = RCAR_GP_PIN(1, 28), /* HTX3 */ + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN2", 0xE60580C0, "PUD2", 0xE60580E0) { + [ 0] = RCAR_GP_PIN(2, 0), /* FXR_TXDA */ + [ 1] = RCAR_GP_PIN(2, 1), /* FXR_TXENA_N */ + [ 2] = RCAR_GP_PIN(2, 2), /* RXDA_EXTFXR */ + [ 3] = RCAR_GP_PIN(2, 3), /* CLK_EXTFXR */ + [ 4] = RCAR_GP_PIN(2, 4), /* RXDB_EXTFXR */ + [ 5] = RCAR_GP_PIN(2, 5), /* FXR_TXENB_N */ + [ 6] = RCAR_GP_PIN(2, 6), /* FXR_TXDB */ + [ 7] = RCAR_GP_PIN(2, 7), /* TPU0TO1 */ + [ 8] = RCAR_GP_PIN(2, 8), /* TPU0TO0 */ + [ 9] = RCAR_GP_PIN(2, 9), /* CAN_CLK */ + [10] = RCAR_GP_PIN(2, 10), /* CANFD0_TX */ + [11] = RCAR_GP_PIN(2, 11), /* CANFD0_RX */ + [12] = RCAR_GP_PIN(2, 12), /* CANFD2_TX */ + [13] = RCAR_GP_PIN(2, 13), /* CANFD2_RX */ + [14] = RCAR_GP_PIN(2, 14), /* CANFD3_TX */ + [15] = RCAR_GP_PIN(2, 15), /* CANFD3_RX */ + [16] = RCAR_GP_PIN(2, 16), /* CANFD4_TX */ + [17] = RCAR_GP_PIN(2, 17), /* CANFD4_RX */ + [18] = RCAR_GP_PIN(2, 18), /* CANFD7_TX */ + [19] = RCAR_GP_PIN(2, 19), /* CANFD7_RX */ + [20] = SH_PFC_PIN_NONE, + [21] = SH_PFC_PIN_NONE, + [22] = SH_PFC_PIN_NONE, + [23] = SH_PFC_PIN_NONE, + [24] = SH_PFC_PIN_NONE, + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN3", 0xE60588C0, "PUD3", 0xE60588E0) { + [ 0] = RCAR_GP_PIN(3, 0), /* MMC_SD_D1 */ + [ 1] = RCAR_GP_PIN(3, 1), /* MMC_SD_D0 */ + [ 2] = RCAR_GP_PIN(3, 2), /* MMC_SD_D2 */ + [ 3] = RCAR_GP_PIN(3, 3), /* MMC_SD_CLK */ + [ 4] = RCAR_GP_PIN(3, 4), /* MMC_DS */ + [ 5] = RCAR_GP_PIN(3, 5), /* MMC_SD_D3 */ + [ 6] = RCAR_GP_PIN(3, 6), /* MMC_D5 */ + [ 7] = RCAR_GP_PIN(3, 7), /* MMC_D4 */ + [ 8] = RCAR_GP_PIN(3, 8), /* MMC_D7 */ + [ 9] = RCAR_GP_PIN(3, 9), /* MMC_D6 */ + [10] = RCAR_GP_PIN(3, 10), /* MMC_SD_CMD */ + [11] = RCAR_GP_PIN(3, 11), /* SD_CD */ + [12] = RCAR_GP_PIN(3, 12), /* SD_WP */ + [13] = RCAR_GP_PIN(3, 13), /* IPC_CLKIN */ + [14] = RCAR_GP_PIN(3, 14), /* IPC_CLKOUT */ + [15] = RCAR_GP_PIN(3, 15), /* QSPI0_SSL */ + [16] = RCAR_GP_PIN(3, 16), /* QSPI0_IO3 */ + [17] = RCAR_GP_PIN(3, 17), /* QSPI0_IO2 */ + [18] = RCAR_GP_PIN(3, 18), /* QSPI0_MISO_IO1 */ + [19] = RCAR_GP_PIN(3, 19), /* QSPI0_MOSI_IO0 */ + [20] = RCAR_GP_PIN(3, 20), /* QSPI0_SPCLK */ + [21] = RCAR_GP_PIN(3, 21), /* QSPI1_MOSI_IO0 */ + [22] = RCAR_GP_PIN(3, 22), /* QSPI1_SPCLK */ + [23] = RCAR_GP_PIN(3, 23), /* QSPI1_MISO_IO1 */ + [24] = RCAR_GP_PIN(3, 24), /* QSPI1_IO2 */ + [25] = RCAR_GP_PIN(3, 25), /* QSPI1_SSL */ + [26] = RCAR_GP_PIN(3, 26), /* QSPI1_IO3 */ + [27] = RCAR_GP_PIN(3, 27), /* RPC_RESET_N */ + [28] = RCAR_GP_PIN(3, 28), /* RPC_WP_N */ + [29] = RCAR_GP_PIN(3, 29), /* RPC_INT_N */ + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN4", 0xE60600C0, "PUD4", 0xE60600E0) { + [ 0] = RCAR_GP_PIN(4, 0), /* TSN0_MDIO */ + [ 1] = RCAR_GP_PIN(4, 1), /* TSN0_MDC */ + [ 2] = RCAR_GP_PIN(4, 2), /* TSN0_AVTP_PPS1 */ + [ 3] = RCAR_GP_PIN(4, 3), /* TSN0_PHY_INT */ + [ 4] = RCAR_GP_PIN(4, 4), /* TSN0_LINK */ + [ 5] = RCAR_GP_PIN(4, 5), /* TSN0_AVTP_MATCH */ + [ 6] = RCAR_GP_PIN(4, 6), /* TSN0_AVTP_CAPTURE */ + [ 7] = RCAR_GP_PIN(4, 7), /* TSN0_RX_CTL */ + [ 8] = RCAR_GP_PIN(4, 8), /* TSN0_AVTP_PPS0 */ + [ 9] = RCAR_GP_PIN(4, 9), /* TSN0_TX_CTL */ + [10] = RCAR_GP_PIN(4, 10), /* TSN0_RD0 */ + [11] = RCAR_GP_PIN(4, 11), /* TSN0_RXC */ + [12] = RCAR_GP_PIN(4, 12), /* TSN0_TXC */ + [13] = RCAR_GP_PIN(4, 13), /* TSN0_RD1 */ + [14] = RCAR_GP_PIN(4, 14), /* TSN0_TD1 */ + [15] = RCAR_GP_PIN(4, 15), /* TSN0_TD0 */ + [16] = RCAR_GP_PIN(4, 16), /* TSN0_RD3 */ + [17] = RCAR_GP_PIN(4, 17), /* TSN0_RD2 */ + [18] = RCAR_GP_PIN(4, 18), /* TSN0_TD3 */ + [19] = RCAR_GP_PIN(4, 19), /* TSN0_TD2 */ + [20] = RCAR_GP_PIN(4, 20), /* TSN0_TXCREFCLK */ + [21] = RCAR_GP_PIN(4, 21), /* PCIE0_CLKREQ_N */ + [22] = RCAR_GP_PIN(4, 22), /* PCIE1_CLKREQ_N */ + [23] = RCAR_GP_PIN(4, 23), /* AVS0 */ + [24] = RCAR_GP_PIN(4, 24), /* AVS1 */ + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN5", 0xE60608C0, "PUD5", 0xE60608E0) { + [ 0] = RCAR_GP_PIN(5, 0), /* AVB2_AVTP_PPS */ + [ 1] = RCAR_GP_PIN(5, 1), /* AVB0_AVTP_CAPTURE */ + [ 2] = RCAR_GP_PIN(5, 2), /* AVB2_AVTP_MATCH */ + [ 3] = RCAR_GP_PIN(5, 3), /* AVB2_LINK */ + [ 4] = RCAR_GP_PIN(5, 4), /* AVB2_PHY_INT */ + [ 5] = RCAR_GP_PIN(5, 5), /* AVB2_MAGIC */ + [ 6] = RCAR_GP_PIN(5, 6), /* AVB2_MDC */ + [ 7] = RCAR_GP_PIN(5, 7), /* AVB2_TXCREFCLK */ + [ 8] = RCAR_GP_PIN(5, 8), /* AVB2_TD3 */ + [ 9] = RCAR_GP_PIN(5, 9), /* AVB2_RD3 */ + [10] = RCAR_GP_PIN(5, 10), /* AVB2_MDIO */ + [11] = RCAR_GP_PIN(5, 11), /* AVB2_TD2 */ + [12] = RCAR_GP_PIN(5, 12), /* AVB2_TD1 */ + [13] = RCAR_GP_PIN(5, 13), /* AVB2_RD2 */ + [14] = RCAR_GP_PIN(5, 14), /* AVB2_RD1 */ + [15] = RCAR_GP_PIN(5, 15), /* AVB2_TD0 */ + [16] = RCAR_GP_PIN(5, 16), /* AVB2_TXC */ + [17] = RCAR_GP_PIN(5, 17), /* AVB2_RD0 */ + [18] = RCAR_GP_PIN(5, 18), /* AVB2_RXC */ + [19] = RCAR_GP_PIN(5, 19), /* AVB2_TX_CTL */ + [20] = RCAR_GP_PIN(5, 20), /* AVB2_RX_CTL */ + [21] = SH_PFC_PIN_NONE, + [22] = SH_PFC_PIN_NONE, + [23] = SH_PFC_PIN_NONE, + [24] = SH_PFC_PIN_NONE, + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN6", 0xE60610C0, "PUD6", 0xE60610E0) { + [ 0] = RCAR_GP_PIN(6, 0), /* AVB1_MDIO */ + [ 1] = RCAR_GP_PIN(6, 1), /* AVB1_MAGIC */ + [ 2] = RCAR_GP_PIN(6, 2), /* AVB1_MDC */ + [ 3] = RCAR_GP_PIN(6, 3), /* AVB1_PHY_INT */ + [ 4] = RCAR_GP_PIN(6, 4), /* AVB1_LINK */ + [ 5] = RCAR_GP_PIN(6, 5), /* AVB1_AVTP_MATCH */ + [ 6] = RCAR_GP_PIN(6, 6), /* AVB1_TXC */ + [ 7] = RCAR_GP_PIN(6, 7), /* AVB1_TX_CTL */ + [ 8] = RCAR_GP_PIN(6, 8), /* AVB1_RXC */ + [ 9] = RCAR_GP_PIN(6, 9), /* AVB1_RX_CTL */ + [10] = RCAR_GP_PIN(6, 10), /* AVB1_AVTP_PPS */ + [11] = RCAR_GP_PIN(6, 11), /* AVB1_AVTP_CAPTURE */ + [12] = RCAR_GP_PIN(6, 12), /* AVB1_TD1 */ + [13] = RCAR_GP_PIN(6, 13), /* AVB1_TD0 */ + [14] = RCAR_GP_PIN(6, 14), /* AVB1_RD1*/ + [15] = RCAR_GP_PIN(6, 15), /* AVB1_RD0 */ + [16] = RCAR_GP_PIN(6, 16), /* AVB1_TD2 */ + [17] = RCAR_GP_PIN(6, 17), /* AVB1_RD2 */ + [18] = RCAR_GP_PIN(6, 18), /* AVB1_TD3 */ + [19] = RCAR_GP_PIN(6, 19), /* AVB1_RD3 */ + [20] = RCAR_GP_PIN(6, 20), /* AVB1_TXCREFCLK */ + [21] = SH_PFC_PIN_NONE, + [22] = SH_PFC_PIN_NONE, + [23] = SH_PFC_PIN_NONE, + [24] = SH_PFC_PIN_NONE, + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN7", 0xE60618C0, "PUD7", 0xE60618E0) { + [ 0] = RCAR_GP_PIN(7, 0), /* AVB0_AVTP_PPS */ + [ 1] = RCAR_GP_PIN(7, 1), /* AVB0_AVTP_CAPTURE */ + [ 2] = RCAR_GP_PIN(7, 2), /* AVB0_AVTP_MATCH */ + [ 3] = RCAR_GP_PIN(7, 3), /* AVB0_TD3 */ + [ 4] = RCAR_GP_PIN(7, 4), /* AVB0_LINK */ + [ 5] = RCAR_GP_PIN(7, 5), /* AVB0_PHY_INT */ + [ 6] = RCAR_GP_PIN(7, 6), /* AVB0_TD2 */ + [ 7] = RCAR_GP_PIN(7, 7), /* AVB0_TD1 */ + [ 8] = RCAR_GP_PIN(7, 8), /* AVB0_RD3 */ + [ 9] = RCAR_GP_PIN(7, 9), /* AVB0_TXCREFCLK */ + [10] = RCAR_GP_PIN(7, 10), /* AVB0_MAGIC */ + [11] = RCAR_GP_PIN(7, 11), /* AVB0_TD0 */ + [12] = RCAR_GP_PIN(7, 12), /* AVB0_RD2 */ + [13] = RCAR_GP_PIN(7, 13), /* AVB0_MDC */ + [14] = RCAR_GP_PIN(7, 14), /* AVB0_MDIO */ + [15] = RCAR_GP_PIN(7, 15), /* AVB0_TXC */ + [16] = RCAR_GP_PIN(7, 16), /* AVB0_TX_CTL */ + [17] = RCAR_GP_PIN(7, 17), /* AVB0_RD1 */ + [18] = RCAR_GP_PIN(7, 18), /* AVB0_RD0 */ + [19] = RCAR_GP_PIN(7, 19), /* AVB0_RXC */ + [20] = RCAR_GP_PIN(7, 20), /* AVB0_RX_CTL */ + [21] = SH_PFC_PIN_NONE, + [22] = SH_PFC_PIN_NONE, + [23] = SH_PFC_PIN_NONE, + [24] = SH_PFC_PIN_NONE, + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { PINMUX_BIAS_REG("PUEN8", 0xE60680C0, "PUD8", 0xE60680E0) { + [ 0] = RCAR_GP_PIN(8, 0), /* SCL0 */ + [ 1] = RCAR_GP_PIN(8, 1), /* SDA0 */ + [ 2] = RCAR_GP_PIN(8, 2), /* SCL1 */ + [ 3] = RCAR_GP_PIN(8, 3), /* SDA1 */ + [ 4] = RCAR_GP_PIN(8, 4), /* SCL2 */ + [ 5] = RCAR_GP_PIN(8, 5), /* SDA2 */ + [ 6] = RCAR_GP_PIN(8, 6), /* SCL3 */ + [ 7] = RCAR_GP_PIN(8, 7), /* SDA3 */ + [ 8] = RCAR_GP_PIN(8, 8), /* SCL4 */ + [ 9] = RCAR_GP_PIN(8, 9), /* SDA4 */ + [10] = RCAR_GP_PIN(8, 10), /* SCL5 */ + [11] = RCAR_GP_PIN(8, 11), /* SDA5 */ + [12] = RCAR_GP_PIN(8, 12), /* GP8_12 */ + [13] = RCAR_GP_PIN(8, 13), /* GP8_13 */ + [14] = SH_PFC_PIN_NONE, + [15] = SH_PFC_PIN_NONE, + [16] = SH_PFC_PIN_NONE, + [17] = SH_PFC_PIN_NONE, + [18] = SH_PFC_PIN_NONE, + [19] = SH_PFC_PIN_NONE, + [20] = SH_PFC_PIN_NONE, + [21] = SH_PFC_PIN_NONE, + [22] = SH_PFC_PIN_NONE, + [23] = SH_PFC_PIN_NONE, + [24] = SH_PFC_PIN_NONE, + [25] = SH_PFC_PIN_NONE, + [26] = SH_PFC_PIN_NONE, + [27] = SH_PFC_PIN_NONE, + [28] = SH_PFC_PIN_NONE, + [29] = SH_PFC_PIN_NONE, + [30] = SH_PFC_PIN_NONE, + [31] = SH_PFC_PIN_NONE, + } }, + { /* sentinel */ }, +}; + +static const struct sh_pfc_soc_operations r8a779g0_pin_ops = { + .pin_to_pocctrl = r8a779g0_pin_to_pocctrl, + .get_bias = rcar_pinmux_get_bias, + .set_bias = rcar_pinmux_set_bias, +}; + +const struct sh_pfc_soc_info r8a779g0_pinmux_info = { + .name = "r8a779g0_pfc", + .ops = &r8a779g0_pin_ops, + .unlock_reg = 0x1ff, /* PMMRn mask */ + + .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, + + .pins = pinmux_pins, + .nr_pins = ARRAY_SIZE(pinmux_pins), + .groups = pinmux_groups, + .nr_groups = ARRAY_SIZE(pinmux_groups), + .functions = pinmux_functions, + .nr_functions = ARRAY_SIZE(pinmux_functions), + + .cfg_regs = pinmux_config_regs, + .drive_regs = pinmux_drive_regs, + .bias_regs = pinmux_bias_regs, + .ioctrl_regs = pinmux_ioctrl_regs, + + .pinmux_data = pinmux_data, + .pinmux_data_size = ARRAY_SIZE(pinmux_data), +}; diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index c47eed9d948f..a43824fd9505 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -527,6 +527,8 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, if (!(cfg & PIN_CFG_IEN)) return -EINVAL; arg = rzg2l_read_pin_config(pctrl, IEN(port_offset), bit, IEN_MASK); + if (!arg) + return -EINVAL; break; case PIN_CONFIG_POWER_SOURCE: { diff --git a/drivers/pinctrl/renesas/pinctrl-rzv2m.c b/drivers/pinctrl/renesas/pinctrl-rzv2m.c new file mode 100644 index 000000000000..e8c18198bebd --- /dev/null +++ b/drivers/pinctrl/renesas/pinctrl-rzv2m.c @@ -0,0 +1,1119 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/V2M Pin Control and GPIO driver core + * + * Based on: + * Renesas RZ/G2L Pin Control and GPIO driver core + * + * Copyright (C) 2022 Renesas Electronics Corporation. + */ + +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/gpio/driver.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> +#include <linux/spinlock.h> + +#include <dt-bindings/pinctrl/rzv2m-pinctrl.h> + +#include "../core.h" +#include "../pinconf.h" +#include "../pinmux.h" + +#define DRV_NAME "pinctrl-rzv2m" + +/* + * Use 16 lower bits [15:0] for pin identifier + * Use 16 higher bits [31:16] for pin mux function + */ +#define MUX_PIN_ID_MASK GENMASK(15, 0) +#define MUX_FUNC_MASK GENMASK(31, 16) +#define MUX_FUNC(pinconf) FIELD_GET(MUX_FUNC_MASK, (pinconf)) + +/* PIN capabilities */ +#define PIN_CFG_GRP_1_8V_2 1 +#define PIN_CFG_GRP_1_8V_3 2 +#define PIN_CFG_GRP_SWIO_1 3 +#define PIN_CFG_GRP_SWIO_2 4 +#define PIN_CFG_GRP_3_3V 5 +#define PIN_CFG_GRP_MASK GENMASK(2, 0) +#define PIN_CFG_BIAS BIT(3) +#define PIN_CFG_DRV BIT(4) +#define PIN_CFG_SLEW BIT(5) + +#define RZV2M_MPXED_PIN_FUNCS (PIN_CFG_BIAS | \ + PIN_CFG_DRV | \ + PIN_CFG_SLEW) + +/* + * n indicates number of pins in the port, a is the register index + * and f is pin configuration capabilities supported. + */ +#define RZV2M_GPIO_PORT_PACK(n, a, f) (((n) << 24) | ((a) << 16) | (f)) +#define RZV2M_GPIO_PORT_GET_PINCNT(x) FIELD_GET(GENMASK(31, 24), (x)) +#define RZV2M_GPIO_PORT_GET_INDEX(x) FIELD_GET(GENMASK(23, 16), (x)) +#define RZV2M_GPIO_PORT_GET_CFGS(x) FIELD_GET(GENMASK(15, 0), (x)) + +#define RZV2M_DEDICATED_PORT_IDX 22 + +/* + * BIT(31) indicates dedicated pin, b is the register bits (b * 16) + * and f is the pin configuration capabilities supported. + */ +#define RZV2M_SINGLE_PIN BIT(31) +#define RZV2M_SINGLE_PIN_PACK(b, f) (RZV2M_SINGLE_PIN | \ + ((RZV2M_DEDICATED_PORT_IDX) << 24) | \ + ((b) << 16) | (f)) +#define RZV2M_SINGLE_PIN_GET_PORT(x) FIELD_GET(GENMASK(30, 24), (x)) +#define RZV2M_SINGLE_PIN_GET_BIT(x) FIELD_GET(GENMASK(23, 16), (x)) +#define RZV2M_SINGLE_PIN_GET_CFGS(x) FIELD_GET(GENMASK(15, 0), (x)) + +#define RZV2M_PIN_ID_TO_PORT(id) ((id) / RZV2M_PINS_PER_PORT) +#define RZV2M_PIN_ID_TO_PIN(id) ((id) % RZV2M_PINS_PER_PORT) + +#define DO(n) (0x00 + (n) * 0x40) +#define OE(n) (0x04 + (n) * 0x40) +#define IE(n) (0x08 + (n) * 0x40) +#define PFSEL(n) (0x10 + (n) * 0x40) +#define DI(n) (0x20 + (n) * 0x40) +#define PUPD(n) (0x24 + (n) * 0x40) +#define DRV(n) ((n) < RZV2M_DEDICATED_PORT_IDX ? (0x28 + (n) * 0x40) \ + : 0x590) +#define SR(n) ((n) < RZV2M_DEDICATED_PORT_IDX ? (0x2c + (n) * 0x40) \ + : 0x594) +#define DI_MSK(n) (0x30 + (n) * 0x40) +#define EN_MSK(n) (0x34 + (n) * 0x40) + +#define PFC_MASK 0x07 +#define PUPD_MASK 0x03 +#define DRV_MASK 0x03 + +struct rzv2m_dedicated_configs { + const char *name; + u32 config; +}; + +struct rzv2m_pinctrl_data { + const char * const *port_pins; + const u32 *port_pin_configs; + const struct rzv2m_dedicated_configs *dedicated_pins; + unsigned int n_port_pins; + unsigned int n_dedicated_pins; +}; + +struct rzv2m_pinctrl { + struct pinctrl_dev *pctl; + struct pinctrl_desc desc; + struct pinctrl_pin_desc *pins; + + const struct rzv2m_pinctrl_data *data; + void __iomem *base; + struct device *dev; + struct clk *clk; + + struct gpio_chip gpio_chip; + struct pinctrl_gpio_range gpio_range; + + spinlock_t lock; +}; + +static const unsigned int drv_1_8V_group2_uA[] = { 1800, 3800, 7800, 11000 }; +static const unsigned int drv_1_8V_group3_uA[] = { 1600, 3200, 6400, 9600 }; +static const unsigned int drv_SWIO_group2_3_3V_uA[] = { 9000, 11000, 13000, 18000 }; +static const unsigned int drv_3_3V_group_uA[] = { 2000, 4000, 8000, 12000 }; + +/* Helper for registers that have a write enable bit in the upper word */ +static void rzv2m_writel_we(void __iomem *addr, u8 shift, u8 value) +{ + writel((BIT(16) | value) << shift, addr); +} + +static void rzv2m_pinctrl_set_pfc_mode(struct rzv2m_pinctrl *pctrl, + u8 port, u8 pin, u8 func) +{ + void __iomem *addr; + + /* Mask input/output */ + rzv2m_writel_we(pctrl->base + DI_MSK(port), pin, 1); + rzv2m_writel_we(pctrl->base + EN_MSK(port), pin, 1); + + /* Select the function and set the write enable bits */ + addr = pctrl->base + PFSEL(port) + (pin / 4) * 4; + writel(((PFC_MASK << 16) | func) << ((pin % 4) * 4), addr); + + /* Unmask input/output */ + rzv2m_writel_we(pctrl->base + EN_MSK(port), pin, 0); + rzv2m_writel_we(pctrl->base + DI_MSK(port), pin, 0); +}; + +static int rzv2m_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned int func_selector, + unsigned int group_selector) +{ + struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct function_desc *func; + unsigned int i, *psel_val; + struct group_desc *group; + int *pins; + + func = pinmux_generic_get_function(pctldev, func_selector); + if (!func) + return -EINVAL; + group = pinctrl_generic_get_group(pctldev, group_selector); + if (!group) + return -EINVAL; + + psel_val = func->data; + pins = group->pins; + + for (i = 0; i < group->num_pins; i++) { + dev_dbg(pctrl->dev, "port:%u pin: %u PSEL:%u\n", + RZV2M_PIN_ID_TO_PORT(pins[i]), RZV2M_PIN_ID_TO_PIN(pins[i]), + psel_val[i]); + rzv2m_pinctrl_set_pfc_mode(pctrl, RZV2M_PIN_ID_TO_PORT(pins[i]), + RZV2M_PIN_ID_TO_PIN(pins[i]), psel_val[i]); + } + + return 0; +}; + +static int rzv2m_map_add_config(struct pinctrl_map *map, + const char *group_or_pin, + enum pinctrl_map_type type, + unsigned long *configs, + unsigned int num_configs) +{ + unsigned long *cfgs; + + cfgs = kmemdup(configs, num_configs * sizeof(*cfgs), + GFP_KERNEL); + if (!cfgs) + return -ENOMEM; + + map->type = type; + map->data.configs.group_or_pin = group_or_pin; + map->data.configs.configs = cfgs; + map->data.configs.num_configs = num_configs; + + return 0; +} + +static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned int *num_maps, + unsigned int *index) +{ + struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct pinctrl_map *maps = *map; + unsigned int nmaps = *num_maps; + unsigned long *configs = NULL; + unsigned int *pins, *psel_val; + unsigned int num_pinmux = 0; + unsigned int idx = *index; + unsigned int num_pins, i; + unsigned int num_configs; + struct property *pinmux; + struct property *prop; + int ret, gsel, fsel; + const char **pin_fn; + const char *pin; + + pinmux = of_find_property(np, "pinmux", NULL); + if (pinmux) + num_pinmux = pinmux->length / sizeof(u32); + + ret = of_property_count_strings(np, "pins"); + if (ret == -EINVAL) { + num_pins = 0; + } else if (ret < 0) { + dev_err(pctrl->dev, "Invalid pins list in DT\n"); + return ret; + } else { + num_pins = ret; + } + + if (!num_pinmux && !num_pins) + return 0; + + if (num_pinmux && num_pins) { + dev_err(pctrl->dev, + "DT node must contain either a pinmux or pins and not both\n"); + return -EINVAL; + } + + ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs); + if (ret < 0) + return ret; + + if (num_pins && !num_configs) { + dev_err(pctrl->dev, "DT node must contain a config\n"); + ret = -ENODEV; + goto done; + } + + if (num_pinmux) + nmaps += 1; + + if (num_pins) + nmaps += num_pins; + + maps = krealloc_array(maps, nmaps, sizeof(*maps), GFP_KERNEL); + if (!maps) { + ret = -ENOMEM; + goto done; + } + + *map = maps; + *num_maps = nmaps; + if (num_pins) { + of_property_for_each_string(np, "pins", prop, pin) { + ret = rzv2m_map_add_config(&maps[idx], pin, + PIN_MAP_TYPE_CONFIGS_PIN, + configs, num_configs); + if (ret < 0) + goto done; + + idx++; + } + ret = 0; + goto done; + } + + pins = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*pins), GFP_KERNEL); + psel_val = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*psel_val), + GFP_KERNEL); + pin_fn = devm_kzalloc(pctrl->dev, sizeof(*pin_fn), GFP_KERNEL); + if (!pins || !psel_val || !pin_fn) { + ret = -ENOMEM; + goto done; + } + + /* Collect pin locations and mux settings from DT properties */ + for (i = 0; i < num_pinmux; ++i) { + u32 value; + + ret = of_property_read_u32_index(np, "pinmux", i, &value); + if (ret) + goto done; + pins[i] = value & MUX_PIN_ID_MASK; + psel_val[i] = MUX_FUNC(value); + } + + /* Register a single pin group listing all the pins we read from DT */ + gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL); + if (gsel < 0) { + ret = gsel; + goto done; + } + + /* + * Register a single group function where the 'data' is an array PSEL + * register values read from DT. + */ + pin_fn[0] = np->name; + fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1, + psel_val); + if (fsel < 0) { + ret = fsel; + goto remove_group; + } + + maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; + maps[idx].data.mux.group = np->name; + maps[idx].data.mux.function = np->name; + idx++; + + dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux); + ret = 0; + goto done; + +remove_group: + pinctrl_generic_remove_group(pctldev, gsel); +done: + *index = idx; + kfree(configs); + return ret; +} + +static void rzv2m_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, + unsigned int num_maps) +{ + unsigned int i; + + if (!map) + return; + + for (i = 0; i < num_maps; ++i) { + if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP || + map[i].type == PIN_MAP_TYPE_CONFIGS_PIN) + kfree(map[i].data.configs.configs); + } + kfree(map); +} + +static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned int *num_maps) +{ + struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct device_node *child; + unsigned int index; + int ret; + + *map = NULL; + *num_maps = 0; + index = 0; + + for_each_child_of_node(np, child) { + ret = rzv2m_dt_subnode_to_map(pctldev, child, map, + num_maps, &index); + if (ret < 0) { + of_node_put(child); + goto done; + } + } + + if (*num_maps == 0) { + ret = rzv2m_dt_subnode_to_map(pctldev, np, map, + num_maps, &index); + if (ret < 0) + goto done; + } + + if (*num_maps) + return 0; + + dev_err(pctrl->dev, "no mapping found in node %pOF\n", np); + ret = -EINVAL; + +done: + if (ret < 0) + rzv2m_dt_free_map(pctldev, *map, *num_maps); + + return ret; +} + +static int rzv2m_validate_gpio_pin(struct rzv2m_pinctrl *pctrl, + u32 cfg, u32 port, u8 bit) +{ + u8 pincount = RZV2M_GPIO_PORT_GET_PINCNT(cfg); + u32 port_index = RZV2M_GPIO_PORT_GET_INDEX(cfg); + u32 data; + + if (bit >= pincount || port >= pctrl->data->n_port_pins) + return -EINVAL; + + data = pctrl->data->port_pin_configs[port]; + if (port_index != RZV2M_GPIO_PORT_GET_INDEX(data)) + return -EINVAL; + + return 0; +} + +static void rzv2m_rmw_pin_config(struct rzv2m_pinctrl *pctrl, u32 offset, + u8 shift, u32 mask, u32 val) +{ + void __iomem *addr = pctrl->base + offset; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&pctrl->lock, flags); + reg = readl(addr) & ~(mask << shift); + writel(reg | (val << shift), addr); + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static int rzv2m_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, + unsigned int _pin, + unsigned long *config) +{ + struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param = pinconf_to_config_param(*config); + const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin]; + unsigned int *pin_data = pin->drv_data; + unsigned int arg = 0; + u32 port; + u32 cfg; + u8 bit; + u32 val; + + if (!pin_data) + return -EINVAL; + + if (*pin_data & RZV2M_SINGLE_PIN) { + port = RZV2M_SINGLE_PIN_GET_PORT(*pin_data); + cfg = RZV2M_SINGLE_PIN_GET_CFGS(*pin_data); + bit = RZV2M_SINGLE_PIN_GET_BIT(*pin_data); + } else { + cfg = RZV2M_GPIO_PORT_GET_CFGS(*pin_data); + port = RZV2M_PIN_ID_TO_PORT(_pin); + bit = RZV2M_PIN_ID_TO_PIN(_pin); + + if (rzv2m_validate_gpio_pin(pctrl, *pin_data, RZV2M_PIN_ID_TO_PORT(_pin), bit)) + return -EINVAL; + } + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: { + enum pin_config_param bias; + + if (!(cfg & PIN_CFG_BIAS)) + return -EINVAL; + + /* PUPD uses 2-bits per pin */ + bit *= 2; + + switch ((readl(pctrl->base + PUPD(port)) >> bit) & PUPD_MASK) { + case 0: + bias = PIN_CONFIG_BIAS_PULL_DOWN; + break; + case 2: + bias = PIN_CONFIG_BIAS_PULL_UP; + break; + default: + bias = PIN_CONFIG_BIAS_DISABLE; + } + + if (bias != param) + return -EINVAL; + break; + } + + case PIN_CONFIG_DRIVE_STRENGTH_UA: + if (!(cfg & PIN_CFG_DRV)) + return -EINVAL; + + /* DRV uses 2-bits per pin */ + bit *= 2; + + val = (readl(pctrl->base + DRV(port)) >> bit) & DRV_MASK; + + switch (cfg & PIN_CFG_GRP_MASK) { + case PIN_CFG_GRP_1_8V_2: + arg = drv_1_8V_group2_uA[val]; + break; + case PIN_CFG_GRP_1_8V_3: + arg = drv_1_8V_group3_uA[val]; + break; + case PIN_CFG_GRP_SWIO_2: + arg = drv_SWIO_group2_3_3V_uA[val]; + break; + case PIN_CFG_GRP_SWIO_1: + case PIN_CFG_GRP_3_3V: + arg = drv_3_3V_group_uA[val]; + break; + default: + return -EINVAL; + } + + break; + + case PIN_CONFIG_SLEW_RATE: + if (!(cfg & PIN_CFG_SLEW)) + return -EINVAL; + + arg = readl(pctrl->base + SR(port)) & BIT(bit); + break; + + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +}; + +static int rzv2m_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int _pin, + unsigned long *_configs, + unsigned int num_configs) +{ + struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin]; + unsigned int *pin_data = pin->drv_data; + enum pin_config_param param; + u32 port; + unsigned int i; + u32 cfg; + u8 bit; + u32 val; + + if (!pin_data) + return -EINVAL; + + if (*pin_data & RZV2M_SINGLE_PIN) { + port = RZV2M_SINGLE_PIN_GET_PORT(*pin_data); + cfg = RZV2M_SINGLE_PIN_GET_CFGS(*pin_data); + bit = RZV2M_SINGLE_PIN_GET_BIT(*pin_data); + } else { + cfg = RZV2M_GPIO_PORT_GET_CFGS(*pin_data); + port = RZV2M_PIN_ID_TO_PORT(_pin); + bit = RZV2M_PIN_ID_TO_PIN(_pin); + + if (rzv2m_validate_gpio_pin(pctrl, *pin_data, RZV2M_PIN_ID_TO_PORT(_pin), bit)) + return -EINVAL; + } + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(_configs[i]); + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + if (!(cfg & PIN_CFG_BIAS)) + return -EINVAL; + + /* PUPD uses 2-bits per pin */ + bit *= 2; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_DOWN: + val = 0; + break; + case PIN_CONFIG_BIAS_PULL_UP: + val = 2; + break; + default: + val = 1; + } + + rzv2m_rmw_pin_config(pctrl, PUPD(port), bit, PUPD_MASK, val); + break; + + case PIN_CONFIG_DRIVE_STRENGTH_UA: { + unsigned int arg = pinconf_to_config_argument(_configs[i]); + const unsigned int *drv_strengths; + unsigned int index; + + if (!(cfg & PIN_CFG_DRV)) + return -EINVAL; + + switch (cfg & PIN_CFG_GRP_MASK) { + case PIN_CFG_GRP_1_8V_2: + drv_strengths = drv_1_8V_group2_uA; + break; + case PIN_CFG_GRP_1_8V_3: + drv_strengths = drv_1_8V_group3_uA; + break; + case PIN_CFG_GRP_SWIO_2: + drv_strengths = drv_SWIO_group2_3_3V_uA; + break; + case PIN_CFG_GRP_SWIO_1: + case PIN_CFG_GRP_3_3V: + drv_strengths = drv_3_3V_group_uA; + break; + default: + return -EINVAL; + } + + for (index = 0; index < 4; index++) { + if (arg == drv_strengths[index]) + break; + } + if (index >= 4) + return -EINVAL; + + /* DRV uses 2-bits per pin */ + bit *= 2; + + rzv2m_rmw_pin_config(pctrl, DRV(port), bit, DRV_MASK, index); + break; + } + + case PIN_CONFIG_SLEW_RATE: { + unsigned int arg = pinconf_to_config_argument(_configs[i]); + + if (!(cfg & PIN_CFG_SLEW)) + return -EINVAL; + + rzv2m_writel_we(pctrl->base + SR(port), bit, !arg); + break; + } + + default: + return -EOPNOTSUPP; + } + } + + return 0; +} + +static int rzv2m_pinctrl_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *configs, + unsigned int num_configs) +{ + const unsigned int *pins; + unsigned int i, npins; + int ret; + + ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + for (i = 0; i < npins; i++) { + ret = rzv2m_pinctrl_pinconf_set(pctldev, pins[i], configs, + num_configs); + if (ret) + return ret; + } + + return 0; +}; + +static int rzv2m_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *config) +{ + const unsigned int *pins; + unsigned int i, npins, prev_config = 0; + int ret; + + ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + for (i = 0; i < npins; i++) { + ret = rzv2m_pinctrl_pinconf_get(pctldev, pins[i], config); + if (ret) + return ret; + + /* Check config matches previous pins */ + if (i && prev_config != *config) + return -EOPNOTSUPP; + + prev_config = *config; + } + + return 0; +}; + +static const struct pinctrl_ops rzv2m_pinctrl_pctlops = { + .get_groups_count = pinctrl_generic_get_group_count, + .get_group_name = pinctrl_generic_get_group_name, + .get_group_pins = pinctrl_generic_get_group_pins, + .dt_node_to_map = rzv2m_dt_node_to_map, + .dt_free_map = rzv2m_dt_free_map, +}; + +static const struct pinmux_ops rzv2m_pinctrl_pmxops = { + .get_functions_count = pinmux_generic_get_function_count, + .get_function_name = pinmux_generic_get_function_name, + .get_function_groups = pinmux_generic_get_function_groups, + .set_mux = rzv2m_pinctrl_set_mux, + .strict = true, +}; + +static const struct pinconf_ops rzv2m_pinctrl_confops = { + .is_generic = true, + .pin_config_get = rzv2m_pinctrl_pinconf_get, + .pin_config_set = rzv2m_pinctrl_pinconf_set, + .pin_config_group_set = rzv2m_pinctrl_pinconf_group_set, + .pin_config_group_get = rzv2m_pinctrl_pinconf_group_get, + .pin_config_config_dbg_show = pinconf_generic_dump_config, +}; + +static int rzv2m_gpio_request(struct gpio_chip *chip, unsigned int offset) +{ + struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip); + u32 port = RZV2M_PIN_ID_TO_PORT(offset); + u8 bit = RZV2M_PIN_ID_TO_PIN(offset); + int ret; + + ret = pinctrl_gpio_request(chip->base + offset); + if (ret) + return ret; + + rzv2m_pinctrl_set_pfc_mode(pctrl, port, bit, 0); + + return 0; +} + +static void rzv2m_gpio_set_direction(struct rzv2m_pinctrl *pctrl, u32 port, + u8 bit, bool output) +{ + rzv2m_writel_we(pctrl->base + OE(port), bit, output); + rzv2m_writel_we(pctrl->base + IE(port), bit, !output); +} + +static int rzv2m_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip); + u32 port = RZV2M_PIN_ID_TO_PORT(offset); + u8 bit = RZV2M_PIN_ID_TO_PIN(offset); + + if (!(readl(pctrl->base + IE(port)) & BIT(bit))) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int rzv2m_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip); + u32 port = RZV2M_PIN_ID_TO_PORT(offset); + u8 bit = RZV2M_PIN_ID_TO_PIN(offset); + + rzv2m_gpio_set_direction(pctrl, port, bit, false); + + return 0; +} + +static void rzv2m_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip); + u32 port = RZV2M_PIN_ID_TO_PORT(offset); + u8 bit = RZV2M_PIN_ID_TO_PIN(offset); + + rzv2m_writel_we(pctrl->base + DO(port), bit, !!value); +} + +static int rzv2m_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip); + u32 port = RZV2M_PIN_ID_TO_PORT(offset); + u8 bit = RZV2M_PIN_ID_TO_PIN(offset); + + rzv2m_gpio_set(chip, offset, value); + rzv2m_gpio_set_direction(pctrl, port, bit, true); + + return 0; +} + +static int rzv2m_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip); + u32 port = RZV2M_PIN_ID_TO_PORT(offset); + u8 bit = RZV2M_PIN_ID_TO_PIN(offset); + int direction = rzv2m_gpio_get_direction(chip, offset); + + if (direction == GPIO_LINE_DIRECTION_IN) + return !!(readl(pctrl->base + DI(port)) & BIT(bit)); + else + return !!(readl(pctrl->base + DO(port)) & BIT(bit)); +} + +static void rzv2m_gpio_free(struct gpio_chip *chip, unsigned int offset) +{ + pinctrl_gpio_free(chip->base + offset); + + /* + * Set the GPIO as an input to ensure that the next GPIO request won't + * drive the GPIO pin as an output. + */ + rzv2m_gpio_direction_input(chip, offset); +} + +static const char * const rzv2m_gpio_names[] = { + "P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7", + "P0_8", "P0_9", "P0_10", "P0_11", "P0_12", "P0_13", "P0_14", "P0_15", + "P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7", + "P1_8", "P1_9", "P1_10", "P1_11", "P1_12", "P1_13", "P1_14", "P1_15", + "P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7", + "P2_8", "P2_9", "P2_10", "P2_11", "P2_12", "P2_13", "P2_14", "P2_15", + "P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7", + "P3_8", "P3_9", "P3_10", "P3_11", "P3_12", "P3_13", "P3_14", "P3_15", + "P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7", + "P4_8", "P4_9", "P4_10", "P4_11", "P4_12", "P4_13", "P4_14", "P4_15", + "P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7", + "P5_8", "P5_9", "P5_10", "P5_11", "P5_12", "P5_13", "P5_14", "P5_15", + "P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7", + "P6_8", "P6_9", "P6_10", "P6_11", "P6_12", "P6_13", "P6_14", "P6_15", + "P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7", + "P7_8", "P7_9", "P7_10", "P7_11", "P7_12", "P7_13", "P7_14", "P7_15", + "P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7", + "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15", + "P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7", + "P9_8", "P9_9", "P9_10", "P9_11", "P9_12", "P9_13", "P9_14", "P9_15", + "P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7", + "P10_8", "P10_9", "P10_10", "P10_11", "P10_12", "P10_13", "P10_14", "P10_15", + "P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7", + "P11_8", "P11_9", "P11_10", "P11_11", "P11_12", "P11_13", "P11_14", "P11_15", + "P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7", + "P12_8", "P12_9", "P12_10", "P12_11", "P12_12", "P12_13", "P12_14", "P12_15", + "P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7", + "P13_8", "P13_9", "P13_10", "P13_11", "P13_12", "P13_13", "P13_14", "P13_15", + "P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7", + "P14_8", "P14_9", "P14_10", "P14_11", "P14_12", "P14_13", "P14_14", "P14_15", + "P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7", + "P15_8", "P15_9", "P15_10", "P15_11", "P15_12", "P15_13", "P15_14", "P15_15", + "P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7", + "P16_8", "P16_9", "P16_10", "P16_11", "P16_12", "P16_13", "P16_14", "P16_15", + "P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7", + "P17_8", "P17_9", "P17_10", "P17_11", "P17_12", "P17_13", "P17_14", "P17_15", + "P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7", + "P18_8", "P18_9", "P18_10", "P18_11", "P18_12", "P18_13", "P18_14", "P18_15", + "P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7", + "P19_8", "P19_9", "P19_10", "P19_11", "P19_12", "P19_13", "P19_14", "P19_15", + "P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7", + "P20_8", "P20_9", "P20_10", "P20_11", "P20_12", "P20_13", "P20_14", "P20_15", + "P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7", + "P21_8", "P21_9", "P21_10", "P21_11", "P21_12", "P21_13", "P21_14", "P21_15", +}; + +static const u32 rzv2m_gpio_configs[] = { + RZV2M_GPIO_PORT_PACK(14, 0, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(16, 1, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(8, 2, PIN_CFG_GRP_1_8V_3 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(16, 3, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(8, 4, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(4, 5, PIN_CFG_GRP_1_8V_3 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(12, 6, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(6, 7, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(8, 8, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(8, 9, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(9, 10, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(9, 11, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(4, 12, PIN_CFG_GRP_3_3V | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(12, 13, PIN_CFG_GRP_3_3V | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(8, 14, PIN_CFG_GRP_3_3V | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(16, 15, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(14, 16, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(1, 17, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS), + RZV2M_GPIO_PORT_PACK(0, 18, 0), + RZV2M_GPIO_PORT_PACK(0, 19, 0), + RZV2M_GPIO_PORT_PACK(3, 20, PIN_CFG_GRP_1_8V_2 | PIN_CFG_DRV), + RZV2M_GPIO_PORT_PACK(1, 21, PIN_CFG_GRP_SWIO_1 | PIN_CFG_DRV | PIN_CFG_SLEW), +}; + +static const struct rzv2m_dedicated_configs rzv2m_dedicated_pins[] = { + { "NAWPN", RZV2M_SINGLE_PIN_PACK(0, + (PIN_CFG_GRP_SWIO_2 | PIN_CFG_DRV | PIN_CFG_SLEW)) }, + { "IM0CLK", RZV2M_SINGLE_PIN_PACK(1, + (PIN_CFG_GRP_SWIO_1 | PIN_CFG_DRV | PIN_CFG_SLEW)) }, + { "IM1CLK", RZV2M_SINGLE_PIN_PACK(2, + (PIN_CFG_GRP_SWIO_1 | PIN_CFG_DRV | PIN_CFG_SLEW)) }, + { "DETDO", RZV2M_SINGLE_PIN_PACK(5, + (PIN_CFG_GRP_1_8V_3 | PIN_CFG_DRV | PIN_CFG_SLEW)) }, + { "DETMS", RZV2M_SINGLE_PIN_PACK(6, + (PIN_CFG_GRP_1_8V_3 | PIN_CFG_DRV | PIN_CFG_SLEW)) }, + { "PCRSTOUTB", RZV2M_SINGLE_PIN_PACK(12, + (PIN_CFG_GRP_3_3V | PIN_CFG_DRV | PIN_CFG_SLEW)) }, + { "USPWEN", RZV2M_SINGLE_PIN_PACK(14, + (PIN_CFG_GRP_3_3V | PIN_CFG_DRV | PIN_CFG_SLEW)) }, +}; + +static int rzv2m_gpio_register(struct rzv2m_pinctrl *pctrl) +{ + struct device_node *np = pctrl->dev->of_node; + struct gpio_chip *chip = &pctrl->gpio_chip; + const char *name = dev_name(pctrl->dev); + struct of_phandle_args of_args; + int ret; + + ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args); + if (ret) { + dev_err(pctrl->dev, "Unable to parse gpio-ranges\n"); + return ret; + } + + if (of_args.args[0] != 0 || of_args.args[1] != 0 || + of_args.args[2] != pctrl->data->n_port_pins) { + dev_err(pctrl->dev, "gpio-ranges does not match selected SOC\n"); + return -EINVAL; + } + + chip->names = pctrl->data->port_pins; + chip->request = rzv2m_gpio_request; + chip->free = rzv2m_gpio_free; + chip->get_direction = rzv2m_gpio_get_direction; + chip->direction_input = rzv2m_gpio_direction_input; + chip->direction_output = rzv2m_gpio_direction_output; + chip->get = rzv2m_gpio_get; + chip->set = rzv2m_gpio_set; + chip->label = name; + chip->parent = pctrl->dev; + chip->owner = THIS_MODULE; + chip->base = -1; + chip->ngpio = of_args.args[2]; + + pctrl->gpio_range.id = 0; + pctrl->gpio_range.pin_base = 0; + pctrl->gpio_range.base = 0; + pctrl->gpio_range.npins = chip->ngpio; + pctrl->gpio_range.name = chip->label; + pctrl->gpio_range.gc = chip; + ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); + if (ret) { + dev_err(pctrl->dev, "failed to add GPIO controller\n"); + return ret; + } + + dev_dbg(pctrl->dev, "Registered gpio controller\n"); + + return 0; +} + +static int rzv2m_pinctrl_register(struct rzv2m_pinctrl *pctrl) +{ + struct pinctrl_pin_desc *pins; + unsigned int i, j; + u32 *pin_data; + int ret; + + pctrl->desc.name = DRV_NAME; + pctrl->desc.npins = pctrl->data->n_port_pins + pctrl->data->n_dedicated_pins; + pctrl->desc.pctlops = &rzv2m_pinctrl_pctlops; + pctrl->desc.pmxops = &rzv2m_pinctrl_pmxops; + pctrl->desc.confops = &rzv2m_pinctrl_confops; + pctrl->desc.owner = THIS_MODULE; + + pins = devm_kcalloc(pctrl->dev, pctrl->desc.npins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + pin_data = devm_kcalloc(pctrl->dev, pctrl->desc.npins, + sizeof(*pin_data), GFP_KERNEL); + if (!pin_data) + return -ENOMEM; + + pctrl->pins = pins; + pctrl->desc.pins = pins; + + for (i = 0, j = 0; i < pctrl->data->n_port_pins; i++) { + pins[i].number = i; + pins[i].name = pctrl->data->port_pins[i]; + if (i && !(i % RZV2M_PINS_PER_PORT)) + j++; + pin_data[i] = pctrl->data->port_pin_configs[j]; + pins[i].drv_data = &pin_data[i]; + } + + for (i = 0; i < pctrl->data->n_dedicated_pins; i++) { + unsigned int index = pctrl->data->n_port_pins + i; + + pins[index].number = index; + pins[index].name = pctrl->data->dedicated_pins[i].name; + pin_data[index] = pctrl->data->dedicated_pins[i].config; + pins[index].drv_data = &pin_data[index]; + } + + ret = devm_pinctrl_register_and_init(pctrl->dev, &pctrl->desc, pctrl, + &pctrl->pctl); + if (ret) { + dev_err(pctrl->dev, "pinctrl registration failed\n"); + return ret; + } + + ret = pinctrl_enable(pctrl->pctl); + if (ret) { + dev_err(pctrl->dev, "pinctrl enable failed\n"); + return ret; + } + + ret = rzv2m_gpio_register(pctrl); + if (ret) { + dev_err(pctrl->dev, "failed to add GPIO chip: %i\n", ret); + return ret; + } + + return 0; +} + +static void rzv2m_pinctrl_clk_disable(void *data) +{ + clk_disable_unprepare(data); +} + +static int rzv2m_pinctrl_probe(struct platform_device *pdev) +{ + struct rzv2m_pinctrl *pctrl; + int ret; + + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + pctrl->dev = &pdev->dev; + + pctrl->data = of_device_get_match_data(&pdev->dev); + if (!pctrl->data) + return -EINVAL; + + pctrl->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pctrl->base)) + return PTR_ERR(pctrl->base); + + pctrl->clk = devm_clk_get(pctrl->dev, NULL); + if (IS_ERR(pctrl->clk)) { + ret = PTR_ERR(pctrl->clk); + dev_err(pctrl->dev, "failed to get GPIO clk : %i\n", ret); + return ret; + } + + spin_lock_init(&pctrl->lock); + + platform_set_drvdata(pdev, pctrl); + + ret = clk_prepare_enable(pctrl->clk); + if (ret) { + dev_err(pctrl->dev, "failed to enable GPIO clk: %i\n", ret); + return ret; + } + + ret = devm_add_action_or_reset(&pdev->dev, rzv2m_pinctrl_clk_disable, + pctrl->clk); + if (ret) { + dev_err(pctrl->dev, + "failed to register GPIO clk disable action, %i\n", + ret); + return ret; + } + + ret = rzv2m_pinctrl_register(pctrl); + if (ret) + return ret; + + dev_info(pctrl->dev, "%s support registered\n", DRV_NAME); + return 0; +} + +static struct rzv2m_pinctrl_data r9a09g011_data = { + .port_pins = rzv2m_gpio_names, + .port_pin_configs = rzv2m_gpio_configs, + .dedicated_pins = rzv2m_dedicated_pins, + .n_port_pins = ARRAY_SIZE(rzv2m_gpio_configs) * RZV2M_PINS_PER_PORT, + .n_dedicated_pins = ARRAY_SIZE(rzv2m_dedicated_pins), +}; + +static const struct of_device_id rzv2m_pinctrl_of_table[] = { + { + .compatible = "renesas,r9a09g011-pinctrl", + .data = &r9a09g011_data, + }, + { /* sentinel */ } +}; + +static struct platform_driver rzv2m_pinctrl_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(rzv2m_pinctrl_of_table), + }, + .probe = rzv2m_pinctrl_probe, +}; + +static int __init rzv2m_pinctrl_init(void) +{ + return platform_driver_register(&rzv2m_pinctrl_driver); +} +core_initcall(rzv2m_pinctrl_init); + +MODULE_AUTHOR("Phil Edworthy <[email protected]>"); +MODULE_DESCRIPTION("Pin and gpio controller driver for RZ/V2M"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h index 12bc279f5733..0fcb29ab0c84 100644 --- a/drivers/pinctrl/renesas/sh_pfc.h +++ b/drivers/pinctrl/renesas/sh_pfc.h @@ -325,6 +325,7 @@ extern const struct sh_pfc_soc_info r8a77990_pinmux_info; extern const struct sh_pfc_soc_info r8a77995_pinmux_info; extern const struct sh_pfc_soc_info r8a779a0_pinmux_info; extern const struct sh_pfc_soc_info r8a779f0_pinmux_info; +extern const struct sh_pfc_soc_info r8a779g0_pinmux_info; extern const struct sh_pfc_soc_info sh7203_pinmux_info; extern const struct sh_pfc_soc_info sh7264_pinmux_info; extern const struct sh_pfc_soc_info sh7269_pinmux_info; @@ -492,9 +493,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info; PORT_GP_CFG_1(bank, 11, fn, sfx, cfg) #define PORT_GP_12(bank, fn, sfx) PORT_GP_CFG_12(bank, fn, sfx, 0) -#define PORT_GP_CFG_14(bank, fn, sfx, cfg) \ +#define PORT_GP_CFG_13(bank, fn, sfx, cfg) \ PORT_GP_CFG_12(bank, fn, sfx, cfg), \ - PORT_GP_CFG_1(bank, 12, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 12, fn, sfx, cfg) +#define PORT_GP_13(bank, fn, sfx) PORT_GP_CFG_13(bank, fn, sfx, 0) + +#define PORT_GP_CFG_14(bank, fn, sfx, cfg) \ + PORT_GP_CFG_13(bank, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 13, fn, sfx, cfg) #define PORT_GP_14(bank, fn, sfx) PORT_GP_CFG_14(bank, fn, sfx, 0) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index 6d7ca1758292..a8212fc126bf 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -27,8 +27,6 @@ #include <linux/soc/samsung/exynos-pmu.h> #include <linux/soc/samsung/exynos-regs-pmu.h> -#include <dt-bindings/pinctrl/samsung.h> - #include "pinctrl-samsung.h" #include "pinctrl-exynos.h" @@ -173,7 +171,7 @@ static int exynos_irq_request_resources(struct irq_data *irqd) con = readl(bank->pctl_base + reg_con); con &= ~(mask << shift); - con |= EXYNOS_PIN_FUNC_EINT << shift; + con |= EXYNOS_PIN_CON_FUNC_EINT << shift; writel(con, bank->pctl_base + reg_con); raw_spin_unlock_irqrestore(&bank->slock, flags); @@ -196,7 +194,7 @@ static void exynos_irq_release_resources(struct irq_data *irqd) con = readl(bank->pctl_base + reg_con); con &= ~(mask << shift); - con |= EXYNOS_PIN_FUNC_INPUT << shift; + con |= PIN_CON_FUNC_INPUT << shift; writel(con, bank->pctl_base + reg_con); raw_spin_unlock_irqrestore(&bank->slock, flags); diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h index bfad1ced8017..7bd6d82c9f36 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.h +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h @@ -16,6 +16,9 @@ #ifndef __PINCTRL_SAMSUNG_EXYNOS_H #define __PINCTRL_SAMSUNG_EXYNOS_H +/* Values for the pin CON register */ +#define EXYNOS_PIN_CON_FUNC_EINT 0xf + /* External GPIO and wakeup interrupt related definitions */ #define EXYNOS_GPIO_ECON_OFFSET 0x700 #define EXYNOS_GPIO_EFLTCON_OFFSET 0x800 diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 26d309d2516d..4837bceb767b 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -26,8 +26,6 @@ #include <linux/of_device.h> #include <linux/spinlock.h> -#include <dt-bindings/pinctrl/samsung.h> - #include "../core.h" #include "pinctrl-samsung.h" @@ -614,7 +612,7 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, data = readl(reg); data &= ~(mask << shift); if (!input) - data |= EXYNOS_PIN_FUNC_OUTPUT << shift; + data |= PIN_CON_FUNC_OUTPUT << shift; writel(data, reg); return 0; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index fc6f5199c548..9af93e3d8d9f 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -53,6 +53,14 @@ enum pincfg_type { #define PINCFG_UNPACK_TYPE(cfg) ((cfg) & PINCFG_TYPE_MASK) #define PINCFG_UNPACK_VALUE(cfg) (((cfg) & PINCFG_VALUE_MASK) >> \ PINCFG_VALUE_SHIFT) +/* + * Values for the pin CON register, choosing pin function. + * The basic set (input and output) are same between: S3C24xx, S3C64xx, S5PV210, + * Exynos ARMv7, Exynos ARMv8, Tesla FSD. + */ +#define PIN_CON_FUNC_INPUT 0x0 +#define PIN_CON_FUNC_OUTPUT 0x1 + /** * enum eint_type - possible external interrupt types. * @EINT_TYPE_NONE: bank does not support external interrupts diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig index 33751a6a0757..a78fdbbdfc0c 100644 --- a/drivers/pinctrl/sunxi/Kconfig +++ b/drivers/pinctrl/sunxi/Kconfig @@ -29,7 +29,6 @@ config PINCTRL_SUN6I_A31 config PINCTRL_SUN6I_A31_R bool "Support for the Allwinner A31 R-PIO" default MACH_SUN6I - depends on RESET_CONTROLLER select PINCTRL_SUNXI config PINCTRL_SUN8I_A23 @@ -55,7 +54,6 @@ config PINCTRL_SUN8I_A83T_R config PINCTRL_SUN8I_A23_R bool "Support for the Allwinner A23 and A33 R-PIO" default MACH_SUN8I - depends on RESET_CONTROLLER select PINCTRL_SUNXI config PINCTRL_SUN8I_H3 @@ -81,7 +79,11 @@ config PINCTRL_SUN9I_A80 config PINCTRL_SUN9I_A80_R bool "Support for the Allwinner A80 R-PIO" default MACH_SUN9I - depends on RESET_CONTROLLER + select PINCTRL_SUNXI + +config PINCTRL_SUN20I_D1 + bool "Support for the Allwinner D1 PIO" + default MACH_SUN8I || (RISCV && ARCH_SUNXI) select PINCTRL_SUNXI config PINCTRL_SUN50I_A64 diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile index d3440c42b9d6..2ff5a55927ad 100644 --- a/drivers/pinctrl/sunxi/Makefile +++ b/drivers/pinctrl/sunxi/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R) += pinctrl-sun8i-a83t-r.o obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o obj-$(CONFIG_PINCTRL_SUN8I_H3_R) += pinctrl-sun8i-h3-r.o obj-$(CONFIG_PINCTRL_SUN8I_V3S) += pinctrl-sun8i-v3s.o +obj-$(CONFIG_PINCTRL_SUN20I_D1) += pinctrl-sun20i-d1.o obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c new file mode 100644 index 000000000000..40858b881298 --- /dev/null +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c @@ -0,0 +1,840 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner D1 SoC pinctrl driver. + * + * Copyright (c) 2020 [email protected] + * Copyright (c) 2021-2022 Samuel Holland <[email protected]> + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-sunxi.h" + +static const struct sunxi_desc_pin d1_pins[] = { + /* PB */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "pwm3"), + SUNXI_FUNCTION(0x3, "ir"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x5, "spi1"), /* WP */ + SUNXI_FUNCTION(0x6, "uart0"), /* TX */ + SUNXI_FUNCTION(0x7, "uart2"), /* TX */ + SUNXI_FUNCTION(0x8, "spdif"), /* OUT */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "pwm4"), + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT3 */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN3 */ + SUNXI_FUNCTION(0x6, "uart0"), /* RX */ + SUNXI_FUNCTION(0x7, "uart2"), /* RX */ + SUNXI_FUNCTION(0x8, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D0 */ + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT2 */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN2 */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D18 */ + SUNXI_FUNCTION(0x7, "uart4"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D1 */ + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN0 */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D19 */ + SUNXI_FUNCTION(0x7, "uart4"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D8 */ + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN1 */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D20 */ + SUNXI_FUNCTION(0x7, "uart5"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D9 */ + SUNXI_FUNCTION(0x3, "i2s2"), /* BCLK */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x5, "pwm0"), + SUNXI_FUNCTION(0x6, "lcd0"), /* D21 */ + SUNXI_FUNCTION(0x7, "uart5"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D16 */ + SUNXI_FUNCTION(0x3, "i2s2"), /* LRCK */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x5, "pwm1"), + SUNXI_FUNCTION(0x6, "lcd0"), /* D22 */ + SUNXI_FUNCTION(0x7, "uart3"), /* TX */ + SUNXI_FUNCTION(0x8, "bist0"), /* BIST_RESULT0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D17 */ + SUNXI_FUNCTION(0x3, "i2s2"), /* MCLK */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x5, "ir"), /* RX */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D23 */ + SUNXI_FUNCTION(0x7, "uart3"), /* RX */ + SUNXI_FUNCTION(0x8, "bist1"), /* BIST_RESULT1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA3 */ + SUNXI_FUNCTION(0x3, "pwm5"), + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x5, "spi1"), /* HOLD */ + SUNXI_FUNCTION(0x6, "uart0"), /* TX */ + SUNXI_FUNCTION(0x7, "uart1"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA2 */ + SUNXI_FUNCTION(0x3, "pwm6"), + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x5, "spi1"), /* MISO */ + SUNXI_FUNCTION(0x6, "uart0"), /* RX */ + SUNXI_FUNCTION(0x7, "uart1"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA1 */ + SUNXI_FUNCTION(0x3, "pwm7"), + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "spi1"), /* MOSI */ + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x7, "uart1"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA0 */ + SUNXI_FUNCTION(0x3, "pwm2"), + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "spi1"), /* CLK */ + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x7, "uart1"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* CLK */ + SUNXI_FUNCTION(0x3, "pwm0"), + SUNXI_FUNCTION(0x4, "spdif"), /* IN */ + SUNXI_FUNCTION(0x5, "spi1"), /* CS0 */ + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x7, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)), + /* PC */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* TX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "ledc"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* RX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* CLK */ + SUNXI_FUNCTION(0x3, "mmc2"), /* CLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* CS0 */ + SUNXI_FUNCTION(0x3, "mmc2"), /* CMD */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* MOSI */ + SUNXI_FUNCTION(0x3, "mmc2"), /* D2 */ + SUNXI_FUNCTION(0x4, "boot"), /* SEL0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* MISO */ + SUNXI_FUNCTION(0x3, "mmc2"), /* D1 */ + SUNXI_FUNCTION(0x4, "boot"), /* SEL1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* WP */ + SUNXI_FUNCTION(0x3, "mmc2"), /* D0 */ + SUNXI_FUNCTION(0x4, "uart3"), /* TX */ + SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x6, "pll"), /* DBG-CLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* HOLD */ + SUNXI_FUNCTION(0x3, "mmc2"), /* D3 */ + SUNXI_FUNCTION(0x4, "uart3"), /* RX */ + SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x6, "tcon"), /* TRIG0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)), + /* PD */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D2 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V0P */ + SUNXI_FUNCTION(0x4, "dsi"), /* D0P */ + SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D3 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V0N */ + SUNXI_FUNCTION(0x4, "dsi"), /* D0N */ + SUNXI_FUNCTION(0x5, "uart2"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D4 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V1P */ + SUNXI_FUNCTION(0x4, "dsi"), /* D1P */ + SUNXI_FUNCTION(0x5, "uart2"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D5 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V1N */ + SUNXI_FUNCTION(0x4, "dsi"), /* D1N */ + SUNXI_FUNCTION(0x5, "uart2"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D6 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V2P */ + SUNXI_FUNCTION(0x4, "dsi"), /* CKP */ + SUNXI_FUNCTION(0x5, "uart2"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D7 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V2N */ + SUNXI_FUNCTION(0x4, "dsi"), /* CKN */ + SUNXI_FUNCTION(0x5, "uart5"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D10 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* CKP */ + SUNXI_FUNCTION(0x4, "dsi"), /* D2P */ + SUNXI_FUNCTION(0x5, "uart5"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D11 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* CKN */ + SUNXI_FUNCTION(0x4, "dsi"), /* D2N */ + SUNXI_FUNCTION(0x5, "uart4"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D12 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V3P */ + SUNXI_FUNCTION(0x4, "dsi"), /* D3P */ + SUNXI_FUNCTION(0x5, "uart4"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D13 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V3N */ + SUNXI_FUNCTION(0x4, "dsi"), /* D3N */ + SUNXI_FUNCTION(0x5, "pwm6"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D14 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V0P */ + SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */ + SUNXI_FUNCTION(0x5, "uart3"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D15 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V0N */ + SUNXI_FUNCTION(0x4, "spi1"), /* CLK */ + SUNXI_FUNCTION(0x5, "uart3"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D18 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V1P */ + SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */ + SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D19 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V1N */ + SUNXI_FUNCTION(0x4, "spi1"), /* MISO */ + SUNXI_FUNCTION(0x5, "uart3"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D20 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V2P */ + SUNXI_FUNCTION(0x4, "spi1"), /* HOLD */ + SUNXI_FUNCTION(0x5, "uart3"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D21 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V2N */ + SUNXI_FUNCTION(0x4, "spi1"), /* WP */ + SUNXI_FUNCTION(0x5, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D22 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* CKP */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA3 */ + SUNXI_FUNCTION(0x5, "pwm0"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D23 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* CKN */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA2 */ + SUNXI_FUNCTION(0x5, "pwm1"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* CLK */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V3P */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA1 */ + SUNXI_FUNCTION(0x5, "pwm2"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* DE */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V3N */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA0 */ + SUNXI_FUNCTION(0x5, "pwm3"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* HSYNC */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "dmic"), /* CLK */ + SUNXI_FUNCTION(0x5, "pwm4"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* VSYNC */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x4, "uart1"), /* TX */ + SUNXI_FUNCTION(0x5, "pwm5"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x3, "ir"), /* RX */ + SUNXI_FUNCTION(0x4, "uart1"), /* RX */ + SUNXI_FUNCTION(0x5, "pwm7"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)), + /* PE */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* HSYNC */ + SUNXI_FUNCTION(0x3, "uart2"), /* RTS */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x5, "lcd0"), /* HSYNC */ + SUNXI_FUNCTION(0x8, "emac"), /* RXCTL/CRS_DV */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* VSYNC */ + SUNXI_FUNCTION(0x3, "uart2"), /* CTS */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x5, "lcd0"), /* VSYNC */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* PCLK */ + SUNXI_FUNCTION(0x3, "uart2"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x6, "uart0"), /* TX */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* MCLK */ + SUNXI_FUNCTION(0x3, "uart2"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x6, "uart0"), /* RX */ + SUNXI_FUNCTION(0x8, "emac"), /* TXCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D0 */ + SUNXI_FUNCTION(0x3, "uart4"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x6, "d_jtag"), /* MS */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* MS */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D1 */ + SUNXI_FUNCTION(0x3, "uart4"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x5, "ledc"), + SUNXI_FUNCTION(0x6, "d_jtag"), /* DI */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* DI */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D2 */ + SUNXI_FUNCTION(0x3, "uart5"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x5, "spdif"), /* IN */ + SUNXI_FUNCTION(0x6, "d_jtag"), /* DO */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* DO */ + SUNXI_FUNCTION(0x8, "emac"), /* TXCTL/TXEN */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D3 */ + SUNXI_FUNCTION(0x3, "uart5"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x5, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x6, "d_jtag"), /* CK */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* CK */ + SUNXI_FUNCTION(0x8, "emac"), /* CK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D4 */ + SUNXI_FUNCTION(0x3, "uart1"), /* RTS */ + SUNXI_FUNCTION(0x4, "pwm2"), + SUNXI_FUNCTION(0x5, "uart3"), /* TX */ + SUNXI_FUNCTION(0x6, "jtag"), /* MS */ + SUNXI_FUNCTION(0x8, "emac"), /* MDC */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D5 */ + SUNXI_FUNCTION(0x3, "uart1"), /* CTS */ + SUNXI_FUNCTION(0x4, "pwm3"), + SUNXI_FUNCTION(0x5, "uart3"), /* RX */ + SUNXI_FUNCTION(0x6, "jtag"), /* DI */ + SUNXI_FUNCTION(0x8, "emac"), /* MDIO */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D6 */ + SUNXI_FUNCTION(0x3, "uart1"), /* TX */ + SUNXI_FUNCTION(0x4, "pwm4"), + SUNXI_FUNCTION(0x5, "ir"), /* RX */ + SUNXI_FUNCTION(0x6, "jtag"), /* DO */ + SUNXI_FUNCTION(0x8, "emac"), /* EPHY-25M */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D7 */ + SUNXI_FUNCTION(0x3, "uart1"), /* RX */ + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT3 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN3 */ + SUNXI_FUNCTION(0x6, "jtag"), /* CK */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD2 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x3, "ncsi0"), /* FIELD */ + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT2 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN2 */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD3 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x3, "pwm5"), + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN1 */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA3 */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD2 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* MS */ + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN0 */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA2 */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD3 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* DI */ + SUNXI_FUNCTION(0x4, "pwm6"), + SUNXI_FUNCTION(0x5, "i2s0"), /* LRCK */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA1 */ + SUNXI_FUNCTION(0x8, "emac"), /* RXCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* DO */ + SUNXI_FUNCTION(0x4, "pwm7"), + SUNXI_FUNCTION(0x5, "i2s0"), /* BCLK */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* CK */ + SUNXI_FUNCTION(0x4, "ir"), /* TX */ + SUNXI_FUNCTION(0x5, "i2s0"), /* MCLK */ + SUNXI_FUNCTION(0x6, "dmic"), /* CLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)), + /* PF */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */ + SUNXI_FUNCTION(0x3, "jtag"), /* MS */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* MS */ + SUNXI_FUNCTION(0x5, "i2s2_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x6, "i2s2_din"), /* DIN0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */ + SUNXI_FUNCTION(0x3, "jtag"), /* DI */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* DI */ + SUNXI_FUNCTION(0x5, "i2s2_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x6, "i2s2_din"), /* DIN1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */ + SUNXI_FUNCTION(0x3, "uart0"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "ledc"), + SUNXI_FUNCTION(0x6, "spdif"), /* IN */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */ + SUNXI_FUNCTION(0x3, "jtag"), /* DO */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* DO */ + SUNXI_FUNCTION(0x5, "i2s2"), /* BCLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */ + SUNXI_FUNCTION(0x3, "uart0"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "pwm6"), + SUNXI_FUNCTION(0x6, "ir"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */ + SUNXI_FUNCTION(0x3, "jtag"), /* CK */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* CK */ + SUNXI_FUNCTION(0x5, "i2s2"), /* LRCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x3, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x4, "ir"), /* RX */ + SUNXI_FUNCTION(0x5, "i2s2"), /* MCLK */ + SUNXI_FUNCTION(0x6, "pwm5"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)), + /* PG */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */ + SUNXI_FUNCTION(0x3, "uart3"), /* TX */ + SUNXI_FUNCTION(0x4, "emac"), /* RXCTRL/CRS_DV */ + SUNXI_FUNCTION(0x5, "pwm7"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */ + SUNXI_FUNCTION(0x3, "uart3"), /* RX */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD0 */ + SUNXI_FUNCTION(0x5, "pwm6"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */ + SUNXI_FUNCTION(0x3, "uart3"), /* RTS */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD1 */ + SUNXI_FUNCTION(0x5, "uart4"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */ + SUNXI_FUNCTION(0x3, "uart3"), /* CTS */ + SUNXI_FUNCTION(0x4, "emac"), /* TXCK */ + SUNXI_FUNCTION(0x5, "uart4"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */ + SUNXI_FUNCTION(0x3, "uart5"), /* TX */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD0 */ + SUNXI_FUNCTION(0x5, "pwm5"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */ + SUNXI_FUNCTION(0x3, "uart5"), /* RX */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD1 */ + SUNXI_FUNCTION(0x5, "pwm4"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* TX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD2 */ + SUNXI_FUNCTION(0x5, "pwm1"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* RX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD3 */ + SUNXI_FUNCTION(0x5, "spdif"), /* IN */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* RTS */ + SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD2 */ + SUNXI_FUNCTION(0x5, "uart3"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* CTS */ + SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD3 */ + SUNXI_FUNCTION(0x5, "uart3"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "pwm3"), + SUNXI_FUNCTION(0x3, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* RXCK */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x6, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1"), /* MCLK */ + SUNXI_FUNCTION(0x3, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* EPHY-25M */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x6, "tcon"), /* TRIG0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1"), /* LRCK */ + SUNXI_FUNCTION(0x3, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* TXCTL/TXEN */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x6, "pwm0"), + SUNXI_FUNCTION(0x7, "uart1"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 12)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1"), /* BCLK */ + SUNXI_FUNCTION(0x3, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* CLKIN/RXER */ + SUNXI_FUNCTION(0x5, "pwm2"), + SUNXI_FUNCTION(0x6, "ledc"), + SUNXI_FUNCTION(0x7, "uart1"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 13)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1_din"), /* DIN0 */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* MDC */ + SUNXI_FUNCTION(0x5, "i2s1_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x6, "spi0"), /* WP */ + SUNXI_FUNCTION(0x7, "uart1"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 14)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* MDIO */ + SUNXI_FUNCTION(0x5, "i2s1_din"), /* DIN1 */ + SUNXI_FUNCTION(0x6, "spi0"), /* HOLD */ + SUNXI_FUNCTION(0x7, "uart1"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 15)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ir"), /* RX */ + SUNXI_FUNCTION(0x3, "tcon"), /* TRIG0 */ + SUNXI_FUNCTION(0x4, "pwm5"), + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x6, "spdif"), /* IN */ + SUNXI_FUNCTION(0x7, "ledc"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 16)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* TX */ + SUNXI_FUNCTION(0x3, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x4, "pwm7"), + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x6, "ir"), /* TX */ + SUNXI_FUNCTION(0x7, "uart0"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 17)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* RX */ + SUNXI_FUNCTION(0x3, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x4, "pwm6"), + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x6, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x7, "uart0"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 18)), +}; + +static const unsigned int d1_irq_bank_map[] = { 1, 2, 3, 4, 5, 6 }; + +static const struct sunxi_pinctrl_desc d1_pinctrl_data = { + .pins = d1_pins, + .npins = ARRAY_SIZE(d1_pins), + .irq_banks = ARRAY_SIZE(d1_irq_bank_map), + .irq_bank_map = d1_irq_bank_map, + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL, +}; + +static int d1_pinctrl_probe(struct platform_device *pdev) +{ + unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev); + + return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant); +} + +static const struct of_device_id d1_pinctrl_match[] = { + { + .compatible = "allwinner,sun20i-d1-pinctrl", + .data = (void *)PINCTRL_SUN20I_D1 + }, + {} +}; + +static struct platform_driver d1_pinctrl_driver = { + .probe = d1_pinctrl_probe, + .driver = { + .name = "sun20i-d1-pinctrl", + .of_match_table = d1_pinctrl_match, + }, +}; +builtin_platform_driver(d1_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index 21054fcacd34..afc1f5df7545 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data = { .npins = ARRAY_SIZE(a100_r_pins), .pin_base = PL_BASE, .irq_banks = 1, + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL, }; static int a100_r_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index e69f6da40dc0..f682e0e4244d 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data = { .npins = ARRAY_SIZE(a100_pins), .irq_banks = 7, .irq_bank_map = a100_irq_bank_map, - .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL, + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL, }; static int a100_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c index e69c8dae121a..ef261eccda56 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c @@ -24,7 +24,6 @@ #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/platform_device.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c index c7d90c44e87a..3aba0aec3d78 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c @@ -16,7 +16,6 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" @@ -107,6 +106,7 @@ static const struct sunxi_pinctrl_desc sun50i_h6_r_pinctrl_data = { .npins = ARRAY_SIZE(sun50i_h6_r_pins), .pin_base = PL_BASE, .irq_banks = 2, + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL, }; static int sun50i_h6_r_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c index 8e4f10ab96ce..c39ea46046c2 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c @@ -12,7 +12,6 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index 152b71226a80..d6ca720ee8d8 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map), .irq_bank_map = h616_irq_bank_map, .irq_read_needs_mux = true, - .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL, + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL, }; static int h616_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c index a00246d3dd49..2486cdf345e1 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c @@ -17,7 +17,6 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" @@ -111,26 +110,7 @@ static const struct sunxi_pinctrl_desc sun6i_a31_r_pinctrl_data = { static int sun6i_a31_r_pinctrl_probe(struct platform_device *pdev) { - struct reset_control *rstc; - int ret; - - rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(rstc)) { - dev_err(&pdev->dev, "Reset controller missing\n"); - return PTR_ERR(rstc); - } - - ret = reset_control_deassert(rstc); - if (ret) - return ret; - - ret = sunxi_pinctrl_init(pdev, - &sun6i_a31_r_pinctrl_data); - - if (ret) - reset_control_assert(rstc); - - return ret; + return sunxi_pinctrl_init(pdev, &sun6i_a31_r_pinctrl_data); } static const struct of_device_id sun6i_a31_r_pinctrl_match[] = { diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c index 9e5b61449999..4fae12c905b7 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c @@ -20,7 +20,6 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" @@ -98,29 +97,7 @@ static const struct sunxi_pinctrl_desc sun8i_a23_r_pinctrl_data = { static int sun8i_a23_r_pinctrl_probe(struct platform_device *pdev) { - struct reset_control *rstc; - int ret; - - rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(rstc)) { - ret = PTR_ERR(rstc); - if (ret == -EPROBE_DEFER) - return ret; - dev_err(&pdev->dev, "Reset controller missing err=%d\n", ret); - return ret; - } - - ret = reset_control_deassert(rstc); - if (ret) - return ret; - - ret = sunxi_pinctrl_init(pdev, - &sun8i_a23_r_pinctrl_data); - - if (ret) - reset_control_assert(rstc); - - return ret; + return sunxi_pinctrl_init(pdev, &sun8i_a23_r_pinctrl_data); } static const struct of_device_id sun8i_a23_r_pinctrl_match[] = { diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t-r.c index 6531cf67958e..0cb6c1a970c9 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t-r.c @@ -27,7 +27,6 @@ #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/platform_device.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" diff --git a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c index a191a65217ac..f11cb5bba0f7 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c @@ -14,7 +14,6 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/pinctrl.h> -#include <linux/reset.h> #include "pinctrl-sunxi.h" diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index dd928402af99..6c04027d0dd9 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -46,6 +46,67 @@ static struct lock_class_key sunxi_pinctrl_irq_request_class; static struct irq_chip sunxi_pinctrl_edge_irq_chip; static struct irq_chip sunxi_pinctrl_level_irq_chip; +/* + * The sunXi PIO registers are organized as a series of banks, with registers + * for each bank in the following order: + * - Mux config + * - Data value + * - Drive level + * - Pull direction + * + * Multiple consecutive registers are used for fields wider than one bit. + * + * The following functions calculate the register and the bit offset to access. + * They take a pin number which is relative to the start of the current device. + */ +static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl, + u32 pin, u32 *reg, u32 *shift, u32 *mask) +{ + u32 bank = pin / PINS_PER_BANK; + u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH; + + *reg = bank * pctl->bank_mem_size + MUX_REGS_OFFSET + + offset / BITS_PER_TYPE(u32) * sizeof(u32); + *shift = offset % BITS_PER_TYPE(u32); + *mask = (BIT(MUX_FIELD_WIDTH) - 1) << *shift; +} + +static void sunxi_data_reg(const struct sunxi_pinctrl *pctl, + u32 pin, u32 *reg, u32 *shift, u32 *mask) +{ + u32 bank = pin / PINS_PER_BANK; + u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH; + + *reg = bank * pctl->bank_mem_size + DATA_REGS_OFFSET + + offset / BITS_PER_TYPE(u32) * sizeof(u32); + *shift = offset % BITS_PER_TYPE(u32); + *mask = (BIT(DATA_FIELD_WIDTH) - 1) << *shift; +} + +static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl, + u32 pin, u32 *reg, u32 *shift, u32 *mask) +{ + u32 bank = pin / PINS_PER_BANK; + u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width; + + *reg = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET + + offset / BITS_PER_TYPE(u32) * sizeof(u32); + *shift = offset % BITS_PER_TYPE(u32); + *mask = (BIT(pctl->dlevel_field_width) - 1) << *shift; +} + +static void sunxi_pull_reg(const struct sunxi_pinctrl *pctl, + u32 pin, u32 *reg, u32 *shift, u32 *mask) +{ + u32 bank = pin / PINS_PER_BANK; + u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH; + + *reg = bank * pctl->bank_mem_size + pctl->pull_regs_offset + + offset / BITS_PER_TYPE(u32) * sizeof(u32); + *shift = offset % BITS_PER_TYPE(u32); + *mask = (BIT(PULL_FIELD_WIDTH) - 1) << *shift; +} + static struct sunxi_pinctrl_group * sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group) { @@ -451,22 +512,19 @@ static const struct pinctrl_ops sunxi_pctrl_ops = { .get_group_pins = sunxi_pctrl_get_group_pins, }; -static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param, - u32 *offset, u32 *shift, u32 *mask) +static int sunxi_pconf_reg(const struct sunxi_pinctrl *pctl, + u32 pin, enum pin_config_param param, + u32 *reg, u32 *shift, u32 *mask) { switch (param) { case PIN_CONFIG_DRIVE_STRENGTH: - *offset = sunxi_dlevel_reg(pin); - *shift = sunxi_dlevel_offset(pin); - *mask = DLEVEL_PINS_MASK; + sunxi_dlevel_reg(pctl, pin, reg, shift, mask); break; case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_DISABLE: - *offset = sunxi_pull_reg(pin); - *shift = sunxi_pull_offset(pin); - *mask = PULL_PINS_MASK; + sunxi_pull_reg(pctl, pin, reg, shift, mask); break; default: @@ -481,17 +539,17 @@ static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin, { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); enum pin_config_param param = pinconf_to_config_param(*config); - u32 offset, shift, mask, val; + u32 reg, shift, mask, val; u16 arg; int ret; pin -= pctl->desc->pin_base; - ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); + ret = sunxi_pconf_reg(pctl, pin, param, ®, &shift, &mask); if (ret < 0) return ret; - val = (readl(pctl->membase + offset) >> shift) & mask; + val = (readl(pctl->membase + reg) & mask) >> shift; switch (pinconf_to_config_param(*config)) { case PIN_CONFIG_DRIVE_STRENGTH: @@ -547,16 +605,15 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin, pin -= pctl->desc->pin_base; for (i = 0; i < num_configs; i++) { + u32 arg, reg, shift, mask, val; enum pin_config_param param; unsigned long flags; - u32 offset, shift, mask, reg; - u32 arg, val; int ret; param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); - ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); + ret = sunxi_pconf_reg(pctl, pin, param, ®, &shift, &mask); if (ret < 0) return ret; @@ -593,9 +650,8 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin, } raw_spin_lock_irqsave(&pctl->lock, flags); - reg = readl(pctl->membase + offset); - reg &= ~(mask << shift); - writel(reg | val << shift, pctl->membase + offset); + writel((readl(pctl->membase + reg) & ~mask) | val << shift, + pctl->membase + reg); raw_spin_unlock_irqrestore(&pctl->lock, flags); } /* for each config */ @@ -624,7 +680,7 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl, unsigned pin, struct regulator *supply) { - unsigned short bank = pin / PINS_PER_BANK; + unsigned short bank; unsigned long flags; u32 val, reg; int uV; @@ -640,6 +696,9 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl, if (uV == 0) return 0; + pin -= pctl->desc->pin_base; + bank = pin / PINS_PER_BANK; + switch (pctl->desc->io_bias_cfg_variant) { case BIAS_VOLTAGE_GRP_CONFIG: /* @@ -657,12 +716,20 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl, else val = 0xD; /* 3.3V */ - pin -= pctl->desc->pin_base; - reg = readl(pctl->membase + sunxi_grp_config_reg(pin)); reg &= ~IO_BIAS_MASK; writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin)); return 0; + case BIAS_VOLTAGE_PIO_POW_MODE_CTL: + val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0; + + raw_spin_lock_irqsave(&pctl->lock, flags); + reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG); + reg &= ~BIT(bank); + writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG); + raw_spin_unlock_irqrestore(&pctl->lock, flags); + + fallthrough; case BIAS_VOLTAGE_PIO_POW_MODE_SEL: val = uV <= 1800000 ? 1 : 0; @@ -710,16 +777,16 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev, u8 config) { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + u32 reg, shift, mask; unsigned long flags; - u32 val, mask; + + pin -= pctl->desc->pin_base; + sunxi_mux_reg(pctl, pin, ®, &shift, &mask); raw_spin_lock_irqsave(&pctl->lock, flags); - pin -= pctl->desc->pin_base; - val = readl(pctl->membase + sunxi_mux_reg(pin)); - mask = MUX_PINS_MASK << sunxi_mux_offset(pin); - writel((val & ~mask) | config << sunxi_mux_offset(pin), - pctl->membase + sunxi_mux_reg(pin)); + writel((readl(pctl->membase + reg) & ~mask) | config << shift, + pctl->membase + reg); raw_spin_unlock_irqrestore(&pctl->lock, flags); } @@ -852,43 +919,43 @@ static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip, static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset) { struct sunxi_pinctrl *pctl = gpiochip_get_data(chip); - u32 reg = sunxi_data_reg(offset); - u8 index = sunxi_data_offset(offset); bool set_mux = pctl->desc->irq_read_needs_mux && gpiochip_line_is_irq(chip, offset); u32 pin = offset + chip->base; - u32 val; + u32 reg, shift, mask, val; + + sunxi_data_reg(pctl, offset, ®, &shift, &mask); if (set_mux) sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT); - val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK; + val = (readl(pctl->membase + reg) & mask) >> shift; if (set_mux) sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ); - return !!val; + return val; } static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct sunxi_pinctrl *pctl = gpiochip_get_data(chip); - u32 reg = sunxi_data_reg(offset); - u8 index = sunxi_data_offset(offset); + u32 reg, shift, mask, val; unsigned long flags; - u32 regval; + + sunxi_data_reg(pctl, offset, ®, &shift, &mask); raw_spin_lock_irqsave(&pctl->lock, flags); - regval = readl(pctl->membase + reg); + val = readl(pctl->membase + reg); if (value) - regval |= BIT(index); + val |= mask; else - regval &= ~(BIT(index)); + val &= ~mask; - writel(regval, pctl->membase + reg); + writel(val, pctl->membase + reg); raw_spin_unlock_irqrestore(&pctl->lock, flags); } @@ -1232,11 +1299,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) /* * Find an upper bound for the maximum number of functions: in - * the worst case we have gpio_in, gpio_out, irq and up to four + * the worst case we have gpio_in, gpio_out, irq and up to seven * special functions per pin, plus one entry for the sentinel. * We'll reallocate that later anyway. */ - pctl->functions = kcalloc(4 * pctl->ngroups + 4, + pctl->functions = kcalloc(7 * pctl->ngroups + 4, sizeof(*pctl->functions), GFP_KERNEL); if (!pctl->functions) @@ -1429,6 +1496,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev, pctl->dev = &pdev->dev; pctl->desc = desc; pctl->variant = variant; + if (pctl->variant >= PINCTRL_SUN20I_D1) { + pctl->bank_mem_size = D1_BANK_MEM_SIZE; + pctl->pull_regs_offset = D1_PULL_REGS_OFFSET; + pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH; + } else { + pctl->bank_mem_size = BANK_MEM_SIZE; + pctl->pull_regs_offset = PULL_REGS_OFFSET; + pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH; + } pctl->irq_array = devm_kcalloc(&pdev->dev, IRQ_PER_BANK * pctl->desc->irq_banks, diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index a32bb5bcb754..a87a2f944d60 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h @@ -36,23 +36,19 @@ #define BANK_MEM_SIZE 0x24 #define MUX_REGS_OFFSET 0x0 +#define MUX_FIELD_WIDTH 4 #define DATA_REGS_OFFSET 0x10 +#define DATA_FIELD_WIDTH 1 #define DLEVEL_REGS_OFFSET 0x14 +#define DLEVEL_FIELD_WIDTH 2 #define PULL_REGS_OFFSET 0x1c +#define PULL_FIELD_WIDTH 2 + +#define D1_BANK_MEM_SIZE 0x30 +#define D1_DLEVEL_FIELD_WIDTH 4 +#define D1_PULL_REGS_OFFSET 0x24 #define PINS_PER_BANK 32 -#define MUX_PINS_PER_REG 8 -#define MUX_PINS_BITS 4 -#define MUX_PINS_MASK 0x0f -#define DATA_PINS_PER_REG 32 -#define DATA_PINS_BITS 1 -#define DATA_PINS_MASK 0x01 -#define DLEVEL_PINS_PER_REG 16 -#define DLEVEL_PINS_BITS 2 -#define DLEVEL_PINS_MASK 0x03 -#define PULL_PINS_PER_REG 16 -#define PULL_PINS_BITS 2 -#define PULL_PINS_MASK 0x03 #define IRQ_PER_BANK 32 @@ -96,8 +92,11 @@ #define PINCTRL_SUN8I_R40 BIT(8) #define PINCTRL_SUN8I_V3 BIT(9) #define PINCTRL_SUN8I_V3S BIT(10) +/* Variants below here have an updated register layout. */ +#define PINCTRL_SUN20I_D1 BIT(11) #define PIO_POW_MOD_SEL_REG 0x340 +#define PIO_POW_MOD_CTL_REG 0x344 enum sunxi_desc_bias_voltage { BIAS_VOLTAGE_NONE, @@ -111,6 +110,12 @@ enum sunxi_desc_bias_voltage { * register, as seen on H6 SoC, for example. */ BIAS_VOLTAGE_PIO_POW_MODE_SEL, + /* + * Bias voltage is set through PIO_POW_MOD_SEL_REG + * and PIO_POW_MOD_CTL_REG register, as seen on + * A100 and D1 SoC, for example. + */ + BIAS_VOLTAGE_PIO_POW_MODE_CTL, }; struct sunxi_desc_function { @@ -170,6 +175,9 @@ struct sunxi_pinctrl { raw_spinlock_t lock; struct pinctrl_dev *pctl_dev; unsigned long variant; + u32 bank_mem_size; + u32 pull_regs_offset; + u32 dlevel_field_width; }; #define SUNXI_PIN(_pin, ...) \ @@ -215,83 +223,6 @@ struct sunxi_pinctrl { .irqnum = _irq, \ } -/* - * The sunXi PIO registers are organized as is: - * 0x00 - 0x0c Muxing values. - * 8 pins per register, each pin having a 4bits value - * 0x10 Pin values - * 32 bits per register, each pin corresponding to one bit - * 0x14 - 0x18 Drive level - * 16 pins per register, each pin having a 2bits value - * 0x1c - 0x20 Pull-Up values - * 16 pins per register, each pin having a 2bits value - * - * This is for the first bank. Each bank will have the same layout, - * with an offset being a multiple of 0x24. - * - * The following functions calculate from the pin number the register - * and the bit offset that we should access. - */ -static inline u32 sunxi_mux_reg(u16 pin) -{ - u8 bank = pin / PINS_PER_BANK; - u32 offset = bank * BANK_MEM_SIZE; - offset += MUX_REGS_OFFSET; - offset += pin % PINS_PER_BANK / MUX_PINS_PER_REG * 0x04; - return round_down(offset, 4); -} - -static inline u32 sunxi_mux_offset(u16 pin) -{ - u32 pin_num = pin % MUX_PINS_PER_REG; - return pin_num * MUX_PINS_BITS; -} - -static inline u32 sunxi_data_reg(u16 pin) -{ - u8 bank = pin / PINS_PER_BANK; - u32 offset = bank * BANK_MEM_SIZE; - offset += DATA_REGS_OFFSET; - offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04; - return round_down(offset, 4); -} - -static inline u32 sunxi_data_offset(u16 pin) -{ - u32 pin_num = pin % DATA_PINS_PER_REG; - return pin_num * DATA_PINS_BITS; -} - -static inline u32 sunxi_dlevel_reg(u16 pin) -{ - u8 bank = pin / PINS_PER_BANK; - u32 offset = bank * BANK_MEM_SIZE; - offset += DLEVEL_REGS_OFFSET; - offset += pin % PINS_PER_BANK / DLEVEL_PINS_PER_REG * 0x04; - return round_down(offset, 4); -} - -static inline u32 sunxi_dlevel_offset(u16 pin) -{ - u32 pin_num = pin % DLEVEL_PINS_PER_REG; - return pin_num * DLEVEL_PINS_BITS; -} - -static inline u32 sunxi_pull_reg(u16 pin) -{ - u8 bank = pin / PINS_PER_BANK; - u32 offset = bank * BANK_MEM_SIZE; - offset += PULL_REGS_OFFSET; - offset += pin % PINS_PER_BANK / PULL_PINS_PER_REG * 0x04; - return round_down(offset, 4); -} - -static inline u32 sunxi_pull_offset(u16 pin) -{ - u32 pin_num = pin % PULL_PINS_PER_REG; - return pin_num * PULL_PINS_BITS; -} - static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc, u8 bank) { if (!desc->irq_bank_map) diff --git a/fs/Kconfig b/fs/Kconfig index 5976eb33535f..a547307c1ae8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -247,8 +247,7 @@ config HUGETLB_PAGE # # Select this config option from the architecture Kconfig, if it is preferred -# to enable the feature of minimizing overhead of struct page associated with -# each HugeTLB page. +# to enable the feature of HugeTLB Vmemmap Optimization (HVO). # config ARCH_WANT_HUGETLB_PAGE_OPTIMIZE_VMEMMAP bool @@ -259,14 +258,13 @@ config HUGETLB_PAGE_OPTIMIZE_VMEMMAP depends on SPARSEMEM_VMEMMAP config HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON - bool "Default optimizing vmemmap pages of HugeTLB to on" + bool "HugeTLB Vmemmap Optimization (HVO) defaults to on" default n depends on HUGETLB_PAGE_OPTIMIZE_VMEMMAP help - When using HUGETLB_PAGE_OPTIMIZE_VMEMMAP, the optimizing unused vmemmap - pages associated with each HugeTLB page is default off. Say Y here - to enable optimizing vmemmap pages of HugeTLB by default. It can then - be disabled on the command line via hugetlb_free_vmemmap=off. + The HugeTLB VmemmapvOptimization (HVO) defaults to off. Say Y here to + enable HVO by default. It can be disabled via hugetlb_free_vmemmap=off + (boot command line) or hugetlb_optimize_vmemmap (sysctl). config MEMFD_CREATE def_bool TMPFS || HUGETLBFS diff --git a/include/dt-bindings/pinctrl/r7s9210-pinctrl.h b/include/dt-bindings/pinctrl/r7s9210-pinctrl.h index 2d0c23e5d3a7..8736ce038eca 100644 --- a/include/dt-bindings/pinctrl/r7s9210-pinctrl.h +++ b/include/dt-bindings/pinctrl/r7s9210-pinctrl.h @@ -42,6 +42,6 @@ /* * Convert a port and pin label to its global pin index */ - #define RZA2_PIN(port, pin) ((port) * RZA2_PINS_PER_PORT + (pin)) +#define RZA2_PIN(port, pin) ((port) * RZA2_PINS_PER_PORT + (pin)) #endif /* __DT_BINDINGS_PINCTRL_RENESAS_RZA2_H */ diff --git a/include/dt-bindings/pinctrl/rzg2l-pinctrl.h b/include/dt-bindings/pinctrl/rzg2l-pinctrl.h index b48f8c7a5556..c78ed5e5efb7 100644 --- a/include/dt-bindings/pinctrl/rzg2l-pinctrl.h +++ b/include/dt-bindings/pinctrl/rzg2l-pinctrl.h @@ -18,6 +18,6 @@ #define RZG2L_PORT_PINMUX(b, p, f) ((b) * RZG2L_PINS_PER_PORT + (p) | ((f) << 16)) /* Convert a port and pin label to its global pin index */ - #define RZG2L_GPIO(port, pin) ((port) * RZG2L_PINS_PER_PORT + (pin)) +#define RZG2L_GPIO(port, pin) ((port) * RZG2L_PINS_PER_PORT + (pin)) #endif /* __DT_BINDINGS_RZG2L_PINCTRL_H */ diff --git a/include/dt-bindings/pinctrl/rzv2m-pinctrl.h b/include/dt-bindings/pinctrl/rzv2m-pinctrl.h new file mode 100644 index 000000000000..525532cd15da --- /dev/null +++ b/include/dt-bindings/pinctrl/rzv2m-pinctrl.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * This header provides constants for Renesas RZ/V2M pinctrl bindings. + * + * Copyright (C) 2022 Renesas Electronics Corp. + * + */ + +#ifndef __DT_BINDINGS_RZV2M_PINCTRL_H +#define __DT_BINDINGS_RZV2M_PINCTRL_H + +#define RZV2M_PINS_PER_PORT 16 + +/* + * Create the pin index from its bank and position numbers and store in + * the upper 16 bits the alternate function identifier + */ +#define RZV2M_PORT_PINMUX(b, p, f) ((b) * RZV2M_PINS_PER_PORT + (p) | ((f) << 16)) + +/* Convert a port and pin label to its global pin index */ +#define RZV2M_GPIO(port, pin) ((port) * RZV2M_PINS_PER_PORT + (pin)) + +#endif /* __DT_BINDINGS_RZV2M_PINCTRL_H */ diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index cbde3b1fa414..9f50dacbf7d6 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -369,6 +369,11 @@ enum pm_pinctrl_drive_strength { PM_PINCTRL_DRIVE_STRENGTH_12MA = 3, }; +enum pm_pinctrl_tri_state { + PM_PINCTRL_TRI_STATE_DISABLE = 0, + PM_PINCTRL_TRI_STATE_ENABLE = 1, +}; + enum zynqmp_pm_shutdown_type { ZYNQMP_PM_SHUTDOWN_TYPE_SHUTDOWN = 0, ZYNQMP_PM_SHUTDOWN_TYPE_RESET = 1, diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 177b07944640..25679035ca28 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -60,11 +60,11 @@ static inline void kmap_flush_unused(void); /** * kmap_local_page - Map a page for temporary usage - * @page: Pointer to the page to be mapped + * @page: Pointer to the page to be mapped * * Returns: The virtual address of the mapping * - * Can be invoked from any context. + * Can be invoked from any context, including interrupts. * * Requires careful handling when nesting multiple mappings because the map * management is stack based. The unmap has to be in the reverse order of @@ -86,8 +86,7 @@ static inline void kmap_flush_unused(void); * temporarily mapped. * * While it is significantly faster than kmap() for the higmem case it - * comes with restrictions about the pointer validity. Only use when really - * necessary. + * comes with restrictions about the pointer validity. * * On HIGHMEM enabled systems mapping a highmem page has the side effect of * disabling migration in order to keep the virtual address stable across diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 4cdfce976644..3ec981a0d8b3 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -43,6 +43,9 @@ enum { SUBPAGE_INDEX_CGROUP_RSVD, /* reuse page->private */ __MAX_CGROUP_SUBPAGE_INDEX = SUBPAGE_INDEX_CGROUP_RSVD, #endif +#ifdef CONFIG_MEMORY_FAILURE + SUBPAGE_INDEX_HWPOISON, +#endif __NR_USED_SUBPAGE, }; @@ -551,7 +554,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr, * Synchronization: Initially set after new page allocation with no * locking. When examined and modified during migration processing * (isolate, migrate, putback) the hugetlb_lock is held. - * HPG_temporary - - Set on a page that is temporarily allocated from the buddy + * HPG_temporary - Set on a page that is temporarily allocated from the buddy * allocator. Typically used for migration target pages when no pages * are available in the pool. The hugetlb free page path will * immediately free pages with this flag set to the buddy allocator. @@ -561,6 +564,8 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr, * HPG_freed - Set when page is on the free lists. * Synchronization: hugetlb_lock held for examination and modification. * HPG_vmemmap_optimized - Set when the vmemmap pages of the page are freed. + * HPG_raw_hwp_unreliable - Set when the hugetlb page has a hwpoison sub-page + * that is not tracked by raw_hwp_page list. */ enum hugetlb_page_flags { HPG_restore_reserve = 0, @@ -568,6 +573,7 @@ enum hugetlb_page_flags { HPG_temporary, HPG_freed, HPG_vmemmap_optimized, + HPG_raw_hwp_unreliable, __NR_HPAGEFLAGS, }; @@ -614,6 +620,7 @@ HPAGEFLAG(Migratable, migratable) HPAGEFLAG(Temporary, temporary) HPAGEFLAG(Freed, freed) HPAGEFLAG(VmemmapOptimized, vmemmap_optimized) +HPAGEFLAG(RawHwpUnreliable, raw_hwp_unreliable) #ifdef CONFIG_HUGETLB_PAGE @@ -638,9 +645,6 @@ struct hstate { unsigned int nr_huge_pages_node[MAX_NUMNODES]; unsigned int free_huge_pages_node[MAX_NUMNODES]; unsigned int surplus_huge_pages_node[MAX_NUMNODES]; -#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP - unsigned int optimize_vmemmap_pages; -#endif #ifdef CONFIG_CGROUP_HUGETLB /* cgroup control files */ struct cftype cgroup_files_dfl[8]; @@ -716,7 +720,7 @@ static inline struct hstate *hstate_vma(struct vm_area_struct *vma) return hstate_file(vma->vm_file); } -static inline unsigned long huge_page_size(struct hstate *h) +static inline unsigned long huge_page_size(const struct hstate *h) { return (unsigned long)PAGE_SIZE << h->order; } @@ -745,7 +749,7 @@ static inline bool hstate_is_gigantic(struct hstate *h) return huge_page_order(h) >= MAX_ORDER; } -static inline unsigned int pages_per_huge_page(struct hstate *h) +static inline unsigned int pages_per_huge_page(const struct hstate *h) { return 1 << h->order; } @@ -799,6 +803,14 @@ extern int dissolve_free_huge_page(struct page *page); extern int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn); +#ifdef CONFIG_MEMORY_FAILURE +extern void hugetlb_clear_page_hwpoison(struct page *hpage); +#else +static inline void hugetlb_clear_page_hwpoison(struct page *hpage) +{ +} +#endif + #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION #ifndef arch_hugetlb_migration_supported static inline bool arch_hugetlb_migration_supported(struct hstate *h) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index ec5f71f7135b..616b683563a9 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -141,6 +141,7 @@ enum { IORES_DESC_DEVICE_PRIVATE_MEMORY = 6, IORES_DESC_RESERVED = 7, IORES_DESC_SOFT_RESERVED = 8, + IORES_DESC_CXL = 9, }; /* @@ -329,6 +330,8 @@ struct resource *devm_request_free_mem_region(struct device *dev, struct resource *base, unsigned long size); struct resource *request_free_mem_region(struct resource *base, unsigned long size, const char *name); +struct resource *alloc_free_mem_region(struct resource *base, + unsigned long size, unsigned long align, const char *name); static inline void irqresource_disabled(struct resource *res, u32 irq) { diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index 0d61e07b6827..c74acfa1a3fe 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h @@ -59,6 +59,9 @@ enum { /* Platform provides asynchronous flush mechanism */ ND_REGION_ASYNC = 3, + /* Region was created by CXL subsystem */ + ND_REGION_CXL = 4, + /* mark newly adjusted resources as requiring a label update */ DPA_RESOURCE_ADJUSTED = 1 << 0, }; @@ -122,6 +125,7 @@ struct nd_region_desc { int numa_node; int target_node; unsigned long flags; + int memregion; struct device_node *of_node; int (*flush)(struct nd_region *nd_region, struct bio *bio); }; @@ -259,6 +263,7 @@ static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, cmd_mask, num_flush, flush_wpq, NULL, NULL, NULL); } void nvdimm_delete(struct nvdimm *nvdimm); +void nvdimm_region_delete(struct nd_region *nd_region); const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd); const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd); diff --git a/include/linux/mm.h b/include/linux/mm.h index 18e01474cf6b..3bedc449c14d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3142,13 +3142,6 @@ static inline void print_vma_addr(char *prefix, unsigned long rip) } #endif -#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP -int vmemmap_remap_free(unsigned long start, unsigned long end, - unsigned long reuse); -int vmemmap_remap_alloc(unsigned long start, unsigned long end, - unsigned long reuse, gfp_t gfp_mask); -#endif - void *sparse_buffer_alloc(unsigned long size); struct page * __populate_section_memmap(unsigned long pfn, unsigned long nr_pages, int nid, struct vmem_altmap *altmap, @@ -3183,6 +3176,7 @@ enum mf_flags { MF_SOFT_OFFLINE = 1 << 3, MF_UNPOISON = 1 << 4, MF_SW_SIMULATED = 1 << 5, + MF_NO_RETRY = 1 << 6, }; int mf_dax_kill_procs(struct address_space *mapping, pgoff_t index, unsigned long count, int mf_flags); @@ -3235,7 +3229,6 @@ enum mf_action_page_type { MF_MSG_DIFFERENT_COMPOUND, MF_MSG_HUGE, MF_MSG_FREE_HUGE, - MF_MSG_NON_PMD_HUGE, MF_MSG_UNMAP_FAILED, MF_MSG_DIRTY_SWAPCACHE, MF_MSG_CLEAN_SWAPCACHE, diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index ea19528564d1..465ff35a8c00 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -205,34 +205,15 @@ enum pageflags { #ifndef __GENERATING_BOUNDS_H #ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP -DECLARE_STATIC_KEY_MAYBE(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON, - hugetlb_optimize_vmemmap_key); - -static __always_inline bool hugetlb_optimize_vmemmap_enabled(void) -{ - return static_branch_maybe(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON, - &hugetlb_optimize_vmemmap_key); -} +DECLARE_STATIC_KEY_FALSE(hugetlb_optimize_vmemmap_key); /* - * If the feature of optimizing vmemmap pages associated with each HugeTLB - * page is enabled, the head vmemmap page frame is reused and all of the tail - * vmemmap addresses map to the head vmemmap page frame (furture details can - * refer to the figure at the head of the mm/hugetlb_vmemmap.c). In other - * words, there are more than one page struct with PG_head associated with each - * HugeTLB page. We __know__ that there is only one head page struct, the tail - * page structs with PG_head are fake head page structs. We need an approach - * to distinguish between those two different types of page structs so that - * compound_head() can return the real head page struct when the parameter is - * the tail page struct but with PG_head. - * - * The page_fixed_fake_head() returns the real head page struct if the @page is - * fake page head, otherwise, returns @page which can either be a true page - * head or tail. + * Return the real head page struct iff the @page is a fake head page, otherwise + * return the @page itself. See Documentation/mm/vmemmap_dedup.rst. */ static __always_inline const struct page *page_fixed_fake_head(const struct page *page) { - if (!hugetlb_optimize_vmemmap_enabled()) + if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key)) return page; /* @@ -260,11 +241,6 @@ static inline const struct page *page_fixed_fake_head(const struct page *page) { return page; } - -static inline bool hugetlb_optimize_vmemmap_enabled(void) -{ - return false; -} #endif static __always_inline int page_is_fake_head(struct page *page) diff --git a/include/linux/pci-doe.h b/include/linux/pci-doe.h new file mode 100644 index 000000000000..ed9b4df792b8 --- /dev/null +++ b/include/linux/pci-doe.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Data Object Exchange + * PCIe r6.0, sec 6.30 DOE + * + * Copyright (C) 2021 Huawei + * Jonathan Cameron <[email protected]> + * + * Copyright (C) 2022 Intel Corporation + * Ira Weiny <[email protected]> + */ + +#ifndef LINUX_PCI_DOE_H +#define LINUX_PCI_DOE_H + +struct pci_doe_protocol { + u16 vid; + u8 type; +}; + +struct pci_doe_mb; + +/** + * struct pci_doe_task - represents a single query/response + * + * @prot: DOE Protocol + * @request_pl: The request payload + * @request_pl_sz: Size of the request payload (bytes) + * @response_pl: The response payload + * @response_pl_sz: Size of the response payload (bytes) + * @rv: Return value. Length of received response or error (bytes) + * @complete: Called when task is complete + * @private: Private data for the consumer + * @work: Used internally by the mailbox + * @doe_mb: Used internally by the mailbox + * + * The payload sizes and rv are specified in bytes with the following + * restrictions concerning the protocol. + * + * 1) The request_pl_sz must be a multiple of double words (4 bytes) + * 2) The response_pl_sz must be >= a single double word (4 bytes) + * 3) rv is returned as bytes but it will be a multiple of double words + * + * NOTE there is no need for the caller to initialize work or doe_mb. + */ +struct pci_doe_task { + struct pci_doe_protocol prot; + u32 *request_pl; + size_t request_pl_sz; + u32 *response_pl; + size_t response_pl_sz; + int rv; + void (*complete)(struct pci_doe_task *task); + void *private; + + /* No need for the user to initialize these fields */ + struct work_struct work; + struct pci_doe_mb *doe_mb; +}; + +/** + * pci_doe_for_each_off - Iterate each DOE capability + * @pdev: struct pci_dev to iterate + * @off: u16 of config space offset of each mailbox capability found + */ +#define pci_doe_for_each_off(pdev, off) \ + for (off = pci_find_next_ext_capability(pdev, off, \ + PCI_EXT_CAP_ID_DOE); \ + off > 0; \ + off = pci_find_next_ext_capability(pdev, off, \ + PCI_EXT_CAP_ID_DOE)) + +struct pci_doe_mb *pcim_doe_create_mb(struct pci_dev *pdev, u16 cap_offset); +bool pci_doe_supports_prot(struct pci_doe_mb *doe_mb, u16 vid, u8 type); +int pci_doe_submit_task(struct pci_doe_mb *doe_mb, struct pci_doe_task *task); + +#endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 7fa460ccf7fa..6feade66efdb 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -151,6 +151,7 @@ #define PCI_CLASS_OTHERS 0xff /* Vendors and devices. Sort key: vendor first, device next. */ +#define PCI_VENDOR_ID_PCI_SIG 0x0001 #define PCI_VENDOR_ID_LOONGSON 0x0014 diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 70b45d28e7a9..487117ccb1bc 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -27,6 +27,26 @@ struct gpio_chip; struct device_node; /** + * struct pingroup - provides information on pingroup + * @name: a name for pingroup + * @pins: an array of pins in the pingroup + * @npins: number of pins in the pingroup + */ +struct pingroup { + const char *name; + const unsigned int *pins; + size_t npins; +}; + +/* Convenience macro to define a single named or anonymous pingroup */ +#define PINCTRL_PINGROUP(_name, _pins, _npins) \ +(struct pingroup){ \ + .name = _name, \ + .pins = _pins, \ + .npins = _npins, \ +} + +/** * struct pinctrl_pin_desc - boards/machines provide information on their * pins, pads or other muxable units in this struct * @number: unique pin number from the global pin number space diff --git a/include/linux/swapops.h b/include/linux/swapops.h index bb7afd03a324..a3d435bf9f97 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -490,6 +490,11 @@ static inline void num_poisoned_pages_dec(void) atomic_long_dec(&num_poisoned_pages); } +static inline void num_poisoned_pages_sub(long i) +{ + atomic_long_sub(i, &num_poisoned_pages); +} + #else static inline swp_entry_t make_hwpoison_entry(struct page *page) @@ -505,6 +510,10 @@ static inline int is_hwpoison_entry(swp_entry_t swp) static inline void num_poisoned_pages_inc(void) { } + +static inline void num_poisoned_pages_sub(long i) +{ +} #endif static inline int non_swap_entry(swp_entry_t entry) diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 17b42ce89d3e..780690dc08cd 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -268,6 +268,10 @@ static inline struct ctl_table_header *register_sysctl_table(struct ctl_table * return NULL; } +static inline void register_sysctl_init(const char *path, struct ctl_table *table) +{ +} + static inline struct ctl_table_header *register_sysctl_mount_point(const char *path) { return NULL; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index e3f1e8ac1f85..fd3fe5c8c17f 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -235,6 +235,22 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_WO(_name, _size) #define BIN_ATTR_RW(_name, _size) \ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size) + +#define __BIN_ATTR_ADMIN_RO(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0400 }, \ + .read = _name##_read, \ + .size = _size, \ +} + +#define __BIN_ATTR_ADMIN_RW(_name, _size) \ + __BIN_ATTR(_name, 0600, _name##_read, _name##_write, _size) + +#define BIN_ATTR_ADMIN_RO(_name, _size) \ +struct bin_attribute bin_attr_##_name = __BIN_ATTR_ADMIN_RO(_name, _size) + +#define BIN_ATTR_ADMIN_RW(_name, _size) \ +struct bin_attribute bin_attr_##_name = __BIN_ATTR_ADMIN_RW(_name, _size) + struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h index d0337a41141c..cbd3ddd7c33d 100644 --- a/include/ras/ras_event.h +++ b/include/ras/ras_event.h @@ -360,7 +360,6 @@ TRACE_EVENT(aer_event, EM ( MF_MSG_DIFFERENT_COMPOUND, "different compound page after locking" ) \ EM ( MF_MSG_HUGE, "huge page" ) \ EM ( MF_MSG_FREE_HUGE, "free huge page" ) \ - EM ( MF_MSG_NON_PMD_HUGE, "non-pmd-sized huge page" ) \ EM ( MF_MSG_UNMAP_FAILED, "unmapping failed page" ) \ EM ( MF_MSG_DIRTY_SWAPCACHE, "dirty swapcache page" ) \ EM ( MF_MSG_CLEAN_SWAPCACHE, "clean swapcache page" ) \ diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 108f8523fa04..57b8e2ffb1dd 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -737,7 +737,8 @@ #define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */ #define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */ #define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_16GT +#define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE #define PCI_EXT_CAP_DSN_SIZEOF 12 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 @@ -1103,4 +1104,30 @@ #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0 #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4 +/* Data Object Exchange */ +#define PCI_DOE_CAP 0x04 /* DOE Capabilities Register */ +#define PCI_DOE_CAP_INT_SUP 0x00000001 /* Interrupt Support */ +#define PCI_DOE_CAP_INT_MSG_NUM 0x00000ffe /* Interrupt Message Number */ +#define PCI_DOE_CTRL 0x08 /* DOE Control Register */ +#define PCI_DOE_CTRL_ABORT 0x00000001 /* DOE Abort */ +#define PCI_DOE_CTRL_INT_EN 0x00000002 /* DOE Interrupt Enable */ +#define PCI_DOE_CTRL_GO 0x80000000 /* DOE Go */ +#define PCI_DOE_STATUS 0x0c /* DOE Status Register */ +#define PCI_DOE_STATUS_BUSY 0x00000001 /* DOE Busy */ +#define PCI_DOE_STATUS_INT_STATUS 0x00000002 /* DOE Interrupt Status */ +#define PCI_DOE_STATUS_ERROR 0x00000004 /* DOE Error */ +#define PCI_DOE_STATUS_DATA_OBJECT_READY 0x80000000 /* Data Object Ready */ +#define PCI_DOE_WRITE 0x10 /* DOE Write Data Mailbox Register */ +#define PCI_DOE_READ 0x14 /* DOE Read Data Mailbox Register */ + +/* DOE Data Object - note not actually registers */ +#define PCI_DOE_DATA_OBJECT_HEADER_1_VID 0x0000ffff +#define PCI_DOE_DATA_OBJECT_HEADER_1_TYPE 0x00ff0000 +#define PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH 0x0003ffff + +#define PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX 0x000000ff +#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID 0x0000ffff +#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000 +#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000 + #endif /* LINUX_PCI_REGS_H */ diff --git a/init/Kconfig b/init/Kconfig index 922848a094d7..80fe60fa77fb 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1411,13 +1411,6 @@ config CC_OPTIMIZE_FOR_PERFORMANCE with the "-O2" compiler flag for best performance and most helpful compile-time warnings. -config CC_OPTIMIZE_FOR_PERFORMANCE_O3 - bool "Optimize more for performance (-O3)" - depends on ARC - help - Choosing this option will pass "-O3" to your compiler to optimize - the kernel yet more for performance. - config CC_OPTIMIZE_FOR_SIZE bool "Optimize for size (-Os)" help @@ -1733,16 +1726,17 @@ config KALLSYMS_ALL help Normally kallsyms only contains the symbols of functions for nicer OOPS messages and backtraces (i.e., symbols from the text and inittext - sections). This is sufficient for most cases. And only in very rare - cases (e.g., when a debugger is used) all symbols are required (e.g., - names of variables from the data sections, etc). + sections). This is sufficient for most cases. And only if you want to + enable kernel live patching, or other less common use cases (e.g., + when a debugger is used) all symbols are required (i.e., names of + variables from the data sections, etc). This option makes sure that all symbols are loaded into the kernel image (i.e., symbols from all sections) in cost of increased kernel size (depending on the kernel configuration, it may be 300KiB or something like this). - Say N unless you really need all symbols. + Say N unless you really need all symbols, or kernel live patching. config KALLSYMS_ABSOLUTE_PERCPU bool diff --git a/kernel/resource.c b/kernel/resource.c index 34eaee179689..4c5e80b92f2f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -489,8 +489,9 @@ int __weak page_is_ram(unsigned long pfn) } EXPORT_SYMBOL_GPL(page_is_ram); -static int __region_intersects(resource_size_t start, size_t size, - unsigned long flags, unsigned long desc) +static int __region_intersects(struct resource *parent, resource_size_t start, + size_t size, unsigned long flags, + unsigned long desc) { struct resource res; int type = 0; int other = 0; @@ -499,7 +500,7 @@ static int __region_intersects(resource_size_t start, size_t size, res.start = start; res.end = start + size - 1; - for (p = iomem_resource.child; p ; p = p->sibling) { + for (p = parent->child; p ; p = p->sibling) { bool is_type = (((p->flags & flags) == flags) && ((desc == IORES_DESC_NONE) || (desc == p->desc))); @@ -543,7 +544,7 @@ int region_intersects(resource_size_t start, size_t size, unsigned long flags, int ret; read_lock(&resource_lock); - ret = __region_intersects(start, size, flags, desc); + ret = __region_intersects(&iomem_resource, start, size, flags, desc); read_unlock(&resource_lock); return ret; @@ -891,6 +892,13 @@ void insert_resource_expand_to_fit(struct resource *root, struct resource *new) } write_unlock(&resource_lock); } +/* + * Not for general consumption, only early boot memory map parsing, PCI + * resource discovery, and late discovery of CXL resources are expected + * to use this interface. The former are built-in and only the latter, + * CXL, is a module. + */ +EXPORT_SYMBOL_NS_GPL(insert_resource_expand_to_fit, CXL); /** * remove_resource - Remove a resource in the resource tree @@ -1773,62 +1781,139 @@ void resource_list_free(struct list_head *head) } EXPORT_SYMBOL(resource_list_free); -#ifdef CONFIG_DEVICE_PRIVATE -static struct resource *__request_free_mem_region(struct device *dev, - struct resource *base, unsigned long size, const char *name) +#ifdef CONFIG_GET_FREE_REGION +#define GFR_DESCENDING (1UL << 0) +#define GFR_REQUEST_REGION (1UL << 1) +#define GFR_DEFAULT_ALIGN (1UL << PA_SECTION_SHIFT) + +static resource_size_t gfr_start(struct resource *base, resource_size_t size, + resource_size_t align, unsigned long flags) +{ + if (flags & GFR_DESCENDING) { + resource_size_t end; + + end = min_t(resource_size_t, base->end, + (1ULL << MAX_PHYSMEM_BITS) - 1); + return end - size + 1; + } + + return ALIGN(base->start, align); +} + +static bool gfr_continue(struct resource *base, resource_size_t addr, + resource_size_t size, unsigned long flags) +{ + if (flags & GFR_DESCENDING) + return addr > size && addr >= base->start; + /* + * In the ascend case be careful that the last increment by + * @size did not wrap 0. + */ + return addr > addr - size && + addr <= min_t(resource_size_t, base->end, + (1ULL << MAX_PHYSMEM_BITS) - 1); +} + +static resource_size_t gfr_next(resource_size_t addr, resource_size_t size, + unsigned long flags) { - resource_size_t end, addr; + if (flags & GFR_DESCENDING) + return addr - size; + return addr + size; +} + +static void remove_free_mem_region(void *_res) +{ + struct resource *res = _res; + + if (res->parent) + remove_resource(res); + free_resource(res); +} + +static struct resource * +get_free_mem_region(struct device *dev, struct resource *base, + resource_size_t size, const unsigned long align, + const char *name, const unsigned long desc, + const unsigned long flags) +{ + resource_size_t addr; struct resource *res; struct region_devres *dr = NULL; - size = ALIGN(size, 1UL << PA_SECTION_SHIFT); - end = min_t(unsigned long, base->end, (1UL << MAX_PHYSMEM_BITS) - 1); - addr = end - size + 1UL; + size = ALIGN(size, align); res = alloc_resource(GFP_KERNEL); if (!res) return ERR_PTR(-ENOMEM); - if (dev) { + if (dev && (flags & GFR_REQUEST_REGION)) { dr = devres_alloc(devm_region_release, sizeof(struct region_devres), GFP_KERNEL); if (!dr) { free_resource(res); return ERR_PTR(-ENOMEM); } + } else if (dev) { + if (devm_add_action_or_reset(dev, remove_free_mem_region, res)) + return ERR_PTR(-ENOMEM); } write_lock(&resource_lock); - for (; addr > size && addr >= base->start; addr -= size) { - if (__region_intersects(addr, size, 0, IORES_DESC_NONE) != - REGION_DISJOINT) + for (addr = gfr_start(base, size, align, flags); + gfr_continue(base, addr, size, flags); + addr = gfr_next(addr, size, flags)) { + if (__region_intersects(base, addr, size, 0, IORES_DESC_NONE) != + REGION_DISJOINT) continue; - if (__request_region_locked(res, &iomem_resource, addr, size, - name, 0)) - break; + if (flags & GFR_REQUEST_REGION) { + if (__request_region_locked(res, &iomem_resource, addr, + size, name, 0)) + break; - if (dev) { - dr->parent = &iomem_resource; - dr->start = addr; - dr->n = size; - devres_add(dev, dr); - } + if (dev) { + dr->parent = &iomem_resource; + dr->start = addr; + dr->n = size; + devres_add(dev, dr); + } - res->desc = IORES_DESC_DEVICE_PRIVATE_MEMORY; - write_unlock(&resource_lock); + res->desc = desc; + write_unlock(&resource_lock); + + + /* + * A driver is claiming this region so revoke any + * mappings. + */ + revoke_iomem(res); + } else { + res->start = addr; + res->end = addr + size - 1; + res->name = name; + res->desc = desc; + res->flags = IORESOURCE_MEM; + + /* + * Only succeed if the resource hosts an exclusive + * range after the insert + */ + if (__insert_resource(base, res) || res->child) + break; + + write_unlock(&resource_lock); + } - /* - * A driver is claiming this region so revoke any mappings. - */ - revoke_iomem(res); return res; } write_unlock(&resource_lock); - free_resource(res); - if (dr) + if (flags & GFR_REQUEST_REGION) { + free_resource(res); devres_free(dr); + } else if (dev) + devm_release_action(dev, remove_free_mem_region, res); return ERR_PTR(-ERANGE); } @@ -1847,18 +1932,48 @@ static struct resource *__request_free_mem_region(struct device *dev, struct resource *devm_request_free_mem_region(struct device *dev, struct resource *base, unsigned long size) { - return __request_free_mem_region(dev, base, size, dev_name(dev)); + unsigned long flags = GFR_DESCENDING | GFR_REQUEST_REGION; + + return get_free_mem_region(dev, base, size, GFR_DEFAULT_ALIGN, + dev_name(dev), + IORES_DESC_DEVICE_PRIVATE_MEMORY, flags); } EXPORT_SYMBOL_GPL(devm_request_free_mem_region); struct resource *request_free_mem_region(struct resource *base, unsigned long size, const char *name) { - return __request_free_mem_region(NULL, base, size, name); + unsigned long flags = GFR_DESCENDING | GFR_REQUEST_REGION; + + return get_free_mem_region(NULL, base, size, GFR_DEFAULT_ALIGN, name, + IORES_DESC_DEVICE_PRIVATE_MEMORY, flags); } EXPORT_SYMBOL_GPL(request_free_mem_region); -#endif /* CONFIG_DEVICE_PRIVATE */ +/** + * alloc_free_mem_region - find a free region relative to @base + * @base: resource that will parent the new resource + * @size: size in bytes of memory to allocate from @base + * @align: alignment requirements for the allocation + * @name: resource name + * + * Buses like CXL, that can dynamically instantiate new memory regions, + * need a method to allocate physical address space for those regions. + * Allocate and insert a new resource to cover a free, unclaimed by a + * descendant of @base, range in the span of @base. + */ +struct resource *alloc_free_mem_region(struct resource *base, + unsigned long size, unsigned long align, + const char *name) +{ + /* Default of ascending direction and insert resource */ + unsigned long flags = 0; + + return get_free_mem_region(NULL, base, size, align, name, + IORES_DESC_NONE, flags); +} +EXPORT_SYMBOL_NS_GPL(alloc_free_mem_region, CXL); +#endif /* CONFIG_GET_FREE_REGION */ static int __init strict_iomem(char *str) { diff --git a/mm/Kconfig b/mm/Kconfig index e59cf5fe5ce9..0331f1461f81 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -983,9 +983,14 @@ config HMM_MIRROR bool depends on MMU +config GET_FREE_REGION + depends on SPARSEMEM + bool + config DEVICE_PRIVATE bool "Unaddressable device memory (GPU memory, ...)" depends on ZONE_DEVICE + select GET_FREE_REGION help Allows creation of struct pages to represent unaddressable device diff --git a/mm/hugetlb.c b/mm/hugetlb.c index f044962ad9df..0aee2f3ae15c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1535,7 +1535,14 @@ static void __update_and_free_page(struct hstate *h, struct page *page) if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) return; - if (hugetlb_vmemmap_alloc(h, page)) { + /* + * If we don't know which subpages are hwpoisoned, we can't free + * the hugepage, so it's leaked intentionally. + */ + if (HPageRawHwpUnreliable(page)) + return; + + if (hugetlb_vmemmap_restore(h, page)) { spin_lock_irq(&hugetlb_lock); /* * If we cannot allocate vmemmap pages, just refuse to free the @@ -1547,6 +1554,13 @@ static void __update_and_free_page(struct hstate *h, struct page *page) return; } + /* + * Move PageHWPoison flag from head page to the raw error pages, + * which makes any healthy subpages reusable. + */ + if (unlikely(PageHWPoison(page))) + hugetlb_clear_page_hwpoison(page); + for (i = 0; i < pages_per_huge_page(h); i++, subpage = mem_map_next(subpage, page, i)) { subpage->flags &= ~(1 << PG_locked | 1 << PG_error | @@ -1612,7 +1626,7 @@ static DECLARE_WORK(free_hpage_work, free_hpage_workfn); static inline void flush_free_hpage_work(struct hstate *h) { - if (hugetlb_optimize_vmemmap_pages(h)) + if (hugetlb_vmemmap_optimizable(h)) flush_work(&free_hpage_work); } @@ -1734,7 +1748,7 @@ static void __prep_account_new_huge_page(struct hstate *h, int nid) static void __prep_new_huge_page(struct hstate *h, struct page *page) { - hugetlb_vmemmap_free(h, page); + hugetlb_vmemmap_optimize(h, page); INIT_LIST_HEAD(&page->lru); set_compound_page_dtor(page, HUGETLB_PAGE_DTOR); hugetlb_set_page_subpool(page, NULL); @@ -2107,17 +2121,8 @@ retry: * Attempt to allocate vmemmmap here so that we can take * appropriate action on failure. */ - rc = hugetlb_vmemmap_alloc(h, head); + rc = hugetlb_vmemmap_restore(h, head); if (!rc) { - /* - * Move PageHWPoison flag from head page to the raw - * error page, which makes any subpages rather than - * the error page reusable. - */ - if (PageHWPoison(head) && page != head) { - SetPageHWPoison(page); - ClearPageHWPoison(head); - } update_and_free_page(h, head, false); } else { spin_lock_irq(&hugetlb_lock); @@ -2432,8 +2437,7 @@ static void return_unused_surplus_pages(struct hstate *h, /* Uncommit the reservation */ h->resv_huge_pages -= unused_resv_pages; - /* Cannot return gigantic pages currently */ - if (hstate_is_gigantic(h)) + if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) goto out; /* @@ -3182,8 +3186,10 @@ static void __init report_hugepages(void) char buf[32]; string_get_size(huge_page_size(h), 1, STRING_UNITS_2, buf, 32); - pr_info("HugeTLB registered %s page size, pre-allocated %ld pages\n", + pr_info("HugeTLB: registered %s page size, pre-allocated %ld pages\n", buf, h->free_huge_pages); + pr_info("HugeTLB: %d KiB vmemmap can be freed for a %s page\n", + hugetlb_vmemmap_optimizable_size(h) / SZ_1K, buf); } } @@ -3421,7 +3427,7 @@ static int demote_free_huge_page(struct hstate *h, struct page *page) remove_hugetlb_page_for_demote(h, page, false); spin_unlock_irq(&hugetlb_lock); - rc = hugetlb_vmemmap_alloc(h, page); + rc = hugetlb_vmemmap_restore(h, page); if (rc) { /* Allocation of vmemmmap failed, we can not demote page */ spin_lock_irq(&hugetlb_lock); @@ -4111,7 +4117,6 @@ void __init hugetlb_add_hstate(unsigned int order) h->next_nid_to_free = first_memory_node; snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", huge_page_size(h)/1024); - hugetlb_vmemmap_init(h); parsed_hstate = h; } @@ -6985,10 +6990,38 @@ struct page * __weak follow_huge_pud(struct mm_struct *mm, unsigned long address, pud_t *pud, int flags) { - if (flags & (FOLL_GET | FOLL_PIN)) + struct page *page = NULL; + spinlock_t *ptl; + pte_t pte; + + if (WARN_ON_ONCE(flags & FOLL_PIN)) return NULL; - return pte_page(*(pte_t *)pud) + ((address & ~PUD_MASK) >> PAGE_SHIFT); +retry: + ptl = huge_pte_lock(hstate_sizelog(PUD_SHIFT), mm, (pte_t *)pud); + if (!pud_huge(*pud)) + goto out; + pte = huge_ptep_get((pte_t *)pud); + if (pte_present(pte)) { + page = pud_page(*pud) + ((address & ~PUD_MASK) >> PAGE_SHIFT); + if (WARN_ON_ONCE(!try_grab_page(page, flags))) { + page = NULL; + goto out; + } + } else { + if (is_hugetlb_entry_migration(pte)) { + spin_unlock(ptl); + __migration_entry_wait(mm, (pte_t *)pud, ptl); + goto retry; + } + /* + * hwpoisoned entry is treated as no_page_table in + * follow_page_mask(). + */ + } +out: + spin_unlock(ptl); + return page; } struct page * __weak diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c index 1362feb3c6c9..20f414c0379f 100644 --- a/mm/hugetlb_vmemmap.c +++ b/mm/hugetlb_vmemmap.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Optimize vmemmap pages associated with HugeTLB + * HugeTLB Vmemmap Optimization (HVO) * - * Copyright (c) 2020, Bytedance. All rights reserved. + * Copyright (c) 2020, ByteDance. All rights reserved. * * Author: Muchun Song <[email protected]> * @@ -10,84 +10,443 @@ */ #define pr_fmt(fmt) "HugeTLB: " fmt -#include <linux/memory.h> +#include <linux/pgtable.h> +#include <linux/bootmem_info.h> +#include <asm/pgalloc.h> +#include <asm/tlbflush.h> #include "hugetlb_vmemmap.h" -/* - * There are a lot of struct page structures associated with each HugeTLB page. - * For tail pages, the value of compound_head is the same. So we can reuse first - * page of head page structures. We map the virtual addresses of all the pages - * of tail page structures to the head page struct, and then free these page - * frames. Therefore, we need to reserve one pages as vmemmap areas. +/** + * struct vmemmap_remap_walk - walk vmemmap page table + * + * @remap_pte: called for each lowest-level entry (PTE). + * @nr_walked: the number of walked pte. + * @reuse_page: the page which is reused for the tail vmemmap pages. + * @reuse_addr: the virtual address of the @reuse_page page. + * @vmemmap_pages: the list head of the vmemmap pages that can be freed + * or is mapped from. */ -#define RESERVE_VMEMMAP_NR 1U -#define RESERVE_VMEMMAP_SIZE (RESERVE_VMEMMAP_NR << PAGE_SHIFT) - -enum vmemmap_optimize_mode { - VMEMMAP_OPTIMIZE_OFF, - VMEMMAP_OPTIMIZE_ON, +struct vmemmap_remap_walk { + void (*remap_pte)(pte_t *pte, unsigned long addr, + struct vmemmap_remap_walk *walk); + unsigned long nr_walked; + struct page *reuse_page; + unsigned long reuse_addr; + struct list_head *vmemmap_pages; }; -DEFINE_STATIC_KEY_MAYBE(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON, - hugetlb_optimize_vmemmap_key); -EXPORT_SYMBOL(hugetlb_optimize_vmemmap_key); +static int __split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start) +{ + pmd_t __pmd; + int i; + unsigned long addr = start; + struct page *page = pmd_page(*pmd); + pte_t *pgtable = pte_alloc_one_kernel(&init_mm); + + if (!pgtable) + return -ENOMEM; + + pmd_populate_kernel(&init_mm, &__pmd, pgtable); + + for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { + pte_t entry, *pte; + pgprot_t pgprot = PAGE_KERNEL; + + entry = mk_pte(page + i, pgprot); + pte = pte_offset_kernel(&__pmd, addr); + set_pte_at(&init_mm, addr, pte, entry); + } -static enum vmemmap_optimize_mode vmemmap_optimize_mode = - IS_ENABLED(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON); + spin_lock(&init_mm.page_table_lock); + if (likely(pmd_leaf(*pmd))) { + /* + * Higher order allocations from buddy allocator must be able to + * be treated as indepdenent small pages (as they can be freed + * individually). + */ + if (!PageReserved(page)) + split_page(page, get_order(PMD_SIZE)); + + /* Make pte visible before pmd. See comment in pmd_install(). */ + smp_wmb(); + pmd_populate_kernel(&init_mm, pmd, pgtable); + flush_tlb_kernel_range(start, start + PMD_SIZE); + } else { + pte_free_kernel(&init_mm, pgtable); + } + spin_unlock(&init_mm.page_table_lock); + + return 0; +} -static void vmemmap_optimize_mode_switch(enum vmemmap_optimize_mode to) +static int split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start) { - if (vmemmap_optimize_mode == to) - return; + int leaf; - if (to == VMEMMAP_OPTIMIZE_OFF) - static_branch_dec(&hugetlb_optimize_vmemmap_key); - else - static_branch_inc(&hugetlb_optimize_vmemmap_key); - WRITE_ONCE(vmemmap_optimize_mode, to); + spin_lock(&init_mm.page_table_lock); + leaf = pmd_leaf(*pmd); + spin_unlock(&init_mm.page_table_lock); + + if (!leaf) + return 0; + + return __split_vmemmap_huge_pmd(pmd, start); +} + +static void vmemmap_pte_range(pmd_t *pmd, unsigned long addr, + unsigned long end, + struct vmemmap_remap_walk *walk) +{ + pte_t *pte = pte_offset_kernel(pmd, addr); + + /* + * The reuse_page is found 'first' in table walk before we start + * remapping (which is calling @walk->remap_pte). + */ + if (!walk->reuse_page) { + walk->reuse_page = pte_page(*pte); + /* + * Because the reuse address is part of the range that we are + * walking, skip the reuse address range. + */ + addr += PAGE_SIZE; + pte++; + walk->nr_walked++; + } + + for (; addr != end; addr += PAGE_SIZE, pte++) { + walk->remap_pte(pte, addr, walk); + walk->nr_walked++; + } } -static int __init hugetlb_vmemmap_early_param(char *buf) +static int vmemmap_pmd_range(pud_t *pud, unsigned long addr, + unsigned long end, + struct vmemmap_remap_walk *walk) { - bool enable; - enum vmemmap_optimize_mode mode; + pmd_t *pmd; + unsigned long next; - if (kstrtobool(buf, &enable)) - return -EINVAL; + pmd = pmd_offset(pud, addr); + do { + int ret; - mode = enable ? VMEMMAP_OPTIMIZE_ON : VMEMMAP_OPTIMIZE_OFF; - vmemmap_optimize_mode_switch(mode); + ret = split_vmemmap_huge_pmd(pmd, addr & PMD_MASK); + if (ret) + return ret; + + next = pmd_addr_end(addr, end); + vmemmap_pte_range(pmd, addr, next, walk); + } while (pmd++, addr = next, addr != end); + + return 0; +} + +static int vmemmap_pud_range(p4d_t *p4d, unsigned long addr, + unsigned long end, + struct vmemmap_remap_walk *walk) +{ + pud_t *pud; + unsigned long next; + + pud = pud_offset(p4d, addr); + do { + int ret; + + next = pud_addr_end(addr, end); + ret = vmemmap_pmd_range(pud, addr, next, walk); + if (ret) + return ret; + } while (pud++, addr = next, addr != end); + + return 0; +} + +static int vmemmap_p4d_range(pgd_t *pgd, unsigned long addr, + unsigned long end, + struct vmemmap_remap_walk *walk) +{ + p4d_t *p4d; + unsigned long next; + + p4d = p4d_offset(pgd, addr); + do { + int ret; + + next = p4d_addr_end(addr, end); + ret = vmemmap_pud_range(p4d, addr, next, walk); + if (ret) + return ret; + } while (p4d++, addr = next, addr != end); + + return 0; +} + +static int vmemmap_remap_range(unsigned long start, unsigned long end, + struct vmemmap_remap_walk *walk) +{ + unsigned long addr = start; + unsigned long next; + pgd_t *pgd; + + VM_BUG_ON(!PAGE_ALIGNED(start)); + VM_BUG_ON(!PAGE_ALIGNED(end)); + + pgd = pgd_offset_k(addr); + do { + int ret; + + next = pgd_addr_end(addr, end); + ret = vmemmap_p4d_range(pgd, addr, next, walk); + if (ret) + return ret; + } while (pgd++, addr = next, addr != end); + + /* + * We only change the mapping of the vmemmap virtual address range + * [@start + PAGE_SIZE, end), so we only need to flush the TLB which + * belongs to the range. + */ + flush_tlb_kernel_range(start + PAGE_SIZE, end); return 0; } -early_param("hugetlb_free_vmemmap", hugetlb_vmemmap_early_param); /* - * Previously discarded vmemmap pages will be allocated and remapping - * after this function returns zero. + * Free a vmemmap page. A vmemmap page can be allocated from the memblock + * allocator or buddy allocator. If the PG_reserved flag is set, it means + * that it allocated from the memblock allocator, just free it via the + * free_bootmem_page(). Otherwise, use __free_page(). */ -int hugetlb_vmemmap_alloc(struct hstate *h, struct page *head) +static inline void free_vmemmap_page(struct page *page) +{ + if (PageReserved(page)) + free_bootmem_page(page); + else + __free_page(page); +} + +/* Free a list of the vmemmap pages */ +static void free_vmemmap_page_list(struct list_head *list) +{ + struct page *page, *next; + + list_for_each_entry_safe(page, next, list, lru) { + list_del(&page->lru); + free_vmemmap_page(page); + } +} + +static void vmemmap_remap_pte(pte_t *pte, unsigned long addr, + struct vmemmap_remap_walk *walk) +{ + /* + * Remap the tail pages as read-only to catch illegal write operation + * to the tail pages. + */ + pgprot_t pgprot = PAGE_KERNEL_RO; + pte_t entry = mk_pte(walk->reuse_page, pgprot); + struct page *page = pte_page(*pte); + + list_add_tail(&page->lru, walk->vmemmap_pages); + set_pte_at(&init_mm, addr, pte, entry); +} + +/* + * How many struct page structs need to be reset. When we reuse the head + * struct page, the special metadata (e.g. page->flags or page->mapping) + * cannot copy to the tail struct page structs. The invalid value will be + * checked in the free_tail_pages_check(). In order to avoid the message + * of "corrupted mapping in tail page". We need to reset at least 3 (one + * head struct page struct and two tail struct page structs) struct page + * structs. + */ +#define NR_RESET_STRUCT_PAGE 3 + +static inline void reset_struct_pages(struct page *start) +{ + int i; + struct page *from = start + NR_RESET_STRUCT_PAGE; + + for (i = 0; i < NR_RESET_STRUCT_PAGE; i++) + memcpy(start + i, from, sizeof(*from)); +} + +static void vmemmap_restore_pte(pte_t *pte, unsigned long addr, + struct vmemmap_remap_walk *walk) +{ + pgprot_t pgprot = PAGE_KERNEL; + struct page *page; + void *to; + + BUG_ON(pte_page(*pte) != walk->reuse_page); + + page = list_first_entry(walk->vmemmap_pages, struct page, lru); + list_del(&page->lru); + to = page_to_virt(page); + copy_page(to, (void *)walk->reuse_addr); + reset_struct_pages(to); + + set_pte_at(&init_mm, addr, pte, mk_pte(page, pgprot)); +} + +/** + * vmemmap_remap_free - remap the vmemmap virtual address range [@start, @end) + * to the page which @reuse is mapped to, then free vmemmap + * which the range are mapped to. + * @start: start address of the vmemmap virtual address range that we want + * to remap. + * @end: end address of the vmemmap virtual address range that we want to + * remap. + * @reuse: reuse address. + * + * Return: %0 on success, negative error code otherwise. + */ +static int vmemmap_remap_free(unsigned long start, unsigned long end, + unsigned long reuse) +{ + int ret; + LIST_HEAD(vmemmap_pages); + struct vmemmap_remap_walk walk = { + .remap_pte = vmemmap_remap_pte, + .reuse_addr = reuse, + .vmemmap_pages = &vmemmap_pages, + }; + + /* + * In order to make remapping routine most efficient for the huge pages, + * the routine of vmemmap page table walking has the following rules + * (see more details from the vmemmap_pte_range()): + * + * - The range [@start, @end) and the range [@reuse, @reuse + PAGE_SIZE) + * should be continuous. + * - The @reuse address is part of the range [@reuse, @end) that we are + * walking which is passed to vmemmap_remap_range(). + * - The @reuse address is the first in the complete range. + * + * So we need to make sure that @start and @reuse meet the above rules. + */ + BUG_ON(start - reuse != PAGE_SIZE); + + mmap_read_lock(&init_mm); + ret = vmemmap_remap_range(reuse, end, &walk); + if (ret && walk.nr_walked) { + end = reuse + walk.nr_walked * PAGE_SIZE; + /* + * vmemmap_pages contains pages from the previous + * vmemmap_remap_range call which failed. These + * are pages which were removed from the vmemmap. + * They will be restored in the following call. + */ + walk = (struct vmemmap_remap_walk) { + .remap_pte = vmemmap_restore_pte, + .reuse_addr = reuse, + .vmemmap_pages = &vmemmap_pages, + }; + + vmemmap_remap_range(reuse, end, &walk); + } + mmap_read_unlock(&init_mm); + + free_vmemmap_page_list(&vmemmap_pages); + + return ret; +} + +static int alloc_vmemmap_page_list(unsigned long start, unsigned long end, + gfp_t gfp_mask, struct list_head *list) +{ + unsigned long nr_pages = (end - start) >> PAGE_SHIFT; + int nid = page_to_nid((struct page *)start); + struct page *page, *next; + + while (nr_pages--) { + page = alloc_pages_node(nid, gfp_mask, 0); + if (!page) + goto out; + list_add_tail(&page->lru, list); + } + + return 0; +out: + list_for_each_entry_safe(page, next, list, lru) + __free_pages(page, 0); + return -ENOMEM; +} + +/** + * vmemmap_remap_alloc - remap the vmemmap virtual address range [@start, end) + * to the page which is from the @vmemmap_pages + * respectively. + * @start: start address of the vmemmap virtual address range that we want + * to remap. + * @end: end address of the vmemmap virtual address range that we want to + * remap. + * @reuse: reuse address. + * @gfp_mask: GFP flag for allocating vmemmap pages. + * + * Return: %0 on success, negative error code otherwise. + */ +static int vmemmap_remap_alloc(unsigned long start, unsigned long end, + unsigned long reuse, gfp_t gfp_mask) +{ + LIST_HEAD(vmemmap_pages); + struct vmemmap_remap_walk walk = { + .remap_pte = vmemmap_restore_pte, + .reuse_addr = reuse, + .vmemmap_pages = &vmemmap_pages, + }; + + /* See the comment in the vmemmap_remap_free(). */ + BUG_ON(start - reuse != PAGE_SIZE); + + if (alloc_vmemmap_page_list(start, end, gfp_mask, &vmemmap_pages)) + return -ENOMEM; + + mmap_read_lock(&init_mm); + vmemmap_remap_range(reuse, end, &walk); + mmap_read_unlock(&init_mm); + + return 0; +} + +DEFINE_STATIC_KEY_FALSE(hugetlb_optimize_vmemmap_key); +EXPORT_SYMBOL(hugetlb_optimize_vmemmap_key); + +static bool vmemmap_optimize_enabled = IS_ENABLED(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON); +core_param(hugetlb_free_vmemmap, vmemmap_optimize_enabled, bool, 0); + +/** + * hugetlb_vmemmap_restore - restore previously optimized (by + * hugetlb_vmemmap_optimize()) vmemmap pages which + * will be reallocated and remapped. + * @h: struct hstate. + * @head: the head page whose vmemmap pages will be restored. + * + * Return: %0 if @head's vmemmap pages have been reallocated and remapped, + * negative error code otherwise. + */ +int hugetlb_vmemmap_restore(const struct hstate *h, struct page *head) { int ret; - unsigned long vmemmap_addr = (unsigned long)head; - unsigned long vmemmap_end, vmemmap_reuse, vmemmap_pages; + unsigned long vmemmap_start = (unsigned long)head, vmemmap_end; + unsigned long vmemmap_reuse; if (!HPageVmemmapOptimized(head)) return 0; - vmemmap_addr += RESERVE_VMEMMAP_SIZE; - vmemmap_pages = hugetlb_optimize_vmemmap_pages(h); - vmemmap_end = vmemmap_addr + (vmemmap_pages << PAGE_SHIFT); - vmemmap_reuse = vmemmap_addr - PAGE_SIZE; + vmemmap_end = vmemmap_start + hugetlb_vmemmap_size(h); + vmemmap_reuse = vmemmap_start; + vmemmap_start += HUGETLB_VMEMMAP_RESERVE_SIZE; /* - * The pages which the vmemmap virtual address range [@vmemmap_addr, + * The pages which the vmemmap virtual address range [@vmemmap_start, * @vmemmap_end) are mapped to are freed to the buddy allocator, and * the range is mapped to the page which @vmemmap_reuse is mapped to. * When a HugeTLB page is freed to the buddy allocator, previously * discarded vmemmap pages must be allocated and remapping. */ - ret = vmemmap_remap_alloc(vmemmap_addr, vmemmap_end, vmemmap_reuse, + ret = vmemmap_remap_alloc(vmemmap_start, vmemmap_end, vmemmap_reuse, GFP_KERNEL | __GFP_NORETRY | __GFP_THISNODE); if (!ret) { ClearHPageVmemmapOptimized(head); @@ -97,11 +456,14 @@ int hugetlb_vmemmap_alloc(struct hstate *h, struct page *head) return ret; } -static unsigned int vmemmap_optimizable_pages(struct hstate *h, - struct page *head) +/* Return true iff a HugeTLB whose vmemmap should and can be optimized. */ +static bool vmemmap_should_optimize(const struct hstate *h, const struct page *head) { - if (READ_ONCE(vmemmap_optimize_mode) == VMEMMAP_OPTIMIZE_OFF) - return 0; + if (!READ_ONCE(vmemmap_optimize_enabled)) + return false; + + if (!hugetlb_vmemmap_optimizable(h)) + return false; if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) { pmd_t *pmdp, pmd; @@ -144,118 +506,73 @@ static unsigned int vmemmap_optimizable_pages(struct hstate *h, * +-------------------------------------------+ */ if (PageVmemmapSelfHosted(vmemmap_page)) - return 0; + return false; } - return hugetlb_optimize_vmemmap_pages(h); + return true; } -void hugetlb_vmemmap_free(struct hstate *h, struct page *head) +/** + * hugetlb_vmemmap_optimize - optimize @head page's vmemmap pages. + * @h: struct hstate. + * @head: the head page whose vmemmap pages will be optimized. + * + * This function only tries to optimize @head's vmemmap pages and does not + * guarantee that the optimization will succeed after it returns. The caller + * can use HPageVmemmapOptimized(@head) to detect if @head's vmemmap pages + * have been optimized. + */ +void hugetlb_vmemmap_optimize(const struct hstate *h, struct page *head) { - unsigned long vmemmap_addr = (unsigned long)head; - unsigned long vmemmap_end, vmemmap_reuse, vmemmap_pages; + unsigned long vmemmap_start = (unsigned long)head, vmemmap_end; + unsigned long vmemmap_reuse; - vmemmap_pages = vmemmap_optimizable_pages(h, head); - if (!vmemmap_pages) + if (!vmemmap_should_optimize(h, head)) return; static_branch_inc(&hugetlb_optimize_vmemmap_key); - vmemmap_addr += RESERVE_VMEMMAP_SIZE; - vmemmap_end = vmemmap_addr + (vmemmap_pages << PAGE_SHIFT); - vmemmap_reuse = vmemmap_addr - PAGE_SIZE; + vmemmap_end = vmemmap_start + hugetlb_vmemmap_size(h); + vmemmap_reuse = vmemmap_start; + vmemmap_start += HUGETLB_VMEMMAP_RESERVE_SIZE; /* - * Remap the vmemmap virtual address range [@vmemmap_addr, @vmemmap_end) + * Remap the vmemmap virtual address range [@vmemmap_start, @vmemmap_end) * to the page which @vmemmap_reuse is mapped to, then free the pages - * which the range [@vmemmap_addr, @vmemmap_end] is mapped to. + * which the range [@vmemmap_start, @vmemmap_end] is mapped to. */ - if (vmemmap_remap_free(vmemmap_addr, vmemmap_end, vmemmap_reuse)) + if (vmemmap_remap_free(vmemmap_start, vmemmap_end, vmemmap_reuse)) static_branch_dec(&hugetlb_optimize_vmemmap_key); else SetHPageVmemmapOptimized(head); } -void __init hugetlb_vmemmap_init(struct hstate *h) -{ - unsigned int nr_pages = pages_per_huge_page(h); - unsigned int vmemmap_pages; - - /* - * There are only (RESERVE_VMEMMAP_SIZE / sizeof(struct page)) struct - * page structs that can be used when CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP, - * so add a BUILD_BUG_ON to catch invalid usage of the tail struct page. - */ - BUILD_BUG_ON(__NR_USED_SUBPAGE >= - RESERVE_VMEMMAP_SIZE / sizeof(struct page)); - - if (!is_power_of_2(sizeof(struct page))) { - pr_warn_once("cannot optimize vmemmap pages because \"struct page\" crosses page boundaries\n"); - static_branch_disable(&hugetlb_optimize_vmemmap_key); - return; - } - - vmemmap_pages = (nr_pages * sizeof(struct page)) >> PAGE_SHIFT; - /* - * The head page is not to be freed to buddy allocator, the other tail - * pages will map to the head page, so they can be freed. - * - * Could RESERVE_VMEMMAP_NR be greater than @vmemmap_pages? It is true - * on some architectures (e.g. aarch64). See Documentation/arm64/ - * hugetlbpage.rst for more details. - */ - if (likely(vmemmap_pages > RESERVE_VMEMMAP_NR)) - h->optimize_vmemmap_pages = vmemmap_pages - RESERVE_VMEMMAP_NR; - - pr_info("can optimize %d vmemmap pages for %s\n", - h->optimize_vmemmap_pages, h->name); -} - -#ifdef CONFIG_PROC_SYSCTL -static int hugetlb_optimize_vmemmap_handler(struct ctl_table *table, int write, - void *buffer, size_t *length, - loff_t *ppos) -{ - int ret; - enum vmemmap_optimize_mode mode; - static DEFINE_MUTEX(sysctl_mutex); - - if (write && !capable(CAP_SYS_ADMIN)) - return -EPERM; - - mutex_lock(&sysctl_mutex); - mode = vmemmap_optimize_mode; - table->data = &mode; - ret = proc_dointvec_minmax(table, write, buffer, length, ppos); - if (write && !ret) - vmemmap_optimize_mode_switch(mode); - mutex_unlock(&sysctl_mutex); - - return ret; -} - static struct ctl_table hugetlb_vmemmap_sysctls[] = { { .procname = "hugetlb_optimize_vmemmap", - .maxlen = sizeof(enum vmemmap_optimize_mode), + .data = &vmemmap_optimize_enabled, + .maxlen = sizeof(int), .mode = 0644, - .proc_handler = hugetlb_optimize_vmemmap_handler, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, + .proc_handler = proc_dobool, }, { } }; -static __init int hugetlb_vmemmap_sysctls_init(void) +static int __init hugetlb_vmemmap_init(void) { - /* - * If "struct page" crosses page boundaries, the vmemmap pages cannot - * be optimized. - */ - if (is_power_of_2(sizeof(struct page))) - register_sysctl_init("vm", hugetlb_vmemmap_sysctls); - + /* HUGETLB_VMEMMAP_RESERVE_SIZE should cover all used struct pages */ + BUILD_BUG_ON(__NR_USED_SUBPAGE * sizeof(struct page) > HUGETLB_VMEMMAP_RESERVE_SIZE); + + if (IS_ENABLED(CONFIG_PROC_SYSCTL)) { + const struct hstate *h; + + for_each_hstate(h) { + if (hugetlb_vmemmap_optimizable(h)) { + register_sysctl_init("vm", hugetlb_vmemmap_sysctls); + break; + } + } + } return 0; } -late_initcall(hugetlb_vmemmap_sysctls_init); -#endif /* CONFIG_PROC_SYSCTL */ +late_initcall(hugetlb_vmemmap_init); diff --git a/mm/hugetlb_vmemmap.h b/mm/hugetlb_vmemmap.h index 109b0a53b6fe..25bd0e002431 100644 --- a/mm/hugetlb_vmemmap.h +++ b/mm/hugetlb_vmemmap.h @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Optimize vmemmap pages associated with HugeTLB + * HugeTLB Vmemmap Optimization (HVO) * - * Copyright (c) 2020, Bytedance. All rights reserved. + * Copyright (c) 2020, ByteDance. All rights reserved. * * Author: Muchun Song <[email protected]> */ @@ -11,35 +11,50 @@ #include <linux/hugetlb.h> #ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP -int hugetlb_vmemmap_alloc(struct hstate *h, struct page *head); -void hugetlb_vmemmap_free(struct hstate *h, struct page *head); -void hugetlb_vmemmap_init(struct hstate *h); +int hugetlb_vmemmap_restore(const struct hstate *h, struct page *head); +void hugetlb_vmemmap_optimize(const struct hstate *h, struct page *head); /* - * How many vmemmap pages associated with a HugeTLB page that can be - * optimized and freed to the buddy allocator. + * Reserve one vmemmap page, all vmemmap addresses are mapped to it. See + * Documentation/vm/vmemmap_dedup.rst. */ -static inline unsigned int hugetlb_optimize_vmemmap_pages(struct hstate *h) +#define HUGETLB_VMEMMAP_RESERVE_SIZE PAGE_SIZE + +static inline unsigned int hugetlb_vmemmap_size(const struct hstate *h) { - return h->optimize_vmemmap_pages; + return pages_per_huge_page(h) * sizeof(struct page); +} + +/* + * Return how many vmemmap size associated with a HugeTLB page that can be + * optimized and can be freed to the buddy allocator. + */ +static inline unsigned int hugetlb_vmemmap_optimizable_size(const struct hstate *h) +{ + int size = hugetlb_vmemmap_size(h) - HUGETLB_VMEMMAP_RESERVE_SIZE; + + if (!is_power_of_2(sizeof(struct page))) + return 0; + return size > 0 ? size : 0; } #else -static inline int hugetlb_vmemmap_alloc(struct hstate *h, struct page *head) +static inline int hugetlb_vmemmap_restore(const struct hstate *h, struct page *head) { return 0; } -static inline void hugetlb_vmemmap_free(struct hstate *h, struct page *head) +static inline void hugetlb_vmemmap_optimize(const struct hstate *h, struct page *head) { } -static inline void hugetlb_vmemmap_init(struct hstate *h) +static inline unsigned int hugetlb_vmemmap_optimizable_size(const struct hstate *h) { + return 0; } +#endif /* CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP */ -static inline unsigned int hugetlb_optimize_vmemmap_pages(struct hstate *h) +static inline bool hugetlb_vmemmap_optimizable(const struct hstate *h) { - return 0; + return hugetlb_vmemmap_optimizable_size(h) != 0; } -#endif /* CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP */ #endif /* _LINUX_HUGETLB_VMEMMAP_H */ diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 9a7a228ad04a..14439806b5ef 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -74,7 +74,13 @@ atomic_long_t num_poisoned_pages __read_mostly = ATOMIC_LONG_INIT(0); static bool hw_memory_failure __read_mostly = false; -static bool __page_handle_poison(struct page *page) +/* + * Return values: + * 1: the page is dissolved (if needed) and taken off from buddy, + * 0: the page is dissolved (if needed) and not taken off from buddy, + * < 0: failed to dissolve. + */ +static int __page_handle_poison(struct page *page) { int ret; @@ -84,7 +90,7 @@ static bool __page_handle_poison(struct page *page) ret = take_page_off_buddy(page); zone_pcp_enable(page_zone(page)); - return ret > 0; + return ret; } static bool page_handle_poison(struct page *page, bool hugepage_or_freepage, bool release) @@ -94,7 +100,7 @@ static bool page_handle_poison(struct page *page, bool hugepage_or_freepage, boo * Doing this check for free pages is also fine since dissolve_free_huge_page * returns 0 for non-hugetlb pages as well. */ - if (!__page_handle_poison(page)) + if (__page_handle_poison(page) <= 0) /* * We could fail to take off the target page from buddy * for example due to racy page allocation, but that's @@ -762,7 +768,6 @@ static const char * const action_page_types[] = { [MF_MSG_DIFFERENT_COMPOUND] = "different compound page after locking", [MF_MSG_HUGE] = "huge page", [MF_MSG_FREE_HUGE] = "free huge page", - [MF_MSG_NON_PMD_HUGE] = "non-pmd-sized huge page", [MF_MSG_UNMAP_FAILED] = "unmapping failed page", [MF_MSG_DIRTY_SWAPCACHE] = "dirty swapcache page", [MF_MSG_CLEAN_SWAPCACHE] = "clean swapcache page", @@ -1078,7 +1083,6 @@ static int me_huge_page(struct page_state *ps, struct page *p) res = truncate_error_page(hpage, page_to_pfn(p), mapping); unlock_page(hpage); } else { - res = MF_FAILED; unlock_page(hpage); /* * migration entry prevents later access on error hugepage, @@ -1086,9 +1090,11 @@ static int me_huge_page(struct page_state *ps, struct page *p) * subpages. */ put_page(hpage); - if (__page_handle_poison(p)) { + if (__page_handle_poison(p) >= 0) { page_ref_inc(p); res = MF_RECOVERED; + } else { + res = MF_FAILED; } } @@ -1662,6 +1668,113 @@ unlock: EXPORT_SYMBOL_GPL(mf_dax_kill_procs); #endif /* CONFIG_FS_DAX */ +#ifdef CONFIG_HUGETLB_PAGE +/* + * Struct raw_hwp_page represents information about "raw error page", + * constructing singly linked list originated from ->private field of + * SUBPAGE_INDEX_HWPOISON-th tail page. + */ +struct raw_hwp_page { + struct llist_node node; + struct page *page; +}; + +static inline struct llist_head *raw_hwp_list_head(struct page *hpage) +{ + return (struct llist_head *)&page_private(hpage + SUBPAGE_INDEX_HWPOISON); +} + +static unsigned long __free_raw_hwp_pages(struct page *hpage, bool move_flag) +{ + struct llist_head *head; + struct llist_node *t, *tnode; + unsigned long count = 0; + + head = raw_hwp_list_head(hpage); + llist_for_each_safe(tnode, t, head->first) { + struct raw_hwp_page *p = container_of(tnode, struct raw_hwp_page, node); + + if (move_flag) + SetPageHWPoison(p->page); + kfree(p); + count++; + } + llist_del_all(head); + return count; +} + +static int hugetlb_set_page_hwpoison(struct page *hpage, struct page *page) +{ + struct llist_head *head; + struct raw_hwp_page *raw_hwp; + struct llist_node *t, *tnode; + int ret = TestSetPageHWPoison(hpage) ? -EHWPOISON : 0; + + /* + * Once the hwpoison hugepage has lost reliable raw error info, + * there is little meaning to keep additional error info precisely, + * so skip to add additional raw error info. + */ + if (HPageRawHwpUnreliable(hpage)) + return -EHWPOISON; + head = raw_hwp_list_head(hpage); + llist_for_each_safe(tnode, t, head->first) { + struct raw_hwp_page *p = container_of(tnode, struct raw_hwp_page, node); + + if (p->page == page) + return -EHWPOISON; + } + + raw_hwp = kmalloc(sizeof(struct raw_hwp_page), GFP_ATOMIC); + if (raw_hwp) { + raw_hwp->page = page; + llist_add(&raw_hwp->node, head); + /* the first error event will be counted in action_result(). */ + if (ret) + num_poisoned_pages_inc(); + } else { + /* + * Failed to save raw error info. We no longer trace all + * hwpoisoned subpages, and we need refuse to free/dissolve + * this hwpoisoned hugepage. + */ + SetHPageRawHwpUnreliable(hpage); + /* + * Once HPageRawHwpUnreliable is set, raw_hwp_page is not + * used any more, so free it. + */ + __free_raw_hwp_pages(hpage, false); + } + return ret; +} + +static unsigned long free_raw_hwp_pages(struct page *hpage, bool move_flag) +{ + /* + * HPageVmemmapOptimized hugepages can't be freed because struct + * pages for tail pages are required but they don't exist. + */ + if (move_flag && HPageVmemmapOptimized(hpage)) + return 0; + + /* + * HPageRawHwpUnreliable hugepages shouldn't be unpoisoned by + * definition. + */ + if (HPageRawHwpUnreliable(hpage)) + return 0; + + return __free_raw_hwp_pages(hpage, move_flag); +} + +void hugetlb_clear_page_hwpoison(struct page *hpage) +{ + if (HPageRawHwpUnreliable(hpage)) + return; + ClearPageHWPoison(hpage); + free_raw_hwp_pages(hpage, true); +} + /* * Called from hugetlb code with hugetlb_lock held. * @@ -1693,10 +1806,11 @@ int __get_huge_page_for_hwpoison(unsigned long pfn, int flags) count_increased = true; } else { ret = -EBUSY; - goto out; + if (!(flags & MF_NO_RETRY)) + goto out; } - if (TestSetPageHWPoison(head)) { + if (hugetlb_set_page_hwpoison(head, page)) { ret = -EHWPOISON; goto out; } @@ -1708,7 +1822,6 @@ out: return ret; } -#ifdef CONFIG_HUGETLB_PAGE /* * Taking refcount of hugetlb pages needs extra care about race conditions * with basic operations like hugepage allocation/free/demotion. @@ -1721,7 +1834,6 @@ static int try_memory_failure_hugetlb(unsigned long pfn, int flags, int *hugetlb struct page *p = pfn_to_page(pfn); struct page *head; unsigned long page_flags; - bool retry = true; *hugetlb = 1; retry: @@ -1737,8 +1849,8 @@ retry: } return res; } else if (res == -EBUSY) { - if (retry) { - retry = false; + if (!(flags & MF_NO_RETRY)) { + flags |= MF_NO_RETRY; goto retry; } action_result(pfn, MF_MSG_UNKNOWN, MF_IGNORED); @@ -1749,7 +1861,7 @@ retry: lock_page(head); if (hwpoison_filter(p)) { - ClearPageHWPoison(head); + hugetlb_clear_page_hwpoison(head); res = -EOPNOTSUPP; goto out; } @@ -1760,10 +1872,11 @@ retry: */ if (res == 0) { unlock_page(head); - res = MF_FAILED; - if (__page_handle_poison(p)) { + if (__page_handle_poison(p) >= 0) { page_ref_inc(p); res = MF_RECOVERED; + } else { + res = MF_FAILED; } action_result(pfn, MF_MSG_FREE_HUGE, res); return res == MF_RECOVERED ? 0 : -EBUSY; @@ -1771,21 +1884,6 @@ retry: page_flags = head->flags; - /* - * TODO: hwpoison for pud-sized hugetlb doesn't work right now, so - * simply disable it. In order to make it work properly, we need - * make sure that: - * - conversion of a pud that maps an error hugetlb into hwpoison - * entry properly works, and - * - other mm code walking over page table is aware of pud-aligned - * hwpoison entries. - */ - if (huge_page_size(page_hstate(head)) > PMD_SIZE) { - action_result(pfn, MF_MSG_NON_PMD_HUGE, MF_IGNORED); - res = -EBUSY; - goto out; - } - if (!hwpoison_user_mappings(p, pfn, flags, head)) { action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED); res = -EBUSY; @@ -1804,6 +1902,10 @@ static inline int try_memory_failure_hugetlb(unsigned long pfn, int flags, int * return 0; } +static inline unsigned long free_raw_hwp_pages(struct page *hpage, bool flag) +{ + return 0; +} #endif /* CONFIG_HUGETLB_PAGE */ static int memory_failure_dev_pagemap(unsigned long pfn, int flags, @@ -2209,6 +2311,7 @@ int unpoison_memory(unsigned long pfn) struct page *p; int ret = -EBUSY; int freeit = 0; + unsigned long count = 1; static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); @@ -2256,6 +2359,13 @@ int unpoison_memory(unsigned long pfn) ret = get_hwpoison_page(p, MF_UNPOISON); if (!ret) { + if (PageHuge(p)) { + count = free_raw_hwp_pages(page, false); + if (count == 0) { + ret = -EBUSY; + goto unlock_mutex; + } + } ret = TestClearPageHWPoison(page) ? 0 : -EBUSY; } else if (ret < 0) { if (ret == -EHWPOISON) { @@ -2264,6 +2374,13 @@ int unpoison_memory(unsigned long pfn) unpoison_pr_info("Unpoison: failed to grab page %#lx\n", pfn, &unpoison_rs); } else { + if (PageHuge(p)) { + count = free_raw_hwp_pages(page, false); + if (count == 0) { + ret = -EBUSY; + goto unlock_mutex; + } + } freeit = !!TestClearPageHWPoison(p); put_page(page); @@ -2276,7 +2393,7 @@ int unpoison_memory(unsigned long pfn) unlock_mutex: mutex_unlock(&mf_mutex); if (!ret || freeit) { - num_poisoned_pages_dec(); + num_poisoned_pages_sub(count); unpoison_pr_info("Unpoison: Software-unpoisoned page %#lx\n", page_to_pfn(p), &unpoison_rs); } diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 5f0ed4717ed0..46ae542118c0 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -27,408 +27,9 @@ #include <linux/spinlock.h> #include <linux/vmalloc.h> #include <linux/sched.h> -#include <linux/pgtable.h> -#include <linux/bootmem_info.h> #include <asm/dma.h> #include <asm/pgalloc.h> -#include <asm/tlbflush.h> - -#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP -/** - * struct vmemmap_remap_walk - walk vmemmap page table - * - * @remap_pte: called for each lowest-level entry (PTE). - * @nr_walked: the number of walked pte. - * @reuse_page: the page which is reused for the tail vmemmap pages. - * @reuse_addr: the virtual address of the @reuse_page page. - * @vmemmap_pages: the list head of the vmemmap pages that can be freed - * or is mapped from. - */ -struct vmemmap_remap_walk { - void (*remap_pte)(pte_t *pte, unsigned long addr, - struct vmemmap_remap_walk *walk); - unsigned long nr_walked; - struct page *reuse_page; - unsigned long reuse_addr; - struct list_head *vmemmap_pages; -}; - -static int __split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start) -{ - pmd_t __pmd; - int i; - unsigned long addr = start; - struct page *page = pmd_page(*pmd); - pte_t *pgtable = pte_alloc_one_kernel(&init_mm); - - if (!pgtable) - return -ENOMEM; - - pmd_populate_kernel(&init_mm, &__pmd, pgtable); - - for (i = 0; i < PMD_SIZE / PAGE_SIZE; i++, addr += PAGE_SIZE) { - pte_t entry, *pte; - pgprot_t pgprot = PAGE_KERNEL; - - entry = mk_pte(page + i, pgprot); - pte = pte_offset_kernel(&__pmd, addr); - set_pte_at(&init_mm, addr, pte, entry); - } - - spin_lock(&init_mm.page_table_lock); - if (likely(pmd_leaf(*pmd))) { - /* - * Higher order allocations from buddy allocator must be able to - * be treated as indepdenent small pages (as they can be freed - * individually). - */ - if (!PageReserved(page)) - split_page(page, get_order(PMD_SIZE)); - - /* Make pte visible before pmd. See comment in pmd_install(). */ - smp_wmb(); - pmd_populate_kernel(&init_mm, pmd, pgtable); - flush_tlb_kernel_range(start, start + PMD_SIZE); - } else { - pte_free_kernel(&init_mm, pgtable); - } - spin_unlock(&init_mm.page_table_lock); - - return 0; -} - -static int split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start) -{ - int leaf; - - spin_lock(&init_mm.page_table_lock); - leaf = pmd_leaf(*pmd); - spin_unlock(&init_mm.page_table_lock); - - if (!leaf) - return 0; - - return __split_vmemmap_huge_pmd(pmd, start); -} - -static void vmemmap_pte_range(pmd_t *pmd, unsigned long addr, - unsigned long end, - struct vmemmap_remap_walk *walk) -{ - pte_t *pte = pte_offset_kernel(pmd, addr); - - /* - * The reuse_page is found 'first' in table walk before we start - * remapping (which is calling @walk->remap_pte). - */ - if (!walk->reuse_page) { - walk->reuse_page = pte_page(*pte); - /* - * Because the reuse address is part of the range that we are - * walking, skip the reuse address range. - */ - addr += PAGE_SIZE; - pte++; - walk->nr_walked++; - } - - for (; addr != end; addr += PAGE_SIZE, pte++) { - walk->remap_pte(pte, addr, walk); - walk->nr_walked++; - } -} - -static int vmemmap_pmd_range(pud_t *pud, unsigned long addr, - unsigned long end, - struct vmemmap_remap_walk *walk) -{ - pmd_t *pmd; - unsigned long next; - - pmd = pmd_offset(pud, addr); - do { - int ret; - - ret = split_vmemmap_huge_pmd(pmd, addr & PMD_MASK); - if (ret) - return ret; - - next = pmd_addr_end(addr, end); - vmemmap_pte_range(pmd, addr, next, walk); - } while (pmd++, addr = next, addr != end); - - return 0; -} - -static int vmemmap_pud_range(p4d_t *p4d, unsigned long addr, - unsigned long end, - struct vmemmap_remap_walk *walk) -{ - pud_t *pud; - unsigned long next; - - pud = pud_offset(p4d, addr); - do { - int ret; - - next = pud_addr_end(addr, end); - ret = vmemmap_pmd_range(pud, addr, next, walk); - if (ret) - return ret; - } while (pud++, addr = next, addr != end); - - return 0; -} - -static int vmemmap_p4d_range(pgd_t *pgd, unsigned long addr, - unsigned long end, - struct vmemmap_remap_walk *walk) -{ - p4d_t *p4d; - unsigned long next; - - p4d = p4d_offset(pgd, addr); - do { - int ret; - - next = p4d_addr_end(addr, end); - ret = vmemmap_pud_range(p4d, addr, next, walk); - if (ret) - return ret; - } while (p4d++, addr = next, addr != end); - - return 0; -} - -static int vmemmap_remap_range(unsigned long start, unsigned long end, - struct vmemmap_remap_walk *walk) -{ - unsigned long addr = start; - unsigned long next; - pgd_t *pgd; - - VM_BUG_ON(!PAGE_ALIGNED(start)); - VM_BUG_ON(!PAGE_ALIGNED(end)); - - pgd = pgd_offset_k(addr); - do { - int ret; - - next = pgd_addr_end(addr, end); - ret = vmemmap_p4d_range(pgd, addr, next, walk); - if (ret) - return ret; - } while (pgd++, addr = next, addr != end); - - /* - * We only change the mapping of the vmemmap virtual address range - * [@start + PAGE_SIZE, end), so we only need to flush the TLB which - * belongs to the range. - */ - flush_tlb_kernel_range(start + PAGE_SIZE, end); - - return 0; -} - -/* - * Free a vmemmap page. A vmemmap page can be allocated from the memblock - * allocator or buddy allocator. If the PG_reserved flag is set, it means - * that it allocated from the memblock allocator, just free it via the - * free_bootmem_page(). Otherwise, use __free_page(). - */ -static inline void free_vmemmap_page(struct page *page) -{ - if (PageReserved(page)) - free_bootmem_page(page); - else - __free_page(page); -} - -/* Free a list of the vmemmap pages */ -static void free_vmemmap_page_list(struct list_head *list) -{ - struct page *page, *next; - - list_for_each_entry_safe(page, next, list, lru) { - list_del(&page->lru); - free_vmemmap_page(page); - } -} - -static void vmemmap_remap_pte(pte_t *pte, unsigned long addr, - struct vmemmap_remap_walk *walk) -{ - /* - * Remap the tail pages as read-only to catch illegal write operation - * to the tail pages. - */ - pgprot_t pgprot = PAGE_KERNEL_RO; - pte_t entry = mk_pte(walk->reuse_page, pgprot); - struct page *page = pte_page(*pte); - - list_add_tail(&page->lru, walk->vmemmap_pages); - set_pte_at(&init_mm, addr, pte, entry); -} - -/* - * How many struct page structs need to be reset. When we reuse the head - * struct page, the special metadata (e.g. page->flags or page->mapping) - * cannot copy to the tail struct page structs. The invalid value will be - * checked in the free_tail_pages_check(). In order to avoid the message - * of "corrupted mapping in tail page". We need to reset at least 3 (one - * head struct page struct and two tail struct page structs) struct page - * structs. - */ -#define NR_RESET_STRUCT_PAGE 3 - -static inline void reset_struct_pages(struct page *start) -{ - int i; - struct page *from = start + NR_RESET_STRUCT_PAGE; - - for (i = 0; i < NR_RESET_STRUCT_PAGE; i++) - memcpy(start + i, from, sizeof(*from)); -} - -static void vmemmap_restore_pte(pte_t *pte, unsigned long addr, - struct vmemmap_remap_walk *walk) -{ - pgprot_t pgprot = PAGE_KERNEL; - struct page *page; - void *to; - - BUG_ON(pte_page(*pte) != walk->reuse_page); - - page = list_first_entry(walk->vmemmap_pages, struct page, lru); - list_del(&page->lru); - to = page_to_virt(page); - copy_page(to, (void *)walk->reuse_addr); - reset_struct_pages(to); - - set_pte_at(&init_mm, addr, pte, mk_pte(page, pgprot)); -} - -/** - * vmemmap_remap_free - remap the vmemmap virtual address range [@start, @end) - * to the page which @reuse is mapped to, then free vmemmap - * which the range are mapped to. - * @start: start address of the vmemmap virtual address range that we want - * to remap. - * @end: end address of the vmemmap virtual address range that we want to - * remap. - * @reuse: reuse address. - * - * Return: %0 on success, negative error code otherwise. - */ -int vmemmap_remap_free(unsigned long start, unsigned long end, - unsigned long reuse) -{ - int ret; - LIST_HEAD(vmemmap_pages); - struct vmemmap_remap_walk walk = { - .remap_pte = vmemmap_remap_pte, - .reuse_addr = reuse, - .vmemmap_pages = &vmemmap_pages, - }; - - /* - * In order to make remapping routine most efficient for the huge pages, - * the routine of vmemmap page table walking has the following rules - * (see more details from the vmemmap_pte_range()): - * - * - The range [@start, @end) and the range [@reuse, @reuse + PAGE_SIZE) - * should be continuous. - * - The @reuse address is part of the range [@reuse, @end) that we are - * walking which is passed to vmemmap_remap_range(). - * - The @reuse address is the first in the complete range. - * - * So we need to make sure that @start and @reuse meet the above rules. - */ - BUG_ON(start - reuse != PAGE_SIZE); - - mmap_read_lock(&init_mm); - ret = vmemmap_remap_range(reuse, end, &walk); - if (ret && walk.nr_walked) { - end = reuse + walk.nr_walked * PAGE_SIZE; - /* - * vmemmap_pages contains pages from the previous - * vmemmap_remap_range call which failed. These - * are pages which were removed from the vmemmap. - * They will be restored in the following call. - */ - walk = (struct vmemmap_remap_walk) { - .remap_pte = vmemmap_restore_pte, - .reuse_addr = reuse, - .vmemmap_pages = &vmemmap_pages, - }; - - vmemmap_remap_range(reuse, end, &walk); - } - mmap_read_unlock(&init_mm); - - free_vmemmap_page_list(&vmemmap_pages); - - return ret; -} - -static int alloc_vmemmap_page_list(unsigned long start, unsigned long end, - gfp_t gfp_mask, struct list_head *list) -{ - unsigned long nr_pages = (end - start) >> PAGE_SHIFT; - int nid = page_to_nid((struct page *)start); - struct page *page, *next; - - while (nr_pages--) { - page = alloc_pages_node(nid, gfp_mask, 0); - if (!page) - goto out; - list_add_tail(&page->lru, list); - } - - return 0; -out: - list_for_each_entry_safe(page, next, list, lru) - __free_pages(page, 0); - return -ENOMEM; -} - -/** - * vmemmap_remap_alloc - remap the vmemmap virtual address range [@start, end) - * to the page which is from the @vmemmap_pages - * respectively. - * @start: start address of the vmemmap virtual address range that we want - * to remap. - * @end: end address of the vmemmap virtual address range that we want to - * remap. - * @reuse: reuse address. - * @gfp_mask: GFP flag for allocating vmemmap pages. - * - * Return: %0 on success, negative error code otherwise. - */ -int vmemmap_remap_alloc(unsigned long start, unsigned long end, - unsigned long reuse, gfp_t gfp_mask) -{ - LIST_HEAD(vmemmap_pages); - struct vmemmap_remap_walk walk = { - .remap_pte = vmemmap_restore_pte, - .reuse_addr = reuse, - .vmemmap_pages = &vmemmap_pages, - }; - - /* See the comment in the vmemmap_remap_free(). */ - BUG_ON(start - reuse != PAGE_SIZE); - - if (alloc_vmemmap_page_list(start, end, gfp_mask, &vmemmap_pages)) - return -ENOMEM; - - mmap_read_lock(&init_mm); - vmemmap_remap_range(reuse, end, &walk); - mmap_read_unlock(&init_mm); - - return 0; -} -#endif /* CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP */ /* * Allocate a block of memory to be used to back the virtual memory map diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index 0496efd6e117..a0ccceb22cf8 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -25,7 +25,7 @@ failure = $(if-success,$(1),n,y) # $(cc-option,<flag>) # Return y if the compiler supports <flag>, n otherwise -cc-option = $(success,mkdir .tmp_$$$$; trap "rm -rf .tmp_$$$$" EXIT; $(CC) -Werror $(CLANG_FLAGS) $(1) -c -x c /dev/null -o .tmp_$$$$/tmp.o) +cc-option = $(success,trap "rm -rf .tmp_$$" EXIT; mkdir .tmp_$$; $(CC) -Werror $(CLANG_FLAGS) $(1) -c -x c /dev/null -o .tmp_$$/tmp.o) # $(ld-option,<flag>) # Return y if the linker supports <flag>, n otherwise diff --git a/scripts/Makefile.build b/scripts/Makefile.build index cac070aee791..784f46d41959 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -358,9 +358,8 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ; quiet_cmd_ar_builtin = AR $@ cmd_ar_builtin = rm -f $@; \ - echo $(patsubst $(obj)/%,%,$(real-prereqs)) | \ - sed -E 's:([^ ]+):$(obj)/\1:g' | \ - xargs $(AR) cDPrST $@ + $(if $(real-prereqs), printf "$(obj)/%s " $(patsubst $(obj)/%,%,$(real-prereqs)) | xargs) \ + $(AR) cDPrST $@ $(obj)/built-in.a: $(real-obj-y) FORCE $(call if_changed,ar_builtin) diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler index 86ecd2ac874c..94d0d40cddb3 100644 --- a/scripts/Makefile.compiler +++ b/scripts/Makefile.compiler @@ -21,8 +21,8 @@ TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$ # automatically cleaned up. try-run = $(shell set -e; \ TMP=$(TMPOUT)/tmp; \ - mkdir -p $(TMPOUT); \ trap "rm -rf $(TMPOUT)" EXIT; \ + mkdir -p $(TMPOUT); \ if ($(1)) >/dev/null 2>&1; \ then echo "$(2)"; \ else echo "$(3)"; \ diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index f5f0d6f09053..9bbaf7112a9b 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -47,7 +47,6 @@ else ifdef CONFIG_CC_IS_CLANG KBUILD_CFLAGS += -Wno-initializer-overrides -KBUILD_CFLAGS += -Wno-format KBUILD_CFLAGS += -Wno-sign-compare KBUILD_CFLAGS += -Wno-format-zero-length KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index 16a02e9237d3..a4c987c23750 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -18,6 +18,9 @@ INSTALL_MOD_DIR ?= extra dst := $(MODLIB)/$(INSTALL_MOD_DIR) endif +$(foreach x, % :, $(if $(findstring $x, $(dst)), \ + $(error module installation path cannot contain '$x'))) + suffix-y := suffix-$(CONFIG_MODULE_COMPRESS_GZIP) := .gz suffix-$(CONFIG_MODULE_COMPRESS_XZ) := .xz diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 77b612183c08..5017f6b2da80 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -56,7 +56,7 @@ rpm-pkg: $(MAKE) clean $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec $(call cmd,src_tar,$(KERNELPATH),kernel.spec) - +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz \ + +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -ta $(KERNELPATH).tar.gz \ --define='_smp_mflags %{nil}' # binrpm-pkg @@ -66,7 +66,7 @@ binrpm-pkg: $(MAKE) -f $(srctree)/Makefile $(CONFIG_SHELL) $(MKSPEC) prebuilt > $(objtree)/binkernel.spec +rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \ - $(UTS_MACHINE) -bb $(objtree)/binkernel.spec + $(UTS_MACHINE)-linux -bb $(objtree)/binkernel.spec PHONY += deb-pkg deb-pkg: diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index d2c38584ece6..d48dfed6d3db 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -16,6 +16,7 @@ # AArch64, PARISC ports by Kyle McMartin # sparc port by Martin Habets <[email protected]> # ppc64le port by Breno Leitao <[email protected]> +# riscv port by Wadim Mueller <[email protected]> # # Usage: # objdump -d vmlinux | scripts/checkstack.pl [arch] @@ -108,6 +109,9 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack); } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { # f0019d10: 9d e3 bf 90 save %sp, -112, %sp $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; + } elsif ($arch =~ /^riscv(64)?$/) { + #ffffffff8036e868: c2010113 addi sp,sp,-992 + $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; } else { print("wrong or unknown architecture \"$arch\"\n"); exit diff --git a/scripts/dummy-tools/dummy-plugin-dir/include/plugin-version.h b/scripts/dummy-tools/dummy-plugin-dir/include/plugin-version.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/scripts/dummy-tools/dummy-plugin-dir/include/plugin-version.h diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc index b2483149bbe5..7db825843435 100755 --- a/scripts/dummy-tools/gcc +++ b/scripts/dummy-tools/gcc @@ -96,12 +96,8 @@ fi # To set GCC_PLUGINS if arg_contain -print-file-name=plugin "$@"; then - plugin_dir=$(mktemp -d) - - mkdir -p $plugin_dir/include - touch $plugin_dir/include/plugin-version.h - - echo $plugin_dir + # Use $0 to find the in-tree dummy directory + echo "$(dirname "$(readlink -f "$0")")/dummy-plugin-dir" exit 0 fi diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh index dd554bd436cc..4041881746ad 100755 --- a/scripts/headers_install.sh +++ b/scripts/headers_install.sh @@ -70,7 +70,6 @@ configs=$(sed -e ' # # The format is <file-name>:<CONFIG-option> in each line. config_leak_ignores=" -arch/alpha/include/uapi/asm/setup.h:CONFIG_ALPHA_LEGACY_START_ADDRESS arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_16K arch/arc/include/uapi/asm/page.h:CONFIG_ARC_PAGE_SIZE_4K arch/arc/include/uapi/asm/swab.h:CONFIG_ARC_HAS_SWAPE @@ -84,7 +83,6 @@ arch/nios2/include/uapi/asm/swab.h:CONFIG_NIOS2_CI_SWAB_SUPPORT arch/x86/include/uapi/asm/auxvec.h:CONFIG_IA32_EMULATION arch/x86/include/uapi/asm/auxvec.h:CONFIG_X86_64 arch/x86/include/uapi/asm/mman.h:CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS -include/uapi/asm-generic/fcntl.h:CONFIG_64BIT include/uapi/linux/atmdev.h:CONFIG_COMPAT include/uapi/linux/eventpoll.h:CONFIG_PM_SLEEP include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh index 9b695e5cd9b3..ad652cb53947 100755 --- a/scripts/kconfig/qconf-cfg.sh +++ b/scripts/kconfig/qconf-cfg.sh @@ -20,5 +20,6 @@ fi echo >&2 "*" echo >&2 "* Could not find Qt5 via ${HOSTPKG_CONFIG}." echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH" +echo >&2 "* You need $PKG" echo >&2 "*" exit 1 diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index cbd6b0f48b4e..80d973144fde 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1571,9 +1571,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, zeros = calloc(1, sym->st_size); symval = zeros; } else { - symval = (void *)info->hdr - + info->sechdrs[get_secindex(info, sym)].sh_offset - + sym->st_value; + symval = sym_get_data(info, sym); } /* First handle the "special" cases */ diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 29474cee10b1..55e32af2e53f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -321,13 +321,10 @@ static void *sym_get_data_by_offset(const struct elf_info *info, { Elf_Shdr *sechdr = &info->sechdrs[secindex]; - if (info->hdr->e_type != ET_REL) - offset -= sechdr->sh_addr; - return (void *)info->hdr + sechdr->sh_offset + offset; } -static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) +void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) { return sym_get_data_by_offset(info, get_secindex(info, sym), sym->st_value); @@ -339,8 +336,16 @@ static const char *sech_name(const struct elf_info *info, Elf_Shdr *sechdr) sechdr->sh_name); } -static const char *sec_name(const struct elf_info *info, int secindex) +static const char *sec_name(const struct elf_info *info, unsigned int secindex) { + /* + * If sym->st_shndx is a special section index, there is no + * corresponding section header. + * Return "" if the index is out of range of info->sechdrs[] array. + */ + if (secindex >= info->num_sections) + return ""; + return sech_name(info, &info->sechdrs[secindex]); } @@ -466,6 +471,10 @@ static int parse_elf(struct elf_info *info, const char *filename) sechdrs = (void *)hdr + hdr->e_shoff; info->sechdrs = sechdrs; + /* modpost only works for relocatable objects */ + if (hdr->e_type != ET_REL) + fatal("%s: not relocatable object.", filename); + /* Check if file offset is correct */ if (hdr->e_shoff > info->size) { fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n", @@ -737,12 +746,18 @@ static bool match(const char *string, const char *const patterns[]) return false; } +/* useful to pass patterns to match() directly */ +#define PATTERNS(...) \ + ({ \ + static const char *const patterns[] = {__VA_ARGS__, NULL}; \ + patterns; \ + }) + /* sections that we do not want to do full section mismatch check on */ static const char *const section_white_list[] = { ".comment*", ".debug*", - ".cranges", /* sh64 */ ".zdebug*", /* Compressed debug sections. */ ".GCC.command.line", /* record-gcc-switches */ ".mdebug*", /* alpha, score, mips etc. */ @@ -830,28 +845,12 @@ static const char *const init_data_sections[] = /* all init sections */ static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL }; -/* All init and exit sections (code + data) */ -static const char *const init_exit_sections[] = - {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; - /* all text sections */ static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL }; /* data section */ static const char *const data_sections[] = { DATA_SECTIONS, NULL }; - -/* symbols in .data that may refer to init/exit sections */ -#define DEFAULT_SYMBOL_WHITE_LIST \ - "*driver", \ - "*_template", /* scsi uses *_template a lot */ \ - "*_timer", /* arm uses ops structures named _timer a lot */ \ - "*_sht", /* scsi also used *_sht to some extent */ \ - "*_ops", \ - "*_probe", \ - "*_probe_one", \ - "*_console" - static const char *const head_sections[] = { ".head.text*", NULL }; static const char *const linker_symbols[] = { "__init_begin", "_sinittext", "_einittext", NULL }; @@ -883,9 +882,6 @@ enum mismatch { * * @mismatch: Type of mismatch. * - * @symbol_white_list: Do not match a relocation to a symbol in this list - * even if it is targeting a section in @bad_to_sec. - * * @handler: Specific handler to call when a match is found. If NULL, * default_mismatch_handler() will be called. * @@ -895,7 +891,6 @@ struct sectioncheck { const char *bad_tosec[20]; const char *good_tosec[20]; enum mismatch mismatch; - const char *symbol_white_list[20]; void (*handler)(const char *modname, struct elf_info *elf, const struct sectioncheck* const mismatch, Elf_Rela *r, Elf_Sym *sym, const char *fromsec); @@ -915,75 +910,61 @@ static const struct sectioncheck sectioncheck[] = { .fromsec = { TEXT_SECTIONS, NULL }, .bad_tosec = { ALL_INIT_SECTIONS, NULL }, .mismatch = TEXT_TO_ANY_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { DATA_SECTIONS, NULL }, .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { DATA_SECTIONS, NULL }, .bad_tosec = { INIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_INIT, - .symbol_white_list = { - "*_template", "*_timer", "*_sht", "*_ops", - "*_probe", "*_probe_one", "*_console", NULL - }, }, { .fromsec = { TEXT_SECTIONS, NULL }, .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, .mismatch = TEXT_TO_ANY_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { DATA_SECTIONS, NULL }, .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference init code/data from meminit code/data */ { .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, .bad_tosec = { INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_SOME_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference exit code/data from memexit code/data */ { .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, .bad_tosec = { EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_SOME_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not use exit code/data from init code */ { .fromsec = { ALL_INIT_SECTIONS, NULL }, .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, .mismatch = ANY_INIT_TO_ANY_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not use init code/data from exit code */ { .fromsec = { ALL_EXIT_SECTIONS, NULL }, .bad_tosec = { ALL_INIT_SECTIONS, NULL }, .mismatch = ANY_EXIT_TO_ANY_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, .bad_tosec = { INIT_SECTIONS, NULL }, .mismatch = ANY_INIT_TO_ANY_EXIT, - .symbol_white_list = { NULL }, }, /* Do not export init/exit functions or data */ { .fromsec = { "___ksymtab*", NULL }, .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, .mismatch = EXPORT_TO_INIT_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { "__ex_table", NULL }, @@ -1044,15 +1025,6 @@ static const struct sectioncheck *section_mismatch( * fromsec = .data* * atsym = __param_ops_* * - * Pattern 2: - * Many drivers utilise a *driver container with references to - * add, remove, probe functions etc. - * the pattern is identified by: - * tosec = init or exit section - * fromsec = data section - * atsym = *driver, *_template, *_sht, *_ops, *_probe, - * *probe_one, *_console, *_timer - * * Pattern 3: * Whitelist all references from .head.text to any init section * @@ -1101,10 +1073,22 @@ static int secref_whitelist(const struct sectioncheck *mismatch, strstarts(fromsym, "__param_ops_")) return 0; - /* Check for pattern 2 */ - if (match(tosec, init_exit_sections) && - match(fromsec, data_sections) && - match(fromsym, mismatch->symbol_white_list)) + /* symbols in data sections that may refer to any init/exit sections */ + if (match(fromsec, PATTERNS(DATA_SECTIONS)) && + match(tosec, PATTERNS(ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS)) && + match(fromsym, PATTERNS("*_template", // scsi uses *_template a lot + "*_timer", // arm uses ops structures named _timer a lot + "*_sht", // scsi also used *_sht to some extent + "*_ops", + "*_probe", + "*_probe_one", + "*_console"))) + return 0; + + /* symbols in data sections that may refer to meminit/exit sections */ + if (match(fromsec, PATTERNS(DATA_SECTIONS)) && + match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS, ALL_EXIT_SECTIONS)) && + match(fromsym, PATTERNS("*driver"))) return 0; /* Check for pattern 3 */ @@ -1230,42 +1214,6 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, return near; } -/* - * Convert a section name to the function/data attribute - * .init.text => __init - * .memexitconst => __memconst - * etc. - * - * The memory of returned value has been allocated on a heap. The user of this - * method should free it after usage. -*/ -static char *sec2annotation(const char *s) -{ - if (match(s, init_exit_sections)) { - char *p = NOFAIL(malloc(20)); - char *r = p; - - *p++ = '_'; - *p++ = '_'; - if (*s == '.') - s++; - while (*s && *s != '.') - *p++ = *s++; - *p = '\0'; - if (*s == '.') - s++; - if (strstr(s, "rodata") != NULL) - strcat(p, "const "); - else if (strstr(s, "data") != NULL) - strcat(p, "data "); - else - strcat(p, " "); - return r; - } else { - return NOFAIL(strdup("")); - } -} - static int is_function(Elf_Sym *sym) { if (sym) @@ -1274,19 +1222,6 @@ static int is_function(Elf_Sym *sym) return -1; } -static void print_section_list(const char * const list[20]) -{ - const char *const *s = list; - - while (*s) { - fprintf(stderr, "%s", *s); - s++; - if (*s) - fprintf(stderr, ", "); - } - fprintf(stderr, "\n"); -} - static inline void get_pretty_name(int is_func, const char** name, const char** name_p) { switch (is_func) { @@ -1304,141 +1239,31 @@ static inline void get_pretty_name(int is_func, const char** name, const char** static void report_sec_mismatch(const char *modname, const struct sectioncheck *mismatch, const char *fromsec, - unsigned long long fromaddr, const char *fromsym, - int from_is_func, - const char *tosec, const char *tosym, - int to_is_func) + const char *tosec, const char *tosym) { - const char *from, *from_p; - const char *to, *to_p; - char *prl_from; - char *prl_to; - sec_mismatch_count++; - get_pretty_name(from_is_func, &from, &from_p); - get_pretty_name(to_is_func, &to, &to_p); - - warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s " - "to the %s %s:%s%s\n", - modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, - tosym, to_p); - switch (mismatch->mismatch) { case TEXT_TO_ANY_INIT: - prl_from = sec2annotation(fromsec); - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The function %s%s() references\n" - "the %s %s%s%s.\n" - "This is often because %s lacks a %s\n" - "annotation or the annotation of %s is wrong.\n", - prl_from, fromsym, - to, prl_to, tosym, to_p, - fromsym, prl_to, tosym); - free(prl_from); - free(prl_to); - break; - case DATA_TO_ANY_INIT: { - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The variable %s references\n" - "the %s %s%s%s\n" - "If the reference is valid then annotate the\n" - "variable with __init* or __refdata (see linux/init.h) " - "or name the variable:\n", - fromsym, to, prl_to, tosym, to_p); - print_section_list(mismatch->symbol_white_list); - free(prl_to); - break; - } + case DATA_TO_ANY_INIT: case TEXT_TO_ANY_EXIT: - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The function %s() references a %s in an exit section.\n" - "Often the %s %s%s has valid usage outside the exit section\n" - "and the fix is to remove the %sannotation of %s.\n", - fromsym, to, to, tosym, to_p, prl_to, tosym); - free(prl_to); - break; - case DATA_TO_ANY_EXIT: { - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The variable %s references\n" - "the %s %s%s%s\n" - "If the reference is valid then annotate the\n" - "variable with __exit* (see linux/init.h) or " - "name the variable:\n", - fromsym, to, prl_to, tosym, to_p); - print_section_list(mismatch->symbol_white_list); - free(prl_to); - break; - } + case DATA_TO_ANY_EXIT: case XXXINIT_TO_SOME_INIT: case XXXEXIT_TO_SOME_EXIT: - prl_from = sec2annotation(fromsec); - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The %s %s%s%s references\n" - "a %s %s%s%s.\n" - "If %s is only used by %s then\n" - "annotate %s with a matching annotation.\n", - from, prl_from, fromsym, from_p, - to, prl_to, tosym, to_p, - tosym, fromsym, tosym); - free(prl_from); - free(prl_to); - break; case ANY_INIT_TO_ANY_EXIT: - prl_from = sec2annotation(fromsec); - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The %s %s%s%s references\n" - "a %s %s%s%s.\n" - "This is often seen when error handling " - "in the init function\n" - "uses functionality in the exit path.\n" - "The fix is often to remove the %sannotation of\n" - "%s%s so it may be used outside an exit section.\n", - from, prl_from, fromsym, from_p, - to, prl_to, tosym, to_p, - prl_to, tosym, to_p); - free(prl_from); - free(prl_to); - break; case ANY_EXIT_TO_ANY_INIT: - prl_from = sec2annotation(fromsec); - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The %s %s%s%s references\n" - "a %s %s%s%s.\n" - "This is often seen when error handling " - "in the exit function\n" - "uses functionality in the init path.\n" - "The fix is often to remove the %sannotation of\n" - "%s%s so it may be used outside an init section.\n", - from, prl_from, fromsym, from_p, - to, prl_to, tosym, to_p, - prl_to, tosym, to_p); - free(prl_from); - free(prl_to); + warn("%s: section mismatch in reference: %s (section: %s) -> %s (section: %s)\n", + modname, fromsym, fromsec, tosym, tosec); break; case EXPORT_TO_INIT_EXIT: - prl_to = sec2annotation(tosec); - fprintf(stderr, - "The symbol %s is exported and annotated %s\n" - "Fix this by removing the %sannotation of %s " - "or drop the export.\n", - tosym, prl_to, prl_to, tosym); - free(prl_to); + warn("%s: EXPORT_SYMBOL used for init/exit symbol: %s (section: %s)\n", + modname, tosym, tosec); break; case EXTABLE_TO_NON_TEXT: - fatal("There's a special handler for this mismatch type, " - "we should never get here."); + fatal("There's a special handler for this mismatch type, we should never get here.\n"); break; } - fprintf(stderr, "\n"); } static void default_mismatch_handler(const char *modname, struct elf_info *elf, @@ -1454,9 +1279,6 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, from = find_elf_symbol2(elf, r->r_offset, fromsec); fromsym = sym_name(elf, from); - if (strstarts(fromsym, "reference___initcall")) - return; - tosec = sec_name(elf, get_secindex(elf, sym)); to = find_elf_symbol(elf, r->r_addend, sym); tosym = sym_name(elf, to); @@ -1465,9 +1287,7 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, if (secref_whitelist(mismatch, fromsec, fromsym, tosec, tosym)) { report_sec_mismatch(modname, mismatch, - fromsec, r->r_offset, fromsym, - is_function(from), tosec, tosym, - is_function(to)); + fromsec, fromsym, tosec, tosym); } } @@ -1623,9 +1443,6 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) break; case R_386_PC32: r->r_addend = TO_NATIVE(*location) + 4; - /* For CONFIG_RELOCATABLE=y */ - if (elf->hdr->e_type == ET_EXEC) - r->r_addend += r->r_offset; break; } return 0; @@ -1718,8 +1535,7 @@ static void section_rela(const char *modname, struct elf_info *elf, Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; Elf_Rela *stop = (void *)start + sechdr->sh_size; - fromsec = sech_name(elf, sechdr); - fromsec += strlen(".rela"); + fromsec = sec_name(elf, sechdr->sh_info); /* if from section (name) is know good then skip it */ if (match(fromsec, section_white_list)) return; @@ -1771,8 +1587,7 @@ static void section_rel(const char *modname, struct elf_info *elf, Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; Elf_Rel *stop = (void *)start + sechdr->sh_size; - fromsec = sech_name(elf, sechdr); - fromsec += strlen(".rel"); + fromsec = sec_name(elf, sechdr->sh_info); /* if from section (name) is know good then skip it */ if (match(fromsec, section_white_list)) return; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 044bdfb894b7..1178f40a73f3 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -26,7 +26,6 @@ #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym #define Elf_Addr Elf32_Addr -#define Elf_Sword Elf64_Sword #define Elf_Section Elf32_Half #define ELF_ST_BIND ELF32_ST_BIND #define ELF_ST_TYPE ELF32_ST_TYPE @@ -41,7 +40,6 @@ #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym #define Elf_Addr Elf64_Addr -#define Elf_Sword Elf64_Sxword #define Elf_Section Elf64_Half #define ELF_ST_BIND ELF64_ST_BIND #define ELF_ST_TYPE ELF64_ST_TYPE @@ -158,22 +156,28 @@ static inline int is_shndx_special(unsigned int i) return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; } -/* - * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of - * the way to -256..-1, to avoid conflicting with real section - * indices. - */ -#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1)) - /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ static inline unsigned int get_secindex(const struct elf_info *info, const Elf_Sym *sym) { - if (is_shndx_special(sym->st_shndx)) - return SPECIAL(sym->st_shndx); - if (sym->st_shndx != SHN_XINDEX) - return sym->st_shndx; - return info->symtab_shndx_start[sym - info->symtab_start]; + unsigned int index = sym->st_shndx; + + /* + * Elf{32,64}_Sym::st_shndx is 2 byte. Big section numbers are available + * in the .symtab_shndx section. + */ + if (index == SHN_XINDEX) + return info->symtab_shndx_start[sym - info->symtab_start]; + + /* + * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of + * the way to UINT_MAX-255..UINT_MAX, to avoid conflicting with real + * section indices. + */ + if (index >= SHN_LORESERVE && index <= SHN_HIRESERVE) + return index - SHN_HIRESERVE - 1; + + return index; } /* file2alias.c */ @@ -187,6 +191,7 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen); /* from modpost.c */ char *read_text_file(const char *filename); char *get_line(char **stringp); +void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym); enum loglevel { LOG_WARN, diff --git a/scripts/package/mkspec b/scripts/package/mkspec index 7c477ca7dc98..8fa7c5b8a1a1 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -49,6 +49,9 @@ sed -e '/^DEL/d' -e 's/^\t*//' <<EOF URL: https://www.kernel.org $S Source: kernel-$__KERNELRELEASE.tar.gz Provides: $PROVIDES + # $UTS_MACHINE as a fallback of _arch in case + # /usr/lib/rpm/platform/*/macros was not included. + %define _arch %{?_arch:$UTS_MACHINE} %define __spec_install_post /usr/lib/rpm/brp-compress || : %define debug_package %{nil} diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig index 348ed6cfa08a..cb3496e00d8a 100644 --- a/security/apparmor/Kconfig +++ b/security/apparmor/Kconfig @@ -6,8 +6,6 @@ config SECURITY_APPARMOR select SECURITY_PATH select SECURITYFS select SECURITY_NETWORK - select ZLIB_INFLATE - select ZLIB_DEFLATE default n help This enables the AppArmor security module. @@ -17,29 +15,6 @@ config SECURITY_APPARMOR If you are unsure how to answer this question, answer N. -config SECURITY_APPARMOR_HASH - bool "Enable introspection of sha1 hashes for loaded profiles" - depends on SECURITY_APPARMOR - select CRYPTO - select CRYPTO_SHA1 - default y - help - This option selects whether introspection of loaded policy - is available to userspace via the apparmor filesystem. - -config SECURITY_APPARMOR_HASH_DEFAULT - bool "Enable policy hash introspection by default" - depends on SECURITY_APPARMOR_HASH - default y - help - This option selects whether sha1 hashing of loaded policy - is enabled by default. The generation of sha1 hashes for - loaded policy provide system administrators a quick way - to verify that policy in the kernel matches what is expected, - however it can slow down policy load on some devices. In - these cases policy hashing can be disabled by default and - enabled only if needed. - config SECURITY_APPARMOR_DEBUG bool "Build AppArmor with debug code" depends on SECURITY_APPARMOR @@ -69,6 +44,67 @@ config SECURITY_APPARMOR_DEBUG_MESSAGES When enabled, various debug messages will be logged to the kernel message buffer. +config SECURITY_APPARMOR_INTROSPECT_POLICY + bool "Allow loaded policy to be introspected" + depends on SECURITY_APPARMOR + default y + help + This option selects whether introspection of loaded policy + is available to userspace via the apparmor filesystem. This + adds to kernel memory usage. It is required for introspection + of loaded policy, and check point and restore support. It + can be disabled for embedded systems where reducing memory and + cpu is paramount. + +config SECURITY_APPARMOR_HASH + bool "Enable introspection of sha1 hashes for loaded profiles" + depends on SECURITY_APPARMOR_INTROSPECT_POLICY + select CRYPTO + select CRYPTO_SHA1 + default y + help + This option selects whether introspection of loaded policy + hashes is available to userspace via the apparmor + filesystem. This option provides a light weight means of + checking loaded policy. This option adds to policy load + time and can be disabled for small embedded systems. + +config SECURITY_APPARMOR_HASH_DEFAULT + bool "Enable policy hash introspection by default" + depends on SECURITY_APPARMOR_HASH + default y + help + This option selects whether sha1 hashing of loaded policy + is enabled by default. The generation of sha1 hashes for + loaded policy provide system administrators a quick way + to verify that policy in the kernel matches what is expected, + however it can slow down policy load on some devices. In + these cases policy hashing can be disabled by default and + enabled only if needed. + +config SECURITY_APPARMOR_EXPORT_BINARY + bool "Allow exporting the raw binary policy" + depends on SECURITY_APPARMOR_INTROSPECT_POLICY + select ZLIB_INFLATE + select ZLIB_DEFLATE + default y + help + This option allows reading back binary policy as it was loaded. + It increases the amount of kernel memory needed by policy and + also increases policy load time. This option is required for + checkpoint and restore support, and debugging of loaded policy. + +config SECURITY_APPARMOR_PARANOID_LOAD + bool "Perform full verification of loaded policy" + depends on SECURITY_APPARMOR + default y + help + This options allows controlling whether apparmor does a full + verification of loaded policy. This should not be disabled + except for embedded systems where the image is read only, + includes policy, and has some form of integrity check. + Disabling the check will speed up policy loads. + config SECURITY_APPARMOR_KUNIT_TEST bool "Build KUnit tests for policy_unpack.c" if !KUNIT_ALL_TESTS depends on KUNIT=y && SECURITY_APPARMOR diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 0797edb2fb3d..d066ccc219e2 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -36,6 +36,7 @@ #include "include/policy_ns.h" #include "include/resource.h" #include "include/policy_unpack.h" +#include "include/task.h" /* * The apparmor filesystem interface used for policy load and introspection @@ -70,6 +71,7 @@ struct rawdata_f_data { struct aa_loaddata *loaddata; }; +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY #define RAWDATA_F_DATA_BUF(p) (char *)(p + 1) static void rawdata_f_data_free(struct rawdata_f_data *private) @@ -94,9 +96,10 @@ static struct rawdata_f_data *rawdata_f_data_alloc(size_t size) return ret; } +#endif /** - * aa_mangle_name - mangle a profile name to std profile layout form + * mangle_name - mangle a profile name to std profile layout form * @name: profile name to mangle (NOT NULL) * @target: buffer to store mangled name, same length as @name (MAYBE NULL) * @@ -401,7 +404,7 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf, data->size = copy_size; if (copy_from_user(data->data, userbuf, copy_size)) { - kvfree(data); + aa_put_loaddata(data); return ERR_PTR(-EFAULT); } @@ -1201,7 +1204,7 @@ SEQ_NS_FOPS(name); /* policy/raw_data/ * file ops */ - +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY #define SEQ_RAWDATA_FOPS(NAME) \ static int seq_rawdata_ ##NAME ##_open(struct inode *inode, struct file *file)\ { \ @@ -1294,44 +1297,47 @@ SEQ_RAWDATA_FOPS(compressed_size); static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen) { - int error; - struct z_stream_s strm; +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY + if (aa_g_rawdata_compression_level != 0) { + int error = 0; + struct z_stream_s strm; - if (aa_g_rawdata_compression_level == 0) { - if (dlen < slen) - return -EINVAL; - memcpy(dst, src, slen); - return 0; - } + memset(&strm, 0, sizeof(strm)); - memset(&strm, 0, sizeof(strm)); + strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + if (!strm.workspace) + return -ENOMEM; - strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); - if (!strm.workspace) - return -ENOMEM; - - strm.next_in = src; - strm.avail_in = slen; + strm.next_in = src; + strm.avail_in = slen; - error = zlib_inflateInit(&strm); - if (error != Z_OK) { - error = -ENOMEM; - goto fail_inflate_init; - } + error = zlib_inflateInit(&strm); + if (error != Z_OK) { + error = -ENOMEM; + goto fail_inflate_init; + } - strm.next_out = dst; - strm.avail_out = dlen; + strm.next_out = dst; + strm.avail_out = dlen; - error = zlib_inflate(&strm, Z_FINISH); - if (error != Z_STREAM_END) - error = -EINVAL; - else - error = 0; + error = zlib_inflate(&strm, Z_FINISH); + if (error != Z_STREAM_END) + error = -EINVAL; + else + error = 0; - zlib_inflateEnd(&strm); + zlib_inflateEnd(&strm); fail_inflate_init: - kvfree(strm.workspace); - return error; + kvfree(strm.workspace); + + return error; + } +#endif + + if (dlen < slen) + return -EINVAL; + memcpy(dst, src, slen); + return 0; } static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size, @@ -1492,10 +1498,12 @@ fail: return PTR_ERR(dent); } +#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ + /** fns to setup dynamic per profile/namespace files **/ -/** +/* * * Requires: @profile->ns->lock held */ @@ -1522,7 +1530,7 @@ void __aafs_profile_rmdir(struct aa_profile *profile) } } -/** +/* * * Requires: @old->ns->lock held */ @@ -1557,6 +1565,7 @@ static struct dentry *create_profile_file(struct dentry *dir, const char *name, return dent; } +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY static int profile_depth(struct aa_profile *profile) { int depth = 0; @@ -1658,7 +1667,7 @@ static const struct inode_operations rawdata_link_abi_iops = { static const struct inode_operations rawdata_link_data_iops = { .get_link = rawdata_get_link_data, }; - +#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ /* * Requires: @profile->ns->lock held @@ -1729,15 +1738,17 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) profile->dents[AAFS_PROF_HASH] = dent; } +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY if (profile->rawdata) { - dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir, - profile->label.proxy, NULL, NULL, - &rawdata_link_sha1_iops); - if (IS_ERR(dent)) - goto fail; - aa_get_proxy(profile->label.proxy); - profile->dents[AAFS_PROF_RAW_HASH] = dent; - + if (aa_g_hash_policy) { + dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir, + profile->label.proxy, NULL, NULL, + &rawdata_link_sha1_iops); + if (IS_ERR(dent)) + goto fail; + aa_get_proxy(profile->label.proxy); + profile->dents[AAFS_PROF_RAW_HASH] = dent; + } dent = aafs_create("raw_abi", S_IFLNK | 0444, dir, profile->label.proxy, NULL, NULL, &rawdata_link_abi_iops); @@ -1754,6 +1765,7 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) aa_get_proxy(profile->label.proxy); profile->dents[AAFS_PROF_RAW_DATA] = dent; } +#endif /*CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ list_for_each_entry(child, &profile->base.profiles, base.list) { error = __aafs_profile_mkdir(child, prof_child_dir(profile)); @@ -1880,7 +1892,7 @@ static void __aa_fs_list_remove_rawdata(struct aa_ns *ns) __aa_fs_remove_rawdata(ent); } -/** +/* * * Requires: @ns->lock held */ @@ -2323,6 +2335,7 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = { AA_SFS_FILE_BOOLEAN("v6", 1), AA_SFS_FILE_BOOLEAN("v7", 1), AA_SFS_FILE_BOOLEAN("v8", 1), + AA_SFS_FILE_BOOLEAN("v9", 1), { } }; diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index f7e97c7e80f3..704b0c895605 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -137,7 +137,7 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, } if (AUDIT_MODE(profile) == AUDIT_QUIET || (type == AUDIT_APPARMOR_DENIED && - AUDIT_MODE(profile) == AUDIT_QUIET)) + AUDIT_MODE(profile) == AUDIT_QUIET_DENIED)) return aad(sa)->error; if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index a29e69d2c300..91689d34d281 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -119,7 +119,7 @@ static inline unsigned int match_component(struct aa_profile *profile, * @profile: profile to find perms for * @label: label to check access permissions for * @stack: whether this is a stacking request - * @start: state to start match in + * @state: state to start match in * @subns: whether to do permission checks on components in a subns * @request: permissions to request * @perms: perms struct to set @@ -466,7 +466,7 @@ restart: * xattrs, or a longer match */ candidate = profile; - candidate_len = profile->xmatch_len; + candidate_len = max(count, profile->xmatch_len); candidate_xattrs = ret; conflict = false; } @@ -1279,7 +1279,6 @@ static int change_profile_perms_wrapper(const char *op, const char *name, /** * aa_change_profile - perform a one-way profile transition * @fqname: name of profile may include namespace (NOT NULL) - * @onexec: whether this transition is to take place immediately or at exec * @flags: flags affecting change behavior * * Change to new profile @name. Unlike with hats, there is no way diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index 1fbabdb565a8..9c3fc36a0702 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -36,6 +36,7 @@ extern enum audit_mode aa_g_audit; extern bool aa_g_audit_header; extern bool aa_g_debug; extern bool aa_g_hash_policy; +extern bool aa_g_export_binary; extern int aa_g_rawdata_compression_level; extern bool aa_g_lock_policy; extern bool aa_g_logsyscall; diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h index 6e14f6cecdb9..1e94904f68d9 100644 --- a/security/apparmor/include/apparmorfs.h +++ b/security/apparmor/include/apparmorfs.h @@ -114,7 +114,21 @@ int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name, struct dentry *dent); struct aa_loaddata; + +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata); int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata); +#else +static inline void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata) +{ + /* empty stub */ +} + +static inline int __aa_fs_create_rawdata(struct aa_ns *ns, + struct aa_loaddata *rawdata) +{ + return 0; +} +#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ #endif /* __AA_APPARMORFS_H */ diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index 7517605a183d..029cb20e322d 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -142,6 +142,7 @@ static inline u16 dfa_map_xindex(u16 mask) */ #define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \ ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) +#define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f) #define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f) #define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f) #define dfa_user_xindex(dfa, state) \ @@ -150,6 +151,8 @@ static inline u16 dfa_map_xindex(u16 mask) #define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \ 0x7f) | \ ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) +#define dfa_other_xbits(dfa, state) \ + ((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f) #define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f) #define dfa_other_quiet(dfa, state) \ ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f) diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h index 9cafd80f7731..a1ac6ffb95e9 100644 --- a/security/apparmor/include/ipc.h +++ b/security/apparmor/include/ipc.h @@ -13,24 +13,6 @@ #include <linux/sched.h> -struct aa_profile; - -#define AA_PTRACE_TRACE MAY_WRITE -#define AA_PTRACE_READ MAY_READ -#define AA_MAY_BE_TRACED AA_MAY_APPEND -#define AA_MAY_BE_READ AA_MAY_CREATE -#define PTRACE_PERM_SHIFT 2 - -#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ - AA_MAY_BE_READ | AA_MAY_BE_TRACED) -#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) - -#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ - "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ - "xcpu xfsz vtalrm prof winch io pwr sys emt lost" - -int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - u32 request); int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); #endif /* __AA_IPC_H */ diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h index 9101c2c76d9e..860484c6f99a 100644 --- a/security/apparmor/include/label.h +++ b/security/apparmor/include/label.h @@ -92,6 +92,8 @@ enum label_flags { FLAG_STALE = 0x800, /* replaced/removed */ FLAG_RENAMED = 0x1000, /* label has renaming in it */ FLAG_REVOKED = 0x2000, /* label has revocation in it */ + FLAG_DEBUG1 = 0x4000, + FLAG_DEBUG2 = 0x8000, /* These flags must correspond with PATH_flags */ /* TODO: add new path flags */ diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index e2e8df0c6f1c..f42359f58eb5 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h @@ -22,6 +22,11 @@ */ #define DEBUG_ON (aa_g_debug) +/* + * split individual debug cases out in preparation for finer grained + * debug controls in the future. + */ +#define AA_DEBUG_LABEL DEBUG_ON #define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args) #define AA_DEBUG(fmt, args...) \ do { \ diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h index 44a7945fbe3c..343189903dba 100644 --- a/security/apparmor/include/path.h +++ b/security/apparmor/include/path.h @@ -17,8 +17,8 @@ enum path_flags { PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ - PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */ - PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ + PATH_DELEGATE_DELETED = 0x10000, /* delegate deleted files */ + PATH_MEDIATE_DELETED = 0x20000, /* mediate deleted paths */ }; int aa_path_name(const struct path *path, int flags, char *buffer, diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index cb5ef21991b7..639b5b248e63 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -48,6 +48,10 @@ extern const char *const aa_profile_mode_names[]; #define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT) +#define CHECK_DEBUG1(_profile) ((_profile)->label.flags & FLAG_DEBUG1) + +#define CHECK_DEBUG2(_profile) ((_profile)->label.flags & FLAG_DEBUG2) + #define profile_is_stale(_profile) (label_is_stale(&(_profile)->label)) #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) @@ -135,7 +139,7 @@ struct aa_profile { const char *attach; struct aa_dfa *xmatch; - int xmatch_len; + unsigned int xmatch_len; enum audit_mode audit; long mode; u32 path_flags; diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h index 3df6f804922d..33d665516fc1 100644 --- a/security/apparmor/include/policy_ns.h +++ b/security/apparmor/include/policy_ns.h @@ -74,6 +74,7 @@ struct aa_ns { struct dentry *dents[AAFS_NS_SIZEOF]; }; +extern struct aa_label *kernel_t; extern struct aa_ns *root_ns; extern const char *aa_hidden_ns_name; diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h index e0e1ca7ebc38..eb5f7d7f132b 100644 --- a/security/apparmor/include/policy_unpack.h +++ b/security/apparmor/include/policy_unpack.h @@ -28,6 +28,8 @@ void aa_load_ent_free(struct aa_load_ent *ent); struct aa_load_ent *aa_load_ent_alloc(void); #define PACKED_FLAG_HAT 1 +#define PACKED_FLAG_DEBUG1 2 +#define PACKED_FLAG_DEBUG2 4 #define PACKED_MODE_ENFORCE 0 #define PACKED_MODE_COMPLAIN 1 diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h index 48ff1ddecad5..a912a5d5d04f 100644 --- a/security/apparmor/include/secid.h +++ b/security/apparmor/include/secid.h @@ -21,6 +21,9 @@ struct aa_label; /* secid value that matches any other secid */ #define AA_SECID_WILDCARD 1 +/* sysctl to enable displaying mode when converting secid to secctx */ +extern int apparmor_display_secid_mode; + struct aa_label *aa_secid_to_label(u32 secid); int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); @@ -31,6 +34,4 @@ int aa_alloc_secid(struct aa_label *label, gfp_t gfp); void aa_free_secid(u32 secid); void aa_secid_update(u32 secid, struct aa_label *label); -void aa_secids_init(void); - #endif /* __AA_SECID_H */ diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h index f13d12373b25..13437d62c70f 100644 --- a/security/apparmor/include/task.h +++ b/security/apparmor/include/task.h @@ -77,4 +77,22 @@ static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) ctx->token = 0; } +#define AA_PTRACE_TRACE MAY_WRITE +#define AA_PTRACE_READ MAY_READ +#define AA_MAY_BE_TRACED AA_MAY_APPEND +#define AA_MAY_BE_READ AA_MAY_CREATE +#define PTRACE_PERM_SHIFT 2 + +#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ + AA_MAY_BE_READ | AA_MAY_BE_TRACED) +#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) + +#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ + "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ + "xcpu xfsz vtalrm prof winch io pwr sys emt lost" + +int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, + u32 request); + + #endif /* __AA_TASK_H */ diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index fe36d112aad9..3dbbc59d440d 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -9,7 +9,6 @@ */ #include <linux/gfp.h> -#include <linux/ptrace.h> #include "include/audit.h" #include "include/capability.h" @@ -18,115 +17,6 @@ #include "include/ipc.h" #include "include/sig_names.h" -/** - * audit_ptrace_mask - convert mask to permission string - * @mask: permission mask to convert - * - * Returns: pointer to static string - */ -static const char *audit_ptrace_mask(u32 mask) -{ - switch (mask) { - case MAY_READ: - return "read"; - case MAY_WRITE: - return "trace"; - case AA_MAY_BE_READ: - return "readby"; - case AA_MAY_BE_TRACED: - return "tracedby"; - } - return ""; -} - -/* call back to audit ptrace fields */ -static void audit_ptrace_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - - if (aad(sa)->request & AA_PTRACE_PERM_MASK) { - audit_log_format(ab, " requested_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->request)); - - if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { - audit_log_format(ab, " denied_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->denied)); - } - } - audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, - FLAGS_NONE, GFP_ATOMIC); -} - -/* assumes check for PROFILE_MEDIATES is already done */ -/* TODO: conditionals */ -static int profile_ptrace_perm(struct aa_profile *profile, - struct aa_label *peer, u32 request, - struct common_audit_data *sa) -{ - struct aa_perms perms = { }; - - aad(sa)->peer = peer; - aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, - &perms); - aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); -} - -static int profile_tracee_perm(struct aa_profile *tracee, - struct aa_label *tracer, u32 request, - struct common_audit_data *sa) -{ - if (profile_unconfined(tracee) || unconfined(tracer) || - !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) - return 0; - - return profile_ptrace_perm(tracee, tracer, request, sa); -} - -static int profile_tracer_perm(struct aa_profile *tracer, - struct aa_label *tracee, u32 request, - struct common_audit_data *sa) -{ - if (profile_unconfined(tracer)) - return 0; - - if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) - return profile_ptrace_perm(tracer, tracee, request, sa); - - /* profile uses the old style capability check for ptrace */ - if (&tracer->label == tracee) - return 0; - - aad(sa)->label = &tracer->label; - aad(sa)->peer = tracee; - aad(sa)->request = 0; - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, - CAP_OPT_NONE); - - return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); -} - -/** - * aa_may_ptrace - test if tracer task can trace the tracee - * @tracer: label of the task doing the tracing (NOT NULL) - * @tracee: task label to be traced - * @request: permission request - * - * Returns: %0 else error code if permission denied or error - */ -int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - u32 request) -{ - struct aa_profile *profile; - u32 xrequest = request << PTRACE_PERM_SHIFT; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); - - return xcheck_labels(tracer, tracee, profile, - profile_tracer_perm(profile, tracee, request, &sa), - profile_tracee_perm(profile, tracer, xrequest, &sa)); -} - static inline int map_signal_num(int sig) { diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 0b0265da1926..0f36ee907438 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -197,18 +197,18 @@ static bool vec_is_stale(struct aa_profile **vec, int n) return false; } -static bool vec_unconfined(struct aa_profile **vec, int n) +static long union_vec_flags(struct aa_profile **vec, int n, long mask) { + long u = 0; int i; AA_BUG(!vec); for (i = 0; i < n; i++) { - if (!profile_unconfined(vec[i])) - return false; + u |= vec[i]->label.flags & mask; } - return true; + return u; } static int sort_cmp(const void *a, const void *b) @@ -485,7 +485,7 @@ int aa_label_next_confined(struct aa_label *label, int i) } /** - * aa_label_next_not_in_set - return the next profile of @sub not in @set + * __aa_label_next_not_in_set - return the next profile of @sub not in @set * @I: label iterator * @set: label to test against * @sub: label to if is subset of @set @@ -1097,8 +1097,8 @@ static struct aa_label *label_merge_insert(struct aa_label *new, else if (k == b->size) return aa_get_label(b); } - if (vec_unconfined(new->vec, new->size)) - new->flags |= FLAG_UNCONFINED; + new->flags |= union_vec_flags(new->vec, new->size, FLAG_UNCONFINED | + FLAG_DEBUG1 | FLAG_DEBUG2); ls = labels_set(new); write_lock_irqsave(&ls->lock, flags); label = __label_insert(labels_set(new), new, false); @@ -1631,9 +1631,9 @@ int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns, AA_BUG(!str && size != 0); AA_BUG(!label); - if (flags & FLAG_ABS_ROOT) { + if (AA_DEBUG_LABEL && (flags & FLAG_ABS_ROOT)) { ns = root_ns; - len = snprintf(str, size, "="); + len = snprintf(str, size, "_"); update_for_len(total, len, size, str); } else if (!ns) { ns = labels_ns(label); @@ -1744,7 +1744,7 @@ void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns, if (!use_label_hname(ns, label, flags) || display_mode(ns, label, flags)) { len = aa_label_asxprint(&name, ns, label, flags, gfp); - if (len == -1) { + if (len < 0) { AA_DEBUG("label print error"); return; } @@ -1772,7 +1772,7 @@ void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns, int len; len = aa_label_asxprint(&str, ns, label, flags, gfp); - if (len == -1) { + if (len < 0) { AA_DEBUG("label print error"); return; } @@ -1795,7 +1795,7 @@ void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags, int len; len = aa_label_asxprint(&str, ns, label, flags, gfp); - if (len == -1) { + if (len < 0) { AA_DEBUG("label print error"); return; } @@ -1895,7 +1895,8 @@ struct aa_label *aa_label_strn_parse(struct aa_label *base, const char *str, AA_BUG(!str); str = skipn_spaces(str, n); - if (str == NULL || (*str == '=' && base != &root_ns->unconfined->label)) + if (str == NULL || (AA_DEBUG_LABEL && *str == '_' && + base != &root_ns->unconfined->label)) return ERR_PTR(-EINVAL); len = label_count_strn_entries(str, end - str); @@ -2136,7 +2137,7 @@ static void __labelset_update(struct aa_ns *ns) } /** - * __aa_labelset_udate_subtree - update all labels with a stale component + * __aa_labelset_update_subtree - update all labels with a stale component * @ns: ns to start update at (NOT NULL) * * Requires: @ns lock be held diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index fa49b81eb54c..1c72a61108d3 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -136,7 +136,7 @@ __counted char *aa_str_alloc(int size, gfp_t gfp) { struct counted_str *str; - str = kmalloc(sizeof(struct counted_str) + size, gfp); + str = kmalloc(struct_size(str, name, size), gfp); if (!str) return NULL; @@ -322,22 +322,39 @@ static u32 map_other(u32 x) ((x & 0x60) << 19); /* SETOPT/GETOPT */ } +static u32 map_xbits(u32 x) +{ + return ((x & 0x1) << 7) | + ((x & 0x7e) << 9); +} + void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, struct aa_perms *perms) { + /* This mapping is convulated due to history. + * v1-v4: only file perms + * v5: added policydb which dropped in perm user conditional to + * gain new perm bits, but had to map around the xbits because + * the userspace compiler was still munging them. + * v9: adds using the xbits in policydb because the compiler now + * supports treating policydb permission bits different. + * Unfortunately there is not way to force auditing on the + * perms represented by the xbits + */ *perms = (struct aa_perms) { - .allow = dfa_user_allow(dfa, state), + .allow = dfa_user_allow(dfa, state) | + map_xbits(dfa_user_xbits(dfa, state)), .audit = dfa_user_audit(dfa, state), - .quiet = dfa_user_quiet(dfa, state), + .quiet = dfa_user_quiet(dfa, state) | + map_xbits(dfa_other_xbits(dfa, state)), }; - /* for v5 perm mapping in the policydb, the other set is used + /* for v5-v9 perm mapping in the policydb, the other set is used * to extend the general perm set */ perms->allow |= map_other(dfa_other_allow(dfa, state)); perms->audit |= map_other(dfa_other_audit(dfa, state)); perms->quiet |= map_other(dfa_other_quiet(dfa, state)); -// perms->xindex = dfa_user_xindex(dfa, state); } /** diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 900bc540656a..e29cade7b662 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -832,7 +832,7 @@ static void apparmor_sk_free_security(struct sock *sk) } /** - * apparmor_clone_security - clone the sk_security field + * apparmor_sk_clone_security - clone the sk_security field */ static void apparmor_sk_clone_security(const struct sock *sk, struct sock *newsk) @@ -886,10 +886,7 @@ static int apparmor_socket_post_create(struct socket *sock, int family, struct aa_label *label; if (kern) { - struct aa_ns *ns = aa_get_current_ns(); - - label = aa_get_label(ns_unconfined(ns)); - aa_put_ns(ns); + label = aa_get_label(kernel_t); } else label = aa_get_current_label(); @@ -937,7 +934,7 @@ static int apparmor_socket_connect(struct socket *sock, } /** - * apparmor_socket_list - check perms before allowing listen + * apparmor_socket_listen - check perms before allowing listen */ static int apparmor_socket_listen(struct socket *sock, int backlog) { @@ -1041,7 +1038,7 @@ static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock, } /** - * apparmor_getsockopt - check perms before getting socket options + * apparmor_socket_getsockopt - check perms before getting socket options */ static int apparmor_socket_getsockopt(struct socket *sock, int level, int optname) @@ -1051,7 +1048,7 @@ static int apparmor_socket_getsockopt(struct socket *sock, int level, } /** - * apparmor_setsockopt - check perms before setting socket options + * apparmor_socket_setsockopt - check perms before setting socket options */ static int apparmor_socket_setsockopt(struct socket *sock, int level, int optname) @@ -1070,7 +1067,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) #ifdef CONFIG_NETWORK_SECMARK /** - * apparmor_socket_sock_recv_skb - check perms before associating skb to sk + * apparmor_socket_sock_rcv_skb - check perms before associating skb to sk * * Note: can not sleep may be called with locks held * @@ -1357,6 +1354,12 @@ bool aa_g_hash_policy = IS_ENABLED(CONFIG_SECURITY_APPARMOR_HASH_DEFAULT); module_param_named(hash_policy, aa_g_hash_policy, aabool, S_IRUSR | S_IWUSR); #endif +/* whether policy exactly as loaded is retained for debug and checkpointing */ +bool aa_g_export_binary = IS_ENABLED(CONFIG_SECURITY_APPARMOR_EXPORT_BINARY); +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY +module_param_named(export_binary, aa_g_export_binary, aabool, 0600); +#endif + /* policy loaddata compression level */ int aa_g_rawdata_compression_level = Z_DEFAULT_COMPRESSION; module_param_named(rawdata_compression_level, aa_g_rawdata_compression_level, @@ -1399,7 +1402,7 @@ module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR); * DEPRECATED: read only as strict checking of load is always done now * that none root users (user namespaces) can load policy. */ -bool aa_g_paranoid_load = true; +bool aa_g_paranoid_load = IS_ENABLED(CONFIG_SECURITY_APPARMOR_PARANOID_LOAD); module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); static int param_get_aaintbool(char *buffer, const struct kernel_param *kp); @@ -1761,6 +1764,14 @@ static struct ctl_table apparmor_sysctl_table[] = { .mode = 0600, .proc_handler = apparmor_dointvec, }, + { + .procname = "apparmor_display_secid_mode", + .data = &apparmor_display_secid_mode, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = apparmor_dointvec, + }, + { } }; @@ -1819,11 +1830,8 @@ static const struct nf_hook_ops apparmor_nf_ops[] = { static int __net_init apparmor_nf_register(struct net *net) { - int ret; - - ret = nf_register_net_hooks(net, apparmor_nf_ops, + return nf_register_net_hooks(net, apparmor_nf_ops, ARRAY_SIZE(apparmor_nf_ops)); - return ret; } static void __net_exit apparmor_nf_unregister(struct net *net) @@ -1857,8 +1865,6 @@ static int __init apparmor_init(void) { int error; - aa_secids_init(); - error = aa_setup_dfa_engine(); if (error) { AA_ERROR("Unable to setup dfa engine\n"); diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index aa6fcfde3051..f61247241803 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c @@ -217,7 +217,6 @@ static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa, .allow = dfa_user_allow(dfa, state), .audit = dfa_user_audit(dfa, state), .quiet = dfa_user_quiet(dfa, state), - .xindex = dfa_user_xindex(dfa, state), }; return perms; @@ -229,7 +228,8 @@ static const char * const mnt_info_table[] = { "failed srcname match", "failed type match", "failed flags match", - "failed data match" + "failed data match", + "failed perms check" }; /* @@ -284,8 +284,8 @@ static int do_match_mnt(struct aa_dfa *dfa, unsigned int start, return 0; } - /* failed at end of flags match */ - return 4; + /* failed at perms check, don't confuse with flags match */ + return 6; } @@ -303,7 +303,7 @@ static int path_flags(struct aa_profile *profile, const struct path *path) * @profile: the confining profile * @mntpath: for the mntpnt (NOT NULL) * @buffer: buffer to be used to lookup mntpath - * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR) + * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR) * @type: string for the dev type (MAYBE NULL) * @flags: mount flags to match * @data: fs mount data (MAYBE NULL) @@ -358,7 +358,7 @@ audit: /** * match_mnt - handle path matching for mount * @profile: the confining profile - * @mntpath: for the mntpnt (NOT NULL) + * @path: for the mntpnt (NOT NULL) * @buffer: buffer to be used to lookup mntpath * @devpath: path devname/src_name (MAYBE NULL) * @devbuffer: buffer to be used to lookup devname/src_name @@ -718,6 +718,7 @@ int aa_pivotroot(struct aa_label *label, const struct path *old_path, aa_put_label(target); goto out; } + aa_put_label(target); } else /* already audited error */ error = PTR_ERR(target); diff --git a/security/apparmor/net.c b/security/apparmor/net.c index e0c1b50d6edd..7efe4d17273d 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -145,12 +145,13 @@ int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, struct sock *sk) { + struct aa_sk_ctx *ctx = SK_CTX(sk); int error = 0; AA_BUG(!label); AA_BUG(!sk); - if (!unconfined(label)) { + if (ctx->label != kernel_t && !unconfined(label)) { struct aa_profile *profile; DEFINE_AUDIT_SK(sa, op, sk); diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index b0cbc4906cb3..499c0209b6a4 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -422,7 +422,7 @@ static struct aa_profile *__lookup_profile(struct aa_policy *base, } /** - * aa_lookup_profile - find a profile by its full or partial name + * aa_lookupn_profile - find a profile by its full or partial name * @ns: the namespace to start from (NOT NULL) * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL) * @n: size of @hname @@ -952,16 +952,18 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, mutex_lock_nested(&ns->lock, ns->level); /* check for duplicate rawdata blobs: space and file dedup */ - list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { - if (aa_rawdata_eq(rawdata_ent, udata)) { - struct aa_loaddata *tmp; - - tmp = __aa_get_loaddata(rawdata_ent); - /* check we didn't fail the race */ - if (tmp) { - aa_put_loaddata(udata); - udata = tmp; - break; + if (!list_empty(&ns->rawdata_list)) { + list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { + if (aa_rawdata_eq(rawdata_ent, udata)) { + struct aa_loaddata *tmp; + + tmp = __aa_get_loaddata(rawdata_ent); + /* check we didn't fail the race */ + if (tmp) { + aa_put_loaddata(udata); + udata = tmp; + break; + } } } } @@ -969,7 +971,8 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, list_for_each_entry(ent, &lh, list) { struct aa_policy *policy; - ent->new->rawdata = aa_get_loaddata(udata); + if (aa_g_export_binary) + ent->new->rawdata = aa_get_loaddata(udata); error = __lookup_replace(ns, ent->new->base.hname, !(mask & AA_MAY_REPLACE_POLICY), &ent->old, &info); @@ -1009,7 +1012,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, } /* create new fs entries for introspection if needed */ - if (!udata->dents[AAFS_LOADDATA_DIR]) { + if (!udata->dents[AAFS_LOADDATA_DIR] && aa_g_export_binary) { error = __aa_fs_create_rawdata(ns, udata); if (error) { info = "failed to create raw_data dir and files"; @@ -1037,12 +1040,14 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, /* Done with checks that may fail - do actual replacement */ __aa_bump_ns_revision(ns); - __aa_loaddata_update(udata, ns->revision); + if (aa_g_export_binary) + __aa_loaddata_update(udata, ns->revision); list_for_each_entry_safe(ent, tmp, &lh, list) { list_del_init(&ent->list); op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL; - if (ent->old && ent->old->rawdata == ent->new->rawdata) { + if (ent->old && ent->old->rawdata == ent->new->rawdata && + ent->new->rawdata) { /* dedup actual profile replacement */ audit_policy(label, op, ns_name, ent->new->base.hname, "same as current profile, skipping", diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c index 70921d95fb40..43beaad083fe 100644 --- a/security/apparmor/policy_ns.c +++ b/security/apparmor/policy_ns.c @@ -22,6 +22,9 @@ #include "include/label.h" #include "include/policy.h" +/* kernel label */ +struct aa_label *kernel_t; + /* root profile namespace */ struct aa_ns *root_ns; const char *aa_hidden_ns_name = "---"; @@ -51,10 +54,10 @@ bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns) } /** - * aa_na_name - Find the ns name to display for @view from @curr - * @curr - current namespace (NOT NULL) - * @view - namespace attempting to view (NOT NULL) - * @subns - are subns visible + * aa_ns_name - Find the ns name to display for @view from @curr + * @curr: current namespace (NOT NULL) + * @view: namespace attempting to view (NOT NULL) + * @subns: are subns visible * * Returns: name of @view visible from @curr */ @@ -77,6 +80,23 @@ const char *aa_ns_name(struct aa_ns *curr, struct aa_ns *view, bool subns) return aa_hidden_ns_name; } +static struct aa_profile *alloc_unconfined(const char *name) +{ + struct aa_profile *profile; + + profile = aa_alloc_profile(name, NULL, GFP_KERNEL); + if (!profile) + return NULL; + + profile->label.flags |= FLAG_IX_ON_NAME_ERROR | + FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; + profile->mode = APPARMOR_UNCONFINED; + profile->file.dfa = aa_get_dfa(nulldfa); + profile->policy.dfa = aa_get_dfa(nulldfa); + + return profile; +} + /** * alloc_ns - allocate, initialize and return a new namespace * @prefix: parent namespace name (MAYBE NULL) @@ -101,16 +121,9 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) init_waitqueue_head(&ns->wait); /* released by aa_free_ns() */ - ns->unconfined = aa_alloc_profile("unconfined", NULL, GFP_KERNEL); + ns->unconfined = alloc_unconfined("unconfined"); if (!ns->unconfined) goto fail_unconfined; - - ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | - FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; - ns->unconfined->mode = APPARMOR_UNCONFINED; - ns->unconfined->file.dfa = aa_get_dfa(nulldfa); - ns->unconfined->policy.dfa = aa_get_dfa(nulldfa); - /* ns and ns->unconfined share ns->unconfined refcount */ ns->unconfined->ns = ns; @@ -187,7 +200,7 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) /** * __aa_lookupn_ns - lookup the namespace matching @hname - * @base: base list to start looking up profile name from (NOT NULL) + * @view: namespace to search in (NOT NULL) * @hname: hierarchical ns name (NOT NULL) * @n: length of @hname * @@ -272,7 +285,7 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, } /** - * aa_create_ns - create an ns, fail if it already exists + * __aa_find_or_create_ns - create an ns, fail if it already exists * @parent: the parent of the namespace being created * @name: the name of the namespace * @dir: if not null the dir to put the ns entries in @@ -388,11 +401,22 @@ static void __ns_list_release(struct list_head *head) */ int __init aa_alloc_root_ns(void) { + struct aa_profile *kernel_p; + /* released by aa_free_root_ns - used as list ref*/ root_ns = alloc_ns(NULL, "root"); if (!root_ns) return -ENOMEM; + kernel_p = alloc_unconfined("kernel_t"); + if (!kernel_p) { + destroy_ns(root_ns); + aa_free_ns(root_ns); + return -ENOMEM; + } + kernel_t = &kernel_p->label; + root_ns->unconfined->ns = aa_get_ns(root_ns); + return 0; } @@ -405,6 +429,7 @@ void __init aa_free_root_ns(void) root_ns = NULL; + aa_label_free(kernel_t); destroy_ns(ns); aa_put_ns(ns); } diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 0acca6f2a93f..55d31bac4f35 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -125,15 +125,16 @@ void __aa_loaddata_update(struct aa_loaddata *data, long revision) { AA_BUG(!data); AA_BUG(!data->ns); - AA_BUG(!data->dents[AAFS_LOADDATA_REVISION]); AA_BUG(!mutex_is_locked(&data->ns->lock)); AA_BUG(data->revision > revision); data->revision = revision; - d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime = - current_time(d_inode(data->dents[AAFS_LOADDATA_DIR])); - d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime = - current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION])); + if ((data->dents[AAFS_LOADDATA_REVISION])) { + d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime = + current_time(d_inode(data->dents[AAFS_LOADDATA_DIR])); + d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime = + current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION])); + } } bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r) @@ -213,7 +214,7 @@ static void *kvmemdup(const void *src, size_t len) } /** - * aa_u16_chunck - test and do bounds checking for a u16 size based chunk + * unpack_u16_chunk - test and do bounds checking for a u16 size based chunk * @e: serialized data read head (NOT NULL) * @chunk: start address for chunk of data (NOT NULL) * @@ -456,7 +457,9 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e) ((e->pos - e->start) & 7); size_t pad = ALIGN(sz, 8) - sz; int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32) | DFA_FLAG_VERIFY_STATES; + TO_ACCEPT2_FLAG(YYTD_DATA32); + if (aa_g_paranoid_load) + flags |= DFA_FLAG_VERIFY_STATES; dfa = aa_dfa_unpack(blob + pad, size - pad, flags); if (IS_ERR(dfa)) @@ -668,6 +671,7 @@ static int datacmp(struct rhashtable_compare_arg *arg, const void *obj) /** * unpack_profile - unpack a serialized profile * @e: serialized data extent information (NOT NULL) + * @ns_name: pointer of newly allocated copy of %NULL in case of error * * NOTE: unpack profile sets audit struct if there is a failure */ @@ -744,18 +748,24 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) goto fail; if (tmp & PACKED_FLAG_HAT) profile->label.flags |= FLAG_HAT; + if (tmp & PACKED_FLAG_DEBUG1) + profile->label.flags |= FLAG_DEBUG1; + if (tmp & PACKED_FLAG_DEBUG2) + profile->label.flags |= FLAG_DEBUG2; if (!unpack_u32(e, &tmp, NULL)) goto fail; - if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) + if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) { profile->mode = APPARMOR_COMPLAIN; - else if (tmp == PACKED_MODE_ENFORCE) + } else if (tmp == PACKED_MODE_ENFORCE) { profile->mode = APPARMOR_ENFORCE; - else if (tmp == PACKED_MODE_KILL) + } else if (tmp == PACKED_MODE_KILL) { profile->mode = APPARMOR_KILL; - else if (tmp == PACKED_MODE_UNCONFINED) + } else if (tmp == PACKED_MODE_UNCONFINED) { profile->mode = APPARMOR_UNCONFINED; - else + profile->label.flags |= FLAG_UNCONFINED; + } else { goto fail; + } if (!unpack_u32(e, &tmp, NULL)) goto fail; if (tmp) @@ -936,7 +946,7 @@ fail: } /** - * verify_head - unpack serialized stream header + * verify_header - unpack serialized stream header * @e: serialized data read head (NOT NULL) * @required: whether the header is required or optional * @ns: Returns - namespace if one is specified else NULL (NOT NULL) @@ -1052,6 +1062,7 @@ struct aa_load_ent *aa_load_ent_alloc(void) static int deflate_compress(const char *src, size_t slen, char **dst, size_t *dlen) { +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY int error; struct z_stream_s strm; void *stgbuf, *dstbuf; @@ -1123,6 +1134,10 @@ fail_deflate_init: fail_deflate: kvfree(stgbuf); goto fail_stg_alloc; +#else + *dlen = slen; + return 0; +#endif } static int compress_loaddata(struct aa_loaddata *data) @@ -1141,7 +1156,8 @@ static int compress_loaddata(struct aa_loaddata *data) if (error) return error; - kvfree(udata); + if (udata != data->data) + kvfree(udata); } else data->compressed_size = data->size; @@ -1216,9 +1232,12 @@ int aa_unpack(struct aa_loaddata *udata, struct list_head *lh, goto fail; } } - error = compress_loaddata(udata); - if (error) - goto fail; + + if (aa_g_export_binary) { + error = compress_loaddata(udata); + if (error) + goto fail; + } return 0; fail_profile: diff --git a/security/apparmor/policy_unpack_test.c b/security/apparmor/policy_unpack_test.c index 7954cb23d5f2..0a969b2e03db 100644 --- a/security/apparmor/policy_unpack_test.c +++ b/security/apparmor/policy_unpack_test.c @@ -48,8 +48,8 @@ struct policy_unpack_fixture { size_t e_size; }; -struct aa_ext *build_aa_ext_struct(struct policy_unpack_fixture *puf, - struct kunit *test, size_t buf_size) +static struct aa_ext *build_aa_ext_struct(struct policy_unpack_fixture *puf, + struct kunit *test, size_t buf_size) { char *buf; struct aa_ext *e; @@ -439,7 +439,7 @@ static void policy_unpack_test_unpack_u32_with_null_name(struct kunit *test) { struct policy_unpack_fixture *puf = test->priv; bool success; - u32 data; + u32 data = 0; puf->e->pos += TEST_U32_BUF_OFFSET; @@ -456,7 +456,7 @@ static void policy_unpack_test_unpack_u32_with_name(struct kunit *test) struct policy_unpack_fixture *puf = test->priv; const char name[] = TEST_U32_NAME; bool success; - u32 data; + u32 data = 0; puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; @@ -473,7 +473,7 @@ static void policy_unpack_test_unpack_u32_out_of_bounds(struct kunit *test) struct policy_unpack_fixture *puf = test->priv; const char name[] = TEST_U32_NAME; bool success; - u32 data; + u32 data = 0; puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; puf->e->end = puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32); @@ -489,7 +489,7 @@ static void policy_unpack_test_unpack_u64_with_null_name(struct kunit *test) { struct policy_unpack_fixture *puf = test->priv; bool success; - u64 data; + u64 data = 0; puf->e->pos += TEST_U64_BUF_OFFSET; @@ -506,7 +506,7 @@ static void policy_unpack_test_unpack_u64_with_name(struct kunit *test) struct policy_unpack_fixture *puf = test->priv; const char name[] = TEST_U64_NAME; bool success; - u64 data; + u64 data = 0; puf->e->pos += TEST_NAMED_U64_BUF_OFFSET; @@ -523,7 +523,7 @@ static void policy_unpack_test_unpack_u64_out_of_bounds(struct kunit *test) struct policy_unpack_fixture *puf = test->priv; const char name[] = TEST_U64_NAME; bool success; - u64 data; + u64 data = 0; puf->e->pos += TEST_NAMED_U64_BUF_OFFSET; puf->e->end = puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64); diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c index fde332e0ea7d..86ad26ef72ed 100644 --- a/security/apparmor/procattr.c +++ b/security/apparmor/procattr.c @@ -90,7 +90,7 @@ static char *split_token_from_name(const char *op, char *args, u64 *token) } /** - * aa_setprocattr_chagnehat - handle procattr interface to change_hat + * aa_setprocattr_changehat - handle procattr interface to change_hat * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL) * @size: size of the args * @flags: set of flags governing behavior diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c index ce545f99259e..24a0e23f1b2b 100644 --- a/security/apparmor/secid.c +++ b/security/apparmor/secid.c @@ -13,9 +13,9 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/gfp.h> -#include <linux/idr.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/xarray.h> #include "include/cred.h" #include "include/lib.h" @@ -29,8 +29,9 @@ */ #define AA_FIRST_SECID 2 -static DEFINE_IDR(aa_secids); -static DEFINE_SPINLOCK(secid_lock); +static DEFINE_XARRAY_FLAGS(aa_secids, XA_FLAGS_LOCK_IRQ | XA_FLAGS_TRACK_FREE); + +int apparmor_display_secid_mode; /* * TODO: allow policy to reserve a secid range? @@ -47,9 +48,9 @@ void aa_secid_update(u32 secid, struct aa_label *label) { unsigned long flags; - spin_lock_irqsave(&secid_lock, flags); - idr_replace(&aa_secids, label, secid); - spin_unlock_irqrestore(&secid_lock, flags); + xa_lock_irqsave(&aa_secids, flags); + __xa_store(&aa_secids, secid, label, 0); + xa_unlock_irqrestore(&aa_secids, flags); } /** @@ -58,19 +59,14 @@ void aa_secid_update(u32 secid, struct aa_label *label) */ struct aa_label *aa_secid_to_label(u32 secid) { - struct aa_label *label; - - rcu_read_lock(); - label = idr_find(&aa_secids, secid); - rcu_read_unlock(); - - return label; + return xa_load(&aa_secids, secid); } int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { /* TODO: cache secctx and ref count so we don't have to recreate */ struct aa_label *label = aa_secid_to_label(secid); + int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT; int len; AA_BUG(!seclen); @@ -78,15 +74,15 @@ int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) if (!label) return -EINVAL; + if (apparmor_display_secid_mode) + flags |= FLAG_SHOW_MODE; + if (secdata) len = aa_label_asxprint(secdata, root_ns, label, - FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | - FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT, - GFP_ATOMIC); + flags, GFP_ATOMIC); else - len = aa_label_snxprint(NULL, 0, root_ns, label, - FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | - FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT); + len = aa_label_snxprint(NULL, 0, root_ns, label, flags); + if (len < 0) return -ENOMEM; @@ -126,19 +122,16 @@ int aa_alloc_secid(struct aa_label *label, gfp_t gfp) unsigned long flags; int ret; - idr_preload(gfp); - spin_lock_irqsave(&secid_lock, flags); - ret = idr_alloc(&aa_secids, label, AA_FIRST_SECID, 0, GFP_ATOMIC); - spin_unlock_irqrestore(&secid_lock, flags); - idr_preload_end(); + xa_lock_irqsave(&aa_secids, flags); + ret = __xa_alloc(&aa_secids, &label->secid, label, + XA_LIMIT(AA_FIRST_SECID, INT_MAX), gfp); + xa_unlock_irqrestore(&aa_secids, flags); if (ret < 0) { label->secid = AA_SECID_INVALID; return ret; } - AA_BUG(ret == AA_SECID_INVALID); - label->secid = ret; return 0; } @@ -150,12 +143,7 @@ void aa_free_secid(u32 secid) { unsigned long flags; - spin_lock_irqsave(&secid_lock, flags); - idr_remove(&aa_secids, secid); - spin_unlock_irqrestore(&secid_lock, flags); -} - -void aa_secids_init(void) -{ - idr_init_base(&aa_secids, AA_FIRST_SECID); + xa_lock_irqsave(&aa_secids, flags); + __xa_erase(&aa_secids, secid); + xa_unlock_irqrestore(&aa_secids, flags); } diff --git a/security/apparmor/task.c b/security/apparmor/task.c index d17130ee6795..503dc0877fb1 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c @@ -12,7 +12,12 @@ * should return to the previous cred if it has not been modified. */ +#include <linux/gfp.h> +#include <linux/ptrace.h> + +#include "include/audit.h" #include "include/cred.h" +#include "include/policy.h" #include "include/task.h" /** @@ -177,3 +182,112 @@ int aa_restore_previous_label(u64 token) return 0; } + +/** + * audit_ptrace_mask - convert mask to permission string + * @mask: permission mask to convert + * + * Returns: pointer to static string + */ +static const char *audit_ptrace_mask(u32 mask) +{ + switch (mask) { + case MAY_READ: + return "read"; + case MAY_WRITE: + return "trace"; + case AA_MAY_BE_READ: + return "readby"; + case AA_MAY_BE_TRACED: + return "tracedby"; + } + return ""; +} + +/* call back to audit ptrace fields */ +static void audit_ptrace_cb(struct audit_buffer *ab, void *va) +{ + struct common_audit_data *sa = va; + + if (aad(sa)->request & AA_PTRACE_PERM_MASK) { + audit_log_format(ab, " requested_mask=\"%s\"", + audit_ptrace_mask(aad(sa)->request)); + + if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { + audit_log_format(ab, " denied_mask=\"%s\"", + audit_ptrace_mask(aad(sa)->denied)); + } + } + audit_log_format(ab, " peer="); + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + FLAGS_NONE, GFP_ATOMIC); +} + +/* assumes check for PROFILE_MEDIATES is already done */ +/* TODO: conditionals */ +static int profile_ptrace_perm(struct aa_profile *profile, + struct aa_label *peer, u32 request, + struct common_audit_data *sa) +{ + struct aa_perms perms = { }; + + aad(sa)->peer = peer; + aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, + &perms); + aa_apply_modes_to_perms(profile, &perms); + return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); +} + +static int profile_tracee_perm(struct aa_profile *tracee, + struct aa_label *tracer, u32 request, + struct common_audit_data *sa) +{ + if (profile_unconfined(tracee) || unconfined(tracer) || + !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) + return 0; + + return profile_ptrace_perm(tracee, tracer, request, sa); +} + +static int profile_tracer_perm(struct aa_profile *tracer, + struct aa_label *tracee, u32 request, + struct common_audit_data *sa) +{ + if (profile_unconfined(tracer)) + return 0; + + if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) + return profile_ptrace_perm(tracer, tracee, request, sa); + + /* profile uses the old style capability check for ptrace */ + if (&tracer->label == tracee) + return 0; + + aad(sa)->label = &tracer->label; + aad(sa)->peer = tracee; + aad(sa)->request = 0; + aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, + CAP_OPT_NONE); + + return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); +} + +/** + * aa_may_ptrace - test if tracer task can trace the tracee + * @tracer: label of the task doing the tracing (NOT NULL) + * @tracee: task label to be traced + * @request: permission request + * + * Returns: %0 else error code if permission denied or error + */ +int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, + u32 request) +{ + struct aa_profile *profile; + u32 xrequest = request << PTRACE_PERM_SHIFT; + DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); + + return xcheck_labels(tracer, tracee, profile, + profile_tracer_perm(profile, tracee, request, &sa), + profile_tracee_perm(profile, tracer, xrequest, &sa)); +} diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild index 33543231d453..500be85729cc 100644 --- a/tools/testing/cxl/Kbuild +++ b/tools/testing/cxl/Kbuild @@ -47,6 +47,7 @@ cxl_core-y += $(CXL_CORE_SRC)/memdev.o cxl_core-y += $(CXL_CORE_SRC)/mbox.o cxl_core-y += $(CXL_CORE_SRC)/pci.o cxl_core-y += $(CXL_CORE_SRC)/hdm.o +cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o cxl_core-y += config_check.o obj-m += test/ diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c index 431f2bddf6c8..a072b2d3e726 100644 --- a/tools/testing/cxl/test/cxl.c +++ b/tools/testing/cxl/test/cxl.c @@ -14,7 +14,7 @@ #define NR_CXL_HOST_BRIDGES 2 #define NR_CXL_ROOT_PORTS 2 #define NR_CXL_SWITCH_PORTS 2 -#define NR_CXL_PORT_DECODERS 2 +#define NR_CXL_PORT_DECODERS 8 static struct platform_device *cxl_acpi; static struct platform_device *cxl_host_bridge[NR_CXL_HOST_BRIDGES]; @@ -118,7 +118,7 @@ static struct { .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 | ACPI_CEDT_CFMWS_RESTRICT_VOLATILE, .qtg_id = 0, - .window_size = SZ_256M, + .window_size = SZ_256M * 4UL, }, .target = { 0 }, }, @@ -133,7 +133,7 @@ static struct { .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 | ACPI_CEDT_CFMWS_RESTRICT_VOLATILE, .qtg_id = 1, - .window_size = SZ_256M * 2, + .window_size = SZ_256M * 8UL, }, .target = { 0, 1, }, }, @@ -148,7 +148,7 @@ static struct { .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 | ACPI_CEDT_CFMWS_RESTRICT_PMEM, .qtg_id = 2, - .window_size = SZ_256M, + .window_size = SZ_256M * 4UL, }, .target = { 0 }, }, @@ -163,7 +163,7 @@ static struct { .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 | ACPI_CEDT_CFMWS_RESTRICT_PMEM, .qtg_id = 3, - .window_size = SZ_256M * 2, + .window_size = SZ_256M * 8UL, }, .target = { 0, 1, }, }, @@ -429,6 +429,50 @@ static int map_targets(struct device *dev, void *data) return 0; } +static int mock_decoder_commit(struct cxl_decoder *cxld) +{ + struct cxl_port *port = to_cxl_port(cxld->dev.parent); + int id = cxld->id; + + if (cxld->flags & CXL_DECODER_F_ENABLE) + return 0; + + dev_dbg(&port->dev, "%s commit\n", dev_name(&cxld->dev)); + if (port->commit_end + 1 != id) { + dev_dbg(&port->dev, + "%s: out of order commit, expected decoder%d.%d\n", + dev_name(&cxld->dev), port->id, port->commit_end + 1); + return -EBUSY; + } + + port->commit_end++; + cxld->flags |= CXL_DECODER_F_ENABLE; + + return 0; +} + +static int mock_decoder_reset(struct cxl_decoder *cxld) +{ + struct cxl_port *port = to_cxl_port(cxld->dev.parent); + int id = cxld->id; + + if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0) + return 0; + + dev_dbg(&port->dev, "%s reset\n", dev_name(&cxld->dev)); + if (port->commit_end != id) { + dev_dbg(&port->dev, + "%s: out of order reset, expected decoder%d.%d\n", + dev_name(&cxld->dev), port->id, port->commit_end); + return -EBUSY; + } + + port->commit_end--; + cxld->flags &= ~CXL_DECODER_F_ENABLE; + + return 0; +} + static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) { struct cxl_port *port = cxlhdm->port; @@ -451,25 +495,39 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) struct cxl_decoder *cxld; int rc; - if (target_count) - cxld = cxl_switch_decoder_alloc(port, target_count); - else - cxld = cxl_endpoint_decoder_alloc(port); - if (IS_ERR(cxld)) { - dev_warn(&port->dev, - "Failed to allocate the decoder\n"); - return PTR_ERR(cxld); + if (target_count) { + struct cxl_switch_decoder *cxlsd; + + cxlsd = cxl_switch_decoder_alloc(port, target_count); + if (IS_ERR(cxlsd)) { + dev_warn(&port->dev, + "Failed to allocate the decoder\n"); + return PTR_ERR(cxlsd); + } + cxld = &cxlsd->cxld; + } else { + struct cxl_endpoint_decoder *cxled; + + cxled = cxl_endpoint_decoder_alloc(port); + + if (IS_ERR(cxled)) { + dev_warn(&port->dev, + "Failed to allocate the decoder\n"); + return PTR_ERR(cxled); + } + cxld = &cxled->cxld; } - cxld->decoder_range = (struct range) { + cxld->hpa_range = (struct range) { .start = 0, .end = -1, }; - cxld->flags = CXL_DECODER_F_ENABLE; cxld->interleave_ways = min_not_zero(target_count, 1); cxld->interleave_granularity = SZ_4K; cxld->target_type = CXL_DECODER_EXPANDER; + cxld->commit = mock_decoder_commit; + cxld->reset = mock_decoder_reset; if (target_count) { rc = device_for_each_child(port->uport, &ctx, @@ -569,44 +627,6 @@ static void mock_companion(struct acpi_device *adev, struct device *dev) #define SZ_512G (SZ_64G * 8) #endif -static struct platform_device *alloc_memdev(int id) -{ - struct resource res[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_MEM, - .desc = IORES_DESC_PERSISTENT_MEMORY, - }, - }; - struct platform_device *pdev; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(res); i++) { - struct cxl_mock_res *r = alloc_mock_res(SZ_256M); - - if (!r) - return NULL; - res[i].start = r->range.start; - res[i].end = r->range.end; - } - - pdev = platform_device_alloc("cxl_mem", id); - if (!pdev) - return NULL; - - rc = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); - if (rc) - goto err; - - return pdev; - -err: - platform_device_put(pdev); - return NULL; -} - static __init int cxl_test_init(void) { int rc, i; @@ -619,7 +639,8 @@ static __init int cxl_test_init(void) goto err_gen_pool_create; } - rc = gen_pool_add(cxl_mock_pool, SZ_512G, SZ_64G, NUMA_NO_NODE); + rc = gen_pool_add(cxl_mock_pool, iomem_resource.end + 1 - SZ_64G, + SZ_64G, NUMA_NO_NODE); if (rc) goto err_gen_pool_add; @@ -708,7 +729,7 @@ static __init int cxl_test_init(void) struct platform_device *dport = cxl_switch_dport[i]; struct platform_device *pdev; - pdev = alloc_memdev(i); + pdev = platform_device_alloc("cxl_mem", i); if (!pdev) goto err_mem; pdev->dev.parent = &dport->dev; diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index 6b9239b2afd4..aa2df3a15051 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -10,6 +10,7 @@ #include <cxlmem.h> #define LSA_SIZE SZ_128K +#define DEV_SIZE SZ_2G #define EFFECT(x) (1U << x) static struct cxl_cel_entry mock_cel[] = { @@ -26,6 +27,10 @@ static struct cxl_cel_entry mock_cel[] = { .effect = cpu_to_le16(0), }, { + .opcode = cpu_to_le16(CXL_MBOX_OP_GET_PARTITION_INFO), + .effect = cpu_to_le16(0), + }, + { .opcode = cpu_to_le16(CXL_MBOX_OP_SET_LSA), .effect = cpu_to_le16(EFFECT(1) | EFFECT(2)), }, @@ -97,42 +102,37 @@ static int mock_get_log(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) { - struct platform_device *pdev = to_platform_device(cxlds->dev); struct cxl_mbox_identify id = { .fw_revision = { "mock fw v1 " }, .lsa_size = cpu_to_le32(LSA_SIZE), - /* FIXME: Add partition support */ - .partition_align = cpu_to_le64(0), + .partition_align = + cpu_to_le64(SZ_256M / CXL_CAPACITY_MULTIPLIER), + .total_capacity = + cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER), }; - u64 capacity = 0; - int i; if (cmd->size_out < sizeof(id)) return -EINVAL; - for (i = 0; i < 2; i++) { - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) - break; - - capacity += resource_size(res) / CXL_CAPACITY_MULTIPLIER; + memcpy(cmd->payload_out, &id, sizeof(id)); - if (le64_to_cpu(id.partition_align)) - continue; + return 0; +} - if (res->desc == IORES_DESC_PERSISTENT_MEMORY) - id.persistent_capacity = cpu_to_le64( - resource_size(res) / CXL_CAPACITY_MULTIPLIER); - else - id.volatile_capacity = cpu_to_le64( - resource_size(res) / CXL_CAPACITY_MULTIPLIER); - } +static int mock_partition_info(struct cxl_dev_state *cxlds, + struct cxl_mbox_cmd *cmd) +{ + struct cxl_mbox_get_partition_info pi = { + .active_volatile_cap = + cpu_to_le64(DEV_SIZE / 2 / CXL_CAPACITY_MULTIPLIER), + .active_persistent_cap = + cpu_to_le64(DEV_SIZE / 2 / CXL_CAPACITY_MULTIPLIER), + }; - id.total_capacity = cpu_to_le64(capacity); + if (cmd->size_out < sizeof(pi)) + return -EINVAL; - memcpy(cmd->payload_out, &id, sizeof(id)); + memcpy(cmd->payload_out, &pi, sizeof(pi)); return 0; } @@ -221,6 +221,9 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd * case CXL_MBOX_OP_GET_LSA: rc = mock_get_lsa(cxlds, cmd); break; + case CXL_MBOX_OP_GET_PARTITION_INFO: + rc = mock_partition_info(cxlds, cmd); + break; case CXL_MBOX_OP_SET_LSA: rc = mock_set_lsa(cxlds, cmd); break; @@ -282,7 +285,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); - if (range_len(&cxlds->pmem_range) && IS_ENABLED(CONFIG_CXL_PMEM)) + if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) rc = devm_cxl_add_nvdimm(dev, cxlmd); return 0; diff --git a/tools/testing/cxl/test/mock.c b/tools/testing/cxl/test/mock.c index f1f8c40948c5..bce6a21df0d5 100644 --- a/tools/testing/cxl/test/mock.c +++ b/tools/testing/cxl/test/mock.c @@ -208,13 +208,15 @@ int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) } EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); -bool __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, - struct cxl_hdm *cxlhdm) +int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, + struct cxl_hdm *cxlhdm) { int rc = 0, index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); - if (!ops || !ops->is_mock_dev(cxlds->dev)) + if (ops && ops->is_mock_dev(cxlds->dev)) + rc = 0; + else rc = cxl_hdm_decode_init(cxlds, cxlhdm); put_cxl_mock_ops(index); |