All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 0/7] LPC: legacy ISA I/O support
@ 2017-05-25 11:37 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patchset supports the IPMI-bt device attached to the Low-Pin-Count
interface implemented on Hisilicon Hip06/Hip07 SoC.
                        -----------
                        | LPC host|
                        |         |
                        -----------
                             |
                _____________V_______________LPC
                  |                       |
                  V                       V
                                     ------------
                                     |  BT(ipmi)|
                                     ------------

When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
the target peripherals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out accessors are based
on MMIO ranges; on Hip06/Hip07 LPC the I/O accesses are performed through driver
specific accessors rather than MMIO.
To solve this issue and keep the relevant existing peripherals' drivers untouched,
this patchset:
   - introduces a generic I/O space management framework, LIBIO, to support I/O
     operations on host controllers operating either on MMIO buses or on buses
     requiring specific driver I/O accessors;
   - redefines the in/out accessors to provide a unified interface for both MMIO
     and driver specific I/O operations. Using LIBIO, th call of in/out() from
     the host children drivers, such as ipmi-si, will be redirected to the
     corresponding device-specific I/O hooks to perform the I/O accesses.

 Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals can
 be supported without any changes on the existing ipmi-si driver.

 The whole patchset has been tested on Hip07 D05 board both using DTB and ACPI.

Changes from v8:
  - Simplified LIB IO framewrok
  - Moved INDIRECT PIO ACPI framework under acpi/arm64
  - Renamed occurrences of "lib io" and "indirect io" to "lib pio" and
    "indirect pio" to keep the patchset nomenclature consistent
  - Removed Alignment reuqirements
  - Moved LPC specific code out of ACPI common framework
  - Now PIO indirect HW ranges can overlap
  - Changed HiSilicon LPC driver maintainer (Gabriele Paoloni now) and split
    maintaner file modifications in a separate commit
  - Removed the commit with the DT nodes support for hip06 and hip07 (to be
    pushed separately)
  - Added a checking on ioport_map() not to break that function as Arnd points
    out in V7 review thread;
  - fixed the compile issues on alpha, m68k;

Changes from V7:
  - Based on Arnd's comment, rename the LIBIO as LOGIC_PIO;
  - Improved the mapping process in LOGIC_PIO to gain better efficiency when
    redirecting the I/O accesses to right device driver;
  - To reduce the impact on PCI MMIO to a minimum, add a new
    CONFIG_INDIRECT_PIO for indirect-IO hosts/devices;
  - Added a new ACPI handler for indirect-IO hosts/devices;
  - Fixed the compile issues on V6;

Changes from V6:
  - According to the comments from Bjorn and Alex, merge PCI IO and indirect-IO
    into a generic I/O space management, LIBIO;
  - Adopted the '_DEP' to replace the platform bus notifier. In this way, we can
    ensure the LPC peripherals' I/O resources had been translated to logical IO
    before the LPC peripheral enumeration;
  - Replaced the rwlock with rcu list based on Alex's suggestion;
  - Applied relaxed write/read to LPC driver;
  - Some bugs fixing and some optimazations based on the comments of V6;

Changes from V5:
  - Made the extio driver more generic and locate in lib/;
  - Supported multiple indirect-IO bus instances;
  - Extended the pci_register_io_range() to support indirect-IO, then dropped
  the I/O reservation used in previous patchset;
  - Reimplemented the ACPI LPC support;
  - Fixed some bugs, including the compile error on other archs, the module
  building failure found by Ming Lei, etc;

Changes from V4:
  - Some revises based on the comments from Bjorn, Rob on V4;
  - Fixed the compile error on some platforms, such as openrisc;

Changes from V3:
  - UART support deferred to a separate patchset; This patchset only support
  ipmi device under LPC;
  - LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
  from PCI/PCIE PIO space;
  - Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
  added a new fixup function, of_isa_indirect_io(), to get the I/O address
  directly from LPC dts configurations;
  - Support in(w,l)/out(w,l) for Hip06 lpc I/O;
  - Decouple the header file dependency on the gerenic io.h by defining in/out
  as normal functions in c file;
  - removed unused macro definitions in the LPC driver;

Changes from V2:
  - Support the PIO retrieval from the linux PIO generated by
  pci_address_to_pio. This method replace the 4K PIO reservation in V2;
  - Support the flat-tree earlycon;
  - Some revises based on Arnd's remarks;
  - Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
  from non-ZERO;

Changes from V1:
  - Support the ACPI LPC device;
  - Optimize the dts LPC driver in ISA compatible mode;
  - Reserve the IO range below 4K in avoid the possible conflict with PCI host
  IO ranges;
  - Support the LPC uart and relevant earlycon;

V8 thread here: https://lkml.org/lkml/2017/3/30/619
V7 thread here: https://lkml.org/lkml/2017/3/12/279
v6 thread here: https://lkml.org/lkml/2017/1/24/25
v5 thread here: https://lkml.org/lkml/2016/11/7/955
v4 thread here: https://lkml.org/lkml/2016/10/20/149
v3 thread here: https://lkml.org/lkml/2016/9/14/326
v2 thread here: https://lkml.org/lkml/2016/9/7/356
v1 thread here: https://lkml.org/lkml/2015/12/29/154

Gabriele (1):
  ACPI: Translate the I/O range of non-MMIO devices before scanning

Gabriele Paoloni (1):
  MANTAINERS: Add maintainer for HiSilicon LPC driver

zhichang.yuan (5):
  LIB: Introduce a generic PIO mapping method
  PCI: Apply the new generic I/O management on PCI IO hosts
  OF: Add missing I/O range exception for indirect-IO devices
  LPC: Support the device-tree LPC host on Hip06/Hip07
  LPC: Add the ACPI LPC support

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 MAINTAINERS                                        |   8 +
 drivers/acpi/arm64/Makefile                        |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c             | 304 ++++++++++
 drivers/acpi/internal.h                            |   5 +
 drivers/acpi/pci_root.c                            |   8 +-
 drivers/acpi/scan.c                                |   1 +
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 609 +++++++++++++++++++++
 drivers/of/address.c                               |  95 +++-
 drivers/pci/pci.c                                  | 101 +---
 include/acpi/acpi_indirect_pio.h                   |  28 +
 include/asm-generic/io.h                           |  52 +-
 include/linux/logic_pio.h                          | 110 ++++
 include/linux/pci.h                                |   3 +-
 lib/Kconfig                                        |  26 +
 lib/Makefile                                       |   2 +
 lib/logic_pio.c                                    | 280 ++++++++++
 19 files changed, 1573 insertions(+), 103 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 include/acpi/acpi_indirect_pio.h
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 0/7] LPC: legacy ISA I/O support
@ 2017-05-25 11:37 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patchset supports the IPMI-bt device attached to the Low-Pin-Count
interface implemented on Hisilicon Hip06/Hip07 SoC.
                        -----------
                        | LPC host|
                        |         |
                        -----------
                             |
                _____________V_______________LPC
                  |                       |
                  V                       V
                                     ------------
                                     |  BT(ipmi)|
                                     ------------

When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
the target peripherals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out accessors are based
on MMIO ranges; on Hip06/Hip07 LPC the I/O accesses are performed through driver
specific accessors rather than MMIO.
To solve this issue and keep the relevant existing peripherals' drivers untouched,
this patchset:
   - introduces a generic I/O space management framework, LIBIO, to support I/O
     operations on host controllers operating either on MMIO buses or on buses
     requiring specific driver I/O accessors;
   - redefines the in/out accessors to provide a unified interface for both MMIO
     and driver specific I/O operations. Using LIBIO, th call of in/out() from
     the host children drivers, such as ipmi-si, will be redirected to the
     corresponding device-specific I/O hooks to perform the I/O accesses.

 Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals can
 be supported without any changes on the existing ipmi-si driver.

 The whole patchset has been tested on Hip07 D05 board both using DTB and ACPI.

Changes from v8:
  - Simplified LIB IO framewrok
  - Moved INDIRECT PIO ACPI framework under acpi/arm64
  - Renamed occurrences of "lib io" and "indirect io" to "lib pio" and
    "indirect pio" to keep the patchset nomenclature consistent
  - Removed Alignment reuqirements
  - Moved LPC specific code out of ACPI common framework
  - Now PIO indirect HW ranges can overlap
  - Changed HiSilicon LPC driver maintainer (Gabriele Paoloni now) and split
    maintaner file modifications in a separate commit
  - Removed the commit with the DT nodes support for hip06 and hip07 (to be
    pushed separately)
  - Added a checking on ioport_map() not to break that function as Arnd points
    out in V7 review thread;
  - fixed the compile issues on alpha, m68k;

Changes from V7:
  - Based on Arnd's comment, rename the LIBIO as LOGIC_PIO;
  - Improved the mapping process in LOGIC_PIO to gain better efficiency when
    redirecting the I/O accesses to right device driver;
  - To reduce the impact on PCI MMIO to a minimum, add a new
    CONFIG_INDIRECT_PIO for indirect-IO hosts/devices;
  - Added a new ACPI handler for indirect-IO hosts/devices;
  - Fixed the compile issues on V6;

Changes from V6:
  - According to the comments from Bjorn and Alex, merge PCI IO and indirect-IO
    into a generic I/O space management, LIBIO;
  - Adopted the '_DEP' to replace the platform bus notifier. In this way, we can
    ensure the LPC peripherals' I/O resources had been translated to logical IO
    before the LPC peripheral enumeration;
  - Replaced the rwlock with rcu list based on Alex's suggestion;
  - Applied relaxed write/read to LPC driver;
  - Some bugs fixing and some optimazations based on the comments of V6;

Changes from V5:
  - Made the extio driver more generic and locate in lib/;
  - Supported multiple indirect-IO bus instances;
  - Extended the pci_register_io_range() to support indirect-IO, then dropped
  the I/O reservation used in previous patchset;
  - Reimplemented the ACPI LPC support;
  - Fixed some bugs, including the compile error on other archs, the module
  building failure found by Ming Lei, etc;

Changes from V4:
  - Some revises based on the comments from Bjorn, Rob on V4;
  - Fixed the compile error on some platforms, such as openrisc;

Changes from V3:
  - UART support deferred to a separate patchset; This patchset only support
  ipmi device under LPC;
  - LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
  from PCI/PCIE PIO space;
  - Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
  added a new fixup function, of_isa_indirect_io(), to get the I/O address
  directly from LPC dts configurations;
  - Support in(w,l)/out(w,l) for Hip06 lpc I/O;
  - Decouple the header file dependency on the gerenic io.h by defining in/out
  as normal functions in c file;
  - removed unused macro definitions in the LPC driver;

Changes from V2:
  - Support the PIO retrieval from the linux PIO generated by
  pci_address_to_pio. This method replace the 4K PIO reservation in V2;
  - Support the flat-tree earlycon;
  - Some revises based on Arnd's remarks;
  - Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
  from non-ZERO;

Changes from V1:
  - Support the ACPI LPC device;
  - Optimize the dts LPC driver in ISA compatible mode;
  - Reserve the IO range below 4K in avoid the possible conflict with PCI host
  IO ranges;
  - Support the LPC uart and relevant earlycon;

V8 thread here: https://lkml.org/lkml/2017/3/30/619
V7 thread here: https://lkml.org/lkml/2017/3/12/279
v6 thread here: https://lkml.org/lkml/2017/1/24/25
v5 thread here: https://lkml.org/lkml/2016/11/7/955
v4 thread here: https://lkml.org/lkml/2016/10/20/149
v3 thread here: https://lkml.org/lkml/2016/9/14/326
v2 thread here: https://lkml.org/lkml/2016/9/7/356
v1 thread here: https://lkml.org/lkml/2015/12/29/154

Gabriele (1):
  ACPI: Translate the I/O range of non-MMIO devices before scanning

Gabriele Paoloni (1):
  MANTAINERS: Add maintainer for HiSilicon LPC driver

zhichang.yuan (5):
  LIB: Introduce a generic PIO mapping method
  PCI: Apply the new generic I/O management on PCI IO hosts
  OF: Add missing I/O range exception for indirect-IO devices
  LPC: Support the device-tree LPC host on Hip06/Hip07
  LPC: Add the ACPI LPC support

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 MAINTAINERS                                        |   8 +
 drivers/acpi/arm64/Makefile                        |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c             | 304 ++++++++++
 drivers/acpi/internal.h                            |   5 +
 drivers/acpi/pci_root.c                            |   8 +-
 drivers/acpi/scan.c                                |   1 +
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 609 +++++++++++++++++++++
 drivers/of/address.c                               |  95 +++-
 drivers/pci/pci.c                                  | 101 +---
 include/acpi/acpi_indirect_pio.h                   |  28 +
 include/asm-generic/io.h                           |  52 +-
 include/linux/logic_pio.h                          | 110 ++++
 include/linux/pci.h                                |   3 +-
 lib/Kconfig                                        |  26 +
 lib/Makefile                                       |   2 +
 lib/logic_pio.c                                    | 280 ++++++++++
 19 files changed, 1573 insertions(+), 103 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 include/acpi/acpi_indirect_pio.h
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 0/7] LPC: legacy ISA I/O support
@ 2017-05-25 11:37 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, linux-pci, olof,
	brian.starkey

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patchset supports the IPMI-bt device attached to the Low-Pin-Count
interface implemented on Hisilicon Hip06/Hip07 SoC.
                        -----------
                        | LPC host|
                        |         |
                        -----------
                             |
                _____________V_______________LPC
                  |                       |
                  V                       V
                                     ------------
                                     |  BT(ipmi)|
                                     ------------

When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
the target peripherals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out accessors are based
on MMIO ranges; on Hip06/Hip07 LPC the I/O accesses are performed through driver
specific accessors rather than MMIO.
To solve this issue and keep the relevant existing peripherals' drivers untouched,
this patchset:
   - introduces a generic I/O space management framework, LIBIO, to support I/O
     operations on host controllers operating either on MMIO buses or on buses
     requiring specific driver I/O accessors;
   - redefines the in/out accessors to provide a unified interface for both MMIO
     and driver specific I/O operations. Using LIBIO, th call of in/out() from
     the host children drivers, such as ipmi-si, will be redirected to the
     corresponding device-specific I/O hooks to perform the I/O accesses.

 Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals can
 be supported without any changes on the existing ipmi-si driver.

 The whole patchset has been tested on Hip07 D05 board both using DTB and ACPI.

Changes from v8:
  - Simplified LIB IO framewrok
  - Moved INDIRECT PIO ACPI framework under acpi/arm64
  - Renamed occurrences of "lib io" and "indirect io" to "lib pio" and
    "indirect pio" to keep the patchset nomenclature consistent
  - Removed Alignment reuqirements
  - Moved LPC specific code out of ACPI common framework
  - Now PIO indirect HW ranges can overlap
  - Changed HiSilicon LPC driver maintainer (Gabriele Paoloni now) and split
    maintaner file modifications in a separate commit
  - Removed the commit with the DT nodes support for hip06 and hip07 (to be
    pushed separately)
  - Added a checking on ioport_map() not to break that function as Arnd points
    out in V7 review thread;
  - fixed the compile issues on alpha, m68k;

Changes from V7:
  - Based on Arnd's comment, rename the LIBIO as LOGIC_PIO;
  - Improved the mapping process in LOGIC_PIO to gain better efficiency when
    redirecting the I/O accesses to right device driver;
  - To reduce the impact on PCI MMIO to a minimum, add a new
    CONFIG_INDIRECT_PIO for indirect-IO hosts/devices;
  - Added a new ACPI handler for indirect-IO hosts/devices;
  - Fixed the compile issues on V6;

Changes from V6:
  - According to the comments from Bjorn and Alex, merge PCI IO and indirect-IO
    into a generic I/O space management, LIBIO;
  - Adopted the '_DEP' to replace the platform bus notifier. In this way, we can
    ensure the LPC peripherals' I/O resources had been translated to logical IO
    before the LPC peripheral enumeration;
  - Replaced the rwlock with rcu list based on Alex's suggestion;
  - Applied relaxed write/read to LPC driver;
  - Some bugs fixing and some optimazations based on the comments of V6;

Changes from V5:
  - Made the extio driver more generic and locate in lib/;
  - Supported multiple indirect-IO bus instances;
  - Extended the pci_register_io_range() to support indirect-IO, then dropped
  the I/O reservation used in previous patchset;
  - Reimplemented the ACPI LPC support;
  - Fixed some bugs, including the compile error on other archs, the module
  building failure found by Ming Lei, etc;

Changes from V4:
  - Some revises based on the comments from Bjorn, Rob on V4;
  - Fixed the compile error on some platforms, such as openrisc;

Changes from V3:
  - UART support deferred to a separate patchset; This patchset only support
  ipmi device under LPC;
  - LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
  from PCI/PCIE PIO space;
  - Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
  added a new fixup function, of_isa_indirect_io(), to get the I/O address
  directly from LPC dts configurations;
  - Support in(w,l)/out(w,l) for Hip06 lpc I/O;
  - Decouple the header file dependency on the gerenic io.h by defining in/out
  as normal functions in c file;
  - removed unused macro definitions in the LPC driver;

Changes from V2:
  - Support the PIO retrieval from the linux PIO generated by
  pci_address_to_pio. This method replace the 4K PIO reservation in V2;
  - Support the flat-tree earlycon;
  - Some revises based on Arnd's remarks;
  - Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
  from non-ZERO;

Changes from V1:
  - Support the ACPI LPC device;
  - Optimize the dts LPC driver in ISA compatible mode;
  - Reserve the IO range below 4K in avoid the possible conflict with PCI host
  IO ranges;
  - Support the LPC uart and relevant earlycon;

V8 thread here: https://lkml.org/lkml/2017/3/30/619
V7 thread here: https://lkml.org/lkml/2017/3/12/279
v6 thread here: https://lkml.org/lkml/2017/1/24/25
v5 thread here: https://lkml.org/lkml/2016/11/7/955
v4 thread here: https://lkml.org/lkml/2016/10/20/149
v3 thread here: https://lkml.org/lkml/2016/9/14/326
v2 thread here: https://lkml.org/lkml/2016/9/7/356
v1 thread here: https://lkml.org/lkml/2015/12/29/154

Gabriele (1):
  ACPI: Translate the I/O range of non-MMIO devices before scanning

Gabriele Paoloni (1):
  MANTAINERS: Add maintainer for HiSilicon LPC driver

zhichang.yuan (5):
  LIB: Introduce a generic PIO mapping method
  PCI: Apply the new generic I/O management on PCI IO hosts
  OF: Add missing I/O range exception for indirect-IO devices
  LPC: Support the device-tree LPC host on Hip06/Hip07
  LPC: Add the ACPI LPC support

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 MAINTAINERS                                        |   8 +
 drivers/acpi/arm64/Makefile                        |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c             | 304 ++++++++++
 drivers/acpi/internal.h                            |   5 +
 drivers/acpi/pci_root.c                            |   8 +-
 drivers/acpi/scan.c                                |   1 +
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 609 +++++++++++++++++++++
 drivers/of/address.c                               |  95 +++-
 drivers/pci/pci.c                                  | 101 +---
 include/acpi/acpi_indirect_pio.h                   |  28 +
 include/asm-generic/io.h                           |  52 +-
 include/linux/logic_pio.h                          | 110 ++++
 include/linux/pci.h                                |   3 +-
 lib/Kconfig                                        |  26 +
 lib/Makefile                                       |   2 +
 lib/logic_pio.c                                    | 280 ++++++++++
 19 files changed, 1573 insertions(+), 103 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 include/acpi/acpi_indirect_pio.h
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 0/7] LPC: legacy ISA I/O support
@ 2017-05-25 11:37 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patchset supports the IPMI-bt device attached to the Low-Pin-Count
interface implemented on Hisilicon Hip06/Hip07 SoC.
                        -----------
                        | LPC host|
                        |         |
                        -----------
                             |
                _____________V_______________LPC
                  |                       |
                  V                       V
                                     ------------
                                     |  BT(ipmi)|
                                     ------------

When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
the target peripherals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out accessors are based
on MMIO ranges; on Hip06/Hip07 LPC the I/O accesses are performed through driver
specific accessors rather than MMIO.
To solve this issue and keep the relevant existing peripherals' drivers untouched,
this patchset:
   - introduces a generic I/O space management framework, LIBIO, to support I/O
     operations on host controllers operating either on MMIO buses or on buses
     requiring specific driver I/O accessors;
   - redefines the in/out accessors to provide a unified interface for both MMIO
     and driver specific I/O operations. Using LIBIO, th call of in/out() from
     the host children drivers, such as ipmi-si, will be redirected to the
     corresponding device-specific I/O hooks to perform the I/O accesses.

 Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals can
 be supported without any changes on the existing ipmi-si driver.

 The whole patchset has been tested on Hip07 D05 board both using DTB and ACPI.

Changes from v8:
  - Simplified LIB IO framewrok
  - Moved INDIRECT PIO ACPI framework under acpi/arm64
  - Renamed occurrences of "lib io" and "indirect io" to "lib pio" and
    "indirect pio" to keep the patchset nomenclature consistent
  - Removed Alignment reuqirements
  - Moved LPC specific code out of ACPI common framework
  - Now PIO indirect HW ranges can overlap
  - Changed HiSilicon LPC driver maintainer (Gabriele Paoloni now) and split
    maintaner file modifications in a separate commit
  - Removed the commit with the DT nodes support for hip06 and hip07 (to be
    pushed separately)
  - Added a checking on ioport_map() not to break that function as Arnd points
    out in V7 review thread;
  - fixed the compile issues on alpha, m68k;

Changes from V7:
  - Based on Arnd's comment, rename the LIBIO as LOGIC_PIO;
  - Improved the mapping process in LOGIC_PIO to gain better efficiency when
    redirecting the I/O accesses to right device driver;
  - To reduce the impact on PCI MMIO to a minimum, add a new
    CONFIG_INDIRECT_PIO for indirect-IO hosts/devices;
  - Added a new ACPI handler for indirect-IO hosts/devices;
  - Fixed the compile issues on V6;

Changes from V6:
  - According to the comments from Bjorn and Alex, merge PCI IO and indirect-IO
    into a generic I/O space management, LIBIO;
  - Adopted the '_DEP' to replace the platform bus notifier. In this way, we can
    ensure the LPC peripherals' I/O resources had been translated to logical IO
    before the LPC peripheral enumeration;
  - Replaced the rwlock with rcu list based on Alex's suggestion;
  - Applied relaxed write/read to LPC driver;
  - Some bugs fixing and some optimazations based on the comments of V6;

Changes from V5:
  - Made the extio driver more generic and locate in lib/;
  - Supported multiple indirect-IO bus instances;
  - Extended the pci_register_io_range() to support indirect-IO, then dropped
  the I/O reservation used in previous patchset;
  - Reimplemented the ACPI LPC support;
  - Fixed some bugs, including the compile error on other archs, the module
  building failure found by Ming Lei, etc;

Changes from V4:
  - Some revises based on the comments from Bjorn, Rob on V4;
  - Fixed the compile error on some platforms, such as openrisc;

Changes from V3:
  - UART support deferred to a separate patchset; This patchset only support
  ipmi device under LPC;
  - LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
  from PCI/PCIE PIO space;
  - Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
  added a new fixup function, of_isa_indirect_io(), to get the I/O address
  directly from LPC dts configurations;
  - Support in(w,l)/out(w,l) for Hip06 lpc I/O;
  - Decouple the header file dependency on the gerenic io.h by defining in/out
  as normal functions in c file;
  - removed unused macro definitions in the LPC driver;

Changes from V2:
  - Support the PIO retrieval from the linux PIO generated by
  pci_address_to_pio. This method replace the 4K PIO reservation in V2;
  - Support the flat-tree earlycon;
  - Some revises based on Arnd's remarks;
  - Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
  from non-ZERO;

Changes from V1:
  - Support the ACPI LPC device;
  - Optimize the dts LPC driver in ISA compatible mode;
  - Reserve the IO range below 4K in avoid the possible conflict with PCI host
  IO ranges;
  - Support the LPC uart and relevant earlycon;

V8 thread here: https://lkml.org/lkml/2017/3/30/619
V7 thread here: https://lkml.org/lkml/2017/3/12/279
v6 thread here: https://lkml.org/lkml/2017/1/24/25
v5 thread here: https://lkml.org/lkml/2016/11/7/955
v4 thread here: https://lkml.org/lkml/2016/10/20/149
v3 thread here: https://lkml.org/lkml/2016/9/14/326
v2 thread here: https://lkml.org/lkml/2016/9/7/356
v1 thread here: https://lkml.org/lkml/2015/12/29/154

Gabriele (1):
  ACPI: Translate the I/O range of non-MMIO devices before scanning

Gabriele Paoloni (1):
  MANTAINERS: Add maintainer for HiSilicon LPC driver

zhichang.yuan (5):
  LIB: Introduce a generic PIO mapping method
  PCI: Apply the new generic I/O management on PCI IO hosts
  OF: Add missing I/O range exception for indirect-IO devices
  LPC: Support the device-tree LPC host on Hip06/Hip07
  LPC: Add the ACPI LPC support

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 MAINTAINERS                                        |   8 +
 drivers/acpi/arm64/Makefile                        |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c             | 304 ++++++++++
 drivers/acpi/internal.h                            |   5 +
 drivers/acpi/pci_root.c                            |   8 +-
 drivers/acpi/scan.c                                |   1 +
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 609 +++++++++++++++++++++
 drivers/of/address.c                               |  95 +++-
 drivers/pci/pci.c                                  | 101 +---
 include/acpi/acpi_indirect_pio.h                   |  28 +
 include/asm-generic/io.h                           |  52 +-
 include/linux/logic_pio.h                          | 110 ++++
 include/linux/pci.h                                |   3 +-
 lib/Kconfig                                        |  26 +
 lib/Makefile                                       |   2 +
 lib/logic_pio.c                                    | 280 ++++++++++
 19 files changed, 1573 insertions(+), 103 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 include/acpi/acpi_indirect_pio.h
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
pci_pio_to_address()")' a new I/O space management was supported. With that
driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
can be mapped to logical PIO, converted easily between CPU address and the
corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
in a memory read/write way through the unified in/out accessors.

But on some archs/platforms, there are bus hosts which access I/O
peripherals with host-local I/O port addresses rather than memory
addresses after memory-mapped.
To support those devices, a more generic I/O mapping method is introduced
here. Through this patch, both the CPU addresses and the host-local port
can be mapped into the logical PIO space with different logical/fake PIOs.
After this, all the I/O accesses to either PCI MMIO devices or host-local
I/O peripherals can be unified into the existing I/O accessors defined in
asm-generic/io.h and be redirected to the right device-specific hooks
based on the input logical PIO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 include/asm-generic/io.h  |  50 +++++++++
 include/linux/logic_pio.h | 110 ++++++++++++++++++
 lib/Kconfig               |  26 +++++
 lib/Makefile              |   2 +
 lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 468 insertions(+)
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 7ef015e..f7fbec3 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -351,6 +351,8 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
 #define IO_SPACE_LIMIT 0xffff
 #endif
 
+#include <linux/logic_pio.h>
+
 /*
  * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
  * implemented on hardware that needs an additional delay for I/O accesses to
@@ -358,51 +360,75 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
  */
 
 #ifndef inb
+#ifdef CONFIG_INDIRECT_PIO
+#define inb logic_inb
+#else
 #define inb inb
 static inline u8 inb(unsigned long addr)
 {
 	return readb(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inw
+#ifdef CONFIG_INDIRECT_PIO
+#define inw logic_inw
+#else
 #define inw inw
 static inline u16 inw(unsigned long addr)
 {
 	return readw(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inl
+#ifdef CONFIG_INDIRECT_PIO
+#define inl logic_inl
+#else
 #define inl inl
 static inline u32 inl(unsigned long addr)
 {
 	return readl(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outb
+#ifdef CONFIG_INDIRECT_PIO
+#define outb logic_outb
+#else
 #define outb outb
 static inline void outb(u8 value, unsigned long addr)
 {
 	writeb(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outw
+#ifdef CONFIG_INDIRECT_PIO
+#define outw logic_outw
+#else
 #define outw outw
 static inline void outw(u16 value, unsigned long addr)
 {
 	writew(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outl
+#ifdef CONFIG_INDIRECT_PIO
+#define outl logic_outl
+#else
 #define outl outl
 static inline void outl(u32 value, unsigned long addr)
 {
 	writel(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inb_p
@@ -459,54 +485,78 @@ static inline void outl_p(u32 value, unsigned long addr)
  */
 
 #ifndef insb
+#ifdef CONFIG_INDIRECT_PIO
+#define insb logic_insb
+#else
 #define insb insb
 static inline void insb(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insw
+#ifdef CONFIG_INDIRECT_PIO
+#define insw logic_insw
+#else
 #define insw insw
 static inline void insw(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insl
+#ifdef CONFIG_INDIRECT_PIO
+#define insl logic_insl
+#else
 #define insl insl
 static inline void insl(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsb
+#ifdef CONFIG_INDIRECT_PIO
+#define outsb logic_outsb
+#else
 #define outsb outsb
 static inline void outsb(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsw
+#ifdef CONFIG_INDIRECT_PIO
+#define outsw logic_outsw
+#else
 #define outsw outsw
 static inline void outsw(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsl
+#ifdef CONFIG_INDIRECT_PIO
+#define outsl logic_outsl
+#else
 #define outsl outsl
 static inline void outsl(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insb_p
diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
new file mode 100644
index 0000000..8e4dc65
--- /dev/null
+++ b/include/linux/logic_pio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_LOGIC_PIO_H
+#define __LINUX_LOGIC_PIO_H
+
+#ifdef __KERNEL__
+
+#include <linux/fwnode.h>
+
+#define PIO_INDIRECT		0x01UL /* indirect IO flag */
+#define PIO_CPU_MMIO		0x00UL /* memory mapped io flag */
+
+struct logic_pio_hwaddr {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	resource_size_t hw_start;
+	resource_size_t io_start;
+	resource_size_t size; /* range size populated */
+	unsigned long flags;
+
+	void *devpara;	/* private parameter of the host device */
+	struct hostio_ops *ops;	/* ops operating on this node */
+};
+
+struct hostio_ops {
+	u32 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+			size_t dlen);
+	u32 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+			size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count);
+};
+
+extern u8 logic_inb(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern u16 logic_inw(unsigned long addr);
+extern u32 logic_inl(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern void logic_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insl(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insw(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_outsb(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsw(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsl(unsigned long addr, const void *buffer,
+			unsigned int count);
+
+#ifdef CONFIG_INDIRECT_PIO
+/* Below make 75% of IO Space for MMIO and the rest for Indirect IO */
+#define MMIO_UPPER_LIMIT (IO_SPACE_LIMIT - (IO_SPACE_LIMIT >> 2))
+#else
+#define MMIO_UPPER_LIMIT IO_SPACE_LIMIT
+#endif
+
+#ifdef CONFIG_LOGIC_PIO
+extern struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
+
+extern unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
+			resource_size_t hw_addr);
+
+extern int logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+#else
+static inline struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t hw_addr)
+{
+	return -1;
+}
+
+static inline struct logic_pio_hwaddr
+*logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+{
+	return NULL;
+}
+#endif
+
+extern resource_size_t logic_pio_to_hwaddr(unsigned long pio);
+
+extern unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_LOGIC_PIO_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 0c8b78a..503c2e0 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -59,6 +59,32 @@ config ARCH_USE_CMPXCHG_LOCKREF
 config ARCH_HAS_FAST_MULTIPLIER
 	bool
 
+config LOGIC_PIO
+	bool "Generic logical I/O management"
+	def_bool y if PCI && !X86 && !IA64 && !POWERPC
+	help
+	  For some architectures, there are no IO space. To support the
+	  accesses to legacy I/O devices on those architectures, kernel
+	  implemented the memory mapped I/O mechanism based on bridge bus
+	  supports. But for some buses which do not support MMIO, the
+	  peripherals there should be accessed with device-specific way.
+	  To abstract those different I/O accesses into unified I/O accessors,
+	  this option provide a generic I/O space management way after mapping
+	  the device I/O to system logical/fake I/O and help to hide all the
+	  hardware detail.
+
+config INDIRECT_PIO
+	bool "Access I/O in non-MMIO mode" if LOGIC_PIO
+	help
+	  On some platforms where no separate I/O space exist, there are I/O
+	  hosts which can not be accessed in MMIO mode. Based on LOGIC_PIO
+	  mechanism, the host-local I/O resource can be mapped into system
+	  logic PIO space shared with MMIO hosts, such as PCI/PCIE, then system
+	  can access the I/O devices with the mapped logic PIO through I/O
+	  accessors.
+	  This way has a little I/O performance cost. Please make sure your
+	  devices really need this configure item enabled.
+
 config CRC_CCITT
 	tristate "CRC-CCITT functions"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 0166fbc..1a27f6e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
+obj-$(CONFIG_LOGIC_PIO) += logic_pio.o
+
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
new file mode 100644
index 0000000..4a960cd
--- /dev/null
+++ b/lib/logic_pio.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/mm.h>
+#include <linux/rculist.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+/* The unique hardware address list. */
+static LIST_HEAD(io_range_list);
+static DEFINE_MUTEX(io_range_mutex);
+
+/*
+ * register a new io range node in the io range list.
+ *
+ * @newrange: pointer to the io range to be registered.
+ *
+ * returns 0 on success, the error code in case of failure
+ */
+int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
+{
+	struct logic_pio_hwaddr *range;
+	int ret = 0;
+	resource_size_t start = new_range->hw_start;
+	resource_size_t end = new_range->hw_start + new_range->size;
+	resource_size_t allocated_mmio_size = 0;
+	resource_size_t allocated_iio_size = MMIO_UPPER_LIMIT;
+
+	if (!new_range || !new_range->fwnode || !new_range->size)
+		return -EINVAL;
+
+	mutex_lock(&io_range_mutex);
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+
+		if (range->fwnode == new_range->fwnode) {
+			/* range already there */
+			ret = -EFAULT;
+			goto end_register;
+		}
+		if (range->flags == PIO_CPU_MMIO &&
+				new_range->flags == PIO_CPU_MMIO) {
+			/* for MMIO ranges we need to check for overlap */
+			if (start >= range->hw_start + range->size ||
+				end < range->hw_start)
+				allocated_mmio_size += range->size;
+			else {
+				ret = -EFAULT;
+				goto end_register;
+			}
+		} else if (range->flags == PIO_INDIRECT &&
+				new_range->flags == PIO_INDIRECT) {
+			allocated_iio_size += range->size;
+		}
+	}
+
+	/* range not registered yet, check for available space */
+	if (new_range->flags == PIO_CPU_MMIO) {
+
+		if (allocated_mmio_size + new_range->size - 1 >
+			MMIO_UPPER_LIMIT) {
+			/* if it's too big check if 64K space can be reserved */
+			if (allocated_mmio_size + SZ_64K - 1 >
+			MMIO_UPPER_LIMIT) {
+				ret = -E2BIG;
+				goto end_register;
+			}
+			new_range->size = SZ_64K;
+			pr_warn("Requested IO range too big, new size set to 64K\n");
+		}
+
+		new_range->io_start = allocated_mmio_size + new_range->size;
+
+	} else if (new_range->flags == PIO_INDIRECT) {
+
+		if (allocated_iio_size + new_range->size - 1 >
+		IO_SPACE_LIMIT) {
+			ret = -E2BIG;
+			goto end_register;
+		}
+		new_range->io_start = allocated_iio_size + new_range->size;
+
+	} else {
+		/* invalid flag */
+		ret = -EINVAL;
+		goto end_register;
+	}
+
+	list_add_tail_rcu(&new_range->list, &io_range_list);
+
+end_register:
+	mutex_unlock(&io_range_mutex);
+	return ret;
+}
+
+/*
+ * traverse the io_range_list to find the registered node whose device node
+ * and/or physical IO address match to.
+ */
+struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->fwnode == fwnode)
+			return range;
+	}
+	return NULL;
+}
+
+/* return a registered range given an input PIO token */
+static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (pio >= range->io_start &&
+				pio < range->io_start + range->size)
+			return range;
+	}
+	pr_err("PIO entry token invalid\n");
+	return NULL;
+}
+
+/*
+ * Translate the input logical pio to the corresponding hardware address.
+ * The input pio should be unique in the whole logical PIO space.
+ */
+resource_size_t logic_pio_to_hwaddr(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+	resource_size_t hwaddr = -1;
+
+	range = find_io_range(pio);
+	if (range)
+		hwaddr = range->hw_start + pio - range->io_start;
+
+	return hwaddr;
+}
+
+/*
+ * This function is generic for translating a hardware address to logical PIO.
+ * @hw_addr: the hardware address of host, can be CPU address or host-local
+ *		address;
+ */
+unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	range = find_io_range_by_fwnode(fwnode);
+	if (!range || range->flags == PIO_CPU_MMIO) {
+		pr_err("range not found or invalid\n");
+		return -1;
+	}
+	return addr - range->hw_start + range->io_start;
+}
+
+unsigned long
+logic_pio_trans_cpuaddr(resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->flags != PIO_CPU_MMIO)
+			continue;
+		if (addr >= range->hw_start &&
+			addr < range->hw_start + range->size)
+			return addr - range->hw_start +
+				range->io_start;
+	}
+	pr_err("addr not registered in io_range_list\n");
+	return -1;
+}
+
+#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
+#define BUILD_LOGIC_PIO(bw, type)\
+type logic_in##bw(unsigned long addr)\
+{\
+	type ret = -1;\
+\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		ret = read##bw(PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			ret = entry->ops->pfin(entry->devpara,\
+					addr, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+	return ret;\
+}	\
+\
+void logic_out##bw(type value, unsigned long addr)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		write##bw(value, PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfout(entry->devpara,\
+						addr, value, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}	\
+\
+void logic_ins##bw(unsigned long addr, void *buffer, unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		reads##bw(PCI_IOBASE + addr, buffer, count);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfins(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+\
+}	\
+\
+void logic_outs##bw(unsigned long addr, const void *buffer,\
+		    unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT)\
+		writes##bw(PCI_IOBASE + addr, buffer, count);\
+	else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfouts(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}
+
+BUILD_LOGIC_PIO(b, u8)
+
+EXPORT_SYMBOL(logic_inb);
+EXPORT_SYMBOL(logic_outb);
+EXPORT_SYMBOL(logic_insb);
+EXPORT_SYMBOL(logic_outsb);
+
+BUILD_LOGIC_PIO(w, u16)
+
+EXPORT_SYMBOL(logic_inw);
+EXPORT_SYMBOL(logic_outw);
+EXPORT_SYMBOL(logic_insw);
+EXPORT_SYMBOL(logic_outsw);
+
+BUILD_LOGIC_PIO(l, u32)
+
+EXPORT_SYMBOL(logic_inl);
+EXPORT_SYMBOL(logic_outl);
+EXPORT_SYMBOL(logic_insl);
+EXPORT_SYMBOL(logic_outsl);
+#endif /* CONFIG_INDIRECT_PIO && PCI_IOBASE */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
pci_pio_to_address()")' a new I/O space management was supported. With that
driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
can be mapped to logical PIO, converted easily between CPU address and the
corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
in a memory read/write way through the unified in/out accessors.

But on some archs/platforms, there are bus hosts which access I/O
peripherals with host-local I/O port addresses rather than memory
addresses after memory-mapped.
To support those devices, a more generic I/O mapping method is introduced
here. Through this patch, both the CPU addresses and the host-local port
can be mapped into the logical PIO space with different logical/fake PIOs.
After this, all the I/O accesses to either PCI MMIO devices or host-local
I/O peripherals can be unified into the existing I/O accessors defined in
asm-generic/io.h and be redirected to the right device-specific hooks
based on the input logical PIO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 include/asm-generic/io.h  |  50 +++++++++
 include/linux/logic_pio.h | 110 ++++++++++++++++++
 lib/Kconfig               |  26 +++++
 lib/Makefile              |   2 +
 lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 468 insertions(+)
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 7ef015e..f7fbec3 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -351,6 +351,8 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
 #define IO_SPACE_LIMIT 0xffff
 #endif
 
+#include <linux/logic_pio.h>
+
 /*
  * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
  * implemented on hardware that needs an additional delay for I/O accesses to
@@ -358,51 +360,75 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
  */
 
 #ifndef inb
+#ifdef CONFIG_INDIRECT_PIO
+#define inb logic_inb
+#else
 #define inb inb
 static inline u8 inb(unsigned long addr)
 {
 	return readb(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inw
+#ifdef CONFIG_INDIRECT_PIO
+#define inw logic_inw
+#else
 #define inw inw
 static inline u16 inw(unsigned long addr)
 {
 	return readw(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inl
+#ifdef CONFIG_INDIRECT_PIO
+#define inl logic_inl
+#else
 #define inl inl
 static inline u32 inl(unsigned long addr)
 {
 	return readl(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outb
+#ifdef CONFIG_INDIRECT_PIO
+#define outb logic_outb
+#else
 #define outb outb
 static inline void outb(u8 value, unsigned long addr)
 {
 	writeb(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outw
+#ifdef CONFIG_INDIRECT_PIO
+#define outw logic_outw
+#else
 #define outw outw
 static inline void outw(u16 value, unsigned long addr)
 {
 	writew(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outl
+#ifdef CONFIG_INDIRECT_PIO
+#define outl logic_outl
+#else
 #define outl outl
 static inline void outl(u32 value, unsigned long addr)
 {
 	writel(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inb_p
@@ -459,54 +485,78 @@ static inline void outl_p(u32 value, unsigned long addr)
  */
 
 #ifndef insb
+#ifdef CONFIG_INDIRECT_PIO
+#define insb logic_insb
+#else
 #define insb insb
 static inline void insb(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insw
+#ifdef CONFIG_INDIRECT_PIO
+#define insw logic_insw
+#else
 #define insw insw
 static inline void insw(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insl
+#ifdef CONFIG_INDIRECT_PIO
+#define insl logic_insl
+#else
 #define insl insl
 static inline void insl(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsb
+#ifdef CONFIG_INDIRECT_PIO
+#define outsb logic_outsb
+#else
 #define outsb outsb
 static inline void outsb(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsw
+#ifdef CONFIG_INDIRECT_PIO
+#define outsw logic_outsw
+#else
 #define outsw outsw
 static inline void outsw(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsl
+#ifdef CONFIG_INDIRECT_PIO
+#define outsl logic_outsl
+#else
 #define outsl outsl
 static inline void outsl(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insb_p
diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
new file mode 100644
index 0000000..8e4dc65
--- /dev/null
+++ b/include/linux/logic_pio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_LOGIC_PIO_H
+#define __LINUX_LOGIC_PIO_H
+
+#ifdef __KERNEL__
+
+#include <linux/fwnode.h>
+
+#define PIO_INDIRECT		0x01UL /* indirect IO flag */
+#define PIO_CPU_MMIO		0x00UL /* memory mapped io flag */
+
+struct logic_pio_hwaddr {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	resource_size_t hw_start;
+	resource_size_t io_start;
+	resource_size_t size; /* range size populated */
+	unsigned long flags;
+
+	void *devpara;	/* private parameter of the host device */
+	struct hostio_ops *ops;	/* ops operating on this node */
+};
+
+struct hostio_ops {
+	u32 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+			size_t dlen);
+	u32 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+			size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count);
+};
+
+extern u8 logic_inb(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern u16 logic_inw(unsigned long addr);
+extern u32 logic_inl(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern void logic_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insl(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insw(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_outsb(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsw(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsl(unsigned long addr, const void *buffer,
+			unsigned int count);
+
+#ifdef CONFIG_INDIRECT_PIO
+/* Below make 75% of IO Space for MMIO and the rest for Indirect IO */
+#define MMIO_UPPER_LIMIT (IO_SPACE_LIMIT - (IO_SPACE_LIMIT >> 2))
+#else
+#define MMIO_UPPER_LIMIT IO_SPACE_LIMIT
+#endif
+
+#ifdef CONFIG_LOGIC_PIO
+extern struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
+
+extern unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
+			resource_size_t hw_addr);
+
+extern int logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+#else
+static inline struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t hw_addr)
+{
+	return -1;
+}
+
+static inline struct logic_pio_hwaddr
+*logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+{
+	return NULL;
+}
+#endif
+
+extern resource_size_t logic_pio_to_hwaddr(unsigned long pio);
+
+extern unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_LOGIC_PIO_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 0c8b78a..503c2e0 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -59,6 +59,32 @@ config ARCH_USE_CMPXCHG_LOCKREF
 config ARCH_HAS_FAST_MULTIPLIER
 	bool
 
+config LOGIC_PIO
+	bool "Generic logical I/O management"
+	def_bool y if PCI && !X86 && !IA64 && !POWERPC
+	help
+	  For some architectures, there are no IO space. To support the
+	  accesses to legacy I/O devices on those architectures, kernel
+	  implemented the memory mapped I/O mechanism based on bridge bus
+	  supports. But for some buses which do not support MMIO, the
+	  peripherals there should be accessed with device-specific way.
+	  To abstract those different I/O accesses into unified I/O accessors,
+	  this option provide a generic I/O space management way after mapping
+	  the device I/O to system logical/fake I/O and help to hide all the
+	  hardware detail.
+
+config INDIRECT_PIO
+	bool "Access I/O in non-MMIO mode" if LOGIC_PIO
+	help
+	  On some platforms where no separate I/O space exist, there are I/O
+	  hosts which can not be accessed in MMIO mode. Based on LOGIC_PIO
+	  mechanism, the host-local I/O resource can be mapped into system
+	  logic PIO space shared with MMIO hosts, such as PCI/PCIE, then system
+	  can access the I/O devices with the mapped logic PIO through I/O
+	  accessors.
+	  This way has a little I/O performance cost. Please make sure your
+	  devices really need this configure item enabled.
+
 config CRC_CCITT
 	tristate "CRC-CCITT functions"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 0166fbc..1a27f6e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
+obj-$(CONFIG_LOGIC_PIO) += logic_pio.o
+
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
new file mode 100644
index 0000000..4a960cd
--- /dev/null
+++ b/lib/logic_pio.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/mm.h>
+#include <linux/rculist.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+/* The unique hardware address list. */
+static LIST_HEAD(io_range_list);
+static DEFINE_MUTEX(io_range_mutex);
+
+/*
+ * register a new io range node in the io range list.
+ *
+ * @newrange: pointer to the io range to be registered.
+ *
+ * returns 0 on success, the error code in case of failure
+ */
+int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
+{
+	struct logic_pio_hwaddr *range;
+	int ret = 0;
+	resource_size_t start = new_range->hw_start;
+	resource_size_t end = new_range->hw_start + new_range->size;
+	resource_size_t allocated_mmio_size = 0;
+	resource_size_t allocated_iio_size = MMIO_UPPER_LIMIT;
+
+	if (!new_range || !new_range->fwnode || !new_range->size)
+		return -EINVAL;
+
+	mutex_lock(&io_range_mutex);
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+
+		if (range->fwnode == new_range->fwnode) {
+			/* range already there */
+			ret = -EFAULT;
+			goto end_register;
+		}
+		if (range->flags == PIO_CPU_MMIO &&
+				new_range->flags == PIO_CPU_MMIO) {
+			/* for MMIO ranges we need to check for overlap */
+			if (start >= range->hw_start + range->size ||
+				end < range->hw_start)
+				allocated_mmio_size += range->size;
+			else {
+				ret = -EFAULT;
+				goto end_register;
+			}
+		} else if (range->flags == PIO_INDIRECT &&
+				new_range->flags == PIO_INDIRECT) {
+			allocated_iio_size += range->size;
+		}
+	}
+
+	/* range not registered yet, check for available space */
+	if (new_range->flags == PIO_CPU_MMIO) {
+
+		if (allocated_mmio_size + new_range->size - 1 >
+			MMIO_UPPER_LIMIT) {
+			/* if it's too big check if 64K space can be reserved */
+			if (allocated_mmio_size + SZ_64K - 1 >
+			MMIO_UPPER_LIMIT) {
+				ret = -E2BIG;
+				goto end_register;
+			}
+			new_range->size = SZ_64K;
+			pr_warn("Requested IO range too big, new size set to 64K\n");
+		}
+
+		new_range->io_start = allocated_mmio_size + new_range->size;
+
+	} else if (new_range->flags == PIO_INDIRECT) {
+
+		if (allocated_iio_size + new_range->size - 1 >
+		IO_SPACE_LIMIT) {
+			ret = -E2BIG;
+			goto end_register;
+		}
+		new_range->io_start = allocated_iio_size + new_range->size;
+
+	} else {
+		/* invalid flag */
+		ret = -EINVAL;
+		goto end_register;
+	}
+
+	list_add_tail_rcu(&new_range->list, &io_range_list);
+
+end_register:
+	mutex_unlock(&io_range_mutex);
+	return ret;
+}
+
+/*
+ * traverse the io_range_list to find the registered node whose device node
+ * and/or physical IO address match to.
+ */
+struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->fwnode == fwnode)
+			return range;
+	}
+	return NULL;
+}
+
+/* return a registered range given an input PIO token */
+static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (pio >= range->io_start &&
+				pio < range->io_start + range->size)
+			return range;
+	}
+	pr_err("PIO entry token invalid\n");
+	return NULL;
+}
+
+/*
+ * Translate the input logical pio to the corresponding hardware address.
+ * The input pio should be unique in the whole logical PIO space.
+ */
+resource_size_t logic_pio_to_hwaddr(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+	resource_size_t hwaddr = -1;
+
+	range = find_io_range(pio);
+	if (range)
+		hwaddr = range->hw_start + pio - range->io_start;
+
+	return hwaddr;
+}
+
+/*
+ * This function is generic for translating a hardware address to logical PIO.
+ * @hw_addr: the hardware address of host, can be CPU address or host-local
+ *		address;
+ */
+unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	range = find_io_range_by_fwnode(fwnode);
+	if (!range || range->flags == PIO_CPU_MMIO) {
+		pr_err("range not found or invalid\n");
+		return -1;
+	}
+	return addr - range->hw_start + range->io_start;
+}
+
+unsigned long
+logic_pio_trans_cpuaddr(resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->flags != PIO_CPU_MMIO)
+			continue;
+		if (addr >= range->hw_start &&
+			addr < range->hw_start + range->size)
+			return addr - range->hw_start +
+				range->io_start;
+	}
+	pr_err("addr not registered in io_range_list\n");
+	return -1;
+}
+
+#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
+#define BUILD_LOGIC_PIO(bw, type)\
+type logic_in##bw(unsigned long addr)\
+{\
+	type ret = -1;\
+\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		ret = read##bw(PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			ret = entry->ops->pfin(entry->devpara,\
+					addr, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+	return ret;\
+}	\
+\
+void logic_out##bw(type value, unsigned long addr)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		write##bw(value, PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfout(entry->devpara,\
+						addr, value, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}	\
+\
+void logic_ins##bw(unsigned long addr, void *buffer, unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		reads##bw(PCI_IOBASE + addr, buffer, count);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfins(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+\
+}	\
+\
+void logic_outs##bw(unsigned long addr, const void *buffer,\
+		    unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT)\
+		writes##bw(PCI_IOBASE + addr, buffer, count);\
+	else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfouts(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}
+
+BUILD_LOGIC_PIO(b, u8)
+
+EXPORT_SYMBOL(logic_inb);
+EXPORT_SYMBOL(logic_outb);
+EXPORT_SYMBOL(logic_insb);
+EXPORT_SYMBOL(logic_outsb);
+
+BUILD_LOGIC_PIO(w, u16)
+
+EXPORT_SYMBOL(logic_inw);
+EXPORT_SYMBOL(logic_outw);
+EXPORT_SYMBOL(logic_insw);
+EXPORT_SYMBOL(logic_outsw);
+
+BUILD_LOGIC_PIO(l, u32)
+
+EXPORT_SYMBOL(logic_inl);
+EXPORT_SYMBOL(logic_outl);
+EXPORT_SYMBOL(logic_insl);
+EXPORT_SYMBOL(logic_outsl);
+#endif /* CONFIG_INDIRECT_PIO && PCI_IOBASE */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, zhichang.yuan,
	linux-pci, olof, brian.starkey

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
pci_pio_to_address()")' a new I/O space management was supported. With that
driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
can be mapped to logical PIO, converted easily between CPU address and the
corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
in a memory read/write way through the unified in/out accessors.

But on some archs/platforms, there are bus hosts which access I/O
peripherals with host-local I/O port addresses rather than memory
addresses after memory-mapped.
To support those devices, a more generic I/O mapping method is introduced
here. Through this patch, both the CPU addresses and the host-local port
can be mapped into the logical PIO space with different logical/fake PIOs.
After this, all the I/O accesses to either PCI MMIO devices or host-local
I/O peripherals can be unified into the existing I/O accessors defined in
asm-generic/io.h and be redirected to the right device-specific hooks
based on the input logical PIO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 include/asm-generic/io.h  |  50 +++++++++
 include/linux/logic_pio.h | 110 ++++++++++++++++++
 lib/Kconfig               |  26 +++++
 lib/Makefile              |   2 +
 lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 468 insertions(+)
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 7ef015e..f7fbec3 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -351,6 +351,8 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
 #define IO_SPACE_LIMIT 0xffff
 #endif
 
+#include <linux/logic_pio.h>
+
 /*
  * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
  * implemented on hardware that needs an additional delay for I/O accesses to
@@ -358,51 +360,75 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
  */
 
 #ifndef inb
+#ifdef CONFIG_INDIRECT_PIO
+#define inb logic_inb
+#else
 #define inb inb
 static inline u8 inb(unsigned long addr)
 {
 	return readb(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inw
+#ifdef CONFIG_INDIRECT_PIO
+#define inw logic_inw
+#else
 #define inw inw
 static inline u16 inw(unsigned long addr)
 {
 	return readw(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inl
+#ifdef CONFIG_INDIRECT_PIO
+#define inl logic_inl
+#else
 #define inl inl
 static inline u32 inl(unsigned long addr)
 {
 	return readl(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outb
+#ifdef CONFIG_INDIRECT_PIO
+#define outb logic_outb
+#else
 #define outb outb
 static inline void outb(u8 value, unsigned long addr)
 {
 	writeb(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outw
+#ifdef CONFIG_INDIRECT_PIO
+#define outw logic_outw
+#else
 #define outw outw
 static inline void outw(u16 value, unsigned long addr)
 {
 	writew(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outl
+#ifdef CONFIG_INDIRECT_PIO
+#define outl logic_outl
+#else
 #define outl outl
 static inline void outl(u32 value, unsigned long addr)
 {
 	writel(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inb_p
@@ -459,54 +485,78 @@ static inline void outl_p(u32 value, unsigned long addr)
  */
 
 #ifndef insb
+#ifdef CONFIG_INDIRECT_PIO
+#define insb logic_insb
+#else
 #define insb insb
 static inline void insb(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insw
+#ifdef CONFIG_INDIRECT_PIO
+#define insw logic_insw
+#else
 #define insw insw
 static inline void insw(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insl
+#ifdef CONFIG_INDIRECT_PIO
+#define insl logic_insl
+#else
 #define insl insl
 static inline void insl(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsb
+#ifdef CONFIG_INDIRECT_PIO
+#define outsb logic_outsb
+#else
 #define outsb outsb
 static inline void outsb(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsw
+#ifdef CONFIG_INDIRECT_PIO
+#define outsw logic_outsw
+#else
 #define outsw outsw
 static inline void outsw(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsl
+#ifdef CONFIG_INDIRECT_PIO
+#define outsl logic_outsl
+#else
 #define outsl outsl
 static inline void outsl(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insb_p
diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
new file mode 100644
index 0000000..8e4dc65
--- /dev/null
+++ b/include/linux/logic_pio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_LOGIC_PIO_H
+#define __LINUX_LOGIC_PIO_H
+
+#ifdef __KERNEL__
+
+#include <linux/fwnode.h>
+
+#define PIO_INDIRECT		0x01UL /* indirect IO flag */
+#define PIO_CPU_MMIO		0x00UL /* memory mapped io flag */
+
+struct logic_pio_hwaddr {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	resource_size_t hw_start;
+	resource_size_t io_start;
+	resource_size_t size; /* range size populated */
+	unsigned long flags;
+
+	void *devpara;	/* private parameter of the host device */
+	struct hostio_ops *ops;	/* ops operating on this node */
+};
+
+struct hostio_ops {
+	u32 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+			size_t dlen);
+	u32 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+			size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count);
+};
+
+extern u8 logic_inb(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern u16 logic_inw(unsigned long addr);
+extern u32 logic_inl(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern void logic_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insl(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insw(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_outsb(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsw(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsl(unsigned long addr, const void *buffer,
+			unsigned int count);
+
+#ifdef CONFIG_INDIRECT_PIO
+/* Below make 75% of IO Space for MMIO and the rest for Indirect IO */
+#define MMIO_UPPER_LIMIT (IO_SPACE_LIMIT - (IO_SPACE_LIMIT >> 2))
+#else
+#define MMIO_UPPER_LIMIT IO_SPACE_LIMIT
+#endif
+
+#ifdef CONFIG_LOGIC_PIO
+extern struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
+
+extern unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
+			resource_size_t hw_addr);
+
+extern int logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+#else
+static inline struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t hw_addr)
+{
+	return -1;
+}
+
+static inline struct logic_pio_hwaddr
+*logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+{
+	return NULL;
+}
+#endif
+
+extern resource_size_t logic_pio_to_hwaddr(unsigned long pio);
+
+extern unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_LOGIC_PIO_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 0c8b78a..503c2e0 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -59,6 +59,32 @@ config ARCH_USE_CMPXCHG_LOCKREF
 config ARCH_HAS_FAST_MULTIPLIER
 	bool
 
+config LOGIC_PIO
+	bool "Generic logical I/O management"
+	def_bool y if PCI && !X86 && !IA64 && !POWERPC
+	help
+	  For some architectures, there are no IO space. To support the
+	  accesses to legacy I/O devices on those architectures, kernel
+	  implemented the memory mapped I/O mechanism based on bridge bus
+	  supports. But for some buses which do not support MMIO, the
+	  peripherals there should be accessed with device-specific way.
+	  To abstract those different I/O accesses into unified I/O accessors,
+	  this option provide a generic I/O space management way after mapping
+	  the device I/O to system logical/fake I/O and help to hide all the
+	  hardware detail.
+
+config INDIRECT_PIO
+	bool "Access I/O in non-MMIO mode" if LOGIC_PIO
+	help
+	  On some platforms where no separate I/O space exist, there are I/O
+	  hosts which can not be accessed in MMIO mode. Based on LOGIC_PIO
+	  mechanism, the host-local I/O resource can be mapped into system
+	  logic PIO space shared with MMIO hosts, such as PCI/PCIE, then system
+	  can access the I/O devices with the mapped logic PIO through I/O
+	  accessors.
+	  This way has a little I/O performance cost. Please make sure your
+	  devices really need this configure item enabled.
+
 config CRC_CCITT
 	tristate "CRC-CCITT functions"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 0166fbc..1a27f6e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
+obj-$(CONFIG_LOGIC_PIO) += logic_pio.o
+
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
new file mode 100644
index 0000000..4a960cd
--- /dev/null
+++ b/lib/logic_pio.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/mm.h>
+#include <linux/rculist.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+/* The unique hardware address list. */
+static LIST_HEAD(io_range_list);
+static DEFINE_MUTEX(io_range_mutex);
+
+/*
+ * register a new io range node in the io range list.
+ *
+ * @newrange: pointer to the io range to be registered.
+ *
+ * returns 0 on success, the error code in case of failure
+ */
+int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
+{
+	struct logic_pio_hwaddr *range;
+	int ret = 0;
+	resource_size_t start = new_range->hw_start;
+	resource_size_t end = new_range->hw_start + new_range->size;
+	resource_size_t allocated_mmio_size = 0;
+	resource_size_t allocated_iio_size = MMIO_UPPER_LIMIT;
+
+	if (!new_range || !new_range->fwnode || !new_range->size)
+		return -EINVAL;
+
+	mutex_lock(&io_range_mutex);
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+
+		if (range->fwnode == new_range->fwnode) {
+			/* range already there */
+			ret = -EFAULT;
+			goto end_register;
+		}
+		if (range->flags == PIO_CPU_MMIO &&
+				new_range->flags == PIO_CPU_MMIO) {
+			/* for MMIO ranges we need to check for overlap */
+			if (start >= range->hw_start + range->size ||
+				end < range->hw_start)
+				allocated_mmio_size += range->size;
+			else {
+				ret = -EFAULT;
+				goto end_register;
+			}
+		} else if (range->flags == PIO_INDIRECT &&
+				new_range->flags == PIO_INDIRECT) {
+			allocated_iio_size += range->size;
+		}
+	}
+
+	/* range not registered yet, check for available space */
+	if (new_range->flags == PIO_CPU_MMIO) {
+
+		if (allocated_mmio_size + new_range->size - 1 >
+			MMIO_UPPER_LIMIT) {
+			/* if it's too big check if 64K space can be reserved */
+			if (allocated_mmio_size + SZ_64K - 1 >
+			MMIO_UPPER_LIMIT) {
+				ret = -E2BIG;
+				goto end_register;
+			}
+			new_range->size = SZ_64K;
+			pr_warn("Requested IO range too big, new size set to 64K\n");
+		}
+
+		new_range->io_start = allocated_mmio_size + new_range->size;
+
+	} else if (new_range->flags == PIO_INDIRECT) {
+
+		if (allocated_iio_size + new_range->size - 1 >
+		IO_SPACE_LIMIT) {
+			ret = -E2BIG;
+			goto end_register;
+		}
+		new_range->io_start = allocated_iio_size + new_range->size;
+
+	} else {
+		/* invalid flag */
+		ret = -EINVAL;
+		goto end_register;
+	}
+
+	list_add_tail_rcu(&new_range->list, &io_range_list);
+
+end_register:
+	mutex_unlock(&io_range_mutex);
+	return ret;
+}
+
+/*
+ * traverse the io_range_list to find the registered node whose device node
+ * and/or physical IO address match to.
+ */
+struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->fwnode == fwnode)
+			return range;
+	}
+	return NULL;
+}
+
+/* return a registered range given an input PIO token */
+static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (pio >= range->io_start &&
+				pio < range->io_start + range->size)
+			return range;
+	}
+	pr_err("PIO entry token invalid\n");
+	return NULL;
+}
+
+/*
+ * Translate the input logical pio to the corresponding hardware address.
+ * The input pio should be unique in the whole logical PIO space.
+ */
+resource_size_t logic_pio_to_hwaddr(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+	resource_size_t hwaddr = -1;
+
+	range = find_io_range(pio);
+	if (range)
+		hwaddr = range->hw_start + pio - range->io_start;
+
+	return hwaddr;
+}
+
+/*
+ * This function is generic for translating a hardware address to logical PIO.
+ * @hw_addr: the hardware address of host, can be CPU address or host-local
+ *		address;
+ */
+unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	range = find_io_range_by_fwnode(fwnode);
+	if (!range || range->flags == PIO_CPU_MMIO) {
+		pr_err("range not found or invalid\n");
+		return -1;
+	}
+	return addr - range->hw_start + range->io_start;
+}
+
+unsigned long
+logic_pio_trans_cpuaddr(resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->flags != PIO_CPU_MMIO)
+			continue;
+		if (addr >= range->hw_start &&
+			addr < range->hw_start + range->size)
+			return addr - range->hw_start +
+				range->io_start;
+	}
+	pr_err("addr not registered in io_range_list\n");
+	return -1;
+}
+
+#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
+#define BUILD_LOGIC_PIO(bw, type)\
+type logic_in##bw(unsigned long addr)\
+{\
+	type ret = -1;\
+\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		ret = read##bw(PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			ret = entry->ops->pfin(entry->devpara,\
+					addr, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+	return ret;\
+}	\
+\
+void logic_out##bw(type value, unsigned long addr)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		write##bw(value, PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfout(entry->devpara,\
+						addr, value, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}	\
+\
+void logic_ins##bw(unsigned long addr, void *buffer, unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		reads##bw(PCI_IOBASE + addr, buffer, count);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfins(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+\
+}	\
+\
+void logic_outs##bw(unsigned long addr, const void *buffer,\
+		    unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT)\
+		writes##bw(PCI_IOBASE + addr, buffer, count);\
+	else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfouts(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}
+
+BUILD_LOGIC_PIO(b, u8)
+
+EXPORT_SYMBOL(logic_inb);
+EXPORT_SYMBOL(logic_outb);
+EXPORT_SYMBOL(logic_insb);
+EXPORT_SYMBOL(logic_outsb);
+
+BUILD_LOGIC_PIO(w, u16)
+
+EXPORT_SYMBOL(logic_inw);
+EXPORT_SYMBOL(logic_outw);
+EXPORT_SYMBOL(logic_insw);
+EXPORT_SYMBOL(logic_outsw);
+
+BUILD_LOGIC_PIO(l, u32)
+
+EXPORT_SYMBOL(logic_inl);
+EXPORT_SYMBOL(logic_outl);
+EXPORT_SYMBOL(logic_insl);
+EXPORT_SYMBOL(logic_outsl);
+#endif /* CONFIG_INDIRECT_PIO && PCI_IOBASE */
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
pci_pio_to_address()")' a new I/O space management was supported. With that
driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
can be mapped to logical PIO, converted easily between CPU address and the
corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
in a memory read/write way through the unified in/out accessors.

But on some archs/platforms, there are bus hosts which access I/O
peripherals with host-local I/O port addresses rather than memory
addresses after memory-mapped.
To support those devices, a more generic I/O mapping method is introduced
here. Through this patch, both the CPU addresses and the host-local port
can be mapped into the logical PIO space with different logical/fake PIOs.
After this, all the I/O accesses to either PCI MMIO devices or host-local
I/O peripherals can be unified into the existing I/O accessors defined in
asm-generic/io.h and be redirected to the right device-specific hooks
based on the input logical PIO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 include/asm-generic/io.h  |  50 +++++++++
 include/linux/logic_pio.h | 110 ++++++++++++++++++
 lib/Kconfig               |  26 +++++
 lib/Makefile              |   2 +
 lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 468 insertions(+)
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 7ef015e..f7fbec3 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -351,6 +351,8 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
 #define IO_SPACE_LIMIT 0xffff
 #endif
 
+#include <linux/logic_pio.h>
+
 /*
  * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
  * implemented on hardware that needs an additional delay for I/O accesses to
@@ -358,51 +360,75 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
  */
 
 #ifndef inb
+#ifdef CONFIG_INDIRECT_PIO
+#define inb logic_inb
+#else
 #define inb inb
 static inline u8 inb(unsigned long addr)
 {
 	return readb(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inw
+#ifdef CONFIG_INDIRECT_PIO
+#define inw logic_inw
+#else
 #define inw inw
 static inline u16 inw(unsigned long addr)
 {
 	return readw(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inl
+#ifdef CONFIG_INDIRECT_PIO
+#define inl logic_inl
+#else
 #define inl inl
 static inline u32 inl(unsigned long addr)
 {
 	return readl(PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outb
+#ifdef CONFIG_INDIRECT_PIO
+#define outb logic_outb
+#else
 #define outb outb
 static inline void outb(u8 value, unsigned long addr)
 {
 	writeb(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outw
+#ifdef CONFIG_INDIRECT_PIO
+#define outw logic_outw
+#else
 #define outw outw
 static inline void outw(u16 value, unsigned long addr)
 {
 	writew(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outl
+#ifdef CONFIG_INDIRECT_PIO
+#define outl logic_outl
+#else
 #define outl outl
 static inline void outl(u32 value, unsigned long addr)
 {
 	writel(value, PCI_IOBASE + addr);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef inb_p
@@ -459,54 +485,78 @@ static inline void outl_p(u32 value, unsigned long addr)
  */
 
 #ifndef insb
+#ifdef CONFIG_INDIRECT_PIO
+#define insb logic_insb
+#else
 #define insb insb
 static inline void insb(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insw
+#ifdef CONFIG_INDIRECT_PIO
+#define insw logic_insw
+#else
 #define insw insw
 static inline void insw(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insl
+#ifdef CONFIG_INDIRECT_PIO
+#define insl logic_insl
+#else
 #define insl insl
 static inline void insl(unsigned long addr, void *buffer, unsigned int count)
 {
 	readsl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsb
+#ifdef CONFIG_INDIRECT_PIO
+#define outsb logic_outsb
+#else
 #define outsb outsb
 static inline void outsb(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesb(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsw
+#ifdef CONFIG_INDIRECT_PIO
+#define outsw logic_outsw
+#else
 #define outsw outsw
 static inline void outsw(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesw(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef outsl
+#ifdef CONFIG_INDIRECT_PIO
+#define outsl logic_outsl
+#else
 #define outsl outsl
 static inline void outsl(unsigned long addr, const void *buffer,
 			 unsigned int count)
 {
 	writesl(PCI_IOBASE + addr, buffer, count);
 }
+#endif /* CONFIG_INDIRECT_PIO */
 #endif
 
 #ifndef insb_p
diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
new file mode 100644
index 0000000..8e4dc65
--- /dev/null
+++ b/include/linux/logic_pio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_LOGIC_PIO_H
+#define __LINUX_LOGIC_PIO_H
+
+#ifdef __KERNEL__
+
+#include <linux/fwnode.h>
+
+#define PIO_INDIRECT		0x01UL /* indirect IO flag */
+#define PIO_CPU_MMIO		0x00UL /* memory mapped io flag */
+
+struct logic_pio_hwaddr {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	resource_size_t hw_start;
+	resource_size_t io_start;
+	resource_size_t size; /* range size populated */
+	unsigned long flags;
+
+	void *devpara;	/* private parameter of the host device */
+	struct hostio_ops *ops;	/* ops operating on this node */
+};
+
+struct hostio_ops {
+	u32 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+			size_t dlen);
+	u32 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+			size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count);
+};
+
+extern u8 logic_inb(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern u16 logic_inw(unsigned long addr);
+extern u32 logic_inl(unsigned long addr);
+extern void logic_outb(u8 value, unsigned long addr);
+extern void logic_outw(u16 value, unsigned long addr);
+extern void logic_outl(u32 value, unsigned long addr);
+extern void logic_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insl(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_insw(unsigned long addr, void *buffer, unsigned int count);
+extern void logic_outsb(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsw(unsigned long addr, const void *buffer,
+			unsigned int count);
+extern void logic_outsl(unsigned long addr, const void *buffer,
+			unsigned int count);
+
+#ifdef CONFIG_INDIRECT_PIO
+/* Below make 75% of IO Space for MMIO and the rest for Indirect IO */
+#define MMIO_UPPER_LIMIT (IO_SPACE_LIMIT - (IO_SPACE_LIMIT >> 2))
+#else
+#define MMIO_UPPER_LIMIT IO_SPACE_LIMIT
+#endif
+
+#ifdef CONFIG_LOGIC_PIO
+extern struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
+
+extern unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
+			resource_size_t hw_addr);
+
+extern int logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+#else
+static inline struct logic_pio_hwaddr
+*find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t hw_addr)
+{
+	return -1;
+}
+
+static inline struct logic_pio_hwaddr
+*logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+{
+	return NULL;
+}
+#endif
+
+extern resource_size_t logic_pio_to_hwaddr(unsigned long pio);
+
+extern unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_LOGIC_PIO_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 0c8b78a..503c2e0 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -59,6 +59,32 @@ config ARCH_USE_CMPXCHG_LOCKREF
 config ARCH_HAS_FAST_MULTIPLIER
 	bool
 
+config LOGIC_PIO
+	bool "Generic logical I/O management"
+	def_bool y if PCI && !X86 && !IA64 && !POWERPC
+	help
+	  For some architectures, there are no IO space. To support the
+	  accesses to legacy I/O devices on those architectures, kernel
+	  implemented the memory mapped I/O mechanism based on bridge bus
+	  supports. But for some buses which do not support MMIO, the
+	  peripherals there should be accessed with device-specific way.
+	  To abstract those different I/O accesses into unified I/O accessors,
+	  this option provide a generic I/O space management way after mapping
+	  the device I/O to system logical/fake I/O and help to hide all the
+	  hardware detail.
+
+config INDIRECT_PIO
+	bool "Access I/O in non-MMIO mode" if LOGIC_PIO
+	help
+	  On some platforms where no separate I/O space exist, there are I/O
+	  hosts which can not be accessed in MMIO mode. Based on LOGIC_PIO
+	  mechanism, the host-local I/O resource can be mapped into system
+	  logic PIO space shared with MMIO hosts, such as PCI/PCIE, then system
+	  can access the I/O devices with the mapped logic PIO through I/O
+	  accessors.
+	  This way has a little I/O performance cost. Please make sure your
+	  devices really need this configure item enabled.
+
 config CRC_CCITT
 	tristate "CRC-CCITT functions"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 0166fbc..1a27f6e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
+obj-$(CONFIG_LOGIC_PIO) += logic_pio.o
+
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
 obj-$(CONFIG_BTREE) += btree.o
diff --git a/lib/logic_pio.c b/lib/logic_pio.c
new file mode 100644
index 0000000..4a960cd
--- /dev/null
+++ b/lib/logic_pio.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/mm.h>
+#include <linux/rculist.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+/* The unique hardware address list. */
+static LIST_HEAD(io_range_list);
+static DEFINE_MUTEX(io_range_mutex);
+
+/*
+ * register a new io range node in the io range list.
+ *
+ * @newrange: pointer to the io range to be registered.
+ *
+ * returns 0 on success, the error code in case of failure
+ */
+int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
+{
+	struct logic_pio_hwaddr *range;
+	int ret = 0;
+	resource_size_t start = new_range->hw_start;
+	resource_size_t end = new_range->hw_start + new_range->size;
+	resource_size_t allocated_mmio_size = 0;
+	resource_size_t allocated_iio_size = MMIO_UPPER_LIMIT;
+
+	if (!new_range || !new_range->fwnode || !new_range->size)
+		return -EINVAL;
+
+	mutex_lock(&io_range_mutex);
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+
+		if (range->fwnode == new_range->fwnode) {
+			/* range already there */
+			ret = -EFAULT;
+			goto end_register;
+		}
+		if (range->flags == PIO_CPU_MMIO &&
+				new_range->flags == PIO_CPU_MMIO) {
+			/* for MMIO ranges we need to check for overlap */
+			if (start >= range->hw_start + range->size ||
+				end < range->hw_start)
+				allocated_mmio_size += range->size;
+			else {
+				ret = -EFAULT;
+				goto end_register;
+			}
+		} else if (range->flags == PIO_INDIRECT &&
+				new_range->flags == PIO_INDIRECT) {
+			allocated_iio_size += range->size;
+		}
+	}
+
+	/* range not registered yet, check for available space */
+	if (new_range->flags == PIO_CPU_MMIO) {
+
+		if (allocated_mmio_size + new_range->size - 1 >
+			MMIO_UPPER_LIMIT) {
+			/* if it's too big check if 64K space can be reserved */
+			if (allocated_mmio_size + SZ_64K - 1 >
+			MMIO_UPPER_LIMIT) {
+				ret = -E2BIG;
+				goto end_register;
+			}
+			new_range->size = SZ_64K;
+			pr_warn("Requested IO range too big, new size set to 64K\n");
+		}
+
+		new_range->io_start = allocated_mmio_size + new_range->size;
+
+	} else if (new_range->flags == PIO_INDIRECT) {
+
+		if (allocated_iio_size + new_range->size - 1 >
+		IO_SPACE_LIMIT) {
+			ret = -E2BIG;
+			goto end_register;
+		}
+		new_range->io_start = allocated_iio_size + new_range->size;
+
+	} else {
+		/* invalid flag */
+		ret = -EINVAL;
+		goto end_register;
+	}
+
+	list_add_tail_rcu(&new_range->list, &io_range_list);
+
+end_register:
+	mutex_unlock(&io_range_mutex);
+	return ret;
+}
+
+/*
+ * traverse the io_range_list to find the registered node whose device node
+ * and/or physical IO address match to.
+ */
+struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->fwnode == fwnode)
+			return range;
+	}
+	return NULL;
+}
+
+/* return a registered range given an input PIO token */
+static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (pio >= range->io_start &&
+				pio < range->io_start + range->size)
+			return range;
+	}
+	pr_err("PIO entry token invalid\n");
+	return NULL;
+}
+
+/*
+ * Translate the input logical pio to the corresponding hardware address.
+ * The input pio should be unique in the whole logical PIO space.
+ */
+resource_size_t logic_pio_to_hwaddr(unsigned long pio)
+{
+	struct logic_pio_hwaddr *range;
+	resource_size_t hwaddr = -1;
+
+	range = find_io_range(pio);
+	if (range)
+		hwaddr = range->hw_start + pio - range->io_start;
+
+	return hwaddr;
+}
+
+/*
+ * This function is generic for translating a hardware address to logical PIO.
+ * @hw_addr: the hardware address of host, can be CPU address or host-local
+ *		address;
+ */
+unsigned long
+logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	range = find_io_range_by_fwnode(fwnode);
+	if (!range || range->flags == PIO_CPU_MMIO) {
+		pr_err("range not found or invalid\n");
+		return -1;
+	}
+	return addr - range->hw_start + range->io_start;
+}
+
+unsigned long
+logic_pio_trans_cpuaddr(resource_size_t addr)
+{
+	struct logic_pio_hwaddr *range;
+
+	list_for_each_entry_rcu(range, &io_range_list, list) {
+		if (range->flags != PIO_CPU_MMIO)
+			continue;
+		if (addr >= range->hw_start &&
+			addr < range->hw_start + range->size)
+			return addr - range->hw_start +
+				range->io_start;
+	}
+	pr_err("addr not registered in io_range_list\n");
+	return -1;
+}
+
+#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
+#define BUILD_LOGIC_PIO(bw, type)\
+type logic_in##bw(unsigned long addr)\
+{\
+	type ret = -1;\
+\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		ret = read##bw(PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			ret = entry->ops->pfin(entry->devpara,\
+					addr, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+	return ret;\
+}	\
+\
+void logic_out##bw(type value, unsigned long addr)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		write##bw(value, PCI_IOBASE + addr);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfout(entry->devpara,\
+						addr, value, sizeof(type));\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}	\
+\
+void logic_ins##bw(unsigned long addr, void *buffer, unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT) {\
+		reads##bw(PCI_IOBASE + addr, buffer, count);\
+	} else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfins(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+\
+}	\
+\
+void logic_outs##bw(unsigned long addr, const void *buffer,\
+		    unsigned int count)\
+{\
+	if (addr < MMIO_UPPER_LIMIT)\
+		writes##bw(PCI_IOBASE + addr, buffer, count);\
+	else {\
+		struct logic_pio_hwaddr *entry = find_io_range(addr);\
+\
+		if (entry && entry->ops)\
+			entry->ops->pfouts(entry->devpara,\
+				addr, buffer, sizeof(type), count);\
+		else\
+			WARN_ON_ONCE(1);\
+	}	\
+}
+
+BUILD_LOGIC_PIO(b, u8)
+
+EXPORT_SYMBOL(logic_inb);
+EXPORT_SYMBOL(logic_outb);
+EXPORT_SYMBOL(logic_insb);
+EXPORT_SYMBOL(logic_outsb);
+
+BUILD_LOGIC_PIO(w, u16)
+
+EXPORT_SYMBOL(logic_inw);
+EXPORT_SYMBOL(logic_outw);
+EXPORT_SYMBOL(logic_insw);
+EXPORT_SYMBOL(logic_outsw);
+
+BUILD_LOGIC_PIO(l, u32)
+
+EXPORT_SYMBOL(logic_inl);
+EXPORT_SYMBOL(logic_outl);
+EXPORT_SYMBOL(logic_insl);
+EXPORT_SYMBOL(logic_outsl);
+#endif /* CONFIG_INDIRECT_PIO && PCI_IOBASE */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

After introducing the new generic I/O space management(LOGIC_IO), the
original PCI MMIO relevant helpers need to be updated based on the new
interfaces defined in LOGIC_IO.
This patch adapts the corresponding code to match the changes introduced
by LOGIC_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
---
 drivers/acpi/pci_root.c  |   8 ++--
 drivers/of/address.c     |   5 ++-
 drivers/pci/pci.c        | 101 ++++++++++-------------------------------------
 include/asm-generic/io.h |   2 +-
 include/linux/pci.h      |   3 +-
 5 files changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 919be0a..4d8cc24 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -730,7 +730,8 @@ static void acpi_pci_root_validate_resources(struct device *dev,
 	}
 }
 
-static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
+			struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,7 +740,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
 	resource_size_t length = resource_size(res);
 	unsigned long port;
 
-	if (pci_register_io_range(cpu_addr, length))
+	if (pci_register_io_range(fwnode, cpu_addr, length))
 		goto err;
 
 	port = pci_address_to_pio(cpu_addr);
@@ -781,7 +782,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
 			if (entry->res->flags & IORESOURCE_IO)
-				acpi_pci_root_remap_iospace(entry);
+				acpi_pci_root_remap_iospace(&device->fwnode,
+						entry);
 
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72914cd..34a55e8 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,8 +2,10 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/logic_pio.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci.h>
@@ -323,7 +325,8 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 
 	if (res->flags & IORESOURCE_IO) {
 		unsigned long port;
-		err = pci_register_io_range(range->cpu_addr, range->size);
+		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
+				range->size);
 		if (err)
 			goto invalid_range;
 		port = pci_address_to_pio(range->cpu_addr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b01bd5b..c9fe12b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/logic_pio.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -3241,68 +3242,34 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#ifdef PCI_IOBASE
-struct io_range {
-	struct list_head list;
-	phys_addr_t start;
-	resource_size_t size;
-};
-
-static LIST_HEAD(io_range_list);
-static DEFINE_SPINLOCK(io_range_lock);
-#endif
-
 /*
  * Record the PCI IO range (expressed as CPU physical address + size).
  * Return a negative value if an error has occured, zero otherwise
  */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t	size)
 {
-	int err = 0;
-
+	int ret = 0;
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	/* check if the range hasn't been previously recorded */
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (addr >= range->start && addr + size <= range->start + size) {
-			/* range already registered, bail out */
-			goto end_register;
-		}
-		allocated_size += range->size;
-	}
-
-	/* range not registed yet, check for available space */
-	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
-		/* if it's too big check if 64K space can be reserved */
-		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
-			err = -E2BIG;
-			goto end_register;
-		}
-
-		size = SZ_64K;
-		pr_warn("Requested IO range too big, new size set to 64K\n");
-	}
+	struct logic_pio_hwaddr *range;
 
-	/* add the range to the list */
-	range = kzalloc(sizeof(*range), GFP_ATOMIC);
-	if (!range) {
-		err = -ENOMEM;
-		goto end_register;
-	}
+	if (!size || addr + size < addr)
+		return -EINVAL;
 
-	range->start = addr;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = fwnode;
 	range->size = size;
+	range->hw_start = addr;
+	range->flags = PIO_CPU_MMIO;
 
-	list_add_tail(&range->list, &io_range_list);
-
-end_register:
-	spin_unlock(&io_range_lock);
+	ret = logic_pio_register_range(range);
+	if (ret)
+		kfree(range);
 #endif
 
-	return err;
+	return ret;
 }
 
 phys_addr_t pci_pio_to_address(unsigned long pio)
@@ -3310,21 +3277,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	if (pio > IO_SPACE_LIMIT)
+	if (pio >= MMIO_UPPER_LIMIT)
 		return address;
 
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (pio >= allocated_size && pio < allocated_size + range->size) {
-			address = range->start + pio - allocated_size;
-			break;
-		}
-		allocated_size += range->size;
-	}
-	spin_unlock(&io_range_lock);
+	address = logic_pio_to_hwaddr(pio);
 #endif
 
 	return address;
@@ -3333,25 +3289,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
-	struct io_range *res;
-	resource_size_t offset = 0;
-	unsigned long addr = -1;
-
-	spin_lock(&io_range_lock);
-	list_for_each_entry(res, &io_range_list, list) {
-		if (address >= res->start && address < res->start + res->size) {
-			addr = address - res->start + offset;
-			break;
-		}
-		offset += res->size;
-	}
-	spin_unlock(&io_range_lock);
-
-	return addr;
+	return logic_pio_trans_cpuaddr(address);
 #else
-	if (address > IO_SPACE_LIMIT)
-		return (unsigned long)-1;
-
 	return (unsigned long) address;
 #endif
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index f7fbec3..41ecc09 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -949,7 +949,7 @@ static inline void iounmap(void __iomem *addr)
 #define ioport_map ioport_map
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return PCI_IOBASE + (port & IO_SPACE_LIMIT);
+	return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
 }
 #endif
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33c2b0b..e420d03 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1188,7 +1188,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 			void *alignf_data);
 
 
-int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

After introducing the new generic I/O space management(LOGIC_IO), the
original PCI MMIO relevant helpers need to be updated based on the new
interfaces defined in LOGIC_IO.
This patch adapts the corresponding code to match the changes introduced
by LOGIC_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
---
 drivers/acpi/pci_root.c  |   8 ++--
 drivers/of/address.c     |   5 ++-
 drivers/pci/pci.c        | 101 ++++++++++-------------------------------------
 include/asm-generic/io.h |   2 +-
 include/linux/pci.h      |   3 +-
 5 files changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 919be0a..4d8cc24 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -730,7 +730,8 @@ static void acpi_pci_root_validate_resources(struct device *dev,
 	}
 }
 
-static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
+			struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,7 +740,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
 	resource_size_t length = resource_size(res);
 	unsigned long port;
 
-	if (pci_register_io_range(cpu_addr, length))
+	if (pci_register_io_range(fwnode, cpu_addr, length))
 		goto err;
 
 	port = pci_address_to_pio(cpu_addr);
@@ -781,7 +782,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
 			if (entry->res->flags & IORESOURCE_IO)
-				acpi_pci_root_remap_iospace(entry);
+				acpi_pci_root_remap_iospace(&device->fwnode,
+						entry);
 
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72914cd..34a55e8 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,8 +2,10 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/logic_pio.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci.h>
@@ -323,7 +325,8 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 
 	if (res->flags & IORESOURCE_IO) {
 		unsigned long port;
-		err = pci_register_io_range(range->cpu_addr, range->size);
+		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
+				range->size);
 		if (err)
 			goto invalid_range;
 		port = pci_address_to_pio(range->cpu_addr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b01bd5b..c9fe12b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/logic_pio.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -3241,68 +3242,34 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#ifdef PCI_IOBASE
-struct io_range {
-	struct list_head list;
-	phys_addr_t start;
-	resource_size_t size;
-};
-
-static LIST_HEAD(io_range_list);
-static DEFINE_SPINLOCK(io_range_lock);
-#endif
-
 /*
  * Record the PCI IO range (expressed as CPU physical address + size).
  * Return a negative value if an error has occured, zero otherwise
  */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t	size)
 {
-	int err = 0;
-
+	int ret = 0;
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	/* check if the range hasn't been previously recorded */
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (addr >= range->start && addr + size <= range->start + size) {
-			/* range already registered, bail out */
-			goto end_register;
-		}
-		allocated_size += range->size;
-	}
-
-	/* range not registed yet, check for available space */
-	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
-		/* if it's too big check if 64K space can be reserved */
-		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
-			err = -E2BIG;
-			goto end_register;
-		}
-
-		size = SZ_64K;
-		pr_warn("Requested IO range too big, new size set to 64K\n");
-	}
+	struct logic_pio_hwaddr *range;
 
-	/* add the range to the list */
-	range = kzalloc(sizeof(*range), GFP_ATOMIC);
-	if (!range) {
-		err = -ENOMEM;
-		goto end_register;
-	}
+	if (!size || addr + size < addr)
+		return -EINVAL;
 
-	range->start = addr;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = fwnode;
 	range->size = size;
+	range->hw_start = addr;
+	range->flags = PIO_CPU_MMIO;
 
-	list_add_tail(&range->list, &io_range_list);
-
-end_register:
-	spin_unlock(&io_range_lock);
+	ret = logic_pio_register_range(range);
+	if (ret)
+		kfree(range);
 #endif
 
-	return err;
+	return ret;
 }
 
 phys_addr_t pci_pio_to_address(unsigned long pio)
@@ -3310,21 +3277,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	if (pio > IO_SPACE_LIMIT)
+	if (pio >= MMIO_UPPER_LIMIT)
 		return address;
 
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (pio >= allocated_size && pio < allocated_size + range->size) {
-			address = range->start + pio - allocated_size;
-			break;
-		}
-		allocated_size += range->size;
-	}
-	spin_unlock(&io_range_lock);
+	address = logic_pio_to_hwaddr(pio);
 #endif
 
 	return address;
@@ -3333,25 +3289,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
-	struct io_range *res;
-	resource_size_t offset = 0;
-	unsigned long addr = -1;
-
-	spin_lock(&io_range_lock);
-	list_for_each_entry(res, &io_range_list, list) {
-		if (address >= res->start && address < res->start + res->size) {
-			addr = address - res->start + offset;
-			break;
-		}
-		offset += res->size;
-	}
-	spin_unlock(&io_range_lock);
-
-	return addr;
+	return logic_pio_trans_cpuaddr(address);
 #else
-	if (address > IO_SPACE_LIMIT)
-		return (unsigned long)-1;
-
 	return (unsigned long) address;
 #endif
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index f7fbec3..41ecc09 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -949,7 +949,7 @@ static inline void iounmap(void __iomem *addr)
 #define ioport_map ioport_map
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return PCI_IOBASE + (port & IO_SPACE_LIMIT);
+	return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
 }
 #endif
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33c2b0b..e420d03 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1188,7 +1188,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 			void *alignf_data);
 
 
-int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, zhichang.yuan,
	linux-pci, olof, brian.starkey

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

After introducing the new generic I/O space management(LOGIC_IO), the
original PCI MMIO relevant helpers need to be updated based on the new
interfaces defined in LOGIC_IO.
This patch adapts the corresponding code to match the changes introduced
by LOGIC_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
---
 drivers/acpi/pci_root.c  |   8 ++--
 drivers/of/address.c     |   5 ++-
 drivers/pci/pci.c        | 101 ++++++++++-------------------------------------
 include/asm-generic/io.h |   2 +-
 include/linux/pci.h      |   3 +-
 5 files changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 919be0a..4d8cc24 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -730,7 +730,8 @@ static void acpi_pci_root_validate_resources(struct device *dev,
 	}
 }
 
-static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
+			struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,7 +740,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
 	resource_size_t length = resource_size(res);
 	unsigned long port;
 
-	if (pci_register_io_range(cpu_addr, length))
+	if (pci_register_io_range(fwnode, cpu_addr, length))
 		goto err;
 
 	port = pci_address_to_pio(cpu_addr);
@@ -781,7 +782,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
 			if (entry->res->flags & IORESOURCE_IO)
-				acpi_pci_root_remap_iospace(entry);
+				acpi_pci_root_remap_iospace(&device->fwnode,
+						entry);
 
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72914cd..34a55e8 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,8 +2,10 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/logic_pio.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci.h>
@@ -323,7 +325,8 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 
 	if (res->flags & IORESOURCE_IO) {
 		unsigned long port;
-		err = pci_register_io_range(range->cpu_addr, range->size);
+		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
+				range->size);
 		if (err)
 			goto invalid_range;
 		port = pci_address_to_pio(range->cpu_addr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b01bd5b..c9fe12b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/logic_pio.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -3241,68 +3242,34 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#ifdef PCI_IOBASE
-struct io_range {
-	struct list_head list;
-	phys_addr_t start;
-	resource_size_t size;
-};
-
-static LIST_HEAD(io_range_list);
-static DEFINE_SPINLOCK(io_range_lock);
-#endif
-
 /*
  * Record the PCI IO range (expressed as CPU physical address + size).
  * Return a negative value if an error has occured, zero otherwise
  */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t	size)
 {
-	int err = 0;
-
+	int ret = 0;
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	/* check if the range hasn't been previously recorded */
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (addr >= range->start && addr + size <= range->start + size) {
-			/* range already registered, bail out */
-			goto end_register;
-		}
-		allocated_size += range->size;
-	}
-
-	/* range not registed yet, check for available space */
-	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
-		/* if it's too big check if 64K space can be reserved */
-		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
-			err = -E2BIG;
-			goto end_register;
-		}
-
-		size = SZ_64K;
-		pr_warn("Requested IO range too big, new size set to 64K\n");
-	}
+	struct logic_pio_hwaddr *range;
 
-	/* add the range to the list */
-	range = kzalloc(sizeof(*range), GFP_ATOMIC);
-	if (!range) {
-		err = -ENOMEM;
-		goto end_register;
-	}
+	if (!size || addr + size < addr)
+		return -EINVAL;
 
-	range->start = addr;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = fwnode;
 	range->size = size;
+	range->hw_start = addr;
+	range->flags = PIO_CPU_MMIO;
 
-	list_add_tail(&range->list, &io_range_list);
-
-end_register:
-	spin_unlock(&io_range_lock);
+	ret = logic_pio_register_range(range);
+	if (ret)
+		kfree(range);
 #endif
 
-	return err;
+	return ret;
 }
 
 phys_addr_t pci_pio_to_address(unsigned long pio)
@@ -3310,21 +3277,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	if (pio > IO_SPACE_LIMIT)
+	if (pio >= MMIO_UPPER_LIMIT)
 		return address;
 
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (pio >= allocated_size && pio < allocated_size + range->size) {
-			address = range->start + pio - allocated_size;
-			break;
-		}
-		allocated_size += range->size;
-	}
-	spin_unlock(&io_range_lock);
+	address = logic_pio_to_hwaddr(pio);
 #endif
 
 	return address;
@@ -3333,25 +3289,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
-	struct io_range *res;
-	resource_size_t offset = 0;
-	unsigned long addr = -1;
-
-	spin_lock(&io_range_lock);
-	list_for_each_entry(res, &io_range_list, list) {
-		if (address >= res->start && address < res->start + res->size) {
-			addr = address - res->start + offset;
-			break;
-		}
-		offset += res->size;
-	}
-	spin_unlock(&io_range_lock);
-
-	return addr;
+	return logic_pio_trans_cpuaddr(address);
 #else
-	if (address > IO_SPACE_LIMIT)
-		return (unsigned long)-1;
-
 	return (unsigned long) address;
 #endif
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index f7fbec3..41ecc09 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -949,7 +949,7 @@ static inline void iounmap(void __iomem *addr)
 #define ioport_map ioport_map
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return PCI_IOBASE + (port & IO_SPACE_LIMIT);
+	return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
 }
 #endif
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33c2b0b..e420d03 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1188,7 +1188,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 			void *alignf_data);
 
 
-int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

After introducing the new generic I/O space management(LOGIC_IO), the
original PCI MMIO relevant helpers need to be updated based on the new
interfaces defined in LOGIC_IO.
This patch adapts the corresponding code to match the changes introduced
by LOGIC_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
---
 drivers/acpi/pci_root.c  |   8 ++--
 drivers/of/address.c     |   5 ++-
 drivers/pci/pci.c        | 101 ++++++++++-------------------------------------
 include/asm-generic/io.h |   2 +-
 include/linux/pci.h      |   3 +-
 5 files changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 919be0a..4d8cc24 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -730,7 +730,8 @@ static void acpi_pci_root_validate_resources(struct device *dev,
 	}
 }
 
-static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
+			struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,7 +740,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
 	resource_size_t length = resource_size(res);
 	unsigned long port;
 
-	if (pci_register_io_range(cpu_addr, length))
+	if (pci_register_io_range(fwnode, cpu_addr, length))
 		goto err;
 
 	port = pci_address_to_pio(cpu_addr);
@@ -781,7 +782,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
 			if (entry->res->flags & IORESOURCE_IO)
-				acpi_pci_root_remap_iospace(entry);
+				acpi_pci_root_remap_iospace(&device->fwnode,
+						entry);
 
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72914cd..34a55e8 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,8 +2,10 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/logic_pio.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci.h>
@@ -323,7 +325,8 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 
 	if (res->flags & IORESOURCE_IO) {
 		unsigned long port;
-		err = pci_register_io_range(range->cpu_addr, range->size);
+		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
+				range->size);
 		if (err)
 			goto invalid_range;
 		port = pci_address_to_pio(range->cpu_addr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b01bd5b..c9fe12b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/logic_pio.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -3241,68 +3242,34 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#ifdef PCI_IOBASE
-struct io_range {
-	struct list_head list;
-	phys_addr_t start;
-	resource_size_t size;
-};
-
-static LIST_HEAD(io_range_list);
-static DEFINE_SPINLOCK(io_range_lock);
-#endif
-
 /*
  * Record the PCI IO range (expressed as CPU physical address + size).
  * Return a negative value if an error has occured, zero otherwise
  */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t	size)
 {
-	int err = 0;
-
+	int ret = 0;
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	/* check if the range hasn't been previously recorded */
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (addr >= range->start && addr + size <= range->start + size) {
-			/* range already registered, bail out */
-			goto end_register;
-		}
-		allocated_size += range->size;
-	}
-
-	/* range not registed yet, check for available space */
-	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
-		/* if it's too big check if 64K space can be reserved */
-		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
-			err = -E2BIG;
-			goto end_register;
-		}
-
-		size = SZ_64K;
-		pr_warn("Requested IO range too big, new size set to 64K\n");
-	}
+	struct logic_pio_hwaddr *range;
 
-	/* add the range to the list */
-	range = kzalloc(sizeof(*range), GFP_ATOMIC);
-	if (!range) {
-		err = -ENOMEM;
-		goto end_register;
-	}
+	if (!size || addr + size < addr)
+		return -EINVAL;
 
-	range->start = addr;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = fwnode;
 	range->size = size;
+	range->hw_start = addr;
+	range->flags = PIO_CPU_MMIO;
 
-	list_add_tail(&range->list, &io_range_list);
-
-end_register:
-	spin_unlock(&io_range_lock);
+	ret = logic_pio_register_range(range);
+	if (ret)
+		kfree(range);
 #endif
 
-	return err;
+	return ret;
 }
 
 phys_addr_t pci_pio_to_address(unsigned long pio)
@@ -3310,21 +3277,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 
 #ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	if (pio > IO_SPACE_LIMIT)
+	if (pio >= MMIO_UPPER_LIMIT)
 		return address;
 
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (pio >= allocated_size && pio < allocated_size + range->size) {
-			address = range->start + pio - allocated_size;
-			break;
-		}
-		allocated_size += range->size;
-	}
-	spin_unlock(&io_range_lock);
+	address = logic_pio_to_hwaddr(pio);
 #endif
 
 	return address;
@@ -3333,25 +3289,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
-	struct io_range *res;
-	resource_size_t offset = 0;
-	unsigned long addr = -1;
-
-	spin_lock(&io_range_lock);
-	list_for_each_entry(res, &io_range_list, list) {
-		if (address >= res->start && address < res->start + res->size) {
-			addr = address - res->start + offset;
-			break;
-		}
-		offset += res->size;
-	}
-	spin_unlock(&io_range_lock);
-
-	return addr;
+	return logic_pio_trans_cpuaddr(address);
 #else
-	if (address > IO_SPACE_LIMIT)
-		return (unsigned long)-1;
-
 	return (unsigned long) address;
 #endif
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index f7fbec3..41ecc09 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -949,7 +949,7 @@ static inline void iounmap(void __iomem *addr)
 #define ioport_map ioport_map
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return PCI_IOBASE + (port & IO_SPACE_LIMIT);
+	return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
 }
 #endif
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33c2b0b..e420d03 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1188,7 +1188,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 			void *alignf_data);
 
 
-int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

There are some special ISA/LPC devices that work on a specific I/O range
where it is not correct to specify a 'ranges' property in DTS parent node
as cpu addresses translated from DTS node are only for memory space on some
architectures, such as Arm64. Without the parent 'ranges' property, current
of_translate_address() return an error.
Here we add special handlings for this case.
During the OF address translation, some checkings will be perfromed to
identify whether the device node is registered as indirect-IO. If yes, the
I/O translation will be done in a different way from that one of PCI MMIO.
In this way, the I/O 'reg' property of the special ISA/LPC devices will be
parsed correctly.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>    #earlier draft
Acked-by: Rob Herring <robh@kernel.org>
---
 drivers/of/address.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 74 insertions(+), 16 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 34a55e8..c51de70 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -552,9 +552,14 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that translation is impossible (that is we are not dealing with a value
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
+ *
+ * Whenever the translation fails, the *host pointer will be set to the
+ * device that had registered logical PIO mapping, and the return code is
+ * relative to that node.
  */
 static u64 __of_translate_address(struct device_node *dev,
-				  const __be32 *in_addr, const char *rprop)
+				  const __be32 *in_addr, const char *rprop,
+				  struct device_node **host)
 {
 	struct device_node *parent = NULL;
 	struct of_bus *bus, *pbus;
@@ -567,6 +572,7 @@ static u64 __of_translate_address(struct device_node *dev,
 	/* Increase refcount at current level */
 	of_node_get(dev);
 
+	*host = NULL;
 	/* Get parent & match bus type */
 	parent = of_get_parent(dev);
 	if (parent == NULL)
@@ -587,6 +593,8 @@ static u64 __of_translate_address(struct device_node *dev,
 
 	/* Translate */
 	for (;;) {
+		struct logic_pio_hwaddr *iorange;
+
 		/* Switch to parent bus */
 		of_node_put(dev);
 		dev = parent;
@@ -599,6 +607,19 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		iorange = find_io_range_by_fwnode(&dev->fwnode);
+		if (iorange && (iorange->flags != PIO_CPU_MMIO)) {
+			result = of_read_number(addr + 1, na - 1);
+			pr_debug("indirectIO matched(%s) 0x%llx\n",
+					of_node_full_name(dev), result);
+			*host = of_node_get(dev);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
@@ -631,13 +652,32 @@ static u64 __of_translate_address(struct device_node *dev,
 
 u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret =  __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_address);
 
 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "dma-ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret = __of_translate_address(dev, in_addr, "dma-ranges", &host);
+
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_dma_address);
 
@@ -679,29 +719,47 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr)
+{
+	u64 taddr;
+	unsigned long port;
+	struct device_node *host;
+
+	taddr = __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		/* host specific port access */
+		port = logic_pio_trans_hwaddr(&host->fwnode, taddr);
+		of_node_put(host);
+	} else {
+		/* memory mapped I/O range */
+		port = pci_address_to_pio(taddr);
+	}
+
+	if (port == (unsigned long)-1)
+		return OF_BAD_ADDR;
+
+	return port;
+}
+
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
 {
 	u64 taddr;
 
-	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+	if (flags & IORESOURCE_MEM)
+		taddr = of_translate_address(dev, addrp);
+	else if (flags & IORESOURCE_IO)
+		taddr = of_translate_ioport(dev, addrp);
+	else
 		return -EINVAL;
-	taddr = of_translate_address(dev, addrp);
+
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
-		unsigned long port;
-		port = pci_address_to_pio(taddr);
-		if (port == (unsigned long)-1)
-			return -EINVAL;
-		r->start = port;
-		r->end = port + size - 1;
-	} else {
-		r->start = taddr;
-		r->end = taddr + size - 1;
-	}
+
+	r->start = taddr;
+	r->end = taddr + size - 1;
 	r->flags = flags;
 	r->name = name ? name : dev->full_name;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

There are some special ISA/LPC devices that work on a specific I/O range
where it is not correct to specify a 'ranges' property in DTS parent node
as cpu addresses translated from DTS node are only for memory space on some
architectures, such as Arm64. Without the parent 'ranges' property, current
of_translate_address() return an error.
Here we add special handlings for this case.
During the OF address translation, some checkings will be perfromed to
identify whether the device node is registered as indirect-IO. If yes, the
I/O translation will be done in a different way from that one of PCI MMIO.
In this way, the I/O 'reg' property of the special ISA/LPC devices will be
parsed correctly.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>    #earlier draft
Acked-by: Rob Herring <robh@kernel.org>
---
 drivers/of/address.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 74 insertions(+), 16 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 34a55e8..c51de70 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -552,9 +552,14 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that translation is impossible (that is we are not dealing with a value
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
+ *
+ * Whenever the translation fails, the *host pointer will be set to the
+ * device that had registered logical PIO mapping, and the return code is
+ * relative to that node.
  */
 static u64 __of_translate_address(struct device_node *dev,
-				  const __be32 *in_addr, const char *rprop)
+				  const __be32 *in_addr, const char *rprop,
+				  struct device_node **host)
 {
 	struct device_node *parent = NULL;
 	struct of_bus *bus, *pbus;
@@ -567,6 +572,7 @@ static u64 __of_translate_address(struct device_node *dev,
 	/* Increase refcount at current level */
 	of_node_get(dev);
 
+	*host = NULL;
 	/* Get parent & match bus type */
 	parent = of_get_parent(dev);
 	if (parent == NULL)
@@ -587,6 +593,8 @@ static u64 __of_translate_address(struct device_node *dev,
 
 	/* Translate */
 	for (;;) {
+		struct logic_pio_hwaddr *iorange;
+
 		/* Switch to parent bus */
 		of_node_put(dev);
 		dev = parent;
@@ -599,6 +607,19 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		iorange = find_io_range_by_fwnode(&dev->fwnode);
+		if (iorange && (iorange->flags != PIO_CPU_MMIO)) {
+			result = of_read_number(addr + 1, na - 1);
+			pr_debug("indirectIO matched(%s) 0x%llx\n",
+					of_node_full_name(dev), result);
+			*host = of_node_get(dev);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
@@ -631,13 +652,32 @@ static u64 __of_translate_address(struct device_node *dev,
 
 u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret =  __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_address);
 
 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "dma-ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret = __of_translate_address(dev, in_addr, "dma-ranges", &host);
+
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_dma_address);
 
@@ -679,29 +719,47 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr)
+{
+	u64 taddr;
+	unsigned long port;
+	struct device_node *host;
+
+	taddr = __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		/* host specific port access */
+		port = logic_pio_trans_hwaddr(&host->fwnode, taddr);
+		of_node_put(host);
+	} else {
+		/* memory mapped I/O range */
+		port = pci_address_to_pio(taddr);
+	}
+
+	if (port == (unsigned long)-1)
+		return OF_BAD_ADDR;
+
+	return port;
+}
+
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
 {
 	u64 taddr;
 
-	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+	if (flags & IORESOURCE_MEM)
+		taddr = of_translate_address(dev, addrp);
+	else if (flags & IORESOURCE_IO)
+		taddr = of_translate_ioport(dev, addrp);
+	else
 		return -EINVAL;
-	taddr = of_translate_address(dev, addrp);
+
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
-		unsigned long port;
-		port = pci_address_to_pio(taddr);
-		if (port == (unsigned long)-1)
-			return -EINVAL;
-		r->start = port;
-		r->end = port + size - 1;
-	} else {
-		r->start = taddr;
-		r->end = taddr + size - 1;
-	}
+
+	r->start = taddr;
+	r->end = taddr + size - 1;
 	r->flags = flags;
 	r->name = name ? name : dev->full_name;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, zhichang.yuan,
	linux-pci, olof, brian.starkey

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

There are some special ISA/LPC devices that work on a specific I/O range
where it is not correct to specify a 'ranges' property in DTS parent node
as cpu addresses translated from DTS node are only for memory space on some
architectures, such as Arm64. Without the parent 'ranges' property, current
of_translate_address() return an error.
Here we add special handlings for this case.
During the OF address translation, some checkings will be perfromed to
identify whether the device node is registered as indirect-IO. If yes, the
I/O translation will be done in a different way from that one of PCI MMIO.
In this way, the I/O 'reg' property of the special ISA/LPC devices will be
parsed correctly.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>    #earlier draft
Acked-by: Rob Herring <robh@kernel.org>
---
 drivers/of/address.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 74 insertions(+), 16 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 34a55e8..c51de70 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -552,9 +552,14 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that translation is impossible (that is we are not dealing with a value
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
+ *
+ * Whenever the translation fails, the *host pointer will be set to the
+ * device that had registered logical PIO mapping, and the return code is
+ * relative to that node.
  */
 static u64 __of_translate_address(struct device_node *dev,
-				  const __be32 *in_addr, const char *rprop)
+				  const __be32 *in_addr, const char *rprop,
+				  struct device_node **host)
 {
 	struct device_node *parent = NULL;
 	struct of_bus *bus, *pbus;
@@ -567,6 +572,7 @@ static u64 __of_translate_address(struct device_node *dev,
 	/* Increase refcount at current level */
 	of_node_get(dev);
 
+	*host = NULL;
 	/* Get parent & match bus type */
 	parent = of_get_parent(dev);
 	if (parent == NULL)
@@ -587,6 +593,8 @@ static u64 __of_translate_address(struct device_node *dev,
 
 	/* Translate */
 	for (;;) {
+		struct logic_pio_hwaddr *iorange;
+
 		/* Switch to parent bus */
 		of_node_put(dev);
 		dev = parent;
@@ -599,6 +607,19 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		iorange = find_io_range_by_fwnode(&dev->fwnode);
+		if (iorange && (iorange->flags != PIO_CPU_MMIO)) {
+			result = of_read_number(addr + 1, na - 1);
+			pr_debug("indirectIO matched(%s) 0x%llx\n",
+					of_node_full_name(dev), result);
+			*host = of_node_get(dev);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
@@ -631,13 +652,32 @@ static u64 __of_translate_address(struct device_node *dev,
 
 u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret =  __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_address);
 
 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "dma-ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret = __of_translate_address(dev, in_addr, "dma-ranges", &host);
+
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_dma_address);
 
@@ -679,29 +719,47 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr)
+{
+	u64 taddr;
+	unsigned long port;
+	struct device_node *host;
+
+	taddr = __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		/* host specific port access */
+		port = logic_pio_trans_hwaddr(&host->fwnode, taddr);
+		of_node_put(host);
+	} else {
+		/* memory mapped I/O range */
+		port = pci_address_to_pio(taddr);
+	}
+
+	if (port == (unsigned long)-1)
+		return OF_BAD_ADDR;
+
+	return port;
+}
+
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
 {
 	u64 taddr;
 
-	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+	if (flags & IORESOURCE_MEM)
+		taddr = of_translate_address(dev, addrp);
+	else if (flags & IORESOURCE_IO)
+		taddr = of_translate_ioport(dev, addrp);
+	else
 		return -EINVAL;
-	taddr = of_translate_address(dev, addrp);
+
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
-		unsigned long port;
-		port = pci_address_to_pio(taddr);
-		if (port == (unsigned long)-1)
-			return -EINVAL;
-		r->start = port;
-		r->end = port + size - 1;
-	} else {
-		r->start = taddr;
-		r->end = taddr + size - 1;
-	}
+
+	r->start = taddr;
+	r->end = taddr + size - 1;
 	r->flags = flags;
 	r->name = name ? name : dev->full_name;
 
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

There are some special ISA/LPC devices that work on a specific I/O range
where it is not correct to specify a 'ranges' property in DTS parent node
as cpu addresses translated from DTS node are only for memory space on some
architectures, such as Arm64. Without the parent 'ranges' property, current
of_translate_address() return an error.
Here we add special handlings for this case.
During the OF address translation, some checkings will be perfromed to
identify whether the device node is registered as indirect-IO. If yes, the
I/O translation will be done in a different way from that one of PCI MMIO.
In this way, the I/O 'reg' property of the special ISA/LPC devices will be
parsed correctly.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>    #earlier draft
Acked-by: Rob Herring <robh@kernel.org>
---
 drivers/of/address.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 74 insertions(+), 16 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 34a55e8..c51de70 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -552,9 +552,14 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that translation is impossible (that is we are not dealing with a value
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
+ *
+ * Whenever the translation fails, the *host pointer will be set to the
+ * device that had registered logical PIO mapping, and the return code is
+ * relative to that node.
  */
 static u64 __of_translate_address(struct device_node *dev,
-				  const __be32 *in_addr, const char *rprop)
+				  const __be32 *in_addr, const char *rprop,
+				  struct device_node **host)
 {
 	struct device_node *parent = NULL;
 	struct of_bus *bus, *pbus;
@@ -567,6 +572,7 @@ static u64 __of_translate_address(struct device_node *dev,
 	/* Increase refcount at current level */
 	of_node_get(dev);
 
+	*host = NULL;
 	/* Get parent & match bus type */
 	parent = of_get_parent(dev);
 	if (parent == NULL)
@@ -587,6 +593,8 @@ static u64 __of_translate_address(struct device_node *dev,
 
 	/* Translate */
 	for (;;) {
+		struct logic_pio_hwaddr *iorange;
+
 		/* Switch to parent bus */
 		of_node_put(dev);
 		dev = parent;
@@ -599,6 +607,19 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		iorange = find_io_range_by_fwnode(&dev->fwnode);
+		if (iorange && (iorange->flags != PIO_CPU_MMIO)) {
+			result = of_read_number(addr + 1, na - 1);
+			pr_debug("indirectIO matched(%s) 0x%llx\n",
+					of_node_full_name(dev), result);
+			*host = of_node_get(dev);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
@@ -631,13 +652,32 @@ static u64 __of_translate_address(struct device_node *dev,
 
 u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret =  __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_address);
 
 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "dma-ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret = __of_translate_address(dev, in_addr, "dma-ranges", &host);
+
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_dma_address);
 
@@ -679,29 +719,47 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr)
+{
+	u64 taddr;
+	unsigned long port;
+	struct device_node *host;
+
+	taddr = __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		/* host specific port access */
+		port = logic_pio_trans_hwaddr(&host->fwnode, taddr);
+		of_node_put(host);
+	} else {
+		/* memory mapped I/O range */
+		port = pci_address_to_pio(taddr);
+	}
+
+	if (port == (unsigned long)-1)
+		return OF_BAD_ADDR;
+
+	return port;
+}
+
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
 {
 	u64 taddr;
 
-	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+	if (flags & IORESOURCE_MEM)
+		taddr = of_translate_address(dev, addrp);
+	else if (flags & IORESOURCE_IO)
+		taddr = of_translate_ioport(dev, addrp);
+	else
 		return -EINVAL;
-	taddr = of_translate_address(dev, addrp);
+
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
-		unsigned long port;
-		port = pci_address_to_pio(taddr);
-		if (port == (unsigned long)-1)
-			return -EINVAL;
-		r->start = port;
-		r->end = port + size - 1;
-	} else {
-		r->start = taddr;
-		r->end = taddr + size - 1;
-	}
+
+	r->start = taddr;
+	r->end = taddr + size - 1;
 	r->flags = flags;
 	r->name = name ? name : dev->full_name;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 4/7] LPC: Support the device-tree LPC host on Hip06/Hip07
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

The low-pin-count(LPC) interface of Hip06/Hip07 accesses the peripherals
in I/O port addresses. This patch implements the LPC host controller
driver which perform the I/O operations on the underlying hardware.
We don't want to touch those existing peripherals' driver, such as
ipmi-bt. So this driver applies the indirect-IO introduced in the previous
patch after registering an indirect-IO node to the indirect-IO devices
list which will be searched in the I/O accessors to retrieve the
host-local I/O port.

Signed-off-by: Zou Rongrong <zourongrong@huawei.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Rob Herring <robh@kernel.org> #dts part
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 544 +++++++++++++++++++++
 4 files changed, 587 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..213181f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,33 @@
+Hisilicon Hip06 low-pin-count device
+  Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
+  provides I/O access to some legacy ISA devices.
+  Hip06 is based on arm64 architecture where there is no I/O space. So, the
+  I/O ports here are not cpu addresses, and there is no 'ranges' property in
+  LPC device node.
+
+Required properties:
+- compatible:  value should be as follows:
+	(a) "hisilicon,hip06-lpc"
+	(b) "hisilicon,hip07-lpc"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the LPC register set is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicon,hip06-lpc";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 0a52da4..4b548dd 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,15 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Support for ISA I/O space on Hisilicon Hip0X"
+	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index cc6364b..28e3862 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..4f3bf76
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#define LPC_MIN_BUS_RANGE	0x0
+
+/*
+ * The default maximal IO size for Hip06/Hip07 LPC bus.
+ * Defining the I/O range size as 0x400 here should be sufficient for
+ * all peripherals under the bus.
+ */
+#define LPC_BUS_IO_SIZE		0x400
+
+/*
+ * Setting this bit means each IO operation will target to a
+ * different port address:
+ * 0 means repeatedly IO operations will stick on the same port,
+ * such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct logic_pio_hwaddr *io_host;
+};
+
+/* The maximum continuous cycles per burst */
+#define LPC_MAX_BURST	16
+/* The IO cycle counts supported is four per operation at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_BURST
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#if LPC_MAX_BURST % LPC_MAX_DULEN
+#error "LPC.. LPC_MAX_BURST must be multiple of LPC_MAX_DULEN!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields */
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal nanosecond interval for each query on LPC cycle status.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * It is specific for stream I/O, such as ins.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specific for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/*
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		       from target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_in(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		  unsigned long ptaddr, unsigned char *buf,
+		  unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (cnt_per_trans--; cnt_per_trans--; buf++)
+				*buf = readb_relaxed(lpcdev->membase +
+					LPC_REG_RDATA);
+			*buf = readb(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/*
+ * hisilpc_target_out - trigger a series of lpc cycles to write required
+ *			data to target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_out(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		   unsigned long ptaddr, const unsigned char *buf,
+		   unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writeb_relaxed(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+static inline unsigned long
+hisi_lpc_pio_to_addr(struct hisilpc_dev *lpcdev, unsigned long pio)
+{
+	return pio - lpcdev->io_host->io_start +
+		lpcdev->io_host->hw_start;
+}
+
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral
+ *		     through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u32 hisilpc_comm_in(void *devobj, unsigned long pio, size_t dlen)
+{
+	int ret = 0;
+	u32 rd_data = 0;
+	unsigned long ptaddr;
+	unsigned char *newbuf;
+	struct lpc_cycle_para iopara;
+	struct hisilpc_dev *lpcdev = devobj;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - output the data whose maximum length is four bytes
+		      to the I/O peripheral through the LPC host.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputted from caller, maximum is four bytes.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port.
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long pio,
+			     u32 outval, size_t dlen)
+{
+	unsigned long ptaddr;
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/*
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u32
+hisilpc_comm_ins(void *devobj, unsigned long pio, void *inbuf,
+		 size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !inbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return -EINVAL;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		int ret;
+
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr,
+					newbuf, loopcnt);
+		if (ret)
+			return ret;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return 0;
+}
+
+/*
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void
+hisilpc_comm_outs(void *devobj, unsigned long pio, const void *outbuf,
+		  size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !outbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		if (hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt))
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+static struct hostio_ops hisi_lpc_ops = {
+	.pfin = hisilpc_comm_in,
+	.pfout = hisilpc_comm_out,
+	.pfins = hisilpc_comm_ins,
+	.pfouts = hisilpc_comm_outs,
+};
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		   will finish all the initialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct hisilpc_dev *lpcdev;
+	int ret = 0;
+
+	dev_info(dev, "probing...\n");
+
+	lpcdev = devm_kzalloc(dev, sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "no MEM resource\n");
+		return -ENODEV;
+	}
+
+	lpcdev->membase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(dev, "remap failed\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	/* register the LPC host PIO resources */
+	if (!has_acpi_companion(dev)) {
+		struct logic_pio_hwaddr *range;
+
+		range = kzalloc(sizeof(*range), GFP_KERNEL);
+		if (!range)
+			return -ENOMEM;
+		range->fwnode = dev->fwnode;
+		range->flags = PIO_INDIRECT;
+		range->size = LPC_BUS_IO_SIZE;
+		range->hw_start = LPC_MIN_BUS_RANGE;
+
+		ret = logic_pio_register_range(range);
+		if (ret) {
+			kfree(range);
+			dev_err(dev, "OF: register IO range FAIL!\n");
+			return -ret;
+		}
+		lpcdev->io_host = range;
+	}
+	if (!lpcdev->io_host) {
+		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		return -EFAULT;
+	}
+
+	lpcdev->io_host->devpara = lpcdev;
+	lpcdev->io_host->ops = &hisi_lpc_ops;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	/*
+	 * It is time to start the children scannings....
+	 * For ACPI children, the corresponding devices had been created
+	 * during the ACPI enumeration.
+	 * The OF scanning must be performed after initialization of 'lpcdev'
+	 * to avoid some children which complete the scanning trigger the
+	 * MMIO accesses which will probably cause panic.
+	 */
+	if (!has_acpi_companion(dev))
+		ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+
+	if (!ret) {
+		dev_info(dev, "hslpc end probing. range[%pa - sz:%pa]\n",
+			&lpcdev->io_host->io_start,
+			&lpcdev->io_host->size);
+	} else {
+		/*
+		 * When LPC probing is not completely successful, set 'devpara'
+		 * as NULL. This will make all the LPC I/O return failure
+		 * directly without any hardware operations. It will prevent
+		 * some peripherals which had not finished the initialization to
+		 * manipulate I/O for safety.
+		 */
+		lpcdev->io_host->devpara = NULL;
+		dev_info(dev, "OF: scan hisilpc children got failed(%d)\n",
+			ret);
+	}
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{ .compatible = "hisilicon,hip06-lpc", },
+	{ .compatible = "hisilicon,hip07-lpc", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+builtin_platform_driver(hisilpc_driver);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 4/7] LPC: Support the device-tree LPC host on Hip06/Hip07
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

The low-pin-count(LPC) interface of Hip06/Hip07 accesses the peripherals
in I/O port addresses. This patch implements the LPC host controller
driver which perform the I/O operations on the underlying hardware.
We don't want to touch those existing peripherals' driver, such as
ipmi-bt. So this driver applies the indirect-IO introduced in the previous
patch after registering an indirect-IO node to the indirect-IO devices
list which will be searched in the I/O accessors to retrieve the
host-local I/O port.

Signed-off-by: Zou Rongrong <zourongrong@huawei.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Rob Herring <robh@kernel.org> #dts part
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 544 +++++++++++++++++++++
 4 files changed, 587 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..213181f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,33 @@
+Hisilicon Hip06 low-pin-count device
+  Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
+  provides I/O access to some legacy ISA devices.
+  Hip06 is based on arm64 architecture where there is no I/O space. So, the
+  I/O ports here are not cpu addresses, and there is no 'ranges' property in
+  LPC device node.
+
+Required properties:
+- compatible:  value should be as follows:
+	(a) "hisilicon,hip06-lpc"
+	(b) "hisilicon,hip07-lpc"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the LPC register set is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicon,hip06-lpc";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 0a52da4..4b548dd 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,15 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Support for ISA I/O space on Hisilicon Hip0X"
+	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index cc6364b..28e3862 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..4f3bf76
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#define LPC_MIN_BUS_RANGE	0x0
+
+/*
+ * The default maximal IO size for Hip06/Hip07 LPC bus.
+ * Defining the I/O range size as 0x400 here should be sufficient for
+ * all peripherals under the bus.
+ */
+#define LPC_BUS_IO_SIZE		0x400
+
+/*
+ * Setting this bit means each IO operation will target to a
+ * different port address:
+ * 0 means repeatedly IO operations will stick on the same port,
+ * such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct logic_pio_hwaddr *io_host;
+};
+
+/* The maximum continuous cycles per burst */
+#define LPC_MAX_BURST	16
+/* The IO cycle counts supported is four per operation at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_BURST
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#if LPC_MAX_BURST % LPC_MAX_DULEN
+#error "LPC.. LPC_MAX_BURST must be multiple of LPC_MAX_DULEN!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields */
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal nanosecond interval for each query on LPC cycle status.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * It is specific for stream I/O, such as ins.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specific for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/*
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		       from target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_in(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		  unsigned long ptaddr, unsigned char *buf,
+		  unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (cnt_per_trans--; cnt_per_trans--; buf++)
+				*buf = readb_relaxed(lpcdev->membase +
+					LPC_REG_RDATA);
+			*buf = readb(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/*
+ * hisilpc_target_out - trigger a series of lpc cycles to write required
+ *			data to target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_out(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		   unsigned long ptaddr, const unsigned char *buf,
+		   unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writeb_relaxed(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+static inline unsigned long
+hisi_lpc_pio_to_addr(struct hisilpc_dev *lpcdev, unsigned long pio)
+{
+	return pio - lpcdev->io_host->io_start +
+		lpcdev->io_host->hw_start;
+}
+
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral
+ *		     through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u32 hisilpc_comm_in(void *devobj, unsigned long pio, size_t dlen)
+{
+	int ret = 0;
+	u32 rd_data = 0;
+	unsigned long ptaddr;
+	unsigned char *newbuf;
+	struct lpc_cycle_para iopara;
+	struct hisilpc_dev *lpcdev = devobj;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - output the data whose maximum length is four bytes
+		      to the I/O peripheral through the LPC host.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputted from caller, maximum is four bytes.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port.
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long pio,
+			     u32 outval, size_t dlen)
+{
+	unsigned long ptaddr;
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/*
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u32
+hisilpc_comm_ins(void *devobj, unsigned long pio, void *inbuf,
+		 size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !inbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return -EINVAL;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		int ret;
+
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr,
+					newbuf, loopcnt);
+		if (ret)
+			return ret;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return 0;
+}
+
+/*
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void
+hisilpc_comm_outs(void *devobj, unsigned long pio, const void *outbuf,
+		  size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !outbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		if (hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt))
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+static struct hostio_ops hisi_lpc_ops = {
+	.pfin = hisilpc_comm_in,
+	.pfout = hisilpc_comm_out,
+	.pfins = hisilpc_comm_ins,
+	.pfouts = hisilpc_comm_outs,
+};
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		   will finish all the initialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct hisilpc_dev *lpcdev;
+	int ret = 0;
+
+	dev_info(dev, "probing...\n");
+
+	lpcdev = devm_kzalloc(dev, sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "no MEM resource\n");
+		return -ENODEV;
+	}
+
+	lpcdev->membase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(dev, "remap failed\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	/* register the LPC host PIO resources */
+	if (!has_acpi_companion(dev)) {
+		struct logic_pio_hwaddr *range;
+
+		range = kzalloc(sizeof(*range), GFP_KERNEL);
+		if (!range)
+			return -ENOMEM;
+		range->fwnode = dev->fwnode;
+		range->flags = PIO_INDIRECT;
+		range->size = LPC_BUS_IO_SIZE;
+		range->hw_start = LPC_MIN_BUS_RANGE;
+
+		ret = logic_pio_register_range(range);
+		if (ret) {
+			kfree(range);
+			dev_err(dev, "OF: register IO range FAIL!\n");
+			return -ret;
+		}
+		lpcdev->io_host = range;
+	}
+	if (!lpcdev->io_host) {
+		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		return -EFAULT;
+	}
+
+	lpcdev->io_host->devpara = lpcdev;
+	lpcdev->io_host->ops = &hisi_lpc_ops;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	/*
+	 * It is time to start the children scannings....
+	 * For ACPI children, the corresponding devices had been created
+	 * during the ACPI enumeration.
+	 * The OF scanning must be performed after initialization of 'lpcdev'
+	 * to avoid some children which complete the scanning trigger the
+	 * MMIO accesses which will probably cause panic.
+	 */
+	if (!has_acpi_companion(dev))
+		ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+
+	if (!ret) {
+		dev_info(dev, "hslpc end probing. range[%pa - sz:%pa]\n",
+			&lpcdev->io_host->io_start,
+			&lpcdev->io_host->size);
+	} else {
+		/*
+		 * When LPC probing is not completely successful, set 'devpara'
+		 * as NULL. This will make all the LPC I/O return failure
+		 * directly without any hardware operations. It will prevent
+		 * some peripherals which had not finished the initialization to
+		 * manipulate I/O for safety.
+		 */
+		lpcdev->io_host->devpara = NULL;
+		dev_info(dev, "OF: scan hisilpc children got failed(%d)\n",
+			ret);
+	}
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{ .compatible = "hisilicon,hip06-lpc", },
+	{ .compatible = "hisilicon,hip07-lpc", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+builtin_platform_driver(hisilpc_driver);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 4/7] LPC: Support the device-tree LPC host on Hip06/Hip07
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, zhichang.yuan,
	linux-pci, olof, brian.starkey

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

The low-pin-count(LPC) interface of Hip06/Hip07 accesses the peripherals
in I/O port addresses. This patch implements the LPC host controller
driver which perform the I/O operations on the underlying hardware.
We don't want to touch those existing peripherals' driver, such as
ipmi-bt. So this driver applies the indirect-IO introduced in the previous
patch after registering an indirect-IO node to the indirect-IO devices
list which will be searched in the I/O accessors to retrieve the
host-local I/O port.

Signed-off-by: Zou Rongrong <zourongrong@huawei.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Rob Herring <robh@kernel.org> #dts part
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 544 +++++++++++++++++++++
 4 files changed, 587 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..213181f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,33 @@
+Hisilicon Hip06 low-pin-count device
+  Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
+  provides I/O access to some legacy ISA devices.
+  Hip06 is based on arm64 architecture where there is no I/O space. So, the
+  I/O ports here are not cpu addresses, and there is no 'ranges' property in
+  LPC device node.
+
+Required properties:
+- compatible:  value should be as follows:
+	(a) "hisilicon,hip06-lpc"
+	(b) "hisilicon,hip07-lpc"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the LPC register set is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicon,hip06-lpc";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 0a52da4..4b548dd 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,15 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Support for ISA I/O space on Hisilicon Hip0X"
+	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index cc6364b..28e3862 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..4f3bf76
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#define LPC_MIN_BUS_RANGE	0x0
+
+/*
+ * The default maximal IO size for Hip06/Hip07 LPC bus.
+ * Defining the I/O range size as 0x400 here should be sufficient for
+ * all peripherals under the bus.
+ */
+#define LPC_BUS_IO_SIZE		0x400
+
+/*
+ * Setting this bit means each IO operation will target to a
+ * different port address:
+ * 0 means repeatedly IO operations will stick on the same port,
+ * such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct logic_pio_hwaddr *io_host;
+};
+
+/* The maximum continuous cycles per burst */
+#define LPC_MAX_BURST	16
+/* The IO cycle counts supported is four per operation at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_BURST
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#if LPC_MAX_BURST % LPC_MAX_DULEN
+#error "LPC.. LPC_MAX_BURST must be multiple of LPC_MAX_DULEN!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields */
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal nanosecond interval for each query on LPC cycle status.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * It is specific for stream I/O, such as ins.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specific for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/*
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		       from target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_in(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		  unsigned long ptaddr, unsigned char *buf,
+		  unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (cnt_per_trans--; cnt_per_trans--; buf++)
+				*buf = readb_relaxed(lpcdev->membase +
+					LPC_REG_RDATA);
+			*buf = readb(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/*
+ * hisilpc_target_out - trigger a series of lpc cycles to write required
+ *			data to target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_out(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		   unsigned long ptaddr, const unsigned char *buf,
+		   unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writeb_relaxed(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+static inline unsigned long
+hisi_lpc_pio_to_addr(struct hisilpc_dev *lpcdev, unsigned long pio)
+{
+	return pio - lpcdev->io_host->io_start +
+		lpcdev->io_host->hw_start;
+}
+
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral
+ *		     through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u32 hisilpc_comm_in(void *devobj, unsigned long pio, size_t dlen)
+{
+	int ret = 0;
+	u32 rd_data = 0;
+	unsigned long ptaddr;
+	unsigned char *newbuf;
+	struct lpc_cycle_para iopara;
+	struct hisilpc_dev *lpcdev = devobj;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - output the data whose maximum length is four bytes
+		      to the I/O peripheral through the LPC host.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputted from caller, maximum is four bytes.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port.
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long pio,
+			     u32 outval, size_t dlen)
+{
+	unsigned long ptaddr;
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/*
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u32
+hisilpc_comm_ins(void *devobj, unsigned long pio, void *inbuf,
+		 size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !inbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return -EINVAL;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		int ret;
+
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr,
+					newbuf, loopcnt);
+		if (ret)
+			return ret;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return 0;
+}
+
+/*
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void
+hisilpc_comm_outs(void *devobj, unsigned long pio, const void *outbuf,
+		  size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !outbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		if (hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt))
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+static struct hostio_ops hisi_lpc_ops = {
+	.pfin = hisilpc_comm_in,
+	.pfout = hisilpc_comm_out,
+	.pfins = hisilpc_comm_ins,
+	.pfouts = hisilpc_comm_outs,
+};
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		   will finish all the initialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct hisilpc_dev *lpcdev;
+	int ret = 0;
+
+	dev_info(dev, "probing...\n");
+
+	lpcdev = devm_kzalloc(dev, sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "no MEM resource\n");
+		return -ENODEV;
+	}
+
+	lpcdev->membase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(dev, "remap failed\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	/* register the LPC host PIO resources */
+	if (!has_acpi_companion(dev)) {
+		struct logic_pio_hwaddr *range;
+
+		range = kzalloc(sizeof(*range), GFP_KERNEL);
+		if (!range)
+			return -ENOMEM;
+		range->fwnode = dev->fwnode;
+		range->flags = PIO_INDIRECT;
+		range->size = LPC_BUS_IO_SIZE;
+		range->hw_start = LPC_MIN_BUS_RANGE;
+
+		ret = logic_pio_register_range(range);
+		if (ret) {
+			kfree(range);
+			dev_err(dev, "OF: register IO range FAIL!\n");
+			return -ret;
+		}
+		lpcdev->io_host = range;
+	}
+	if (!lpcdev->io_host) {
+		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		return -EFAULT;
+	}
+
+	lpcdev->io_host->devpara = lpcdev;
+	lpcdev->io_host->ops = &hisi_lpc_ops;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	/*
+	 * It is time to start the children scannings....
+	 * For ACPI children, the corresponding devices had been created
+	 * during the ACPI enumeration.
+	 * The OF scanning must be performed after initialization of 'lpcdev'
+	 * to avoid some children which complete the scanning trigger the
+	 * MMIO accesses which will probably cause panic.
+	 */
+	if (!has_acpi_companion(dev))
+		ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+
+	if (!ret) {
+		dev_info(dev, "hslpc end probing. range[%pa - sz:%pa]\n",
+			&lpcdev->io_host->io_start,
+			&lpcdev->io_host->size);
+	} else {
+		/*
+		 * When LPC probing is not completely successful, set 'devpara'
+		 * as NULL. This will make all the LPC I/O return failure
+		 * directly without any hardware operations. It will prevent
+		 * some peripherals which had not finished the initialization to
+		 * manipulate I/O for safety.
+		 */
+		lpcdev->io_host->devpara = NULL;
+		dev_info(dev, "OF: scan hisilpc children got failed(%d)\n",
+			ret);
+	}
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{ .compatible = "hisilicon,hip06-lpc", },
+	{ .compatible = "hisilicon,hip07-lpc", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+builtin_platform_driver(hisilpc_driver);
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 4/7] LPC: Support the device-tree LPC host on Hip06/Hip07
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

The low-pin-count(LPC) interface of Hip06/Hip07 accesses the peripherals
in I/O port addresses. This patch implements the LPC host controller
driver which perform the I/O operations on the underlying hardware.
We don't want to touch those existing peripherals' driver, such as
ipmi-bt. So this driver applies the indirect-IO introduced in the previous
patch after registering an indirect-IO node to the indirect-IO devices
list which will be searched in the I/O accessors to retrieve the
host-local I/O port.

Signed-off-by: Zou Rongrong <zourongrong@huawei.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Rob Herring <robh@kernel.org> #dts part
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 544 +++++++++++++++++++++
 4 files changed, 587 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..213181f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,33 @@
+Hisilicon Hip06 low-pin-count device
+  Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
+  provides I/O access to some legacy ISA devices.
+  Hip06 is based on arm64 architecture where there is no I/O space. So, the
+  I/O ports here are not cpu addresses, and there is no 'ranges' property in
+  LPC device node.
+
+Required properties:
+- compatible:  value should be as follows:
+	(a) "hisilicon,hip06-lpc"
+	(b) "hisilicon,hip07-lpc"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the LPC register set is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa at a01b0000 {
+	compatible = "hisilicon,hip06-lpc";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt at e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 0a52da4..4b548dd 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,15 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Support for ISA I/O space on Hisilicon Hip0X"
+	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index cc6364b..28e3862 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..4f3bf76
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/logic_pio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#define LPC_MIN_BUS_RANGE	0x0
+
+/*
+ * The default maximal IO size for Hip06/Hip07 LPC bus.
+ * Defining the I/O range size as 0x400 here should be sufficient for
+ * all peripherals under the bus.
+ */
+#define LPC_BUS_IO_SIZE		0x400
+
+/*
+ * Setting this bit means each IO operation will target to a
+ * different port address:
+ * 0 means repeatedly IO operations will stick on the same port,
+ * such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct logic_pio_hwaddr *io_host;
+};
+
+/* The maximum continuous cycles per burst */
+#define LPC_MAX_BURST	16
+/* The IO cycle counts supported is four per operation at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_BURST
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#if LPC_MAX_BURST % LPC_MAX_DULEN
+#error "LPC.. LPC_MAX_BURST must be multiple of LPC_MAX_DULEN!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields */
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal nanosecond interval for each query on LPC cycle status.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * It is specific for stream I/O, such as ins.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specific for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/*
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		       from target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_in(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		  unsigned long ptaddr, unsigned char *buf,
+		  unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (cnt_per_trans--; cnt_per_trans--; buf++)
+				*buf = readb_relaxed(lpcdev->membase +
+					LPC_REG_RDATA);
+			*buf = readb(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/*
+ * hisilpc_target_out - trigger a series of lpc cycles to write required
+ *			data to target peripheral.
+ * @pdev: pointer to hisi lpc device
+ * @para: some parameters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * Only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int
+hisilpc_target_out(struct hisilpc_dev *lpcdev, struct lpc_cycle_para *para,
+		   unsigned long ptaddr, const unsigned char *buf,
+		   unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = LPC_PEROP_WAITCNT;
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel_relaxed(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
+		writel_relaxed(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writeb_relaxed(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+static inline unsigned long
+hisi_lpc_pio_to_addr(struct hisilpc_dev *lpcdev, unsigned long pio)
+{
+	return pio - lpcdev->io_host->io_start +
+		lpcdev->io_host->hw_start;
+}
+
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral
+ *		     through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u32 hisilpc_comm_in(void *devobj, unsigned long pio, size_t dlen)
+{
+	int ret = 0;
+	u32 rd_data = 0;
+	unsigned long ptaddr;
+	unsigned char *newbuf;
+	struct lpc_cycle_para iopara;
+	struct hisilpc_dev *lpcdev = devobj;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - output the data whose maximum length is four bytes
+		      to the I/O peripheral through the LPC host.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputted from caller, maximum is four bytes.
+ * @pio: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port.
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long pio,
+			     u32 outval, size_t dlen)
+{
+	unsigned long ptaddr;
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/*
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u32
+hisilpc_comm_ins(void *devobj, unsigned long pio, void *inbuf,
+		 size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !inbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return -EINVAL;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		int ret;
+
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr,
+					newbuf, loopcnt);
+		if (ret)
+			return ret;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return 0;
+}
+
+/*
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O
+ *		peripheral through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @pio: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void
+hisilpc_comm_outs(void *devobj, unsigned long pio, const void *outbuf,
+		  size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev = devobj;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned long ptaddr;
+
+	if (!lpcdev || !outbuf || !count || !dlen || dlen > LPC_MAX_DULEN ||
+			count % dlen)
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ptaddr = hisi_lpc_pio_to_addr(lpcdev, pio);
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= LPC_MAX_BURST) ? LPC_MAX_BURST : cntleft;
+		if (hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt))
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+static struct hostio_ops hisi_lpc_ops = {
+	.pfin = hisilpc_comm_in,
+	.pfout = hisilpc_comm_out,
+	.pfins = hisilpc_comm_ins,
+	.pfouts = hisilpc_comm_outs,
+};
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		   will finish all the initialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct hisilpc_dev *lpcdev;
+	int ret = 0;
+
+	dev_info(dev, "probing...\n");
+
+	lpcdev = devm_kzalloc(dev, sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "no MEM resource\n");
+		return -ENODEV;
+	}
+
+	lpcdev->membase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(dev, "remap failed\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	/* register the LPC host PIO resources */
+	if (!has_acpi_companion(dev)) {
+		struct logic_pio_hwaddr *range;
+
+		range = kzalloc(sizeof(*range), GFP_KERNEL);
+		if (!range)
+			return -ENOMEM;
+		range->fwnode = dev->fwnode;
+		range->flags = PIO_INDIRECT;
+		range->size = LPC_BUS_IO_SIZE;
+		range->hw_start = LPC_MIN_BUS_RANGE;
+
+		ret = logic_pio_register_range(range);
+		if (ret) {
+			kfree(range);
+			dev_err(dev, "OF: register IO range FAIL!\n");
+			return -ret;
+		}
+		lpcdev->io_host = range;
+	}
+	if (!lpcdev->io_host) {
+		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		return -EFAULT;
+	}
+
+	lpcdev->io_host->devpara = lpcdev;
+	lpcdev->io_host->ops = &hisi_lpc_ops;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	/*
+	 * It is time to start the children scannings....
+	 * For ACPI children, the corresponding devices had been created
+	 * during the ACPI enumeration.
+	 * The OF scanning must be performed after initialization of 'lpcdev'
+	 * to avoid some children which complete the scanning trigger the
+	 * MMIO accesses which will probably cause panic.
+	 */
+	if (!has_acpi_companion(dev))
+		ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+
+	if (!ret) {
+		dev_info(dev, "hslpc end probing. range[%pa - sz:%pa]\n",
+			&lpcdev->io_host->io_start,
+			&lpcdev->io_host->size);
+	} else {
+		/*
+		 * When LPC probing is not completely successful, set 'devpara'
+		 * as NULL. This will make all the LPC I/O return failure
+		 * directly without any hardware operations. It will prevent
+		 * some peripherals which had not finished the initialization to
+		 * manipulate I/O for safety.
+		 */
+		lpcdev->io_host->devpara = NULL;
+		dev_info(dev, "OF: scan hisilpc children got failed(%d)\n",
+			ret);
+	}
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{ .compatible = "hisilicon,hip06-lpc", },
+	{ .compatible = "hisilicon,hip07-lpc", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+builtin_platform_driver(hisilpc_driver);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

From: Gabriele <gabriele.paoloni@huawei.com>

On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
I/O with some special host-local I/O ports known on x86. As their I/O
space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
meant to support a new class of I/O host controllers where the local IO
ports of the children devices are translated into the Indirect I/O address
space.
Through the handler attach callback, all the I/O translations are done
before starting the enumeration on children devices and the translated
addresses are replaced in the children resources.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 drivers/acpi/arm64/Makefile            |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
 drivers/acpi/internal.h                |   5 +
 drivers/acpi/scan.c                    |   1 +
 include/acpi/acpi_indirect_pio.h       |  24 +++
 5 files changed, 332 insertions(+)
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 include/acpi/acpi_indirect_pio.h

diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 1017def..3944775 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ACPI_IORT) 	+= iort.o
 obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
+obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
new file mode 100644
index 0000000..7813f73
--- /dev/null
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -0,0 +1,301 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/logic_pio.h>
+
+#include <acpi/acpi_indirect_pio.h>
+
+ACPI_MODULE_NAME("indirect PIO");
+
+#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
+
+static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
+					   void *data)
+{
+	int *res_cnt = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
+		(*res_cnt)++;
+
+	return AE_OK;
+}
+
+static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
+		void *data)
+{
+	struct acpi_resource **resource = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
+		memcpy((*resource), res, sizeof(struct acpi_resource));
+		(*resource)->length = sizeof(struct acpi_resource);
+		(*resource)->type = res->type;
+		(*resource)++;
+	}
+
+	return AE_OK;
+}
+
+static acpi_status
+acpi_build_logicpiores_template(struct acpi_device *adev,
+			struct acpi_buffer *buffer)
+{
+	acpi_handle handle = adev->handle;
+	struct acpi_resource *resource;
+	acpi_status status;
+	int res_cnt = 0;
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_count_logic_iores, &res_cnt);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	if (!res_cnt) {
+		dev_err(&adev->dev, "no logic IO resources\n");
+		return -ENODEV;
+	}
+
+	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
+	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
+	if (!buffer->pointer)
+		return -ENOMEM;
+
+	resource = (struct acpi_resource *)buffer->pointer;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_read_one_logicpiores, &resource);
+	if (ACPI_FAILURE(status)) {
+		kfree(buffer->pointer);
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
+	resource->length = sizeof(struct acpi_resource);
+
+	return 0;
+}
+
+static int acpi_translate_logicpiores(struct acpi_device *adev,
+		struct acpi_device *host, struct acpi_buffer *buffer)
+{
+	struct acpi_resource *resource = buffer->pointer;
+	unsigned long sys_port;
+	struct device *dev = &adev->dev;
+	union acpi_resource_data *trans_data = &resource->data;
+	resource_size_t bus_addr;
+	resource_size_t max_pio;
+	resource_size_t length;
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		if (trans_data->address16.min_address_fixed !=
+				trans_data->address16.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address16.address.minimum;
+		length = trans_data->address16.address.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		if (trans_data->address32.min_address_fixed !=
+				trans_data->address32.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address32.address.minimum;
+		length = trans_data->address32.address.address_length;
+		max_pio = U32_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		if (trans_data->address64.min_address_fixed !=
+				trans_data->address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address64.address.minimum;
+		length = trans_data->address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		if (trans_data->ext_address64.min_address_fixed !=
+				trans_data->ext_address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->ext_address64.address.minimum;
+		length = trans_data->ext_address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		bus_addr = trans_data->io.minimum;
+		length = trans_data->io.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		bus_addr = trans_data->fixed_io.address;
+		length = trans_data->fixed_io.address_length;
+		max_pio = U16_MAX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sys_port = logic_pio_trans_hwaddr(&host->fwnode, bus_addr);
+	if (sys_port == -1) {
+		dev_err(dev, "translate bus-addr(0x%llx) fail!\n", bus_addr);
+		return -EFAULT;
+	}
+
+	/*
+	 * we need to check if the resource address can contain the
+	 * translated IO token
+	 */
+	if ((sys_port + length) > max_pio) {
+		dev_err(dev, "sys_port exceeds the max resource address\n");
+		return -ENOSPC;
+	}
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		trans_data->address16.address.minimum = sys_port;
+		trans_data->address16.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		trans_data->address32.address.minimum = sys_port;
+		trans_data->address32.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		trans_data->address64.address.minimum = sys_port;
+		trans_data->address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		trans_data->ext_address64.address.minimum = sys_port;
+		trans_data->ext_address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		trans_data->io.minimum = sys_port;
+		trans_data->io.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		trans_data->fixed_io.address = sys_port;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * update/set the current I/O resource of the designated device node.
+ * after this calling, the enumeration can be started as the I/O resource
+ * had been translated to logicial I/O from bus-local I/O.
+ *
+ * @adev: the device node to be updated the I/O resource;
+ * @host: the device node where 'adev' is attached, which can be not
+ *	the parent of 'adev';
+ *
+ * return 0 when successful, negative is for failure.
+ */
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev)
+{
+	struct acpi_device *adev;
+	struct acpi_device *host;
+	struct acpi_buffer buffer;
+	acpi_status status;
+	int ret;
+
+	if (!child || !hostdev)
+		return -EINVAL;
+
+	host = to_acpi_device(hostdev);
+	adev = to_acpi_device(child);
+
+	/* check the device state */
+	if (!adev->status.present) {
+		dev_info(child, "ACPI: device is not present!\n");
+		return 0;
+	}
+	/* whether the child had been enumerated? */
+	if (acpi_device_enumerated(adev)) {
+		dev_info(child, "ACPI: had been enumerated!\n");
+		return 0;
+	}
+
+	/* read the _CRS and convert as acpi_buffer */
+	status = acpi_build_logicpiores_template(adev, &buffer);
+	if (ACPI_FAILURE(status)) {
+		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
+		return -ENODEV;
+	}
+
+	/* translate the I/O resources */
+	ret = acpi_translate_logicpiores(adev, host, &buffer);
+	if (ret) {
+		kfree(buffer.pointer);
+		dev_err(child, "Translate I/O range FAIL!\n");
+		return ret;
+	}
+
+	/* set current resource... */
+	status = acpi_set_current_resources(adev->handle, &buffer);
+	kfree(buffer.pointer);
+	if (ACPI_FAILURE(status)) {
+		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/* All the host devices which apply indirect-PIO can be listed here. */
+static const struct acpi_device_id acpi_indirect_host_id[] = {
+	{""},
+};
+
+static int acpi_indirectpio_attach(struct acpi_device *adev,
+				const struct acpi_device_id *id)
+{
+	struct indirect_pio_device_desc *hostdata;
+	struct platform_device *pdev;
+	int ret;
+
+	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
+	if (!hostdata || !hostdata->pre_setup)
+		return -EINVAL;
+
+	ret = hostdata->pre_setup(adev, hostdata->pdata);
+	if (!ret) {
+		pdev = acpi_create_platform_device(adev, NULL);
+		if (IS_ERR_OR_NULL(pdev)) {
+			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
+			return -EFAULT;
+		}
+		acpi_device_set_enumerated(adev);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+
+static struct acpi_scan_handler acpi_indirect_handler = {
+	.ids = acpi_indirect_host_id,
+	.attach = acpi_indirectpio_attach,
+};
+
+void __init acpi_indirectio_scan_init(void)
+{
+	acpi_scan_add_handler(&acpi_indirect_handler);
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 66229ff..bf8aaf8 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -31,6 +31,11 @@ void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
 void acpi_int340x_thermal_init(void);
+#ifdef CONFIG_INDIRECT_PIO
+void acpi_indirectio_scan_init(void);
+#else
+static inline void acpi_indirectio_scan_init(void) {}
+#endif
 #ifdef CONFIG_ARM_AMBA
 void acpi_amba_init(void);
 #else
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b..37dd23c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
 	acpi_int340x_thermal_init();
 	acpi_amba_init();
 	acpi_watchdog_init();
+	acpi_indirectio_scan_init();
 
 	acpi_scan_add_handler(&generic_device_handler);
 
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
new file mode 100644
index 0000000..efc5c43
--- /dev/null
+++ b/include/acpi/acpi_indirect_pio.h
@@ -0,0 +1,24 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ACPI_INDIRECT_PIO_H
+#define _ACPI_INDIRECT_PIO_H
+
+struct indirect_pio_device_desc {
+	void *pdata; /* device relevant info data */
+	int (*pre_setup)(struct acpi_device *adev, void *pdata);
+};
+
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev);
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

From: Gabriele <gabriele.paoloni@huawei.com>

On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
I/O with some special host-local I/O ports known on x86. As their I/O
space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
meant to support a new class of I/O host controllers where the local IO
ports of the children devices are translated into the Indirect I/O address
space.
Through the handler attach callback, all the I/O translations are done
before starting the enumeration on children devices and the translated
addresses are replaced in the children resources.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 drivers/acpi/arm64/Makefile            |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
 drivers/acpi/internal.h                |   5 +
 drivers/acpi/scan.c                    |   1 +
 include/acpi/acpi_indirect_pio.h       |  24 +++
 5 files changed, 332 insertions(+)
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 include/acpi/acpi_indirect_pio.h

diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 1017def..3944775 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ACPI_IORT) 	+= iort.o
 obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
+obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
new file mode 100644
index 0000000..7813f73
--- /dev/null
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -0,0 +1,301 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/logic_pio.h>
+
+#include <acpi/acpi_indirect_pio.h>
+
+ACPI_MODULE_NAME("indirect PIO");
+
+#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
+
+static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
+					   void *data)
+{
+	int *res_cnt = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
+		(*res_cnt)++;
+
+	return AE_OK;
+}
+
+static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
+		void *data)
+{
+	struct acpi_resource **resource = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
+		memcpy((*resource), res, sizeof(struct acpi_resource));
+		(*resource)->length = sizeof(struct acpi_resource);
+		(*resource)->type = res->type;
+		(*resource)++;
+	}
+
+	return AE_OK;
+}
+
+static acpi_status
+acpi_build_logicpiores_template(struct acpi_device *adev,
+			struct acpi_buffer *buffer)
+{
+	acpi_handle handle = adev->handle;
+	struct acpi_resource *resource;
+	acpi_status status;
+	int res_cnt = 0;
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_count_logic_iores, &res_cnt);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	if (!res_cnt) {
+		dev_err(&adev->dev, "no logic IO resources\n");
+		return -ENODEV;
+	}
+
+	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
+	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
+	if (!buffer->pointer)
+		return -ENOMEM;
+
+	resource = (struct acpi_resource *)buffer->pointer;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_read_one_logicpiores, &resource);
+	if (ACPI_FAILURE(status)) {
+		kfree(buffer->pointer);
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
+	resource->length = sizeof(struct acpi_resource);
+
+	return 0;
+}
+
+static int acpi_translate_logicpiores(struct acpi_device *adev,
+		struct acpi_device *host, struct acpi_buffer *buffer)
+{
+	struct acpi_resource *resource = buffer->pointer;
+	unsigned long sys_port;
+	struct device *dev = &adev->dev;
+	union acpi_resource_data *trans_data = &resource->data;
+	resource_size_t bus_addr;
+	resource_size_t max_pio;
+	resource_size_t length;
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		if (trans_data->address16.min_address_fixed !=
+				trans_data->address16.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address16.address.minimum;
+		length = trans_data->address16.address.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		if (trans_data->address32.min_address_fixed !=
+				trans_data->address32.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address32.address.minimum;
+		length = trans_data->address32.address.address_length;
+		max_pio = U32_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		if (trans_data->address64.min_address_fixed !=
+				trans_data->address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address64.address.minimum;
+		length = trans_data->address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		if (trans_data->ext_address64.min_address_fixed !=
+				trans_data->ext_address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->ext_address64.address.minimum;
+		length = trans_data->ext_address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		bus_addr = trans_data->io.minimum;
+		length = trans_data->io.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		bus_addr = trans_data->fixed_io.address;
+		length = trans_data->fixed_io.address_length;
+		max_pio = U16_MAX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sys_port = logic_pio_trans_hwaddr(&host->fwnode, bus_addr);
+	if (sys_port == -1) {
+		dev_err(dev, "translate bus-addr(0x%llx) fail!\n", bus_addr);
+		return -EFAULT;
+	}
+
+	/*
+	 * we need to check if the resource address can contain the
+	 * translated IO token
+	 */
+	if ((sys_port + length) > max_pio) {
+		dev_err(dev, "sys_port exceeds the max resource address\n");
+		return -ENOSPC;
+	}
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		trans_data->address16.address.minimum = sys_port;
+		trans_data->address16.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		trans_data->address32.address.minimum = sys_port;
+		trans_data->address32.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		trans_data->address64.address.minimum = sys_port;
+		trans_data->address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		trans_data->ext_address64.address.minimum = sys_port;
+		trans_data->ext_address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		trans_data->io.minimum = sys_port;
+		trans_data->io.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		trans_data->fixed_io.address = sys_port;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * update/set the current I/O resource of the designated device node.
+ * after this calling, the enumeration can be started as the I/O resource
+ * had been translated to logicial I/O from bus-local I/O.
+ *
+ * @adev: the device node to be updated the I/O resource;
+ * @host: the device node where 'adev' is attached, which can be not
+ *	the parent of 'adev';
+ *
+ * return 0 when successful, negative is for failure.
+ */
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev)
+{
+	struct acpi_device *adev;
+	struct acpi_device *host;
+	struct acpi_buffer buffer;
+	acpi_status status;
+	int ret;
+
+	if (!child || !hostdev)
+		return -EINVAL;
+
+	host = to_acpi_device(hostdev);
+	adev = to_acpi_device(child);
+
+	/* check the device state */
+	if (!adev->status.present) {
+		dev_info(child, "ACPI: device is not present!\n");
+		return 0;
+	}
+	/* whether the child had been enumerated? */
+	if (acpi_device_enumerated(adev)) {
+		dev_info(child, "ACPI: had been enumerated!\n");
+		return 0;
+	}
+
+	/* read the _CRS and convert as acpi_buffer */
+	status = acpi_build_logicpiores_template(adev, &buffer);
+	if (ACPI_FAILURE(status)) {
+		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
+		return -ENODEV;
+	}
+
+	/* translate the I/O resources */
+	ret = acpi_translate_logicpiores(adev, host, &buffer);
+	if (ret) {
+		kfree(buffer.pointer);
+		dev_err(child, "Translate I/O range FAIL!\n");
+		return ret;
+	}
+
+	/* set current resource... */
+	status = acpi_set_current_resources(adev->handle, &buffer);
+	kfree(buffer.pointer);
+	if (ACPI_FAILURE(status)) {
+		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/* All the host devices which apply indirect-PIO can be listed here. */
+static const struct acpi_device_id acpi_indirect_host_id[] = {
+	{""},
+};
+
+static int acpi_indirectpio_attach(struct acpi_device *adev,
+				const struct acpi_device_id *id)
+{
+	struct indirect_pio_device_desc *hostdata;
+	struct platform_device *pdev;
+	int ret;
+
+	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
+	if (!hostdata || !hostdata->pre_setup)
+		return -EINVAL;
+
+	ret = hostdata->pre_setup(adev, hostdata->pdata);
+	if (!ret) {
+		pdev = acpi_create_platform_device(adev, NULL);
+		if (IS_ERR_OR_NULL(pdev)) {
+			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
+			return -EFAULT;
+		}
+		acpi_device_set_enumerated(adev);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+
+static struct acpi_scan_handler acpi_indirect_handler = {
+	.ids = acpi_indirect_host_id,
+	.attach = acpi_indirectpio_attach,
+};
+
+void __init acpi_indirectio_scan_init(void)
+{
+	acpi_scan_add_handler(&acpi_indirect_handler);
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 66229ff..bf8aaf8 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -31,6 +31,11 @@ void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
 void acpi_int340x_thermal_init(void);
+#ifdef CONFIG_INDIRECT_PIO
+void acpi_indirectio_scan_init(void);
+#else
+static inline void acpi_indirectio_scan_init(void) {}
+#endif
 #ifdef CONFIG_ARM_AMBA
 void acpi_amba_init(void);
 #else
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b..37dd23c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
 	acpi_int340x_thermal_init();
 	acpi_amba_init();
 	acpi_watchdog_init();
+	acpi_indirectio_scan_init();
 
 	acpi_scan_add_handler(&generic_device_handler);
 
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
new file mode 100644
index 0000000..efc5c43
--- /dev/null
+++ b/include/acpi/acpi_indirect_pio.h
@@ -0,0 +1,24 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ACPI_INDIRECT_PIO_H
+#define _ACPI_INDIRECT_PIO_H
+
+struct indirect_pio_device_desc {
+	void *pdata; /* device relevant info data */
+	int (*pre_setup)(struct acpi_device *adev, void *pdata);
+};
+
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev);
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, linux-pci, olof,
	brian.starkey

From: Gabriele <gabriele.paoloni@huawei.com>

On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
I/O with some special host-local I/O ports known on x86. As their I/O
space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
meant to support a new class of I/O host controllers where the local IO
ports of the children devices are translated into the Indirect I/O address
space.
Through the handler attach callback, all the I/O translations are done
before starting the enumeration on children devices and the translated
addresses are replaced in the children resources.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 drivers/acpi/arm64/Makefile            |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
 drivers/acpi/internal.h                |   5 +
 drivers/acpi/scan.c                    |   1 +
 include/acpi/acpi_indirect_pio.h       |  24 +++
 5 files changed, 332 insertions(+)
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 include/acpi/acpi_indirect_pio.h

diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 1017def..3944775 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ACPI_IORT) 	+= iort.o
 obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
+obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
new file mode 100644
index 0000000..7813f73
--- /dev/null
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -0,0 +1,301 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/logic_pio.h>
+
+#include <acpi/acpi_indirect_pio.h>
+
+ACPI_MODULE_NAME("indirect PIO");
+
+#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
+
+static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
+					   void *data)
+{
+	int *res_cnt = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
+		(*res_cnt)++;
+
+	return AE_OK;
+}
+
+static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
+		void *data)
+{
+	struct acpi_resource **resource = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
+		memcpy((*resource), res, sizeof(struct acpi_resource));
+		(*resource)->length = sizeof(struct acpi_resource);
+		(*resource)->type = res->type;
+		(*resource)++;
+	}
+
+	return AE_OK;
+}
+
+static acpi_status
+acpi_build_logicpiores_template(struct acpi_device *adev,
+			struct acpi_buffer *buffer)
+{
+	acpi_handle handle = adev->handle;
+	struct acpi_resource *resource;
+	acpi_status status;
+	int res_cnt = 0;
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_count_logic_iores, &res_cnt);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	if (!res_cnt) {
+		dev_err(&adev->dev, "no logic IO resources\n");
+		return -ENODEV;
+	}
+
+	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
+	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
+	if (!buffer->pointer)
+		return -ENOMEM;
+
+	resource = (struct acpi_resource *)buffer->pointer;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_read_one_logicpiores, &resource);
+	if (ACPI_FAILURE(status)) {
+		kfree(buffer->pointer);
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
+	resource->length = sizeof(struct acpi_resource);
+
+	return 0;
+}
+
+static int acpi_translate_logicpiores(struct acpi_device *adev,
+		struct acpi_device *host, struct acpi_buffer *buffer)
+{
+	struct acpi_resource *resource = buffer->pointer;
+	unsigned long sys_port;
+	struct device *dev = &adev->dev;
+	union acpi_resource_data *trans_data = &resource->data;
+	resource_size_t bus_addr;
+	resource_size_t max_pio;
+	resource_size_t length;
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		if (trans_data->address16.min_address_fixed !=
+				trans_data->address16.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address16.address.minimum;
+		length = trans_data->address16.address.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		if (trans_data->address32.min_address_fixed !=
+				trans_data->address32.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address32.address.minimum;
+		length = trans_data->address32.address.address_length;
+		max_pio = U32_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		if (trans_data->address64.min_address_fixed !=
+				trans_data->address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address64.address.minimum;
+		length = trans_data->address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		if (trans_data->ext_address64.min_address_fixed !=
+				trans_data->ext_address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->ext_address64.address.minimum;
+		length = trans_data->ext_address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		bus_addr = trans_data->io.minimum;
+		length = trans_data->io.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		bus_addr = trans_data->fixed_io.address;
+		length = trans_data->fixed_io.address_length;
+		max_pio = U16_MAX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sys_port = logic_pio_trans_hwaddr(&host->fwnode, bus_addr);
+	if (sys_port == -1) {
+		dev_err(dev, "translate bus-addr(0x%llx) fail!\n", bus_addr);
+		return -EFAULT;
+	}
+
+	/*
+	 * we need to check if the resource address can contain the
+	 * translated IO token
+	 */
+	if ((sys_port + length) > max_pio) {
+		dev_err(dev, "sys_port exceeds the max resource address\n");
+		return -ENOSPC;
+	}
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		trans_data->address16.address.minimum = sys_port;
+		trans_data->address16.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		trans_data->address32.address.minimum = sys_port;
+		trans_data->address32.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		trans_data->address64.address.minimum = sys_port;
+		trans_data->address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		trans_data->ext_address64.address.minimum = sys_port;
+		trans_data->ext_address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		trans_data->io.minimum = sys_port;
+		trans_data->io.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		trans_data->fixed_io.address = sys_port;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * update/set the current I/O resource of the designated device node.
+ * after this calling, the enumeration can be started as the I/O resource
+ * had been translated to logicial I/O from bus-local I/O.
+ *
+ * @adev: the device node to be updated the I/O resource;
+ * @host: the device node where 'adev' is attached, which can be not
+ *	the parent of 'adev';
+ *
+ * return 0 when successful, negative is for failure.
+ */
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev)
+{
+	struct acpi_device *adev;
+	struct acpi_device *host;
+	struct acpi_buffer buffer;
+	acpi_status status;
+	int ret;
+
+	if (!child || !hostdev)
+		return -EINVAL;
+
+	host = to_acpi_device(hostdev);
+	adev = to_acpi_device(child);
+
+	/* check the device state */
+	if (!adev->status.present) {
+		dev_info(child, "ACPI: device is not present!\n");
+		return 0;
+	}
+	/* whether the child had been enumerated? */
+	if (acpi_device_enumerated(adev)) {
+		dev_info(child, "ACPI: had been enumerated!\n");
+		return 0;
+	}
+
+	/* read the _CRS and convert as acpi_buffer */
+	status = acpi_build_logicpiores_template(adev, &buffer);
+	if (ACPI_FAILURE(status)) {
+		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
+		return -ENODEV;
+	}
+
+	/* translate the I/O resources */
+	ret = acpi_translate_logicpiores(adev, host, &buffer);
+	if (ret) {
+		kfree(buffer.pointer);
+		dev_err(child, "Translate I/O range FAIL!\n");
+		return ret;
+	}
+
+	/* set current resource... */
+	status = acpi_set_current_resources(adev->handle, &buffer);
+	kfree(buffer.pointer);
+	if (ACPI_FAILURE(status)) {
+		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/* All the host devices which apply indirect-PIO can be listed here. */
+static const struct acpi_device_id acpi_indirect_host_id[] = {
+	{""},
+};
+
+static int acpi_indirectpio_attach(struct acpi_device *adev,
+				const struct acpi_device_id *id)
+{
+	struct indirect_pio_device_desc *hostdata;
+	struct platform_device *pdev;
+	int ret;
+
+	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
+	if (!hostdata || !hostdata->pre_setup)
+		return -EINVAL;
+
+	ret = hostdata->pre_setup(adev, hostdata->pdata);
+	if (!ret) {
+		pdev = acpi_create_platform_device(adev, NULL);
+		if (IS_ERR_OR_NULL(pdev)) {
+			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
+			return -EFAULT;
+		}
+		acpi_device_set_enumerated(adev);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+
+static struct acpi_scan_handler acpi_indirect_handler = {
+	.ids = acpi_indirect_host_id,
+	.attach = acpi_indirectpio_attach,
+};
+
+void __init acpi_indirectio_scan_init(void)
+{
+	acpi_scan_add_handler(&acpi_indirect_handler);
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 66229ff..bf8aaf8 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -31,6 +31,11 @@ void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
 void acpi_int340x_thermal_init(void);
+#ifdef CONFIG_INDIRECT_PIO
+void acpi_indirectio_scan_init(void);
+#else
+static inline void acpi_indirectio_scan_init(void) {}
+#endif
 #ifdef CONFIG_ARM_AMBA
 void acpi_amba_init(void);
 #else
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b..37dd23c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
 	acpi_int340x_thermal_init();
 	acpi_amba_init();
 	acpi_watchdog_init();
+	acpi_indirectio_scan_init();
 
 	acpi_scan_add_handler(&generic_device_handler);
 
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
new file mode 100644
index 0000000..efc5c43
--- /dev/null
+++ b/include/acpi/acpi_indirect_pio.h
@@ -0,0 +1,24 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ACPI_INDIRECT_PIO_H
+#define _ACPI_INDIRECT_PIO_H
+
+struct indirect_pio_device_desc {
+	void *pdata; /* device relevant info data */
+	int (*pre_setup)(struct acpi_device *adev, void *pdata);
+};
+
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev);
+
+#endif
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: Gabriele <gabriele.paoloni@huawei.com>

On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
I/O with some special host-local I/O ports known on x86. As their I/O
space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
meant to support a new class of I/O host controllers where the local IO
ports of the children devices are translated into the Indirect I/O address
space.
Through the handler attach callback, all the I/O translations are done
before starting the enumeration on children devices and the translated
addresses are replaced in the children resources.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 drivers/acpi/arm64/Makefile            |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
 drivers/acpi/internal.h                |   5 +
 drivers/acpi/scan.c                    |   1 +
 include/acpi/acpi_indirect_pio.h       |  24 +++
 5 files changed, 332 insertions(+)
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 include/acpi/acpi_indirect_pio.h

diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 1017def..3944775 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ACPI_IORT) 	+= iort.o
 obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
+obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
new file mode 100644
index 0000000..7813f73
--- /dev/null
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -0,0 +1,301 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/logic_pio.h>
+
+#include <acpi/acpi_indirect_pio.h>
+
+ACPI_MODULE_NAME("indirect PIO");
+
+#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
+
+static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
+					   void *data)
+{
+	int *res_cnt = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
+		(*res_cnt)++;
+
+	return AE_OK;
+}
+
+static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
+		void *data)
+{
+	struct acpi_resource **resource = data;
+
+	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
+		memcpy((*resource), res, sizeof(struct acpi_resource));
+		(*resource)->length = sizeof(struct acpi_resource);
+		(*resource)->type = res->type;
+		(*resource)++;
+	}
+
+	return AE_OK;
+}
+
+static acpi_status
+acpi_build_logicpiores_template(struct acpi_device *adev,
+			struct acpi_buffer *buffer)
+{
+	acpi_handle handle = adev->handle;
+	struct acpi_resource *resource;
+	acpi_status status;
+	int res_cnt = 0;
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_count_logic_iores, &res_cnt);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	if (!res_cnt) {
+		dev_err(&adev->dev, "no logic IO resources\n");
+		return -ENODEV;
+	}
+
+	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
+	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
+	if (!buffer->pointer)
+		return -ENOMEM;
+
+	resource = (struct acpi_resource *)buffer->pointer;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     acpi_read_one_logicpiores, &resource);
+	if (ACPI_FAILURE(status)) {
+		kfree(buffer->pointer);
+		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
+		return -EINVAL;
+	}
+
+	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
+	resource->length = sizeof(struct acpi_resource);
+
+	return 0;
+}
+
+static int acpi_translate_logicpiores(struct acpi_device *adev,
+		struct acpi_device *host, struct acpi_buffer *buffer)
+{
+	struct acpi_resource *resource = buffer->pointer;
+	unsigned long sys_port;
+	struct device *dev = &adev->dev;
+	union acpi_resource_data *trans_data = &resource->data;
+	resource_size_t bus_addr;
+	resource_size_t max_pio;
+	resource_size_t length;
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		if (trans_data->address16.min_address_fixed !=
+				trans_data->address16.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address16.address.minimum;
+		length = trans_data->address16.address.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		if (trans_data->address32.min_address_fixed !=
+				trans_data->address32.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address32.address.minimum;
+		length = trans_data->address32.address.address_length;
+		max_pio = U32_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		if (trans_data->address64.min_address_fixed !=
+				trans_data->address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->address64.address.minimum;
+		length = trans_data->address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		if (trans_data->ext_address64.min_address_fixed !=
+				trans_data->ext_address64.max_address_fixed) {
+			dev_warn(dev, "variable I/O resource is invalid!\n");
+			return -EINVAL;
+		}
+		bus_addr = trans_data->ext_address64.address.minimum;
+		length = trans_data->ext_address64.address.address_length;
+		max_pio = U64_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		bus_addr = trans_data->io.minimum;
+		length = trans_data->io.address_length;
+		max_pio = U16_MAX;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		bus_addr = trans_data->fixed_io.address;
+		length = trans_data->fixed_io.address_length;
+		max_pio = U16_MAX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sys_port = logic_pio_trans_hwaddr(&host->fwnode, bus_addr);
+	if (sys_port == -1) {
+		dev_err(dev, "translate bus-addr(0x%llx) fail!\n", bus_addr);
+		return -EFAULT;
+	}
+
+	/*
+	 * we need to check if the resource address can contain the
+	 * translated IO token
+	 */
+	if ((sys_port + length) > max_pio) {
+		dev_err(dev, "sys_port exceeds the max resource address\n");
+		return -ENOSPC;
+	}
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+		trans_data->address16.address.minimum = sys_port;
+		trans_data->address16.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+		trans_data->address32.address.minimum = sys_port;
+		trans_data->address32.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		trans_data->address64.address.minimum = sys_port;
+		trans_data->address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		trans_data->ext_address64.address.minimum = sys_port;
+		trans_data->ext_address64.address.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_IO:
+		trans_data->io.minimum = sys_port;
+		trans_data->io.maximum = sys_port + length;
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		trans_data->fixed_io.address = sys_port;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * update/set the current I/O resource of the designated device node.
+ * after this calling, the enumeration can be started as the I/O resource
+ * had been translated to logicial I/O from bus-local I/O.
+ *
+ * @adev: the device node to be updated the I/O resource;
+ * @host: the device node where 'adev' is attached, which can be not
+ *	the parent of 'adev';
+ *
+ * return 0 when successful, negative is for failure.
+ */
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev)
+{
+	struct acpi_device *adev;
+	struct acpi_device *host;
+	struct acpi_buffer buffer;
+	acpi_status status;
+	int ret;
+
+	if (!child || !hostdev)
+		return -EINVAL;
+
+	host = to_acpi_device(hostdev);
+	adev = to_acpi_device(child);
+
+	/* check the device state */
+	if (!adev->status.present) {
+		dev_info(child, "ACPI: device is not present!\n");
+		return 0;
+	}
+	/* whether the child had been enumerated? */
+	if (acpi_device_enumerated(adev)) {
+		dev_info(child, "ACPI: had been enumerated!\n");
+		return 0;
+	}
+
+	/* read the _CRS and convert as acpi_buffer */
+	status = acpi_build_logicpiores_template(adev, &buffer);
+	if (ACPI_FAILURE(status)) {
+		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
+		return -ENODEV;
+	}
+
+	/* translate the I/O resources */
+	ret = acpi_translate_logicpiores(adev, host, &buffer);
+	if (ret) {
+		kfree(buffer.pointer);
+		dev_err(child, "Translate I/O range FAIL!\n");
+		return ret;
+	}
+
+	/* set current resource... */
+	status = acpi_set_current_resources(adev->handle, &buffer);
+	kfree(buffer.pointer);
+	if (ACPI_FAILURE(status)) {
+		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/* All the host devices which apply indirect-PIO can be listed here. */
+static const struct acpi_device_id acpi_indirect_host_id[] = {
+	{""},
+};
+
+static int acpi_indirectpio_attach(struct acpi_device *adev,
+				const struct acpi_device_id *id)
+{
+	struct indirect_pio_device_desc *hostdata;
+	struct platform_device *pdev;
+	int ret;
+
+	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
+	if (!hostdata || !hostdata->pre_setup)
+		return -EINVAL;
+
+	ret = hostdata->pre_setup(adev, hostdata->pdata);
+	if (!ret) {
+		pdev = acpi_create_platform_device(adev, NULL);
+		if (IS_ERR_OR_NULL(pdev)) {
+			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
+			return -EFAULT;
+		}
+		acpi_device_set_enumerated(adev);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+
+static struct acpi_scan_handler acpi_indirect_handler = {
+	.ids = acpi_indirect_host_id,
+	.attach = acpi_indirectpio_attach,
+};
+
+void __init acpi_indirectio_scan_init(void)
+{
+	acpi_scan_add_handler(&acpi_indirect_handler);
+}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 66229ff..bf8aaf8 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -31,6 +31,11 @@ void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
 void acpi_int340x_thermal_init(void);
+#ifdef CONFIG_INDIRECT_PIO
+void acpi_indirectio_scan_init(void);
+#else
+static inline void acpi_indirectio_scan_init(void) {}
+#endif
 #ifdef CONFIG_ARM_AMBA
 void acpi_amba_init(void);
 #else
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b..37dd23c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
 	acpi_int340x_thermal_init();
 	acpi_amba_init();
 	acpi_watchdog_init();
+	acpi_indirectio_scan_init();
 
 	acpi_scan_add_handler(&generic_device_handler);
 
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
new file mode 100644
index 0000000..efc5c43
--- /dev/null
+++ b/include/acpi/acpi_indirect_pio.h
@@ -0,0 +1,24 @@
+/*
+ * ACPI support for indirect-PIO bus.
+ *
+ * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
+ * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ACPI_INDIRECT_PIO_H
+#define _ACPI_INDIRECT_PIO_H
+
+struct indirect_pio_device_desc {
+	void *pdata; /* device relevant info data */
+	int (*pre_setup)(struct acpi_device *adev, void *pdata);
+};
+
+int acpi_set_logic_pio_resource(struct device *child,
+		struct device *hostdev);
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 6/7] LPC: Add the ACPI LPC support
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

Based on the provious patches, this patch supports the ACPI LPC host on
Hip06/Hip07.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Tested-by: dann frazier <dann.frazier@canonical.com>
---
 drivers/acpi/arm64/acpi_indirect_pio.c |  3 ++
 drivers/bus/hisi_lpc.c                 | 71 ++++++++++++++++++++++++++++++++--
 include/acpi/acpi_indirect_pio.h       |  4 ++
 3 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
index 7813f73..3a5ba7a 100644
--- a/drivers/acpi/arm64/acpi_indirect_pio.c
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -261,6 +261,9 @@ int acpi_set_logic_pio_resource(struct device *child,
 
 /* All the host devices which apply indirect-PIO can be listed here. */
 static const struct acpi_device_id acpi_indirect_host_id[] = {
+#ifdef CONFIG_HISILICON_LPC
+	{"HISI0191", INDIRECT_PIO_INFO(lpc_host_desc)},
+#endif
 	{""},
 };
 
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 4f3bf76..05a0a84 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -467,7 +467,9 @@ static int hisilpc_probe(struct platform_device *pdev)
 	}
 
 	/* register the LPC host PIO resources */
-	if (!has_acpi_companion(dev)) {
+	if (has_acpi_companion(dev)) {
+		lpcdev->io_host = find_io_range_by_fwnode(dev->fwnode);
+	} else {
 		struct logic_pio_hwaddr *range;
 
 		range = kzalloc(sizeof(*range), GFP_KERNEL);
@@ -481,13 +483,14 @@ static int hisilpc_probe(struct platform_device *pdev)
 		ret = logic_pio_register_range(range);
 		if (ret) {
 			kfree(range);
-			dev_err(dev, "OF: register IO range FAIL!\n");
+			dev_err(dev, "OF: logic_pio_register_range returned %d!\n",
+					ret);
 			return -ret;
 		}
 		lpcdev->io_host = range;
 	}
 	if (!lpcdev->io_host) {
-		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		dev_err(dev, "HiSi LPC IO hasn't been registered!\n");
 		return -EFAULT;
 	}
 
@@ -533,10 +536,72 @@ static const struct of_device_id hisilpc_of_match[] = {
 	{},
 };
 
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_indirect_pio.h>
+
+struct lpc_private_data {
+	resource_size_t io_size;
+	resource_size_t io_start;
+};
+
+static struct lpc_private_data lpc_data = {
+	.io_size = LPC_BUS_IO_SIZE,
+	.io_start = LPC_MIN_BUS_RANGE,
+};
+
+static int lpc_host_io_setup(struct acpi_device *adev, void *pdata)
+{
+	int ret = 0;
+	struct logic_pio_hwaddr *range;
+	struct lpc_private_data *lpc_private;
+	struct acpi_device *child;
+
+	lpc_private = (struct lpc_private_data *)pdata;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = &adev->fwnode;
+	range->flags = PIO_INDIRECT;
+	range->size = lpc_private->io_size;
+	range->hw_start = lpc_private->io_start;
+
+	ret = logic_pio_register_range(range);
+	if (ret) {
+		kfree(range);
+		return ret;
+	}
+
+	/* In HiSilicon lpc, only care about the children of the host. */
+	list_for_each_entry(child, &adev->children, node) {
+		ret = acpi_set_logic_pio_resource(&child->dev, &adev->dev);
+		if (ret) {
+			dev_err(&child->dev,
+					"acpi_set_logic_pio_resource() returned %d\n",
+					ret);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+const struct indirect_pio_device_desc lpc_host_desc = {
+	.pdata = &lpc_data,
+	.pre_setup = lpc_host_io_setup,
+};
+
+#endif
+
 static struct platform_driver hisilpc_driver = {
 	.driver = {
 		.name           = "hisi_lpc",
 		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = ACPI_PTR(hisilpc_acpi_match),
 	},
 	.probe = hisilpc_probe,
 };
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
index efc5c43..7a8d26b 100644
--- a/include/acpi/acpi_indirect_pio.h
+++ b/include/acpi/acpi_indirect_pio.h
@@ -18,6 +18,10 @@ struct indirect_pio_device_desc {
 	int (*pre_setup)(struct acpi_device *adev, void *pdata);
 };
 
+#ifdef CONFIG_HISILICON_LPC
+extern const struct indirect_pio_device_desc lpc_host_desc;
+#endif
+
 int acpi_set_logic_pio_resource(struct device *child,
 		struct device *hostdev);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

Based on the provious patches, this patch supports the ACPI LPC host on
Hip06/Hip07.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Tested-by: dann frazier <dann.frazier@canonical.com>
---
 drivers/acpi/arm64/acpi_indirect_pio.c |  3 ++
 drivers/bus/hisi_lpc.c                 | 71 ++++++++++++++++++++++++++++++++--
 include/acpi/acpi_indirect_pio.h       |  4 ++
 3 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
index 7813f73..3a5ba7a 100644
--- a/drivers/acpi/arm64/acpi_indirect_pio.c
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -261,6 +261,9 @@ int acpi_set_logic_pio_resource(struct device *child,
 
 /* All the host devices which apply indirect-PIO can be listed here. */
 static const struct acpi_device_id acpi_indirect_host_id[] = {
+#ifdef CONFIG_HISILICON_LPC
+	{"HISI0191", INDIRECT_PIO_INFO(lpc_host_desc)},
+#endif
 	{""},
 };
 
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 4f3bf76..05a0a84 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -467,7 +467,9 @@ static int hisilpc_probe(struct platform_device *pdev)
 	}
 
 	/* register the LPC host PIO resources */
-	if (!has_acpi_companion(dev)) {
+	if (has_acpi_companion(dev)) {
+		lpcdev->io_host = find_io_range_by_fwnode(dev->fwnode);
+	} else {
 		struct logic_pio_hwaddr *range;
 
 		range = kzalloc(sizeof(*range), GFP_KERNEL);
@@ -481,13 +483,14 @@ static int hisilpc_probe(struct platform_device *pdev)
 		ret = logic_pio_register_range(range);
 		if (ret) {
 			kfree(range);
-			dev_err(dev, "OF: register IO range FAIL!\n");
+			dev_err(dev, "OF: logic_pio_register_range returned %d!\n",
+					ret);
 			return -ret;
 		}
 		lpcdev->io_host = range;
 	}
 	if (!lpcdev->io_host) {
-		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		dev_err(dev, "HiSi LPC IO hasn't been registered!\n");
 		return -EFAULT;
 	}
 
@@ -533,10 +536,72 @@ static const struct of_device_id hisilpc_of_match[] = {
 	{},
 };
 
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_indirect_pio.h>
+
+struct lpc_private_data {
+	resource_size_t io_size;
+	resource_size_t io_start;
+};
+
+static struct lpc_private_data lpc_data = {
+	.io_size = LPC_BUS_IO_SIZE,
+	.io_start = LPC_MIN_BUS_RANGE,
+};
+
+static int lpc_host_io_setup(struct acpi_device *adev, void *pdata)
+{
+	int ret = 0;
+	struct logic_pio_hwaddr *range;
+	struct lpc_private_data *lpc_private;
+	struct acpi_device *child;
+
+	lpc_private = (struct lpc_private_data *)pdata;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = &adev->fwnode;
+	range->flags = PIO_INDIRECT;
+	range->size = lpc_private->io_size;
+	range->hw_start = lpc_private->io_start;
+
+	ret = logic_pio_register_range(range);
+	if (ret) {
+		kfree(range);
+		return ret;
+	}
+
+	/* In HiSilicon lpc, only care about the children of the host. */
+	list_for_each_entry(child, &adev->children, node) {
+		ret = acpi_set_logic_pio_resource(&child->dev, &adev->dev);
+		if (ret) {
+			dev_err(&child->dev,
+					"acpi_set_logic_pio_resource() returned %d\n",
+					ret);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+const struct indirect_pio_device_desc lpc_host_desc = {
+	.pdata = &lpc_data,
+	.pre_setup = lpc_host_io_setup,
+};
+
+#endif
+
 static struct platform_driver hisilpc_driver = {
 	.driver = {
 		.name           = "hisi_lpc",
 		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = ACPI_PTR(hisilpc_acpi_match),
 	},
 	.probe = hisilpc_probe,
 };
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
index efc5c43..7a8d26b 100644
--- a/include/acpi/acpi_indirect_pio.h
+++ b/include/acpi/acpi_indirect_pio.h
@@ -18,6 +18,10 @@ struct indirect_pio_device_desc {
 	int (*pre_setup)(struct acpi_device *adev, void *pdata);
 };
 
+#ifdef CONFIG_HISILICON_LPC
+extern const struct indirect_pio_device_desc lpc_host_desc;
+#endif
+
 int acpi_set_logic_pio_resource(struct device *child,
 		struct device *hostdev);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, zhichang.yuan,
	linux-pci, olof, brian.starkey

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

Based on the provious patches, this patch supports the ACPI LPC host on
Hip06/Hip07.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Tested-by: dann frazier <dann.frazier@canonical.com>
---
 drivers/acpi/arm64/acpi_indirect_pio.c |  3 ++
 drivers/bus/hisi_lpc.c                 | 71 ++++++++++++++++++++++++++++++++--
 include/acpi/acpi_indirect_pio.h       |  4 ++
 3 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
index 7813f73..3a5ba7a 100644
--- a/drivers/acpi/arm64/acpi_indirect_pio.c
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -261,6 +261,9 @@ int acpi_set_logic_pio_resource(struct device *child,
 
 /* All the host devices which apply indirect-PIO can be listed here. */
 static const struct acpi_device_id acpi_indirect_host_id[] = {
+#ifdef CONFIG_HISILICON_LPC
+	{"HISI0191", INDIRECT_PIO_INFO(lpc_host_desc)},
+#endif
 	{""},
 };
 
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 4f3bf76..05a0a84 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -467,7 +467,9 @@ static int hisilpc_probe(struct platform_device *pdev)
 	}
 
 	/* register the LPC host PIO resources */
-	if (!has_acpi_companion(dev)) {
+	if (has_acpi_companion(dev)) {
+		lpcdev->io_host = find_io_range_by_fwnode(dev->fwnode);
+	} else {
 		struct logic_pio_hwaddr *range;
 
 		range = kzalloc(sizeof(*range), GFP_KERNEL);
@@ -481,13 +483,14 @@ static int hisilpc_probe(struct platform_device *pdev)
 		ret = logic_pio_register_range(range);
 		if (ret) {
 			kfree(range);
-			dev_err(dev, "OF: register IO range FAIL!\n");
+			dev_err(dev, "OF: logic_pio_register_range returned %d!\n",
+					ret);
 			return -ret;
 		}
 		lpcdev->io_host = range;
 	}
 	if (!lpcdev->io_host) {
-		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		dev_err(dev, "HiSi LPC IO hasn't been registered!\n");
 		return -EFAULT;
 	}
 
@@ -533,10 +536,72 @@ static const struct of_device_id hisilpc_of_match[] = {
 	{},
 };
 
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_indirect_pio.h>
+
+struct lpc_private_data {
+	resource_size_t io_size;
+	resource_size_t io_start;
+};
+
+static struct lpc_private_data lpc_data = {
+	.io_size = LPC_BUS_IO_SIZE,
+	.io_start = LPC_MIN_BUS_RANGE,
+};
+
+static int lpc_host_io_setup(struct acpi_device *adev, void *pdata)
+{
+	int ret = 0;
+	struct logic_pio_hwaddr *range;
+	struct lpc_private_data *lpc_private;
+	struct acpi_device *child;
+
+	lpc_private = (struct lpc_private_data *)pdata;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = &adev->fwnode;
+	range->flags = PIO_INDIRECT;
+	range->size = lpc_private->io_size;
+	range->hw_start = lpc_private->io_start;
+
+	ret = logic_pio_register_range(range);
+	if (ret) {
+		kfree(range);
+		return ret;
+	}
+
+	/* In HiSilicon lpc, only care about the children of the host. */
+	list_for_each_entry(child, &adev->children, node) {
+		ret = acpi_set_logic_pio_resource(&child->dev, &adev->dev);
+		if (ret) {
+			dev_err(&child->dev,
+					"acpi_set_logic_pio_resource() returned %d\n",
+					ret);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+const struct indirect_pio_device_desc lpc_host_desc = {
+	.pdata = &lpc_data,
+	.pre_setup = lpc_host_io_setup,
+};
+
+#endif
+
 static struct platform_driver hisilpc_driver = {
 	.driver = {
 		.name           = "hisi_lpc",
 		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = ACPI_PTR(hisilpc_acpi_match),
 	},
 	.probe = hisilpc_probe,
 };
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
index efc5c43..7a8d26b 100644
--- a/include/acpi/acpi_indirect_pio.h
+++ b/include/acpi/acpi_indirect_pio.h
@@ -18,6 +18,10 @@ struct indirect_pio_device_desc {
 	int (*pre_setup)(struct acpi_device *adev, void *pdata);
 };
 
+#ifdef CONFIG_HISILICON_LPC
+extern const struct indirect_pio_device_desc lpc_host_desc;
+#endif
+
 int acpi_set_logic_pio_resource(struct device *child,
 		struct device *hostdev);
 
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

Based on the provious patches, this patch supports the ACPI LPC host on
Hip06/Hip07.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Tested-by: dann frazier <dann.frazier@canonical.com>
---
 drivers/acpi/arm64/acpi_indirect_pio.c |  3 ++
 drivers/bus/hisi_lpc.c                 | 71 ++++++++++++++++++++++++++++++++--
 include/acpi/acpi_indirect_pio.h       |  4 ++
 3 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
index 7813f73..3a5ba7a 100644
--- a/drivers/acpi/arm64/acpi_indirect_pio.c
+++ b/drivers/acpi/arm64/acpi_indirect_pio.c
@@ -261,6 +261,9 @@ int acpi_set_logic_pio_resource(struct device *child,
 
 /* All the host devices which apply indirect-PIO can be listed here. */
 static const struct acpi_device_id acpi_indirect_host_id[] = {
+#ifdef CONFIG_HISILICON_LPC
+	{"HISI0191", INDIRECT_PIO_INFO(lpc_host_desc)},
+#endif
 	{""},
 };
 
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 4f3bf76..05a0a84 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -467,7 +467,9 @@ static int hisilpc_probe(struct platform_device *pdev)
 	}
 
 	/* register the LPC host PIO resources */
-	if (!has_acpi_companion(dev)) {
+	if (has_acpi_companion(dev)) {
+		lpcdev->io_host = find_io_range_by_fwnode(dev->fwnode);
+	} else {
 		struct logic_pio_hwaddr *range;
 
 		range = kzalloc(sizeof(*range), GFP_KERNEL);
@@ -481,13 +483,14 @@ static int hisilpc_probe(struct platform_device *pdev)
 		ret = logic_pio_register_range(range);
 		if (ret) {
 			kfree(range);
-			dev_err(dev, "OF: register IO range FAIL!\n");
+			dev_err(dev, "OF: logic_pio_register_range returned %d!\n",
+					ret);
 			return -ret;
 		}
 		lpcdev->io_host = range;
 	}
 	if (!lpcdev->io_host) {
-		dev_err(dev, "Hisilpc IO hasn't registered!\n");
+		dev_err(dev, "HiSi LPC IO hasn't been registered!\n");
 		return -EFAULT;
 	}
 
@@ -533,10 +536,72 @@ static const struct of_device_id hisilpc_of_match[] = {
 	{},
 };
 
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_indirect_pio.h>
+
+struct lpc_private_data {
+	resource_size_t io_size;
+	resource_size_t io_start;
+};
+
+static struct lpc_private_data lpc_data = {
+	.io_size = LPC_BUS_IO_SIZE,
+	.io_start = LPC_MIN_BUS_RANGE,
+};
+
+static int lpc_host_io_setup(struct acpi_device *adev, void *pdata)
+{
+	int ret = 0;
+	struct logic_pio_hwaddr *range;
+	struct lpc_private_data *lpc_private;
+	struct acpi_device *child;
+
+	lpc_private = (struct lpc_private_data *)pdata;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = &adev->fwnode;
+	range->flags = PIO_INDIRECT;
+	range->size = lpc_private->io_size;
+	range->hw_start = lpc_private->io_start;
+
+	ret = logic_pio_register_range(range);
+	if (ret) {
+		kfree(range);
+		return ret;
+	}
+
+	/* In HiSilicon lpc, only care about the children of the host. */
+	list_for_each_entry(child, &adev->children, node) {
+		ret = acpi_set_logic_pio_resource(&child->dev, &adev->dev);
+		if (ret) {
+			dev_err(&child->dev,
+					"acpi_set_logic_pio_resource() returned %d\n",
+					ret);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+const struct indirect_pio_device_desc lpc_host_desc = {
+	.pdata = &lpc_data,
+	.pre_setup = lpc_host_io_setup,
+};
+
+#endif
+
 static struct platform_driver hisilpc_driver = {
 	.driver = {
 		.name           = "hisi_lpc",
 		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = ACPI_PTR(hisilpc_acpi_match),
 	},
 	.probe = hisilpc_probe,
 };
diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
index efc5c43..7a8d26b 100644
--- a/include/acpi/acpi_indirect_pio.h
+++ b/include/acpi/acpi_indirect_pio.h
@@ -18,6 +18,10 @@ struct indirect_pio_device_desc {
 	int (*pre_setup)(struct acpi_device *adev, void *pdata);
 };
 
+#ifdef CONFIG_HISILICON_LPC
+extern const struct indirect_pio_device_desc lpc_host_desc;
+#endif
+
 int acpi_set_logic_pio_resource(struct device *child,
 		struct device *hostdev);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver
  2017-05-25 11:37 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-25 11:37   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

Added maintainer for drivers/bus/hisi_lpc.c

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e98464..8fb9006 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6061,6 +6061,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Gabriele Paoloni <gabriele.paoloni@huawei.com>
+L:	linux-arm-kernel@lists.infradead.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/bus/hisi_lpc.c
+F:	Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+
 HISILICON NETWORK SUBSYSTEM DRIVER
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

Added maintainer for drivers/bus/hisi_lpc.c

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e98464..8fb9006 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6061,6 +6061,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Gabriele Paoloni <gabriele.paoloni@huawei.com>
+L:	linux-arm-kernel@lists.infradead.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/bus/hisi_lpc.c
+F:	Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+
 HISILICON NETWORK SUBSYSTEM DRIVER
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi
  Cc: mark.rutland, minyard, gabriele.paoloni, benh, john.garry,
	linux-kernel, xuwei5, linuxarm, linux-acpi, linux-pci, olof,
	brian.starkey

Added maintainer for drivers/bus/hisi_lpc.c

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e98464..8fb9006 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6061,6 +6061,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Gabriele Paoloni <gabriele.paoloni@huawei.com>
+L:	linux-arm-kernel@lists.infradead.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/bus/hisi_lpc.c
+F:	Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+
 HISILICON NETWORK SUBSYSTEM DRIVER
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
-- 
2.7.4



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver
@ 2017-05-25 11:37   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-25 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

Added maintainer for drivers/bus/hisi_lpc.c

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e98464..8fb9006 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6061,6 +6061,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Gabriele Paoloni <gabriele.paoloni@huawei.com>
+L:	linux-arm-kernel at lists.infradead.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/bus/hisi_lpc.c
+F:	Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+
 HISILICON NETWORK SUBSYSTEM DRIVER
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-05-25 11:37   ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-26  0:03     ` kbuild test robot
  -1 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  0:03 UTC (permalink / raw)
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, frowand.list,
	bhelgaas, rafael, arnd, linux-arm-kernel, lorenzo.pieralisi,
	gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

[-- Attachment #1: Type: text/plain, Size: 965 bytes --]

Hi Gabriele,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `acpi_scan_init':
>> (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47743 bytes --]

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-26  0:03     ` kbuild test robot
  0 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  0:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, frowand.list,
	bhelgaas, rafael, arnd, linux-arm-kernel, lorenzo.pieralisi,
	gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5

[-- Attachment #1: Type: text/plain, Size: 965 bytes --]

Hi Gabriele,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `acpi_scan_init':
>> (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47743 bytes --]

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-26  0:03     ` kbuild test robot
  0 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  0:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, gabriele.paoloni, rafael, linux-pci,
	will.deacon, linuxarm, frowand.list, lorenzo.pieralisi, arnd,
	xuwei5, linux-acpi, catalin.marinas, minyard, john.garry,
	robh+dt, bhelgaas, linux-arm-kernel, linux-kernel, kbuild-all,
	olof, brian.starkey

[-- Attachment #1: Type: text/plain, Size: 965 bytes --]

Hi Gabriele,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `acpi_scan_init':
>> (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47743 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-26  0:03     ` kbuild test robot
  0 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  0:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Gabriele,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `acpi_scan_init':
>> (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 47743 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170526/e1dfddfc/attachment-0001.gz>

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 6/7] LPC: Add the ACPI LPC support
  2017-05-25 11:37   ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-26  3:12     ` kbuild test robot
  -1 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  3:12 UTC (permalink / raw)
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, frowand.list,
	bhelgaas, rafael, arnd, linux-arm-kernel, lorenzo.pieralisi,
	gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 1108 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `lpc_host_io_setup':
>> hisi_lpc.c:(.text+0x252): undefined reference to `acpi_set_logic_pio_resource'
   drivers/built-in.o: In function `acpi_scan_init':
   (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47743 bytes --]

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-26  3:12     ` kbuild test robot
  0 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  3:12 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, frowand.list,
	bhelgaas, rafael, arnd, linux-arm-kernel, lorenzo.pieralisi,
	gabriele.paoloni, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, linuxarm, linux-pci, minyard,
	john.garry, xuwei5, zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 1108 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `lpc_host_io_setup':
>> hisi_lpc.c:(.text+0x252): undefined reference to `acpi_set_logic_pio_resource'
   drivers/built-in.o: In function `acpi_scan_init':
   (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47743 bytes --]

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-26  3:12     ` kbuild test robot
  0 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  3:12 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, gabriele.paoloni, rafael, linux-pci,
	will.deacon, linuxarm, frowand.list, lorenzo.pieralisi, arnd,
	xuwei5, linux-acpi, catalin.marinas, minyard, john.garry,
	robh+dt, bhelgaas, linux-arm-kernel, linux-kernel, zhichang.yuan,
	kbuild-all, olof, brian.starkey

[-- Attachment #1: Type: text/plain, Size: 1108 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `lpc_host_io_setup':
>> hisi_lpc.c:(.text+0x252): undefined reference to `acpi_set_logic_pio_resource'
   drivers/built-in.o: In function `acpi_scan_init':
   (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47743 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-26  3:12     ` kbuild test robot
  0 siblings, 0 replies; 171+ messages in thread
From: kbuild test robot @ 2017-05-26  3:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc2 next-20170525]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-legacy-ISA-I-O-support/20170526-033719
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `lpc_host_io_setup':
>> hisi_lpc.c:(.text+0x252): undefined reference to `acpi_set_logic_pio_resource'
   drivers/built-in.o: In function `acpi_scan_init':
   (.init.text+0x6742): undefined reference to `acpi_indirectio_scan_init'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 47743 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170526/1912511c/attachment-0001.gz>

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 6/7] LPC: Add the ACPI LPC support
  2017-05-26  3:12     ` kbuild test robot
  (?)
  (?)
@ 2017-05-26 10:12       ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-26 10:12 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, frowand.list,
	bhelgaas, rafael, arnd, linux-arm-kernel, lorenzo.pieralisi,
	mark.rutland, brian.starkey, olof, benh, linux-kernel

[...]

> Hi zhichang.yuan,
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.12-rc2 next-20170525]
> [if your patch is applied to the wrong git tree, please drop us a note
> to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-
> legacy-ISA-I-O-support/20170526-033719
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 6.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/01org/lkp-
> tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=ia64
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/built-in.o: In function `lpc_host_io_setup':
> >> hisi_lpc.c:(.text+0x252): undefined reference to
> `acpi_set_logic_pio_resource'
>    drivers/built-in.o: In function `acpi_scan_init':
>    (.init.text+0x6742): undefined reference to
> `acpi_indirectio_scan_init'

I believe the problem is in patch 4/7

config HISILICON_LPC
	bool "Support for ISA I/O space on Hisilicon Hip0X"
	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
                                         ^^^^^^^^^^^^

the COMPILE_TEST above allowing HISILICON_LPC also for other architectures. 
I think we can remove "|| COMPILE_TEST"...I will fix it in v10

Gab

+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.

> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology
> Center
> https://lists.01.org/pipermail/kbuild-all                   Intel
> Corporation

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-26 10:12       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-26 10:12 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, frowand.list,
	bhelgaas, rafael, arnd, linux-arm-kernel, lorenzo.pieralisi,
	mark.rutland, brian.starkey, olof, benh, linux-kernel,
	linux-acpi, Linuxarm, linux-pci, minyard, John Garry, xuwei (O),
	zhichang.yuan

[...]

> Hi zhichang.yuan,
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.12-rc2 next-20170525]
> [if your patch is applied to the wrong git tree, please drop us a note
> to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-
> legacy-ISA-I-O-support/20170526-033719
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 6.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/01org/lkp-
> tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=ia64
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/built-in.o: In function `lpc_host_io_setup':
> >> hisi_lpc.c:(.text+0x252): undefined reference to
> `acpi_set_logic_pio_resource'
>    drivers/built-in.o: In function `acpi_scan_init':
>    (.init.text+0x6742): undefined reference to
> `acpi_indirectio_scan_init'

I believe the problem is in patch 4/7

config HISILICON_LPC
	bool "Support for ISA I/O space on Hisilicon Hip0X"
	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
                                         ^^^^^^^^^^^^

the COMPILE_TEST above allowing HISILICON_LPC also for other architectures. 
I think we can remove "|| COMPILE_TEST"...I will fix it in v10

Gab

+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.

> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology
> Center
> https://lists.01.org/pipermail/kbuild-all                   Intel
> Corporation

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-26 10:12       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-26 10:12 UTC (permalink / raw)
  To: kbuild test robot
  Cc: mark.rutland, benh, rafael, linux-pci, will.deacon, Linuxarm,
	frowand.list, lorenzo.pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, linux-arm-kernel, linux-kernel, zhichang.yuan,
	kbuild-all, olof, brian.starkey

[...]

> Hi zhichang.yuan,
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.12-rc2 next-20170525]
> [if your patch is applied to the wrong git tree, please drop us a note
> to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-
> legacy-ISA-I-O-support/20170526-033719
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 6.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/01org/lkp-
> tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=ia64
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/built-in.o: In function `lpc_host_io_setup':
> >> hisi_lpc.c:(.text+0x252): undefined reference to
> `acpi_set_logic_pio_resource'
>    drivers/built-in.o: In function `acpi_scan_init':
>    (.init.text+0x6742): undefined reference to
> `acpi_indirectio_scan_init'

I believe the problem is in patch 4/7

config HISILICON_LPC
	bool "Support for ISA I/O space on Hisilicon Hip0X"
	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
                                         ^^^^^^^^^^^^

the COMPILE_TEST above allowing HISILICON_LPC also for other architectures. 
I think we can remove "|| COMPILE_TEST"...I will fix it in v10

Gab

+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.

> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology
> Center
> https://lists.01.org/pipermail/kbuild-all                   Intel
> Corporation

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 6/7] LPC: Add the ACPI LPC support
@ 2017-05-26 10:12       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-26 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

[...]

> Hi zhichang.yuan,
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.12-rc2 next-20170525]
> [if your patch is applied to the wrong git tree, please drop us a note
> to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Gabriele-Paoloni/LPC-
> legacy-ISA-I-O-support/20170526-033719
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 6.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/01org/lkp-
> tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=ia64
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/built-in.o: In function `lpc_host_io_setup':
> >> hisi_lpc.c:(.text+0x252): undefined reference to
> `acpi_set_logic_pio_resource'
>    drivers/built-in.o: In function `acpi_scan_init':
>    (.init.text+0x6742): undefined reference to
> `acpi_indirectio_scan_init'

I believe the problem is in patch 4/7

config HISILICON_LPC
	bool "Support for ISA I/O space on Hisilicon Hip0X"
	depends on (ARM64 && ARCH_HISI) || COMPILE_TEST
                                         ^^^^^^^^^^^^

the COMPILE_TEST above allowing HISILICON_LPC also for other architectures. 
I think we can remove "|| COMPILE_TEST"...I will fix it in v10

Gab

+	select LOGIC_PIO
+	select INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.

> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology
> Center
> https://lists.01.org/pipermail/kbuild-all                   Intel
> Corporation

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
  2017-05-25 11:37   ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-26 20:57     ` Bjorn Helgaas
  -1 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 20:57 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, lorenzo.pieralisi, minyard, arnd, rafael,
	linux-pci, catalin.marinas, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, linux-acpi, robh+dt,
	zhichang.yuan, benh, bhelgaas, frowand.list, brian.starkey,
	linux-arm-kernel, olof

On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> pci_pio_to_address()")' a new I/O space management was supported. With that
> driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
> can be mapped to logical PIO, converted easily between CPU address and the
> corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
> in a memory read/write way through the unified in/out accessors.
> 
> But on some archs/platforms, there are bus hosts which access I/O
> peripherals with host-local I/O port addresses rather than memory
> addresses after memory-mapped.
> To support those devices, a more generic I/O mapping method is introduced
> here. Through this patch, both the CPU addresses and the host-local port
> can be mapped into the logical PIO space with different logical/fake PIOs.
> After this, all the I/O accesses to either PCI MMIO devices or host-local
> I/O peripherals can be unified into the existing I/O accessors defined in
> asm-generic/io.h and be redirected to the right device-specific hooks
> based on the input logical PIO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  include/asm-generic/io.h  |  50 +++++++++
>  include/linux/logic_pio.h | 110 ++++++++++++++++++
>  lib/Kconfig               |  26 +++++
>  lib/Makefile              |   2 +
>  lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 468 insertions(+)
>  create mode 100644 include/linux/logic_pio.h
>  create mode 100644 lib/logic_pio.c
> 
> diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> index 7ef015e..f7fbec3 100644
> --- a/include/asm-generic/io.h
> +++ b/include/asm-generic/io.h
> ...  

>  #ifndef inb
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inb logic_inb
> +#else
>  #define inb inb
>  static inline u8 inb(unsigned long addr)
>  {
>  	return readb(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif
>  
>  #ifndef inw
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inw logic_inw

Cosmetic: could these ifdefs all be collected in one place, e.g.,

  #ifdef CONFIG_INDIRECT_PIO
  #define inb logic_inb
  #define inw logic_inw
  #define inl logic_inl
  ...
  #endif

to avoid cluttering every one of the default definitions?  Could the
collection be in logic_pio.h itself, next to the extern declarations?

> +#else
>  #define inw inw
>  static inline u16 inw(unsigned long addr)
>  {
>  	return readw(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif

>  #ifndef insb_p
> diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> new file mode 100644
> index 0000000..8e4dc65
> --- /dev/null
> +++ b/include/linux/logic_pio.h
> ...

> +extern u8 logic_inb(unsigned long addr);

I think you only build the definitions for these if
CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
too.

In PCI code, I omit the "extern" from function declarations.  This
isn't PCI code, and I don't know if there's a real consensus on this,
but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
function prototypes in <asm/proto.h>")

> +#ifdef CONFIG_LOGIC_PIO
> +extern struct logic_pio_hwaddr
> +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);

If you have to split the line (this one would fit without the
"extern"), the "*" goes with the type, e.g.,

  struct logic_pio_hwaddr *
  find_io_range_by_fwnode(struct fwnode_handle *fwnode);

More occurrences below.

> diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> new file mode 100644
> index 0000000..4a960cd
> --- /dev/null
> +++ b/lib/logic_pio.c
> ...

> +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> +#define BUILD_LOGIC_PIO(bw, type)\
> +type logic_in##bw(unsigned long addr)\
> +{\
> +	type ret = -1;\
> +\
> +	if (addr < MMIO_UPPER_LIMIT) {\
> +		ret = read##bw(PCI_IOBASE + addr);\
> +	} else {\
> +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> +\
> +		if (entry && entry->ops)\
> +			ret = entry->ops->pfin(entry->devpara,\
> +					addr, sizeof(type));\
> +		else\
> +			WARN_ON_ONCE(1);\
> +	}	\
> +	return ret;\
> +}	\

I think these would be slightly easier to read if the line continuation
backslashes were aligned at the right, as with
ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
etc.

Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-26 20:57     ` Bjorn Helgaas
  0 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 20:57 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, john.garry, linux-kernel, xuwei5, linuxarm,
	linux-acpi, zhichang.yuan, linux-pci, olof, brian.starkey

On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> pci_pio_to_address()")' a new I/O space management was supported. With that
> driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
> can be mapped to logical PIO, converted easily between CPU address and the
> corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
> in a memory read/write way through the unified in/out accessors.
> 
> But on some archs/platforms, there are bus hosts which access I/O
> peripherals with host-local I/O port addresses rather than memory
> addresses after memory-mapped.
> To support those devices, a more generic I/O mapping method is introduced
> here. Through this patch, both the CPU addresses and the host-local port
> can be mapped into the logical PIO space with different logical/fake PIOs.
> After this, all the I/O accesses to either PCI MMIO devices or host-local
> I/O peripherals can be unified into the existing I/O accessors defined in
> asm-generic/io.h and be redirected to the right device-specific hooks
> based on the input logical PIO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  include/asm-generic/io.h  |  50 +++++++++
>  include/linux/logic_pio.h | 110 ++++++++++++++++++
>  lib/Kconfig               |  26 +++++
>  lib/Makefile              |   2 +
>  lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 468 insertions(+)
>  create mode 100644 include/linux/logic_pio.h
>  create mode 100644 lib/logic_pio.c
> 
> diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> index 7ef015e..f7fbec3 100644
> --- a/include/asm-generic/io.h
> +++ b/include/asm-generic/io.h
> ...  

>  #ifndef inb
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inb logic_inb
> +#else
>  #define inb inb
>  static inline u8 inb(unsigned long addr)
>  {
>  	return readb(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif
>  
>  #ifndef inw
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inw logic_inw

Cosmetic: could these ifdefs all be collected in one place, e.g.,

  #ifdef CONFIG_INDIRECT_PIO
  #define inb logic_inb
  #define inw logic_inw
  #define inl logic_inl
  ...
  #endif

to avoid cluttering every one of the default definitions?  Could the
collection be in logic_pio.h itself, next to the extern declarations?

> +#else
>  #define inw inw
>  static inline u16 inw(unsigned long addr)
>  {
>  	return readw(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif

>  #ifndef insb_p
> diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> new file mode 100644
> index 0000000..8e4dc65
> --- /dev/null
> +++ b/include/linux/logic_pio.h
> ...

> +extern u8 logic_inb(unsigned long addr);

I think you only build the definitions for these if
CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
too.

In PCI code, I omit the "extern" from function declarations.  This
isn't PCI code, and I don't know if there's a real consensus on this,
but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
function prototypes in <asm/proto.h>")

> +#ifdef CONFIG_LOGIC_PIO
> +extern struct logic_pio_hwaddr
> +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);

If you have to split the line (this one would fit without the
"extern"), the "*" goes with the type, e.g.,

  struct logic_pio_hwaddr *
  find_io_range_by_fwnode(struct fwnode_handle *fwnode);

More occurrences below.

> diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> new file mode 100644
> index 0000000..4a960cd
> --- /dev/null
> +++ b/lib/logic_pio.c
> ...

> +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> +#define BUILD_LOGIC_PIO(bw, type)\
> +type logic_in##bw(unsigned long addr)\
> +{\
> +	type ret = -1;\
> +\
> +	if (addr < MMIO_UPPER_LIMIT) {\
> +		ret = read##bw(PCI_IOBASE + addr);\
> +	} else {\
> +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> +\
> +		if (entry && entry->ops)\
> +			ret = entry->ops->pfin(entry->devpara,\
> +					addr, sizeof(type));\
> +		else\
> +			WARN_ON_ONCE(1);\
> +	}	\
> +	return ret;\
> +}	\

I think these would be slightly easier to read if the line continuation
backslashes were aligned at the right, as with
ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
etc.

Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-26 20:57     ` Bjorn Helgaas
  0 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 20:57 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, lorenzo.pieralisi, minyard, arnd, rafael,
	linux-pci, catalin.marinas, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, linux-acpi, robh+dt,
	zhichang.yuan, benh, bhelgaas, frowand.list, brian.starkey,
	linux-arm-kernel, olof

On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> pci_pio_to_address()")' a new I/O space management was supported. With that
> driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
> can be mapped to logical PIO, converted easily between CPU address and the
> corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
> in a memory read/write way through the unified in/out accessors.
> 
> But on some archs/platforms, there are bus hosts which access I/O
> peripherals with host-local I/O port addresses rather than memory
> addresses after memory-mapped.
> To support those devices, a more generic I/O mapping method is introduced
> here. Through this patch, both the CPU addresses and the host-local port
> can be mapped into the logical PIO space with different logical/fake PIOs.
> After this, all the I/O accesses to either PCI MMIO devices or host-local
> I/O peripherals can be unified into the existing I/O accessors defined in
> asm-generic/io.h and be redirected to the right device-specific hooks
> based on the input logical PIO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  include/asm-generic/io.h  |  50 +++++++++
>  include/linux/logic_pio.h | 110 ++++++++++++++++++
>  lib/Kconfig               |  26 +++++
>  lib/Makefile              |   2 +
>  lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 468 insertions(+)
>  create mode 100644 include/linux/logic_pio.h
>  create mode 100644 lib/logic_pio.c
> 
> diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> index 7ef015e..f7fbec3 100644
> --- a/include/asm-generic/io.h
> +++ b/include/asm-generic/io.h
> ...  

>  #ifndef inb
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inb logic_inb
> +#else
>  #define inb inb
>  static inline u8 inb(unsigned long addr)
>  {
>  	return readb(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif
>  
>  #ifndef inw
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inw logic_inw

Cosmetic: could these ifdefs all be collected in one place, e.g.,

  #ifdef CONFIG_INDIRECT_PIO
  #define inb logic_inb
  #define inw logic_inw
  #define inl logic_inl
  ...
  #endif

to avoid cluttering every one of the default definitions?  Could the
collection be in logic_pio.h itself, next to the extern declarations?

> +#else
>  #define inw inw
>  static inline u16 inw(unsigned long addr)
>  {
>  	return readw(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif

>  #ifndef insb_p
> diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> new file mode 100644
> index 0000000..8e4dc65
> --- /dev/null
> +++ b/include/linux/logic_pio.h
> ...

> +extern u8 logic_inb(unsigned long addr);

I think you only build the definitions for these if
CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
too.

In PCI code, I omit the "extern" from function declarations.  This
isn't PCI code, and I don't know if there's a real consensus on this,
but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
function prototypes in <asm/proto.h>")

> +#ifdef CONFIG_LOGIC_PIO
> +extern struct logic_pio_hwaddr
> +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);

If you have to split the line (this one would fit without the
"extern"), the "*" goes with the type, e.g.,

  struct logic_pio_hwaddr *
  find_io_range_by_fwnode(struct fwnode_handle *fwnode);

More occurrences below.

> diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> new file mode 100644
> index 0000000..4a960cd
> --- /dev/null
> +++ b/lib/logic_pio.c
> ...

> +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> +#define BUILD_LOGIC_PIO(bw, type)\
> +type logic_in##bw(unsigned long addr)\
> +{\
> +	type ret = -1;\
> +\
> +	if (addr < MMIO_UPPER_LIMIT) {\
> +		ret = read##bw(PCI_IOBASE + addr);\
> +	} else {\
> +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> +\
> +		if (entry && entry->ops)\
> +			ret = entry->ops->pfin(entry->devpara,\
> +					addr, sizeof(type));\
> +		else\
> +			WARN_ON_ONCE(1);\
> +	}	\
> +	return ret;\
> +}	\

I think these would be slightly easier to read if the line continuation
backslashes were aligned at the right, as with
ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
etc.

Bjorn

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-26 20:57     ` Bjorn Helgaas
  0 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 20:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> pci_pio_to_address()")' a new I/O space management was supported. With that
> driver, the I/O ranges configured for PCI/PCIE hosts on some architectures
> can be mapped to logical PIO, converted easily between CPU address and the
> corresponding logicial PIO. Based on this, PCI I/O devices can be accessed
> in a memory read/write way through the unified in/out accessors.
> 
> But on some archs/platforms, there are bus hosts which access I/O
> peripherals with host-local I/O port addresses rather than memory
> addresses after memory-mapped.
> To support those devices, a more generic I/O mapping method is introduced
> here. Through this patch, both the CPU addresses and the host-local port
> can be mapped into the logical PIO space with different logical/fake PIOs.
> After this, all the I/O accesses to either PCI MMIO devices or host-local
> I/O peripherals can be unified into the existing I/O accessors defined in
> asm-generic/io.h and be redirected to the right device-specific hooks
> based on the input logical PIO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  include/asm-generic/io.h  |  50 +++++++++
>  include/linux/logic_pio.h | 110 ++++++++++++++++++
>  lib/Kconfig               |  26 +++++
>  lib/Makefile              |   2 +
>  lib/logic_pio.c           | 280 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 468 insertions(+)
>  create mode 100644 include/linux/logic_pio.h
>  create mode 100644 lib/logic_pio.c
> 
> diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> index 7ef015e..f7fbec3 100644
> --- a/include/asm-generic/io.h
> +++ b/include/asm-generic/io.h
> ...  

>  #ifndef inb
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inb logic_inb
> +#else
>  #define inb inb
>  static inline u8 inb(unsigned long addr)
>  {
>  	return readb(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif
>  
>  #ifndef inw
> +#ifdef CONFIG_INDIRECT_PIO
> +#define inw logic_inw

Cosmetic: could these ifdefs all be collected in one place, e.g.,

  #ifdef CONFIG_INDIRECT_PIO
  #define inb logic_inb
  #define inw logic_inw
  #define inl logic_inl
  ...
  #endif

to avoid cluttering every one of the default definitions?  Could the
collection be in logic_pio.h itself, next to the extern declarations?

> +#else
>  #define inw inw
>  static inline u16 inw(unsigned long addr)
>  {
>  	return readw(PCI_IOBASE + addr);
>  }
> +#endif /* CONFIG_INDIRECT_PIO */
>  #endif

>  #ifndef insb_p
> diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> new file mode 100644
> index 0000000..8e4dc65
> --- /dev/null
> +++ b/include/linux/logic_pio.h
> ...

> +extern u8 logic_inb(unsigned long addr);

I think you only build the definitions for these if
CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
too.

In PCI code, I omit the "extern" from function declarations.  This
isn't PCI code, and I don't know if there's a real consensus on this,
but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
function prototypes in <asm/proto.h>")

> +#ifdef CONFIG_LOGIC_PIO
> +extern struct logic_pio_hwaddr
> +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);

If you have to split the line (this one would fit without the
"extern"), the "*" goes with the type, e.g.,

  struct logic_pio_hwaddr *
  find_io_range_by_fwnode(struct fwnode_handle *fwnode);

More occurrences below.

> diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> new file mode 100644
> index 0000000..4a960cd
> --- /dev/null
> +++ b/lib/logic_pio.c
> ...

> +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> +#define BUILD_LOGIC_PIO(bw, type)\
> +type logic_in##bw(unsigned long addr)\
> +{\
> +	type ret = -1;\
> +\
> +	if (addr < MMIO_UPPER_LIMIT) {\
> +		ret = read##bw(PCI_IOBASE + addr);\
> +	} else {\
> +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> +\
> +		if (entry && entry->ops)\
> +			ret = entry->ops->pfin(entry->devpara,\
> +					addr, sizeof(type));\
> +		else\
> +			WARN_ON_ONCE(1);\
> +	}	\
> +	return ret;\
> +}	\

I think these would be slightly easier to read if the line continuation
backslashes were aligned at the right, as with
ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
etc.

Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
  2017-05-25 11:37   ` Gabriele Paoloni
  (?)
  (?)
@ 2017-05-26 21:20     ` Bjorn Helgaas
  -1 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 21:20 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, lorenzo.pieralisi, minyard, arnd, rafael,
	linux-pci, catalin.marinas, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, linux-acpi, robh+dt,
	zhichang.yuan, benh, bhelgaas, frowand.list, brian.starkey,
	linux-arm-kernel, olof

On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> After introducing the new generic I/O space management(LOGIC_IO), the
> original PCI MMIO relevant helpers need to be updated based on the new
> interfaces defined in LOGIC_IO.
> This patch adapts the corresponding code to match the changes introduced
> by LOGIC_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft

Not sure how you plan to merge this, but here's my ack:

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

If you split this as suggested below, add my ack to all three patches.

> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b01bd5b..c9fe12b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
>...

> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
> +			resource_size_t	size)

It's trivial and nit-picky, but I would do the __weak removal in its
own patch.  It's obviously fine because there's only one
implementation, but it's unrelated to the main point of this patch.

I would split the signature change (fwnode addition) to a separate
patch, too, just to make the actual change more obvious, especially
since that's the only part that crosses subsystems (ACPI, PCI, OF).

>  {
> -	int err = 0;
> -
> +	int ret = 0;
>  #ifdef PCI_IOBASE
> -	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> -
> -	/* check if the range hasn't been previously recorded */
> -	spin_lock(&io_range_lock);
> -	list_for_each_entry(range, &io_range_list, list) {
> -		if (addr >= range->start && addr + size <= range->start + size) {
> -			/* range already registered, bail out */
> -			goto end_register;
> -		}
> -		allocated_size += range->size;
> -	}
> -
> -	/* range not registed yet, check for available space */
> -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> -		/* if it's too big check if 64K space can be reserved */
> -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> -			err = -E2BIG;
> -			goto end_register;
> -		}
> -
> -		size = SZ_64K;
> -		pr_warn("Requested IO range too big, new size set to 64K\n");
> -	}
> +	struct logic_pio_hwaddr *range;
>  
> -	/* add the range to the list */
> -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> -	if (!range) {
> -		err = -ENOMEM;
> -		goto end_register;
> -	}
> +	if (!size || addr + size < addr)
> +		return -EINVAL;
>  
> -	range->start = addr;
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;

Add a blank line here.

> +	range->fwnode = fwnode;
>  	range->size = size;
> +	range->hw_start = addr;
> +	range->flags = PIO_CPU_MMIO;
>  
> -	list_add_tail(&range->list, &io_range_list);
> -
> -end_register:
> -	spin_unlock(&io_range_lock);
> +	ret = logic_pio_register_range(range);
> +	if (ret)
> +		kfree(range);
>  #endif
>  
> -	return err;
> +	return ret;
>  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-26 21:20     ` Bjorn Helgaas
  0 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 21:20 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, john.garry, linux-kernel, xuwei5, linuxarm,
	linux-acpi, zhichang.yuan, linux-pci, olof, brian.starkey

On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> After introducing the new generic I/O space management(LOGIC_IO), the
> original PCI MMIO relevant helpers need to be updated based on the new
> interfaces defined in LOGIC_IO.
> This patch adapts the corresponding code to match the changes introduced
> by LOGIC_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft

Not sure how you plan to merge this, but here's my ack:

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

If you split this as suggested below, add my ack to all three patches.

> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b01bd5b..c9fe12b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
>...

> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
> +			resource_size_t	size)

It's trivial and nit-picky, but I would do the __weak removal in its
own patch.  It's obviously fine because there's only one
implementation, but it's unrelated to the main point of this patch.

I would split the signature change (fwnode addition) to a separate
patch, too, just to make the actual change more obvious, especially
since that's the only part that crosses subsystems (ACPI, PCI, OF).

>  {
> -	int err = 0;
> -
> +	int ret = 0;
>  #ifdef PCI_IOBASE
> -	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> -
> -	/* check if the range hasn't been previously recorded */
> -	spin_lock(&io_range_lock);
> -	list_for_each_entry(range, &io_range_list, list) {
> -		if (addr >= range->start && addr + size <= range->start + size) {
> -			/* range already registered, bail out */
> -			goto end_register;
> -		}
> -		allocated_size += range->size;
> -	}
> -
> -	/* range not registed yet, check for available space */
> -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> -		/* if it's too big check if 64K space can be reserved */
> -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> -			err = -E2BIG;
> -			goto end_register;
> -		}
> -
> -		size = SZ_64K;
> -		pr_warn("Requested IO range too big, new size set to 64K\n");
> -	}
> +	struct logic_pio_hwaddr *range;
>  
> -	/* add the range to the list */
> -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> -	if (!range) {
> -		err = -ENOMEM;
> -		goto end_register;
> -	}
> +	if (!size || addr + size < addr)
> +		return -EINVAL;
>  
> -	range->start = addr;
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;

Add a blank line here.

> +	range->fwnode = fwnode;
>  	range->size = size;
> +	range->hw_start = addr;
> +	range->flags = PIO_CPU_MMIO;
>  
> -	list_add_tail(&range->list, &io_range_list);
> -
> -end_register:
> -	spin_unlock(&io_range_lock);
> +	ret = logic_pio_register_range(range);
> +	if (ret)
> +		kfree(range);
>  #endif
>  
> -	return err;
> +	return ret;
>  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-26 21:20     ` Bjorn Helgaas
  0 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 21:20 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, lorenzo.pieralisi, minyard, arnd, rafael,
	linux-pci, catalin.marinas, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, linux-acpi, robh+dt,
	zhichang.yuan, benh, bhelgaas, frowand.list, brian.starkey,
	linux-arm-kernel, olof

On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> After introducing the new generic I/O space management(LOGIC_IO), the
> original PCI MMIO relevant helpers need to be updated based on the new
> interfaces defined in LOGIC_IO.
> This patch adapts the corresponding code to match the changes introduced
> by LOGIC_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft

Not sure how you plan to merge this, but here's my ack:

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

If you split this as suggested below, add my ack to all three patches.

> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b01bd5b..c9fe12b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
>...

> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
> +			resource_size_t	size)

It's trivial and nit-picky, but I would do the __weak removal in its
own patch.  It's obviously fine because there's only one
implementation, but it's unrelated to the main point of this patch.

I would split the signature change (fwnode addition) to a separate
patch, too, just to make the actual change more obvious, especially
since that's the only part that crosses subsystems (ACPI, PCI, OF).

>  {
> -	int err = 0;
> -
> +	int ret = 0;
>  #ifdef PCI_IOBASE
> -	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> -
> -	/* check if the range hasn't been previously recorded */
> -	spin_lock(&io_range_lock);
> -	list_for_each_entry(range, &io_range_list, list) {
> -		if (addr >= range->start && addr + size <= range->start + size) {
> -			/* range already registered, bail out */
> -			goto end_register;
> -		}
> -		allocated_size += range->size;
> -	}
> -
> -	/* range not registed yet, check for available space */
> -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> -		/* if it's too big check if 64K space can be reserved */
> -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> -			err = -E2BIG;
> -			goto end_register;
> -		}
> -
> -		size = SZ_64K;
> -		pr_warn("Requested IO range too big, new size set to 64K\n");
> -	}
> +	struct logic_pio_hwaddr *range;
>  
> -	/* add the range to the list */
> -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> -	if (!range) {
> -		err = -ENOMEM;
> -		goto end_register;
> -	}
> +	if (!size || addr + size < addr)
> +		return -EINVAL;
>  
> -	range->start = addr;
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;

Add a blank line here.

> +	range->fwnode = fwnode;
>  	range->size = size;
> +	range->hw_start = addr;
> +	range->flags = PIO_CPU_MMIO;
>  
> -	list_add_tail(&range->list, &io_range_list);
> -
> -end_register:
> -	spin_unlock(&io_range_lock);
> +	ret = logic_pio_register_range(range);
> +	if (ret)
> +		kfree(range);
>  #endif
>  
> -	return err;
> +	return ret;
>  }

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-26 21:20     ` Bjorn Helgaas
  0 siblings, 0 replies; 171+ messages in thread
From: Bjorn Helgaas @ 2017-05-26 21:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> After introducing the new generic I/O space management(LOGIC_IO), the
> original PCI MMIO relevant helpers need to be updated based on the new
> interfaces defined in LOGIC_IO.
> This patch adapts the corresponding code to match the changes introduced
> by LOGIC_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft

Not sure how you plan to merge this, but here's my ack:

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

If you split this as suggested below, add my ack to all three patches.

> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b01bd5b..c9fe12b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
>...

> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
> +			resource_size_t	size)

It's trivial and nit-picky, but I would do the __weak removal in its
own patch.  It's obviously fine because there's only one
implementation, but it's unrelated to the main point of this patch.

I would split the signature change (fwnode addition) to a separate
patch, too, just to make the actual change more obvious, especially
since that's the only part that crosses subsystems (ACPI, PCI, OF).

>  {
> -	int err = 0;
> -
> +	int ret = 0;
>  #ifdef PCI_IOBASE
> -	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> -
> -	/* check if the range hasn't been previously recorded */
> -	spin_lock(&io_range_lock);
> -	list_for_each_entry(range, &io_range_list, list) {
> -		if (addr >= range->start && addr + size <= range->start + size) {
> -			/* range already registered, bail out */
> -			goto end_register;
> -		}
> -		allocated_size += range->size;
> -	}
> -
> -	/* range not registed yet, check for available space */
> -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> -		/* if it's too big check if 64K space can be reserved */
> -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> -			err = -E2BIG;
> -			goto end_register;
> -		}
> -
> -		size = SZ_64K;
> -		pr_warn("Requested IO range too big, new size set to 64K\n");
> -	}
> +	struct logic_pio_hwaddr *range;
>  
> -	/* add the range to the list */
> -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> -	if (!range) {
> -		err = -ENOMEM;
> -		goto end_register;
> -	}
> +	if (!size || addr + size < addr)
> +		return -EINVAL;
>  
> -	range->start = addr;
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;

Add a blank line here.

> +	range->fwnode = fwnode;
>  	range->size = size;
> +	range->hw_start = addr;
> +	range->flags = PIO_CPU_MMIO;
>  
> -	list_add_tail(&range->list, &io_range_list);
> -
> -end_register:
> -	spin_unlock(&io_range_lock);
> +	ret = logic_pio_register_range(range);
> +	if (ret)
> +		kfree(range);
>  #endif
>  
> -	return err;
> +	return ret;
>  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
  2017-05-26 21:20     ` Bjorn Helgaas
  (?)
  (?)
@ 2017-05-30  8:12       ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30  8:12 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, John Garry, linux-kernel, xuwei (O),
	Linuxarm, linux-acpi

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 22:20
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management
> on PCI IO hosts
> 
> On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > After introducing the new generic I/O space management(LOGIC_IO), the
> > original PCI MMIO relevant helpers need to be updated based on the
> new
> > interfaces defined in LOGIC_IO.
> > This patch adapts the corresponding code to match the changes
> introduced
> > by LOGIC_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
> 
> Not sure how you plan to merge this, but here's my ack:
> 
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>

Many thanks for your Ack :)

Maybe Arnd can take the whole patchset (or just the lib framework + DT part
leaving the ACPI part to Lorenzo)....?

> 
> If you split this as suggested below, add my ack to all three patches.

Sure I will

> 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index b01bd5b..c9fe12b 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> >...
> 
> > -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t
> size)
> > +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t
> addr,
> > +			resource_size_t	size)
> 
> It's trivial and nit-picky, but I would do the __weak removal in its
> own patch.  It's obviously fine because there's only one
> implementation, but it's unrelated to the main point of this patch.

Agreed

> 
> I would split the signature change (fwnode addition) to a separate
> patch, too, just to make the actual change more obvious, especially
> since that's the only part that crosses subsystems (ACPI, PCI, OF).

Agreed too

> 
> >  {
> > -	int err = 0;
> > -
> > +	int ret = 0;
> >  #ifdef PCI_IOBASE
> > -	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > -
> > -	/* check if the range hasn't been previously recorded */
> > -	spin_lock(&io_range_lock);
> > -	list_for_each_entry(range, &io_range_list, list) {
> > -		if (addr >= range->start && addr + size <= range->start +
> size) {
> > -			/* range already registered, bail out */
> > -			goto end_register;
> > -		}
> > -		allocated_size += range->size;
> > -	}
> > -
> > -	/* range not registed yet, check for available space */
> > -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> > -		/* if it's too big check if 64K space can be reserved */
> > -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> > -			err = -E2BIG;
> > -			goto end_register;
> > -		}
> > -
> > -		size = SZ_64K;
> > -		pr_warn("Requested IO range too big, new size set to
> 64K\n");
> > -	}
> > +	struct logic_pio_hwaddr *range;
> >
> > -	/* add the range to the list */
> > -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> > -	if (!range) {
> > -		err = -ENOMEM;
> > -		goto end_register;
> > -	}
> > +	if (!size || addr + size < addr)
> > +		return -EINVAL;
> >
> > -	range->start = addr;
> > +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> > +	if (!range)
> > +		return -ENOMEM;
> 
> Add a blank line here.

Yep I will

Cheers
Gab

> 
> > +	range->fwnode = fwnode;
> >  	range->size = size;
> > +	range->hw_start = addr;
> > +	range->flags = PIO_CPU_MMIO;
> >
> > -	list_add_tail(&range->list, &io_range_list);
> > -
> > -end_register:
> > -	spin_unlock(&io_range_lock);
> > +	ret = logic_pio_register_range(range);
> > +	if (ret)
> > +		kfree(range);
> >  #endif
> >
> > -	return err;
> > +	return ret;
> >  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-30  8:12       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30  8:12 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, John Garry, linux-kernel, xuwei (O),
	Linuxarm, linux-acpi, zhichang.yuan, linux-pci, olof,
	brian.starkey

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 22:20
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management
> on PCI IO hosts
> 
> On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > After introducing the new generic I/O space management(LOGIC_IO), the
> > original PCI MMIO relevant helpers need to be updated based on the
> new
> > interfaces defined in LOGIC_IO.
> > This patch adapts the corresponding code to match the changes
> introduced
> > by LOGIC_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
> 
> Not sure how you plan to merge this, but here's my ack:
> 
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>

Many thanks for your Ack :)

Maybe Arnd can take the whole patchset (or just the lib framework + DT part
leaving the ACPI part to Lorenzo)....?

> 
> If you split this as suggested below, add my ack to all three patches.

Sure I will

> 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index b01bd5b..c9fe12b 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> >...
> 
> > -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t
> size)
> > +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t
> addr,
> > +			resource_size_t	size)
> 
> It's trivial and nit-picky, but I would do the __weak removal in its
> own patch.  It's obviously fine because there's only one
> implementation, but it's unrelated to the main point of this patch.

Agreed

> 
> I would split the signature change (fwnode addition) to a separate
> patch, too, just to make the actual change more obvious, especially
> since that's the only part that crosses subsystems (ACPI, PCI, OF).

Agreed too

> 
> >  {
> > -	int err = 0;
> > -
> > +	int ret = 0;
> >  #ifdef PCI_IOBASE
> > -	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > -
> > -	/* check if the range hasn't been previously recorded */
> > -	spin_lock(&io_range_lock);
> > -	list_for_each_entry(range, &io_range_list, list) {
> > -		if (addr >= range->start && addr + size <= range->start +
> size) {
> > -			/* range already registered, bail out */
> > -			goto end_register;
> > -		}
> > -		allocated_size += range->size;
> > -	}
> > -
> > -	/* range not registed yet, check for available space */
> > -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> > -		/* if it's too big check if 64K space can be reserved */
> > -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> > -			err = -E2BIG;
> > -			goto end_register;
> > -		}
> > -
> > -		size = SZ_64K;
> > -		pr_warn("Requested IO range too big, new size set to
> 64K\n");
> > -	}
> > +	struct logic_pio_hwaddr *range;
> >
> > -	/* add the range to the list */
> > -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> > -	if (!range) {
> > -		err = -ENOMEM;
> > -		goto end_register;
> > -	}
> > +	if (!size || addr + size < addr)
> > +		return -EINVAL;
> >
> > -	range->start = addr;
> > +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> > +	if (!range)
> > +		return -ENOMEM;
> 
> Add a blank line here.

Yep I will

Cheers
Gab

> 
> > +	range->fwnode = fwnode;
> >  	range->size = size;
> > +	range->hw_start = addr;
> > +	range->flags = PIO_CPU_MMIO;
> >
> > -	list_add_tail(&range->list, &io_range_list);
> > -
> > -end_register:
> > -	spin_unlock(&io_range_lock);
> > +	ret = logic_pio_register_range(range);
> > +	if (ret)
> > +		kfree(range);
> >  #endif
> >
> > -	return err;
> > +	return ret;
> >  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-30  8:12       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30  8:12 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, John Garry, linux-kernel, xuwei (O),
	Linuxarm, linux-acpi, zhichang.yuan, linux-pci, olof,
	brian.starkey

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 22:20
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management
> on PCI IO hosts
> 
> On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > After introducing the new generic I/O space management(LOGIC_IO), the
> > original PCI MMIO relevant helpers need to be updated based on the
> new
> > interfaces defined in LOGIC_IO.
> > This patch adapts the corresponding code to match the changes
> introduced
> > by LOGIC_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
> 
> Not sure how you plan to merge this, but here's my ack:
> 
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>

Many thanks for your Ack :)

Maybe Arnd can take the whole patchset (or just the lib framework + DT part
leaving the ACPI part to Lorenzo)....?

> 
> If you split this as suggested below, add my ack to all three patches.

Sure I will

> 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index b01bd5b..c9fe12b 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> >...
> 
> > -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t
> size)
> > +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t
> addr,
> > +			resource_size_t	size)
> 
> It's trivial and nit-picky, but I would do the __weak removal in its
> own patch.  It's obviously fine because there's only one
> implementation, but it's unrelated to the main point of this patch.

Agreed

> 
> I would split the signature change (fwnode addition) to a separate
> patch, too, just to make the actual change more obvious, especially
> since that's the only part that crosses subsystems (ACPI, PCI, OF).

Agreed too

> 
> >  {
> > -	int err = 0;
> > -
> > +	int ret = 0;
> >  #ifdef PCI_IOBASE
> > -	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > -
> > -	/* check if the range hasn't been previously recorded */
> > -	spin_lock(&io_range_lock);
> > -	list_for_each_entry(range, &io_range_list, list) {
> > -		if (addr >= range->start && addr + size <= range->start +
> size) {
> > -			/* range already registered, bail out */
> > -			goto end_register;
> > -		}
> > -		allocated_size += range->size;
> > -	}
> > -
> > -	/* range not registed yet, check for available space */
> > -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> > -		/* if it's too big check if 64K space can be reserved */
> > -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> > -			err = -E2BIG;
> > -			goto end_register;
> > -		}
> > -
> > -		size = SZ_64K;
> > -		pr_warn("Requested IO range too big, new size set to
> 64K\n");
> > -	}
> > +	struct logic_pio_hwaddr *range;
> >
> > -	/* add the range to the list */
> > -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> > -	if (!range) {
> > -		err = -ENOMEM;
> > -		goto end_register;
> > -	}
> > +	if (!size || addr + size < addr)
> > +		return -EINVAL;
> >
> > -	range->start = addr;
> > +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> > +	if (!range)
> > +		return -ENOMEM;
> 
> Add a blank line here.

Yep I will

Cheers
Gab

> 
> > +	range->fwnode = fwnode;
> >  	range->size = size;
> > +	range->hw_start = addr;
> > +	range->flags = PIO_CPU_MMIO;
> >
> > -	list_add_tail(&range->list, &io_range_list);
> > -
> > -end_register:
> > -	spin_unlock(&io_range_lock);
> > +	ret = logic_pio_register_range(range);
> > +	if (ret)
> > +		kfree(range);
> >  #endif
> >
> > -	return err;
> > +	return ret;
> >  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
@ 2017-05-30  8:12       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30  8:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas at kernel.org]
> Sent: 26 May 2017 22:20
> To: Gabriele Paoloni
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; rafael at kernel.org;
> arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> lorenzo.pieralisi at arm.com; mark.rutland at arm.com; minyard at acm.org;
> benh at kernel.crashing.org; John Garry; linux-kernel at vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi at vger.kernel.org; zhichang.yuan; linux-
> pci at vger.kernel.org; olof at lixom.net; brian.starkey at arm.com
> Subject: Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management
> on PCI IO hosts
> 
> On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > After introducing the new generic I/O space management(LOGIC_IO), the
> > original PCI MMIO relevant helpers need to be updated based on the
> new
> > interfaces defined in LOGIC_IO.
> > This patch adapts the corresponding code to match the changes
> introduced
> > by LOGIC_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
> 
> Not sure how you plan to merge this, but here's my ack:
> 
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>

Many thanks for your Ack :)

Maybe Arnd can take the whole patchset (or just the lib framework + DT part
leaving the ACPI part to Lorenzo)....?

> 
> If you split this as suggested below, add my ack to all three patches.

Sure I will

> 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index b01bd5b..c9fe12b 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> >...
> 
> > -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t
> size)
> > +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t
> addr,
> > +			resource_size_t	size)
> 
> It's trivial and nit-picky, but I would do the __weak removal in its
> own patch.  It's obviously fine because there's only one
> implementation, but it's unrelated to the main point of this patch.

Agreed

> 
> I would split the signature change (fwnode addition) to a separate
> patch, too, just to make the actual change more obvious, especially
> since that's the only part that crosses subsystems (ACPI, PCI, OF).

Agreed too

> 
> >  {
> > -	int err = 0;
> > -
> > +	int ret = 0;
> >  #ifdef PCI_IOBASE
> > -	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > -
> > -	/* check if the range hasn't been previously recorded */
> > -	spin_lock(&io_range_lock);
> > -	list_for_each_entry(range, &io_range_list, list) {
> > -		if (addr >= range->start && addr + size <= range->start +
> size) {
> > -			/* range already registered, bail out */
> > -			goto end_register;
> > -		}
> > -		allocated_size += range->size;
> > -	}
> > -
> > -	/* range not registed yet, check for available space */
> > -	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> > -		/* if it's too big check if 64K space can be reserved */
> > -		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> > -			err = -E2BIG;
> > -			goto end_register;
> > -		}
> > -
> > -		size = SZ_64K;
> > -		pr_warn("Requested IO range too big, new size set to
> 64K\n");
> > -	}
> > +	struct logic_pio_hwaddr *range;
> >
> > -	/* add the range to the list */
> > -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> > -	if (!range) {
> > -		err = -ENOMEM;
> > -		goto end_register;
> > -	}
> > +	if (!size || addr + size < addr)
> > +		return -EINVAL;
> >
> > -	range->start = addr;
> > +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> > +	if (!range)
> > +		return -ENOMEM;
> 
> Add a blank line here.

Yep I will

Cheers
Gab

> 
> > +	range->fwnode = fwnode;
> >  	range->size = size;
> > +	range->hw_start = addr;
> > +	range->flags = PIO_CPU_MMIO;
> >
> > -	list_add_tail(&range->list, &io_range_list);
> > -
> > -end_register:
> > -	spin_unlock(&io_range_lock);
> > +	ret = logic_pio_register_range(range);
> > +	if (ret)
> > +		kfree(range);
> >  #endif
> >
> > -	return err;
> > +	return ret;
> >  }

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-05-25 11:37   ` Gabriele Paoloni
  (?)
@ 2017-05-30 13:24     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-05-30 13:24 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, mark.rutland, brian.starkey,
	olof, benh, linux-kernel, linux-acpi, linuxarm, linux-pci,
	minyard, john.garry, xuwei5

Hi Gab,

On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> From: Gabriele <gabriele.paoloni@huawei.com>
> 
> On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
> I/O with some special host-local I/O ports known on x86. As their I/O
> space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
> meant to support a new class of I/O host controllers where the local IO
> ports of the children devices are translated into the Indirect I/O address
> space.
> Through the handler attach callback, all the I/O translations are done
> before starting the enumeration on children devices and the translated
> addresses are replaced in the children resources.

I do not understand why this is done through a scan handler and to
be frank I do not see how this mechanism is supposed to be a generic
kernel layer, possibly used by other platforms, when there is no notion
in ACPI to cater for that.

As far as I am concerned this patch code should live in the Hisilicon
LPC driver - as things stand it is neither ACPI generic code nor ARM64
specific, it is code to make ACPI work like DT bindings without any ACPI
binding at all; I still have some concerns from an ACPI standpoint
below.

> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  drivers/acpi/arm64/Makefile            |   1 +
>  drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
>  drivers/acpi/internal.h                |   5 +
>  drivers/acpi/scan.c                    |   1 +
>  include/acpi/acpi_indirect_pio.h       |  24 +++
>  5 files changed, 332 insertions(+)
>  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
>  create mode 100644 include/acpi/acpi_indirect_pio.h
> 
> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
> index 1017def..3944775 100644
> --- a/drivers/acpi/arm64/Makefile
> +++ b/drivers/acpi/arm64/Makefile
> @@ -1,2 +1,3 @@
>  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
>  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
> new file mode 100644
> index 0000000..7813f73
> --- /dev/null
> +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> @@ -0,0 +1,301 @@
> +/*
> + * ACPI support for indirect-PIO bus.
> + *
> + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/platform_device.h>
> +#include <linux/logic_pio.h>
> +
> +#include <acpi/acpi_indirect_pio.h>
> +
> +ACPI_MODULE_NAME("indirect PIO");
> +
> +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> +
> +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> +					   void *data)
> +{
> +	int *res_cnt = data;
> +
> +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> +		(*res_cnt)++;
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
> +		void *data)
> +{
> +	struct acpi_resource **resource = data;
> +
> +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> +		memcpy((*resource), res, sizeof(struct acpi_resource));
> +		(*resource)->length = sizeof(struct acpi_resource);
> +		(*resource)->type = res->type;
> +		(*resource)++;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status
> +acpi_build_logicpiores_template(struct acpi_device *adev,
> +			struct acpi_buffer *buffer)
> +{
> +	acpi_handle handle = adev->handle;
> +	struct acpi_resource *resource;
> +	acpi_status status;
> +	int res_cnt = 0;
> +
> +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> +				     acpi_count_logic_iores, &res_cnt);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	if (!res_cnt) {
> +		dev_err(&adev->dev, "no logic IO resources\n");
> +		return -ENODEV;
> +	}
> +
> +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> +	if (!buffer->pointer)
> +		return -ENOMEM;
> +
> +	resource = (struct acpi_resource *)buffer->pointer;
> +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> +				     acpi_read_one_logicpiores, &resource);
> +	if (ACPI_FAILURE(status)) {
> +		kfree(buffer->pointer);
> +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> +	resource->length = sizeof(struct acpi_resource);
> +
> +	return 0;
> +}

IIUC correctly this code is here to count resources and replace them
with kernel specific IO offsets and I think that's wrong. ACPI devices
_CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
with resources that are basically Linux kernel internals specific.

The problem you are facing is there because there is no way in ACPI
to specify in FW what you want to describe but that's not a reason
to make it work by other means.

[...]

> + * update/set the current I/O resource of the designated device node.
> + * after this calling, the enumeration can be started as the I/O resource
> + * had been translated to logicial I/O from bus-local I/O.
> + *
> + * @adev: the device node to be updated the I/O resource;
> + * @host: the device node where 'adev' is attached, which can be not
> + *	the parent of 'adev';
> + *
> + * return 0 when successful, negative is for failure.
> + */
> +int acpi_set_logic_pio_resource(struct device *child,
> +		struct device *hostdev)
> +{
> +	struct acpi_device *adev;
> +	struct acpi_device *host;
> +	struct acpi_buffer buffer;
> +	acpi_status status;
> +	int ret;
> +
> +	if (!child || !hostdev)
> +		return -EINVAL;
> +
> +	host = to_acpi_device(hostdev);
> +	adev = to_acpi_device(child);
> +
> +	/* check the device state */
> +	if (!adev->status.present) {
> +		dev_info(child, "ACPI: device is not present!\n");
> +		return 0;
> +	}
> +	/* whether the child had been enumerated? */
> +	if (acpi_device_enumerated(adev)) {
> +		dev_info(child, "ACPI: had been enumerated!\n");
> +		return 0;
> +	}
> +
> +	/* read the _CRS and convert as acpi_buffer */
> +	status = acpi_build_logicpiores_template(adev, &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
> +		return -ENODEV;
> +	}
> +
> +	/* translate the I/O resources */
> +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> +	if (ret) {
> +		kfree(buffer.pointer);
> +		dev_err(child, "Translate I/O range FAIL!\n");
> +		return ret;
> +	}
> +
> +	/* set current resource... */
> +	status = acpi_set_current_resources(adev->handle, &buffer);

I reckon that this is wrong. You are updating ACPI device resources with
kernel specific built resources (ie IO space offsets) made by slicing up
IO space into the kernel available virtual address space offset
allocated to it.

IIUC this is done to make sure platform devices contains the
"translated" resources by the time they are probed, it is hard
to follow and again, not correct from an ACPI standpoint.

Furthermore I have no idea how this code is supposed to be used by
_any_ other platform, ACPI just has no notion of the translation you
are carrying out here (which mirrors what's done in DT without any
firmware binding to support it) so even if any other platform has
the same requirements I have no idea how people developing FW may
write their bindings to match these given that they just don't exist.

> +	kfree(buffer.pointer);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> +		ret = -EIO;
> +	}
> +
> +	return ret;
> +}
> +
> +/* All the host devices which apply indirect-PIO can be listed here. */
> +static const struct acpi_device_id acpi_indirect_host_id[] = {
> +	{""},

How can this be used by any other platform other than Hisilicon LPC ?

Imagine for a minute you have an ARM64 platform with an LPC bus in it
and you have to write ACPI tables to describe it, you may not want
to start by reading Linux kernel code to understand how to do it.

This code is Hisilicon specific code (ie there is no ACPI binding to
the best of my knowledge describing to FW developers an LPC binding)
and on the ACPI side it makes assumptions that I am not sure are
correct at all, see above.

> +};
> +
> +static int acpi_indirectpio_attach(struct acpi_device *adev,
> +				const struct acpi_device_id *id)
> +{
> +	struct indirect_pio_device_desc *hostdata;
> +	struct platform_device *pdev;
> +	int ret;
> +
> +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> +	if (!hostdata || !hostdata->pre_setup)
> +		return -EINVAL;
> +
> +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> +	if (!ret) {
> +		pdev = acpi_create_platform_device(adev, NULL);

So, this is done through a scan handler for what reason ? Is this
because you want this code to run before platform devices are created
by ACPI core - so that you can update their resources in the

struct indirect_pio_device_desc.pre_setup() method ?

I suspect this is yet another probing order issue to solve but that's
orthogonal to the comments I made above.

To sum it up:

(1) Creating an ARM64 ACPI standard kernel layer to parse something that is
    not an ACPI (let alone ARM64) standard does not make much sense to me,
    so either standard bindings are published for other partners to use
    them or this code belongs to Hisilicon specific LPC bus management
(2) Even with (1), I have concerns about this patch ACPI resources
    handling, I really think it is wrong to update ACPI devices
    resources with something that is Linux kernel specific. I may
    understand building platform devices resources according to your
    LPC bus requirements but not updating ACPI device FW bindings with
    resources that are basically kernel internals.

Thanks,
Lorenzo

> +		if (IS_ERR_OR_NULL(pdev)) {
> +			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
> +			return -EFAULT;
> +		}
> +		acpi_device_set_enumerated(adev);
> +		ret = 1;
> +	}
> +
> +	return ret;
> +}
> +
> +
> +static struct acpi_scan_handler acpi_indirect_handler = {
> +	.ids = acpi_indirect_host_id,
> +	.attach = acpi_indirectpio_attach,
> +};
> +
> +void __init acpi_indirectio_scan_init(void)
> +{
> +	acpi_scan_add_handler(&acpi_indirect_handler);
> +}
> diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> index 66229ff..bf8aaf8 100644
> --- a/drivers/acpi/internal.h
> +++ b/drivers/acpi/internal.h
> @@ -31,6 +31,11 @@ void acpi_processor_init(void);
>  void acpi_platform_init(void);
>  void acpi_pnp_init(void);
>  void acpi_int340x_thermal_init(void);
> +#ifdef CONFIG_INDIRECT_PIO
> +void acpi_indirectio_scan_init(void);
> +#else
> +static inline void acpi_indirectio_scan_init(void) {}
> +#endif
>  #ifdef CONFIG_ARM_AMBA
>  void acpi_amba_init(void);
>  #else
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index e39ec7b..37dd23c 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
>  	acpi_int340x_thermal_init();
>  	acpi_amba_init();
>  	acpi_watchdog_init();
> +	acpi_indirectio_scan_init();
>  
>  	acpi_scan_add_handler(&generic_device_handler);
>  
> diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
> new file mode 100644
> index 0000000..efc5c43
> --- /dev/null
> +++ b/include/acpi/acpi_indirect_pio.h
> @@ -0,0 +1,24 @@
> +/*
> + * ACPI support for indirect-PIO bus.
> + *
> + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _ACPI_INDIRECT_PIO_H
> +#define _ACPI_INDIRECT_PIO_H
> +
> +struct indirect_pio_device_desc {
> +	void *pdata; /* device relevant info data */
> +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> +};
> +
> +int acpi_set_logic_pio_resource(struct device *child,
> +		struct device *hostdev);
> +
> +#endif
> -- 
> 2.7.4
> 
> 

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-30 13:24     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-05-30 13:24 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, minyard, linux-acpi, arnd, rafael, linux-pci,
	catalin.marinas, john.garry, will.deacon, linux-kernel, xuwei5,
	linuxarm, olof, robh+dt, benh, bhelgaas, frowand.list,
	brian.starkey, linux-arm-kernel

Hi Gab,

On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> From: Gabriele <gabriele.paoloni@huawei.com>
> 
> On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
> I/O with some special host-local I/O ports known on x86. As their I/O
> space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
> meant to support a new class of I/O host controllers where the local IO
> ports of the children devices are translated into the Indirect I/O address
> space.
> Through the handler attach callback, all the I/O translations are done
> before starting the enumeration on children devices and the translated
> addresses are replaced in the children resources.

I do not understand why this is done through a scan handler and to
be frank I do not see how this mechanism is supposed to be a generic
kernel layer, possibly used by other platforms, when there is no notion
in ACPI to cater for that.

As far as I am concerned this patch code should live in the Hisilicon
LPC driver - as things stand it is neither ACPI generic code nor ARM64
specific, it is code to make ACPI work like DT bindings without any ACPI
binding at all; I still have some concerns from an ACPI standpoint
below.

> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  drivers/acpi/arm64/Makefile            |   1 +
>  drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
>  drivers/acpi/internal.h                |   5 +
>  drivers/acpi/scan.c                    |   1 +
>  include/acpi/acpi_indirect_pio.h       |  24 +++
>  5 files changed, 332 insertions(+)
>  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
>  create mode 100644 include/acpi/acpi_indirect_pio.h
> 
> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
> index 1017def..3944775 100644
> --- a/drivers/acpi/arm64/Makefile
> +++ b/drivers/acpi/arm64/Makefile
> @@ -1,2 +1,3 @@
>  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
>  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
> new file mode 100644
> index 0000000..7813f73
> --- /dev/null
> +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> @@ -0,0 +1,301 @@
> +/*
> + * ACPI support for indirect-PIO bus.
> + *
> + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/platform_device.h>
> +#include <linux/logic_pio.h>
> +
> +#include <acpi/acpi_indirect_pio.h>
> +
> +ACPI_MODULE_NAME("indirect PIO");
> +
> +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> +
> +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> +					   void *data)
> +{
> +	int *res_cnt = data;
> +
> +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> +		(*res_cnt)++;
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
> +		void *data)
> +{
> +	struct acpi_resource **resource = data;
> +
> +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> +		memcpy((*resource), res, sizeof(struct acpi_resource));
> +		(*resource)->length = sizeof(struct acpi_resource);
> +		(*resource)->type = res->type;
> +		(*resource)++;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status
> +acpi_build_logicpiores_template(struct acpi_device *adev,
> +			struct acpi_buffer *buffer)
> +{
> +	acpi_handle handle = adev->handle;
> +	struct acpi_resource *resource;
> +	acpi_status status;
> +	int res_cnt = 0;
> +
> +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> +				     acpi_count_logic_iores, &res_cnt);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	if (!res_cnt) {
> +		dev_err(&adev->dev, "no logic IO resources\n");
> +		return -ENODEV;
> +	}
> +
> +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> +	if (!buffer->pointer)
> +		return -ENOMEM;
> +
> +	resource = (struct acpi_resource *)buffer->pointer;
> +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> +				     acpi_read_one_logicpiores, &resource);
> +	if (ACPI_FAILURE(status)) {
> +		kfree(buffer->pointer);
> +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> +	resource->length = sizeof(struct acpi_resource);
> +
> +	return 0;
> +}

IIUC correctly this code is here to count resources and replace them
with kernel specific IO offsets and I think that's wrong. ACPI devices
_CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
with resources that are basically Linux kernel internals specific.

The problem you are facing is there because there is no way in ACPI
to specify in FW what you want to describe but that's not a reason
to make it work by other means.

[...]

> + * update/set the current I/O resource of the designated device node.
> + * after this calling, the enumeration can be started as the I/O resource
> + * had been translated to logicial I/O from bus-local I/O.
> + *
> + * @adev: the device node to be updated the I/O resource;
> + * @host: the device node where 'adev' is attached, which can be not
> + *	the parent of 'adev';
> + *
> + * return 0 when successful, negative is for failure.
> + */
> +int acpi_set_logic_pio_resource(struct device *child,
> +		struct device *hostdev)
> +{
> +	struct acpi_device *adev;
> +	struct acpi_device *host;
> +	struct acpi_buffer buffer;
> +	acpi_status status;
> +	int ret;
> +
> +	if (!child || !hostdev)
> +		return -EINVAL;
> +
> +	host = to_acpi_device(hostdev);
> +	adev = to_acpi_device(child);
> +
> +	/* check the device state */
> +	if (!adev->status.present) {
> +		dev_info(child, "ACPI: device is not present!\n");
> +		return 0;
> +	}
> +	/* whether the child had been enumerated? */
> +	if (acpi_device_enumerated(adev)) {
> +		dev_info(child, "ACPI: had been enumerated!\n");
> +		return 0;
> +	}
> +
> +	/* read the _CRS and convert as acpi_buffer */
> +	status = acpi_build_logicpiores_template(adev, &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
> +		return -ENODEV;
> +	}
> +
> +	/* translate the I/O resources */
> +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> +	if (ret) {
> +		kfree(buffer.pointer);
> +		dev_err(child, "Translate I/O range FAIL!\n");
> +		return ret;
> +	}
> +
> +	/* set current resource... */
> +	status = acpi_set_current_resources(adev->handle, &buffer);

I reckon that this is wrong. You are updating ACPI device resources with
kernel specific built resources (ie IO space offsets) made by slicing up
IO space into the kernel available virtual address space offset
allocated to it.

IIUC this is done to make sure platform devices contains the
"translated" resources by the time they are probed, it is hard
to follow and again, not correct from an ACPI standpoint.

Furthermore I have no idea how this code is supposed to be used by
_any_ other platform, ACPI just has no notion of the translation you
are carrying out here (which mirrors what's done in DT without any
firmware binding to support it) so even if any other platform has
the same requirements I have no idea how people developing FW may
write their bindings to match these given that they just don't exist.

> +	kfree(buffer.pointer);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> +		ret = -EIO;
> +	}
> +
> +	return ret;
> +}
> +
> +/* All the host devices which apply indirect-PIO can be listed here. */
> +static const struct acpi_device_id acpi_indirect_host_id[] = {
> +	{""},

How can this be used by any other platform other than Hisilicon LPC ?

Imagine for a minute you have an ARM64 platform with an LPC bus in it
and you have to write ACPI tables to describe it, you may not want
to start by reading Linux kernel code to understand how to do it.

This code is Hisilicon specific code (ie there is no ACPI binding to
the best of my knowledge describing to FW developers an LPC binding)
and on the ACPI side it makes assumptions that I am not sure are
correct at all, see above.

> +};
> +
> +static int acpi_indirectpio_attach(struct acpi_device *adev,
> +				const struct acpi_device_id *id)
> +{
> +	struct indirect_pio_device_desc *hostdata;
> +	struct platform_device *pdev;
> +	int ret;
> +
> +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> +	if (!hostdata || !hostdata->pre_setup)
> +		return -EINVAL;
> +
> +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> +	if (!ret) {
> +		pdev = acpi_create_platform_device(adev, NULL);

So, this is done through a scan handler for what reason ? Is this
because you want this code to run before platform devices are created
by ACPI core - so that you can update their resources in the

struct indirect_pio_device_desc.pre_setup() method ?

I suspect this is yet another probing order issue to solve but that's
orthogonal to the comments I made above.

To sum it up:

(1) Creating an ARM64 ACPI standard kernel layer to parse something that is
    not an ACPI (let alone ARM64) standard does not make much sense to me,
    so either standard bindings are published for other partners to use
    them or this code belongs to Hisilicon specific LPC bus management
(2) Even with (1), I have concerns about this patch ACPI resources
    handling, I really think it is wrong to update ACPI devices
    resources with something that is Linux kernel specific. I may
    understand building platform devices resources according to your
    LPC bus requirements but not updating ACPI device FW bindings with
    resources that are basically kernel internals.

Thanks,
Lorenzo

> +		if (IS_ERR_OR_NULL(pdev)) {
> +			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
> +			return -EFAULT;
> +		}
> +		acpi_device_set_enumerated(adev);
> +		ret = 1;
> +	}
> +
> +	return ret;
> +}
> +
> +
> +static struct acpi_scan_handler acpi_indirect_handler = {
> +	.ids = acpi_indirect_host_id,
> +	.attach = acpi_indirectpio_attach,
> +};
> +
> +void __init acpi_indirectio_scan_init(void)
> +{
> +	acpi_scan_add_handler(&acpi_indirect_handler);
> +}
> diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> index 66229ff..bf8aaf8 100644
> --- a/drivers/acpi/internal.h
> +++ b/drivers/acpi/internal.h
> @@ -31,6 +31,11 @@ void acpi_processor_init(void);
>  void acpi_platform_init(void);
>  void acpi_pnp_init(void);
>  void acpi_int340x_thermal_init(void);
> +#ifdef CONFIG_INDIRECT_PIO
> +void acpi_indirectio_scan_init(void);
> +#else
> +static inline void acpi_indirectio_scan_init(void) {}
> +#endif
>  #ifdef CONFIG_ARM_AMBA
>  void acpi_amba_init(void);
>  #else
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index e39ec7b..37dd23c 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
>  	acpi_int340x_thermal_init();
>  	acpi_amba_init();
>  	acpi_watchdog_init();
> +	acpi_indirectio_scan_init();
>  
>  	acpi_scan_add_handler(&generic_device_handler);
>  
> diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
> new file mode 100644
> index 0000000..efc5c43
> --- /dev/null
> +++ b/include/acpi/acpi_indirect_pio.h
> @@ -0,0 +1,24 @@
> +/*
> + * ACPI support for indirect-PIO bus.
> + *
> + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _ACPI_INDIRECT_PIO_H
> +#define _ACPI_INDIRECT_PIO_H
> +
> +struct indirect_pio_device_desc {
> +	void *pdata; /* device relevant info data */
> +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> +};
> +
> +int acpi_set_logic_pio_resource(struct device *child,
> +		struct device *hostdev);
> +
> +#endif
> -- 
> 2.7.4
> 
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-30 13:24     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-05-30 13:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Gab,

On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> From: Gabriele <gabriele.paoloni@huawei.com>
> 
> On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices access
> I/O with some special host-local I/O ports known on x86. As their I/O
> space are not memory mapped like PCI/PCIE MMIO host bridges, this patch is
> meant to support a new class of I/O host controllers where the local IO
> ports of the children devices are translated into the Indirect I/O address
> space.
> Through the handler attach callback, all the I/O translations are done
> before starting the enumeration on children devices and the translated
> addresses are replaced in the children resources.

I do not understand why this is done through a scan handler and to
be frank I do not see how this mechanism is supposed to be a generic
kernel layer, possibly used by other platforms, when there is no notion
in ACPI to cater for that.

As far as I am concerned this patch code should live in the Hisilicon
LPC driver - as things stand it is neither ACPI generic code nor ARM64
specific, it is code to make ACPI work like DT bindings without any ACPI
binding at all; I still have some concerns from an ACPI standpoint
below.

> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  drivers/acpi/arm64/Makefile            |   1 +
>  drivers/acpi/arm64/acpi_indirect_pio.c | 301 +++++++++++++++++++++++++++++++++
>  drivers/acpi/internal.h                |   5 +
>  drivers/acpi/scan.c                    |   1 +
>  include/acpi/acpi_indirect_pio.h       |  24 +++
>  5 files changed, 332 insertions(+)
>  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
>  create mode 100644 include/acpi/acpi_indirect_pio.h
> 
> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
> index 1017def..3944775 100644
> --- a/drivers/acpi/arm64/Makefile
> +++ b/drivers/acpi/arm64/Makefile
> @@ -1,2 +1,3 @@
>  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
>  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c b/drivers/acpi/arm64/acpi_indirect_pio.c
> new file mode 100644
> index 0000000..7813f73
> --- /dev/null
> +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> @@ -0,0 +1,301 @@
> +/*
> + * ACPI support for indirect-PIO bus.
> + *
> + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/platform_device.h>
> +#include <linux/logic_pio.h>
> +
> +#include <acpi/acpi_indirect_pio.h>
> +
> +ACPI_MODULE_NAME("indirect PIO");
> +
> +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> +
> +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> +					   void *data)
> +{
> +	int *res_cnt = data;
> +
> +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> +		(*res_cnt)++;
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status acpi_read_one_logicpiores(struct acpi_resource *res,
> +		void *data)
> +{
> +	struct acpi_resource **resource = data;
> +
> +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> +		memcpy((*resource), res, sizeof(struct acpi_resource));
> +		(*resource)->length = sizeof(struct acpi_resource);
> +		(*resource)->type = res->type;
> +		(*resource)++;
> +	}
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status
> +acpi_build_logicpiores_template(struct acpi_device *adev,
> +			struct acpi_buffer *buffer)
> +{
> +	acpi_handle handle = adev->handle;
> +	struct acpi_resource *resource;
> +	acpi_status status;
> +	int res_cnt = 0;
> +
> +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> +				     acpi_count_logic_iores, &res_cnt);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	if (!res_cnt) {
> +		dev_err(&adev->dev, "no logic IO resources\n");
> +		return -ENODEV;
> +	}
> +
> +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> +	if (!buffer->pointer)
> +		return -ENOMEM;
> +
> +	resource = (struct acpi_resource *)buffer->pointer;
> +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> +				     acpi_read_one_logicpiores, &resource);
> +	if (ACPI_FAILURE(status)) {
> +		kfree(buffer->pointer);
> +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> +		return -EINVAL;
> +	}
> +
> +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> +	resource->length = sizeof(struct acpi_resource);
> +
> +	return 0;
> +}

IIUC correctly this code is here to count resources and replace them
with kernel specific IO offsets and I think that's wrong. ACPI devices
_CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
with resources that are basically Linux kernel internals specific.

The problem you are facing is there because there is no way in ACPI
to specify in FW what you want to describe but that's not a reason
to make it work by other means.

[...]

> + * update/set the current I/O resource of the designated device node.
> + * after this calling, the enumeration can be started as the I/O resource
> + * had been translated to logicial I/O from bus-local I/O.
> + *
> + * @adev: the device node to be updated the I/O resource;
> + * @host: the device node where 'adev' is attached, which can be not
> + *	the parent of 'adev';
> + *
> + * return 0 when successful, negative is for failure.
> + */
> +int acpi_set_logic_pio_resource(struct device *child,
> +		struct device *hostdev)
> +{
> +	struct acpi_device *adev;
> +	struct acpi_device *host;
> +	struct acpi_buffer buffer;
> +	acpi_status status;
> +	int ret;
> +
> +	if (!child || !hostdev)
> +		return -EINVAL;
> +
> +	host = to_acpi_device(hostdev);
> +	adev = to_acpi_device(child);
> +
> +	/* check the device state */
> +	if (!adev->status.present) {
> +		dev_info(child, "ACPI: device is not present!\n");
> +		return 0;
> +	}
> +	/* whether the child had been enumerated? */
> +	if (acpi_device_enumerated(adev)) {
> +		dev_info(child, "ACPI: had been enumerated!\n");
> +		return 0;
> +	}
> +
> +	/* read the _CRS and convert as acpi_buffer */
> +	status = acpi_build_logicpiores_template(adev, &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		dev_warn(child, "Failure evaluating %s\n", METHOD_NAME__CRS);
> +		return -ENODEV;
> +	}
> +
> +	/* translate the I/O resources */
> +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> +	if (ret) {
> +		kfree(buffer.pointer);
> +		dev_err(child, "Translate I/O range FAIL!\n");
> +		return ret;
> +	}
> +
> +	/* set current resource... */
> +	status = acpi_set_current_resources(adev->handle, &buffer);

I reckon that this is wrong. You are updating ACPI device resources with
kernel specific built resources (ie IO space offsets) made by slicing up
IO space into the kernel available virtual address space offset
allocated to it.

IIUC this is done to make sure platform devices contains the
"translated" resources by the time they are probed, it is hard
to follow and again, not correct from an ACPI standpoint.

Furthermore I have no idea how this code is supposed to be used by
_any_ other platform, ACPI just has no notion of the translation you
are carrying out here (which mirrors what's done in DT without any
firmware binding to support it) so even if any other platform has
the same requirements I have no idea how people developing FW may
write their bindings to match these given that they just don't exist.

> +	kfree(buffer.pointer);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> +		ret = -EIO;
> +	}
> +
> +	return ret;
> +}
> +
> +/* All the host devices which apply indirect-PIO can be listed here. */
> +static const struct acpi_device_id acpi_indirect_host_id[] = {
> +	{""},

How can this be used by any other platform other than Hisilicon LPC ?

Imagine for a minute you have an ARM64 platform with an LPC bus in it
and you have to write ACPI tables to describe it, you may not want
to start by reading Linux kernel code to understand how to do it.

This code is Hisilicon specific code (ie there is no ACPI binding to
the best of my knowledge describing to FW developers an LPC binding)
and on the ACPI side it makes assumptions that I am not sure are
correct at all, see above.

> +};
> +
> +static int acpi_indirectpio_attach(struct acpi_device *adev,
> +				const struct acpi_device_id *id)
> +{
> +	struct indirect_pio_device_desc *hostdata;
> +	struct platform_device *pdev;
> +	int ret;
> +
> +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> +	if (!hostdata || !hostdata->pre_setup)
> +		return -EINVAL;
> +
> +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> +	if (!ret) {
> +		pdev = acpi_create_platform_device(adev, NULL);

So, this is done through a scan handler for what reason ? Is this
because you want this code to run before platform devices are created
by ACPI core - so that you can update their resources in the

struct indirect_pio_device_desc.pre_setup() method ?

I suspect this is yet another probing order issue to solve but that's
orthogonal to the comments I made above.

To sum it up:

(1) Creating an ARM64 ACPI standard kernel layer to parse something that is
    not an ACPI (let alone ARM64) standard does not make much sense to me,
    so either standard bindings are published for other partners to use
    them or this code belongs to Hisilicon specific LPC bus management
(2) Even with (1), I have concerns about this patch ACPI resources
    handling, I really think it is wrong to update ACPI devices
    resources with something that is Linux kernel specific. I may
    understand building platform devices resources according to your
    LPC bus requirements but not updating ACPI device FW bindings with
    resources that are basically kernel internals.

Thanks,
Lorenzo

> +		if (IS_ERR_OR_NULL(pdev)) {
> +			dev_err(&adev->dev, "Create platform device for host FAIL!\n");
> +			return -EFAULT;
> +		}
> +		acpi_device_set_enumerated(adev);
> +		ret = 1;
> +	}
> +
> +	return ret;
> +}
> +
> +
> +static struct acpi_scan_handler acpi_indirect_handler = {
> +	.ids = acpi_indirect_host_id,
> +	.attach = acpi_indirectpio_attach,
> +};
> +
> +void __init acpi_indirectio_scan_init(void)
> +{
> +	acpi_scan_add_handler(&acpi_indirect_handler);
> +}
> diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> index 66229ff..bf8aaf8 100644
> --- a/drivers/acpi/internal.h
> +++ b/drivers/acpi/internal.h
> @@ -31,6 +31,11 @@ void acpi_processor_init(void);
>  void acpi_platform_init(void);
>  void acpi_pnp_init(void);
>  void acpi_int340x_thermal_init(void);
> +#ifdef CONFIG_INDIRECT_PIO
> +void acpi_indirectio_scan_init(void);
> +#else
> +static inline void acpi_indirectio_scan_init(void) {}
> +#endif
>  #ifdef CONFIG_ARM_AMBA
>  void acpi_amba_init(void);
>  #else
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index e39ec7b..37dd23c 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
>  	acpi_int340x_thermal_init();
>  	acpi_amba_init();
>  	acpi_watchdog_init();
> +	acpi_indirectio_scan_init();
>  
>  	acpi_scan_add_handler(&generic_device_handler);
>  
> diff --git a/include/acpi/acpi_indirect_pio.h b/include/acpi/acpi_indirect_pio.h
> new file mode 100644
> index 0000000..efc5c43
> --- /dev/null
> +++ b/include/acpi/acpi_indirect_pio.h
> @@ -0,0 +1,24 @@
> +/*
> + * ACPI support for indirect-PIO bus.
> + *
> + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _ACPI_INDIRECT_PIO_H
> +#define _ACPI_INDIRECT_PIO_H
> +
> +struct indirect_pio_device_desc {
> +	void *pdata; /* device relevant info data */
> +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> +};
> +
> +int acpi_set_logic_pio_resource(struct device *child,
> +		struct device *hostdev);
> +
> +#endif
> -- 
> 2.7.4
> 
> 

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
  2017-05-26 20:57     ` Bjorn Helgaas
  (?)
  (?)
@ 2017-05-30 15:09       ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30 15:09 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, John Garry, linux-kernel, xuwei (O),
	Linuxarm, linux-acpi

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 21:58
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
> 
> On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> > pci_pio_to_address()")' a new I/O space management was supported.
> With that
> > driver, the I/O ranges configured for PCI/PCIE hosts on some
> architectures
> > can be mapped to logical PIO, converted easily between CPU address
> and the
> > corresponding logicial PIO. Based on this, PCI I/O devices can be
> accessed
> > in a memory read/write way through the unified in/out accessors.
> >
> > But on some archs/platforms, there are bus hosts which access I/O
> > peripherals with host-local I/O port addresses rather than memory
> > addresses after memory-mapped.
> > To support those devices, a more generic I/O mapping method is
> introduced
> > here. Through this patch, both the CPU addresses and the host-local
> port
> > can be mapped into the logical PIO space with different logical/fake
> PIOs.
> > After this, all the I/O accesses to either PCI MMIO devices or host-
> local
> > I/O peripherals can be unified into the existing I/O accessors
> defined in
> > asm-generic/io.h and be redirected to the right device-specific hooks
> > based on the input logical PIO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  include/asm-generic/io.h  |  50 +++++++++
> >  include/linux/logic_pio.h | 110 ++++++++++++++++++
> >  lib/Kconfig               |  26 +++++
> >  lib/Makefile              |   2 +
> >  lib/logic_pio.c           | 280
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 468 insertions(+)
> >  create mode 100644 include/linux/logic_pio.h
> >  create mode 100644 lib/logic_pio.c
> >
> > diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> > index 7ef015e..f7fbec3 100644
> > --- a/include/asm-generic/io.h
> > +++ b/include/asm-generic/io.h
> > ...
> 
> >  #ifndef inb
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inb logic_inb
> > +#else
> >  #define inb inb
> >  static inline u8 inb(unsigned long addr)
> >  {
> >  	return readb(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> >
> >  #ifndef inw
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inw logic_inw
> 
> Cosmetic: could these ifdefs all be collected in one place, e.g.,
> 
>   #ifdef CONFIG_INDIRECT_PIO
>   #define inb logic_inb
>   #define inw logic_inw
>   #define inl logic_inl
>   ...
>   #endif
> 
> to avoid cluttering every one of the default definitions?  Could the
> collection be in logic_pio.h itself, next to the extern declarations?

Yes I think it should be doable. I will rework this in the next patchset

> 
> > +#else
> >  #define inw inw
> >  static inline u16 inw(unsigned long addr)
> >  {
> >  	return readw(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> 
> >  #ifndef insb_p
> > diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> > new file mode 100644
> > index 0000000..8e4dc65
> > --- /dev/null
> > +++ b/include/linux/logic_pio.h
> > ...
> 
> > +extern u8 logic_inb(unsigned long addr);
> 
> I think you only build the definitions for these if
> CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
> too.

Yes agreed

> 
> In PCI code, I omit the "extern" from function declarations.  This
> isn't PCI code, and I don't know if there's a real consensus on this,
> but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
> function prototypes in <asm/proto.h>")
> 

To be honest I have no clue...

If you look at include/asm-generic/io.h we have extern declarations...

BTW I can remove the extern and then let's see if somebody complains...


> > +#ifdef CONFIG_LOGIC_PIO
> > +extern struct logic_pio_hwaddr
> > +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
> 
> If you have to split the line (this one would fit without the
> "extern"), the "*" goes with the type, e.g.,
> 
>   struct logic_pio_hwaddr *
>   find_io_range_by_fwnode(struct fwnode_handle *fwnode);
> 
> More occurrences below.

Ok I will rework these

> 
> > diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> > new file mode 100644
> > index 0000000..4a960cd
> > --- /dev/null
> > +++ b/lib/logic_pio.c
> > ...
> 
> > +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> > +#define BUILD_LOGIC_PIO(bw, type)\
> > +type logic_in##bw(unsigned long addr)\
> > +{\
> > +	type ret = -1;\
> > +\
> > +	if (addr < MMIO_UPPER_LIMIT) {\
> > +		ret = read##bw(PCI_IOBASE + addr);\
> > +	} else {\
> > +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> > +\
> > +		if (entry && entry->ops)\
> > +			ret = entry->ops->pfin(entry->devpara,\
> > +					addr, sizeof(type));\
> > +		else\
> > +			WARN_ON_ONCE(1);\
> > +	}	\
> > +	return ret;\
> > +}	\
> 
> I think these would be slightly easier to read if the line continuation
> backslashes were aligned at the right, as with
> ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
> etc.

Ok agreed I will rework this too

Many Thanks
Gab

> 
> Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-30 15:09       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30 15:09 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, John Garry, linux-kernel, xuwei (O),
	Linuxarm, linux-acpi, zhichang.yuan, linux-pci, olof,
	brian.starkey

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 21:58
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
> 
> On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> > pci_pio_to_address()")' a new I/O space management was supported.
> With that
> > driver, the I/O ranges configured for PCI/PCIE hosts on some
> architectures
> > can be mapped to logical PIO, converted easily between CPU address
> and the
> > corresponding logicial PIO. Based on this, PCI I/O devices can be
> accessed
> > in a memory read/write way through the unified in/out accessors.
> >
> > But on some archs/platforms, there are bus hosts which access I/O
> > peripherals with host-local I/O port addresses rather than memory
> > addresses after memory-mapped.
> > To support those devices, a more generic I/O mapping method is
> introduced
> > here. Through this patch, both the CPU addresses and the host-local
> port
> > can be mapped into the logical PIO space with different logical/fake
> PIOs.
> > After this, all the I/O accesses to either PCI MMIO devices or host-
> local
> > I/O peripherals can be unified into the existing I/O accessors
> defined in
> > asm-generic/io.h and be redirected to the right device-specific hooks
> > based on the input logical PIO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  include/asm-generic/io.h  |  50 +++++++++
> >  include/linux/logic_pio.h | 110 ++++++++++++++++++
> >  lib/Kconfig               |  26 +++++
> >  lib/Makefile              |   2 +
> >  lib/logic_pio.c           | 280
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 468 insertions(+)
> >  create mode 100644 include/linux/logic_pio.h
> >  create mode 100644 lib/logic_pio.c
> >
> > diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> > index 7ef015e..f7fbec3 100644
> > --- a/include/asm-generic/io.h
> > +++ b/include/asm-generic/io.h
> > ...
> 
> >  #ifndef inb
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inb logic_inb
> > +#else
> >  #define inb inb
> >  static inline u8 inb(unsigned long addr)
> >  {
> >  	return readb(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> >
> >  #ifndef inw
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inw logic_inw
> 
> Cosmetic: could these ifdefs all be collected in one place, e.g.,
> 
>   #ifdef CONFIG_INDIRECT_PIO
>   #define inb logic_inb
>   #define inw logic_inw
>   #define inl logic_inl
>   ...
>   #endif
> 
> to avoid cluttering every one of the default definitions?  Could the
> collection be in logic_pio.h itself, next to the extern declarations?

Yes I think it should be doable. I will rework this in the next patchset

> 
> > +#else
> >  #define inw inw
> >  static inline u16 inw(unsigned long addr)
> >  {
> >  	return readw(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> 
> >  #ifndef insb_p
> > diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> > new file mode 100644
> > index 0000000..8e4dc65
> > --- /dev/null
> > +++ b/include/linux/logic_pio.h
> > ...
> 
> > +extern u8 logic_inb(unsigned long addr);
> 
> I think you only build the definitions for these if
> CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
> too.

Yes agreed

> 
> In PCI code, I omit the "extern" from function declarations.  This
> isn't PCI code, and I don't know if there's a real consensus on this,
> but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
> function prototypes in <asm/proto.h>")
> 

To be honest I have no clue...

If you look at include/asm-generic/io.h we have extern declarations...

BTW I can remove the extern and then let's see if somebody complains...


> > +#ifdef CONFIG_LOGIC_PIO
> > +extern struct logic_pio_hwaddr
> > +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
> 
> If you have to split the line (this one would fit without the
> "extern"), the "*" goes with the type, e.g.,
> 
>   struct logic_pio_hwaddr *
>   find_io_range_by_fwnode(struct fwnode_handle *fwnode);
> 
> More occurrences below.

Ok I will rework these

> 
> > diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> > new file mode 100644
> > index 0000000..4a960cd
> > --- /dev/null
> > +++ b/lib/logic_pio.c
> > ...
> 
> > +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> > +#define BUILD_LOGIC_PIO(bw, type)\
> > +type logic_in##bw(unsigned long addr)\
> > +{\
> > +	type ret = -1;\
> > +\
> > +	if (addr < MMIO_UPPER_LIMIT) {\
> > +		ret = read##bw(PCI_IOBASE + addr);\
> > +	} else {\
> > +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> > +\
> > +		if (entry && entry->ops)\
> > +			ret = entry->ops->pfin(entry->devpara,\
> > +					addr, sizeof(type));\
> > +		else\
> > +			WARN_ON_ONCE(1);\
> > +	}	\
> > +	return ret;\
> > +}	\
> 
> I think these would be slightly easier to read if the line continuation
> backslashes were aligned at the right, as with
> ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
> etc.

Ok agreed I will rework this too

Many Thanks
Gab

> 
> Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-30 15:09       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30 15:09 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, lorenzo.pieralisi, mark.rutland,
	minyard, benh, John Garry, linux-kernel, xuwei (O),
	Linuxarm, linux-acpi, zhichang.yuan, linux-pci, olof,
	brian.starkey

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 21:58
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
>=20
> On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> > pci_pio_to_address()")' a new I/O space management was supported.
> With that
> > driver, the I/O ranges configured for PCI/PCIE hosts on some
> architectures
> > can be mapped to logical PIO, converted easily between CPU address
> and the
> > corresponding logicial PIO. Based on this, PCI I/O devices can be
> accessed
> > in a memory read/write way through the unified in/out accessors.
> >
> > But on some archs/platforms, there are bus hosts which access I/O
> > peripherals with host-local I/O port addresses rather than memory
> > addresses after memory-mapped.
> > To support those devices, a more generic I/O mapping method is
> introduced
> > here. Through this patch, both the CPU addresses and the host-local
> port
> > can be mapped into the logical PIO space with different logical/fake
> PIOs.
> > After this, all the I/O accesses to either PCI MMIO devices or host-
> local
> > I/O peripherals can be unified into the existing I/O accessors
> defined in
> > asm-generic/io.h and be redirected to the right device-specific hooks
> > based on the input logical PIO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  include/asm-generic/io.h  |  50 +++++++++
> >  include/linux/logic_pio.h | 110 ++++++++++++++++++
> >  lib/Kconfig               |  26 +++++
> >  lib/Makefile              |   2 +
> >  lib/logic_pio.c           | 280
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 468 insertions(+)
> >  create mode 100644 include/linux/logic_pio.h
> >  create mode 100644 lib/logic_pio.c
> >
> > diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> > index 7ef015e..f7fbec3 100644
> > --- a/include/asm-generic/io.h
> > +++ b/include/asm-generic/io.h
> > ...
>=20
> >  #ifndef inb
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inb logic_inb
> > +#else
> >  #define inb inb
> >  static inline u8 inb(unsigned long addr)
> >  {
> >  	return readb(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> >
> >  #ifndef inw
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inw logic_inw
>=20
> Cosmetic: could these ifdefs all be collected in one place, e.g.,
>=20
>   #ifdef CONFIG_INDIRECT_PIO
>   #define inb logic_inb
>   #define inw logic_inw
>   #define inl logic_inl
>   ...
>   #endif
>=20
> to avoid cluttering every one of the default definitions?  Could the
> collection be in logic_pio.h itself, next to the extern declarations?

Yes I think it should be doable. I will rework this in the next patchset

>=20
> > +#else
> >  #define inw inw
> >  static inline u16 inw(unsigned long addr)
> >  {
> >  	return readw(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
>=20
> >  #ifndef insb_p
> > diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> > new file mode 100644
> > index 0000000..8e4dc65
> > --- /dev/null
> > +++ b/include/linux/logic_pio.h
> > ...
>=20
> > +extern u8 logic_inb(unsigned long addr);
>=20
> I think you only build the definitions for these if
> CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
> too.

Yes agreed

>=20
> In PCI code, I omit the "extern" from function declarations.  This
> isn't PCI code, and I don't know if there's a real consensus on this,
> but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
> function prototypes in <asm/proto.h>")
>=20

To be honest I have no clue...

If you look at include/asm-generic/io.h we have extern declarations...

BTW I can remove the extern and then let's see if somebody complains...


> > +#ifdef CONFIG_LOGIC_PIO
> > +extern struct logic_pio_hwaddr
> > +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
>=20
> If you have to split the line (this one would fit without the
> "extern"), the "*" goes with the type, e.g.,
>=20
>   struct logic_pio_hwaddr *
>   find_io_range_by_fwnode(struct fwnode_handle *fwnode);
>=20
> More occurrences below.

Ok I will rework these

>=20
> > diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> > new file mode 100644
> > index 0000000..4a960cd
> > --- /dev/null
> > +++ b/lib/logic_pio.c
> > ...
>=20
> > +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> > +#define BUILD_LOGIC_PIO(bw, type)\
> > +type logic_in##bw(unsigned long addr)\
> > +{\
> > +	type ret =3D -1;\
> > +\
> > +	if (addr < MMIO_UPPER_LIMIT) {\
> > +		ret =3D read##bw(PCI_IOBASE + addr);\
> > +	} else {\
> > +		struct logic_pio_hwaddr *entry =3D find_io_range(addr);\
> > +\
> > +		if (entry && entry->ops)\
> > +			ret =3D entry->ops->pfin(entry->devpara,\
> > +					addr, sizeof(type));\
> > +		else\
> > +			WARN_ON_ONCE(1);\
> > +	}	\
> > +	return ret;\
> > +}	\
>=20
> I think these would be slightly easier to read if the line continuation
> backslashes were aligned at the right, as with
> ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
> etc.

Ok agreed I will rework this too

Many Thanks
Gab

>=20
> Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
@ 2017-05-30 15:09       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-30 15:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas at kernel.org]
> Sent: 26 May 2017 21:58
> To: Gabriele Paoloni
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; rafael at kernel.org;
> arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> lorenzo.pieralisi at arm.com; mark.rutland at arm.com; minyard at acm.org;
> benh at kernel.crashing.org; John Garry; linux-kernel at vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi at vger.kernel.org; zhichang.yuan; linux-
> pci at vger.kernel.org; olof at lixom.net; brian.starkey at arm.com
> Subject: Re: [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method
> 
> On Thu, May 25, 2017 at 12:37:22PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > In 'commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and
> > pci_pio_to_address()")' a new I/O space management was supported.
> With that
> > driver, the I/O ranges configured for PCI/PCIE hosts on some
> architectures
> > can be mapped to logical PIO, converted easily between CPU address
> and the
> > corresponding logicial PIO. Based on this, PCI I/O devices can be
> accessed
> > in a memory read/write way through the unified in/out accessors.
> >
> > But on some archs/platforms, there are bus hosts which access I/O
> > peripherals with host-local I/O port addresses rather than memory
> > addresses after memory-mapped.
> > To support those devices, a more generic I/O mapping method is
> introduced
> > here. Through this patch, both the CPU addresses and the host-local
> port
> > can be mapped into the logical PIO space with different logical/fake
> PIOs.
> > After this, all the I/O accesses to either PCI MMIO devices or host-
> local
> > I/O peripherals can be unified into the existing I/O accessors
> defined in
> > asm-generic/io.h and be redirected to the right device-specific hooks
> > based on the input logical PIO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  include/asm-generic/io.h  |  50 +++++++++
> >  include/linux/logic_pio.h | 110 ++++++++++++++++++
> >  lib/Kconfig               |  26 +++++
> >  lib/Makefile              |   2 +
> >  lib/logic_pio.c           | 280
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 468 insertions(+)
> >  create mode 100644 include/linux/logic_pio.h
> >  create mode 100644 lib/logic_pio.c
> >
> > diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
> > index 7ef015e..f7fbec3 100644
> > --- a/include/asm-generic/io.h
> > +++ b/include/asm-generic/io.h
> > ...
> 
> >  #ifndef inb
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inb logic_inb
> > +#else
> >  #define inb inb
> >  static inline u8 inb(unsigned long addr)
> >  {
> >  	return readb(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> >
> >  #ifndef inw
> > +#ifdef CONFIG_INDIRECT_PIO
> > +#define inw logic_inw
> 
> Cosmetic: could these ifdefs all be collected in one place, e.g.,
> 
>   #ifdef CONFIG_INDIRECT_PIO
>   #define inb logic_inb
>   #define inw logic_inw
>   #define inl logic_inl
>   ...
>   #endif
> 
> to avoid cluttering every one of the default definitions?  Could the
> collection be in logic_pio.h itself, next to the extern declarations?

Yes I think it should be doable. I will rework this in the next patchset

> 
> > +#else
> >  #define inw inw
> >  static inline u16 inw(unsigned long addr)
> >  {
> >  	return readw(PCI_IOBASE + addr);
> >  }
> > +#endif /* CONFIG_INDIRECT_PIO */
> >  #endif
> 
> >  #ifndef insb_p
> > diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h
> > new file mode 100644
> > index 0000000..8e4dc65
> > --- /dev/null
> > +++ b/include/linux/logic_pio.h
> > ...
> 
> > +extern u8 logic_inb(unsigned long addr);
> 
> I think you only build the definitions for these if
> CONFIG_INDIRECT_PIO, so the declarations could be under that #idef,
> too.

Yes agreed

> 
> In PCI code, I omit the "extern" from function declarations.  This
> isn't PCI code, and I don't know if there's a real consensus on this,
> but there is some precedent: 5bd085b5fbd8 ("x86: remove "extern" from
> function prototypes in <asm/proto.h>")
> 

To be honest I have no clue...

If you look at include/asm-generic/io.h we have extern declarations...

BTW I can remove the extern and then let's see if somebody complains...


> > +#ifdef CONFIG_LOGIC_PIO
> > +extern struct logic_pio_hwaddr
> > +*find_io_range_by_fwnode(struct fwnode_handle *fwnode);
> 
> If you have to split the line (this one would fit without the
> "extern"), the "*" goes with the type, e.g.,
> 
>   struct logic_pio_hwaddr *
>   find_io_range_by_fwnode(struct fwnode_handle *fwnode);
> 
> More occurrences below.

Ok I will rework these

> 
> > diff --git a/lib/logic_pio.c b/lib/logic_pio.c
> > new file mode 100644
> > index 0000000..4a960cd
> > --- /dev/null
> > +++ b/lib/logic_pio.c
> > ...
> 
> > +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
> > +#define BUILD_LOGIC_PIO(bw, type)\
> > +type logic_in##bw(unsigned long addr)\
> > +{\
> > +	type ret = -1;\
> > +\
> > +	if (addr < MMIO_UPPER_LIMIT) {\
> > +		ret = read##bw(PCI_IOBASE + addr);\
> > +	} else {\
> > +		struct logic_pio_hwaddr *entry = find_io_range(addr);\
> > +\
> > +		if (entry && entry->ops)\
> > +			ret = entry->ops->pfin(entry->devpara,\
> > +					addr, sizeof(type));\
> > +		else\
> > +			WARN_ON_ONCE(1);\
> > +	}	\
> > +	return ret;\
> > +}	\
> 
> I think these would be slightly easier to read if the line continuation
> backslashes were aligned at the right, as with
> ACPI_DECLARE_PROBE_ENTRY(), __atomic_op_acquire(), DECLARE_EWMA(),
> etc.

Ok agreed I will rework this too

Many Thanks
Gab

> 
> Bjorn

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-05-30 13:24     ` Lorenzo Pieralisi
  (?)
  (?)
@ 2017-05-31 10:24       ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-31 10:24 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, mark.rutland, brian.starkey,
	olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci@vger.kernel.org

Hi Lorenzo

Many thanks for reviewing

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com]
> Sent: 30 May 2017 14:24
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> mark.rutland@arm.com; brian.starkey@arm.com; olof@lixom.net;
> benh@kernel.crashing.org; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; Linuxarm; linux-pci@vger.kernel.org;
> minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Gab,
> 
> On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> > From: Gabriele <gabriele.paoloni@huawei.com>
> >
> > On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices
> access
> > I/O with some special host-local I/O ports known on x86. As their I/O
> > space are not memory mapped like PCI/PCIE MMIO host bridges, this
> patch is
> > meant to support a new class of I/O host controllers where the local
> IO
> > ports of the children devices are translated into the Indirect I/O
> address
> > space.
> > Through the handler attach callback, all the I/O translations are
> done
> > before starting the enumeration on children devices and the
> translated
> > addresses are replaced in the children resources.
> 
> I do not understand why this is done through a scan handler and to
> be frank I do not see how this mechanism is supposed to be a generic
> kernel layer, possibly used by other platforms, when there is no notion
> in ACPI to cater for that.

Well, the main reason is that we need to translate the bus addresses of
the LPC children before the respective children's drivers probe.

> 
> As far as I am concerned this patch code should live in the Hisilicon
> LPC driver - as things stand it is neither ACPI generic code nor ARM64
> specific, it is code to make ACPI work like DT bindings without any
> ACPI
> binding at all; I still have some concerns from an ACPI standpoint
> below.

Well the reason why this patch cannot live in the LPC driver probe is
that AFAIK currently there is no way to guarantee the LPC probe to be
called before the children probe. With respect to the ACPI concerns
please see below.

> 
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  drivers/acpi/arm64/Makefile            |   1 +
> >  drivers/acpi/arm64/acpi_indirect_pio.c | 301
> +++++++++++++++++++++++++++++++++
> >  drivers/acpi/internal.h                |   5 +
> >  drivers/acpi/scan.c                    |   1 +
> >  include/acpi/acpi_indirect_pio.h       |  24 +++
> >  5 files changed, 332 insertions(+)
> >  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
> >  create mode 100644 include/acpi/acpi_indirect_pio.h
> >
> > diff --git a/drivers/acpi/arm64/Makefile
> b/drivers/acpi/arm64/Makefile
> > index 1017def..3944775 100644
> > --- a/drivers/acpi/arm64/Makefile
> > +++ b/drivers/acpi/arm64/Makefile
> > @@ -1,2 +1,3 @@
> >  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
> >  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> > +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> > diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c
> b/drivers/acpi/arm64/acpi_indirect_pio.c
> > new file mode 100644
> > index 0000000..7813f73
> > --- /dev/null
> > +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> > @@ -0,0 +1,301 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/logic_pio.h>
> > +
> > +#include <acpi/acpi_indirect_pio.h>
> > +
> > +ACPI_MODULE_NAME("indirect PIO");
> > +
> > +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> > +
> > +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> > +					   void *data)
> > +{
> > +	int *res_cnt = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> > +		(*res_cnt)++;
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status acpi_read_one_logicpiores(struct acpi_resource
> *res,
> > +		void *data)
> > +{
> > +	struct acpi_resource **resource = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> > +		memcpy((*resource), res, sizeof(struct acpi_resource));
> > +		(*resource)->length = sizeof(struct acpi_resource);
> > +		(*resource)->type = res->type;
> > +		(*resource)++;
> > +	}
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status
> > +acpi_build_logicpiores_template(struct acpi_device *adev,
> > +			struct acpi_buffer *buffer)
> > +{
> > +	acpi_handle handle = adev->handle;
> > +	struct acpi_resource *resource;
> > +	acpi_status status;
> > +	int res_cnt = 0;
> > +
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_count_logic_iores, &res_cnt);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!res_cnt) {
> > +		dev_err(&adev->dev, "no logic IO resources\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> > +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> > +	if (!buffer->pointer)
> > +		return -ENOMEM;
> > +
> > +	resource = (struct acpi_resource *)buffer->pointer;
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_read_one_logicpiores, &resource);
> > +	if (ACPI_FAILURE(status)) {
> > +		kfree(buffer->pointer);
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> > +	resource->length = sizeof(struct acpi_resource);
> > +
> > +	return 0;
> > +}
> 
> IIUC correctly this code is here to count resources and replace them
> with kernel specific IO offsets and I think that's wrong. ACPI devices
> _CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
> with resources that are basically Linux kernel internals specific.
> 
> The problem you are facing is there because there is no way in ACPI
> to specify in FW what you want to describe but that's not a reason
> to make it work by other means.

Mmmm yes I agree with you about not touching the ACPI resources (that indeed
should reflect what we have in the ACPI tables).

However I was thinking that maybe we can have a scan handler that enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

> 
> [...]
> 
> > + * update/set the current I/O resource of the designated device
> node.
> > + * after this calling, the enumeration can be started as the I/O
> resource
> > + * had been translated to logicial I/O from bus-local I/O.
> > + *
> > + * @adev: the device node to be updated the I/O resource;
> > + * @host: the device node where 'adev' is attached, which can be not
> > + *	the parent of 'adev';
> > + *
> > + * return 0 when successful, negative is for failure.
> > + */
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev)
> > +{
> > +	struct acpi_device *adev;
> > +	struct acpi_device *host;
> > +	struct acpi_buffer buffer;
> > +	acpi_status status;
> > +	int ret;
> > +
> > +	if (!child || !hostdev)
> > +		return -EINVAL;
> > +
> > +	host = to_acpi_device(hostdev);
> > +	adev = to_acpi_device(child);
> > +
> > +	/* check the device state */
> > +	if (!adev->status.present) {
> > +		dev_info(child, "ACPI: device is not present!\n");
> > +		return 0;
> > +	}
> > +	/* whether the child had been enumerated? */
> > +	if (acpi_device_enumerated(adev)) {
> > +		dev_info(child, "ACPI: had been enumerated!\n");
> > +		return 0;
> > +	}
> > +
> > +	/* read the _CRS and convert as acpi_buffer */
> > +	status = acpi_build_logicpiores_template(adev, &buffer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_warn(child, "Failure evaluating %s\n",
> METHOD_NAME__CRS);
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* translate the I/O resources */
> > +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> > +	if (ret) {
> > +		kfree(buffer.pointer);
> > +		dev_err(child, "Translate I/O range FAIL!\n");
> > +		return ret;
> > +	}
> > +
> > +	/* set current resource... */
> > +	status = acpi_set_current_resources(adev->handle, &buffer);
> 
> I reckon that this is wrong. You are updating ACPI device resources
> with
> kernel specific built resources (ie IO space offsets) made by slicing
> up
> IO space into the kernel available virtual address space offset
> allocated to it.
> 
> IIUC this is done to make sure platform devices contains the
> "translated" resources by the time they are probed, it is hard
> to follow and again, not correct from an ACPI standpoint.
> 
> Furthermore I have no idea how this code is supposed to be used by
> _any_ other platform, ACPI just has no notion of the translation you
> are carrying out here (which mirrors what's done in DT without any
> firmware binding to support it) so even if any other platform has
> the same requirements I have no idea how people developing FW may
> write their bindings to match these given that they just don't exist.

Agreed see proposal above

> 
> > +	kfree(buffer.pointer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> > +		ret = -EIO;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* All the host devices which apply indirect-PIO can be listed here.
> */
> > +static const struct acpi_device_id acpi_indirect_host_id[] = {
> > +	{""},
> 
> How can this be used by any other platform other than Hisilicon LPC ?

The pre_setup() callback is host specific. It would be used by any other
host that needs to enumerate its children with logic PIOs rather than bus
addresses  

> 
> Imagine for a minute you have an ARM64 platform with an LPC bus in it
> and you have to write ACPI tables to describe it, you may not want
> to start by reading Linux kernel code to understand how to do it.

Well you don't really need to do it. I agree that it is wrong to manipulate
directly the acpi resources; however the translation process would be
independent of the bus addresses to be used in the ACPI tables...

> 
> This code is Hisilicon specific code (ie there is no ACPI binding to
> the best of my knowledge describing to FW developers an LPC binding)
> and on the ACPI side it makes assumptions that I am not sure are
> correct at all, see above.
> 
> > +};
> > +
> > +static int acpi_indirectpio_attach(struct acpi_device *adev,
> > +				const struct acpi_device_id *id)
> > +{
> > +	struct indirect_pio_device_desc *hostdata;
> > +	struct platform_device *pdev;
> > +	int ret;
> > +
> > +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> > +	if (!hostdata || !hostdata->pre_setup)
> > +		return -EINVAL;
> > +
> > +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> > +	if (!ret) {
> > +		pdev = acpi_create_platform_device(adev, NULL);
> 
> So, this is done through a scan handler for what reason ? Is this
> because you want this code to run before platform devices are created
> by ACPI core - so that you can update their resources in the
> 
> struct indirect_pio_device_desc.pre_setup() method ?
> 
> I suspect this is yet another probing order issue to solve but that's
> orthogonal to the comments I made above.

Correct :) see above

> 
> To sum it up:
> 
> (1) Creating an ARM64 ACPI standard kernel layer to parse something
> that is
>     not an ACPI (let alone ARM64) standard does not make much sense to
> me,
>     so either standard bindings are published for other partners to use
>     them or this code belongs to Hisilicon specific LPC bus management
> (2) Even with (1), I have concerns about this patch ACPI resources
>     handling, I really think it is wrong to update ACPI devices
>     resources with something that is Linux kernel specific. I may
>     understand building platform devices resources according to your
>     LPC bus requirements but not updating ACPI device FW bindings with
>     resources that are basically kernel internals.

On (2) I agree (please see proposal above)
On (1) I am not very sure about any binding needed at all...in the end
we are mapping a bus range into a virtual IO address space (Logic PIO)...

Cheers
Gab

> 
> Thanks,
> Lorenzo
> 
> > +		if (IS_ERR_OR_NULL(pdev)) {
> > +			dev_err(&adev->dev, "Create platform device for host
> FAIL!\n");
> > +			return -EFAULT;
> > +		}
> > +		acpi_device_set_enumerated(adev);
> > +		ret = 1;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +
> > +static struct acpi_scan_handler acpi_indirect_handler = {
> > +	.ids = acpi_indirect_host_id,
> > +	.attach = acpi_indirectpio_attach,
> > +};
> > +
> > +void __init acpi_indirectio_scan_init(void)
> > +{
> > +	acpi_scan_add_handler(&acpi_indirect_handler);
> > +}
> > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> > index 66229ff..bf8aaf8 100644
> > --- a/drivers/acpi/internal.h
> > +++ b/drivers/acpi/internal.h
> > @@ -31,6 +31,11 @@ void acpi_processor_init(void);
> >  void acpi_platform_init(void);
> >  void acpi_pnp_init(void);
> >  void acpi_int340x_thermal_init(void);
> > +#ifdef CONFIG_INDIRECT_PIO
> > +void acpi_indirectio_scan_init(void);
> > +#else
> > +static inline void acpi_indirectio_scan_init(void) {}
> > +#endif
> >  #ifdef CONFIG_ARM_AMBA
> >  void acpi_amba_init(void);
> >  #else
> > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > index e39ec7b..37dd23c 100644
> > --- a/drivers/acpi/scan.c
> > +++ b/drivers/acpi/scan.c
> > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> >  	acpi_int340x_thermal_init();
> >  	acpi_amba_init();
> >  	acpi_watchdog_init();
> > +	acpi_indirectio_scan_init();
> >
> >  	acpi_scan_add_handler(&generic_device_handler);
> >
> > diff --git a/include/acpi/acpi_indirect_pio.h
> b/include/acpi/acpi_indirect_pio.h
> > new file mode 100644
> > index 0000000..efc5c43
> > --- /dev/null
> > +++ b/include/acpi/acpi_indirect_pio.h
> > @@ -0,0 +1,24 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#ifndef _ACPI_INDIRECT_PIO_H
> > +#define _ACPI_INDIRECT_PIO_H
> > +
> > +struct indirect_pio_device_desc {
> > +	void *pdata; /* device relevant info data */
> > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > +};
> > +
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev);
> > +
> > +#endif
> > --
> > 2.7.4
> >
> >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-31 10:24       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-31 10:24 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	rafael, arnd, linux-arm-kernel, mark.rutland, brian.starkey,
	olof, benh, linux-kernel, linux-acpi, Linuxarm, linux-pci,
	minyard, John Garry, xuwei (O)

Hi Lorenzo

Many thanks for reviewing

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com]
> Sent: 30 May 2017 14:24
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> mark.rutland@arm.com; brian.starkey@arm.com; olof@lixom.net;
> benh@kernel.crashing.org; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; Linuxarm; linux-pci@vger.kernel.org;
> minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Gab,
> 
> On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> > From: Gabriele <gabriele.paoloni@huawei.com>
> >
> > On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices
> access
> > I/O with some special host-local I/O ports known on x86. As their I/O
> > space are not memory mapped like PCI/PCIE MMIO host bridges, this
> patch is
> > meant to support a new class of I/O host controllers where the local
> IO
> > ports of the children devices are translated into the Indirect I/O
> address
> > space.
> > Through the handler attach callback, all the I/O translations are
> done
> > before starting the enumeration on children devices and the
> translated
> > addresses are replaced in the children resources.
> 
> I do not understand why this is done through a scan handler and to
> be frank I do not see how this mechanism is supposed to be a generic
> kernel layer, possibly used by other platforms, when there is no notion
> in ACPI to cater for that.

Well, the main reason is that we need to translate the bus addresses of
the LPC children before the respective children's drivers probe.

> 
> As far as I am concerned this patch code should live in the Hisilicon
> LPC driver - as things stand it is neither ACPI generic code nor ARM64
> specific, it is code to make ACPI work like DT bindings without any
> ACPI
> binding at all; I still have some concerns from an ACPI standpoint
> below.

Well the reason why this patch cannot live in the LPC driver probe is
that AFAIK currently there is no way to guarantee the LPC probe to be
called before the children probe. With respect to the ACPI concerns
please see below.

> 
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  drivers/acpi/arm64/Makefile            |   1 +
> >  drivers/acpi/arm64/acpi_indirect_pio.c | 301
> +++++++++++++++++++++++++++++++++
> >  drivers/acpi/internal.h                |   5 +
> >  drivers/acpi/scan.c                    |   1 +
> >  include/acpi/acpi_indirect_pio.h       |  24 +++
> >  5 files changed, 332 insertions(+)
> >  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
> >  create mode 100644 include/acpi/acpi_indirect_pio.h
> >
> > diff --git a/drivers/acpi/arm64/Makefile
> b/drivers/acpi/arm64/Makefile
> > index 1017def..3944775 100644
> > --- a/drivers/acpi/arm64/Makefile
> > +++ b/drivers/acpi/arm64/Makefile
> > @@ -1,2 +1,3 @@
> >  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
> >  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> > +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> > diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c
> b/drivers/acpi/arm64/acpi_indirect_pio.c
> > new file mode 100644
> > index 0000000..7813f73
> > --- /dev/null
> > +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> > @@ -0,0 +1,301 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/logic_pio.h>
> > +
> > +#include <acpi/acpi_indirect_pio.h>
> > +
> > +ACPI_MODULE_NAME("indirect PIO");
> > +
> > +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> > +
> > +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> > +					   void *data)
> > +{
> > +	int *res_cnt = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> > +		(*res_cnt)++;
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status acpi_read_one_logicpiores(struct acpi_resource
> *res,
> > +		void *data)
> > +{
> > +	struct acpi_resource **resource = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> > +		memcpy((*resource), res, sizeof(struct acpi_resource));
> > +		(*resource)->length = sizeof(struct acpi_resource);
> > +		(*resource)->type = res->type;
> > +		(*resource)++;
> > +	}
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status
> > +acpi_build_logicpiores_template(struct acpi_device *adev,
> > +			struct acpi_buffer *buffer)
> > +{
> > +	acpi_handle handle = adev->handle;
> > +	struct acpi_resource *resource;
> > +	acpi_status status;
> > +	int res_cnt = 0;
> > +
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_count_logic_iores, &res_cnt);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!res_cnt) {
> > +		dev_err(&adev->dev, "no logic IO resources\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> > +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> > +	if (!buffer->pointer)
> > +		return -ENOMEM;
> > +
> > +	resource = (struct acpi_resource *)buffer->pointer;
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_read_one_logicpiores, &resource);
> > +	if (ACPI_FAILURE(status)) {
> > +		kfree(buffer->pointer);
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> > +	resource->length = sizeof(struct acpi_resource);
> > +
> > +	return 0;
> > +}
> 
> IIUC correctly this code is here to count resources and replace them
> with kernel specific IO offsets and I think that's wrong. ACPI devices
> _CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
> with resources that are basically Linux kernel internals specific.
> 
> The problem you are facing is there because there is no way in ACPI
> to specify in FW what you want to describe but that's not a reason
> to make it work by other means.

Mmmm yes I agree with you about not touching the ACPI resources (that indeed
should reflect what we have in the ACPI tables).

However I was thinking that maybe we can have a scan handler that enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

> 
> [...]
> 
> > + * update/set the current I/O resource of the designated device
> node.
> > + * after this calling, the enumeration can be started as the I/O
> resource
> > + * had been translated to logicial I/O from bus-local I/O.
> > + *
> > + * @adev: the device node to be updated the I/O resource;
> > + * @host: the device node where 'adev' is attached, which can be not
> > + *	the parent of 'adev';
> > + *
> > + * return 0 when successful, negative is for failure.
> > + */
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev)
> > +{
> > +	struct acpi_device *adev;
> > +	struct acpi_device *host;
> > +	struct acpi_buffer buffer;
> > +	acpi_status status;
> > +	int ret;
> > +
> > +	if (!child || !hostdev)
> > +		return -EINVAL;
> > +
> > +	host = to_acpi_device(hostdev);
> > +	adev = to_acpi_device(child);
> > +
> > +	/* check the device state */
> > +	if (!adev->status.present) {
> > +		dev_info(child, "ACPI: device is not present!\n");
> > +		return 0;
> > +	}
> > +	/* whether the child had been enumerated? */
> > +	if (acpi_device_enumerated(adev)) {
> > +		dev_info(child, "ACPI: had been enumerated!\n");
> > +		return 0;
> > +	}
> > +
> > +	/* read the _CRS and convert as acpi_buffer */
> > +	status = acpi_build_logicpiores_template(adev, &buffer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_warn(child, "Failure evaluating %s\n",
> METHOD_NAME__CRS);
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* translate the I/O resources */
> > +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> > +	if (ret) {
> > +		kfree(buffer.pointer);
> > +		dev_err(child, "Translate I/O range FAIL!\n");
> > +		return ret;
> > +	}
> > +
> > +	/* set current resource... */
> > +	status = acpi_set_current_resources(adev->handle, &buffer);
> 
> I reckon that this is wrong. You are updating ACPI device resources
> with
> kernel specific built resources (ie IO space offsets) made by slicing
> up
> IO space into the kernel available virtual address space offset
> allocated to it.
> 
> IIUC this is done to make sure platform devices contains the
> "translated" resources by the time they are probed, it is hard
> to follow and again, not correct from an ACPI standpoint.
> 
> Furthermore I have no idea how this code is supposed to be used by
> _any_ other platform, ACPI just has no notion of the translation you
> are carrying out here (which mirrors what's done in DT without any
> firmware binding to support it) so even if any other platform has
> the same requirements I have no idea how people developing FW may
> write their bindings to match these given that they just don't exist.

Agreed see proposal above

> 
> > +	kfree(buffer.pointer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> > +		ret = -EIO;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* All the host devices which apply indirect-PIO can be listed here.
> */
> > +static const struct acpi_device_id acpi_indirect_host_id[] = {
> > +	{""},
> 
> How can this be used by any other platform other than Hisilicon LPC ?

The pre_setup() callback is host specific. It would be used by any other
host that needs to enumerate its children with logic PIOs rather than bus
addresses  

> 
> Imagine for a minute you have an ARM64 platform with an LPC bus in it
> and you have to write ACPI tables to describe it, you may not want
> to start by reading Linux kernel code to understand how to do it.

Well you don't really need to do it. I agree that it is wrong to manipulate
directly the acpi resources; however the translation process would be
independent of the bus addresses to be used in the ACPI tables...

> 
> This code is Hisilicon specific code (ie there is no ACPI binding to
> the best of my knowledge describing to FW developers an LPC binding)
> and on the ACPI side it makes assumptions that I am not sure are
> correct at all, see above.
> 
> > +};
> > +
> > +static int acpi_indirectpio_attach(struct acpi_device *adev,
> > +				const struct acpi_device_id *id)
> > +{
> > +	struct indirect_pio_device_desc *hostdata;
> > +	struct platform_device *pdev;
> > +	int ret;
> > +
> > +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> > +	if (!hostdata || !hostdata->pre_setup)
> > +		return -EINVAL;
> > +
> > +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> > +	if (!ret) {
> > +		pdev = acpi_create_platform_device(adev, NULL);
> 
> So, this is done through a scan handler for what reason ? Is this
> because you want this code to run before platform devices are created
> by ACPI core - so that you can update their resources in the
> 
> struct indirect_pio_device_desc.pre_setup() method ?
> 
> I suspect this is yet another probing order issue to solve but that's
> orthogonal to the comments I made above.

Correct :) see above

> 
> To sum it up:
> 
> (1) Creating an ARM64 ACPI standard kernel layer to parse something
> that is
>     not an ACPI (let alone ARM64) standard does not make much sense to
> me,
>     so either standard bindings are published for other partners to use
>     them or this code belongs to Hisilicon specific LPC bus management
> (2) Even with (1), I have concerns about this patch ACPI resources
>     handling, I really think it is wrong to update ACPI devices
>     resources with something that is Linux kernel specific. I may
>     understand building platform devices resources according to your
>     LPC bus requirements but not updating ACPI device FW bindings with
>     resources that are basically kernel internals.

On (2) I agree (please see proposal above)
On (1) I am not very sure about any binding needed at all...in the end
we are mapping a bus range into a virtual IO address space (Logic PIO)...

Cheers
Gab

> 
> Thanks,
> Lorenzo
> 
> > +		if (IS_ERR_OR_NULL(pdev)) {
> > +			dev_err(&adev->dev, "Create platform device for host
> FAIL!\n");
> > +			return -EFAULT;
> > +		}
> > +		acpi_device_set_enumerated(adev);
> > +		ret = 1;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +
> > +static struct acpi_scan_handler acpi_indirect_handler = {
> > +	.ids = acpi_indirect_host_id,
> > +	.attach = acpi_indirectpio_attach,
> > +};
> > +
> > +void __init acpi_indirectio_scan_init(void)
> > +{
> > +	acpi_scan_add_handler(&acpi_indirect_handler);
> > +}
> > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> > index 66229ff..bf8aaf8 100644
> > --- a/drivers/acpi/internal.h
> > +++ b/drivers/acpi/internal.h
> > @@ -31,6 +31,11 @@ void acpi_processor_init(void);
> >  void acpi_platform_init(void);
> >  void acpi_pnp_init(void);
> >  void acpi_int340x_thermal_init(void);
> > +#ifdef CONFIG_INDIRECT_PIO
> > +void acpi_indirectio_scan_init(void);
> > +#else
> > +static inline void acpi_indirectio_scan_init(void) {}
> > +#endif
> >  #ifdef CONFIG_ARM_AMBA
> >  void acpi_amba_init(void);
> >  #else
> > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > index e39ec7b..37dd23c 100644
> > --- a/drivers/acpi/scan.c
> > +++ b/drivers/acpi/scan.c
> > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> >  	acpi_int340x_thermal_init();
> >  	acpi_amba_init();
> >  	acpi_watchdog_init();
> > +	acpi_indirectio_scan_init();
> >
> >  	acpi_scan_add_handler(&generic_device_handler);
> >
> > diff --git a/include/acpi/acpi_indirect_pio.h
> b/include/acpi/acpi_indirect_pio.h
> > new file mode 100644
> > index 0000000..efc5c43
> > --- /dev/null
> > +++ b/include/acpi/acpi_indirect_pio.h
> > @@ -0,0 +1,24 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#ifndef _ACPI_INDIRECT_PIO_H
> > +#define _ACPI_INDIRECT_PIO_H
> > +
> > +struct indirect_pio_device_desc {
> > +	void *pdata; /* device relevant info data */
> > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > +};
> > +
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev);
> > +
> > +#endif
> > --
> > 2.7.4
> >
> >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-31 10:24       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-31 10:24 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: mark.rutland, minyard, linux-acpi, arnd, rafael, linux-pci,
	catalin.marinas, John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, benh, bhelgaas, frowand.list,
	brian.starkey, linux-arm-kernel

Hi Lorenzo

Many thanks for reviewing

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com]
> Sent: 30 May 2017 14:24
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> mark.rutland@arm.com; brian.starkey@arm.com; olof@lixom.net;
> benh@kernel.crashing.org; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; Linuxarm; linux-pci@vger.kernel.org;
> minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Gab,
> 
> On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> > From: Gabriele <gabriele.paoloni@huawei.com>
> >
> > On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices
> access
> > I/O with some special host-local I/O ports known on x86. As their I/O
> > space are not memory mapped like PCI/PCIE MMIO host bridges, this
> patch is
> > meant to support a new class of I/O host controllers where the local
> IO
> > ports of the children devices are translated into the Indirect I/O
> address
> > space.
> > Through the handler attach callback, all the I/O translations are
> done
> > before starting the enumeration on children devices and the
> translated
> > addresses are replaced in the children resources.
> 
> I do not understand why this is done through a scan handler and to
> be frank I do not see how this mechanism is supposed to be a generic
> kernel layer, possibly used by other platforms, when there is no notion
> in ACPI to cater for that.

Well, the main reason is that we need to translate the bus addresses of
the LPC children before the respective children's drivers probe.

> 
> As far as I am concerned this patch code should live in the Hisilicon
> LPC driver - as things stand it is neither ACPI generic code nor ARM64
> specific, it is code to make ACPI work like DT bindings without any
> ACPI
> binding at all; I still have some concerns from an ACPI standpoint
> below.

Well the reason why this patch cannot live in the LPC driver probe is
that AFAIK currently there is no way to guarantee the LPC probe to be
called before the children probe. With respect to the ACPI concerns
please see below.

> 
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  drivers/acpi/arm64/Makefile            |   1 +
> >  drivers/acpi/arm64/acpi_indirect_pio.c | 301
> +++++++++++++++++++++++++++++++++
> >  drivers/acpi/internal.h                |   5 +
> >  drivers/acpi/scan.c                    |   1 +
> >  include/acpi/acpi_indirect_pio.h       |  24 +++
> >  5 files changed, 332 insertions(+)
> >  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
> >  create mode 100644 include/acpi/acpi_indirect_pio.h
> >
> > diff --git a/drivers/acpi/arm64/Makefile
> b/drivers/acpi/arm64/Makefile
> > index 1017def..3944775 100644
> > --- a/drivers/acpi/arm64/Makefile
> > +++ b/drivers/acpi/arm64/Makefile
> > @@ -1,2 +1,3 @@
> >  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
> >  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> > +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> > diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c
> b/drivers/acpi/arm64/acpi_indirect_pio.c
> > new file mode 100644
> > index 0000000..7813f73
> > --- /dev/null
> > +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> > @@ -0,0 +1,301 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/logic_pio.h>
> > +
> > +#include <acpi/acpi_indirect_pio.h>
> > +
> > +ACPI_MODULE_NAME("indirect PIO");
> > +
> > +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> > +
> > +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> > +					   void *data)
> > +{
> > +	int *res_cnt = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> > +		(*res_cnt)++;
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status acpi_read_one_logicpiores(struct acpi_resource
> *res,
> > +		void *data)
> > +{
> > +	struct acpi_resource **resource = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> > +		memcpy((*resource), res, sizeof(struct acpi_resource));
> > +		(*resource)->length = sizeof(struct acpi_resource);
> > +		(*resource)->type = res->type;
> > +		(*resource)++;
> > +	}
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status
> > +acpi_build_logicpiores_template(struct acpi_device *adev,
> > +			struct acpi_buffer *buffer)
> > +{
> > +	acpi_handle handle = adev->handle;
> > +	struct acpi_resource *resource;
> > +	acpi_status status;
> > +	int res_cnt = 0;
> > +
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_count_logic_iores, &res_cnt);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!res_cnt) {
> > +		dev_err(&adev->dev, "no logic IO resources\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> > +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> > +	if (!buffer->pointer)
> > +		return -ENOMEM;
> > +
> > +	resource = (struct acpi_resource *)buffer->pointer;
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_read_one_logicpiores, &resource);
> > +	if (ACPI_FAILURE(status)) {
> > +		kfree(buffer->pointer);
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> > +	resource->length = sizeof(struct acpi_resource);
> > +
> > +	return 0;
> > +}
> 
> IIUC correctly this code is here to count resources and replace them
> with kernel specific IO offsets and I think that's wrong. ACPI devices
> _CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
> with resources that are basically Linux kernel internals specific.
> 
> The problem you are facing is there because there is no way in ACPI
> to specify in FW what you want to describe but that's not a reason
> to make it work by other means.

Mmmm yes I agree with you about not touching the ACPI resources (that indeed
should reflect what we have in the ACPI tables).

However I was thinking that maybe we can have a scan handler that enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

> 
> [...]
> 
> > + * update/set the current I/O resource of the designated device
> node.
> > + * after this calling, the enumeration can be started as the I/O
> resource
> > + * had been translated to logicial I/O from bus-local I/O.
> > + *
> > + * @adev: the device node to be updated the I/O resource;
> > + * @host: the device node where 'adev' is attached, which can be not
> > + *	the parent of 'adev';
> > + *
> > + * return 0 when successful, negative is for failure.
> > + */
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev)
> > +{
> > +	struct acpi_device *adev;
> > +	struct acpi_device *host;
> > +	struct acpi_buffer buffer;
> > +	acpi_status status;
> > +	int ret;
> > +
> > +	if (!child || !hostdev)
> > +		return -EINVAL;
> > +
> > +	host = to_acpi_device(hostdev);
> > +	adev = to_acpi_device(child);
> > +
> > +	/* check the device state */
> > +	if (!adev->status.present) {
> > +		dev_info(child, "ACPI: device is not present!\n");
> > +		return 0;
> > +	}
> > +	/* whether the child had been enumerated? */
> > +	if (acpi_device_enumerated(adev)) {
> > +		dev_info(child, "ACPI: had been enumerated!\n");
> > +		return 0;
> > +	}
> > +
> > +	/* read the _CRS and convert as acpi_buffer */
> > +	status = acpi_build_logicpiores_template(adev, &buffer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_warn(child, "Failure evaluating %s\n",
> METHOD_NAME__CRS);
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* translate the I/O resources */
> > +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> > +	if (ret) {
> > +		kfree(buffer.pointer);
> > +		dev_err(child, "Translate I/O range FAIL!\n");
> > +		return ret;
> > +	}
> > +
> > +	/* set current resource... */
> > +	status = acpi_set_current_resources(adev->handle, &buffer);
> 
> I reckon that this is wrong. You are updating ACPI device resources
> with
> kernel specific built resources (ie IO space offsets) made by slicing
> up
> IO space into the kernel available virtual address space offset
> allocated to it.
> 
> IIUC this is done to make sure platform devices contains the
> "translated" resources by the time they are probed, it is hard
> to follow and again, not correct from an ACPI standpoint.
> 
> Furthermore I have no idea how this code is supposed to be used by
> _any_ other platform, ACPI just has no notion of the translation you
> are carrying out here (which mirrors what's done in DT without any
> firmware binding to support it) so even if any other platform has
> the same requirements I have no idea how people developing FW may
> write their bindings to match these given that they just don't exist.

Agreed see proposal above

> 
> > +	kfree(buffer.pointer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> > +		ret = -EIO;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* All the host devices which apply indirect-PIO can be listed here.
> */
> > +static const struct acpi_device_id acpi_indirect_host_id[] = {
> > +	{""},
> 
> How can this be used by any other platform other than Hisilicon LPC ?

The pre_setup() callback is host specific. It would be used by any other
host that needs to enumerate its children with logic PIOs rather than bus
addresses  

> 
> Imagine for a minute you have an ARM64 platform with an LPC bus in it
> and you have to write ACPI tables to describe it, you may not want
> to start by reading Linux kernel code to understand how to do it.

Well you don't really need to do it. I agree that it is wrong to manipulate
directly the acpi resources; however the translation process would be
independent of the bus addresses to be used in the ACPI tables...

> 
> This code is Hisilicon specific code (ie there is no ACPI binding to
> the best of my knowledge describing to FW developers an LPC binding)
> and on the ACPI side it makes assumptions that I am not sure are
> correct at all, see above.
> 
> > +};
> > +
> > +static int acpi_indirectpio_attach(struct acpi_device *adev,
> > +				const struct acpi_device_id *id)
> > +{
> > +	struct indirect_pio_device_desc *hostdata;
> > +	struct platform_device *pdev;
> > +	int ret;
> > +
> > +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> > +	if (!hostdata || !hostdata->pre_setup)
> > +		return -EINVAL;
> > +
> > +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> > +	if (!ret) {
> > +		pdev = acpi_create_platform_device(adev, NULL);
> 
> So, this is done through a scan handler for what reason ? Is this
> because you want this code to run before platform devices are created
> by ACPI core - so that you can update their resources in the
> 
> struct indirect_pio_device_desc.pre_setup() method ?
> 
> I suspect this is yet another probing order issue to solve but that's
> orthogonal to the comments I made above.

Correct :) see above

> 
> To sum it up:
> 
> (1) Creating an ARM64 ACPI standard kernel layer to parse something
> that is
>     not an ACPI (let alone ARM64) standard does not make much sense to
> me,
>     so either standard bindings are published for other partners to use
>     them or this code belongs to Hisilicon specific LPC bus management
> (2) Even with (1), I have concerns about this patch ACPI resources
>     handling, I really think it is wrong to update ACPI devices
>     resources with something that is Linux kernel specific. I may
>     understand building platform devices resources according to your
>     LPC bus requirements but not updating ACPI device FW bindings with
>     resources that are basically kernel internals.

On (2) I agree (please see proposal above)
On (1) I am not very sure about any binding needed at all...in the end
we are mapping a bus range into a virtual IO address space (Logic PIO)...

Cheers
Gab

> 
> Thanks,
> Lorenzo
> 
> > +		if (IS_ERR_OR_NULL(pdev)) {
> > +			dev_err(&adev->dev, "Create platform device for host
> FAIL!\n");
> > +			return -EFAULT;
> > +		}
> > +		acpi_device_set_enumerated(adev);
> > +		ret = 1;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +
> > +static struct acpi_scan_handler acpi_indirect_handler = {
> > +	.ids = acpi_indirect_host_id,
> > +	.attach = acpi_indirectpio_attach,
> > +};
> > +
> > +void __init acpi_indirectio_scan_init(void)
> > +{
> > +	acpi_scan_add_handler(&acpi_indirect_handler);
> > +}
> > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> > index 66229ff..bf8aaf8 100644
> > --- a/drivers/acpi/internal.h
> > +++ b/drivers/acpi/internal.h
> > @@ -31,6 +31,11 @@ void acpi_processor_init(void);
> >  void acpi_platform_init(void);
> >  void acpi_pnp_init(void);
> >  void acpi_int340x_thermal_init(void);
> > +#ifdef CONFIG_INDIRECT_PIO
> > +void acpi_indirectio_scan_init(void);
> > +#else
> > +static inline void acpi_indirectio_scan_init(void) {}
> > +#endif
> >  #ifdef CONFIG_ARM_AMBA
> >  void acpi_amba_init(void);
> >  #else
> > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > index e39ec7b..37dd23c 100644
> > --- a/drivers/acpi/scan.c
> > +++ b/drivers/acpi/scan.c
> > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> >  	acpi_int340x_thermal_init();
> >  	acpi_amba_init();
> >  	acpi_watchdog_init();
> > +	acpi_indirectio_scan_init();
> >
> >  	acpi_scan_add_handler(&generic_device_handler);
> >
> > diff --git a/include/acpi/acpi_indirect_pio.h
> b/include/acpi/acpi_indirect_pio.h
> > new file mode 100644
> > index 0000000..efc5c43
> > --- /dev/null
> > +++ b/include/acpi/acpi_indirect_pio.h
> > @@ -0,0 +1,24 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#ifndef _ACPI_INDIRECT_PIO_H
> > +#define _ACPI_INDIRECT_PIO_H
> > +
> > +struct indirect_pio_device_desc {
> > +	void *pdata; /* device relevant info data */
> > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > +};
> > +
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev);
> > +
> > +#endif
> > --
> > 2.7.4
> >
> >

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-05-31 10:24       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-05-31 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo

Many thanks for reviewing

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> Sent: 30 May 2017 14:24
> To: Gabriele Paoloni
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; rafael at kernel.org;
> arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> mark.rutland at arm.com; brian.starkey at arm.com; olof at lixom.net;
> benh at kernel.crashing.org; linux-kernel at vger.kernel.org; linux-
> acpi at vger.kernel.org; Linuxarm; linux-pci at vger.kernel.org;
> minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Gab,
> 
> On Thu, May 25, 2017 at 12:37:26PM +0100, Gabriele Paoloni wrote:
> > From: Gabriele <gabriele.paoloni@huawei.com>
> >
> > On some platforms(such as Hip06/Hip07), the legacy ISA/LPC devices
> access
> > I/O with some special host-local I/O ports known on x86. As their I/O
> > space are not memory mapped like PCI/PCIE MMIO host bridges, this
> patch is
> > meant to support a new class of I/O host controllers where the local
> IO
> > ports of the children devices are translated into the Indirect I/O
> address
> > space.
> > Through the handler attach callback, all the I/O translations are
> done
> > before starting the enumeration on children devices and the
> translated
> > addresses are replaced in the children resources.
> 
> I do not understand why this is done through a scan handler and to
> be frank I do not see how this mechanism is supposed to be a generic
> kernel layer, possibly used by other platforms, when there is no notion
> in ACPI to cater for that.

Well, the main reason is that we need to translate the bus addresses of
the LPC children before the respective children's drivers probe.

> 
> As far as I am concerned this patch code should live in the Hisilicon
> LPC driver - as things stand it is neither ACPI generic code nor ARM64
> specific, it is code to make ACPI work like DT bindings without any
> ACPI
> binding at all; I still have some concerns from an ACPI standpoint
> below.

Well the reason why this patch cannot live in the LPC driver probe is
that AFAIK currently there is no way to guarantee the LPC probe to be
called before the children probe. With respect to the ACPI concerns
please see below.

> 
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  drivers/acpi/arm64/Makefile            |   1 +
> >  drivers/acpi/arm64/acpi_indirect_pio.c | 301
> +++++++++++++++++++++++++++++++++
> >  drivers/acpi/internal.h                |   5 +
> >  drivers/acpi/scan.c                    |   1 +
> >  include/acpi/acpi_indirect_pio.h       |  24 +++
> >  5 files changed, 332 insertions(+)
> >  create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
> >  create mode 100644 include/acpi/acpi_indirect_pio.h
> >
> > diff --git a/drivers/acpi/arm64/Makefile
> b/drivers/acpi/arm64/Makefile
> > index 1017def..3944775 100644
> > --- a/drivers/acpi/arm64/Makefile
> > +++ b/drivers/acpi/arm64/Makefile
> > @@ -1,2 +1,3 @@
> >  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
> >  obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> > +obj-$(CONFIG_INDIRECT_PIO) += acpi_indirect_pio.o
> > diff --git a/drivers/acpi/arm64/acpi_indirect_pio.c
> b/drivers/acpi/arm64/acpi_indirect_pio.c
> > new file mode 100644
> > index 0000000..7813f73
> > --- /dev/null
> > +++ b/drivers/acpi/arm64/acpi_indirect_pio.c
> > @@ -0,0 +1,301 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/logic_pio.h>
> > +
> > +#include <acpi/acpi_indirect_pio.h>
> > +
> > +ACPI_MODULE_NAME("indirect PIO");
> > +
> > +#define INDIRECT_PIO_INFO(desc) ((unsigned long)&desc)
> > +
> > +static acpi_status acpi_count_logic_iores(struct acpi_resource *res,
> > +					   void *data)
> > +{
> > +	int *res_cnt = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO))
> > +		(*res_cnt)++;
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status acpi_read_one_logicpiores(struct acpi_resource
> *res,
> > +		void *data)
> > +{
> > +	struct acpi_resource **resource = data;
> > +
> > +	if (!acpi_dev_filter_resource_type(res, IORESOURCE_IO)) {
> > +		memcpy((*resource), res, sizeof(struct acpi_resource));
> > +		(*resource)->length = sizeof(struct acpi_resource);
> > +		(*resource)->type = res->type;
> > +		(*resource)++;
> > +	}
> > +
> > +	return AE_OK;
> > +}
> > +
> > +static acpi_status
> > +acpi_build_logicpiores_template(struct acpi_device *adev,
> > +			struct acpi_buffer *buffer)
> > +{
> > +	acpi_handle handle = adev->handle;
> > +	struct acpi_resource *resource;
> > +	acpi_status status;
> > +	int res_cnt = 0;
> > +
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_count_logic_iores, &res_cnt);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!res_cnt) {
> > +		dev_err(&adev->dev, "no logic IO resources\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1);
> > +	buffer->pointer = kzalloc(buffer->length, GFP_KERNEL);
> > +	if (!buffer->pointer)
> > +		return -ENOMEM;
> > +
> > +	resource = (struct acpi_resource *)buffer->pointer;
> > +	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
> > +				     acpi_read_one_logicpiores, &resource);
> > +	if (ACPI_FAILURE(status)) {
> > +		kfree(buffer->pointer);
> > +		dev_err(&adev->dev, "can't evaluate _CRS: %d\n", status);
> > +		return -EINVAL;
> > +	}
> > +
> > +	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
> > +	resource->length = sizeof(struct acpi_resource);
> > +
> > +	return 0;
> > +}
> 
> IIUC correctly this code is here to count resources and replace them
> with kernel specific IO offsets and I think that's wrong. ACPI devices
> _CRS,_PRS,_SRS are set-up by firmware and by no means should be updated
> with resources that are basically Linux kernel internals specific.
> 
> The problem you are facing is there because there is no way in ACPI
> to specify in FW what you want to describe but that's not a reason
> to make it work by other means.

Mmmm yes I agree with you about not touching the ACPI resources (that indeed
should reflect what we have in the ACPI tables).

However I was thinking that maybe we can have a scan handler that enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

> 
> [...]
> 
> > + * update/set the current I/O resource of the designated device
> node.
> > + * after this calling, the enumeration can be started as the I/O
> resource
> > + * had been translated to logicial I/O from bus-local I/O.
> > + *
> > + * @adev: the device node to be updated the I/O resource;
> > + * @host: the device node where 'adev' is attached, which can be not
> > + *	the parent of 'adev';
> > + *
> > + * return 0 when successful, negative is for failure.
> > + */
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev)
> > +{
> > +	struct acpi_device *adev;
> > +	struct acpi_device *host;
> > +	struct acpi_buffer buffer;
> > +	acpi_status status;
> > +	int ret;
> > +
> > +	if (!child || !hostdev)
> > +		return -EINVAL;
> > +
> > +	host = to_acpi_device(hostdev);
> > +	adev = to_acpi_device(child);
> > +
> > +	/* check the device state */
> > +	if (!adev->status.present) {
> > +		dev_info(child, "ACPI: device is not present!\n");
> > +		return 0;
> > +	}
> > +	/* whether the child had been enumerated? */
> > +	if (acpi_device_enumerated(adev)) {
> > +		dev_info(child, "ACPI: had been enumerated!\n");
> > +		return 0;
> > +	}
> > +
> > +	/* read the _CRS and convert as acpi_buffer */
> > +	status = acpi_build_logicpiores_template(adev, &buffer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_warn(child, "Failure evaluating %s\n",
> METHOD_NAME__CRS);
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* translate the I/O resources */
> > +	ret = acpi_translate_logicpiores(adev, host, &buffer);
> > +	if (ret) {
> > +		kfree(buffer.pointer);
> > +		dev_err(child, "Translate I/O range FAIL!\n");
> > +		return ret;
> > +	}
> > +
> > +	/* set current resource... */
> > +	status = acpi_set_current_resources(adev->handle, &buffer);
> 
> I reckon that this is wrong. You are updating ACPI device resources
> with
> kernel specific built resources (ie IO space offsets) made by slicing
> up
> IO space into the kernel available virtual address space offset
> allocated to it.
> 
> IIUC this is done to make sure platform devices contains the
> "translated" resources by the time they are probed, it is hard
> to follow and again, not correct from an ACPI standpoint.
> 
> Furthermore I have no idea how this code is supposed to be used by
> _any_ other platform, ACPI just has no notion of the translation you
> are carrying out here (which mirrors what's done in DT without any
> firmware binding to support it) so even if any other platform has
> the same requirements I have no idea how people developing FW may
> write their bindings to match these given that they just don't exist.

Agreed see proposal above

> 
> > +	kfree(buffer.pointer);
> > +	if (ACPI_FAILURE(status)) {
> > +		dev_err(child, "Error evaluating _SRS (0x%x)\n", status);
> > +		ret = -EIO;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* All the host devices which apply indirect-PIO can be listed here.
> */
> > +static const struct acpi_device_id acpi_indirect_host_id[] = {
> > +	{""},
> 
> How can this be used by any other platform other than Hisilicon LPC ?

The pre_setup() callback is host specific. It would be used by any other
host that needs to enumerate its children with logic PIOs rather than bus
addresses  

> 
> Imagine for a minute you have an ARM64 platform with an LPC bus in it
> and you have to write ACPI tables to describe it, you may not want
> to start by reading Linux kernel code to understand how to do it.

Well you don't really need to do it. I agree that it is wrong to manipulate
directly the acpi resources; however the translation process would be
independent of the bus addresses to be used in the ACPI tables...

> 
> This code is Hisilicon specific code (ie there is no ACPI binding to
> the best of my knowledge describing to FW developers an LPC binding)
> and on the ACPI side it makes assumptions that I am not sure are
> correct at all, see above.
> 
> > +};
> > +
> > +static int acpi_indirectpio_attach(struct acpi_device *adev,
> > +				const struct acpi_device_id *id)
> > +{
> > +	struct indirect_pio_device_desc *hostdata;
> > +	struct platform_device *pdev;
> > +	int ret;
> > +
> > +	hostdata = (struct indirect_pio_device_desc *)id->driver_data;
> > +	if (!hostdata || !hostdata->pre_setup)
> > +		return -EINVAL;
> > +
> > +	ret = hostdata->pre_setup(adev, hostdata->pdata);
> > +	if (!ret) {
> > +		pdev = acpi_create_platform_device(adev, NULL);
> 
> So, this is done through a scan handler for what reason ? Is this
> because you want this code to run before platform devices are created
> by ACPI core - so that you can update their resources in the
> 
> struct indirect_pio_device_desc.pre_setup() method ?
> 
> I suspect this is yet another probing order issue to solve but that's
> orthogonal to the comments I made above.

Correct :) see above

> 
> To sum it up:
> 
> (1) Creating an ARM64 ACPI standard kernel layer to parse something
> that is
>     not an ACPI (let alone ARM64) standard does not make much sense to
> me,
>     so either standard bindings are published for other partners to use
>     them or this code belongs to Hisilicon specific LPC bus management
> (2) Even with (1), I have concerns about this patch ACPI resources
>     handling, I really think it is wrong to update ACPI devices
>     resources with something that is Linux kernel specific. I may
>     understand building platform devices resources according to your
>     LPC bus requirements but not updating ACPI device FW bindings with
>     resources that are basically kernel internals.

On (2) I agree (please see proposal above)
On (1) I am not very sure about any binding needed at all...in the end
we are mapping a bus range into a virtual IO address space (Logic PIO)...

Cheers
Gab

> 
> Thanks,
> Lorenzo
> 
> > +		if (IS_ERR_OR_NULL(pdev)) {
> > +			dev_err(&adev->dev, "Create platform device for host
> FAIL!\n");
> > +			return -EFAULT;
> > +		}
> > +		acpi_device_set_enumerated(adev);
> > +		ret = 1;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +
> > +static struct acpi_scan_handler acpi_indirect_handler = {
> > +	.ids = acpi_indirect_host_id,
> > +	.attach = acpi_indirectpio_attach,
> > +};
> > +
> > +void __init acpi_indirectio_scan_init(void)
> > +{
> > +	acpi_scan_add_handler(&acpi_indirect_handler);
> > +}
> > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> > index 66229ff..bf8aaf8 100644
> > --- a/drivers/acpi/internal.h
> > +++ b/drivers/acpi/internal.h
> > @@ -31,6 +31,11 @@ void acpi_processor_init(void);
> >  void acpi_platform_init(void);
> >  void acpi_pnp_init(void);
> >  void acpi_int340x_thermal_init(void);
> > +#ifdef CONFIG_INDIRECT_PIO
> > +void acpi_indirectio_scan_init(void);
> > +#else
> > +static inline void acpi_indirectio_scan_init(void) {}
> > +#endif
> >  #ifdef CONFIG_ARM_AMBA
> >  void acpi_amba_init(void);
> >  #else
> > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > index e39ec7b..37dd23c 100644
> > --- a/drivers/acpi/scan.c
> > +++ b/drivers/acpi/scan.c
> > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> >  	acpi_int340x_thermal_init();
> >  	acpi_amba_init();
> >  	acpi_watchdog_init();
> > +	acpi_indirectio_scan_init();
> >
> >  	acpi_scan_add_handler(&generic_device_handler);
> >
> > diff --git a/include/acpi/acpi_indirect_pio.h
> b/include/acpi/acpi_indirect_pio.h
> > new file mode 100644
> > index 0000000..efc5c43
> > --- /dev/null
> > +++ b/include/acpi/acpi_indirect_pio.h
> > @@ -0,0 +1,24 @@
> > +/*
> > + * ACPI support for indirect-PIO bus.
> > + *
> > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#ifndef _ACPI_INDIRECT_PIO_H
> > +#define _ACPI_INDIRECT_PIO_H
> > +
> > +struct indirect_pio_device_desc {
> > +	void *pdata; /* device relevant info data */
> > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > +};
> > +
> > +int acpi_set_logic_pio_resource(struct device *child,
> > +		struct device *hostdev);
> > +
> > +#endif
> > --
> > 2.7.4
> >
> >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-05-31 10:24       ` Gabriele Paoloni
  (?)
  (?)
@ 2017-06-06  8:55         ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-06  8:55 UTC (permalink / raw)
  To: Gabriele Paoloni, rafael
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard@acm.org

Hi Gab, Rafael,

On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:

[...]

> > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > index e39ec7b..37dd23c 100644
> > > --- a/drivers/acpi/scan.c
> > > +++ b/drivers/acpi/scan.c
> > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > >  	acpi_int340x_thermal_init();
> > >  	acpi_amba_init();
> > >  	acpi_watchdog_init();
> > > +	acpi_indirectio_scan_init();

Unfortunately this is becoming a pattern and we are ending up
with a static ordering of "subsystems" init (even though for this
LPC series it is just the Hisilicon driver that requires this call)
and I am not sure I see any way of avoiding it. I think that's always
been the case in x86, with fewer subsystems/kernel paths to care
about, I wanted to flag this up though to check your opinion since
I am not sure this is the right direction we are taking.

I also think that relying on _DEP to build any dependency is not
entirely a) usable (owing to legacy bindings and previous _DEP misuse)
and b) compliant with ACPI bindings given that _DEP has to be used
for operation regions only.

Thoughts ?

Thanks,
Lorenzo

> > >  	acpi_scan_add_handler(&generic_device_handler);
> > >
> > > diff --git a/include/acpi/acpi_indirect_pio.h
> > b/include/acpi/acpi_indirect_pio.h
> > > new file mode 100644
> > > index 0000000..efc5c43
> > > --- /dev/null
> > > +++ b/include/acpi/acpi_indirect_pio.h
> > > @@ -0,0 +1,24 @@
> > > +/*
> > > + * ACPI support for indirect-PIO bus.
> > > + *
> > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > + *
> > > + * This program is free software; you can redistribute it and/or
> > modify
> > > + * it under the terms of the GNU General Public License version 2 as
> > > + * published by the Free Software Foundation.
> > > + */
> > > +
> > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > +#define _ACPI_INDIRECT_PIO_H
> > > +
> > > +struct indirect_pio_device_desc {
> > > +	void *pdata; /* device relevant info data */
> > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > +};
> > > +
> > > +int acpi_set_logic_pio_resource(struct device *child,
> > > +		struct device *hostdev);
> > > +
> > > +#endif
> > > --
> > > 2.7.4
> > >
> > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-06  8:55         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-06  8:55 UTC (permalink / raw)
  To: Gabriele Paoloni, rafael
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Gab, Rafael,

On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:

[...]

> > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > index e39ec7b..37dd23c 100644
> > > --- a/drivers/acpi/scan.c
> > > +++ b/drivers/acpi/scan.c
> > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > >  	acpi_int340x_thermal_init();
> > >  	acpi_amba_init();
> > >  	acpi_watchdog_init();
> > > +	acpi_indirectio_scan_init();

Unfortunately this is becoming a pattern and we are ending up
with a static ordering of "subsystems" init (even though for this
LPC series it is just the Hisilicon driver that requires this call)
and I am not sure I see any way of avoiding it. I think that's always
been the case in x86, with fewer subsystems/kernel paths to care
about, I wanted to flag this up though to check your opinion since
I am not sure this is the right direction we are taking.

I also think that relying on _DEP to build any dependency is not
entirely a) usable (owing to legacy bindings and previous _DEP misuse)
and b) compliant with ACPI bindings given that _DEP has to be used
for operation regions only.

Thoughts ?

Thanks,
Lorenzo

> > >  	acpi_scan_add_handler(&generic_device_handler);
> > >
> > > diff --git a/include/acpi/acpi_indirect_pio.h
> > b/include/acpi/acpi_indirect_pio.h
> > > new file mode 100644
> > > index 0000000..efc5c43
> > > --- /dev/null
> > > +++ b/include/acpi/acpi_indirect_pio.h
> > > @@ -0,0 +1,24 @@
> > > +/*
> > > + * ACPI support for indirect-PIO bus.
> > > + *
> > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > + *
> > > + * This program is free software; you can redistribute it and/or
> > modify
> > > + * it under the terms of the GNU General Public License version 2 as
> > > + * published by the Free Software Foundation.
> > > + */
> > > +
> > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > +#define _ACPI_INDIRECT_PIO_H
> > > +
> > > +struct indirect_pio_device_desc {
> > > +	void *pdata; /* device relevant info data */
> > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > +};
> > > +
> > > +int acpi_set_logic_pio_resource(struct device *child,
> > > +		struct device *hostdev);
> > > +
> > > +#endif
> > > --
> > > 2.7.4
> > >
> > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-06  8:55         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-06  8:55 UTC (permalink / raw)
  To: Gabriele Paoloni, rafael
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Gab, Rafael,

On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:

[...]

> > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > index e39ec7b..37dd23c 100644
> > > --- a/drivers/acpi/scan.c
> > > +++ b/drivers/acpi/scan.c
> > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > >  	acpi_int340x_thermal_init();
> > >  	acpi_amba_init();
> > >  	acpi_watchdog_init();
> > > +	acpi_indirectio_scan_init();

Unfortunately this is becoming a pattern and we are ending up
with a static ordering of "subsystems" init (even though for this
LPC series it is just the Hisilicon driver that requires this call)
and I am not sure I see any way of avoiding it. I think that's always
been the case in x86, with fewer subsystems/kernel paths to care
about, I wanted to flag this up though to check your opinion since
I am not sure this is the right direction we are taking.

I also think that relying on _DEP to build any dependency is not
entirely a) usable (owing to legacy bindings and previous _DEP misuse)
and b) compliant with ACPI bindings given that _DEP has to be used
for operation regions only.

Thoughts ?

Thanks,
Lorenzo

> > >  	acpi_scan_add_handler(&generic_device_handler);
> > >
> > > diff --git a/include/acpi/acpi_indirect_pio.h
> > b/include/acpi/acpi_indirect_pio.h
> > > new file mode 100644
> > > index 0000000..efc5c43
> > > --- /dev/null
> > > +++ b/include/acpi/acpi_indirect_pio.h
> > > @@ -0,0 +1,24 @@
> > > +/*
> > > + * ACPI support for indirect-PIO bus.
> > > + *
> > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > + *
> > > + * This program is free software; you can redistribute it and/or
> > modify
> > > + * it under the terms of the GNU General Public License version 2 as
> > > + * published by the Free Software Foundation.
> > > + */
> > > +
> > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > +#define _ACPI_INDIRECT_PIO_H
> > > +
> > > +struct indirect_pio_device_desc {
> > > +	void *pdata; /* device relevant info data */
> > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > +};
> > > +
> > > +int acpi_set_logic_pio_resource(struct device *child,
> > > +		struct device *hostdev);
> > > +
> > > +#endif
> > > --
> > > 2.7.4
> > >
> > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-06  8:55         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-06  8:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Gab, Rafael,

On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:

[...]

> > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > index e39ec7b..37dd23c 100644
> > > --- a/drivers/acpi/scan.c
> > > +++ b/drivers/acpi/scan.c
> > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > >  	acpi_int340x_thermal_init();
> > >  	acpi_amba_init();
> > >  	acpi_watchdog_init();
> > > +	acpi_indirectio_scan_init();

Unfortunately this is becoming a pattern and we are ending up
with a static ordering of "subsystems" init (even though for this
LPC series it is just the Hisilicon driver that requires this call)
and I am not sure I see any way of avoiding it. I think that's always
been the case in x86, with fewer subsystems/kernel paths to care
about, I wanted to flag this up though to check your opinion since
I am not sure this is the right direction we are taking.

I also think that relying on _DEP to build any dependency is not
entirely a) usable (owing to legacy bindings and previous _DEP misuse)
and b) compliant with ACPI bindings given that _DEP has to be used
for operation regions only.

Thoughts ?

Thanks,
Lorenzo

> > >  	acpi_scan_add_handler(&generic_device_handler);
> > >
> > > diff --git a/include/acpi/acpi_indirect_pio.h
> > b/include/acpi/acpi_indirect_pio.h
> > > new file mode 100644
> > > index 0000000..efc5c43
> > > --- /dev/null
> > > +++ b/include/acpi/acpi_indirect_pio.h
> > > @@ -0,0 +1,24 @@
> > > +/*
> > > + * ACPI support for indirect-PIO bus.
> > > + *
> > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > + *
> > > + * This program is free software; you can redistribute it and/or
> > modify
> > > + * it under the terms of the GNU General Public License version 2 as
> > > + * published by the Free Software Foundation.
> > > + */
> > > +
> > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > +#define _ACPI_INDIRECT_PIO_H
> > > +
> > > +struct indirect_pio_device_desc {
> > > +	void *pdata; /* device relevant info data */
> > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > +};
> > > +
> > > +int acpi_set_logic_pio_resource(struct device *child,
> > > +		struct device *hostdev);
> > > +
> > > +#endif
> > > --
> > > 2.7.4
> > >
> > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-06  8:55         ` Lorenzo Pieralisi
  (?)
  (?)
@ 2017-06-12 15:57           ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-12 15:57 UTC (permalink / raw)
  To: Gabriele Paoloni, rafael, Rafael J. Wysocki, Mika Westerberg
  Cc: mark.rutland, minyard, arnd, linux-acpi, linux-pci,
	catalin.marinas, John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, benh, bhelgaas, frowand.list,
	brian.starkey, linux-arm-kernel

[+Mika]

Gab, Rafael,

On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> Hi Gab, Rafael,
> 
> On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> 
> [...]
> 
> > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > index e39ec7b..37dd23c 100644
> > > > --- a/drivers/acpi/scan.c
> > > > +++ b/drivers/acpi/scan.c
> > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > >  	acpi_int340x_thermal_init();
> > > >  	acpi_amba_init();
> > > >  	acpi_watchdog_init();
> > > > +	acpi_indirectio_scan_init();
> 
> Unfortunately this is becoming a pattern and we are ending up
> with a static ordering of "subsystems" init (even though for this
> LPC series it is just the Hisilicon driver that requires this call)
> and I am not sure I see any way of avoiding it. I think that's always
> been the case in x86, with fewer subsystems/kernel paths to care
> about, I wanted to flag this up though to check your opinion since
> I am not sure this is the right direction we are taking.
> 
> I also think that relying on _DEP to build any dependency is not
> entirely a) usable (owing to legacy bindings and previous _DEP misuse)
> and b) compliant with ACPI bindings given that _DEP has to be used
> for operation regions only.

I had a more in-depth look at this series and from my understanding
the problem are the following to manage the LPC bindings in ACPI.

(1) Child devices of an LPC controller require special handling when
    filling their resources (ie they need to be translated - in DT
    that's guaranteed by the "isa" binding, in ACPI it has to be
    done by new code)
(2) In DT systems, LPC child devices are created by the LPC bus
    controller driver through an of_platform_populate() call with
    the LPC controller node as the fwnode root. For ACPI to work
    the same way there must be a way to prevent LPC children to
    be enumerated in acpi_default_enumeration() something like
    I2C does (and then the LPC driver would enumerate its children as
    DT does)

I am not sure how (1) and (2) can be managed with current ACPI bindings
and kernel code - I suspect it may be done by mirroring what's done
for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
is matched as a platform device and it takes care of enumerating its
children - problem though is preventing enumeration from core ACPI code).

I will let Gabriele and Hisilicon guys chime in if I missed something,
which is likely, please let me know your opinion on how this code
can be made functional on ACPI systems - it is uncharted territory.

Thank you !
Lorenzo

> 
> Thoughts ?
> 
> Thanks,
> Lorenzo
> 
> > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > >
> > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > b/include/acpi/acpi_indirect_pio.h
> > > > new file mode 100644
> > > > index 0000000..efc5c43
> > > > --- /dev/null
> > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > @@ -0,0 +1,24 @@
> > > > +/*
> > > > + * ACPI support for indirect-PIO bus.
> > > > + *
> > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > modify
> > > > + * it under the terms of the GNU General Public License version 2 as
> > > > + * published by the Free Software Foundation.
> > > > + */
> > > > +
> > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > +#define _ACPI_INDIRECT_PIO_H
> > > > +
> > > > +struct indirect_pio_device_desc {
> > > > +	void *pdata; /* device relevant info data */
> > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > +};
> > > > +
> > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > +		struct device *hostdev);
> > > > +
> > > > +#endif
> > > > --
> > > > 2.7.4
> > > >
> > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-12 15:57           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-12 15:57 UTC (permalink / raw)
  To: Gabriele Paoloni, rafael, Rafael J. Wysocki, Mika Westerberg
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

[+Mika]

Gab, Rafael,

On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> Hi Gab, Rafael,
> 
> On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> 
> [...]
> 
> > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > index e39ec7b..37dd23c 100644
> > > > --- a/drivers/acpi/scan.c
> > > > +++ b/drivers/acpi/scan.c
> > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > >  	acpi_int340x_thermal_init();
> > > >  	acpi_amba_init();
> > > >  	acpi_watchdog_init();
> > > > +	acpi_indirectio_scan_init();
> 
> Unfortunately this is becoming a pattern and we are ending up
> with a static ordering of "subsystems" init (even though for this
> LPC series it is just the Hisilicon driver that requires this call)
> and I am not sure I see any way of avoiding it. I think that's always
> been the case in x86, with fewer subsystems/kernel paths to care
> about, I wanted to flag this up though to check your opinion since
> I am not sure this is the right direction we are taking.
> 
> I also think that relying on _DEP to build any dependency is not
> entirely a) usable (owing to legacy bindings and previous _DEP misuse)
> and b) compliant with ACPI bindings given that _DEP has to be used
> for operation regions only.

I had a more in-depth look at this series and from my understanding
the problem are the following to manage the LPC bindings in ACPI.

(1) Child devices of an LPC controller require special handling when
    filling their resources (ie they need to be translated - in DT
    that's guaranteed by the "isa" binding, in ACPI it has to be
    done by new code)
(2) In DT systems, LPC child devices are created by the LPC bus
    controller driver through an of_platform_populate() call with
    the LPC controller node as the fwnode root. For ACPI to work
    the same way there must be a way to prevent LPC children to
    be enumerated in acpi_default_enumeration() something like
    I2C does (and then the LPC driver would enumerate its children as
    DT does)

I am not sure how (1) and (2) can be managed with current ACPI bindings
and kernel code - I suspect it may be done by mirroring what's done
for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
is matched as a platform device and it takes care of enumerating its
children - problem though is preventing enumeration from core ACPI code).

I will let Gabriele and Hisilicon guys chime in if I missed something,
which is likely, please let me know your opinion on how this code
can be made functional on ACPI systems - it is uncharted territory.

Thank you !
Lorenzo

> 
> Thoughts ?
> 
> Thanks,
> Lorenzo
> 
> > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > >
> > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > b/include/acpi/acpi_indirect_pio.h
> > > > new file mode 100644
> > > > index 0000000..efc5c43
> > > > --- /dev/null
> > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > @@ -0,0 +1,24 @@
> > > > +/*
> > > > + * ACPI support for indirect-PIO bus.
> > > > + *
> > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > modify
> > > > + * it under the terms of the GNU General Public License version 2 as
> > > > + * published by the Free Software Foundation.
> > > > + */
> > > > +
> > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > +#define _ACPI_INDIRECT_PIO_H
> > > > +
> > > > +struct indirect_pio_device_desc {
> > > > +	void *pdata; /* device relevant info data */
> > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > +};
> > > > +
> > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > +		struct device *hostdev);
> > > > +
> > > > +#endif
> > > > --
> > > > 2.7.4
> > > >
> > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-12 15:57           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-12 15:57 UTC (permalink / raw)
  To: Gabriele Paoloni, rafael, Rafael J. Wysocki, Mika Westerberg
  Cc: mark.rutland, minyard, arnd, linux-acpi, linux-pci,
	catalin.marinas, John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, benh, bhelgaas, frowand.list,
	brian.starkey, linux-arm-kernel

[+Mika]

Gab, Rafael,

On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> Hi Gab, Rafael,
> 
> On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> 
> [...]
> 
> > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > index e39ec7b..37dd23c 100644
> > > > --- a/drivers/acpi/scan.c
> > > > +++ b/drivers/acpi/scan.c
> > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > >  	acpi_int340x_thermal_init();
> > > >  	acpi_amba_init();
> > > >  	acpi_watchdog_init();
> > > > +	acpi_indirectio_scan_init();
> 
> Unfortunately this is becoming a pattern and we are ending up
> with a static ordering of "subsystems" init (even though for this
> LPC series it is just the Hisilicon driver that requires this call)
> and I am not sure I see any way of avoiding it. I think that's always
> been the case in x86, with fewer subsystems/kernel paths to care
> about, I wanted to flag this up though to check your opinion since
> I am not sure this is the right direction we are taking.
> 
> I also think that relying on _DEP to build any dependency is not
> entirely a) usable (owing to legacy bindings and previous _DEP misuse)
> and b) compliant with ACPI bindings given that _DEP has to be used
> for operation regions only.

I had a more in-depth look at this series and from my understanding
the problem are the following to manage the LPC bindings in ACPI.

(1) Child devices of an LPC controller require special handling when
    filling their resources (ie they need to be translated - in DT
    that's guaranteed by the "isa" binding, in ACPI it has to be
    done by new code)
(2) In DT systems, LPC child devices are created by the LPC bus
    controller driver through an of_platform_populate() call with
    the LPC controller node as the fwnode root. For ACPI to work
    the same way there must be a way to prevent LPC children to
    be enumerated in acpi_default_enumeration() something like
    I2C does (and then the LPC driver would enumerate its children as
    DT does)

I am not sure how (1) and (2) can be managed with current ACPI bindings
and kernel code - I suspect it may be done by mirroring what's done
for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
is matched as a platform device and it takes care of enumerating its
children - problem though is preventing enumeration from core ACPI code).

I will let Gabriele and Hisilicon guys chime in if I missed something,
which is likely, please let me know your opinion on how this code
can be made functional on ACPI systems - it is uncharted territory.

Thank you !
Lorenzo

> 
> Thoughts ?
> 
> Thanks,
> Lorenzo
> 
> > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > >
> > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > b/include/acpi/acpi_indirect_pio.h
> > > > new file mode 100644
> > > > index 0000000..efc5c43
> > > > --- /dev/null
> > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > @@ -0,0 +1,24 @@
> > > > +/*
> > > > + * ACPI support for indirect-PIO bus.
> > > > + *
> > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > modify
> > > > + * it under the terms of the GNU General Public License version 2 as
> > > > + * published by the Free Software Foundation.
> > > > + */
> > > > +
> > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > +#define _ACPI_INDIRECT_PIO_H
> > > > +
> > > > +struct indirect_pio_device_desc {
> > > > +	void *pdata; /* device relevant info data */
> > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > +};
> > > > +
> > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > +		struct device *hostdev);
> > > > +
> > > > +#endif
> > > > --
> > > > 2.7.4
> > > >
> > > >

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-12 15:57           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 171+ messages in thread
From: Lorenzo Pieralisi @ 2017-06-12 15:57 UTC (permalink / raw)
  To: linux-arm-kernel

[+Mika]

Gab, Rafael,

On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> Hi Gab, Rafael,
> 
> On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> 
> [...]
> 
> > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > index e39ec7b..37dd23c 100644
> > > > --- a/drivers/acpi/scan.c
> > > > +++ b/drivers/acpi/scan.c
> > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > >  	acpi_int340x_thermal_init();
> > > >  	acpi_amba_init();
> > > >  	acpi_watchdog_init();
> > > > +	acpi_indirectio_scan_init();
> 
> Unfortunately this is becoming a pattern and we are ending up
> with a static ordering of "subsystems" init (even though for this
> LPC series it is just the Hisilicon driver that requires this call)
> and I am not sure I see any way of avoiding it. I think that's always
> been the case in x86, with fewer subsystems/kernel paths to care
> about, I wanted to flag this up though to check your opinion since
> I am not sure this is the right direction we are taking.
> 
> I also think that relying on _DEP to build any dependency is not
> entirely a) usable (owing to legacy bindings and previous _DEP misuse)
> and b) compliant with ACPI bindings given that _DEP has to be used
> for operation regions only.

I had a more in-depth look at this series and from my understanding
the problem are the following to manage the LPC bindings in ACPI.

(1) Child devices of an LPC controller require special handling when
    filling their resources (ie they need to be translated - in DT
    that's guaranteed by the "isa" binding, in ACPI it has to be
    done by new code)
(2) In DT systems, LPC child devices are created by the LPC bus
    controller driver through an of_platform_populate() call with
    the LPC controller node as the fwnode root. For ACPI to work
    the same way there must be a way to prevent LPC children to
    be enumerated in acpi_default_enumeration() something like
    I2C does (and then the LPC driver would enumerate its children as
    DT does)

I am not sure how (1) and (2) can be managed with current ACPI bindings
and kernel code - I suspect it may be done by mirroring what's done
for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
is matched as a platform device and it takes care of enumerating its
children - problem though is preventing enumeration from core ACPI code).

I will let Gabriele and Hisilicon guys chime in if I missed something,
which is likely, please let me know your opinion on how this code
can be made functional on ACPI systems - it is uncharted territory.

Thank you !
Lorenzo

> 
> Thoughts ?
> 
> Thanks,
> Lorenzo
> 
> > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > >
> > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > b/include/acpi/acpi_indirect_pio.h
> > > > new file mode 100644
> > > > index 0000000..efc5c43
> > > > --- /dev/null
> > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > @@ -0,0 +1,24 @@
> > > > +/*
> > > > + * ACPI support for indirect-PIO bus.
> > > > + *
> > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > modify
> > > > + * it under the terms of the GNU General Public License version 2 as
> > > > + * published by the Free Software Foundation.
> > > > + */
> > > > +
> > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > +#define _ACPI_INDIRECT_PIO_H
> > > > +
> > > > +struct indirect_pio_device_desc {
> > > > +	void *pdata; /* device relevant info data */
> > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > +};
> > > > +
> > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > +		struct device *hostdev);
> > > > +
> > > > +#endif
> > > > --
> > > > 2.7.4
> > > >
> > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-12 15:57           ` Lorenzo Pieralisi
  (?)
  (?)
@ 2017-06-13  7:24             ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13  7:24 UTC (permalink / raw)
  To: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, Mika Westerberg
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard@acm.org

Hi Lorenzo, Rafael

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com]
> Sent: 12 June 2017 16:57
> To: Gabriele Paoloni; rafael@kernel.org; Rafael J. Wysocki; Mika
> Westerberg
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> [+Mika]
> 
> Gab, Rafael,
> 
> On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> > Hi Gab, Rafael,
> >
> > On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> >
> > [...]
> >
> > > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > > index e39ec7b..37dd23c 100644
> > > > > --- a/drivers/acpi/scan.c
> > > > > +++ b/drivers/acpi/scan.c
> > > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > > >  	acpi_int340x_thermal_init();
> > > > >  	acpi_amba_init();
> > > > >  	acpi_watchdog_init();
> > > > > +	acpi_indirectio_scan_init();
> >
> > Unfortunately this is becoming a pattern and we are ending up
> > with a static ordering of "subsystems" init (even though for this
> > LPC series it is just the Hisilicon driver that requires this call)
> > and I am not sure I see any way of avoiding it. I think that's always
> > been the case in x86, with fewer subsystems/kernel paths to care
> > about, I wanted to flag this up though to check your opinion since
> > I am not sure this is the right direction we are taking.
> >
> > I also think that relying on _DEP to build any dependency is not
> > entirely a) usable (owing to legacy bindings and previous _DEP
> misuse)
> > and b) compliant with ACPI bindings given that _DEP has to be used
> > for operation regions only.
> 
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)

Correct, LPC resources need to be translated in a virtual IO port
address space.
We cannot strictly follow the ISA bindings as the LPC host does not
define a mapping (through the "range" property) between a CPU address
range and an LPC address range.
Instead LPC has got his own bus accessors; therefore the bus address
range that LPC operates on is directly mapped into the IO port address
range and the IO in/out standard accessors (include/asm-generic/io.h)
are redefined to use the LPC accessors for the virtual IO port address
range that corresponds to LPC. 

> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)

Correct.

> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI
> code).

Yes my idea was to have a scan handler that enumerate the children devices
and translate its addresses filling dev->resources[] and at the same time
we can modify acpi_default_enumeration() to check acpi_device_enumerated()
before continuing with device enumeration...?

Many thanks
Gab

> 
> I will let Gabriele and Hisilicon guys chime in if I missed something,
> which is likely, please let me know your opinion on how this code
> can be made functional on ACPI systems - it is uncharted territory.
> 
> Thank you !
> Lorenzo
> 
> >
> > Thoughts ?
> >
> > Thanks,
> > Lorenzo
> >
> > > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > > >
> > > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > > b/include/acpi/acpi_indirect_pio.h
> > > > > new file mode 100644
> > > > > index 0000000..efc5c43
> > > > > --- /dev/null
> > > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > > @@ -0,0 +1,24 @@
> > > > > +/*
> > > > > + * ACPI support for indirect-PIO bus.
> > > > > + *
> > > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > > + *
> > > > > + * This program is free software; you can redistribute it
> and/or
> > > > modify
> > > > > + * it under the terms of the GNU General Public License
> version 2 as
> > > > > + * published by the Free Software Foundation.
> > > > > + */
> > > > > +
> > > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > > +#define _ACPI_INDIRECT_PIO_H
> > > > > +
> > > > > +struct indirect_pio_device_desc {
> > > > > +	void *pdata; /* device relevant info data */
> > > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > > +};
> > > > > +
> > > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > > +		struct device *hostdev);
> > > > > +
> > > > > +#endif
> > > > > --
> > > > > 2.7.4
> > > > >
> > > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13  7:24             ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13  7:24 UTC (permalink / raw)
  To: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, Mika Westerberg
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Lorenzo, Rafael

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com]
> Sent: 12 June 2017 16:57
> To: Gabriele Paoloni; rafael@kernel.org; Rafael J. Wysocki; Mika
> Westerberg
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> [+Mika]
> 
> Gab, Rafael,
> 
> On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> > Hi Gab, Rafael,
> >
> > On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> >
> > [...]
> >
> > > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > > index e39ec7b..37dd23c 100644
> > > > > --- a/drivers/acpi/scan.c
> > > > > +++ b/drivers/acpi/scan.c
> > > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > > >  	acpi_int340x_thermal_init();
> > > > >  	acpi_amba_init();
> > > > >  	acpi_watchdog_init();
> > > > > +	acpi_indirectio_scan_init();
> >
> > Unfortunately this is becoming a pattern and we are ending up
> > with a static ordering of "subsystems" init (even though for this
> > LPC series it is just the Hisilicon driver that requires this call)
> > and I am not sure I see any way of avoiding it. I think that's always
> > been the case in x86, with fewer subsystems/kernel paths to care
> > about, I wanted to flag this up though to check your opinion since
> > I am not sure this is the right direction we are taking.
> >
> > I also think that relying on _DEP to build any dependency is not
> > entirely a) usable (owing to legacy bindings and previous _DEP
> misuse)
> > and b) compliant with ACPI bindings given that _DEP has to be used
> > for operation regions only.
> 
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)

Correct, LPC resources need to be translated in a virtual IO port
address space.
We cannot strictly follow the ISA bindings as the LPC host does not
define a mapping (through the "range" property) between a CPU address
range and an LPC address range.
Instead LPC has got his own bus accessors; therefore the bus address
range that LPC operates on is directly mapped into the IO port address
range and the IO in/out standard accessors (include/asm-generic/io.h)
are redefined to use the LPC accessors for the virtual IO port address
range that corresponds to LPC. 

> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)

Correct.

> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI
> code).

Yes my idea was to have a scan handler that enumerate the children devices
and translate its addresses filling dev->resources[] and at the same time
we can modify acpi_default_enumeration() to check acpi_device_enumerated()
before continuing with device enumeration...?

Many thanks
Gab

> 
> I will let Gabriele and Hisilicon guys chime in if I missed something,
> which is likely, please let me know your opinion on how this code
> can be made functional on ACPI systems - it is uncharted territory.
> 
> Thank you !
> Lorenzo
> 
> >
> > Thoughts ?
> >
> > Thanks,
> > Lorenzo
> >
> > > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > > >
> > > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > > b/include/acpi/acpi_indirect_pio.h
> > > > > new file mode 100644
> > > > > index 0000000..efc5c43
> > > > > --- /dev/null
> > > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > > @@ -0,0 +1,24 @@
> > > > > +/*
> > > > > + * ACPI support for indirect-PIO bus.
> > > > > + *
> > > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > > + *
> > > > > + * This program is free software; you can redistribute it
> and/or
> > > > modify
> > > > > + * it under the terms of the GNU General Public License
> version 2 as
> > > > > + * published by the Free Software Foundation.
> > > > > + */
> > > > > +
> > > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > > +#define _ACPI_INDIRECT_PIO_H
> > > > > +
> > > > > +struct indirect_pio_device_desc {
> > > > > +	void *pdata; /* device relevant info data */
> > > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > > +};
> > > > > +
> > > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > > +		struct device *hostdev);
> > > > > +
> > > > > +#endif
> > > > > --
> > > > > 2.7.4
> > > > >
> > > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13  7:24             ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13  7:24 UTC (permalink / raw)
  To: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, Mika Westerberg
  Cc: catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Lorenzo, Rafael

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com]
> Sent: 12 June 2017 16:57
> To: Gabriele Paoloni; rafael@kernel.org; Rafael J. Wysocki; Mika
> Westerberg
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> [+Mika]
> 
> Gab, Rafael,
> 
> On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> > Hi Gab, Rafael,
> >
> > On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> >
> > [...]
> >
> > > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > > index e39ec7b..37dd23c 100644
> > > > > --- a/drivers/acpi/scan.c
> > > > > +++ b/drivers/acpi/scan.c
> > > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > > >  	acpi_int340x_thermal_init();
> > > > >  	acpi_amba_init();
> > > > >  	acpi_watchdog_init();
> > > > > +	acpi_indirectio_scan_init();
> >
> > Unfortunately this is becoming a pattern and we are ending up
> > with a static ordering of "subsystems" init (even though for this
> > LPC series it is just the Hisilicon driver that requires this call)
> > and I am not sure I see any way of avoiding it. I think that's always
> > been the case in x86, with fewer subsystems/kernel paths to care
> > about, I wanted to flag this up though to check your opinion since
> > I am not sure this is the right direction we are taking.
> >
> > I also think that relying on _DEP to build any dependency is not
> > entirely a) usable (owing to legacy bindings and previous _DEP
> misuse)
> > and b) compliant with ACPI bindings given that _DEP has to be used
> > for operation regions only.
> 
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)

Correct, LPC resources need to be translated in a virtual IO port
address space.
We cannot strictly follow the ISA bindings as the LPC host does not
define a mapping (through the "range" property) between a CPU address
range and an LPC address range.
Instead LPC has got his own bus accessors; therefore the bus address
range that LPC operates on is directly mapped into the IO port address
range and the IO in/out standard accessors (include/asm-generic/io.h)
are redefined to use the LPC accessors for the virtual IO port address
range that corresponds to LPC. 

> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)

Correct.

> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI
> code).

Yes my idea was to have a scan handler that enumerate the children devices
and translate its addresses filling dev->resources[] and at the same time
we can modify acpi_default_enumeration() to check acpi_device_enumerated()
before continuing with device enumeration...?

Many thanks
Gab

> 
> I will let Gabriele and Hisilicon guys chime in if I missed something,
> which is likely, please let me know your opinion on how this code
> can be made functional on ACPI systems - it is uncharted territory.
> 
> Thank you !
> Lorenzo
> 
> >
> > Thoughts ?
> >
> > Thanks,
> > Lorenzo
> >
> > > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > > >
> > > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > > b/include/acpi/acpi_indirect_pio.h
> > > > > new file mode 100644
> > > > > index 0000000..efc5c43
> > > > > --- /dev/null
> > > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > > @@ -0,0 +1,24 @@
> > > > > +/*
> > > > > + * ACPI support for indirect-PIO bus.
> > > > > + *
> > > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > > + *
> > > > > + * This program is free software; you can redistribute it
> and/or
> > > > modify
> > > > > + * it under the terms of the GNU General Public License
> version 2 as
> > > > > + * published by the Free Software Foundation.
> > > > > + */
> > > > > +
> > > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > > +#define _ACPI_INDIRECT_PIO_H
> > > > > +
> > > > > +struct indirect_pio_device_desc {
> > > > > +	void *pdata; /* device relevant info data */
> > > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > > +};
> > > > > +
> > > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > > +		struct device *hostdev);
> > > > > +
> > > > > +#endif
> > > > > --
> > > > > 2.7.4
> > > > >
> > > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13  7:24             ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13  7:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo, Rafael

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> Sent: 12 June 2017 16:57
> To: Gabriele Paoloni; rafael at kernel.org; Rafael J. Wysocki; Mika
> Westerberg
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> [+Mika]
> 
> Gab, Rafael,
> 
> On Tue, Jun 06, 2017 at 09:55:53AM +0100, Lorenzo Pieralisi wrote:
> > Hi Gab, Rafael,
> >
> > On Wed, May 31, 2017 at 10:24:47AM +0000, Gabriele Paoloni wrote:
> >
> > [...]
> >
> > > > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > > > > index e39ec7b..37dd23c 100644
> > > > > --- a/drivers/acpi/scan.c
> > > > > +++ b/drivers/acpi/scan.c
> > > > > @@ -2035,6 +2035,7 @@ int __init acpi_scan_init(void)
> > > > >  	acpi_int340x_thermal_init();
> > > > >  	acpi_amba_init();
> > > > >  	acpi_watchdog_init();
> > > > > +	acpi_indirectio_scan_init();
> >
> > Unfortunately this is becoming a pattern and we are ending up
> > with a static ordering of "subsystems" init (even though for this
> > LPC series it is just the Hisilicon driver that requires this call)
> > and I am not sure I see any way of avoiding it. I think that's always
> > been the case in x86, with fewer subsystems/kernel paths to care
> > about, I wanted to flag this up though to check your opinion since
> > I am not sure this is the right direction we are taking.
> >
> > I also think that relying on _DEP to build any dependency is not
> > entirely a) usable (owing to legacy bindings and previous _DEP
> misuse)
> > and b) compliant with ACPI bindings given that _DEP has to be used
> > for operation regions only.
> 
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)

Correct, LPC resources need to be translated in a virtual IO port
address space.
We cannot strictly follow the ISA bindings as the LPC host does not
define a mapping (through the "range" property) between a CPU address
range and an LPC address range.
Instead LPC has got his own bus accessors; therefore the bus address
range that LPC operates on is directly mapped into the IO port address
range and the IO in/out standard accessors (include/asm-generic/io.h)
are redefined to use the LPC accessors for the virtual IO port address
range that corresponds to LPC. 

> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)

Correct.

> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI
> code).

Yes my idea was to have a scan handler that enumerate the children devices
and translate its addresses filling dev->resources[] and at the same time
we can modify acpi_default_enumeration() to check acpi_device_enumerated()
before continuing with device enumeration...?

Many thanks
Gab

> 
> I will let Gabriele and Hisilicon guys chime in if I missed something,
> which is likely, please let me know your opinion on how this code
> can be made functional on ACPI systems - it is uncharted territory.
> 
> Thank you !
> Lorenzo
> 
> >
> > Thoughts ?
> >
> > Thanks,
> > Lorenzo
> >
> > > > >  	acpi_scan_add_handler(&generic_device_handler);
> > > > >
> > > > > diff --git a/include/acpi/acpi_indirect_pio.h
> > > > b/include/acpi/acpi_indirect_pio.h
> > > > > new file mode 100644
> > > > > index 0000000..efc5c43
> > > > > --- /dev/null
> > > > > +++ b/include/acpi/acpi_indirect_pio.h
> > > > > @@ -0,0 +1,24 @@
> > > > > +/*
> > > > > + * ACPI support for indirect-PIO bus.
> > > > > + *
> > > > > + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
> > > > > + * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > > + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> > > > > + *
> > > > > + * This program is free software; you can redistribute it
> and/or
> > > > modify
> > > > > + * it under the terms of the GNU General Public License
> version 2 as
> > > > > + * published by the Free Software Foundation.
> > > > > + */
> > > > > +
> > > > > +#ifndef _ACPI_INDIRECT_PIO_H
> > > > > +#define _ACPI_INDIRECT_PIO_H
> > > > > +
> > > > > +struct indirect_pio_device_desc {
> > > > > +	void *pdata; /* device relevant info data */
> > > > > +	int (*pre_setup)(struct acpi_device *adev, void *pdata);
> > > > > +};
> > > > > +
> > > > > +int acpi_set_logic_pio_resource(struct device *child,
> > > > > +		struct device *hostdev);
> > > > > +
> > > > > +#endif
> > > > > --
> > > > > 2.7.4
> > > > >
> > > > >

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-12 15:57           ` Lorenzo Pieralisi
  (?)
  (?)
@ 2017-06-13  8:48             ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13  8:48 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Gabriele Paoloni, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Li

On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)
> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)
> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI code).

Is there an example ASL showing how these LPC devices are
currently presented in ACPI?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13  8:48             ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13  8:48 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Gabriele Paoloni, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)
> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)
> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI code).

Is there an example ASL showing how these LPC devices are
currently presented in ACPI?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13  8:48             ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13  8:48 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: mark.rutland, Rafael J. Wysocki, minyard, arnd, Gabriele Paoloni,
	rafael, linux-pci, catalin.marinas, John Garry, will.deacon,
	linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, benh, bhelgaas, linux-acpi,
	frowand.list, brian.starkey, linux-arm-kernel

On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)
> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)
> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI code).

Is there an example ASL showing how these LPC devices are
currently presented in ACPI?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13  8:48             ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13  8:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> I had a more in-depth look at this series and from my understanding
> the problem are the following to manage the LPC bindings in ACPI.
> 
> (1) Child devices of an LPC controller require special handling when
>     filling their resources (ie they need to be translated - in DT
>     that's guaranteed by the "isa" binding, in ACPI it has to be
>     done by new code)
> (2) In DT systems, LPC child devices are created by the LPC bus
>     controller driver through an of_platform_populate() call with
>     the LPC controller node as the fwnode root. For ACPI to work
>     the same way there must be a way to prevent LPC children to
>     be enumerated in acpi_default_enumeration() something like
>     I2C does (and then the LPC driver would enumerate its children as
>     DT does)
> 
> I am not sure how (1) and (2) can be managed with current ACPI bindings
> and kernel code - I suspect it may be done by mirroring what's done
> for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC adapter
> is matched as a platform device and it takes care of enumerating its
> children - problem though is preventing enumeration from core ACPI code).

Is there an example ASL showing how these LPC devices are
currently presented in ACPI?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-13  8:48             ` Mika Westerberg
  (?)
  (?)
@ 2017-06-13 14:38               ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 14:38 UTC (permalink / raw)
  To: Mika Westerberg, Lorenzo Pieralisi
  Cc: rafael, Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 13 June 2017 09:49
> To: Lorenzo Pieralisi
> Cc: Gabriele Paoloni; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> > I had a more in-depth look at this series and from my understanding
> > the problem are the following to manage the LPC bindings in ACPI.
> >
> > (1) Child devices of an LPC controller require special handling when
> >     filling their resources (ie they need to be translated - in DT
> >     that's guaranteed by the "isa" binding, in ACPI it has to be
> >     done by new code)
> > (2) In DT systems, LPC child devices are created by the LPC bus
> >     controller driver through an of_platform_populate() call with
> >     the LPC controller node as the fwnode root. For ACPI to work
> >     the same way there must be a way to prevent LPC children to
> >     be enumerated in acpi_default_enumeration() something like
> >     I2C does (and then the LPC driver would enumerate its children as
> >     DT does)
> >
> > I am not sure how (1) and (2) can be managed with current ACPI
> bindings
> > and kernel code - I suspect it may be done by mirroring what's done
> > for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC
> adapter
> > is matched as a platform device and it takes care of enumerating its
> > children - problem though is preventing enumeration from core ACPI
> code).
> 
> Is there an example ASL showing how these LPC devices are
> currently presented in ACPI?

Please find below the asl sketch for our LPC and IPMI

//
// LPC
//

Scope(_SB) {
  Device (LPC0) {
    Name (_HID, "HISI0191")  // HiSi LPC
    Name (_CRS, ResourceTemplate () {
      Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
    })
  }

  Device (LPC0.IPMI) {
    Name (_HID, "IPI0001")
    Method (_IFT) {
      Return (0x03)
    }
    Name (LORS, ResourceTemplate() {
      QWordIO (
        ResourceConsumer,
	MinNotFixed,     // _MIF
	MaxNotFixed,     // _MAF
	PosDecode,
	EntireRange,
	0x0,             // _GRA
	0xe4,            // _MIN
	0x3fff,          // _MAX
	0x0,             // _TRA
	0x04,            // _LEN
	, ,
	BTIO
      )
    })
    CreateQWordField (LORS, BTIO._MIN, CMIN)
    CreateQWordField (LORS, BTIO._MAX, CMAX)
    CreateQWordField (LORS, BTIO._LEN, CLEN)

    Method (_PRS, 0) {
      Return (LORS)
    }

    Method (_CRS, 0) {
      Return (LORS)
    }
    Method (_SRS, 1) {
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
      Store (IMIN, CMIN)
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
      Store (IMAX, CMAX)
    }
  } 
[...]
}

Many thanks
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 14:38               ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 14:38 UTC (permalink / raw)
  To: Mika Westerberg, Lorenzo Pieralisi
  Cc: rafael, Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 13 June 2017 09:49
> To: Lorenzo Pieralisi
> Cc: Gabriele Paoloni; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> > I had a more in-depth look at this series and from my understanding
> > the problem are the following to manage the LPC bindings in ACPI.
> >
> > (1) Child devices of an LPC controller require special handling when
> >     filling their resources (ie they need to be translated - in DT
> >     that's guaranteed by the "isa" binding, in ACPI it has to be
> >     done by new code)
> > (2) In DT systems, LPC child devices are created by the LPC bus
> >     controller driver through an of_platform_populate() call with
> >     the LPC controller node as the fwnode root. For ACPI to work
> >     the same way there must be a way to prevent LPC children to
> >     be enumerated in acpi_default_enumeration() something like
> >     I2C does (and then the LPC driver would enumerate its children as
> >     DT does)
> >
> > I am not sure how (1) and (2) can be managed with current ACPI
> bindings
> > and kernel code - I suspect it may be done by mirroring what's done
> > for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC
> adapter
> > is matched as a platform device and it takes care of enumerating its
> > children - problem though is preventing enumeration from core ACPI
> code).
> 
> Is there an example ASL showing how these LPC devices are
> currently presented in ACPI?

Please find below the asl sketch for our LPC and IPMI

//
// LPC
//

Scope(_SB) {
  Device (LPC0) {
    Name (_HID, "HISI0191")  // HiSi LPC
    Name (_CRS, ResourceTemplate () {
      Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
    })
  }

  Device (LPC0.IPMI) {
    Name (_HID, "IPI0001")
    Method (_IFT) {
      Return (0x03)
    }
    Name (LORS, ResourceTemplate() {
      QWordIO (
        ResourceConsumer,
	MinNotFixed,     // _MIF
	MaxNotFixed,     // _MAF
	PosDecode,
	EntireRange,
	0x0,             // _GRA
	0xe4,            // _MIN
	0x3fff,          // _MAX
	0x0,             // _TRA
	0x04,            // _LEN
	, ,
	BTIO
      )
    })
    CreateQWordField (LORS, BTIO._MIN, CMIN)
    CreateQWordField (LORS, BTIO._MAX, CMAX)
    CreateQWordField (LORS, BTIO._LEN, CLEN)

    Method (_PRS, 0) {
      Return (LORS)
    }

    Method (_CRS, 0) {
      Return (LORS)
    }
    Method (_SRS, 1) {
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
      Store (IMIN, CMIN)
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
      Store (IMAX, CMAX)
    }
  } 
[...]
}

Many thanks
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 14:38               ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 14:38 UTC (permalink / raw)
  To: Mika Westerberg, Lorenzo Pieralisi
  Cc: mark.rutland, minyard, linux-acpi, arnd, rafael, linux-pci,
	catalin.marinas, John Garry, Rafael J. Wysocki, linux-kernel,
	will.deacon, Linuxarm, olof, robh+dt, xuwei (O),
	benh, bhelgaas, frowand.list, brian.starkey, linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 13 June 2017 09:49
> To: Lorenzo Pieralisi
> Cc: Gabriele Paoloni; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> > I had a more in-depth look at this series and from my understanding
> > the problem are the following to manage the LPC bindings in ACPI.
> >
> > (1) Child devices of an LPC controller require special handling when
> >     filling their resources (ie they need to be translated - in DT
> >     that's guaranteed by the "isa" binding, in ACPI it has to be
> >     done by new code)
> > (2) In DT systems, LPC child devices are created by the LPC bus
> >     controller driver through an of_platform_populate() call with
> >     the LPC controller node as the fwnode root. For ACPI to work
> >     the same way there must be a way to prevent LPC children to
> >     be enumerated in acpi_default_enumeration() something like
> >     I2C does (and then the LPC driver would enumerate its children as
> >     DT does)
> >
> > I am not sure how (1) and (2) can be managed with current ACPI
> bindings
> > and kernel code - I suspect it may be done by mirroring what's done
> > for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC
> adapter
> > is matched as a platform device and it takes care of enumerating its
> > children - problem though is preventing enumeration from core ACPI
> code).
> 
> Is there an example ASL showing how these LPC devices are
> currently presented in ACPI?

Please find below the asl sketch for our LPC and IPMI

//
// LPC
//

Scope(_SB) {
  Device (LPC0) {
    Name (_HID, "HISI0191")  // HiSi LPC
    Name (_CRS, ResourceTemplate () {
      Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
    })
  }

  Device (LPC0.IPMI) {
    Name (_HID, "IPI0001")
    Method (_IFT) {
      Return (0x03)
    }
    Name (LORS, ResourceTemplate() {
      QWordIO (
        ResourceConsumer,
	MinNotFixed,     // _MIF
	MaxNotFixed,     // _MAF
	PosDecode,
	EntireRange,
	0x0,             // _GRA
	0xe4,            // _MIN
	0x3fff,          // _MAX
	0x0,             // _TRA
	0x04,            // _LEN
	, ,
	BTIO
      )
    })
    CreateQWordField (LORS, BTIO._MIN, CMIN)
    CreateQWordField (LORS, BTIO._MAX, CMAX)
    CreateQWordField (LORS, BTIO._LEN, CLEN)

    Method (_PRS, 0) {
      Return (LORS)
    }

    Method (_CRS, 0) {
      Return (LORS)
    }
    Method (_SRS, 1) {
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
      Store (IMIN, CMIN)
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
      Store (IMAX, CMAX)
    }
  } 
[...]
}

Many thanks
Gab

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 14:38               ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg at linux.intel.com]
> Sent: 13 June 2017 09:49
> To: Lorenzo Pieralisi
> Cc: Gabriele Paoloni; rafael at kernel.org; Rafael J. Wysocki;
> catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 12, 2017 at 04:57:00PM +0100, Lorenzo Pieralisi wrote:
> > I had a more in-depth look at this series and from my understanding
> > the problem are the following to manage the LPC bindings in ACPI.
> >
> > (1) Child devices of an LPC controller require special handling when
> >     filling their resources (ie they need to be translated - in DT
> >     that's guaranteed by the "isa" binding, in ACPI it has to be
> >     done by new code)
> > (2) In DT systems, LPC child devices are created by the LPC bus
> >     controller driver through an of_platform_populate() call with
> >     the LPC controller node as the fwnode root. For ACPI to work
> >     the same way there must be a way to prevent LPC children to
> >     be enumerated in acpi_default_enumeration() something like
> >     I2C does (and then the LPC driver would enumerate its children as
> >     DT does)
> >
> > I am not sure how (1) and (2) can be managed with current ACPI
> bindings
> > and kernel code - I suspect it may be done by mirroring what's done
> > for I2C but I am not sure, that's why I CC'ed Mika (ie the LPC
> adapter
> > is matched as a platform device and it takes care of enumerating its
> > children - problem though is preventing enumeration from core ACPI
> code).
> 
> Is there an example ASL showing how these LPC devices are
> currently presented in ACPI?

Please find below the asl sketch for our LPC and IPMI

//
// LPC
//

Scope(_SB) {
  Device (LPC0) {
    Name (_HID, "HISI0191")  // HiSi LPC
    Name (_CRS, ResourceTemplate () {
      Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
    })
  }

  Device (LPC0.IPMI) {
    Name (_HID, "IPI0001")
    Method (_IFT) {
      Return (0x03)
    }
    Name (LORS, ResourceTemplate() {
      QWordIO (
        ResourceConsumer,
	MinNotFixed,     // _MIF
	MaxNotFixed,     // _MAF
	PosDecode,
	EntireRange,
	0x0,             // _GRA
	0xe4,            // _MIN
	0x3fff,          // _MAX
	0x0,             // _TRA
	0x04,            // _LEN
	, ,
	BTIO
      )
    })
    CreateQWordField (LORS, BTIO._MIN, CMIN)
    CreateQWordField (LORS, BTIO._MAX, CMAX)
    CreateQWordField (LORS, BTIO._LEN, CLEN)

    Method (_PRS, 0) {
      Return (LORS)
    }

    Method (_CRS, 0) {
      Return (LORS)
    }
    Method (_SRS, 1) {
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
      Store (IMIN, CMIN)
      CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
      Store (IMAX, CMAX)
    }
  } 
[...]
}

Many thanks
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-13 14:38               ` Gabriele Paoloni
  (?)
  (?)
@ 2017-06-13 15:10                 ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 15:10 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > Is there an example ASL showing how these LPC devices are
> > currently presented in ACPI?
> 
> Please find below the asl sketch for our LPC and IPMI
> 
> //
> // LPC
> //
> 
> Scope(_SB) {
>   Device (LPC0) {
>     Name (_HID, "HISI0191")  // HiSi LPC
>     Name (_CRS, ResourceTemplate () {
>       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
>     })
>   }
> 
>   Device (LPC0.IPMI) {
>     Name (_HID, "IPI0001")
>     Method (_IFT) {
>       Return (0x03)
>     }
>     Name (LORS, ResourceTemplate() {
>       QWordIO (
>         ResourceConsumer,
> 	MinNotFixed,     // _MIF
> 	MaxNotFixed,     // _MAF
> 	PosDecode,
> 	EntireRange,
> 	0x0,             // _GRA
> 	0xe4,            // _MIN
> 	0x3fff,          // _MAX
> 	0x0,             // _TRA
> 	0x04,            // _LEN
> 	, ,
> 	BTIO
>       )
>     })
>     CreateQWordField (LORS, BTIO._MIN, CMIN)
>     CreateQWordField (LORS, BTIO._MAX, CMAX)
>     CreateQWordField (LORS, BTIO._LEN, CLEN)
> 
>     Method (_PRS, 0) {
>       Return (LORS)
>     }
> 
>     Method (_CRS, 0) {
>       Return (LORS)
>     }
>     Method (_SRS, 1) {
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
>       Store (IMIN, CMIN)
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
>       Store (IMAX, CMAX)
>     }
>   } 
> [...]
> }

Thanks. So this looks pretty much like normal Linux MFD device which we
already have support for adding ACPI bindings to child devices. It
should also support splitting resources to child devices IIRC.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 15:10                 ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 15:10 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > Is there an example ASL showing how these LPC devices are
> > currently presented in ACPI?
> 
> Please find below the asl sketch for our LPC and IPMI
> 
> //
> // LPC
> //
> 
> Scope(_SB) {
>   Device (LPC0) {
>     Name (_HID, "HISI0191")  // HiSi LPC
>     Name (_CRS, ResourceTemplate () {
>       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
>     })
>   }
> 
>   Device (LPC0.IPMI) {
>     Name (_HID, "IPI0001")
>     Method (_IFT) {
>       Return (0x03)
>     }
>     Name (LORS, ResourceTemplate() {
>       QWordIO (
>         ResourceConsumer,
> 	MinNotFixed,     // _MIF
> 	MaxNotFixed,     // _MAF
> 	PosDecode,
> 	EntireRange,
> 	0x0,             // _GRA
> 	0xe4,            // _MIN
> 	0x3fff,          // _MAX
> 	0x0,             // _TRA
> 	0x04,            // _LEN
> 	, ,
> 	BTIO
>       )
>     })
>     CreateQWordField (LORS, BTIO._MIN, CMIN)
>     CreateQWordField (LORS, BTIO._MAX, CMAX)
>     CreateQWordField (LORS, BTIO._LEN, CLEN)
> 
>     Method (_PRS, 0) {
>       Return (LORS)
>     }
> 
>     Method (_CRS, 0) {
>       Return (LORS)
>     }
>     Method (_SRS, 1) {
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
>       Store (IMIN, CMIN)
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
>       Store (IMAX, CMAX)
>     }
>   } 
> [...]
> }

Thanks. So this looks pretty much like normal Linux MFD device which we
already have support for adding ACPI bindings to child devices. It
should also support splitting resources to child devices IIRC.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 15:10                 ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 15:10 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > Is there an example ASL showing how these LPC devices are
> > currently presented in ACPI?
> 
> Please find below the asl sketch for our LPC and IPMI
> 
> //
> // LPC
> //
> 
> Scope(_SB) {
>   Device (LPC0) {
>     Name (_HID, "HISI0191")  // HiSi LPC
>     Name (_CRS, ResourceTemplate () {
>       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
>     })
>   }
> 
>   Device (LPC0.IPMI) {
>     Name (_HID, "IPI0001")
>     Method (_IFT) {
>       Return (0x03)
>     }
>     Name (LORS, ResourceTemplate() {
>       QWordIO (
>         ResourceConsumer,
> 	MinNotFixed,     // _MIF
> 	MaxNotFixed,     // _MAF
> 	PosDecode,
> 	EntireRange,
> 	0x0,             // _GRA
> 	0xe4,            // _MIN
> 	0x3fff,          // _MAX
> 	0x0,             // _TRA
> 	0x04,            // _LEN
> 	, ,
> 	BTIO
>       )
>     })
>     CreateQWordField (LORS, BTIO._MIN, CMIN)
>     CreateQWordField (LORS, BTIO._MAX, CMAX)
>     CreateQWordField (LORS, BTIO._LEN, CLEN)
> 
>     Method (_PRS, 0) {
>       Return (LORS)
>     }
> 
>     Method (_CRS, 0) {
>       Return (LORS)
>     }
>     Method (_SRS, 1) {
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
>       Store (IMIN, CMIN)
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
>       Store (IMAX, CMAX)
>     }
>   } 
> [...]
> }

Thanks. So this looks pretty much like normal Linux MFD device which we
already have support for adding ACPI bindings to child devices. It
should also support splitting resources to child devices IIRC.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 15:10                 ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 15:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > Is there an example ASL showing how these LPC devices are
> > currently presented in ACPI?
> 
> Please find below the asl sketch for our LPC and IPMI
> 
> //
> // LPC
> //
> 
> Scope(_SB) {
>   Device (LPC0) {
>     Name (_HID, "HISI0191")  // HiSi LPC
>     Name (_CRS, ResourceTemplate () {
>       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
>     })
>   }
> 
>   Device (LPC0.IPMI) {
>     Name (_HID, "IPI0001")
>     Method (_IFT) {
>       Return (0x03)
>     }
>     Name (LORS, ResourceTemplate() {
>       QWordIO (
>         ResourceConsumer,
> 	MinNotFixed,     // _MIF
> 	MaxNotFixed,     // _MAF
> 	PosDecode,
> 	EntireRange,
> 	0x0,             // _GRA
> 	0xe4,            // _MIN
> 	0x3fff,          // _MAX
> 	0x0,             // _TRA
> 	0x04,            // _LEN
> 	, ,
> 	BTIO
>       )
>     })
>     CreateQWordField (LORS, BTIO._MIN, CMIN)
>     CreateQWordField (LORS, BTIO._MAX, CMAX)
>     CreateQWordField (LORS, BTIO._LEN, CLEN)
> 
>     Method (_PRS, 0) {
>       Return (LORS)
>     }
> 
>     Method (_CRS, 0) {
>       Return (LORS)
>     }
>     Method (_SRS, 1) {
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
>       Store (IMIN, CMIN)
>       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
>       Store (IMAX, CMAX)
>     }
>   } 
> [...]
> }

Thanks. So this looks pretty much like normal Linux MFD device which we
already have support for adding ACPI bindings to child devices. It
should also support splitting resources to child devices IIRC.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-13 15:10                 ` Mika Westerberg
  (?)
  (?)
@ 2017-06-13 19:01                   ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 19:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 13 June 2017 16:10
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > > Is there an example ASL showing how these LPC devices are
> > > currently presented in ACPI?
> >
> > Please find below the asl sketch for our LPC and IPMI
> >
> > //
> > // LPC
> > //
> >
> > Scope(_SB) {
> >   Device (LPC0) {
> >     Name (_HID, "HISI0191")  // HiSi LPC
> >     Name (_CRS, ResourceTemplate () {
> >       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
> >     })
> >   }
> >
> >   Device (LPC0.IPMI) {
> >     Name (_HID, "IPI0001")
> >     Method (_IFT) {
> >       Return (0x03)
> >     }
> >     Name (LORS, ResourceTemplate() {
> >       QWordIO (
> >         ResourceConsumer,
> > 	MinNotFixed,     // _MIF
> > 	MaxNotFixed,     // _MAF
> > 	PosDecode,
> > 	EntireRange,
> > 	0x0,             // _GRA
> > 	0xe4,            // _MIN
> > 	0x3fff,          // _MAX
> > 	0x0,             // _TRA
> > 	0x04,            // _LEN
> > 	, ,
> > 	BTIO
> >       )
> >     })
> >     CreateQWordField (LORS, BTIO._MIN, CMIN)
> >     CreateQWordField (LORS, BTIO._MAX, CMAX)
> >     CreateQWordField (LORS, BTIO._LEN, CLEN)
> >
> >     Method (_PRS, 0) {
> >       Return (LORS)
> >     }
> >
> >     Method (_CRS, 0) {
> >       Return (LORS)
> >     }
> >     Method (_SRS, 1) {
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
> >       Store (IMIN, CMIN)
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
> >       Store (IMAX, CMAX)
> >     }
> >   }
> > [...]
> > }
> 
> Thanks. So this looks pretty much like normal Linux MFD device which we
> already have support for adding ACPI bindings to child devices. It
> should also support splitting resources to child devices IIRC.

I am not very familiar with Linux MFD however the main issue here is that
1) for IPMI we want to re-use the standard IPMI driver without touching it:
   see 

   static const struct acpi_device_id acpi_ipmi_match[] = {
         { "IPI0001", 0 },
         { },
   };

   in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
   of an LPC child)

2) We need a way to guarantee that all LPC children are not enumerated
   by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
   child it should not be enumerated, otherwise it should be)
   Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
   1) if the acpi resource type is a serial bus
   2) if the type of serial bus descriptor is I2C or SPI

   For LPC we cannot leverage on any ACPI property to "recognize" that our
   devices are LPC children; hence before I proposed for acpi_default_enumeration()
   to skip devices that have already been enumerated (by calling 
   acpi_device_enumerated() ).

So in the current scenario, how do you think that MFD can help?
Do you see any possible solution?

Many thanks
Gab
  



^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 19:01                   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 19:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 13 June 2017 16:10
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > > Is there an example ASL showing how these LPC devices are
> > > currently presented in ACPI?
> >
> > Please find below the asl sketch for our LPC and IPMI
> >
> > //
> > // LPC
> > //
> >
> > Scope(_SB) {
> >   Device (LPC0) {
> >     Name (_HID, "HISI0191")  // HiSi LPC
> >     Name (_CRS, ResourceTemplate () {
> >       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
> >     })
> >   }
> >
> >   Device (LPC0.IPMI) {
> >     Name (_HID, "IPI0001")
> >     Method (_IFT) {
> >       Return (0x03)
> >     }
> >     Name (LORS, ResourceTemplate() {
> >       QWordIO (
> >         ResourceConsumer,
> > 	MinNotFixed,     // _MIF
> > 	MaxNotFixed,     // _MAF
> > 	PosDecode,
> > 	EntireRange,
> > 	0x0,             // _GRA
> > 	0xe4,            // _MIN
> > 	0x3fff,          // _MAX
> > 	0x0,             // _TRA
> > 	0x04,            // _LEN
> > 	, ,
> > 	BTIO
> >       )
> >     })
> >     CreateQWordField (LORS, BTIO._MIN, CMIN)
> >     CreateQWordField (LORS, BTIO._MAX, CMAX)
> >     CreateQWordField (LORS, BTIO._LEN, CLEN)
> >
> >     Method (_PRS, 0) {
> >       Return (LORS)
> >     }
> >
> >     Method (_CRS, 0) {
> >       Return (LORS)
> >     }
> >     Method (_SRS, 1) {
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
> >       Store (IMIN, CMIN)
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
> >       Store (IMAX, CMAX)
> >     }
> >   }
> > [...]
> > }
> 
> Thanks. So this looks pretty much like normal Linux MFD device which we
> already have support for adding ACPI bindings to child devices. It
> should also support splitting resources to child devices IIRC.

I am not very familiar with Linux MFD however the main issue here is that
1) for IPMI we want to re-use the standard IPMI driver without touching it:
   see 

   static const struct acpi_device_id acpi_ipmi_match[] = {
         { "IPI0001", 0 },
         { },
   };

   in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
   of an LPC child)

2) We need a way to guarantee that all LPC children are not enumerated
   by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
   child it should not be enumerated, otherwise it should be)
   Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
   1) if the acpi resource type is a serial bus
   2) if the type of serial bus descriptor is I2C or SPI

   For LPC we cannot leverage on any ACPI property to "recognize" that our
   devices are LPC children; hence before I proposed for acpi_default_enumeration()
   to skip devices that have already been enumerated (by calling 
   acpi_device_enumerated() ).

So in the current scenario, how do you think that MFD can help?
Do you see any possible solution?

Many thanks
Gab
  

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 19:01                   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 19:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 13 June 2017 16:10
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > > Is there an example ASL showing how these LPC devices are
> > > currently presented in ACPI?
> >
> > Please find below the asl sketch for our LPC and IPMI
> >
> > //
> > // LPC
> > //
> >
> > Scope(_SB) {
> >   Device (LPC0) {
> >     Name (_HID, "HISI0191")  // HiSi LPC
> >     Name (_CRS, ResourceTemplate () {
> >       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
> >     })
> >   }
> >
> >   Device (LPC0.IPMI) {
> >     Name (_HID, "IPI0001")
> >     Method (_IFT) {
> >       Return (0x03)
> >     }
> >     Name (LORS, ResourceTemplate() {
> >       QWordIO (
> >         ResourceConsumer,
> > 	MinNotFixed,     // _MIF
> > 	MaxNotFixed,     // _MAF
> > 	PosDecode,
> > 	EntireRange,
> > 	0x0,             // _GRA
> > 	0xe4,            // _MIN
> > 	0x3fff,          // _MAX
> > 	0x0,             // _TRA
> > 	0x04,            // _LEN
> > 	, ,
> > 	BTIO
> >       )
> >     })
> >     CreateQWordField (LORS, BTIO._MIN, CMIN)
> >     CreateQWordField (LORS, BTIO._MAX, CMAX)
> >     CreateQWordField (LORS, BTIO._LEN, CLEN)
> >
> >     Method (_PRS, 0) {
> >       Return (LORS)
> >     }
> >
> >     Method (_CRS, 0) {
> >       Return (LORS)
> >     }
> >     Method (_SRS, 1) {
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
> >       Store (IMIN, CMIN)
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
> >       Store (IMAX, CMAX)
> >     }
> >   }
> > [...]
> > }
> 
> Thanks. So this looks pretty much like normal Linux MFD device which we
> already have support for adding ACPI bindings to child devices. It
> should also support splitting resources to child devices IIRC.

I am not very familiar with Linux MFD however the main issue here is that
1) for IPMI we want to re-use the standard IPMI driver without touching it:
   see 

   static const struct acpi_device_id acpi_ipmi_match[] = {
         { "IPI0001", 0 },
         { },
   };

   in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
   of an LPC child)

2) We need a way to guarantee that all LPC children are not enumerated
   by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
   child it should not be enumerated, otherwise it should be)
   Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
   1) if the acpi resource type is a serial bus
   2) if the type of serial bus descriptor is I2C or SPI

   For LPC we cannot leverage on any ACPI property to "recognize" that our
   devices are LPC children; hence before I proposed for acpi_default_enumeration()
   to skip devices that have already been enumerated (by calling 
   acpi_device_enumerated() ).

So in the current scenario, how do you think that MFD can help?
Do you see any possible solution?

Many thanks
Gab
  



^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 19:01                   ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-13 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg at linux.intel.com]
> Sent: 13 June 2017 16:10
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael at kernel.org; Rafael J. Wysocki;
> catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 02:38:26PM +0000, Gabriele Paoloni wrote:
> > > Is there an example ASL showing how these LPC devices are
> > > currently presented in ACPI?
> >
> > Please find below the asl sketch for our LPC and IPMI
> >
> > //
> > // LPC
> > //
> >
> > Scope(_SB) {
> >   Device (LPC0) {
> >     Name (_HID, "HISI0191")  // HiSi LPC
> >     Name (_CRS, ResourceTemplate () {
> >       Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000)
> >     })
> >   }
> >
> >   Device (LPC0.IPMI) {
> >     Name (_HID, "IPI0001")
> >     Method (_IFT) {
> >       Return (0x03)
> >     }
> >     Name (LORS, ResourceTemplate() {
> >       QWordIO (
> >         ResourceConsumer,
> > 	MinNotFixed,     // _MIF
> > 	MaxNotFixed,     // _MAF
> > 	PosDecode,
> > 	EntireRange,
> > 	0x0,             // _GRA
> > 	0xe4,            // _MIN
> > 	0x3fff,          // _MAX
> > 	0x0,             // _TRA
> > 	0x04,            // _LEN
> > 	, ,
> > 	BTIO
> >       )
> >     })
> >     CreateQWordField (LORS, BTIO._MIN, CMIN)
> >     CreateQWordField (LORS, BTIO._MAX, CMAX)
> >     CreateQWordField (LORS, BTIO._LEN, CLEN)
> >
> >     Method (_PRS, 0) {
> >       Return (LORS)
> >     }
> >
> >     Method (_CRS, 0) {
> >       Return (LORS)
> >     }
> >     Method (_SRS, 1) {
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MIN, IMIN)
> >       Store (IMIN, CMIN)
> >       CreateQWordField (Arg0, \_SB.LPC0.IPMI.BTIO._MAX, IMAX)
> >       Store (IMAX, CMAX)
> >     }
> >   }
> > [...]
> > }
> 
> Thanks. So this looks pretty much like normal Linux MFD device which we
> already have support for adding ACPI bindings to child devices. It
> should also support splitting resources to child devices IIRC.

I am not very familiar with Linux MFD however the main issue here is that
1) for IPMI we want to re-use the standard IPMI driver without touching it:
   see 

   static const struct acpi_device_id acpi_ipmi_match[] = {
         { "IPI0001", 0 },
         { },
   };

   in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
   of an LPC child)

2) We need a way to guarantee that all LPC children are not enumerated
   by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
   child it should not be enumerated, otherwise it should be)
   Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
   1) if the acpi resource type is a serial bus
   2) if the type of serial bus descriptor is I2C or SPI

   For LPC we cannot leverage on any ACPI property to "recognize" that our
   devices are LPC children; hence before I proposed for acpi_default_enumeration()
   to skip devices that have already been enumerated (by calling 
   acpi_device_enumerated() ).

So in the current scenario, how do you think that MFD can help?
Do you see any possible solution?

Many thanks
Gab
  

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-13 19:01                   ` Gabriele Paoloni
  (?)
  (?)
@ 2017-06-13 20:03                     ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 20:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> I am not very familiar with Linux MFD however the main issue here is that
> 1) for IPMI we want to re-use the standard IPMI driver without touching it:
>    see 
> 
>    static const struct acpi_device_id acpi_ipmi_match[] = {
>          { "IPI0001", 0 },
>          { },
>    };
> 
>    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
>    of an LPC child)
> 
> 2) We need a way to guarantee that all LPC children are not enumerated
>    by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
>    child it should not be enumerated, otherwise it should be)
>    Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
>    1) if the acpi resource type is a serial bus
>    2) if the type of serial bus descriptor is I2C or SPI
> 
>    For LPC we cannot leverage on any ACPI property to "recognize" that our
>    devices are LPC children; hence before I proposed for acpi_default_enumeration()
>    to skip devices that have already been enumerated (by calling 
>    acpi_device_enumerated() ).
> 
> So in the current scenario, how do you think that MFD can help?

If you look at Documentation/acpi/enumeration.txt there is a chapter
"MFD devices". I think it pretty much maches what you have here. An LPC
device (MFD device) and bunch of child devices. The driver for your LPC
device can specify _HID for each child device. Those are then mached by
the MFD ACPI code to the corresponding ACPI nodes from which platform
devices are created including "IPI0001".

It causes acpi_default_enumeration() to be called but it should be fine
as we are dealing with platform device anyway.

Once the platform device is created your ipmi driver will be probed by
the driver core.

Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 20:03                     ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 20:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> I am not very familiar with Linux MFD however the main issue here is that
> 1) for IPMI we want to re-use the standard IPMI driver without touching it:
>    see 
> 
>    static const struct acpi_device_id acpi_ipmi_match[] = {
>          { "IPI0001", 0 },
>          { },
>    };
> 
>    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
>    of an LPC child)
> 
> 2) We need a way to guarantee that all LPC children are not enumerated
>    by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
>    child it should not be enumerated, otherwise it should be)
>    Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
>    1) if the acpi resource type is a serial bus
>    2) if the type of serial bus descriptor is I2C or SPI
> 
>    For LPC we cannot leverage on any ACPI property to "recognize" that our
>    devices are LPC children; hence before I proposed for acpi_default_enumeration()
>    to skip devices that have already been enumerated (by calling 
>    acpi_device_enumerated() ).
> 
> So in the current scenario, how do you think that MFD can help?

If you look at Documentation/acpi/enumeration.txt there is a chapter
"MFD devices". I think it pretty much maches what you have here. An LPC
device (MFD device) and bunch of child devices. The driver for your LPC
device can specify _HID for each child device. Those are then mached by
the MFD ACPI code to the corresponding ACPI nodes from which platform
devices are created including "IPI0001".

It causes acpi_default_enumeration() to be called but it should be fine
as we are dealing with platform device anyway.

Once the platform device is created your ipmi driver will be probed by
the driver core.

Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 20:03                     ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 20:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> I am not very familiar with Linux MFD however the main issue here is that
> 1) for IPMI we want to re-use the standard IPMI driver without touching it:
>    see 
> 
>    static const struct acpi_device_id acpi_ipmi_match[] = {
>          { "IPI0001", 0 },
>          { },
>    };
> 
>    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
>    of an LPC child)
> 
> 2) We need a way to guarantee that all LPC children are not enumerated
>    by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
>    child it should not be enumerated, otherwise it should be)
>    Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
>    1) if the acpi resource type is a serial bus
>    2) if the type of serial bus descriptor is I2C or SPI
> 
>    For LPC we cannot leverage on any ACPI property to "recognize" that our
>    devices are LPC children; hence before I proposed for acpi_default_enumeration()
>    to skip devices that have already been enumerated (by calling 
>    acpi_device_enumerated() ).
> 
> So in the current scenario, how do you think that MFD can help?

If you look at Documentation/acpi/enumeration.txt there is a chapter
"MFD devices". I think it pretty much maches what you have here. An LPC
device (MFD device) and bunch of child devices. The driver for your LPC
device can specify _HID for each child device. Those are then mached by
the MFD ACPI code to the corresponding ACPI nodes from which platform
devices are created including "IPI0001".

It causes acpi_default_enumeration() to be called but it should be fine
as we are dealing with platform device anyway.

Once the platform device is created your ipmi driver will be probed by
the driver core.

Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-13 20:03                     ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-13 20:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> I am not very familiar with Linux MFD however the main issue here is that
> 1) for IPMI we want to re-use the standard IPMI driver without touching it:
>    see 
> 
>    static const struct acpi_device_id acpi_ipmi_match[] = {
>          { "IPI0001", 0 },
>          { },
>    };
> 
>    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard driver
>    of an LPC child)
> 
> 2) We need a way to guarantee that all LPC children are not enumerated
>    by acpi_default_enumeration() (so for example if an ipmi node is an LPC#
>    child it should not be enumerated, otherwise it should be)
>    Currently acpi_default_enumeration() skips spi/i2c slaves by checking:
>    1) if the acpi resource type is a serial bus
>    2) if the type of serial bus descriptor is I2C or SPI
> 
>    For LPC we cannot leverage on any ACPI property to "recognize" that our
>    devices are LPC children; hence before I proposed for acpi_default_enumeration()
>    to skip devices that have already been enumerated (by calling 
>    acpi_device_enumerated() ).
> 
> So in the current scenario, how do you think that MFD can help?

If you look at Documentation/acpi/enumeration.txt there is a chapter
"MFD devices". I think it pretty much maches what you have here. An LPC
device (MFD device) and bunch of child devices. The driver for your LPC
device can specify _HID for each child device. Those are then mached by
the MFD ACPI code to the corresponding ACPI nodes from which platform
devices are created including "IPI0001".

It causes acpi_default_enumeration() to be called but it should be fine
as we are dealing with platform device anyway.

Once the platform device is created your ipmi driver will be probed by
the driver core.

Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-13 20:03                     ` Mika Westerberg
  (?)
  (?)
@ 2017-06-15 18:01                       ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-15 18:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

Hi Mika

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Mika Westerberg
> Sent: 13 June 2017 21:04
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > I am not very familiar with Linux MFD however the main issue here is
> that
> > 1) for IPMI we want to re-use the standard IPMI driver without
> touching it:
> >    see
> >
> >    static const struct acpi_device_id acpi_ipmi_match[] = {
> >          { "IPI0001", 0 },
> >          { },
> >    };
> >
> >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> driver
> >    of an LPC child)
> >
> > 2) We need a way to guarantee that all LPC children are not
> enumerated
> >    by acpi_default_enumeration() (so for example if an ipmi node is
> an LPC#
> >    child it should not be enumerated, otherwise it should be)
> >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> checking:
> >    1) if the acpi resource type is a serial bus
> >    2) if the type of serial bus descriptor is I2C or SPI
> >
> >    For LPC we cannot leverage on any ACPI property to "recognize"
> that our
> >    devices are LPC children; hence before I proposed for
> acpi_default_enumeration()
> >    to skip devices that have already been enumerated (by calling
> >    acpi_device_enumerated() ).
> >
> > So in the current scenario, how do you think that MFD can help?
> 
> If you look at Documentation/acpi/enumeration.txt there is a chapter
> "MFD devices". I think it pretty much maches what you have here. An LPC
> device (MFD device) and bunch of child devices. The driver for your LPC
> device can specify _HID for each child device. Those are then mached by
> the MFD ACPI code to the corresponding ACPI nodes from which platform
> devices are created including "IPI0001".

So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:

	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
		.pnpid = "IPI0001",
	};

correct?

> 
> It causes acpi_default_enumeration() to be called but it should be fine
> as we are dealing with platform device anyway.

I do not quite understand how declaring such MFD cell above would make sure
that the LPC probe is called before the IPMI device is enumerated...

Could you point me to the code that does this?

Many Thanks
Gab

> 
> Once the platform device is created your ipmi driver will be probed by
> the driver core.
> 
> Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-15 18:01                       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-15 18:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Mika Westerberg
> Sent: 13 June 2017 21:04
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > I am not very familiar with Linux MFD however the main issue here is
> that
> > 1) for IPMI we want to re-use the standard IPMI driver without
> touching it:
> >    see
> >
> >    static const struct acpi_device_id acpi_ipmi_match[] = {
> >          { "IPI0001", 0 },
> >          { },
> >    };
> >
> >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> driver
> >    of an LPC child)
> >
> > 2) We need a way to guarantee that all LPC children are not
> enumerated
> >    by acpi_default_enumeration() (so for example if an ipmi node is
> an LPC#
> >    child it should not be enumerated, otherwise it should be)
> >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> checking:
> >    1) if the acpi resource type is a serial bus
> >    2) if the type of serial bus descriptor is I2C or SPI
> >
> >    For LPC we cannot leverage on any ACPI property to "recognize"
> that our
> >    devices are LPC children; hence before I proposed for
> acpi_default_enumeration()
> >    to skip devices that have already been enumerated (by calling
> >    acpi_device_enumerated() ).
> >
> > So in the current scenario, how do you think that MFD can help?
> 
> If you look at Documentation/acpi/enumeration.txt there is a chapter
> "MFD devices". I think it pretty much maches what you have here. An LPC
> device (MFD device) and bunch of child devices. The driver for your LPC
> device can specify _HID for each child device. Those are then mached by
> the MFD ACPI code to the corresponding ACPI nodes from which platform
> devices are created including "IPI0001".

So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:

	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
		.pnpid = "IPI0001",
	};

correct?

> 
> It causes acpi_default_enumeration() to be called but it should be fine
> as we are dealing with platform device anyway.

I do not quite understand how declaring such MFD cell above would make sure
that the LPC probe is called before the IPMI device is enumerated...

Could you point me to the code that does this?

Many Thanks
Gab

> 
> Once the platform device is created your ipmi driver will be probed by
> the driver core.
> 
> Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-15 18:01                       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-15 18:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: mark.rutland, minyard, Lorenzo Pieralisi, linux-acpi, arnd,
	rafael, linux-pci, catalin.marinas, John Garry,
	Rafael J. Wysocki, linux-kernel, will.deacon, Linuxarm, olof,
	robh+dt, xuwei (O),
	benh, bhelgaas, frowand.list, brian.starkey, linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Mika Westerberg
> Sent: 13 June 2017 21:04
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > I am not very familiar with Linux MFD however the main issue here is
> that
> > 1) for IPMI we want to re-use the standard IPMI driver without
> touching it:
> >    see
> >
> >    static const struct acpi_device_id acpi_ipmi_match[] = {
> >          { "IPI0001", 0 },
> >          { },
> >    };
> >
> >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> driver
> >    of an LPC child)
> >
> > 2) We need a way to guarantee that all LPC children are not
> enumerated
> >    by acpi_default_enumeration() (so for example if an ipmi node is
> an LPC#
> >    child it should not be enumerated, otherwise it should be)
> >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> checking:
> >    1) if the acpi resource type is a serial bus
> >    2) if the type of serial bus descriptor is I2C or SPI
> >
> >    For LPC we cannot leverage on any ACPI property to "recognize"
> that our
> >    devices are LPC children; hence before I proposed for
> acpi_default_enumeration()
> >    to skip devices that have already been enumerated (by calling
> >    acpi_device_enumerated() ).
> >
> > So in the current scenario, how do you think that MFD can help?
> 
> If you look at Documentation/acpi/enumeration.txt there is a chapter
> "MFD devices". I think it pretty much maches what you have here. An LPC
> device (MFD device) and bunch of child devices. The driver for your LPC
> device can specify _HID for each child device. Those are then mached by
> the MFD ACPI code to the corresponding ACPI nodes from which platform
> devices are created including "IPI0001".

So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:

	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
		.pnpid = "IPI0001",
	};

correct?

> 
> It causes acpi_default_enumeration() to be called but it should be fine
> as we are dealing with platform device anyway.

I do not quite understand how declaring such MFD cell above would make sure
that the LPC probe is called before the IPMI device is enumerated...

Could you point me to the code that does this?

Many Thanks
Gab

> 
> Once the platform device is created your ipmi driver will be probed by
> the driver core.
> 
> Does that make sense?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-15 18:01                       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-15 18:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
> owner at vger.kernel.org] On Behalf Of Mika Westerberg
> Sent: 13 June 2017 21:04
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; rafael at kernel.org; Rafael J. Wysocki;
> catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > I am not very familiar with Linux MFD however the main issue here is
> that
> > 1) for IPMI we want to re-use the standard IPMI driver without
> touching it:
> >    see
> >
> >    static const struct acpi_device_id acpi_ipmi_match[] = {
> >          { "IPI0001", 0 },
> >          { },
> >    };
> >
> >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> driver
> >    of an LPC child)
> >
> > 2) We need a way to guarantee that all LPC children are not
> enumerated
> >    by acpi_default_enumeration() (so for example if an ipmi node is
> an LPC#
> >    child it should not be enumerated, otherwise it should be)
> >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> checking:
> >    1) if the acpi resource type is a serial bus
> >    2) if the type of serial bus descriptor is I2C or SPI
> >
> >    For LPC we cannot leverage on any ACPI property to "recognize"
> that our
> >    devices are LPC children; hence before I proposed for
> acpi_default_enumeration()
> >    to skip devices that have already been enumerated (by calling
> >    acpi_device_enumerated() ).
> >
> > So in the current scenario, how do you think that MFD can help?
> 
> If you look at Documentation/acpi/enumeration.txt there is a chapter
> "MFD devices". I think it pretty much maches what you have here. An LPC
> device (MFD device) and bunch of child devices. The driver for your LPC
> device can specify _HID for each child device. Those are then mached by
> the MFD ACPI code to the corresponding ACPI nodes from which platform
> devices are created including "IPI0001".

So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:

	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
		.pnpid = "IPI0001",
	};

correct?

> 
> It causes acpi_default_enumeration() to be called but it should be fine
> as we are dealing with platform device anyway.

I do not quite understand how declaring such MFD cell above would make sure
that the LPC probe is called before the IPMI device is enumerated...

Could you point me to the code that does this?

Many Thanks
Gab

> 
> Once the platform device is created your ipmi driver will be probed by
> the driver core.
> 
> Does that make sense?

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-15 18:01                       ` Gabriele Paoloni
  (?)
  (?)
@ 2017-06-16  8:33                         ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16  8:33 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> > owner@vger.kernel.org] On Behalf Of Mika Westerberg
> > Sent: 13 June 2017 21:04
> > To: Gabriele Paoloni
> > Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> > 
> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > > I am not very familiar with Linux MFD however the main issue here is
> > that
> > > 1) for IPMI we want to re-use the standard IPMI driver without
> > touching it:
> > >    see
> > >
> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
> > >          { "IPI0001", 0 },
> > >          { },
> > >    };
> > >
> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> > driver
> > >    of an LPC child)
> > >
> > > 2) We need a way to guarantee that all LPC children are not
> > enumerated
> > >    by acpi_default_enumeration() (so for example if an ipmi node is
> > an LPC#
> > >    child it should not be enumerated, otherwise it should be)
> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> > checking:
> > >    1) if the acpi resource type is a serial bus
> > >    2) if the type of serial bus descriptor is I2C or SPI
> > >
> > >    For LPC we cannot leverage on any ACPI property to "recognize"
> > that our
> > >    devices are LPC children; hence before I proposed for
> > acpi_default_enumeration()
> > >    to skip devices that have already been enumerated (by calling
> > >    acpi_device_enumerated() ).
> > >
> > > So in the current scenario, how do you think that MFD can help?
> > 
> > If you look at Documentation/acpi/enumeration.txt there is a chapter
> > "MFD devices". I think it pretty much maches what you have here. An LPC
> > device (MFD device) and bunch of child devices. The driver for your LPC
> > device can specify _HID for each child device. Those are then mached by
> > the MFD ACPI code to the corresponding ACPI nodes from which platform
> > devices are created including "IPI0001".
> 
> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
> 
> 	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
> 		.pnpid = "IPI0001",
> 	};
> 
> correct?

Yes.

> > 
> > It causes acpi_default_enumeration() to be called but it should be fine
> > as we are dealing with platform device anyway.
> 
> I do not quite understand how declaring such MFD cell above would make sure
> that the LPC probe is called before the IPMI device is enumerated...

In fact it may be that it is not sufficient in this case because the
ACPI core might enumerate child devices before the LPC driver even gets
a chance to probe so you would need to add also scan handler to the
child devices and mark them already enumerated or something like that.

> Could you point me to the code that does this?

Check for example drivers/mfd/intel-lpss.c.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16  8:33                         ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16  8:33 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> > owner@vger.kernel.org] On Behalf Of Mika Westerberg
> > Sent: 13 June 2017 21:04
> > To: Gabriele Paoloni
> > Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> > 
> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > > I am not very familiar with Linux MFD however the main issue here is
> > that
> > > 1) for IPMI we want to re-use the standard IPMI driver without
> > touching it:
> > >    see
> > >
> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
> > >          { "IPI0001", 0 },
> > >          { },
> > >    };
> > >
> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> > driver
> > >    of an LPC child)
> > >
> > > 2) We need a way to guarantee that all LPC children are not
> > enumerated
> > >    by acpi_default_enumeration() (so for example if an ipmi node is
> > an LPC#
> > >    child it should not be enumerated, otherwise it should be)
> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> > checking:
> > >    1) if the acpi resource type is a serial bus
> > >    2) if the type of serial bus descriptor is I2C or SPI
> > >
> > >    For LPC we cannot leverage on any ACPI property to "recognize"
> > that our
> > >    devices are LPC children; hence before I proposed for
> > acpi_default_enumeration()
> > >    to skip devices that have already been enumerated (by calling
> > >    acpi_device_enumerated() ).
> > >
> > > So in the current scenario, how do you think that MFD can help?
> > 
> > If you look at Documentation/acpi/enumeration.txt there is a chapter
> > "MFD devices". I think it pretty much maches what you have here. An LPC
> > device (MFD device) and bunch of child devices. The driver for your LPC
> > device can specify _HID for each child device. Those are then mached by
> > the MFD ACPI code to the corresponding ACPI nodes from which platform
> > devices are created including "IPI0001".
> 
> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
> 
> 	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
> 		.pnpid = "IPI0001",
> 	};
> 
> correct?

Yes.

> > 
> > It causes acpi_default_enumeration() to be called but it should be fine
> > as we are dealing with platform device anyway.
> 
> I do not quite understand how declaring such MFD cell above would make sure
> that the LPC probe is called before the IPMI device is enumerated...

In fact it may be that it is not sufficient in this case because the
ACPI core might enumerate child devices before the LPC driver even gets
a chance to probe so you would need to add also scan handler to the
child devices and mark them already enumerated or something like that.

> Could you point me to the code that does this?

Check for example drivers/mfd/intel-lpss.c.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16  8:33                         ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16  8:33 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lorenzo Pieralisi, rafael, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> > owner@vger.kernel.org] On Behalf Of Mika Westerberg
> > Sent: 13 June 2017 21:04
> > To: Gabriele Paoloni
> > Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> > 
> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > > I am not very familiar with Linux MFD however the main issue here is
> > that
> > > 1) for IPMI we want to re-use the standard IPMI driver without
> > touching it:
> > >    see
> > >
> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
> > >          { "IPI0001", 0 },
> > >          { },
> > >    };
> > >
> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> > driver
> > >    of an LPC child)
> > >
> > > 2) We need a way to guarantee that all LPC children are not
> > enumerated
> > >    by acpi_default_enumeration() (so for example if an ipmi node is
> > an LPC#
> > >    child it should not be enumerated, otherwise it should be)
> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> > checking:
> > >    1) if the acpi resource type is a serial bus
> > >    2) if the type of serial bus descriptor is I2C or SPI
> > >
> > >    For LPC we cannot leverage on any ACPI property to "recognize"
> > that our
> > >    devices are LPC children; hence before I proposed for
> > acpi_default_enumeration()
> > >    to skip devices that have already been enumerated (by calling
> > >    acpi_device_enumerated() ).
> > >
> > > So in the current scenario, how do you think that MFD can help?
> > 
> > If you look at Documentation/acpi/enumeration.txt there is a chapter
> > "MFD devices". I think it pretty much maches what you have here. An LPC
> > device (MFD device) and bunch of child devices. The driver for your LPC
> > device can specify _HID for each child device. Those are then mached by
> > the MFD ACPI code to the corresponding ACPI nodes from which platform
> > devices are created including "IPI0001".
> 
> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
> 
> 	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
> 		.pnpid = "IPI0001",
> 	};
> 
> correct?

Yes.

> > 
> > It causes acpi_default_enumeration() to be called but it should be fine
> > as we are dealing with platform device anyway.
> 
> I do not quite understand how declaring such MFD cell above would make sure
> that the LPC probe is called before the IPMI device is enumerated...

In fact it may be that it is not sufficient in this case because the
ACPI core might enumerate child devices before the LPC driver even gets
a chance to probe so you would need to add also scan handler to the
child devices and mark them already enumerated or something like that.

> Could you point me to the code that does this?

Check for example drivers/mfd/intel-lpss.c.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16  8:33                         ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16  8:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
> > owner at vger.kernel.org] On Behalf Of Mika Westerberg
> > Sent: 13 June 2017 21:04
> > To: Gabriele Paoloni
> > Cc: Lorenzo Pieralisi; rafael at kernel.org; Rafael J. Wysocki;
> > catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> > frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> > kernel at lists.infradead.org; mark.rutland at arm.com;
> > brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> > kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> > pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> > 
> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
> > > I am not very familiar with Linux MFD however the main issue here is
> > that
> > > 1) for IPMI we want to re-use the standard IPMI driver without
> > touching it:
> > >    see
> > >
> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
> > >          { "IPI0001", 0 },
> > >          { },
> > >    };
> > >
> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
> > driver
> > >    of an LPC child)
> > >
> > > 2) We need a way to guarantee that all LPC children are not
> > enumerated
> > >    by acpi_default_enumeration() (so for example if an ipmi node is
> > an LPC#
> > >    child it should not be enumerated, otherwise it should be)
> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
> > checking:
> > >    1) if the acpi resource type is a serial bus
> > >    2) if the type of serial bus descriptor is I2C or SPI
> > >
> > >    For LPC we cannot leverage on any ACPI property to "recognize"
> > that our
> > >    devices are LPC children; hence before I proposed for
> > acpi_default_enumeration()
> > >    to skip devices that have already been enumerated (by calling
> > >    acpi_device_enumerated() ).
> > >
> > > So in the current scenario, how do you think that MFD can help?
> > 
> > If you look at Documentation/acpi/enumeration.txt there is a chapter
> > "MFD devices". I think it pretty much maches what you have here. An LPC
> > device (MFD device) and bunch of child devices. The driver for your LPC
> > device can specify _HID for each child device. Those are then mached by
> > the MFD ACPI code to the corresponding ACPI nodes from which platform
> > devices are created including "IPI0001".
> 
> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
> 
> 	static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
> 		.pnpid = "IPI0001",
> 	};
> 
> correct?

Yes.

> > 
> > It causes acpi_default_enumeration() to be called but it should be fine
> > as we are dealing with platform device anyway.
> 
> I do not quite understand how declaring such MFD cell above would make sure
> that the LPC probe is called before the IPMI device is enumerated...

In fact it may be that it is not sufficient in this case because the
ACPI core might enumerate child devices before the LPC driver even gets
a chance to probe so you would need to add also scan handler to the
child devices and mark them already enumerated or something like that.

> Could you point me to the code that does this?

Check for example drivers/mfd/intel-lpss.c.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-16  8:33                         ` Mika Westerberg
  (?)
  (?)
@ 2017-06-16 11:24                           ` Rafael J. Wysocki
  -1 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 11:24 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, rafael, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel@vger.kernel.org

On Fri, Jun 16, 2017 at 10:33 AM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
>> Hi Mika
>>
>> > -----Original Message-----
>> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
>> > owner@vger.kernel.org] On Behalf Of Mika Westerberg
>> > Sent: 13 June 2017 21:04
>> > To: Gabriele Paoloni
>> > Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
>> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
>> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
>> > kernel@lists.infradead.org; mark.rutland@arm.com;
>> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
>> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
>> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
>> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
>> > devices before scanning
>> >
>> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
>> > > I am not very familiar with Linux MFD however the main issue here is
>> > that
>> > > 1) for IPMI we want to re-use the standard IPMI driver without
>> > touching it:
>> > >    see
>> > >
>> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
>> > >          { "IPI0001", 0 },
>> > >          { },
>> > >    };
>> > >
>> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
>> > driver
>> > >    of an LPC child)
>> > >
>> > > 2) We need a way to guarantee that all LPC children are not
>> > enumerated
>> > >    by acpi_default_enumeration() (so for example if an ipmi node is
>> > an LPC#
>> > >    child it should not be enumerated, otherwise it should be)
>> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
>> > checking:
>> > >    1) if the acpi resource type is a serial bus
>> > >    2) if the type of serial bus descriptor is I2C or SPI
>> > >
>> > >    For LPC we cannot leverage on any ACPI property to "recognize"
>> > that our
>> > >    devices are LPC children; hence before I proposed for
>> > acpi_default_enumeration()
>> > >    to skip devices that have already been enumerated (by calling
>> > >    acpi_device_enumerated() ).
>> > >
>> > > So in the current scenario, how do you think that MFD can help?
>> >
>> > If you look at Documentation/acpi/enumeration.txt there is a chapter
>> > "MFD devices". I think it pretty much maches what you have here. An LPC
>> > device (MFD device) and bunch of child devices. The driver for your LPC
>> > device can specify _HID for each child device. Those are then mached by
>> > the MFD ACPI code to the corresponding ACPI nodes from which platform
>> > devices are created including "IPI0001".
>>
>> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
>>
>>       static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
>>               .pnpid = "IPI0001",
>>       };
>>
>> correct?
>
> Yes.
>
>> >
>> > It causes acpi_default_enumeration() to be called but it should be fine
>> > as we are dealing with platform device anyway.
>>
>> I do not quite understand how declaring such MFD cell above would make sure
>> that the LPC probe is called before the IPMI device is enumerated...
>
> In fact it may be that it is not sufficient in this case because the
> ACPI core might enumerate child devices before the LPC driver even gets
> a chance to probe so you would need to add also scan handler to the
> child devices and mark them already enumerated or something like that.

Or extend the special I2C/SPI handling to them.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 11:24                           ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 11:24 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, rafael, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Fri, Jun 16, 2017 at 10:33 AM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
>> Hi Mika
>>
>> > -----Original Message-----
>> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
>> > owner@vger.kernel.org] On Behalf Of Mika Westerberg
>> > Sent: 13 June 2017 21:04
>> > To: Gabriele Paoloni
>> > Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
>> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
>> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
>> > kernel@lists.infradead.org; mark.rutland@arm.com;
>> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
>> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
>> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
>> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
>> > devices before scanning
>> >
>> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
>> > > I am not very familiar with Linux MFD however the main issue here is
>> > that
>> > > 1) for IPMI we want to re-use the standard IPMI driver without
>> > touching it:
>> > >    see
>> > >
>> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
>> > >          { "IPI0001", 0 },
>> > >          { },
>> > >    };
>> > >
>> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
>> > driver
>> > >    of an LPC child)
>> > >
>> > > 2) We need a way to guarantee that all LPC children are not
>> > enumerated
>> > >    by acpi_default_enumeration() (so for example if an ipmi node is
>> > an LPC#
>> > >    child it should not be enumerated, otherwise it should be)
>> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
>> > checking:
>> > >    1) if the acpi resource type is a serial bus
>> > >    2) if the type of serial bus descriptor is I2C or SPI
>> > >
>> > >    For LPC we cannot leverage on any ACPI property to "recognize"
>> > that our
>> > >    devices are LPC children; hence before I proposed for
>> > acpi_default_enumeration()
>> > >    to skip devices that have already been enumerated (by calling
>> > >    acpi_device_enumerated() ).
>> > >
>> > > So in the current scenario, how do you think that MFD can help?
>> >
>> > If you look at Documentation/acpi/enumeration.txt there is a chapter
>> > "MFD devices". I think it pretty much maches what you have here. An LPC
>> > device (MFD device) and bunch of child devices. The driver for your LPC
>> > device can specify _HID for each child device. Those are then mached by
>> > the MFD ACPI code to the corresponding ACPI nodes from which platform
>> > devices are created including "IPI0001".
>>
>> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
>>
>>       static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
>>               .pnpid = "IPI0001",
>>       };
>>
>> correct?
>
> Yes.
>
>> >
>> > It causes acpi_default_enumeration() to be called but it should be fine
>> > as we are dealing with platform device anyway.
>>
>> I do not quite understand how declaring such MFD cell above would make sure
>> that the LPC probe is called before the IPMI device is enumerated...
>
> In fact it may be that it is not sufficient in this case because the
> ACPI core might enumerate child devices before the LPC driver even gets
> a chance to probe so you would need to add also scan handler to the
> child devices and mark them already enumerated or something like that.

Or extend the special I2C/SPI handling to them.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 11:24                           ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 11:24 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: mark.rutland, benh, Gabriele Paoloni, rafael, linux-pci,
	will.deacon, Linuxarm, frowand.list, Lorenzo Pieralisi, arnd,
	xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, linux-arm-kernel, Rafael J. Wysocki, linux-kernel,
	olof, brian.starkey

On Fri, Jun 16, 2017 at 10:33 AM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
>> Hi Mika
>>
>> > -----Original Message-----
>> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
>> > owner@vger.kernel.org] On Behalf Of Mika Westerberg
>> > Sent: 13 June 2017 21:04
>> > To: Gabriele Paoloni
>> > Cc: Lorenzo Pieralisi; rafael@kernel.org; Rafael J. Wysocki;
>> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
>> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
>> > kernel@lists.infradead.org; mark.rutland@arm.com;
>> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
>> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
>> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
>> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
>> > devices before scanning
>> >
>> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
>> > > I am not very familiar with Linux MFD however the main issue here is
>> > that
>> > > 1) for IPMI we want to re-use the standard IPMI driver without
>> > touching it:
>> > >    see
>> > >
>> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
>> > >          { "IPI0001", 0 },
>> > >          { },
>> > >    };
>> > >
>> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
>> > driver
>> > >    of an LPC child)
>> > >
>> > > 2) We need a way to guarantee that all LPC children are not
>> > enumerated
>> > >    by acpi_default_enumeration() (so for example if an ipmi node is
>> > an LPC#
>> > >    child it should not be enumerated, otherwise it should be)
>> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
>> > checking:
>> > >    1) if the acpi resource type is a serial bus
>> > >    2) if the type of serial bus descriptor is I2C or SPI
>> > >
>> > >    For LPC we cannot leverage on any ACPI property to "recognize"
>> > that our
>> > >    devices are LPC children; hence before I proposed for
>> > acpi_default_enumeration()
>> > >    to skip devices that have already been enumerated (by calling
>> > >    acpi_device_enumerated() ).
>> > >
>> > > So in the current scenario, how do you think that MFD can help?
>> >
>> > If you look at Documentation/acpi/enumeration.txt there is a chapter
>> > "MFD devices". I think it pretty much maches what you have here. An LPC
>> > device (MFD device) and bunch of child devices. The driver for your LPC
>> > device can specify _HID for each child device. Those are then mached by
>> > the MFD ACPI code to the corresponding ACPI nodes from which platform
>> > devices are created including "IPI0001".
>>
>> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
>>
>>       static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
>>               .pnpid = "IPI0001",
>>       };
>>
>> correct?
>
> Yes.
>
>> >
>> > It causes acpi_default_enumeration() to be called but it should be fine
>> > as we are dealing with platform device anyway.
>>
>> I do not quite understand how declaring such MFD cell above would make sure
>> that the LPC probe is called before the IPMI device is enumerated...
>
> In fact it may be that it is not sufficient in this case because the
> ACPI core might enumerate child devices before the LPC driver even gets
> a chance to probe so you would need to add also scan handler to the
> child devices and mark them already enumerated or something like that.

Or extend the special I2C/SPI handling to them.

Thanks,
Rafael

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 11:24                           ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 16, 2017 at 10:33 AM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Thu, Jun 15, 2017 at 06:01:02PM +0000, Gabriele Paoloni wrote:
>> Hi Mika
>>
>> > -----Original Message-----
>> > From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
>> > owner at vger.kernel.org] On Behalf Of Mika Westerberg
>> > Sent: 13 June 2017 21:04
>> > To: Gabriele Paoloni
>> > Cc: Lorenzo Pieralisi; rafael at kernel.org; Rafael J. Wysocki;
>> > catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
>> > frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
>> > kernel at lists.infradead.org; mark.rutland at arm.com;
>> > brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
>> > kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
>> > pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
>> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
>> > devices before scanning
>> >
>> > On Tue, Jun 13, 2017 at 07:01:38PM +0000, Gabriele Paoloni wrote:
>> > > I am not very familiar with Linux MFD however the main issue here is
>> > that
>> > > 1) for IPMI we want to re-use the standard IPMI driver without
>> > touching it:
>> > >    see
>> > >
>> > >    static const struct acpi_device_id acpi_ipmi_match[] = {
>> > >          { "IPI0001", 0 },
>> > >          { },
>> > >    };
>> > >
>> > >    in "drivers/char/ipmi/ipmi_si_intf.c" (and in general any standard
>> > driver
>> > >    of an LPC child)
>> > >
>> > > 2) We need a way to guarantee that all LPC children are not
>> > enumerated
>> > >    by acpi_default_enumeration() (so for example if an ipmi node is
>> > an LPC#
>> > >    child it should not be enumerated, otherwise it should be)
>> > >    Currently acpi_default_enumeration() skips spi/i2c slaves by
>> > checking:
>> > >    1) if the acpi resource type is a serial bus
>> > >    2) if the type of serial bus descriptor is I2C or SPI
>> > >
>> > >    For LPC we cannot leverage on any ACPI property to "recognize"
>> > that our
>> > >    devices are LPC children; hence before I proposed for
>> > acpi_default_enumeration()
>> > >    to skip devices that have already been enumerated (by calling
>> > >    acpi_device_enumerated() ).
>> > >
>> > > So in the current scenario, how do you think that MFD can help?
>> >
>> > If you look at Documentation/acpi/enumeration.txt there is a chapter
>> > "MFD devices". I think it pretty much maches what you have here. An LPC
>> > device (MFD device) and bunch of child devices. The driver for your LPC
>> > device can specify _HID for each child device. Those are then mached by
>> > the MFD ACPI code to the corresponding ACPI nodes from which platform
>> > devices are created including "IPI0001".
>>
>> So I guess here in the LPC driver I would have an MFD cell for IPMI. I.e.:
>>
>>       static struct mfd_cell_acpi_match hisi_lpc_ipmi_acpi_match = {
>>               .pnpid = "IPI0001",
>>       };
>>
>> correct?
>
> Yes.
>
>> >
>> > It causes acpi_default_enumeration() to be called but it should be fine
>> > as we are dealing with platform device anyway.
>>
>> I do not quite understand how declaring such MFD cell above would make sure
>> that the LPC probe is called before the IPMI device is enumerated...
>
> In fact it may be that it is not sufficient in this case because the
> ACPI core might enumerate child devices before the LPC driver even gets
> a chance to probe so you would need to add also scan handler to the
> child devices and mark them already enumerated or something like that.

Or extend the special I2C/SPI handling to them.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-16 11:24                           ` Rafael J. Wysocki
  (?)
  (?)
@ 2017-06-16 12:00                             ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16 12:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel

On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> > In fact it may be that it is not sufficient in this case because the
> > ACPI core might enumerate child devices before the LPC driver even gets
> > a chance to probe so you would need to add also scan handler to the
> > child devices and mark them already enumerated or something like that.
> 
> Or extend the special I2C/SPI handling to them.

Sure but those have I2c/SpiSerialBus() resources which we can use to
identify them but for the ipmi thing there is nothing else than _HID so
we would need to keep a list of such devices in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 12:00                             ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16 12:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> > In fact it may be that it is not sufficient in this case because the
> > ACPI core might enumerate child devices before the LPC driver even gets
> > a chance to probe so you would need to add also scan handler to the
> > child devices and mark them already enumerated or something like that.
> 
> Or extend the special I2C/SPI handling to them.

Sure but those have I2c/SpiSerialBus() resources which we can use to
identify them but for the ipmi thing there is nothing else than _HID so
we would need to keep a list of such devices in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 12:00                             ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16 12:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> > In fact it may be that it is not sufficient in this case because the
> > ACPI core might enumerate child devices before the LPC driver even gets
> > a chance to probe so you would need to add also scan handler to the
> > child devices and mark them already enumerated or something like that.
> 
> Or extend the special I2C/SPI handling to them.

Sure but those have I2c/SpiSerialBus() resources which we can use to
identify them but for the ipmi thing there is nothing else than _HID so
we would need to keep a list of such devices in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 12:00                             ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-16 12:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> > In fact it may be that it is not sufficient in this case because the
> > ACPI core might enumerate child devices before the LPC driver even gets
> > a chance to probe so you would need to add also scan handler to the
> > child devices and mark them already enumerated or something like that.
> 
> Or extend the special I2C/SPI handling to them.

Sure but those have I2c/SpiSerialBus() resources which we can use to
identify them but for the ipmi thing there is nothing else than _HID so
we would need to keep a list of such devices in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-16 12:00                             ` Mika Westerberg
  (?)
  (?)
@ 2017-06-16 12:22                               ` Rafael J. Wysocki
  -1 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 12:22 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
>>
>> Or extend the special I2C/SPI handling to them.
>
> Sure but those have I2c/SpiSerialBus() resources which we can use to
> identify them but for the ipmi thing there is nothing else than _HID so
> we would need to keep a list of such devices in ACPI core.

OK, so adding a scan handler for that would be the way to go IMO.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 12:22                               ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 12:22 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
>>
>> Or extend the special I2C/SPI handling to them.
>
> Sure but those have I2c/SpiSerialBus() resources which we can use to
> identify them but for the ipmi thing there is nothing else than _HID so
> we would need to keep a list of such devices in ACPI core.

OK, so adding a scan handler for that would be the way to go IMO.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 12:22                               ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 12:22 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: mark.rutland, benh, Gabriele Paoloni, Rafael J. Wysocki,
	linux-pci, will.deacon, Linuxarm, frowand.list,
	Lorenzo Pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, linux-arm-kernel, Rafael J. Wysocki, linux-kernel,
	olof, brian.starkey

On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
>>
>> Or extend the special I2C/SPI handling to them.
>
> Sure but those have I2c/SpiSerialBus() resources which we can use to
> identify them but for the ipmi thing there is nothing else than _HID so
> we would need to keep a list of such devices in ACPI core.

OK, so adding a scan handler for that would be the way to go IMO.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-16 12:22                               ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-16 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
>>
>> Or extend the special I2C/SPI handling to them.
>
> Sure but those have I2c/SpiSerialBus() resources which we can use to
> identify them but for the ipmi thing there is nothing else than _HID so
> we would need to keep a list of such devices in ACPI core.

OK, so adding a scan handler for that would be the way to go IMO.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-16 12:22                               ` Rafael J. Wysocki
  (?)
  (?)
@ 2017-06-19  9:50                                 ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19  9:50 UTC (permalink / raw)
  To: Rafael J. Wysocki, Mika Westerberg
  Cc: Lorenzo Pieralisi, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm

Hi Rafael, Mika, Lorenzo

> -----Original Message-----
> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
> Rafael J. Wysocki
> Sent: 16 June 2017 13:23
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Gabriele Paoloni; Lorenzo Pieralisi; Rafael J.
> Wysocki; catalin.marinas@arm.com; will.deacon@arm.com;
> robh+dt@kernel.org; frowand.list@gmail.com; bhelgaas@google.com;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> mark.rutland@arm.com; brian.starkey@arm.com; olof@lixom.net;
> benh@kernel.crashing.org; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; Linuxarm; linux-pci@vger.kernel.org;
> minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> >> > In fact it may be that it is not sufficient in this case because
> the
> >> > ACPI core might enumerate child devices before the LPC driver even
> gets
> >> > a chance to probe so you would need to add also scan handler to
> the
> >> > child devices and mark them already enumerated or something like
> that.
> >>
> >> Or extend the special I2C/SPI handling to them.
> >
> > Sure but those have I2c/SpiSerialBus() resources which we can use to
> > identify them but for the ipmi thing there is nothing else than _HID
> so
> > we would need to keep a list of such devices in ACPI core.
> 
> OK, so adding a scan handler for that would be the way to go IMO.

Many thanks for your response and your help here.

I guess that as conclusion with respect to the current v9 patchset we can
disregard the idea of MFD and modify the current v9 so that it doesn't
touch directly ACPI resources.
Instead as I proposed before we can have the scan handler to enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

Do you think it as a viable solution?

Thanks
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19  9:50                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19  9:50 UTC (permalink / raw)
  To: Rafael J. Wysocki, Mika Westerberg
  Cc: Lorenzo Pieralisi, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Rafael, Mika, Lorenzo

> -----Original Message-----
> From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of
> Rafael J. Wysocki
> Sent: 16 June 2017 13:23
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Gabriele Paoloni; Lorenzo Pieralisi; Rafael J.
> Wysocki; catalin.marinas@arm.com; will.deacon@arm.com;
> robh+dt@kernel.org; frowand.list@gmail.com; bhelgaas@google.com;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> mark.rutland@arm.com; brian.starkey@arm.com; olof@lixom.net;
> benh@kernel.crashing.org; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; Linuxarm; linux-pci@vger.kernel.org;
> minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> >> > In fact it may be that it is not sufficient in this case because
> the
> >> > ACPI core might enumerate child devices before the LPC driver even
> gets
> >> > a chance to probe so you would need to add also scan handler to
> the
> >> > child devices and mark them already enumerated or something like
> that.
> >>
> >> Or extend the special I2C/SPI handling to them.
> >
> > Sure but those have I2c/SpiSerialBus() resources which we can use to
> > identify them but for the ipmi thing there is nothing else than _HID
> so
> > we would need to keep a list of such devices in ACPI core.
> 
> OK, so adding a scan handler for that would be the way to go IMO.

Many thanks for your response and your help here.

I guess that as conclusion with respect to the current v9 patchset we can
disregard the idea of MFD and modify the current v9 so that it doesn't
touch directly ACPI resources.
Instead as I proposed before we can have the scan handler to enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

Do you think it as a viable solution?

Thanks
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19  9:50                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19  9:50 UTC (permalink / raw)
  To: Rafael J. Wysocki, Mika Westerberg
  Cc: Lorenzo Pieralisi, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

SGkgUmFmYWVsLCBNaWthLCBMb3JlbnpvDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0N
Cj4gRnJvbTogcmp3eXNvY2tpQGdtYWlsLmNvbSBbbWFpbHRvOnJqd3lzb2NraUBnbWFpbC5jb21d
IE9uIEJlaGFsZiBPZg0KPiBSYWZhZWwgSi4gV3lzb2NraQ0KPiBTZW50OiAxNiBKdW5lIDIwMTcg
MTM6MjMNCj4gVG86IE1pa2EgV2VzdGVyYmVyZw0KPiBDYzogUmFmYWVsIEouIFd5c29ja2k7IEdh
YnJpZWxlIFBhb2xvbmk7IExvcmVuem8gUGllcmFsaXNpOyBSYWZhZWwgSi4NCj4gV3lzb2NraTsg
Y2F0YWxpbi5tYXJpbmFzQGFybS5jb207IHdpbGwuZGVhY29uQGFybS5jb207DQo+IHJvYmgrZHRA
a2VybmVsLm9yZzsgZnJvd2FuZC5saXN0QGdtYWlsLmNvbTsgYmhlbGdhYXNAZ29vZ2xlLmNvbTsN
Cj4gYXJuZEBhcm5kYi5kZTsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOw0K
PiBtYXJrLnJ1dGxhbmRAYXJtLmNvbTsgYnJpYW4uc3RhcmtleUBhcm0uY29tOyBvbG9mQGxpeG9t
Lm5ldDsNCj4gYmVuaEBrZXJuZWwuY3Jhc2hpbmcub3JnOyBsaW51eC1rZXJuZWxAdmdlci5rZXJu
ZWwub3JnOyBsaW51eC0NCj4gYWNwaUB2Z2VyLmtlcm5lbC5vcmc7IExpbnV4YXJtOyBsaW51eC1w
Y2lAdmdlci5rZXJuZWwub3JnOw0KPiBtaW55YXJkQGFjbS5vcmc7IEpvaG4gR2Fycnk7IHh1d2Vp
IChPKQ0KPiBTdWJqZWN0OiBSZTogW1BBVENIIHY5IDUvN10gQUNQSTogVHJhbnNsYXRlIHRoZSBJ
L08gcmFuZ2Ugb2Ygbm9uLU1NSU8NCj4gZGV2aWNlcyBiZWZvcmUgc2Nhbm5pbmcNCj4gDQo+IE9u
IEZyaSwgSnVuIDE2LCAyMDE3IGF0IDI6MDAgUE0sIE1pa2EgV2VzdGVyYmVyZw0KPiA8bWlrYS53
ZXN0ZXJiZXJnQGxpbnV4LmludGVsLmNvbT4gd3JvdGU6DQo+ID4gT24gRnJpLCBKdW4gMTYsIDIw
MTcgYXQgMDE6MjQ6MzJQTSArMDIwMCwgUmFmYWVsIEouIFd5c29ja2kgd3JvdGU6DQo+ID4+ID4g
SW4gZmFjdCBpdCBtYXkgYmUgdGhhdCBpdCBpcyBub3Qgc3VmZmljaWVudCBpbiB0aGlzIGNhc2Ug
YmVjYXVzZQ0KPiB0aGUNCj4gPj4gPiBBQ1BJIGNvcmUgbWlnaHQgZW51bWVyYXRlIGNoaWxkIGRl
dmljZXMgYmVmb3JlIHRoZSBMUEMgZHJpdmVyIGV2ZW4NCj4gZ2V0cw0KPiA+PiA+IGEgY2hhbmNl
IHRvIHByb2JlIHNvIHlvdSB3b3VsZCBuZWVkIHRvIGFkZCBhbHNvIHNjYW4gaGFuZGxlciB0bw0K
PiB0aGUNCj4gPj4gPiBjaGlsZCBkZXZpY2VzIGFuZCBtYXJrIHRoZW0gYWxyZWFkeSBlbnVtZXJh
dGVkIG9yIHNvbWV0aGluZyBsaWtlDQo+IHRoYXQuDQo+ID4+DQo+ID4+IE9yIGV4dGVuZCB0aGUg
c3BlY2lhbCBJMkMvU1BJIGhhbmRsaW5nIHRvIHRoZW0uDQo+ID4NCj4gPiBTdXJlIGJ1dCB0aG9z
ZSBoYXZlIEkyYy9TcGlTZXJpYWxCdXMoKSByZXNvdXJjZXMgd2hpY2ggd2UgY2FuIHVzZSB0bw0K
PiA+IGlkZW50aWZ5IHRoZW0gYnV0IGZvciB0aGUgaXBtaSB0aGluZyB0aGVyZSBpcyBub3RoaW5n
IGVsc2UgdGhhbiBfSElEDQo+IHNvDQo+ID4gd2Ugd291bGQgbmVlZCB0byBrZWVwIGEgbGlzdCBv
ZiBzdWNoIGRldmljZXMgaW4gQUNQSSBjb3JlLg0KPiANCj4gT0ssIHNvIGFkZGluZyBhIHNjYW4g
aGFuZGxlciBmb3IgdGhhdCB3b3VsZCBiZSB0aGUgd2F5IHRvIGdvIElNTy4NCg0KTWFueSB0aGFu
a3MgZm9yIHlvdXIgcmVzcG9uc2UgYW5kIHlvdXIgaGVscCBoZXJlLg0KDQpJIGd1ZXNzIHRoYXQg
YXMgY29uY2x1c2lvbiB3aXRoIHJlc3BlY3QgdG8gdGhlIGN1cnJlbnQgdjkgcGF0Y2hzZXQgd2Ug
Y2FuDQpkaXNyZWdhcmQgdGhlIGlkZWEgb2YgTUZEIGFuZCBtb2RpZnkgdGhlIGN1cnJlbnQgdjkg
c28gdGhhdCBpdCBkb2Vzbid0DQp0b3VjaCBkaXJlY3RseSBBQ1BJIHJlc291cmNlcy4NCkluc3Rl
YWQgYXMgSSBwcm9wb3NlZCBiZWZvcmUgd2UgY2FuIGhhdmUgdGhlIHNjYW4gaGFuZGxlciB0byBl
bnVtZXJhdGUNCnRoZSBjaGlsZHJlbiBkZXZpY2VzIGFuZCB0cmFuc2xhdGUgaXRzIGFkZHJlc3Nl
cyBmaWxsaW5nIGRldi0+cmVzb3VyY2VzW10gYW5kDQphdCB0aGUgc2FtZSB0aW1lIHdlIGNhbiBt
b2RpZnkgYWNwaV9kZWZhdWx0X2VudW1lcmF0aW9uIHRvIGNoZWNrDQphY3BpX2RldmljZV9lbnVt
ZXJhdGVkKCkgYmVmb3JlIGNvbnRpbnVpbmcgd2l0aCBkZXZpY2UgZW51bWVyYXRpb24uLi4/DQoN
CkRvIHlvdSB0aGluayBpdCBhcyBhIHZpYWJsZSBzb2x1dGlvbj8NCg0KVGhhbmtzDQpHYWINCg==

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19  9:50                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rafael, Mika, Lorenzo

> -----Original Message-----
> From: rjwysocki at gmail.com [mailto:rjwysocki at gmail.com] On Behalf Of
> Rafael J. Wysocki
> Sent: 16 June 2017 13:23
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Gabriele Paoloni; Lorenzo Pieralisi; Rafael J.
> Wysocki; catalin.marinas at arm.com; will.deacon at arm.com;
> robh+dt at kernel.org; frowand.list at gmail.com; bhelgaas at google.com;
> arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> mark.rutland at arm.com; brian.starkey at arm.com; olof at lixom.net;
> benh at kernel.crashing.org; linux-kernel at vger.kernel.org; linux-
> acpi at vger.kernel.org; Linuxarm; linux-pci at vger.kernel.org;
> minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Fri, Jun 16, 2017 at 2:00 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Fri, Jun 16, 2017 at 01:24:32PM +0200, Rafael J. Wysocki wrote:
> >> > In fact it may be that it is not sufficient in this case because
> the
> >> > ACPI core might enumerate child devices before the LPC driver even
> gets
> >> > a chance to probe so you would need to add also scan handler to
> the
> >> > child devices and mark them already enumerated or something like
> that.
> >>
> >> Or extend the special I2C/SPI handling to them.
> >
> > Sure but those have I2c/SpiSerialBus() resources which we can use to
> > identify them but for the ipmi thing there is nothing else than _HID
> so
> > we would need to keep a list of such devices in ACPI core.
> 
> OK, so adding a scan handler for that would be the way to go IMO.

Many thanks for your response and your help here.

I guess that as conclusion with respect to the current v9 patchset we can
disregard the idea of MFD and modify the current v9 so that it doesn't
touch directly ACPI resources.
Instead as I proposed before we can have the scan handler to enumerate
the children devices and translate its addresses filling dev->resources[] and
at the same time we can modify acpi_default_enumeration to check
acpi_device_enumerated() before continuing with device enumeration...?

Do you think it as a viable solution?

Thanks
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-19  9:50                                 ` Gabriele Paoloni
  (?)
  (?)
@ 2017-06-19 10:02                                   ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-19 10:02 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> Many thanks for your response and your help here.
> 
> I guess that as conclusion with respect to the current v9 patchset we can
> disregard the idea of MFD and modify the current v9 so that it doesn't
> touch directly ACPI resources.
> Instead as I proposed before we can have the scan handler to enumerate
> the children devices and translate its addresses filling dev->resources[] and
> at the same time we can modify acpi_default_enumeration to check
> acpi_device_enumerated() before continuing with device enumeration...?
> 
> Do you think it as a viable solution?

No, I think MFD + scan handler inside the MFD driver is the way to go.
We don't want to trash ACPI core with stuff that does not belong there
IMHO.

Also you don't need to modify acpi_default_enumeration() because you can
mark your device enumerated in the MFD driver. So all the dirty details
will be in the MFD driver and not in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19 10:02                                   ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-19 10:02 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> Many thanks for your response and your help here.
> 
> I guess that as conclusion with respect to the current v9 patchset we can
> disregard the idea of MFD and modify the current v9 so that it doesn't
> touch directly ACPI resources.
> Instead as I proposed before we can have the scan handler to enumerate
> the children devices and translate its addresses filling dev->resources[] and
> at the same time we can modify acpi_default_enumeration to check
> acpi_device_enumerated() before continuing with device enumeration...?
> 
> Do you think it as a viable solution?

No, I think MFD + scan handler inside the MFD driver is the way to go.
We don't want to trash ACPI core with stuff that does not belong there
IMHO.

Also you don't need to modify acpi_default_enumeration() because you can
mark your device enumerated in the MFD driver. So all the dirty details
will be in the MFD driver and not in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19 10:02                                   ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-19 10:02 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, minyard, Lorenzo Pieralisi, linux-acpi, arnd,
	Rafael J. Wysocki, linux-pci, catalin.marinas, John Garry,
	Rafael J. Wysocki, linux-kernel, will.deacon, Linuxarm, olof,
	robh+dt, xuwei (O),
	benh, bhelgaas, frowand.list, brian.starkey, linux-arm-kernel

On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> Many thanks for your response and your help here.
> 
> I guess that as conclusion with respect to the current v9 patchset we can
> disregard the idea of MFD and modify the current v9 so that it doesn't
> touch directly ACPI resources.
> Instead as I proposed before we can have the scan handler to enumerate
> the children devices and translate its addresses filling dev->resources[] and
> at the same time we can modify acpi_default_enumeration to check
> acpi_device_enumerated() before continuing with device enumeration...?
> 
> Do you think it as a viable solution?

No, I think MFD + scan handler inside the MFD driver is the way to go.
We don't want to trash ACPI core with stuff that does not belong there
IMHO.

Also you don't need to modify acpi_default_enumeration() because you can
mark your device enumerated in the MFD driver. So all the dirty details
will be in the MFD driver and not in ACPI core.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19 10:02                                   ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-19 10:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> Many thanks for your response and your help here.
> 
> I guess that as conclusion with respect to the current v9 patchset we can
> disregard the idea of MFD and modify the current v9 so that it doesn't
> touch directly ACPI resources.
> Instead as I proposed before we can have the scan handler to enumerate
> the children devices and translate its addresses filling dev->resources[] and
> at the same time we can modify acpi_default_enumeration to check
> acpi_device_enumerated() before continuing with device enumeration...?
> 
> Do you think it as a viable solution?

No, I think MFD + scan handler inside the MFD driver is the way to go.
We don't want to trash ACPI core with stuff that does not belong there
IMHO.

Also you don't need to modify acpi_default_enumeration() because you can
mark your device enumerated in the MFD driver. So all the dirty details
will be in the MFD driver and not in ACPI core.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-19 10:02                                   ` Mika Westerberg
  (?)
  (?)
@ 2017-06-19 10:04                                     ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19 10:04 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 19 June 2017 11:02
> To: Gabriele Paoloni
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > Many thanks for your response and your help here.
> >
> > I guess that as conclusion with respect to the current v9 patchset we
> can
> > disregard the idea of MFD and modify the current v9 so that it
> doesn't
> > touch directly ACPI resources.
> > Instead as I proposed before we can have the scan handler to
> enumerate
> > the children devices and translate its addresses filling dev-
> >resources[] and
> > at the same time we can modify acpi_default_enumeration to check
> > acpi_device_enumerated() before continuing with device
> enumeration...?
> >
> > Do you think it as a viable solution?
> 
> No, I think MFD + scan handler inside the MFD driver is the way to go.
> We don't want to trash ACPI core with stuff that does not belong there
> IMHO.

Ok Many thanks I will investigate this direction 

> 
> Also you don't need to modify acpi_default_enumeration() because you
> can
> mark your device enumerated in the MFD driver. So all the dirty details
> will be in the MFD driver and not in ACPI core.

Ok got it :)

Cheers
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19 10:04                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19 10:04 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 19 June 2017 11:02
> To: Gabriele Paoloni
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > Many thanks for your response and your help here.
> >
> > I guess that as conclusion with respect to the current v9 patchset we
> can
> > disregard the idea of MFD and modify the current v9 so that it
> doesn't
> > touch directly ACPI resources.
> > Instead as I proposed before we can have the scan handler to
> enumerate
> > the children devices and translate its addresses filling dev-
> >resources[] and
> > at the same time we can modify acpi_default_enumeration to check
> > acpi_device_enumerated() before continuing with device
> enumeration...?
> >
> > Do you think it as a viable solution?
> 
> No, I think MFD + scan handler inside the MFD driver is the way to go.
> We don't want to trash ACPI core with stuff that does not belong there
> IMHO.

Ok Many thanks I will investigate this direction 

> 
> Also you don't need to modify acpi_default_enumeration() because you
> can
> mark your device enumerated in the MFD driver. So all the dirty details
> will be in the MFD driver and not in ACPI core.

Ok got it :)

Cheers
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19 10:04                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19 10:04 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: 19 June 2017 11:02
> To: Gabriele Paoloni
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > Many thanks for your response and your help here.
> >
> > I guess that as conclusion with respect to the current v9 patchset we
> can
> > disregard the idea of MFD and modify the current v9 so that it
> doesn't
> > touch directly ACPI resources.
> > Instead as I proposed before we can have the scan handler to
> enumerate
> > the children devices and translate its addresses filling dev-
> >resources[] and
> > at the same time we can modify acpi_default_enumeration to check
> > acpi_device_enumerated() before continuing with device
> enumeration...?
> >
> > Do you think it as a viable solution?
> 
> No, I think MFD + scan handler inside the MFD driver is the way to go.
> We don't want to trash ACPI core with stuff that does not belong there
> IMHO.

Ok Many thanks I will investigate this direction 

> 
> Also you don't need to modify acpi_default_enumeration() because you
> can
> mark your device enumerated in the MFD driver. So all the dirty details
> will be in the MFD driver and not in ACPI core.

Ok got it :)

Cheers
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-19 10:04                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-06-19 10:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg at linux.intel.com]
> Sent: 19 June 2017 11:02
> To: Gabriele Paoloni
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > Many thanks for your response and your help here.
> >
> > I guess that as conclusion with respect to the current v9 patchset we
> can
> > disregard the idea of MFD and modify the current v9 so that it
> doesn't
> > touch directly ACPI resources.
> > Instead as I proposed before we can have the scan handler to
> enumerate
> > the children devices and translate its addresses filling dev-
> >resources[] and
> > at the same time we can modify acpi_default_enumeration to check
> > acpi_device_enumerated() before continuing with device
> enumeration...?
> >
> > Do you think it as a viable solution?
> 
> No, I think MFD + scan handler inside the MFD driver is the way to go.
> We don't want to trash ACPI core with stuff that does not belong there
> IMHO.

Ok Many thanks I will investigate this direction 

> 
> Also you don't need to modify acpi_default_enumeration() because you
> can
> mark your device enumerated in the MFD driver. So all the dirty details
> will be in the MFD driver and not in ACPI core.

Ok got it :)

Cheers
Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-16 11:24                           ` Rafael J. Wysocki
  (?)
  (?)
@ 2017-06-29 16:16                             ` John Garry
  -1 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-29 16:16 UTC (permalink / raw)
  To: Rafael J. Wysocki, Mika Westerberg
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel

On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>> >> >
>>>> >> > It causes acpi_default_enumeration() to be called but it should be fine
>>>> >> > as we are dealing with platform device anyway.
>>> >>
>>> >> I do not quite understand how declaring such MFD cell above would make sure
>>> >> that the LPC probe is called before the IPMI device is enumerated...
>> >
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
> Or extend the special I2C/SPI handling to them.
>

For this, is it possible to just configure the ACPI table so we spoof 
that the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a 
resource of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus 
type i2c/spi to solve this?

This resource would/should need to be ignored for other purposes.

John

> Thanks,
> Rafael



^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-29 16:16                             ` John Garry
  0 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-29 16:16 UTC (permalink / raw)
  To: Rafael J. Wysocki, Mika Westerberg
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard, xuwei (O)

On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>> >> >
>>>> >> > It causes acpi_default_enumeration() to be called but it should be fine
>>>> >> > as we are dealing with platform device anyway.
>>> >>
>>> >> I do not quite understand how declaring such MFD cell above would make sure
>>> >> that the LPC probe is called before the IPMI device is enumerated...
>> >
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
> Or extend the special I2C/SPI handling to them.
>

For this, is it possible to just configure the ACPI table so we spoof 
that the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a 
resource of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus 
type i2c/spi to solve this?

This resource would/should need to be ignored for other purposes.

John

> Thanks,
> Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-29 16:16                             ` John Garry
  0 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-29 16:16 UTC (permalink / raw)
  To: Rafael J. Wysocki, Mika Westerberg
  Cc: Gabriele Paoloni, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard, xuwei (O)

On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>> >> >
>>>> >> > It causes acpi_default_enumeration() to be called but it should be fine
>>>> >> > as we are dealing with platform device anyway.
>>> >>
>>> >> I do not quite understand how declaring such MFD cell above would make sure
>>> >> that the LPC probe is called before the IPMI device is enumerated...
>> >
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
> Or extend the special I2C/SPI handling to them.
>

For this, is it possible to just configure the ACPI table so we spoof 
that the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a 
resource of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus 
type i2c/spi to solve this?

This resource would/should need to be ignored for other purposes.

John

> Thanks,
> Rafael



^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-29 16:16                             ` John Garry
  0 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-29 16:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>> >> >
>>>> >> > It causes acpi_default_enumeration() to be called but it should be fine
>>>> >> > as we are dealing with platform device anyway.
>>> >>
>>> >> I do not quite understand how declaring such MFD cell above would make sure
>>> >> that the LPC probe is called before the IPMI device is enumerated...
>> >
>> > In fact it may be that it is not sufficient in this case because the
>> > ACPI core might enumerate child devices before the LPC driver even gets
>> > a chance to probe so you would need to add also scan handler to the
>> > child devices and mark them already enumerated or something like that.
> Or extend the special I2C/SPI handling to them.
>

For this, is it possible to just configure the ACPI table so we spoof 
that the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a 
resource of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus 
type i2c/spi to solve this?

This resource would/should need to be ignored for other purposes.

John

> Thanks,
> Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-29 16:16                             ` John Garry
  (?)
  (?)
@ 2017-06-30  9:05                               ` Mika Westerberg
  -1 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-30  9:05 UTC (permalink / raw)
  To: John Garry
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
> > > > > >> >
> > > > > >> > It causes acpi_default_enumeration() to be called but it should be fine
> > > > > >> > as we are dealing with platform device anyway.
> > > > >>
> > > > >> I do not quite understand how declaring such MFD cell above would make sure
> > > > >> that the LPC probe is called before the IPMI device is enumerated...
> > > >
> > > > In fact it may be that it is not sufficient in this case because the
> > > > ACPI core might enumerate child devices before the LPC driver even gets
> > > > a chance to probe so you would need to add also scan handler to the
> > > > child devices and mark them already enumerated or something like that.
> > Or extend the special I2C/SPI handling to them.
> > 
> 
> For this, is it possible to just configure the ACPI table so we spoof that
> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
> solve this?

But is the device connected to a I2C or SPI bus? If not, then it does
not make much sense to declare it as I2C or SPI slave. Instead it should
be platform device which is the type we use when there is no explicit
bus specified in ACPI.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30  9:05                               ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-30  9:05 UTC (permalink / raw)
  To: John Garry
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, xuwei (O)

On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
> > > > > >> >
> > > > > >> > It causes acpi_default_enumeration() to be called but it should be fine
> > > > > >> > as we are dealing with platform device anyway.
> > > > >>
> > > > >> I do not quite understand how declaring such MFD cell above would make sure
> > > > >> that the LPC probe is called before the IPMI device is enumerated...
> > > >
> > > > In fact it may be that it is not sufficient in this case because the
> > > > ACPI core might enumerate child devices before the LPC driver even gets
> > > > a chance to probe so you would need to add also scan handler to the
> > > > child devices and mark them already enumerated or something like that.
> > Or extend the special I2C/SPI handling to them.
> > 
> 
> For this, is it possible to just configure the ACPI table so we spoof that
> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
> solve this?

But is the device connected to a I2C or SPI bus? If not, then it does
not make much sense to declare it as I2C or SPI slave. Instead it should
be platform device which is the type we use when there is no explicit
bus specified in ACPI.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30  9:05                               ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-30  9:05 UTC (permalink / raw)
  To: John Garry
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, xuwei (O)

On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
> > > > > >> >
> > > > > >> > It causes acpi_default_enumeration() to be called but it should be fine
> > > > > >> > as we are dealing with platform device anyway.
> > > > >>
> > > > >> I do not quite understand how declaring such MFD cell above would make sure
> > > > >> that the LPC probe is called before the IPMI device is enumerated...
> > > >
> > > > In fact it may be that it is not sufficient in this case because the
> > > > ACPI core might enumerate child devices before the LPC driver even gets
> > > > a chance to probe so you would need to add also scan handler to the
> > > > child devices and mark them already enumerated or something like that.
> > Or extend the special I2C/SPI handling to them.
> > 
> 
> For this, is it possible to just configure the ACPI table so we spoof that
> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
> solve this?

But is the device connected to a I2C or SPI bus? If not, then it does
not make much sense to declare it as I2C or SPI slave. Instead it should
be platform device which is the type we use when there is no explicit
bus specified in ACPI.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30  9:05                               ` Mika Westerberg
  0 siblings, 0 replies; 171+ messages in thread
From: Mika Westerberg @ 2017-06-30  9:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
> > > > > >> >
> > > > > >> > It causes acpi_default_enumeration() to be called but it should be fine
> > > > > >> > as we are dealing with platform device anyway.
> > > > >>
> > > > >> I do not quite understand how declaring such MFD cell above would make sure
> > > > >> that the LPC probe is called before the IPMI device is enumerated...
> > > >
> > > > In fact it may be that it is not sufficient in this case because the
> > > > ACPI core might enumerate child devices before the LPC driver even gets
> > > > a chance to probe so you would need to add also scan handler to the
> > > > child devices and mark them already enumerated or something like that.
> > Or extend the special I2C/SPI handling to them.
> > 
> 
> For this, is it possible to just configure the ACPI table so we spoof that
> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
> solve this?

But is the device connected to a I2C or SPI bus? If not, then it does
not make much sense to declare it as I2C or SPI slave. Instead it should
be platform device which is the type we use when there is no explicit
bus specified in ACPI.

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-30  9:05                               ` Mika Westerberg
  (?)
  (?)
@ 2017-06-30  9:28                                 ` John Garry
  -1 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-30  9:28 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

On 30/06/2017 10:05, Mika Westerberg wrote:
> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>
>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be fine
>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>
>>>>>>> I do not quite understand how declaring such MFD cell above would make sure
>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>
>>>>> In fact it may be that it is not sufficient in this case because the
>>>>> ACPI core might enumerate child devices before the LPC driver even gets
>>>>> a chance to probe so you would need to add also scan handler to the
>>>>> child devices and mark them already enumerated or something like that.
>>> Or extend the special I2C/SPI handling to them.
>>>
>>
>> For this, is it possible to just configure the ACPI table so we spoof that
>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
>> solve this?
>
> But is the device connected to a I2C or SPI bus? If not, then it does
> not make much sense to declare it as I2C or SPI slave. Instead it should
> be platform device which is the type we use when there is no explicit
> bus specified in ACPI.
>

No, it's not a SPI nor an I2C bus. I actually would say that my idea is 
generally wrong, as the ACPI definition is not a real reflection of the 
bus/slave.

However, Rafael did suggest extending special I2C/SPI handling to them. 
In this case, I don't see how the LPC slave can be identified like an 
I2C or SPI slave is.

Thanks,
John

> .
>

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30  9:28                                 ` John Garry
  0 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-30  9:28 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Gabriele Paoloni, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, xuwei (O)

On 30/06/2017 10:05, Mika Westerberg wrote:
> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>
>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be fine
>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>
>>>>>>> I do not quite understand how declaring such MFD cell above would make sure
>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>
>>>>> In fact it may be that it is not sufficient in this case because the
>>>>> ACPI core might enumerate child devices before the LPC driver even gets
>>>>> a chance to probe so you would need to add also scan handler to the
>>>>> child devices and mark them already enumerated or something like that.
>>> Or extend the special I2C/SPI handling to them.
>>>
>>
>> For this, is it possible to just configure the ACPI table so we spoof that
>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
>> solve this?
>
> But is the device connected to a I2C or SPI bus? If not, then it does
> not make much sense to declare it as I2C or SPI slave. Instead it should
> be platform device which is the type we use when there is no explicit
> bus specified in ACPI.
>

No, it's not a SPI nor an I2C bus. I actually would say that my idea is 
generally wrong, as the ACPI definition is not a real reflection of the 
bus/slave.

However, Rafael did suggest extending special I2C/SPI handling to them. 
In this case, I don't see how the LPC slave can be identified like an 
I2C or SPI slave is.

Thanks,
John

> .
>

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30  9:28                                 ` John Garry
  0 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-30  9:28 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: mark.rutland, Rafael J. Wysocki, minyard, Lorenzo Pieralisi,
	arnd, Gabriele Paoloni, Rafael J. Wysocki, linux-pci,
	catalin.marinas, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, benh, bhelgaas, linux-acpi,
	frowand.list, brian.starkey, linux-arm-kernel

On 30/06/2017 10:05, Mika Westerberg wrote:
> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>
>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be fine
>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>
>>>>>>> I do not quite understand how declaring such MFD cell above would make sure
>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>
>>>>> In fact it may be that it is not sufficient in this case because the
>>>>> ACPI core might enumerate child devices before the LPC driver even gets
>>>>> a chance to probe so you would need to add also scan handler to the
>>>>> child devices and mark them already enumerated or something like that.
>>> Or extend the special I2C/SPI handling to them.
>>>
>>
>> For this, is it possible to just configure the ACPI table so we spoof that
>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
>> solve this?
>
> But is the device connected to a I2C or SPI bus? If not, then it does
> not make much sense to declare it as I2C or SPI slave. Instead it should
> be platform device which is the type we use when there is no explicit
> bus specified in ACPI.
>

No, it's not a SPI nor an I2C bus. I actually would say that my idea is 
generally wrong, as the ACPI definition is not a real reflection of the 
bus/slave.

However, Rafael did suggest extending special I2C/SPI handling to them. 
In this case, I don't see how the LPC slave can be identified like an 
I2C or SPI slave is.

Thanks,
John

> .
>



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30  9:28                                 ` John Garry
  0 siblings, 0 replies; 171+ messages in thread
From: John Garry @ 2017-06-30  9:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/06/2017 10:05, Mika Westerberg wrote:
> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>
>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be fine
>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>
>>>>>>> I do not quite understand how declaring such MFD cell above would make sure
>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>
>>>>> In fact it may be that it is not sufficient in this case because the
>>>>> ACPI core might enumerate child devices before the LPC driver even gets
>>>>> a chance to probe so you would need to add also scan handler to the
>>>>> child devices and mark them already enumerated or something like that.
>>> Or extend the special I2C/SPI handling to them.
>>>
>>
>> For this, is it possible to just configure the ACPI table so we spoof that
>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a resource
>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi to
>> solve this?
>
> But is the device connected to a I2C or SPI bus? If not, then it does
> not make much sense to declare it as I2C or SPI slave. Instead it should
> be platform device which is the type we use when there is no explicit
> bus specified in ACPI.
>

No, it's not a SPI nor an I2C bus. I actually would say that my idea is 
generally wrong, as the ACPI definition is not a real reflection of the 
bus/slave.

However, Rafael did suggest extending special I2C/SPI handling to them. 
In this case, I don't see how the LPC slave can be identified like an 
I2C or SPI slave is.

Thanks,
John

> .
>

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-30  9:28                                 ` John Garry
  (?)
  (?)
@ 2017-06-30 12:56                                   ` Rafael J. Wysocki
  -1 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-30 12:56 UTC (permalink / raw)
  To: John Garry
  Cc: mark.rutland, benh, Gabriele Paoloni, Rafael J. Wysocki,
	linux-pci, will.deacon, Linuxarm, frowand.list,
	Lorenzo Pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, robh+dt, bhelgaas,
	Mika Westerberg, linux-arm-kernel

On Fri, Jun 30, 2017 at 11:28 AM, John Garry <john.garry@huawei.com> wrote:
> On 30/06/2017 10:05, Mika Westerberg wrote:
>>
>> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>>>
>>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be
>>>>>>>>>> fine
>>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>>
>>>>>>>>
>>>>>>>> I do not quite understand how declaring such MFD cell above would
>>>>>>>> make sure
>>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>>
>>>>>>
>>>>>> In fact it may be that it is not sufficient in this case because the
>>>>>> ACPI core might enumerate child devices before the LPC driver even
>>>>>> gets
>>>>>> a chance to probe so you would need to add also scan handler to the
>>>>>> child devices and mark them already enumerated or something like that.
>>>>
>>>> Or extend the special I2C/SPI handling to them.
>>>>
>>>
>>> For this, is it possible to just configure the ACPI table so we spoof
>>> that
>>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a
>>> resource
>>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi
>>> to
>>> solve this?
>>
>>
>> But is the device connected to a I2C or SPI bus? If not, then it does
>> not make much sense to declare it as I2C or SPI slave. Instead it should
>> be platform device which is the type we use when there is no explicit
>> bus specified in ACPI.
>>
>
> No, it's not a SPI nor an I2C bus. I actually would say that my idea is
> generally wrong, as the ACPI definition is not a real reflection of the
> bus/slave.
>
> However, Rafael did suggest extending special I2C/SPI handling to them. In
> this case, I don't see how the LPC slave can be identified like an I2C or
> SPI slave is.

I meant that it can be handled similarly (ie. as an exception from the
default enumeration), such that the enumeration is delayed until the
proper subsystem can enumerate those devices as appropriate.  Sorry
for the confusion.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30 12:56                                   ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-30 12:56 UTC (permalink / raw)
  To: John Garry
  Cc: Mika Westerberg, Rafael J. Wysocki, Gabriele Paoloni,
	Lorenzo Pieralisi, Rafael J. Wysocki, catalin.marinas,
	will.deacon, robh+dt, frowand.list, bhelgaas, arnd,
	linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard, xuwei (O)

On Fri, Jun 30, 2017 at 11:28 AM, John Garry <john.garry@huawei.com> wrote:
> On 30/06/2017 10:05, Mika Westerberg wrote:
>>
>> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>>>
>>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be
>>>>>>>>>> fine
>>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>>
>>>>>>>>
>>>>>>>> I do not quite understand how declaring such MFD cell above would
>>>>>>>> make sure
>>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>>
>>>>>>
>>>>>> In fact it may be that it is not sufficient in this case because the
>>>>>> ACPI core might enumerate child devices before the LPC driver even
>>>>>> gets
>>>>>> a chance to probe so you would need to add also scan handler to the
>>>>>> child devices and mark them already enumerated or something like that.
>>>>
>>>> Or extend the special I2C/SPI handling to them.
>>>>
>>>
>>> For this, is it possible to just configure the ACPI table so we spoof
>>> that
>>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a
>>> resource
>>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi
>>> to
>>> solve this?
>>
>>
>> But is the device connected to a I2C or SPI bus? If not, then it does
>> not make much sense to declare it as I2C or SPI slave. Instead it should
>> be platform device which is the type we use when there is no explicit
>> bus specified in ACPI.
>>
>
> No, it's not a SPI nor an I2C bus. I actually would say that my idea is
> generally wrong, as the ACPI definition is not a real reflection of the
> bus/slave.
>
> However, Rafael did suggest extending special I2C/SPI handling to them. In
> this case, I don't see how the LPC slave can be identified like an I2C or
> SPI slave is.

I meant that it can be handled similarly (ie. as an exception from the
default enumeration), such that the enumeration is delayed until the
proper subsystem can enumerate those devices as appropriate.  Sorry
for the confusion.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30 12:56                                   ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-30 12:56 UTC (permalink / raw)
  To: John Garry
  Cc: mark.rutland, benh, Gabriele Paoloni, Rafael J. Wysocki,
	linux-pci, will.deacon, Linuxarm, frowand.list,
	Lorenzo Pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, robh+dt, bhelgaas,
	Mika Westerberg, linux-arm-kernel, Rafael J. Wysocki,
	linux-kernel, olof, brian.starkey

On Fri, Jun 30, 2017 at 11:28 AM, John Garry <john.garry@huawei.com> wrote:
> On 30/06/2017 10:05, Mika Westerberg wrote:
>>
>> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>>>
>>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be
>>>>>>>>>> fine
>>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>>
>>>>>>>>
>>>>>>>> I do not quite understand how declaring such MFD cell above would
>>>>>>>> make sure
>>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>>
>>>>>>
>>>>>> In fact it may be that it is not sufficient in this case because the
>>>>>> ACPI core might enumerate child devices before the LPC driver even
>>>>>> gets
>>>>>> a chance to probe so you would need to add also scan handler to the
>>>>>> child devices and mark them already enumerated or something like that.
>>>>
>>>> Or extend the special I2C/SPI handling to them.
>>>>
>>>
>>> For this, is it possible to just configure the ACPI table so we spoof
>>> that
>>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a
>>> resource
>>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi
>>> to
>>> solve this?
>>
>>
>> But is the device connected to a I2C or SPI bus? If not, then it does
>> not make much sense to declare it as I2C or SPI slave. Instead it should
>> be platform device which is the type we use when there is no explicit
>> bus specified in ACPI.
>>
>
> No, it's not a SPI nor an I2C bus. I actually would say that my idea is
> generally wrong, as the ACPI definition is not a real reflection of the
> bus/slave.
>
> However, Rafael did suggest extending special I2C/SPI handling to them. In
> this case, I don't see how the LPC slave can be identified like an I2C or
> SPI slave is.

I meant that it can be handled similarly (ie. as an exception from the
default enumeration), such that the enumeration is delayed until the
proper subsystem can enumerate those devices as appropriate.  Sorry
for the confusion.

Thanks,
Rafael

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-06-30 12:56                                   ` Rafael J. Wysocki
  0 siblings, 0 replies; 171+ messages in thread
From: Rafael J. Wysocki @ 2017-06-30 12:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 30, 2017 at 11:28 AM, John Garry <john.garry@huawei.com> wrote:
> On 30/06/2017 10:05, Mika Westerberg wrote:
>>
>> On Thu, Jun 29, 2017 at 05:16:15PM +0100, John Garry wrote:
>>>
>>> On 16/06/2017 12:24, Rafael J. Wysocki wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> It causes acpi_default_enumeration() to be called but it should be
>>>>>>>>>> fine
>>>>>>>>>> as we are dealing with platform device anyway.
>>>>>>>>
>>>>>>>>
>>>>>>>> I do not quite understand how declaring such MFD cell above would
>>>>>>>> make sure
>>>>>>>> that the LPC probe is called before the IPMI device is enumerated...
>>>>>>
>>>>>>
>>>>>> In fact it may be that it is not sufficient in this case because the
>>>>>> ACPI core might enumerate child devices before the LPC driver even
>>>>>> gets
>>>>>> a chance to probe so you would need to add also scan handler to the
>>>>>> child devices and mark them already enumerated or something like that.
>>>>
>>>> Or extend the special I2C/SPI handling to them.
>>>>
>>>
>>> For this, is it possible to just configure the ACPI table so we spoof
>>> that
>>> the LPC slave (IPI0001), is an i2c/spi slave? Could we just add a
>>> resource
>>> of type ACPI_RESOURCE_TYPE_SERIAL_BUS, and common serial bus type i2c/spi
>>> to
>>> solve this?
>>
>>
>> But is the device connected to a I2C or SPI bus? If not, then it does
>> not make much sense to declare it as I2C or SPI slave. Instead it should
>> be platform device which is the type we use when there is no explicit
>> bus specified in ACPI.
>>
>
> No, it's not a SPI nor an I2C bus. I actually would say that my idea is
> generally wrong, as the ACPI definition is not a real reflection of the
> bus/slave.
>
> However, Rafael did suggest extending special I2C/SPI handling to them. In
> this case, I don't see how the LPC slave can be identified like an I2C or
> SPI slave is.

I meant that it can be handled similarly (ie. as an exception from the
default enumeration), such that the enumeration is delayed until the
proper subsystem can enumerate those devices as appropriate.  Sorry
for the confusion.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-06-19 10:04                                     ` Gabriele Paoloni
  (?)
  (?)
@ 2017-07-03 16:08                                       ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:08 UTC (permalink / raw)
  To: Gabriele Paoloni, Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

Hi Mika

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Gabriele Paoloni
> Sent: 19 June 2017 11:05
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > Sent: 19 June 2017 11:02
> > To: Gabriele Paoloni
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > Many thanks for your response and your help here.
> > >
> > > I guess that as conclusion with respect to the current v9 patchset
> we
> > can
> > > disregard the idea of MFD and modify the current v9 so that it
> > doesn't
> > > touch directly ACPI resources.
> > > Instead as I proposed before we can have the scan handler to
> > enumerate
> > > the children devices and translate its addresses filling dev-
> > >resources[] and
> > > at the same time we can modify acpi_default_enumeration to check
> > > acpi_device_enumerated() before continuing with device
> > enumeration...?
> > >
> > > Do you think it as a viable solution?
> >
> > No, I think MFD + scan handler inside the MFD driver is the way to
> go.
> > We don't want to trash ACPI core with stuff that does not belong
> there
> > IMHO.
> 
> Ok Many thanks I will investigate this direction

I had a look into the MFD framework. If my understanding is correct the mfd
framework create a platform device for each declared mfd_cell that is passed
to mfd_add_devices().
However there is something that I do not quite understand:
from
http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
it seems that mfd_add_device() will create the platform device using the
resources that are statically declared in the respective mfd_cell.

In my case I'd like to have a platform device using the resources that are
parsed from the ACPI table (i.e. as it is done now by 
acpi_create_platform_device()).

If my understanding is correct, if I declared an mfd_cell for my IPMI child
the mfd subsystem would create a platform device for such child and
therefore acpi_create_platform_device() would fail to create a new platform
device as adev->physical_node_count will be non zero.
However as things stand now mfd_cell devices can only use the resources
that are statically defined in the code (and therefore not the ones in the
ACPI nodes)...am I right?

Thanks
Gab

> 
> >
> > Also you don't need to modify acpi_default_enumeration() because you
> > can
> > mark your device enumerated in the MFD driver. So all the dirty
> details
> > will be in the MFD driver and not in ACPI core.
> 
> Ok got it :)
> 
> Cheers
> Gab


^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 16:08                                       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:08 UTC (permalink / raw)
  To: Gabriele Paoloni, Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O)

Hi Mika

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Gabriele Paoloni
> Sent: 19 June 2017 11:05
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > Sent: 19 June 2017 11:02
> > To: Gabriele Paoloni
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > Many thanks for your response and your help here.
> > >
> > > I guess that as conclusion with respect to the current v9 patchset
> we
> > can
> > > disregard the idea of MFD and modify the current v9 so that it
> > doesn't
> > > touch directly ACPI resources.
> > > Instead as I proposed before we can have the scan handler to
> > enumerate
> > > the children devices and translate its addresses filling dev-
> > >resources[] and
> > > at the same time we can modify acpi_default_enumeration to check
> > > acpi_device_enumerated() before continuing with device
> > enumeration...?
> > >
> > > Do you think it as a viable solution?
> >
> > No, I think MFD + scan handler inside the MFD driver is the way to
> go.
> > We don't want to trash ACPI core with stuff that does not belong
> there
> > IMHO.
> 
> Ok Many thanks I will investigate this direction

I had a look into the MFD framework. If my understanding is correct the mfd
framework create a platform device for each declared mfd_cell that is passed
to mfd_add_devices().
However there is something that I do not quite understand:
from
http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
it seems that mfd_add_device() will create the platform device using the
resources that are statically declared in the respective mfd_cell.

In my case I'd like to have a platform device using the resources that are
parsed from the ACPI table (i.e. as it is done now by 
acpi_create_platform_device()).

If my understanding is correct, if I declared an mfd_cell for my IPMI child
the mfd subsystem would create a platform device for such child and
therefore acpi_create_platform_device() would fail to create a new platform
device as adev->physical_node_count will be non zero.
However as things stand now mfd_cell devices can only use the resources
that are statically defined in the code (and therefore not the ones in the
ACPI nodes)...am I right?

Thanks
Gab

> 
> >
> > Also you don't need to modify acpi_default_enumeration() because you
> > can
> > mark your device enumerated in the MFD driver. So all the dirty
> details
> > will be in the MFD driver and not in ACPI core.
> 
> Ok got it :)
> 
> Cheers
> Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 16:08                                       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:08 UTC (permalink / raw)
  To: Gabriele Paoloni, Mika Westerberg
  Cc: mark.rutland, minyard, Lorenzo Pieralisi, linux-acpi, arnd,
	Rafael J. Wysocki, linux-pci, catalin.marinas, John Garry,
	Rafael J. Wysocki, linux-kernel, will.deacon, Linuxarm, olof,
	robh+dt, xuwei (O),
	benh, bhelgaas, frowand.list, brian.starkey, linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Gabriele Paoloni
> Sent: 19 June 2017 11:05
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > Sent: 19 June 2017 11:02
> > To: Gabriele Paoloni
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > Many thanks for your response and your help here.
> > >
> > > I guess that as conclusion with respect to the current v9 patchset
> we
> > can
> > > disregard the idea of MFD and modify the current v9 so that it
> > doesn't
> > > touch directly ACPI resources.
> > > Instead as I proposed before we can have the scan handler to
> > enumerate
> > > the children devices and translate its addresses filling dev-
> > >resources[] and
> > > at the same time we can modify acpi_default_enumeration to check
> > > acpi_device_enumerated() before continuing with device
> > enumeration...?
> > >
> > > Do you think it as a viable solution?
> >
> > No, I think MFD + scan handler inside the MFD driver is the way to
> go.
> > We don't want to trash ACPI core with stuff that does not belong
> there
> > IMHO.
> 
> Ok Many thanks I will investigate this direction

I had a look into the MFD framework. If my understanding is correct the mfd
framework create a platform device for each declared mfd_cell that is passed
to mfd_add_devices().
However there is something that I do not quite understand:
from
http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
it seems that mfd_add_device() will create the platform device using the
resources that are statically declared in the respective mfd_cell.

In my case I'd like to have a platform device using the resources that are
parsed from the ACPI table (i.e. as it is done now by 
acpi_create_platform_device()).

If my understanding is correct, if I declared an mfd_cell for my IPMI child
the mfd subsystem would create a platform device for such child and
therefore acpi_create_platform_device() would fail to create a new platform
device as adev->physical_node_count will be non zero.
However as things stand now mfd_cell devices can only use the resources
that are statically defined in the code (and therefore not the ones in the
ACPI nodes)...am I right?

Thanks
Gab

> 
> >
> > Also you don't need to modify acpi_default_enumeration() because you
> > can
> > mark your device enumerated in the MFD driver. So all the dirty
> details
> > will be in the MFD driver and not in ACPI core.
> 
> Ok got it :)
> 
> Cheers
> Gab


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 16:08                                       ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mika

> -----Original Message-----
> From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
> owner at vger.kernel.org] On Behalf Of Gabriele Paoloni
> Sent: 19 June 2017 11:05
> To: Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: Mika Westerberg [mailto:mika.westerberg at linux.intel.com]
> > Sent: 19 June 2017 11:02
> > To: Gabriele Paoloni
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> > frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-
> arm-
> > kernel at lists.infradead.org; mark.rutland at arm.com;
> > brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org;
> linux-
> > kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> > pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > Many thanks for your response and your help here.
> > >
> > > I guess that as conclusion with respect to the current v9 patchset
> we
> > can
> > > disregard the idea of MFD and modify the current v9 so that it
> > doesn't
> > > touch directly ACPI resources.
> > > Instead as I proposed before we can have the scan handler to
> > enumerate
> > > the children devices and translate its addresses filling dev-
> > >resources[] and
> > > at the same time we can modify acpi_default_enumeration to check
> > > acpi_device_enumerated() before continuing with device
> > enumeration...?
> > >
> > > Do you think it as a viable solution?
> >
> > No, I think MFD + scan handler inside the MFD driver is the way to
> go.
> > We don't want to trash ACPI core with stuff that does not belong
> there
> > IMHO.
> 
> Ok Many thanks I will investigate this direction

I had a look into the MFD framework. If my understanding is correct the mfd
framework create a platform device for each declared mfd_cell that is passed
to mfd_add_devices().
However there is something that I do not quite understand:
from
http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
it seems that mfd_add_device() will create the platform device using the
resources that are statically declared in the respective mfd_cell.

In my case I'd like to have a platform device using the resources that are
parsed from the ACPI table (i.e. as it is done now by 
acpi_create_platform_device()).

If my understanding is correct, if I declared an mfd_cell for my IPMI child
the mfd subsystem would create a platform device for such child and
therefore acpi_create_platform_device() would fail to create a new platform
device as adev->physical_node_count will be non zero.
However as things stand now mfd_cell devices can only use the resources
that are statically defined in the code (and therefore not the ones in the
ACPI nodes)...am I right?

Thanks
Gab

> 
> >
> > Also you don't need to modify acpi_default_enumeration() because you
> > can
> > mark your device enumerated in the MFD driver. So all the dirty
> details
> > will be in the MFD driver and not in ACPI core.
> 
> Ok got it :)
> 
> Cheers
> Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-07-03 16:08                                       ` Gabriele Paoloni
  (?)
  (?)
@ 2017-07-03 16:23                                         ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:23 UTC (permalink / raw)
  To: Gabriele Paoloni, Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi@vger.kernel.org

+CC Lee Jones

> -----Original Message-----
> From: Gabriele Paoloni
> Sent: 03 July 2017 17:08
> To: Gabriele Paoloni; Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> > owner@vger.kernel.org] On Behalf Of Gabriele Paoloni
> > Sent: 19 June 2017 11:05
> > To: Mika Westerberg
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > Hi Mika
> >
> > > -----Original Message-----
> > > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > > Sent: 19 June 2017 11:02
> > > To: Gabriele Paoloni
> > > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> > arm-
> > > kernel@lists.infradead.org; mark.rutland@arm.com;
> > > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> > linux-
> > > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm;
> linux-
> > > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-
> MMIO
> > > devices before scanning
> > >
> > > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > > Many thanks for your response and your help here.
> > > >
> > > > I guess that as conclusion with respect to the current v9
> patchset
> > we
> > > can
> > > > disregard the idea of MFD and modify the current v9 so that it
> > > doesn't
> > > > touch directly ACPI resources.
> > > > Instead as I proposed before we can have the scan handler to
> > > enumerate
> > > > the children devices and translate its addresses filling dev-
> > > >resources[] and
> > > > at the same time we can modify acpi_default_enumeration to check
> > > > acpi_device_enumerated() before continuing with device
> > > enumeration...?
> > > >
> > > > Do you think it as a viable solution?
> > >
> > > No, I think MFD + scan handler inside the MFD driver is the way to
> > go.
> > > We don't want to trash ACPI core with stuff that does not belong
> > there
> > > IMHO.
> >
> > Ok Many thanks I will investigate this direction
> 
> I had a look into the MFD framework. If my understanding is correct the
> mfd
> framework create a platform device for each declared mfd_cell that is
> passed
> to mfd_add_devices().
> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> it seems that mfd_add_device() will create the platform device using
> the
> resources that are statically declared in the respective mfd_cell.
> 
> In my case I'd like to have a platform device using the resources that
> are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).
> 
> If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new
> platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in
> the
> ACPI nodes)...am I right?
> 
> Thanks
> Gab
> 
> >
> > >
> > > Also you don't need to modify acpi_default_enumeration() because
> you
> > > can
> > > mark your device enumerated in the MFD driver. So all the dirty
> > details
> > > will be in the MFD driver and not in ACPI core.
> >
> > Ok got it :)
> >
> > Cheers
> > Gab


^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 16:23                                         ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:23 UTC (permalink / raw)
  To: Gabriele Paoloni, Mika Westerberg
  Cc: Rafael J. Wysocki, Lorenzo Pieralisi, Rafael J. Wysocki,
	catalin.marinas, will.deacon, robh+dt, frowand.list, bhelgaas,
	arnd, linux-arm-kernel, mark.rutland, brian.starkey, olof, benh,
	linux-kernel, linux-acpi, Linuxarm, linux-pci, minyard,
	John Garry, xuwei (O),
	lee.jones

+CC Lee Jones

> -----Original Message-----
> From: Gabriele Paoloni
> Sent: 03 July 2017 17:08
> To: Gabriele Paoloni; Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> > owner@vger.kernel.org] On Behalf Of Gabriele Paoloni
> > Sent: 19 June 2017 11:05
> > To: Mika Westerberg
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > Hi Mika
> >
> > > -----Original Message-----
> > > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > > Sent: 19 June 2017 11:02
> > > To: Gabriele Paoloni
> > > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> > arm-
> > > kernel@lists.infradead.org; mark.rutland@arm.com;
> > > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> > linux-
> > > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm;
> linux-
> > > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-
> MMIO
> > > devices before scanning
> > >
> > > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > > Many thanks for your response and your help here.
> > > >
> > > > I guess that as conclusion with respect to the current v9
> patchset
> > we
> > > can
> > > > disregard the idea of MFD and modify the current v9 so that it
> > > doesn't
> > > > touch directly ACPI resources.
> > > > Instead as I proposed before we can have the scan handler to
> > > enumerate
> > > > the children devices and translate its addresses filling dev-
> > > >resources[] and
> > > > at the same time we can modify acpi_default_enumeration to check
> > > > acpi_device_enumerated() before continuing with device
> > > enumeration...?
> > > >
> > > > Do you think it as a viable solution?
> > >
> > > No, I think MFD + scan handler inside the MFD driver is the way to
> > go.
> > > We don't want to trash ACPI core with stuff that does not belong
> > there
> > > IMHO.
> >
> > Ok Many thanks I will investigate this direction
> 
> I had a look into the MFD framework. If my understanding is correct the
> mfd
> framework create a platform device for each declared mfd_cell that is
> passed
> to mfd_add_devices().
> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> it seems that mfd_add_device() will create the platform device using
> the
> resources that are statically declared in the respective mfd_cell.
> 
> In my case I'd like to have a platform device using the resources that
> are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).
> 
> If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new
> platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in
> the
> ACPI nodes)...am I right?
> 
> Thanks
> Gab
> 
> >
> > >
> > > Also you don't need to modify acpi_default_enumeration() because
> you
> > > can
> > > mark your device enumerated in the MFD driver. So all the dirty
> > details
> > > will be in the MFD driver and not in ACPI core.
> >
> > Ok got it :)
> >
> > Cheers
> > Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 16:23                                         ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:23 UTC (permalink / raw)
  To: Gabriele Paoloni, Mika Westerberg
  Cc: mark.rutland, benh, Rafael J. Wysocki, linux-pci, will.deacon,
	Linuxarm, lee.jones, Lorenzo Pieralisi, arnd, frowand.list,
	xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, linux-arm-kernel, Rafael J. Wysocki, linux-kernel,
	olof, brian.starkey

+CC Lee Jones

> -----Original Message-----
> From: Gabriele Paoloni
> Sent: 03 July 2017 17:08
> To: Gabriele Paoloni; Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-arm-
> kernel@lists.infradead.org; mark.rutland@arm.com;
> brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org; linux-
> kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> > owner@vger.kernel.org] On Behalf Of Gabriele Paoloni
> > Sent: 19 June 2017 11:05
> > To: Mika Westerberg
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> arm-
> > kernel@lists.infradead.org; mark.rutland@arm.com;
> > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> linux-
> > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm; linux-
> > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > Hi Mika
> >
> > > -----Original Message-----
> > > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > > Sent: 19 June 2017 11:02
> > > To: Gabriele Paoloni
> > > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > > catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> > > frowand.list@gmail.com; bhelgaas@google.com; arnd@arndb.de; linux-
> > arm-
> > > kernel@lists.infradead.org; mark.rutland@arm.com;
> > > brian.starkey@arm.com; olof@lixom.net; benh@kernel.crashing.org;
> > linux-
> > > kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Linuxarm;
> linux-
> > > pci@vger.kernel.org; minyard@acm.org; John Garry; xuwei (O)
> > > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-
> MMIO
> > > devices before scanning
> > >
> > > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > > Many thanks for your response and your help here.
> > > >
> > > > I guess that as conclusion with respect to the current v9
> patchset
> > we
> > > can
> > > > disregard the idea of MFD and modify the current v9 so that it
> > > doesn't
> > > > touch directly ACPI resources.
> > > > Instead as I proposed before we can have the scan handler to
> > > enumerate
> > > > the children devices and translate its addresses filling dev-
> > > >resources[] and
> > > > at the same time we can modify acpi_default_enumeration to check
> > > > acpi_device_enumerated() before continuing with device
> > > enumeration...?
> > > >
> > > > Do you think it as a viable solution?
> > >
> > > No, I think MFD + scan handler inside the MFD driver is the way to
> > go.
> > > We don't want to trash ACPI core with stuff that does not belong
> > there
> > > IMHO.
> >
> > Ok Many thanks I will investigate this direction
> 
> I had a look into the MFD framework. If my understanding is correct the
> mfd
> framework create a platform device for each declared mfd_cell that is
> passed
> to mfd_add_devices().
> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> it seems that mfd_add_device() will create the platform device using
> the
> resources that are statically declared in the respective mfd_cell.
> 
> In my case I'd like to have a platform device using the resources that
> are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).
> 
> If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new
> platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in
> the
> ACPI nodes)...am I right?
> 
> Thanks
> Gab
> 
> >
> > >
> > > Also you don't need to modify acpi_default_enumeration() because
> you
> > > can
> > > mark your device enumerated in the MFD driver. So all the dirty
> > details
> > > will be in the MFD driver and not in ACPI core.
> >
> > Ok got it :)
> >
> > Cheers
> > Gab


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 16:23                                         ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-03 16:23 UTC (permalink / raw)
  To: linux-arm-kernel

+CC Lee Jones

> -----Original Message-----
> From: Gabriele Paoloni
> Sent: 03 July 2017 17:08
> To: Gabriele Paoloni; Mika Westerberg
> Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-arm-
> kernel at lists.infradead.org; mark.rutland at arm.com;
> brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> devices before scanning
> 
> Hi Mika
> 
> > -----Original Message-----
> > From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
> > owner at vger.kernel.org] On Behalf Of Gabriele Paoloni
> > Sent: 19 June 2017 11:05
> > To: Mika Westerberg
> > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> > frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-
> arm-
> > kernel at lists.infradead.org; mark.rutland at arm.com;
> > brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org;
> linux-
> > kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm; linux-
> > pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> > Subject: RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO
> > devices before scanning
> >
> > Hi Mika
> >
> > > -----Original Message-----
> > > From: Mika Westerberg [mailto:mika.westerberg at linux.intel.com]
> > > Sent: 19 June 2017 11:02
> > > To: Gabriele Paoloni
> > > Cc: Rafael J. Wysocki; Lorenzo Pieralisi; Rafael J. Wysocki;
> > > catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> > > frowand.list at gmail.com; bhelgaas at google.com; arnd at arndb.de; linux-
> > arm-
> > > kernel at lists.infradead.org; mark.rutland at arm.com;
> > > brian.starkey at arm.com; olof at lixom.net; benh at kernel.crashing.org;
> > linux-
> > > kernel at vger.kernel.org; linux-acpi at vger.kernel.org; Linuxarm;
> linux-
> > > pci at vger.kernel.org; minyard at acm.org; John Garry; xuwei (O)
> > > Subject: Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-
> MMIO
> > > devices before scanning
> > >
> > > On Mon, Jun 19, 2017 at 09:50:49AM +0000, Gabriele Paoloni wrote:
> > > > Many thanks for your response and your help here.
> > > >
> > > > I guess that as conclusion with respect to the current v9
> patchset
> > we
> > > can
> > > > disregard the idea of MFD and modify the current v9 so that it
> > > doesn't
> > > > touch directly ACPI resources.
> > > > Instead as I proposed before we can have the scan handler to
> > > enumerate
> > > > the children devices and translate its addresses filling dev-
> > > >resources[] and
> > > > at the same time we can modify acpi_default_enumeration to check
> > > > acpi_device_enumerated() before continuing with device
> > > enumeration...?
> > > >
> > > > Do you think it as a viable solution?
> > >
> > > No, I think MFD + scan handler inside the MFD driver is the way to
> > go.
> > > We don't want to trash ACPI core with stuff that does not belong
> > there
> > > IMHO.
> >
> > Ok Many thanks I will investigate this direction
> 
> I had a look into the MFD framework. If my understanding is correct the
> mfd
> framework create a platform device for each declared mfd_cell that is
> passed
> to mfd_add_devices().
> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> it seems that mfd_add_device() will create the platform device using
> the
> resources that are statically declared in the respective mfd_cell.
> 
> In my case I'd like to have a platform device using the resources that
> are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).
> 
> If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new
> platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in
> the
> ACPI nodes)...am I right?
> 
> Thanks
> Gab
> 
> >
> > >
> > > Also you don't need to modify acpi_default_enumeration() because
> you
> > > can
> > > mark your device enumerated in the MFD driver. So all the dirty
> > details
> > > will be in the MFD driver and not in ACPI core.
> >
> > Ok got it :)
> >
> > Cheers
> > Gab

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-07-03 16:08                                       ` Gabriele Paoloni
  (?)
  (?)
@ 2017-07-03 20:22                                         ` Andy Shevchenko
  -1 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-03 20:22 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

On Mon, Jul 3, 2017 at 7:08 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

JFYI: Mika on vacation.

> I had a look into the MFD framework. If my understanding is correct the mfd
> framework create a platform device for each declared mfd_cell that is passed
> to mfd_add_devices().

Right.

> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
> it seems that mfd_add_device() will create the platform device using the
> resources that are statically declared in the respective mfd_cell.

It's one possibility.

> In my case I'd like to have a platform device using the resources that are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).

So far so good. Nothing prevents you to do that.

> If my understanding is correct, if I declared an mfd_cell for my IPMI child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in the
> ACPI nodes)...am I right?

You may file resources first and then register MFD cells. See many
existing examples in the kernel.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 20:22                                         ` Andy Shevchenko
  0 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-03 20:22 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

On Mon, Jul 3, 2017 at 7:08 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

JFYI: Mika on vacation.

> I had a look into the MFD framework. If my understanding is correct the mfd
> framework create a platform device for each declared mfd_cell that is passed
> to mfd_add_devices().

Right.

> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
> it seems that mfd_add_device() will create the platform device using the
> resources that are statically declared in the respective mfd_cell.

It's one possibility.

> In my case I'd like to have a platform device using the resources that are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).

So far so good. Nothing prevents you to do that.

> If my understanding is correct, if I declared an mfd_cell for my IPMI child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in the
> ACPI nodes)...am I right?

You may file resources first and then register MFD cells. See many
existing examples in the kernel.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 20:22                                         ` Andy Shevchenko
  0 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-03 20:22 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, Rafael J. Wysocki, linux-pci, will.deacon,
	Linuxarm, frowand.list, Lorenzo Pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, Mika Westerberg, linux-arm-kernel, Rafael J. Wysocki,
	linux-kernel, olof, brian.starkey

On Mon, Jul 3, 2017 at 7:08 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

JFYI: Mika on vacation.

> I had a look into the MFD framework. If my understanding is correct the mfd
> framework create a platform device for each declared mfd_cell that is passed
> to mfd_add_devices().

Right.

> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
> it seems that mfd_add_device() will create the platform device using the
> resources that are statically declared in the respective mfd_cell.

It's one possibility.

> In my case I'd like to have a platform device using the resources that are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).

So far so good. Nothing prevents you to do that.

> If my understanding is correct, if I declared an mfd_cell for my IPMI child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in the
> ACPI nodes)...am I right?

You may file resources first and then register MFD cells. See many
existing examples in the kernel.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-03 20:22                                         ` Andy Shevchenko
  0 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-03 20:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 3, 2017 at 7:08 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

JFYI: Mika on vacation.

> I had a look into the MFD framework. If my understanding is correct the mfd
> framework create a platform device for each declared mfd_cell that is passed
> to mfd_add_devices().

Right.

> However there is something that I do not quite understand:
> from
> http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-core.c#L207
> it seems that mfd_add_device() will create the platform device using the
> resources that are statically declared in the respective mfd_cell.

It's one possibility.

> In my case I'd like to have a platform device using the resources that are
> parsed from the ACPI table (i.e. as it is done now by
> acpi_create_platform_device()).

So far so good. Nothing prevents you to do that.

> If my understanding is correct, if I declared an mfd_cell for my IPMI child
> the mfd subsystem would create a platform device for such child and
> therefore acpi_create_platform_device() would fail to create a new platform
> device as adev->physical_node_count will be non zero.
> However as things stand now mfd_cell devices can only use the resources
> that are statically defined in the code (and therefore not the ones in the
> ACPI nodes)...am I right?

You may file resources first and then register MFD cells. See many
existing examples in the kernel.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-07-03 20:22                                         ` Andy Shevchenko
  (?)
  (?)
@ 2017-07-04 15:14                                           ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 15:14 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

Hi Andy

[...]

> 
> JFYI: Mika on vacation.

Thanks for letting me know

> 
> > I had a look into the MFD framework. If my understanding is correct
> the mfd
> > framework create a platform device for each declared mfd_cell that is
> passed
> > to mfd_add_devices().
> 
> Right.
> 
> > However there is something that I do not quite understand:
> > from
> > http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> > it seems that mfd_add_device() will create the platform device using
> the
> > resources that are statically declared in the respective mfd_cell.
> 
> It's one possibility.
> 
> > In my case I'd like to have a platform device using the resources
> that are
> > parsed from the ACPI table (i.e. as it is done now by
> > acpi_create_platform_device()).
> 
> So far so good. Nothing prevents you to do that.
> 
> > If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> > the mfd subsystem would create a platform device for such child and
> > therefore acpi_create_platform_device() would fail to create a new
> platform
> > device as adev->physical_node_count will be non zero.
> > However as things stand now mfd_cell devices can only use the
> resources
> > that are statically defined in the code (and therefore not the ones
> in the
> > ACPI nodes)...am I right?
> 
> You may file resources first and then register MFD cells. See many
> existing examples in the kernel.

Well I had a look around the Kernel I have seen no mfd cells using
Resources that are not statically defined:
i.e. cell->resources in mfd_add_device() always points to statically
defined resource structures.

Usually for ACPI devices first you need to parse the ACPI resources
from the table calling acpi_dev_get_resources(), then you iterate 
over the resource list and fill the resource array by calling
acpi_platform_fill_resurces() (as in acpi_create_platform_device())

With respect to my case are you suggesting dynamically allocate a
resource array and fill it using the same fashion as 
acpi_create_platform_device(), then point cell->resources to such
array before calling mfd_add_device() ?

Thanks
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 15:14                                           ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 15:14 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

Hi Andy

[...]

> 
> JFYI: Mika on vacation.

Thanks for letting me know

> 
> > I had a look into the MFD framework. If my understanding is correct
> the mfd
> > framework create a platform device for each declared mfd_cell that is
> passed
> > to mfd_add_devices().
> 
> Right.
> 
> > However there is something that I do not quite understand:
> > from
> > http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> > it seems that mfd_add_device() will create the platform device using
> the
> > resources that are statically declared in the respective mfd_cell.
> 
> It's one possibility.
> 
> > In my case I'd like to have a platform device using the resources
> that are
> > parsed from the ACPI table (i.e. as it is done now by
> > acpi_create_platform_device()).
> 
> So far so good. Nothing prevents you to do that.
> 
> > If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> > the mfd subsystem would create a platform device for such child and
> > therefore acpi_create_platform_device() would fail to create a new
> platform
> > device as adev->physical_node_count will be non zero.
> > However as things stand now mfd_cell devices can only use the
> resources
> > that are statically defined in the code (and therefore not the ones
> in the
> > ACPI nodes)...am I right?
> 
> You may file resources first and then register MFD cells. See many
> existing examples in the kernel.

Well I had a look around the Kernel I have seen no mfd cells using
Resources that are not statically defined:
i.e. cell->resources in mfd_add_device() always points to statically
defined resource structures.

Usually for ACPI devices first you need to parse the ACPI resources
from the table calling acpi_dev_get_resources(), then you iterate 
over the resource list and fill the resource array by calling
acpi_platform_fill_resurces() (as in acpi_create_platform_device())

With respect to my case are you suggesting dynamically allocate a
resource array and fill it using the same fashion as 
acpi_create_platform_device(), then point cell->resources to such
array before calling mfd_add_device() ?

Thanks
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 15:14                                           ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 15:14 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

SGkgQW5keQ0KDQpbLi4uXQ0KDQo+IA0KPiBKRllJOiBNaWthIG9uIHZhY2F0aW9uLg0KDQpUaGFu
a3MgZm9yIGxldHRpbmcgbWUga25vdw0KDQo+IA0KPiA+IEkgaGFkIGEgbG9vayBpbnRvIHRoZSBN
RkQgZnJhbWV3b3JrLiBJZiBteSB1bmRlcnN0YW5kaW5nIGlzIGNvcnJlY3QNCj4gdGhlIG1mZA0K
PiA+IGZyYW1ld29yayBjcmVhdGUgYSBwbGF0Zm9ybSBkZXZpY2UgZm9yIGVhY2ggZGVjbGFyZWQg
bWZkX2NlbGwgdGhhdCBpcw0KPiBwYXNzZWQNCj4gPiB0byBtZmRfYWRkX2RldmljZXMoKS4NCj4g
DQo+IFJpZ2h0Lg0KPiANCj4gPiBIb3dldmVyIHRoZXJlIGlzIHNvbWV0aGluZyB0aGF0IEkgZG8g
bm90IHF1aXRlIHVuZGVyc3RhbmQ6DQo+ID4gZnJvbQ0KPiA+IGh0dHA6Ly9lbGl4aXIuZnJlZS1l
bGVjdHJvbnMuY29tL2xpbnV4L2xhdGVzdC9zb3VyY2UvZHJpdmVycy9tZmQvbWZkLQ0KPiBjb3Jl
LmMjTDIwNw0KPiA+IGl0IHNlZW1zIHRoYXQgbWZkX2FkZF9kZXZpY2UoKSB3aWxsIGNyZWF0ZSB0
aGUgcGxhdGZvcm0gZGV2aWNlIHVzaW5nDQo+IHRoZQ0KPiA+IHJlc291cmNlcyB0aGF0IGFyZSBz
dGF0aWNhbGx5IGRlY2xhcmVkIGluIHRoZSByZXNwZWN0aXZlIG1mZF9jZWxsLg0KPiANCj4gSXQn
cyBvbmUgcG9zc2liaWxpdHkuDQo+IA0KPiA+IEluIG15IGNhc2UgSSdkIGxpa2UgdG8gaGF2ZSBh
IHBsYXRmb3JtIGRldmljZSB1c2luZyB0aGUgcmVzb3VyY2VzDQo+IHRoYXQgYXJlDQo+ID4gcGFy
c2VkIGZyb20gdGhlIEFDUEkgdGFibGUgKGkuZS4gYXMgaXQgaXMgZG9uZSBub3cgYnkNCj4gPiBh
Y3BpX2NyZWF0ZV9wbGF0Zm9ybV9kZXZpY2UoKSkuDQo+IA0KPiBTbyBmYXIgc28gZ29vZC4gTm90
aGluZyBwcmV2ZW50cyB5b3UgdG8gZG8gdGhhdC4NCj4gDQo+ID4gSWYgbXkgdW5kZXJzdGFuZGlu
ZyBpcyBjb3JyZWN0LCBpZiBJIGRlY2xhcmVkIGFuIG1mZF9jZWxsIGZvciBteSBJUE1JDQo+IGNo
aWxkDQo+ID4gdGhlIG1mZCBzdWJzeXN0ZW0gd291bGQgY3JlYXRlIGEgcGxhdGZvcm0gZGV2aWNl
IGZvciBzdWNoIGNoaWxkIGFuZA0KPiA+IHRoZXJlZm9yZSBhY3BpX2NyZWF0ZV9wbGF0Zm9ybV9k
ZXZpY2UoKSB3b3VsZCBmYWlsIHRvIGNyZWF0ZSBhIG5ldw0KPiBwbGF0Zm9ybQ0KPiA+IGRldmlj
ZSBhcyBhZGV2LT5waHlzaWNhbF9ub2RlX2NvdW50IHdpbGwgYmUgbm9uIHplcm8uDQo+ID4gSG93
ZXZlciBhcyB0aGluZ3Mgc3RhbmQgbm93IG1mZF9jZWxsIGRldmljZXMgY2FuIG9ubHkgdXNlIHRo
ZQ0KPiByZXNvdXJjZXMNCj4gPiB0aGF0IGFyZSBzdGF0aWNhbGx5IGRlZmluZWQgaW4gdGhlIGNv
ZGUgKGFuZCB0aGVyZWZvcmUgbm90IHRoZSBvbmVzDQo+IGluIHRoZQ0KPiA+IEFDUEkgbm9kZXMp
Li4uYW0gSSByaWdodD8NCj4gDQo+IFlvdSBtYXkgZmlsZSByZXNvdXJjZXMgZmlyc3QgYW5kIHRo
ZW4gcmVnaXN0ZXIgTUZEIGNlbGxzLiBTZWUgbWFueQ0KPiBleGlzdGluZyBleGFtcGxlcyBpbiB0
aGUga2VybmVsLg0KDQpXZWxsIEkgaGFkIGEgbG9vayBhcm91bmQgdGhlIEtlcm5lbCBJIGhhdmUg
c2VlbiBubyBtZmQgY2VsbHMgdXNpbmcNClJlc291cmNlcyB0aGF0IGFyZSBub3Qgc3RhdGljYWxs
eSBkZWZpbmVkOg0KaS5lLiBjZWxsLT5yZXNvdXJjZXMgaW4gbWZkX2FkZF9kZXZpY2UoKSBhbHdh
eXMgcG9pbnRzIHRvIHN0YXRpY2FsbHkNCmRlZmluZWQgcmVzb3VyY2Ugc3RydWN0dXJlcy4NCg0K
VXN1YWxseSBmb3IgQUNQSSBkZXZpY2VzIGZpcnN0IHlvdSBuZWVkIHRvIHBhcnNlIHRoZSBBQ1BJ
IHJlc291cmNlcw0KZnJvbSB0aGUgdGFibGUgY2FsbGluZyBhY3BpX2Rldl9nZXRfcmVzb3VyY2Vz
KCksIHRoZW4geW91IGl0ZXJhdGUgDQpvdmVyIHRoZSByZXNvdXJjZSBsaXN0IGFuZCBmaWxsIHRo
ZSByZXNvdXJjZSBhcnJheSBieSBjYWxsaW5nDQphY3BpX3BsYXRmb3JtX2ZpbGxfcmVzdXJjZXMo
KSAoYXMgaW4gYWNwaV9jcmVhdGVfcGxhdGZvcm1fZGV2aWNlKCkpDQoNCldpdGggcmVzcGVjdCB0
byBteSBjYXNlIGFyZSB5b3Ugc3VnZ2VzdGluZyBkeW5hbWljYWxseSBhbGxvY2F0ZSBhDQpyZXNv
dXJjZSBhcnJheSBhbmQgZmlsbCBpdCB1c2luZyB0aGUgc2FtZSBmYXNoaW9uIGFzIA0KYWNwaV9j
cmVhdGVfcGxhdGZvcm1fZGV2aWNlKCksIHRoZW4gcG9pbnQgY2VsbC0+cmVzb3VyY2VzIHRvIHN1
Y2gNCmFycmF5IGJlZm9yZSBjYWxsaW5nIG1mZF9hZGRfZGV2aWNlKCkgPw0KDQpUaGFua3MNCkdh
Yg0KDQo+IA0KPiAtLQ0KPiBXaXRoIEJlc3QgUmVnYXJkcywNCj4gQW5keSBTaGV2Y2hlbmtvDQo=

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 15:14                                           ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 15:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Andy

[...]

> 
> JFYI: Mika on vacation.

Thanks for letting me know

> 
> > I had a look into the MFD framework. If my understanding is correct
> the mfd
> > framework create a platform device for each declared mfd_cell that is
> passed
> > to mfd_add_devices().
> 
> Right.
> 
> > However there is something that I do not quite understand:
> > from
> > http://elixir.free-electrons.com/linux/latest/source/drivers/mfd/mfd-
> core.c#L207
> > it seems that mfd_add_device() will create the platform device using
> the
> > resources that are statically declared in the respective mfd_cell.
> 
> It's one possibility.
> 
> > In my case I'd like to have a platform device using the resources
> that are
> > parsed from the ACPI table (i.e. as it is done now by
> > acpi_create_platform_device()).
> 
> So far so good. Nothing prevents you to do that.
> 
> > If my understanding is correct, if I declared an mfd_cell for my IPMI
> child
> > the mfd subsystem would create a platform device for such child and
> > therefore acpi_create_platform_device() would fail to create a new
> platform
> > device as adev->physical_node_count will be non zero.
> > However as things stand now mfd_cell devices can only use the
> resources
> > that are statically defined in the code (and therefore not the ones
> in the
> > ACPI nodes)...am I right?
> 
> You may file resources first and then register MFD cells. See many
> existing examples in the kernel.

Well I had a look around the Kernel I have seen no mfd cells using
Resources that are not statically defined:
i.e. cell->resources in mfd_add_device() always points to statically
defined resource structures.

Usually for ACPI devices first you need to parse the ACPI resources
from the table calling acpi_dev_get_resources(), then you iterate 
over the resource list and fill the resource array by calling
acpi_platform_fill_resurces() (as in acpi_create_platform_device())

With respect to my case are you suggesting dynamically allocate a
resource array and fill it using the same fashion as 
acpi_create_platform_device(), then point cell->resources to such
array before calling mfd_add_device() ?

Thanks
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-07-04 15:14                                           ` Gabriele Paoloni
  (?)
  (?)
@ 2017-07-04 15:46                                             ` Andy Shevchenko
  -1 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-04 15:46 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

On Tue, Jul 4, 2017 at 6:14 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

>> > In my case I'd like to have a platform device using the resources
>> that are
>> > parsed from the ACPI table (i.e. as it is done now by
>> > acpi_create_platform_device()).
>>
>> So far so good. Nothing prevents you to do that.
>>
>> > If my understanding is correct, if I declared an mfd_cell for my IPMI
>> child
>> > the mfd subsystem would create a platform device for such child and
>> > therefore acpi_create_platform_device() would fail to create a new
>> platform
>> > device as adev->physical_node_count will be non zero.
>> > However as things stand now mfd_cell devices can only use the
>> resources
>> > that are statically defined in the code (and therefore not the ones
>> in the
>> > ACPI nodes)...am I right?
>>
>> You may file resources first and then register MFD cells. See many
>> existing examples in the kernel.
>
> Well I had a look around the Kernel I have seen no mfd cells using
> Resources that are not statically defined:
> i.e. cell->resources in mfd_add_device() always points to statically
> defined resource structures.
>
> Usually for ACPI devices first you need to parse the ACPI resources
> from the table calling acpi_dev_get_resources(), then you iterate
> over the resource list and fill the resource array by calling
> acpi_platform_fill_resurces() (as in acpi_create_platform_device())
>
> With respect to my case are you suggesting dynamically allocate a
> resource array and fill it using the same fashion as
> acpi_create_platform_device(), then point cell->resources to such
> array before calling mfd_add_device() ?

You may do it on stack. Define your cell statically (but not const)
and apply resources just before mfd_add_devices() call.
There are examples in the existing drivers. Intel LPC comes to my mind
and perhaps PMC (Broxton), though latter has too much other stuff
around.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 15:46                                             ` Andy Shevchenko
  0 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-04 15:46 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

On Tue, Jul 4, 2017 at 6:14 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

>> > In my case I'd like to have a platform device using the resources
>> that are
>> > parsed from the ACPI table (i.e. as it is done now by
>> > acpi_create_platform_device()).
>>
>> So far so good. Nothing prevents you to do that.
>>
>> > If my understanding is correct, if I declared an mfd_cell for my IPMI
>> child
>> > the mfd subsystem would create a platform device for such child and
>> > therefore acpi_create_platform_device() would fail to create a new
>> platform
>> > device as adev->physical_node_count will be non zero.
>> > However as things stand now mfd_cell devices can only use the
>> resources
>> > that are statically defined in the code (and therefore not the ones
>> in the
>> > ACPI nodes)...am I right?
>>
>> You may file resources first and then register MFD cells. See many
>> existing examples in the kernel.
>
> Well I had a look around the Kernel I have seen no mfd cells using
> Resources that are not statically defined:
> i.e. cell->resources in mfd_add_device() always points to statically
> defined resource structures.
>
> Usually for ACPI devices first you need to parse the ACPI resources
> from the table calling acpi_dev_get_resources(), then you iterate
> over the resource list and fill the resource array by calling
> acpi_platform_fill_resurces() (as in acpi_create_platform_device())
>
> With respect to my case are you suggesting dynamically allocate a
> resource array and fill it using the same fashion as
> acpi_create_platform_device(), then point cell->resources to such
> array before calling mfd_add_device() ?

You may do it on stack. Define your cell statically (but not const)
and apply resources just before mfd_add_devices() call.
There are examples in the existing drivers. Intel LPC comes to my mind
and perhaps PMC (Broxton), though latter has too much other stuff
around.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* Re: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 15:46                                             ` Andy Shevchenko
  0 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-04 15:46 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, Rafael J. Wysocki, linux-pci, will.deacon,
	Linuxarm, frowand.list, Lorenzo Pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, Mika Westerberg, linux-arm-kernel, Rafael J. Wysocki,
	linux-kernel, olof, brian.starkey

On Tue, Jul 4, 2017 at 6:14 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

>> > In my case I'd like to have a platform device using the resources
>> that are
>> > parsed from the ACPI table (i.e. as it is done now by
>> > acpi_create_platform_device()).
>>
>> So far so good. Nothing prevents you to do that.
>>
>> > If my understanding is correct, if I declared an mfd_cell for my IPMI
>> child
>> > the mfd subsystem would create a platform device for such child and
>> > therefore acpi_create_platform_device() would fail to create a new
>> platform
>> > device as adev->physical_node_count will be non zero.
>> > However as things stand now mfd_cell devices can only use the
>> resources
>> > that are statically defined in the code (and therefore not the ones
>> in the
>> > ACPI nodes)...am I right?
>>
>> You may file resources first and then register MFD cells. See many
>> existing examples in the kernel.
>
> Well I had a look around the Kernel I have seen no mfd cells using
> Resources that are not statically defined:
> i.e. cell->resources in mfd_add_device() always points to statically
> defined resource structures.
>
> Usually for ACPI devices first you need to parse the ACPI resources
> from the table calling acpi_dev_get_resources(), then you iterate
> over the resource list and fill the resource array by calling
> acpi_platform_fill_resurces() (as in acpi_create_platform_device())
>
> With respect to my case are you suggesting dynamically allocate a
> resource array and fill it using the same fashion as
> acpi_create_platform_device(), then point cell->resources to such
> array before calling mfd_add_device() ?

You may do it on stack. Define your cell statically (but not const)
and apply resources just before mfd_add_devices() call.
There are examples in the existing drivers. Intel LPC comes to my mind
and perhaps PMC (Broxton), though latter has too much other stuff
around.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 15:46                                             ` Andy Shevchenko
  0 siblings, 0 replies; 171+ messages in thread
From: Andy Shevchenko @ 2017-07-04 15:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 4, 2017 at 6:14 PM, Gabriele Paoloni
<gabriele.paoloni@huawei.com> wrote:

>> > In my case I'd like to have a platform device using the resources
>> that are
>> > parsed from the ACPI table (i.e. as it is done now by
>> > acpi_create_platform_device()).
>>
>> So far so good. Nothing prevents you to do that.
>>
>> > If my understanding is correct, if I declared an mfd_cell for my IPMI
>> child
>> > the mfd subsystem would create a platform device for such child and
>> > therefore acpi_create_platform_device() would fail to create a new
>> platform
>> > device as adev->physical_node_count will be non zero.
>> > However as things stand now mfd_cell devices can only use the
>> resources
>> > that are statically defined in the code (and therefore not the ones
>> in the
>> > ACPI nodes)...am I right?
>>
>> You may file resources first and then register MFD cells. See many
>> existing examples in the kernel.
>
> Well I had a look around the Kernel I have seen no mfd cells using
> Resources that are not statically defined:
> i.e. cell->resources in mfd_add_device() always points to statically
> defined resource structures.
>
> Usually for ACPI devices first you need to parse the ACPI resources
> from the table calling acpi_dev_get_resources(), then you iterate
> over the resource list and fill the resource array by calling
> acpi_platform_fill_resurces() (as in acpi_create_platform_device())
>
> With respect to my case are you suggesting dynamically allocate a
> resource array and fill it using the same fashion as
> acpi_create_platform_device(), then point cell->resources to such
> array before calling mfd_add_device() ?

You may do it on stack. Define your cell statically (but not const)
and apply resources just before mfd_add_devices() call.
There are examples in the existing drivers. Intel LPC comes to my mind
and perhaps PMC (Broxton), though latter has too much other stuff
around.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
  2017-07-04 15:46                                             ` Andy Shevchenko
  (?)
  (?)
@ 2017-07-04 16:22                                               ` Gabriele Paoloni
  -1 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 16:22 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel@vger.kernel.org

Hi Andy

[...]

> 
> You may do it on stack. Define your cell statically (but not const)
> and apply resources just before mfd_add_devices() call.

Ok thanks got it

> There are examples in the existing drivers. Intel LPC comes to my mind
> and perhaps PMC (Broxton), though latter has too much other stuff
> around.

Uh yes I see now in lpc_ich.c (base address is read from PCI config space
and resources are set accordingly).

Cheers
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 16:22                                               ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 16:22 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Mika Westerberg, Rafael J. Wysocki, Lorenzo Pieralisi,
	Rafael J. Wysocki, catalin.marinas, will.deacon, robh+dt,
	frowand.list, bhelgaas, arnd, linux-arm-kernel, mark.rutland,
	brian.starkey, olof, benh, linux-kernel, linux-acpi, Linuxarm,
	linux-pci, minyard, John Garry, xuwei (O)

Hi Andy

[...]

> 
> You may do it on stack. Define your cell statically (but not const)
> and apply resources just before mfd_add_devices() call.

Ok thanks got it

> There are examples in the existing drivers. Intel LPC comes to my mind
> and perhaps PMC (Broxton), though latter has too much other stuff
> around.

Uh yes I see now in lpc_ich.c (base address is read from PCI config space
and resources are set accordingly).

Cheers
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

* RE: [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 16:22                                               ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 16:22 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: mark.rutland, benh, Rafael J. Wysocki, linux-pci, will.deacon,
	Linuxarm, frowand.list, Lorenzo Pieralisi, arnd, xuwei (O),
	linux-acpi, catalin.marinas, minyard, John Garry, robh+dt,
	bhelgaas, Mika Westerberg, linux-arm-kernel, Rafael J. Wysocki,
	linux-kernel, olof, brian.starkey

Hi Andy

[...]

> 
> You may do it on stack. Define your cell statically (but not const)
> and apply resources just before mfd_add_devices() call.

Ok thanks got it

> There are examples in the existing drivers. Intel LPC comes to my mind
> and perhaps PMC (Broxton), though latter has too much other stuff
> around.

Uh yes I see now in lpc_ich.c (base address is read from PCI config space
and resources are set accordingly).

Cheers
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 171+ messages in thread

* [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning
@ 2017-07-04 16:22                                               ` Gabriele Paoloni
  0 siblings, 0 replies; 171+ messages in thread
From: Gabriele Paoloni @ 2017-07-04 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Andy

[...]

> 
> You may do it on stack. Define your cell statically (but not const)
> and apply resources just before mfd_add_devices() call.

Ok thanks got it

> There are examples in the existing drivers. Intel LPC comes to my mind
> and perhaps PMC (Broxton), though latter has too much other stuff
> around.

Uh yes I see now in lpc_ich.c (base address is read from PCI config space
and resources are set accordingly).

Cheers
Gab

> 
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 171+ messages in thread

end of thread, other threads:[~2017-07-04 16:26 UTC | newest]

Thread overview: 171+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-25 11:37 [PATCH v9 0/7] LPC: legacy ISA I/O support Gabriele Paoloni
2017-05-25 11:37 ` Gabriele Paoloni
2017-05-25 11:37 ` Gabriele Paoloni
2017-05-25 11:37 ` Gabriele Paoloni
2017-05-25 11:37 ` [PATCH v9 1/7] LIB: Introduce a generic PIO mapping method Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-26 20:57   ` Bjorn Helgaas
2017-05-26 20:57     ` Bjorn Helgaas
2017-05-26 20:57     ` Bjorn Helgaas
2017-05-26 20:57     ` Bjorn Helgaas
2017-05-30 15:09     ` Gabriele Paoloni
2017-05-30 15:09       ` Gabriele Paoloni
2017-05-30 15:09       ` Gabriele Paoloni
2017-05-30 15:09       ` Gabriele Paoloni
2017-05-25 11:37 ` [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-26 21:20   ` Bjorn Helgaas
2017-05-26 21:20     ` Bjorn Helgaas
2017-05-26 21:20     ` Bjorn Helgaas
2017-05-26 21:20     ` Bjorn Helgaas
2017-05-30  8:12     ` Gabriele Paoloni
2017-05-30  8:12       ` Gabriele Paoloni
2017-05-30  8:12       ` Gabriele Paoloni
2017-05-30  8:12       ` Gabriele Paoloni
2017-05-25 11:37 ` [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37 ` [PATCH v9 4/7] LPC: Support the device-tree LPC host on Hip06/Hip07 Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37 ` [PATCH v9 5/7] ACPI: Translate the I/O range of non-MMIO devices before scanning Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-26  0:03   ` kbuild test robot
2017-05-26  0:03     ` kbuild test robot
2017-05-26  0:03     ` kbuild test robot
2017-05-26  0:03     ` kbuild test robot
2017-05-30 13:24   ` Lorenzo Pieralisi
2017-05-30 13:24     ` Lorenzo Pieralisi
2017-05-30 13:24     ` Lorenzo Pieralisi
2017-05-31 10:24     ` Gabriele Paoloni
2017-05-31 10:24       ` Gabriele Paoloni
2017-05-31 10:24       ` Gabriele Paoloni
2017-05-31 10:24       ` Gabriele Paoloni
2017-06-06  8:55       ` Lorenzo Pieralisi
2017-06-06  8:55         ` Lorenzo Pieralisi
2017-06-06  8:55         ` Lorenzo Pieralisi
2017-06-06  8:55         ` Lorenzo Pieralisi
2017-06-12 15:57         ` Lorenzo Pieralisi
2017-06-12 15:57           ` Lorenzo Pieralisi
2017-06-12 15:57           ` Lorenzo Pieralisi
2017-06-12 15:57           ` Lorenzo Pieralisi
2017-06-13  7:24           ` Gabriele Paoloni
2017-06-13  7:24             ` Gabriele Paoloni
2017-06-13  7:24             ` Gabriele Paoloni
2017-06-13  7:24             ` Gabriele Paoloni
2017-06-13  8:48           ` Mika Westerberg
2017-06-13  8:48             ` Mika Westerberg
2017-06-13  8:48             ` Mika Westerberg
2017-06-13  8:48             ` Mika Westerberg
2017-06-13 14:38             ` Gabriele Paoloni
2017-06-13 14:38               ` Gabriele Paoloni
2017-06-13 14:38               ` Gabriele Paoloni
2017-06-13 14:38               ` Gabriele Paoloni
2017-06-13 15:10               ` Mika Westerberg
2017-06-13 15:10                 ` Mika Westerberg
2017-06-13 15:10                 ` Mika Westerberg
2017-06-13 15:10                 ` Mika Westerberg
2017-06-13 19:01                 ` Gabriele Paoloni
2017-06-13 19:01                   ` Gabriele Paoloni
2017-06-13 19:01                   ` Gabriele Paoloni
2017-06-13 19:01                   ` Gabriele Paoloni
2017-06-13 20:03                   ` Mika Westerberg
2017-06-13 20:03                     ` Mika Westerberg
2017-06-13 20:03                     ` Mika Westerberg
2017-06-13 20:03                     ` Mika Westerberg
2017-06-15 18:01                     ` Gabriele Paoloni
2017-06-15 18:01                       ` Gabriele Paoloni
2017-06-15 18:01                       ` Gabriele Paoloni
2017-06-15 18:01                       ` Gabriele Paoloni
2017-06-16  8:33                       ` Mika Westerberg
2017-06-16  8:33                         ` Mika Westerberg
2017-06-16  8:33                         ` Mika Westerberg
2017-06-16  8:33                         ` Mika Westerberg
2017-06-16 11:24                         ` Rafael J. Wysocki
2017-06-16 11:24                           ` Rafael J. Wysocki
2017-06-16 11:24                           ` Rafael J. Wysocki
2017-06-16 11:24                           ` Rafael J. Wysocki
2017-06-16 12:00                           ` Mika Westerberg
2017-06-16 12:00                             ` Mika Westerberg
2017-06-16 12:00                             ` Mika Westerberg
2017-06-16 12:00                             ` Mika Westerberg
2017-06-16 12:22                             ` Rafael J. Wysocki
2017-06-16 12:22                               ` Rafael J. Wysocki
2017-06-16 12:22                               ` Rafael J. Wysocki
2017-06-16 12:22                               ` Rafael J. Wysocki
2017-06-19  9:50                               ` Gabriele Paoloni
2017-06-19  9:50                                 ` Gabriele Paoloni
2017-06-19  9:50                                 ` Gabriele Paoloni
2017-06-19  9:50                                 ` Gabriele Paoloni
2017-06-19 10:02                                 ` Mika Westerberg
2017-06-19 10:02                                   ` Mika Westerberg
2017-06-19 10:02                                   ` Mika Westerberg
2017-06-19 10:02                                   ` Mika Westerberg
2017-06-19 10:04                                   ` Gabriele Paoloni
2017-06-19 10:04                                     ` Gabriele Paoloni
2017-06-19 10:04                                     ` Gabriele Paoloni
2017-06-19 10:04                                     ` Gabriele Paoloni
2017-07-03 16:08                                     ` Gabriele Paoloni
2017-07-03 16:08                                       ` Gabriele Paoloni
2017-07-03 16:08                                       ` Gabriele Paoloni
2017-07-03 16:08                                       ` Gabriele Paoloni
2017-07-03 16:23                                       ` Gabriele Paoloni
2017-07-03 16:23                                         ` Gabriele Paoloni
2017-07-03 16:23                                         ` Gabriele Paoloni
2017-07-03 16:23                                         ` Gabriele Paoloni
2017-07-03 20:22                                       ` Andy Shevchenko
2017-07-03 20:22                                         ` Andy Shevchenko
2017-07-03 20:22                                         ` Andy Shevchenko
2017-07-03 20:22                                         ` Andy Shevchenko
2017-07-04 15:14                                         ` Gabriele Paoloni
2017-07-04 15:14                                           ` Gabriele Paoloni
2017-07-04 15:14                                           ` Gabriele Paoloni
2017-07-04 15:14                                           ` Gabriele Paoloni
2017-07-04 15:46                                           ` Andy Shevchenko
2017-07-04 15:46                                             ` Andy Shevchenko
2017-07-04 15:46                                             ` Andy Shevchenko
2017-07-04 15:46                                             ` Andy Shevchenko
2017-07-04 16:22                                             ` Gabriele Paoloni
2017-07-04 16:22                                               ` Gabriele Paoloni
2017-07-04 16:22                                               ` Gabriele Paoloni
2017-07-04 16:22                                               ` Gabriele Paoloni
2017-06-29 16:16                           ` John Garry
2017-06-29 16:16                             ` John Garry
2017-06-29 16:16                             ` John Garry
2017-06-29 16:16                             ` John Garry
2017-06-30  9:05                             ` Mika Westerberg
2017-06-30  9:05                               ` Mika Westerberg
2017-06-30  9:05                               ` Mika Westerberg
2017-06-30  9:05                               ` Mika Westerberg
2017-06-30  9:28                               ` John Garry
2017-06-30  9:28                                 ` John Garry
2017-06-30  9:28                                 ` John Garry
2017-06-30  9:28                                 ` John Garry
2017-06-30 12:56                                 ` Rafael J. Wysocki
2017-06-30 12:56                                   ` Rafael J. Wysocki
2017-06-30 12:56                                   ` Rafael J. Wysocki
2017-06-30 12:56                                   ` Rafael J. Wysocki
2017-05-25 11:37 ` [PATCH v9 6/7] LPC: Add the ACPI LPC support Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-26  3:12   ` kbuild test robot
2017-05-26  3:12     ` kbuild test robot
2017-05-26  3:12     ` kbuild test robot
2017-05-26  3:12     ` kbuild test robot
2017-05-26 10:12     ` Gabriele Paoloni
2017-05-26 10:12       ` Gabriele Paoloni
2017-05-26 10:12       ` Gabriele Paoloni
2017-05-26 10:12       ` Gabriele Paoloni
2017-05-25 11:37 ` [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni
2017-05-25 11:37   ` Gabriele Paoloni

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.