All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 0/4] ARM64 LPC: legacy ISA I/O support
@ 2016-09-14 12:15 ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

This patch supports the 16550 compatible UART attached to the Low-Pin-Count
interface mplemented on Hisilicon Hip06 SoC. The periperals attached this LPC
include UART, BT, KCS, and so on.
	                -----------
			| LPC host|
	                |         |
	                -----------
	                     |
 	        _____________V_______________LPC
                  |			  |
                  V	                  V
             -----------             ------------
             |  UART   |             |  BT(ipmi)|
             -----------             ------------

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

This patch set is built based on mainline v4.8-rc6;

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;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (4):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: LPC driver implementation on Hip06
  ARM64 LPC: support serial based on low-pin-count
  ARM64 LPC: support earlycon for UART connected to LPC

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  35 +
 .../devicetree/bindings/serial/hisi-lpc-uart.txt   |  60 ++
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/io.h                        |  90 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/extio.c                                |  66 ++
 drivers/bus/hisi_lpc.c                             | 766 +++++++++++++++++++++
 drivers/of/address.c                               |   9 +
 drivers/tty/serial/8250/8250_early.c               |  26 +-
 drivers/tty/serial/8250/8250_hisi_lpc.c            | 171 +++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   1 +
 include/linux/extio.h                              |  49 ++
 14 files changed, 1296 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
 create mode 100644 drivers/bus/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 drivers/tty/serial/8250/8250_hisi_lpc.c
 create mode 100644 include/linux/extio.h

-- 
1.9.1

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

* [PATCH V3 0/4] ARM64 LPC: legacy ISA I/O support
@ 2016-09-14 12:15 ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

This patch supports the 16550 compatible UART attached to the Low-Pin-Count
interface mplemented on Hisilicon Hip06 SoC. The periperals attached this LPC
include UART, BT, KCS, and so on.
	                -----------
			| LPC host|
	                |         |
	                -----------
	                     |
 	        _____________V_______________LPC
                  |			  |
                  V	                  V
             -----------             ------------
             |  UART   |             |  BT(ipmi)|
             -----------             ------------

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

This patch set is built based on mainline v4.8-rc6;

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;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (4):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: LPC driver implementation on Hip06
  ARM64 LPC: support serial based on low-pin-count
  ARM64 LPC: support earlycon for UART connected to LPC

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  35 +
 .../devicetree/bindings/serial/hisi-lpc-uart.txt   |  60 ++
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/io.h                        |  90 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/extio.c                                |  66 ++
 drivers/bus/hisi_lpc.c                             | 766 +++++++++++++++++++++
 drivers/of/address.c                               |   9 +
 drivers/tty/serial/8250/8250_early.c               |  26 +-
 drivers/tty/serial/8250/8250_hisi_lpc.c            | 171 +++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   1 +
 include/linux/extio.h                              |  49 ++
 14 files changed, 1296 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
 create mode 100644 drivers/bus/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 drivers/tty/serial/8250/8250_hisi_lpc.c
 create mode 100644 include/linux/extio.h

-- 
1.9.1

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

* [PATCH V3 0/4] ARM64 LPC: legacy ISA I/O support
@ 2016-09-14 12:15 ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

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

This patch supports the 16550 compatible UART attached to the Low-Pin-Count
interface mplemented on Hisilicon Hip06 SoC. The periperals attached this LPC
include UART, BT, KCS, and so on.
	                -----------
			| LPC host|
	                |         |
	                -----------
	                     |
 	        _____________V_______________LPC
                  |			  |
                  V	                  V
             -----------             ------------
             |  UART   |             |  BT(ipmi)|
             -----------             ------------

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

This patch set is built based on mainline v4.8-rc6;

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;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (4):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: LPC driver implementation on Hip06
  ARM64 LPC: support serial based on low-pin-count
  ARM64 LPC: support earlycon for UART connected to LPC

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  35 +
 .../devicetree/bindings/serial/hisi-lpc-uart.txt   |  60 ++
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/io.h                        |  90 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/extio.c                                |  66 ++
 drivers/bus/hisi_lpc.c                             | 766 +++++++++++++++++++++
 drivers/of/address.c                               |   9 +
 drivers/tty/serial/8250/8250_early.c               |  26 +-
 drivers/tty/serial/8250/8250_hisi_lpc.c            | 171 +++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   1 +
 include/linux/extio.h                              |  49 ++
 14 files changed, 1296 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
 create mode 100644 drivers/bus/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 drivers/tty/serial/8250/8250_hisi_lpc.c
 create mode 100644 include/linux/extio.h

-- 
1.9.1

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
  2016-09-14 12:15 ` Zhichang Yuan
  (?)
@ 2016-09-14 12:15   ` Zhichang Yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 arch/arm64/Kconfig          |  6 +++
 arch/arm64/include/asm/io.h | 90 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/bus/extio.c         | 66 +++++++++++++++++++++++++++++++++
 include/linux/extio.h       | 49 ++++++++++++++++++++++++
 4 files changed, 211 insertions(+)
 create mode 100644 drivers/bus/extio.c
 create mode 100644 include/linux/extio.h

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index bc3f00f..9579479 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	def_bool n
+	help
+	  Support to access the ISA I/O devices with the legacy X86 I/O port
+	  addresses in some SoCs, such as Hisilicon Hip06.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 9b6e408..d3acf1f 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -34,6 +34,10 @@
 
 #include <xen/xen.h>
 
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#include <linux/extio.h>
+#endif
+
 /*
  * Generic IO read/write.  These perform native-endian accesses.
  */
@@ -142,6 +146,38 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define writel(v,c)		({ __iowmb(); writel_relaxed((v),(c)); })
 #define writeq(v,c)		({ __iowmb(); writeq_relaxed((v),(c)); })
 
+
+#define BUILDS_RW(bwl, type)						\
+static inline void reads##bwl(const volatile void __iomem *addr,	\
+				void *buffer, unsigned int count)	\
+{									\
+	if (count) {							\
+		type *buf = buffer;					\
+									\
+		do {							\
+			type x = __raw_read##bwl(addr);			\
+			*buf++ = x;					\
+		} while (--count);					\
+	}								\
+}									\
+									\
+static inline void writes##bwl(volatile void __iomem *addr,		\
+				const void *buffer, unsigned int count)	\
+{									\
+	if (count) {							\
+		const type *buf = buffer;				\
+									\
+		do {							\
+			__raw_write##bwl(*buf++, addr);			\
+		} while (--count);					\
+	}								\
+}
+
+BUILDS_RW(b, u8)
+#define readsb readsb
+#define writesb writesb
+
+
 /*
  *  I/O port access primitives.
  */
@@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#define inb inb
+static inline u8 inb(unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		return extio_inb(addr);
+#endif
+	return readb(PCI_IOBASE + addr);
+}
+
+
+#define outb outb
+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_outb(value, addr);
+	else
+#endif
+		writeb(value, PCI_IOBASE + addr);
+}
+
+#define insb insb
+static inline void insb(unsigned long addr, void *buffer, unsigned int count)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_insb(addr, buffer, count);
+	else
+#endif
+		readsb(PCI_IOBASE + addr, buffer, count);
+}
+
+#define outsb outsb
+static inline void outsb(unsigned long addr, const void *buffer,
+			 unsigned int count)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_outsb(addr, buffer, count);
+	else
+#endif
+		writesb(PCI_IOBASE + addr, buffer, count);
+}
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
new file mode 100644
index 0000000..1e7a9c5
--- /dev/null
+++ b/drivers/bus/extio.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/io.h>
+
+
+struct extio_ops *arm64_extio_ops;
+
+
+u8 __weak extio_inb(unsigned long addr)
+{
+	return arm64_extio_ops->pfin ?
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, NULL,
+			sizeof(u8), 1) : -1;
+}
+
+void __weak extio_outb(u8 value, unsigned long addr)
+{
+	if (!arm64_extio_ops->pfout)
+		return;
+
+	arm64_extio_ops->pfout(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, &value,
+			sizeof(u8), 1);
+}
+
+
+void __weak extio_insb(unsigned long addr, void *buffer,
+				unsigned int count)
+{
+	if (!arm64_extio_ops->pfin)
+		return;
+
+	arm64_extio_ops->pfin(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, buffer,
+			sizeof(u8), count);
+}
+
+void __weak extio_outsb(unsigned long addr, const void *buffer,
+			 unsigned int count)
+{
+	if (!arm64_extio_ops->pfout)
+		return;
+
+	arm64_extio_ops->pfout(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, buffer,
+			sizeof(u8), count);
+}
+
+
diff --git a/include/linux/extio.h b/include/linux/extio.h
new file mode 100644
index 0000000..08d1fca
--- /dev/null
+++ b/include/linux/extio.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+
+typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+typedef void (*outhook)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+	unsigned long ptoffset;/* port Io - system Io */
+
+	inhook	pfin;
+	outhook	pfout;
+	void *devpara;
+};
+
+
+extern struct extio_ops *arm64_extio_ops;
+
+extern u8 extio_inb(unsigned long addr);
+extern void extio_outb(u8 value, unsigned long addr);
+extern void extio_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void extio_outsb(unsigned long addr, const void *buffer,
+				unsigned int count);
+
+
+#endif /* __LINUX_EXTIO_H*/
-- 
1.9.1

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 arch/arm64/Kconfig          |  6 +++
 arch/arm64/include/asm/io.h | 90 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/bus/extio.c         | 66 +++++++++++++++++++++++++++++++++
 include/linux/extio.h       | 49 ++++++++++++++++++++++++
 4 files changed, 211 insertions(+)
 create mode 100644 drivers/bus/extio.c
 create mode 100644 include/linux/extio.h

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index bc3f00f..9579479 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	def_bool n
+	help
+	  Support to access the ISA I/O devices with the legacy X86 I/O port
+	  addresses in some SoCs, such as Hisilicon Hip06.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 9b6e408..d3acf1f 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -34,6 +34,10 @@
 
 #include <xen/xen.h>
 
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#include <linux/extio.h>
+#endif
+
 /*
  * Generic IO read/write.  These perform native-endian accesses.
  */
@@ -142,6 +146,38 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define writel(v,c)		({ __iowmb(); writel_relaxed((v),(c)); })
 #define writeq(v,c)		({ __iowmb(); writeq_relaxed((v),(c)); })
 
+
+#define BUILDS_RW(bwl, type)						\
+static inline void reads##bwl(const volatile void __iomem *addr,	\
+				void *buffer, unsigned int count)	\
+{									\
+	if (count) {							\
+		type *buf = buffer;					\
+									\
+		do {							\
+			type x = __raw_read##bwl(addr);			\
+			*buf++ = x;					\
+		} while (--count);					\
+	}								\
+}									\
+									\
+static inline void writes##bwl(volatile void __iomem *addr,		\
+				const void *buffer, unsigned int count)	\
+{									\
+	if (count) {							\
+		const type *buf = buffer;				\
+									\
+		do {							\
+			__raw_write##bwl(*buf++, addr);			\
+		} while (--count);					\
+	}								\
+}
+
+BUILDS_RW(b, u8)
+#define readsb readsb
+#define writesb writesb
+
+
 /*
  *  I/O port access primitives.
  */
@@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#define inb inb
+static inline u8 inb(unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		return extio_inb(addr);
+#endif
+	return readb(PCI_IOBASE + addr);
+}
+
+
+#define outb outb
+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_outb(value, addr);
+	else
+#endif
+		writeb(value, PCI_IOBASE + addr);
+}
+
+#define insb insb
+static inline void insb(unsigned long addr, void *buffer, unsigned int count)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_insb(addr, buffer, count);
+	else
+#endif
+		readsb(PCI_IOBASE + addr, buffer, count);
+}
+
+#define outsb outsb
+static inline void outsb(unsigned long addr, const void *buffer,
+			 unsigned int count)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_outsb(addr, buffer, count);
+	else
+#endif
+		writesb(PCI_IOBASE + addr, buffer, count);
+}
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
new file mode 100644
index 0000000..1e7a9c5
--- /dev/null
+++ b/drivers/bus/extio.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/io.h>
+
+
+struct extio_ops *arm64_extio_ops;
+
+
+u8 __weak extio_inb(unsigned long addr)
+{
+	return arm64_extio_ops->pfin ?
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, NULL,
+			sizeof(u8), 1) : -1;
+}
+
+void __weak extio_outb(u8 value, unsigned long addr)
+{
+	if (!arm64_extio_ops->pfout)
+		return;
+
+	arm64_extio_ops->pfout(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, &value,
+			sizeof(u8), 1);
+}
+
+
+void __weak extio_insb(unsigned long addr, void *buffer,
+				unsigned int count)
+{
+	if (!arm64_extio_ops->pfin)
+		return;
+
+	arm64_extio_ops->pfin(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, buffer,
+			sizeof(u8), count);
+}
+
+void __weak extio_outsb(unsigned long addr, const void *buffer,
+			 unsigned int count)
+{
+	if (!arm64_extio_ops->pfout)
+		return;
+
+	arm64_extio_ops->pfout(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, buffer,
+			sizeof(u8), count);
+}
+
+
diff --git a/include/linux/extio.h b/include/linux/extio.h
new file mode 100644
index 0000000..08d1fca
--- /dev/null
+++ b/include/linux/extio.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+
+typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+typedef void (*outhook)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+	unsigned long ptoffset;/* port Io - system Io */
+
+	inhook	pfin;
+	outhook	pfout;
+	void *devpara;
+};
+
+
+extern struct extio_ops *arm64_extio_ops;
+
+extern u8 extio_inb(unsigned long addr);
+extern void extio_outb(u8 value, unsigned long addr);
+extern void extio_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void extio_outsb(unsigned long addr, const void *buffer,
+				unsigned int count);
+
+
+#endif /* __LINUX_EXTIO_H*/
-- 
1.9.1

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

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

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 arch/arm64/Kconfig          |  6 +++
 arch/arm64/include/asm/io.h | 90 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/bus/extio.c         | 66 +++++++++++++++++++++++++++++++++
 include/linux/extio.h       | 49 ++++++++++++++++++++++++
 4 files changed, 211 insertions(+)
 create mode 100644 drivers/bus/extio.c
 create mode 100644 include/linux/extio.h

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index bc3f00f..9579479 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	def_bool n
+	help
+	  Support to access the ISA I/O devices with the legacy X86 I/O port
+	  addresses in some SoCs, such as Hisilicon Hip06.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 9b6e408..d3acf1f 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -34,6 +34,10 @@
 
 #include <xen/xen.h>
 
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#include <linux/extio.h>
+#endif
+
 /*
  * Generic IO read/write.  These perform native-endian accesses.
  */
@@ -142,6 +146,38 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define writel(v,c)		({ __iowmb(); writel_relaxed((v),(c)); })
 #define writeq(v,c)		({ __iowmb(); writeq_relaxed((v),(c)); })
 
+
+#define BUILDS_RW(bwl, type)						\
+static inline void reads##bwl(const volatile void __iomem *addr,	\
+				void *buffer, unsigned int count)	\
+{									\
+	if (count) {							\
+		type *buf = buffer;					\
+									\
+		do {							\
+			type x = __raw_read##bwl(addr);			\
+			*buf++ = x;					\
+		} while (--count);					\
+	}								\
+}									\
+									\
+static inline void writes##bwl(volatile void __iomem *addr,		\
+				const void *buffer, unsigned int count)	\
+{									\
+	if (count) {							\
+		const type *buf = buffer;				\
+									\
+		do {							\
+			__raw_write##bwl(*buf++, addr);			\
+		} while (--count);					\
+	}								\
+}
+
+BUILDS_RW(b, u8)
+#define readsb readsb
+#define writesb writesb
+
+
 /*
  *  I/O port access primitives.
  */
@@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#define inb inb
+static inline u8 inb(unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		return extio_inb(addr);
+#endif
+	return readb(PCI_IOBASE + addr);
+}
+
+
+#define outb outb
+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_outb(value, addr);
+	else
+#endif
+		writeb(value, PCI_IOBASE + addr);
+}
+
+#define insb insb
+static inline void insb(unsigned long addr, void *buffer, unsigned int count)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_insb(addr, buffer, count);
+	else
+#endif
+		readsb(PCI_IOBASE + addr, buffer, count);
+}
+
+#define outsb outsb
+static inline void outsb(unsigned long addr, const void *buffer,
+			 unsigned int count)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)
+		extio_outsb(addr, buffer, count);
+	else
+#endif
+		writesb(PCI_IOBASE + addr, buffer, count);
+}
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
new file mode 100644
index 0000000..1e7a9c5
--- /dev/null
+++ b/drivers/bus/extio.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/io.h>
+
+
+struct extio_ops *arm64_extio_ops;
+
+
+u8 __weak extio_inb(unsigned long addr)
+{
+	return arm64_extio_ops->pfin ?
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, NULL,
+			sizeof(u8), 1) : -1;
+}
+
+void __weak extio_outb(u8 value, unsigned long addr)
+{
+	if (!arm64_extio_ops->pfout)
+		return;
+
+	arm64_extio_ops->pfout(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, &value,
+			sizeof(u8), 1);
+}
+
+
+void __weak extio_insb(unsigned long addr, void *buffer,
+				unsigned int count)
+{
+	if (!arm64_extio_ops->pfin)
+		return;
+
+	arm64_extio_ops->pfin(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, buffer,
+			sizeof(u8), count);
+}
+
+void __weak extio_outsb(unsigned long addr, const void *buffer,
+			 unsigned int count)
+{
+	if (!arm64_extio_ops->pfout)
+		return;
+
+	arm64_extio_ops->pfout(arm64_extio_ops->devpara,
+			addr + arm64_extio_ops->ptoffset, buffer,
+			sizeof(u8), count);
+}
+
+
diff --git a/include/linux/extio.h b/include/linux/extio.h
new file mode 100644
index 0000000..08d1fca
--- /dev/null
+++ b/include/linux/extio.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+
+typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+typedef void (*outhook)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+	unsigned long ptoffset;/* port Io - system Io */
+
+	inhook	pfin;
+	outhook	pfout;
+	void *devpara;
+};
+
+
+extern struct extio_ops *arm64_extio_ops;
+
+extern u8 extio_inb(unsigned long addr);
+extern void extio_outb(u8 value, unsigned long addr);
+extern void extio_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void extio_outsb(unsigned long addr, const void *buffer,
+				unsigned int count);
+
+
+#endif /* __LINUX_EXTIO_H*/
-- 
1.9.1

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-14 12:15 ` Zhichang Yuan
  (?)
@ 2016-09-14 12:15   ` Zhichang Yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

On Hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  35 ++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/hisi_lpc.c                             | 653 +++++++++++++++++++++
 drivers/of/address.c                               |   9 +
 5 files changed, 707 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..820e26d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,35 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #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 address and length of the register set for the device.
+- ranges: define a 1:1 mapping between the I/O space of the child device and
+	  the parent.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
+
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 3b205e2..fdb232b 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_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 ac84cc4..6ffbb27 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.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..9b364d0
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/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>
+
+
+struct hisilpc_dev;
+
+/* This flag is specific to differentiate earlycon operations and the others */
+#define FG_EARLYCON_LPC		0x0001
+/*
+ * this bit set means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x0002
+
+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 platform_device *pltdev;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+
+#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_SING	(0x00000008)
+#define LPC_CMD_SAMEADDR_INC	(0x00000000)
+#define LPC_CMD_TYPE_IO		(0x00000000)
+#define LPC_CMD_TYPE_MEM	(0x00000002)
+#define LPC_CMD_TYPE_FWH	(0x00000004)
+#define LPC_CMD_WRITE		(0x00000001)
+#define LPC_CMD_READ		(0x00000000)
+
+#define LPC_IRQ_CLEAR		(0x02)
+#define LPC_IRQ_OCCURRED	(0x02)
+
+#define LPC_STATUS_IDLE		(0x01)
+#define LPC_OP_FINISHED		(0x02)
+
+#define START_WORK		(0x01)
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * 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 specfic 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 = 0;
+
+	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 periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters 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 *pdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int retval;
+	/*initialized as 0 to remove compile warning */
+	unsigned long flags = 0;
+
+	if (!buf || !opcnt || !para || !pdev)
+		return -EINVAL;
+
+	if (para->csize != 1 || opcnt  > LPC_MAX_OPCNT)
+		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_SING;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	/* whole operation must be atomic */
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_lock_irqsave(&pdev->cycle_lock, flags);
+
+	writel(opcnt, pdev->membase + LPC_REG_OP_LEN);
+
+	writel(cmd_word, pdev->membase + LPC_REG_CMD);
+
+	writel(ptaddr, pdev->membase + LPC_REG_ADDR);
+
+	writel(START_WORK, pdev->membase + LPC_REG_START);
+
+	/* whether the operation is finished */
+	retval = wait_lpc_idle(pdev->membase, waitcnt);
+	if (!retval) {
+		for (; opcnt--; buf++)
+			*buf = readl(pdev->membase + LPC_REG_RDATA);
+	}
+
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_unlock_irqrestore(&pdev->cycle_lock, flags);
+
+	return retval;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters 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 *pdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int retval;
+	/* initialized as 0 to remove compile warning */
+	unsigned long flags = 0;
+
+
+	if (!buf || !opcnt || !para || !pdev)
+		return -EINVAL;
+
+	if (para->csize != 1 || opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR_SING;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	/* whole operation must be atomic */
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_lock_irqsave(&pdev->cycle_lock, flags);
+
+	writel(opcnt, pdev->membase + LPC_REG_OP_LEN);
+	for (; opcnt--; buf++)
+		writel(*buf, pdev->membase + LPC_REG_WDATA);
+
+	writel(cmd_word, pdev->membase + LPC_REG_CMD);
+
+	writel(ptaddr, pdev->membase + LPC_REG_ADDR);
+
+	writel(START_WORK, pdev->membase + LPC_REG_START);
+
+	/* whether the operation is finished */
+	retval = wait_lpc_idle(pdev->membase, waitcnt);
+
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_unlock_irqrestore(&pdev->cycle_lock, flags);
+
+	return retval;
+}
+
+/**
+ * hisilpc_comm_inb - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outbuf: a buffer where the data read is stored at.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ * @count: how many I/O operations required in this calling.  >1 is for ins.
+ *
+ * For this lpc, only support inb/insb now.
+ *
+ * For inbs, returns 0 on success, -1 on fail.
+ * 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.
+ */
+u64 hisilpc_comm_inb(void *devobj, unsigned long ptaddr,
+				void *inbuf, size_t dlen,
+				unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned int loopcnt, cntleft;
+	unsigned int rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+	/* only support data unit length is 1 now... */
+	if (!count || (!inbuf && count != 1) || !devobj || dlen != 1)
+		return -1;
+
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * the operation data len is 4 bytes, need to ensure the buffer
+	 * is big enough.
+	 */
+	if (!inbuf || count < sizeof(u32))
+		newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	dev_dbg(&lpcdev->pltdev->dev, "In-IO(0x%lx), count=%u\n", ptaddr,
+			count);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	/*
+	 * to improve performance, support repeatly rd at same target
+	 * address.
+	 */
+	if (count > 1)
+		iopara.opflags &= ~FG_INCRADDR_LPC;
+
+	iopara.csize = dlen;
+
+	cntleft = count;
+	do {
+		loopcnt = (cntleft > LPC_MAX_OPCNT) ? LPC_MAX_OPCNT : cntleft;
+		ret = hisilpc_target_in(lpcdev,
+				&iopara, ptaddr, newbuf, loopcnt);
+		if (ret)
+			return -1;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	/* for inb */
+	if (!inbuf)
+		return rd_data;
+	/* for insb, copy the data to the return variable */
+	if (inbuf != newbuf)
+		memcpy(inbuf, &rd_data, count);
+
+	return 0;
+}
+
+/**
+ * hisilpc_comm_outb - write/output the data in out buffer to the I/O peripheral
+ *		    through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outbuf: a buffer where the data to be written is stored.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many I/O operations required in this calling. >1 is for outs.
+ *
+ * For this lpc, only support outb/outsb now.
+ *
+ */
+void hisilpc_comm_outb(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned int loopcnt;
+	const unsigned char *newbuf;
+	int ret = 0;
+
+	if (!count || !outbuf || !devobj)
+		return;
+
+	newbuf = (const unsigned char *)outbuf;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	dev_dbg(&lpcdev->pltdev->dev, "Out-IO(0x%lx), cnt=%u\n", ptaddr, count);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	/* to improve performance,  support repeatly wr same target address */
+	if (count > 1)
+		iopara.opflags &= ~FG_INCRADDR_LPC;
+
+	iopara.csize = 1;
+
+	do {
+		loopcnt = (count > LPC_MAX_OPCNT) ? LPC_MAX_OPCNT : count;
+		ret = hisilpc_target_out(lpcdev,
+				&iopara, ptaddr, newbuf, loopcnt);
+		if (ret)
+			return;
+		newbuf += loopcnt;
+		count -= loopcnt;
+	} while (count);
+}
+
+
+/**
+ * hisilpc_ischild_ipmi - check whether the designated device is ipmi
+ * @dev: the device to be checked.
+ * @data: the value used to match the acpi device in checking.
+ *
+ * Returns 1 means the device to be checked is matched.
+ * 0 means some failures.
+ *
+ */
+static int  hisilpc_ischild_ipmi(struct device *dev)
+{
+	struct acpi_device *adev;
+	struct acpi_hardware_id *hwid;
+	/* only support dts and acpi */
+	if (IS_ERR_OR_NULL(dev->fwnode) && !dev->of_node) {
+		dev_err(dev, "Not valid child device!\n");
+		return -EINVAL;
+	}
+
+	adev = ACPI_COMPANION(dev);
+	if (adev) {
+		list_for_each_entry(hwid, &adev->pnp.ids, list) {
+			dev_info(dev, "hwid is %s\n", hwid->id);
+			if (!strcmp("IPI0001", hwid->id))
+				return 1;
+		}
+	} else {
+		if (!strcmp(dev->of_node->type, "ipmi"))
+			return 1;
+	}
+
+	dev_info(dev, "not ipmi child device!\n");
+	return 0;
+}
+
+
+/**
+ * hisilpc_children_map_sysio - setup the mapping between system Io and
+ *			physical IO
+ *
+ * @child: the device whose IO is handling
+ * @data: some device specific data. For ACPI device, should be NULL.
+ *
+ * Returns >=0 means the mapping is successfully created;
+ * others mean some failures.
+ */
+static int hisilpc_children_map_sysio(struct device * child, void * data)
+{
+	struct resource *iores;
+	unsigned long cpuio;
+	struct extio_ops *opsnode;
+	int ret;
+	struct hisilpc_dev *lpcdev;
+
+	if (!child || !child->parent)
+		return -EINVAL;
+
+	iores = platform_get_resource_byname(to_platform_device(child),
+					IORESOURCE_IO, "dev_io");
+	if (!iores)
+		return -ENODEV;
+
+	/*
+	 * can not use devm_kzalloc to allocate slab for child before its driver
+	 * start probing. Here allocate the slab with the name of parent.
+	 */
+	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
+	if (!opsnode)
+		return -ENOMEM;
+
+	cpuio = data ? *((unsigned long *)data) : 0;
+
+	opsnode->start = iores->start;
+	opsnode->end = iores->end;
+	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
+
+	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
+				(unsigned long)iores->start,
+				(unsigned long)iores->end,
+				opsnode->ptoffset);
+
+	opsnode->pfin = hisilpc_comm_inb;
+	opsnode->pfout = hisilpc_comm_outb;
+
+	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
+	opsnode->devpara = lpcdev;
+
+	/* only apply indirect-IO to ipmi child device */
+	ret = hisilpc_ischild_ipmi(child);
+	if (ret < 0)
+		return ret;
+
+	if (ret > 0) {
+		WRITE_ONCE(arm64_extio_ops, opsnode);
+		/* update ret as successful */
+		ret = 0;
+	} else {
+		ret = platform_device_add_data(to_platform_device(child),
+						opsnode,
+						sizeof(*opsnode));
+		devm_kfree(child->parent, opsnode);
+	}
+
+	if (!ret)
+		dev_info(child, "to phy [%lx-%lx]\n", cpuio,
+			(unsigned long)(iores->end - iores->start) + cpuio);
+	else
+		dev_info(child, "FAIL(0x%x)!!\n", ret);
+
+	return ret;
+}
+
+/**
+ * of_hisilpc_register_pio - register the deivce physical IO address into
+ *			io_range_list
+ *
+ * Returns >=0 means ok.
+ * others mean some failures.
+ */
+static int of_hisilpc_register_pio(struct device_node *dev,
+					unsigned long *phyport)
+{
+	static int isfirst = 0;
+	const __be32	*addrp;
+	u64		size;
+	unsigned int	flags;
+	u64	taddr;
+	int residx = 0;
+
+
+	if (!dev || !phyport)
+		return -EINVAL;
+	/* only one IO reg exists */
+	do {
+		addrp = of_get_address(dev, residx, &size, &flags);
+		if (addrp == NULL) {
+			pr_err("%s:: get OF address(%d) FAIL!\n",
+				dev->name, residx);
+			return -EINVAL;
+		}
+		residx++;
+	} while(!(flags & IORESOURCE_IO));
+
+
+	taddr = of_translate_address(dev, addrp);
+	if (taddr == OF_BAD_ADDR) {
+		pr_err("%s:: translate IO address fail\n", dev->name);
+		return -EINVAL;
+	}
+
+	/* register one more IO byte for the first register */
+	if (!isfirst) {
+		size += 1;
+		isfirst = 1;
+	}
+
+	if (pci_register_io_range(taddr, size)) {
+		pr_err("%s::register physical range[%llx, %llx) FAIL!\n",
+			dev->name, taddr, size);
+		return -ENXIO;
+	}
+
+	pr_info("%s:: register physical range[%llx, %llx) OK\n",
+			dev->name, taddr, size);
+
+	*phyport = taddr;
+
+	return 0;
+}
+
+/**
+ * hisilpc_probe_child_dev - setup the mapping between linux IO and
+ *			physical IO for all children under hisilpc
+ *
+ * @ppdev: point to the hisilpc device
+ *
+ * Returns =0 means ok.
+ * others mean some failures.
+ */
+static int hisilpc_probe_child_dev(struct device *ppdev)
+{
+	int ret;
+
+	if (!ppdev)
+		return -EINVAL;
+
+	ret = 0;
+	/* for device tree, scan the child devices now */
+	if (!has_acpi_companion(ppdev)) {
+		struct device_node *root, *child;
+
+		root = ppdev->of_node;
+		for_each_available_child_of_node(root, child) {
+			struct platform_device *ptdev;
+			unsigned long cpuio;
+
+			/* register the IO range configured in dt */
+			ret = of_hisilpc_register_pio(child, &cpuio);
+			if (ret) {
+				dev_err(ppdev, "fail to register raw IO for %s\n",
+						child->name);
+				return ret;
+			}
+
+			ptdev = of_platform_device_create(child, NULL, ppdev);
+			if (!ptdev) {
+				dev_err(ppdev, "create platform device fail for %s\n",
+					child->name);
+				return -EFAULT;
+			}
+
+			ret = hisilpc_children_map_sysio(&ptdev->dev, &cpuio);
+			if (ret)
+				dev_err(&ptdev->dev, "Mapping sysio for dts child devices FAIL\n");
+		}
+	} else {
+		ret = device_for_each_child(ppdev, NULL,
+					hisilpc_children_map_sysio);
+		if (ret)
+			dev_err(ppdev, "Mapping sysio for ACPI child devices FAIL\n");
+	}
+
+	return ret;
+}
+
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @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 resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "hslpc start probing...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "No mem resource\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	lpcdev->pltdev = pdev;
+	platform_set_drvdata(pdev, lpcdev);
+
+	ret = hisilpc_probe_child_dev(&pdev->dev);
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc finish probing...\n");
+	else
+		dev_err(&pdev->dev, "hslpc probe got fail(%d)!\n", -ret);
+
+	return ret;
+}
+
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,low-pin-count",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..ba4a330 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -690,9 +690,18 @@ static int __of_address_to_resource(struct device_node *dev,
 	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;
+		/*
+		 * special processing for non-pci device gurantee the linux start pio
+		 * is not ZERO. Otherwise, some drivers' initialization will fail.
+		 */
+		if (!port && (!IS_ENABLED(CONFIG_OF_ADDRESS_PCI) ||
+				!of_bus_pci_match(dev)))
+			port += 1;
+
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
-- 
1.9.1

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

On Hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  35 ++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/hisi_lpc.c                             | 653 +++++++++++++++++++++
 drivers/of/address.c                               |   9 +
 5 files changed, 707 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..820e26d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,35 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #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 address and length of the register set for the device.
+- ranges: define a 1:1 mapping between the I/O space of the child device and
+	  the parent.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
+
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 3b205e2..fdb232b 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_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 ac84cc4..6ffbb27 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.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..9b364d0
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/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>
+
+
+struct hisilpc_dev;
+
+/* This flag is specific to differentiate earlycon operations and the others */
+#define FG_EARLYCON_LPC		0x0001
+/*
+ * this bit set means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x0002
+
+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 platform_device *pltdev;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+
+#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_SING	(0x00000008)
+#define LPC_CMD_SAMEADDR_INC	(0x00000000)
+#define LPC_CMD_TYPE_IO		(0x00000000)
+#define LPC_CMD_TYPE_MEM	(0x00000002)
+#define LPC_CMD_TYPE_FWH	(0x00000004)
+#define LPC_CMD_WRITE		(0x00000001)
+#define LPC_CMD_READ		(0x00000000)
+
+#define LPC_IRQ_CLEAR		(0x02)
+#define LPC_IRQ_OCCURRED	(0x02)
+
+#define LPC_STATUS_IDLE		(0x01)
+#define LPC_OP_FINISHED		(0x02)
+
+#define START_WORK		(0x01)
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * 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 specfic 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 = 0;
+
+	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 periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters 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 *pdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int retval;
+	/*initialized as 0 to remove compile warning */
+	unsigned long flags = 0;
+
+	if (!buf || !opcnt || !para || !pdev)
+		return -EINVAL;
+
+	if (para->csize != 1 || opcnt  > LPC_MAX_OPCNT)
+		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_SING;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	/* whole operation must be atomic */
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_lock_irqsave(&pdev->cycle_lock, flags);
+
+	writel(opcnt, pdev->membase + LPC_REG_OP_LEN);
+
+	writel(cmd_word, pdev->membase + LPC_REG_CMD);
+
+	writel(ptaddr, pdev->membase + LPC_REG_ADDR);
+
+	writel(START_WORK, pdev->membase + LPC_REG_START);
+
+	/* whether the operation is finished */
+	retval = wait_lpc_idle(pdev->membase, waitcnt);
+	if (!retval) {
+		for (; opcnt--; buf++)
+			*buf = readl(pdev->membase + LPC_REG_RDATA);
+	}
+
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_unlock_irqrestore(&pdev->cycle_lock, flags);
+
+	return retval;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters 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 *pdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int retval;
+	/* initialized as 0 to remove compile warning */
+	unsigned long flags = 0;
+
+
+	if (!buf || !opcnt || !para || !pdev)
+		return -EINVAL;
+
+	if (para->csize != 1 || opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR_SING;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	/* whole operation must be atomic */
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_lock_irqsave(&pdev->cycle_lock, flags);
+
+	writel(opcnt, pdev->membase + LPC_REG_OP_LEN);
+	for (; opcnt--; buf++)
+		writel(*buf, pdev->membase + LPC_REG_WDATA);
+
+	writel(cmd_word, pdev->membase + LPC_REG_CMD);
+
+	writel(ptaddr, pdev->membase + LPC_REG_ADDR);
+
+	writel(START_WORK, pdev->membase + LPC_REG_START);
+
+	/* whether the operation is finished */
+	retval = wait_lpc_idle(pdev->membase, waitcnt);
+
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_unlock_irqrestore(&pdev->cycle_lock, flags);
+
+	return retval;
+}
+
+/**
+ * hisilpc_comm_inb - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outbuf: a buffer where the data read is stored at.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ * @count: how many I/O operations required in this calling.  >1 is for ins.
+ *
+ * For this lpc, only support inb/insb now.
+ *
+ * For inbs, returns 0 on success, -1 on fail.
+ * 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.
+ */
+u64 hisilpc_comm_inb(void *devobj, unsigned long ptaddr,
+				void *inbuf, size_t dlen,
+				unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned int loopcnt, cntleft;
+	unsigned int rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+	/* only support data unit length is 1 now... */
+	if (!count || (!inbuf && count != 1) || !devobj || dlen != 1)
+		return -1;
+
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * the operation data len is 4 bytes, need to ensure the buffer
+	 * is big enough.
+	 */
+	if (!inbuf || count < sizeof(u32))
+		newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	dev_dbg(&lpcdev->pltdev->dev, "In-IO(0x%lx), count=%u\n", ptaddr,
+			count);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	/*
+	 * to improve performance, support repeatly rd at same target
+	 * address.
+	 */
+	if (count > 1)
+		iopara.opflags &= ~FG_INCRADDR_LPC;
+
+	iopara.csize = dlen;
+
+	cntleft = count;
+	do {
+		loopcnt = (cntleft > LPC_MAX_OPCNT) ? LPC_MAX_OPCNT : cntleft;
+		ret = hisilpc_target_in(lpcdev,
+				&iopara, ptaddr, newbuf, loopcnt);
+		if (ret)
+			return -1;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	/* for inb */
+	if (!inbuf)
+		return rd_data;
+	/* for insb, copy the data to the return variable */
+	if (inbuf != newbuf)
+		memcpy(inbuf, &rd_data, count);
+
+	return 0;
+}
+
+/**
+ * hisilpc_comm_outb - write/output the data in out buffer to the I/O peripheral
+ *		    through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outbuf: a buffer where the data to be written is stored.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many I/O operations required in this calling. >1 is for outs.
+ *
+ * For this lpc, only support outb/outsb now.
+ *
+ */
+void hisilpc_comm_outb(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned int loopcnt;
+	const unsigned char *newbuf;
+	int ret = 0;
+
+	if (!count || !outbuf || !devobj)
+		return;
+
+	newbuf = (const unsigned char *)outbuf;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	dev_dbg(&lpcdev->pltdev->dev, "Out-IO(0x%lx), cnt=%u\n", ptaddr, count);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	/* to improve performance,  support repeatly wr same target address */
+	if (count > 1)
+		iopara.opflags &= ~FG_INCRADDR_LPC;
+
+	iopara.csize = 1;
+
+	do {
+		loopcnt = (count > LPC_MAX_OPCNT) ? LPC_MAX_OPCNT : count;
+		ret = hisilpc_target_out(lpcdev,
+				&iopara, ptaddr, newbuf, loopcnt);
+		if (ret)
+			return;
+		newbuf += loopcnt;
+		count -= loopcnt;
+	} while (count);
+}
+
+
+/**
+ * hisilpc_ischild_ipmi - check whether the designated device is ipmi
+ * @dev: the device to be checked.
+ * @data: the value used to match the acpi device in checking.
+ *
+ * Returns 1 means the device to be checked is matched.
+ * 0 means some failures.
+ *
+ */
+static int  hisilpc_ischild_ipmi(struct device *dev)
+{
+	struct acpi_device *adev;
+	struct acpi_hardware_id *hwid;
+	/* only support dts and acpi */
+	if (IS_ERR_OR_NULL(dev->fwnode) && !dev->of_node) {
+		dev_err(dev, "Not valid child device!\n");
+		return -EINVAL;
+	}
+
+	adev = ACPI_COMPANION(dev);
+	if (adev) {
+		list_for_each_entry(hwid, &adev->pnp.ids, list) {
+			dev_info(dev, "hwid is %s\n", hwid->id);
+			if (!strcmp("IPI0001", hwid->id))
+				return 1;
+		}
+	} else {
+		if (!strcmp(dev->of_node->type, "ipmi"))
+			return 1;
+	}
+
+	dev_info(dev, "not ipmi child device!\n");
+	return 0;
+}
+
+
+/**
+ * hisilpc_children_map_sysio - setup the mapping between system Io and
+ *			physical IO
+ *
+ * @child: the device whose IO is handling
+ * @data: some device specific data. For ACPI device, should be NULL.
+ *
+ * Returns >=0 means the mapping is successfully created;
+ * others mean some failures.
+ */
+static int hisilpc_children_map_sysio(struct device * child, void * data)
+{
+	struct resource *iores;
+	unsigned long cpuio;
+	struct extio_ops *opsnode;
+	int ret;
+	struct hisilpc_dev *lpcdev;
+
+	if (!child || !child->parent)
+		return -EINVAL;
+
+	iores = platform_get_resource_byname(to_platform_device(child),
+					IORESOURCE_IO, "dev_io");
+	if (!iores)
+		return -ENODEV;
+
+	/*
+	 * can not use devm_kzalloc to allocate slab for child before its driver
+	 * start probing. Here allocate the slab with the name of parent.
+	 */
+	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
+	if (!opsnode)
+		return -ENOMEM;
+
+	cpuio = data ? *((unsigned long *)data) : 0;
+
+	opsnode->start = iores->start;
+	opsnode->end = iores->end;
+	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
+
+	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
+				(unsigned long)iores->start,
+				(unsigned long)iores->end,
+				opsnode->ptoffset);
+
+	opsnode->pfin = hisilpc_comm_inb;
+	opsnode->pfout = hisilpc_comm_outb;
+
+	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
+	opsnode->devpara = lpcdev;
+
+	/* only apply indirect-IO to ipmi child device */
+	ret = hisilpc_ischild_ipmi(child);
+	if (ret < 0)
+		return ret;
+
+	if (ret > 0) {
+		WRITE_ONCE(arm64_extio_ops, opsnode);
+		/* update ret as successful */
+		ret = 0;
+	} else {
+		ret = platform_device_add_data(to_platform_device(child),
+						opsnode,
+						sizeof(*opsnode));
+		devm_kfree(child->parent, opsnode);
+	}
+
+	if (!ret)
+		dev_info(child, "to phy [%lx-%lx]\n", cpuio,
+			(unsigned long)(iores->end - iores->start) + cpuio);
+	else
+		dev_info(child, "FAIL(0x%x)!!\n", ret);
+
+	return ret;
+}
+
+/**
+ * of_hisilpc_register_pio - register the deivce physical IO address into
+ *			io_range_list
+ *
+ * Returns >=0 means ok.
+ * others mean some failures.
+ */
+static int of_hisilpc_register_pio(struct device_node *dev,
+					unsigned long *phyport)
+{
+	static int isfirst = 0;
+	const __be32	*addrp;
+	u64		size;
+	unsigned int	flags;
+	u64	taddr;
+	int residx = 0;
+
+
+	if (!dev || !phyport)
+		return -EINVAL;
+	/* only one IO reg exists */
+	do {
+		addrp = of_get_address(dev, residx, &size, &flags);
+		if (addrp == NULL) {
+			pr_err("%s:: get OF address(%d) FAIL!\n",
+				dev->name, residx);
+			return -EINVAL;
+		}
+		residx++;
+	} while(!(flags & IORESOURCE_IO));
+
+
+	taddr = of_translate_address(dev, addrp);
+	if (taddr == OF_BAD_ADDR) {
+		pr_err("%s:: translate IO address fail\n", dev->name);
+		return -EINVAL;
+	}
+
+	/* register one more IO byte for the first register */
+	if (!isfirst) {
+		size += 1;
+		isfirst = 1;
+	}
+
+	if (pci_register_io_range(taddr, size)) {
+		pr_err("%s::register physical range[%llx, %llx) FAIL!\n",
+			dev->name, taddr, size);
+		return -ENXIO;
+	}
+
+	pr_info("%s:: register physical range[%llx, %llx) OK\n",
+			dev->name, taddr, size);
+
+	*phyport = taddr;
+
+	return 0;
+}
+
+/**
+ * hisilpc_probe_child_dev - setup the mapping between linux IO and
+ *			physical IO for all children under hisilpc
+ *
+ * @ppdev: point to the hisilpc device
+ *
+ * Returns =0 means ok.
+ * others mean some failures.
+ */
+static int hisilpc_probe_child_dev(struct device *ppdev)
+{
+	int ret;
+
+	if (!ppdev)
+		return -EINVAL;
+
+	ret = 0;
+	/* for device tree, scan the child devices now */
+	if (!has_acpi_companion(ppdev)) {
+		struct device_node *root, *child;
+
+		root = ppdev->of_node;
+		for_each_available_child_of_node(root, child) {
+			struct platform_device *ptdev;
+			unsigned long cpuio;
+
+			/* register the IO range configured in dt */
+			ret = of_hisilpc_register_pio(child, &cpuio);
+			if (ret) {
+				dev_err(ppdev, "fail to register raw IO for %s\n",
+						child->name);
+				return ret;
+			}
+
+			ptdev = of_platform_device_create(child, NULL, ppdev);
+			if (!ptdev) {
+				dev_err(ppdev, "create platform device fail for %s\n",
+					child->name);
+				return -EFAULT;
+			}
+
+			ret = hisilpc_children_map_sysio(&ptdev->dev, &cpuio);
+			if (ret)
+				dev_err(&ptdev->dev, "Mapping sysio for dts child devices FAIL\n");
+		}
+	} else {
+		ret = device_for_each_child(ppdev, NULL,
+					hisilpc_children_map_sysio);
+		if (ret)
+			dev_err(ppdev, "Mapping sysio for ACPI child devices FAIL\n");
+	}
+
+	return ret;
+}
+
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @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 resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "hslpc start probing...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "No mem resource\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	lpcdev->pltdev = pdev;
+	platform_set_drvdata(pdev, lpcdev);
+
+	ret = hisilpc_probe_child_dev(&pdev->dev);
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc finish probing...\n");
+	else
+		dev_err(&pdev->dev, "hslpc probe got fail(%d)!\n", -ret);
+
+	return ret;
+}
+
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,low-pin-count",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..ba4a330 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -690,9 +690,18 @@ static int __of_address_to_resource(struct device_node *dev,
 	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;
+		/*
+		 * special processing for non-pci device gurantee the linux start pio
+		 * is not ZERO. Otherwise, some drivers' initialization will fail.
+		 */
+		if (!port && (!IS_ENABLED(CONFIG_OF_ADDRESS_PCI) ||
+				!of_bus_pci_match(dev)))
+			port += 1;
+
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
-- 
1.9.1

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

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

On Hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  35 ++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   2 +
 drivers/bus/hisi_lpc.c                             | 653 +++++++++++++++++++++
 drivers/of/address.c                               |   9 +
 5 files changed, 707 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..820e26d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,35 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #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 address and length of the register set for the device.
+- ranges: define a 1:1 mapping between the I/O space of the child device and
+	  the parent.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa at a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
+
+
+	ipmi0: bt at e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 3b205e2..fdb232b 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_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 ac84cc4..6ffbb27 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.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..9b364d0
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/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>
+
+
+struct hisilpc_dev;
+
+/* This flag is specific to differentiate earlycon operations and the others */
+#define FG_EARLYCON_LPC		0x0001
+/*
+ * this bit set means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x0002
+
+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 platform_device *pltdev;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+
+#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_SING	(0x00000008)
+#define LPC_CMD_SAMEADDR_INC	(0x00000000)
+#define LPC_CMD_TYPE_IO		(0x00000000)
+#define LPC_CMD_TYPE_MEM	(0x00000002)
+#define LPC_CMD_TYPE_FWH	(0x00000004)
+#define LPC_CMD_WRITE		(0x00000001)
+#define LPC_CMD_READ		(0x00000000)
+
+#define LPC_IRQ_CLEAR		(0x02)
+#define LPC_IRQ_OCCURRED	(0x02)
+
+#define LPC_STATUS_IDLE		(0x01)
+#define LPC_OP_FINISHED		(0x02)
+
+#define START_WORK		(0x01)
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * 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 specfic 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 = 0;
+
+	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 periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters 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 *pdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int retval;
+	/*initialized as 0 to remove compile warning */
+	unsigned long flags = 0;
+
+	if (!buf || !opcnt || !para || !pdev)
+		return -EINVAL;
+
+	if (para->csize != 1 || opcnt  > LPC_MAX_OPCNT)
+		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_SING;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	/* whole operation must be atomic */
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_lock_irqsave(&pdev->cycle_lock, flags);
+
+	writel(opcnt, pdev->membase + LPC_REG_OP_LEN);
+
+	writel(cmd_word, pdev->membase + LPC_REG_CMD);
+
+	writel(ptaddr, pdev->membase + LPC_REG_ADDR);
+
+	writel(START_WORK, pdev->membase + LPC_REG_START);
+
+	/* whether the operation is finished */
+	retval = wait_lpc_idle(pdev->membase, waitcnt);
+	if (!retval) {
+		for (; opcnt--; buf++)
+			*buf = readl(pdev->membase + LPC_REG_RDATA);
+	}
+
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_unlock_irqrestore(&pdev->cycle_lock, flags);
+
+	return retval;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters 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 *pdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int retval;
+	/* initialized as 0 to remove compile warning */
+	unsigned long flags = 0;
+
+
+	if (!buf || !opcnt || !para || !pdev)
+		return -EINVAL;
+
+	if (para->csize != 1 || opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR_SING;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	/* whole operation must be atomic */
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_lock_irqsave(&pdev->cycle_lock, flags);
+
+	writel(opcnt, pdev->membase + LPC_REG_OP_LEN);
+	for (; opcnt--; buf++)
+		writel(*buf, pdev->membase + LPC_REG_WDATA);
+
+	writel(cmd_word, pdev->membase + LPC_REG_CMD);
+
+	writel(ptaddr, pdev->membase + LPC_REG_ADDR);
+
+	writel(START_WORK, pdev->membase + LPC_REG_START);
+
+	/* whether the operation is finished */
+	retval = wait_lpc_idle(pdev->membase, waitcnt);
+
+	if (!(para->opflags & FG_EARLYCON_LPC))
+		spin_unlock_irqrestore(&pdev->cycle_lock, flags);
+
+	return retval;
+}
+
+/**
+ * hisilpc_comm_inb - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outbuf: a buffer where the data read is stored at.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ * @count: how many I/O operations required in this calling.  >1 is for ins.
+ *
+ * For this lpc, only support inb/insb now.
+ *
+ * For inbs, returns 0 on success, -1 on fail.
+ * 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.
+ */
+u64 hisilpc_comm_inb(void *devobj, unsigned long ptaddr,
+				void *inbuf, size_t dlen,
+				unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned int loopcnt, cntleft;
+	unsigned int rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+	/* only support data unit length is 1 now... */
+	if (!count || (!inbuf && count != 1) || !devobj || dlen != 1)
+		return -1;
+
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * the operation data len is 4 bytes, need to ensure the buffer
+	 * is big enough.
+	 */
+	if (!inbuf || count < sizeof(u32))
+		newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	dev_dbg(&lpcdev->pltdev->dev, "In-IO(0x%lx), count=%u\n", ptaddr,
+			count);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	/*
+	 * to improve performance, support repeatly rd at same target
+	 * address.
+	 */
+	if (count > 1)
+		iopara.opflags &= ~FG_INCRADDR_LPC;
+
+	iopara.csize = dlen;
+
+	cntleft = count;
+	do {
+		loopcnt = (cntleft > LPC_MAX_OPCNT) ? LPC_MAX_OPCNT : cntleft;
+		ret = hisilpc_target_in(lpcdev,
+				&iopara, ptaddr, newbuf, loopcnt);
+		if (ret)
+			return -1;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	/* for inb */
+	if (!inbuf)
+		return rd_data;
+	/* for insb, copy the data to the return variable */
+	if (inbuf != newbuf)
+		memcpy(inbuf, &rd_data, count);
+
+	return 0;
+}
+
+/**
+ * hisilpc_comm_outb - write/output the data in out buffer to the I/O peripheral
+ *		    through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outbuf: a buffer where the data to be written is stored.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many I/O operations required in this calling. >1 is for outs.
+ *
+ * For this lpc, only support outb/outsb now.
+ *
+ */
+void hisilpc_comm_outb(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned int loopcnt;
+	const unsigned char *newbuf;
+	int ret = 0;
+
+	if (!count || !outbuf || !devobj)
+		return;
+
+	newbuf = (const unsigned char *)outbuf;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	dev_dbg(&lpcdev->pltdev->dev, "Out-IO(0x%lx), cnt=%u\n", ptaddr, count);
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	/* to improve performance,  support repeatly wr same target address */
+	if (count > 1)
+		iopara.opflags &= ~FG_INCRADDR_LPC;
+
+	iopara.csize = 1;
+
+	do {
+		loopcnt = (count > LPC_MAX_OPCNT) ? LPC_MAX_OPCNT : count;
+		ret = hisilpc_target_out(lpcdev,
+				&iopara, ptaddr, newbuf, loopcnt);
+		if (ret)
+			return;
+		newbuf += loopcnt;
+		count -= loopcnt;
+	} while (count);
+}
+
+
+/**
+ * hisilpc_ischild_ipmi - check whether the designated device is ipmi
+ * @dev: the device to be checked.
+ * @data: the value used to match the acpi device in checking.
+ *
+ * Returns 1 means the device to be checked is matched.
+ * 0 means some failures.
+ *
+ */
+static int  hisilpc_ischild_ipmi(struct device *dev)
+{
+	struct acpi_device *adev;
+	struct acpi_hardware_id *hwid;
+	/* only support dts and acpi */
+	if (IS_ERR_OR_NULL(dev->fwnode) && !dev->of_node) {
+		dev_err(dev, "Not valid child device!\n");
+		return -EINVAL;
+	}
+
+	adev = ACPI_COMPANION(dev);
+	if (adev) {
+		list_for_each_entry(hwid, &adev->pnp.ids, list) {
+			dev_info(dev, "hwid is %s\n", hwid->id);
+			if (!strcmp("IPI0001", hwid->id))
+				return 1;
+		}
+	} else {
+		if (!strcmp(dev->of_node->type, "ipmi"))
+			return 1;
+	}
+
+	dev_info(dev, "not ipmi child device!\n");
+	return 0;
+}
+
+
+/**
+ * hisilpc_children_map_sysio - setup the mapping between system Io and
+ *			physical IO
+ *
+ * @child: the device whose IO is handling
+ * @data: some device specific data. For ACPI device, should be NULL.
+ *
+ * Returns >=0 means the mapping is successfully created;
+ * others mean some failures.
+ */
+static int hisilpc_children_map_sysio(struct device * child, void * data)
+{
+	struct resource *iores;
+	unsigned long cpuio;
+	struct extio_ops *opsnode;
+	int ret;
+	struct hisilpc_dev *lpcdev;
+
+	if (!child || !child->parent)
+		return -EINVAL;
+
+	iores = platform_get_resource_byname(to_platform_device(child),
+					IORESOURCE_IO, "dev_io");
+	if (!iores)
+		return -ENODEV;
+
+	/*
+	 * can not use devm_kzalloc to allocate slab for child before its driver
+	 * start probing. Here allocate the slab with the name of parent.
+	 */
+	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
+	if (!opsnode)
+		return -ENOMEM;
+
+	cpuio = data ? *((unsigned long *)data) : 0;
+
+	opsnode->start = iores->start;
+	opsnode->end = iores->end;
+	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
+
+	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
+				(unsigned long)iores->start,
+				(unsigned long)iores->end,
+				opsnode->ptoffset);
+
+	opsnode->pfin = hisilpc_comm_inb;
+	opsnode->pfout = hisilpc_comm_outb;
+
+	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
+	opsnode->devpara = lpcdev;
+
+	/* only apply indirect-IO to ipmi child device */
+	ret = hisilpc_ischild_ipmi(child);
+	if (ret < 0)
+		return ret;
+
+	if (ret > 0) {
+		WRITE_ONCE(arm64_extio_ops, opsnode);
+		/* update ret as successful */
+		ret = 0;
+	} else {
+		ret = platform_device_add_data(to_platform_device(child),
+						opsnode,
+						sizeof(*opsnode));
+		devm_kfree(child->parent, opsnode);
+	}
+
+	if (!ret)
+		dev_info(child, "to phy [%lx-%lx]\n", cpuio,
+			(unsigned long)(iores->end - iores->start) + cpuio);
+	else
+		dev_info(child, "FAIL(0x%x)!!\n", ret);
+
+	return ret;
+}
+
+/**
+ * of_hisilpc_register_pio - register the deivce physical IO address into
+ *			io_range_list
+ *
+ * Returns >=0 means ok.
+ * others mean some failures.
+ */
+static int of_hisilpc_register_pio(struct device_node *dev,
+					unsigned long *phyport)
+{
+	static int isfirst = 0;
+	const __be32	*addrp;
+	u64		size;
+	unsigned int	flags;
+	u64	taddr;
+	int residx = 0;
+
+
+	if (!dev || !phyport)
+		return -EINVAL;
+	/* only one IO reg exists */
+	do {
+		addrp = of_get_address(dev, residx, &size, &flags);
+		if (addrp == NULL) {
+			pr_err("%s:: get OF address(%d) FAIL!\n",
+				dev->name, residx);
+			return -EINVAL;
+		}
+		residx++;
+	} while(!(flags & IORESOURCE_IO));
+
+
+	taddr = of_translate_address(dev, addrp);
+	if (taddr == OF_BAD_ADDR) {
+		pr_err("%s:: translate IO address fail\n", dev->name);
+		return -EINVAL;
+	}
+
+	/* register one more IO byte for the first register */
+	if (!isfirst) {
+		size += 1;
+		isfirst = 1;
+	}
+
+	if (pci_register_io_range(taddr, size)) {
+		pr_err("%s::register physical range[%llx, %llx) FAIL!\n",
+			dev->name, taddr, size);
+		return -ENXIO;
+	}
+
+	pr_info("%s:: register physical range[%llx, %llx) OK\n",
+			dev->name, taddr, size);
+
+	*phyport = taddr;
+
+	return 0;
+}
+
+/**
+ * hisilpc_probe_child_dev - setup the mapping between linux IO and
+ *			physical IO for all children under hisilpc
+ *
+ * @ppdev: point to the hisilpc device
+ *
+ * Returns =0 means ok.
+ * others mean some failures.
+ */
+static int hisilpc_probe_child_dev(struct device *ppdev)
+{
+	int ret;
+
+	if (!ppdev)
+		return -EINVAL;
+
+	ret = 0;
+	/* for device tree, scan the child devices now */
+	if (!has_acpi_companion(ppdev)) {
+		struct device_node *root, *child;
+
+		root = ppdev->of_node;
+		for_each_available_child_of_node(root, child) {
+			struct platform_device *ptdev;
+			unsigned long cpuio;
+
+			/* register the IO range configured in dt */
+			ret = of_hisilpc_register_pio(child, &cpuio);
+			if (ret) {
+				dev_err(ppdev, "fail to register raw IO for %s\n",
+						child->name);
+				return ret;
+			}
+
+			ptdev = of_platform_device_create(child, NULL, ppdev);
+			if (!ptdev) {
+				dev_err(ppdev, "create platform device fail for %s\n",
+					child->name);
+				return -EFAULT;
+			}
+
+			ret = hisilpc_children_map_sysio(&ptdev->dev, &cpuio);
+			if (ret)
+				dev_err(&ptdev->dev, "Mapping sysio for dts child devices FAIL\n");
+		}
+	} else {
+		ret = device_for_each_child(ppdev, NULL,
+					hisilpc_children_map_sysio);
+		if (ret)
+			dev_err(ppdev, "Mapping sysio for ACPI child devices FAIL\n");
+	}
+
+	return ret;
+}
+
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @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 resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "hslpc start probing...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "No mem resource\n");
+		return PTR_ERR(lpcdev->membase);
+	}
+
+	lpcdev->pltdev = pdev;
+	platform_set_drvdata(pdev, lpcdev);
+
+	ret = hisilpc_probe_child_dev(&pdev->dev);
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc finish probing...\n");
+	else
+		dev_err(&pdev->dev, "hslpc probe got fail(%d)!\n", -ret);
+
+	return ret;
+}
+
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,low-pin-count",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..ba4a330 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -690,9 +690,18 @@ static int __of_address_to_resource(struct device_node *dev,
 	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;
+		/*
+		 * special processing for non-pci device gurantee the linux start pio
+		 * is not ZERO. Otherwise, some drivers' initialization will fail.
+		 */
+		if (!port && (!IS_ENABLED(CONFIG_OF_ADDRESS_PCI) ||
+				!of_bus_pci_match(dev)))
+			port += 1;
+
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
-- 
1.9.1

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
  2016-09-14 12:15 ` Zhichang Yuan
  (?)
@ 2016-09-14 12:15   ` Zhichang Yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
controlled through the LPC I/O cycles. After registering the LPC uart specific
serial_in/serial_out to 8250 core driver, serial data can be read/written
through the LPC.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 .../devicetree/bindings/serial/hisi-lpc-uart.txt   |  60 ++++++++
 drivers/tty/serial/8250/8250_hisi_lpc.c            | 171 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |   9 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 4 files changed, 241 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt b/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
new file mode 100644
index 0000000..0f8ec2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
@@ -0,0 +1,60 @@
+* Hisilicon hip06 UART through low-pin-count
+
+Required properties:
+- compatible : "hisilicon,lpc-uart"
+- reg : offset and length of the I/O port set for the device.
+- reg-names : name the uart resources.
+		"lpc_mem" represents memory resource of the LPC parent. When
+		flat-tree earlycon is needed, this memory resource and
+		resource name are mandatory. Otherwise they are optional;
+		"dev_io" represents I/O resource of this device. It is
+		mandatory to access this device;
+
+Clock handling:
+  The clock rate of this device is same as the 8250 default clock rate, that
+  is 1843200. No need to define the clock rate in device tree.
+
+Note:
+  This device depends on its parent device whose compatible string is
+  "hisilicon,low-pin-count".
+
+  The format of "reg" property follows the I/O space definition in ISA/EISA
+  binding specification linked to:
+  http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
+
+Example:
+
+	uart0: lpc-uart@2f8 {
+		compatible = "hisilicon,lpc-uart";
+		reg = <0x01 0x2f8 0x08>;
+		status = "disabled";
+	};
+
+
+Example with low-pin-count parent device:
+
+	isa@a01b0000 {
+		compatible = "hisilicon,low-pin-count";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0x0 0xa01b0000 0x0 0x1000>;
+		ranges = <0x00 0xa01b0000 0x00 0xa01b0000 0x1000>,
+			<0x01 0xe4 0x0 0xe4 0x04>,
+			<0x01 0x2f8 0x0 0x2f8 0x08>;
+
+		ipmi0: bt@e4 {
+			compatible = "ipmi-bt";
+			device_type = "ipmi";
+			reg = <0x01 0xe4 0x04>;
+			reg-names = "dev_io";
+			status = "disabled";
+		};
+
+		uart0: lpc-uart@2f8 {
+			compatible = "hisilicon,lpc-uart";
+			reg =  <0x00 0xa01b0000 0x1000>,
+				<0x01 0x2f8 0x08>;
+			ret-names = "lpc_mem", "dev_io";
+			status = "disabled";
+		};
+	};
diff --git a/drivers/tty/serial/8250/8250_hisi_lpc.c b/drivers/tty/serial/8250/8250_hisi_lpc.c
new file mode 100644
index 0000000..a8ba1ca
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_hisi_lpc.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/module.h>
+#include <linux/acpi.h>
+#include <linux/serial_8250.h>
+#include <asm-generic/serial.h>
+#include <linux/of_address.h>
+
+
+/**
+ * hisilpc_serial_inb - read/input data from the designated serial port.
+ * @p: the serial port where the data read from
+ * @offset:  the target I/O port address where the read is from
+ *
+ * Returns the byte data from this serial port.
+ * -1 means some failures.
+ *
+ */
+static unsigned int hisilpc_serial_inb(struct uart_port *p, int offset)
+{
+	struct extio_ops *parentops;
+
+	parentops = p->private_data;
+	if (!parentops || !parentops->pfin)
+		return -1;
+
+	return parentops->pfin(parentops->devpara,
+				p->iobase + (offset << p->regshift),
+				NULL, sizeof(u8), 1);
+}
+
+/**
+ * hisilpc_serial_outb - write/output data from the designated serial port.
+ * @p: the serial port where the data is written to
+ * @offset:  the target I/O port address where the write is from
+ *
+ */
+static void hisilpc_serial_outb(struct uart_port *p, int offset, int value)
+{
+	struct extio_ops *parentops;
+
+	parentops = p->private_data;
+	if (!parentops || !parentops->pfout)
+		return;
+
+	parentops->pfout(parentops->devpara,
+				p->iobase + (offset << p->regshift),
+				&value, sizeof(u8), 1);
+}
+
+
+static int hisilpc8250_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct uart_port *port = &uart.port;
+	int err = 0;
+	struct resource *iores;
+	struct extio_ops *platdata;
+
+	if (!pdev->dev.parent)
+		return -ENODEV;
+	dev_info(&pdev->dev, "##probe entering\n");
+
+	/* To support the earlycon in bootargs, the first reg must be MEM */
+	iores = platform_get_resource_byname(pdev, IORESOURCE_IO,
+						"dev_io");
+	if (!iores) {
+		dev_err(&pdev->dev, "can not find the IO0\n");
+		return -ENXIO;
+	}
+
+	/*
+	 * save the platform data from parent in uart_port for serial_in,
+	 * serial_out
+	 */
+	platdata = dev_get_platdata(&pdev->dev);
+	port->private_data = (void *)platdata;
+	if (!port->private_data) {
+		dev_err(&pdev->dev, "no platform data!\n");
+		return -ENODEV;
+	}
+
+	if (platdata->start != iores->start || platdata->end != iores->end) {
+		dev_err(&pdev->dev, "PIO range[0x%lx - %lx] isn't fit!\n",
+			(unsigned long)iores->start,
+			(unsigned long)iores->end);
+		return -ENXIO;
+	}
+	port->iobase = (unsigned long)iores->start + platdata->ptoffset;
+	dev_info(&pdev->dev, "real port start is 0x%lx\n", port->iobase);
+
+	port->irq	= 0;
+	port->flags	= UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
+	port->dev	= &pdev->dev;
+	port->iotype	= UPIO_PORT;
+	port->regshift	= 0;
+	port->uartclk	= BASE_BAUD * 16;
+
+	spin_lock_init(&port->lock);
+
+	port->serial_in = hisilpc_serial_inb;
+	port->serial_out = hisilpc_serial_outb;
+
+	err = serial8250_register_8250_port(&uart);
+	if (err < 0) {
+		dev_err(&pdev->dev, "register uart FAIL(%d)!\n", -err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, (void *)&err);
+	dev_info(&pdev->dev, "##probing OK(%d)\n", err);
+	return 0;
+}
+
+static int hisilpc8250_remove(struct platform_device *pdev)
+{
+	int line = *((int *)platform_get_drvdata(pdev));
+
+	serial8250_unregister_port(line);
+
+	return 0;
+}
+
+
+static const struct of_device_id hs8250_of_match[] = {
+	{ .compatible = "hisilicon,lpc-uart" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hs8250_of_match);
+
+static const struct acpi_device_id hs8250_acpi_match[] = {
+	/*{ "PNP0501", 0 },*/
+	{ "HISI1031", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, hs8250_acpi_match);
+
+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe			= hisilpc8250_probe,
+	.remove			= hisilpc8250_remove,
+};
+
+module_platform_driver(hs_lpc8250_driver);
+
+
+MODULE_AUTHOR("Rongrong Zou");
+MODULE_DESCRIPTION("8250 serial probe module for Hisilicon LPC UART");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("v1.0");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 7c6f7af..c2e42f7 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -246,6 +246,15 @@ config SERIAL_8250_HUB6
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8250_hub6.
 
+config SERIAL_8250_HISI_LPC
+	tristate "Support Hisilicon Hip0X UART through LPC"
+	depends on SERIAL_8250 !=n && HISILICON_LPC
+	help
+	  Say Y here if you have a hip06 board.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called 8250_hisi_lpc.
+
 #
 # Misc. options/drivers.
 #
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 367d403..1f2915b 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
+obj-$(CONFIG_SERIAL_8250_HISI_LPC)	+= 8250_hisi_lpc.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
-- 
1.9.1

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
controlled through the LPC I/O cycles. After registering the LPC uart specific
serial_in/serial_out to 8250 core driver, serial data can be read/written
through the LPC.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 .../devicetree/bindings/serial/hisi-lpc-uart.txt   |  60 ++++++++
 drivers/tty/serial/8250/8250_hisi_lpc.c            | 171 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |   9 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 4 files changed, 241 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt b/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
new file mode 100644
index 0000000..0f8ec2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
@@ -0,0 +1,60 @@
+* Hisilicon hip06 UART through low-pin-count
+
+Required properties:
+- compatible : "hisilicon,lpc-uart"
+- reg : offset and length of the I/O port set for the device.
+- reg-names : name the uart resources.
+		"lpc_mem" represents memory resource of the LPC parent. When
+		flat-tree earlycon is needed, this memory resource and
+		resource name are mandatory. Otherwise they are optional;
+		"dev_io" represents I/O resource of this device. It is
+		mandatory to access this device;
+
+Clock handling:
+  The clock rate of this device is same as the 8250 default clock rate, that
+  is 1843200. No need to define the clock rate in device tree.
+
+Note:
+  This device depends on its parent device whose compatible string is
+  "hisilicon,low-pin-count".
+
+  The format of "reg" property follows the I/O space definition in ISA/EISA
+  binding specification linked to:
+  http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
+
+Example:
+
+	uart0: lpc-uart@2f8 {
+		compatible = "hisilicon,lpc-uart";
+		reg = <0x01 0x2f8 0x08>;
+		status = "disabled";
+	};
+
+
+Example with low-pin-count parent device:
+
+	isa@a01b0000 {
+		compatible = "hisilicon,low-pin-count";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0x0 0xa01b0000 0x0 0x1000>;
+		ranges = <0x00 0xa01b0000 0x00 0xa01b0000 0x1000>,
+			<0x01 0xe4 0x0 0xe4 0x04>,
+			<0x01 0x2f8 0x0 0x2f8 0x08>;
+
+		ipmi0: bt@e4 {
+			compatible = "ipmi-bt";
+			device_type = "ipmi";
+			reg = <0x01 0xe4 0x04>;
+			reg-names = "dev_io";
+			status = "disabled";
+		};
+
+		uart0: lpc-uart@2f8 {
+			compatible = "hisilicon,lpc-uart";
+			reg =  <0x00 0xa01b0000 0x1000>,
+				<0x01 0x2f8 0x08>;
+			ret-names = "lpc_mem", "dev_io";
+			status = "disabled";
+		};
+	};
diff --git a/drivers/tty/serial/8250/8250_hisi_lpc.c b/drivers/tty/serial/8250/8250_hisi_lpc.c
new file mode 100644
index 0000000..a8ba1ca
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_hisi_lpc.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/module.h>
+#include <linux/acpi.h>
+#include <linux/serial_8250.h>
+#include <asm-generic/serial.h>
+#include <linux/of_address.h>
+
+
+/**
+ * hisilpc_serial_inb - read/input data from the designated serial port.
+ * @p: the serial port where the data read from
+ * @offset:  the target I/O port address where the read is from
+ *
+ * Returns the byte data from this serial port.
+ * -1 means some failures.
+ *
+ */
+static unsigned int hisilpc_serial_inb(struct uart_port *p, int offset)
+{
+	struct extio_ops *parentops;
+
+	parentops = p->private_data;
+	if (!parentops || !parentops->pfin)
+		return -1;
+
+	return parentops->pfin(parentops->devpara,
+				p->iobase + (offset << p->regshift),
+				NULL, sizeof(u8), 1);
+}
+
+/**
+ * hisilpc_serial_outb - write/output data from the designated serial port.
+ * @p: the serial port where the data is written to
+ * @offset:  the target I/O port address where the write is from
+ *
+ */
+static void hisilpc_serial_outb(struct uart_port *p, int offset, int value)
+{
+	struct extio_ops *parentops;
+
+	parentops = p->private_data;
+	if (!parentops || !parentops->pfout)
+		return;
+
+	parentops->pfout(parentops->devpara,
+				p->iobase + (offset << p->regshift),
+				&value, sizeof(u8), 1);
+}
+
+
+static int hisilpc8250_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct uart_port *port = &uart.port;
+	int err = 0;
+	struct resource *iores;
+	struct extio_ops *platdata;
+
+	if (!pdev->dev.parent)
+		return -ENODEV;
+	dev_info(&pdev->dev, "##probe entering\n");
+
+	/* To support the earlycon in bootargs, the first reg must be MEM */
+	iores = platform_get_resource_byname(pdev, IORESOURCE_IO,
+						"dev_io");
+	if (!iores) {
+		dev_err(&pdev->dev, "can not find the IO0\n");
+		return -ENXIO;
+	}
+
+	/*
+	 * save the platform data from parent in uart_port for serial_in,
+	 * serial_out
+	 */
+	platdata = dev_get_platdata(&pdev->dev);
+	port->private_data = (void *)platdata;
+	if (!port->private_data) {
+		dev_err(&pdev->dev, "no platform data!\n");
+		return -ENODEV;
+	}
+
+	if (platdata->start != iores->start || platdata->end != iores->end) {
+		dev_err(&pdev->dev, "PIO range[0x%lx - %lx] isn't fit!\n",
+			(unsigned long)iores->start,
+			(unsigned long)iores->end);
+		return -ENXIO;
+	}
+	port->iobase = (unsigned long)iores->start + platdata->ptoffset;
+	dev_info(&pdev->dev, "real port start is 0x%lx\n", port->iobase);
+
+	port->irq	= 0;
+	port->flags	= UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
+	port->dev	= &pdev->dev;
+	port->iotype	= UPIO_PORT;
+	port->regshift	= 0;
+	port->uartclk	= BASE_BAUD * 16;
+
+	spin_lock_init(&port->lock);
+
+	port->serial_in = hisilpc_serial_inb;
+	port->serial_out = hisilpc_serial_outb;
+
+	err = serial8250_register_8250_port(&uart);
+	if (err < 0) {
+		dev_err(&pdev->dev, "register uart FAIL(%d)!\n", -err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, (void *)&err);
+	dev_info(&pdev->dev, "##probing OK(%d)\n", err);
+	return 0;
+}
+
+static int hisilpc8250_remove(struct platform_device *pdev)
+{
+	int line = *((int *)platform_get_drvdata(pdev));
+
+	serial8250_unregister_port(line);
+
+	return 0;
+}
+
+
+static const struct of_device_id hs8250_of_match[] = {
+	{ .compatible = "hisilicon,lpc-uart" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hs8250_of_match);
+
+static const struct acpi_device_id hs8250_acpi_match[] = {
+	/*{ "PNP0501", 0 },*/
+	{ "HISI1031", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, hs8250_acpi_match);
+
+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe			= hisilpc8250_probe,
+	.remove			= hisilpc8250_remove,
+};
+
+module_platform_driver(hs_lpc8250_driver);
+
+
+MODULE_AUTHOR("Rongrong Zou");
+MODULE_DESCRIPTION("8250 serial probe module for Hisilicon LPC UART");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("v1.0");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 7c6f7af..c2e42f7 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -246,6 +246,15 @@ config SERIAL_8250_HUB6
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8250_hub6.
 
+config SERIAL_8250_HISI_LPC
+	tristate "Support Hisilicon Hip0X UART through LPC"
+	depends on SERIAL_8250 !=n && HISILICON_LPC
+	help
+	  Say Y here if you have a hip06 board.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called 8250_hisi_lpc.
+
 #
 # Misc. options/drivers.
 #
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 367d403..1f2915b 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
+obj-$(CONFIG_SERIAL_8250_HISI_LPC)	+= 8250_hisi_lpc.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
-- 
1.9.1

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

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

On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
controlled through the LPC I/O cycles. After registering the LPC uart specific
serial_in/serial_out to 8250 core driver, serial data can be read/written
through the LPC.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 .../devicetree/bindings/serial/hisi-lpc-uart.txt   |  60 ++++++++
 drivers/tty/serial/8250/8250_hisi_lpc.c            | 171 +++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig                    |   9 ++
 drivers/tty/serial/8250/Makefile                   |   1 +
 4 files changed, 241 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
 create mode 100644 drivers/tty/serial/8250/8250_hisi_lpc.c

diff --git a/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt b/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
new file mode 100644
index 0000000..0f8ec2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/hisi-lpc-uart.txt
@@ -0,0 +1,60 @@
+* Hisilicon hip06 UART through low-pin-count
+
+Required properties:
+- compatible : "hisilicon,lpc-uart"
+- reg : offset and length of the I/O port set for the device.
+- reg-names : name the uart resources.
+		"lpc_mem" represents memory resource of the LPC parent. When
+		flat-tree earlycon is needed, this memory resource and
+		resource name are mandatory. Otherwise they are optional;
+		"dev_io" represents I/O resource of this device. It is
+		mandatory to access this device;
+
+Clock handling:
+  The clock rate of this device is same as the 8250 default clock rate, that
+  is 1843200. No need to define the clock rate in device tree.
+
+Note:
+  This device depends on its parent device whose compatible string is
+  "hisilicon,low-pin-count".
+
+  The format of "reg" property follows the I/O space definition in ISA/EISA
+  binding specification linked to:
+  http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
+
+Example:
+
+	uart0: lpc-uart at 2f8 {
+		compatible = "hisilicon,lpc-uart";
+		reg = <0x01 0x2f8 0x08>;
+		status = "disabled";
+	};
+
+
+Example with low-pin-count parent device:
+
+	isa at a01b0000 {
+		compatible = "hisilicon,low-pin-count";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0x0 0xa01b0000 0x0 0x1000>;
+		ranges = <0x00 0xa01b0000 0x00 0xa01b0000 0x1000>,
+			<0x01 0xe4 0x0 0xe4 0x04>,
+			<0x01 0x2f8 0x0 0x2f8 0x08>;
+
+		ipmi0: bt at e4 {
+			compatible = "ipmi-bt";
+			device_type = "ipmi";
+			reg = <0x01 0xe4 0x04>;
+			reg-names = "dev_io";
+			status = "disabled";
+		};
+
+		uart0: lpc-uart at 2f8 {
+			compatible = "hisilicon,lpc-uart";
+			reg =  <0x00 0xa01b0000 0x1000>,
+				<0x01 0x2f8 0x08>;
+			ret-names = "lpc_mem", "dev_io";
+			status = "disabled";
+		};
+	};
diff --git a/drivers/tty/serial/8250/8250_hisi_lpc.c b/drivers/tty/serial/8250/8250_hisi_lpc.c
new file mode 100644
index 0000000..a8ba1ca
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_hisi_lpc.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <@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/module.h>
+#include <linux/acpi.h>
+#include <linux/serial_8250.h>
+#include <asm-generic/serial.h>
+#include <linux/of_address.h>
+
+
+/**
+ * hisilpc_serial_inb - read/input data from the designated serial port.
+ * @p: the serial port where the data read from
+ * @offset:  the target I/O port address where the read is from
+ *
+ * Returns the byte data from this serial port.
+ * -1 means some failures.
+ *
+ */
+static unsigned int hisilpc_serial_inb(struct uart_port *p, int offset)
+{
+	struct extio_ops *parentops;
+
+	parentops = p->private_data;
+	if (!parentops || !parentops->pfin)
+		return -1;
+
+	return parentops->pfin(parentops->devpara,
+				p->iobase + (offset << p->regshift),
+				NULL, sizeof(u8), 1);
+}
+
+/**
+ * hisilpc_serial_outb - write/output data from the designated serial port.
+ * @p: the serial port where the data is written to
+ * @offset:  the target I/O port address where the write is from
+ *
+ */
+static void hisilpc_serial_outb(struct uart_port *p, int offset, int value)
+{
+	struct extio_ops *parentops;
+
+	parentops = p->private_data;
+	if (!parentops || !parentops->pfout)
+		return;
+
+	parentops->pfout(parentops->devpara,
+				p->iobase + (offset << p->regshift),
+				&value, sizeof(u8), 1);
+}
+
+
+static int hisilpc8250_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct uart_port *port = &uart.port;
+	int err = 0;
+	struct resource *iores;
+	struct extio_ops *platdata;
+
+	if (!pdev->dev.parent)
+		return -ENODEV;
+	dev_info(&pdev->dev, "##probe entering\n");
+
+	/* To support the earlycon in bootargs, the first reg must be MEM */
+	iores = platform_get_resource_byname(pdev, IORESOURCE_IO,
+						"dev_io");
+	if (!iores) {
+		dev_err(&pdev->dev, "can not find the IO0\n");
+		return -ENXIO;
+	}
+
+	/*
+	 * save the platform data from parent in uart_port for serial_in,
+	 * serial_out
+	 */
+	platdata = dev_get_platdata(&pdev->dev);
+	port->private_data = (void *)platdata;
+	if (!port->private_data) {
+		dev_err(&pdev->dev, "no platform data!\n");
+		return -ENODEV;
+	}
+
+	if (platdata->start != iores->start || platdata->end != iores->end) {
+		dev_err(&pdev->dev, "PIO range[0x%lx - %lx] isn't fit!\n",
+			(unsigned long)iores->start,
+			(unsigned long)iores->end);
+		return -ENXIO;
+	}
+	port->iobase = (unsigned long)iores->start + platdata->ptoffset;
+	dev_info(&pdev->dev, "real port start is 0x%lx\n", port->iobase);
+
+	port->irq	= 0;
+	port->flags	= UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
+	port->dev	= &pdev->dev;
+	port->iotype	= UPIO_PORT;
+	port->regshift	= 0;
+	port->uartclk	= BASE_BAUD * 16;
+
+	spin_lock_init(&port->lock);
+
+	port->serial_in = hisilpc_serial_inb;
+	port->serial_out = hisilpc_serial_outb;
+
+	err = serial8250_register_8250_port(&uart);
+	if (err < 0) {
+		dev_err(&pdev->dev, "register uart FAIL(%d)!\n", -err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, (void *)&err);
+	dev_info(&pdev->dev, "##probing OK(%d)\n", err);
+	return 0;
+}
+
+static int hisilpc8250_remove(struct platform_device *pdev)
+{
+	int line = *((int *)platform_get_drvdata(pdev));
+
+	serial8250_unregister_port(line);
+
+	return 0;
+}
+
+
+static const struct of_device_id hs8250_of_match[] = {
+	{ .compatible = "hisilicon,lpc-uart" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hs8250_of_match);
+
+static const struct acpi_device_id hs8250_acpi_match[] = {
+	/*{ "PNP0501", 0 },*/
+	{ "HISI1031", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, hs8250_acpi_match);
+
+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe			= hisilpc8250_probe,
+	.remove			= hisilpc8250_remove,
+};
+
+module_platform_driver(hs_lpc8250_driver);
+
+
+MODULE_AUTHOR("Rongrong Zou");
+MODULE_DESCRIPTION("8250 serial probe module for Hisilicon LPC UART");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("v1.0");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 7c6f7af..c2e42f7 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -246,6 +246,15 @@ config SERIAL_8250_HUB6
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8250_hub6.
 
+config SERIAL_8250_HISI_LPC
+	tristate "Support Hisilicon Hip0X UART through LPC"
+	depends on SERIAL_8250 !=n && HISILICON_LPC
+	help
+	  Say Y here if you have a hip06 board.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called 8250_hisi_lpc.
+
 #
 # Misc. options/drivers.
 #
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 367d403..1f2915b 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA)		+= 8250_boca.o
 obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554)	+= 8250_exar_st16c554.o
 obj-$(CONFIG_SERIAL_8250_HUB6)		+= 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)		+= 8250_fsl.o
+obj-$(CONFIG_SERIAL_8250_HISI_LPC)	+= 8250_hisi_lpc.o
 obj-$(CONFIG_SERIAL_8250_DW)		+= 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
-- 
1.9.1

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

* [PATCH V3 4/4] ARM64 LPC: support earlycon for UART connected to LPC
  2016-09-14 12:15 ` Zhichang Yuan
  (?)
@ 2016-09-14 12:15   ` Zhichang Yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: arnd, gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

This patch support the earlycon for UART connected to LPC on Hip06.
This patch is depended on the LPC driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 drivers/bus/hisi_lpc.c               | 113 +++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_early.c |  26 +++++++-
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 9b364d0..2269828 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -360,6 +360,119 @@ void hisilpc_comm_outb(void *devobj, unsigned long ptaddr,
 
 
 /**
+ * hisilpc_early_in - read/input operation specific for hisi LPC earlycon.
+ * @devobj: pointer to device relevant information of the caller.
+ * @inbuf: the buffer where the read back data is populated.
+ *
+ * for earlycon, dlen and count should be one.
+ *
+ * Return the data read from earlycon on success, error ID on fail.
+ *
+ */
+static unsigned int __init hisilpc_early_in(struct uart_port *port, int offset)
+{
+	unsigned int backval = 0;
+	unsigned int ret = 0;
+	struct lpc_cycle_para para;
+	struct hisilpc_dev lpcdev;
+
+	if (!port->mapbase || !port->iobase || !port->membase)
+		return -EINVAL;
+
+	para.opflags = FG_EARLYCON_LPC;
+	para.csize = 1;
+	lpcdev.membase = port->membase;
+
+	ret = hisilpc_target_in(&lpcdev, &para,
+				port->iobase + (offset << port->regshift),
+				(unsigned char *)&backval, 1);
+	return (ret) ? : backval;
+}
+
+/**
+ * hisilpc_early_out - write/output operation specific for hisi LPC earlycon.
+ * @port: pointer to uart_port of eralycon
+ *
+ * for earlycon, dlen and count should be one.
+ *
+ */
+static void __init hisilpc_early_out(struct uart_port *port, int offset,
+					int value)
+{
+	struct lpc_cycle_para para;
+	struct hisilpc_dev lpcdev;
+
+	if (!port->mapbase || !port->iobase || !port->membase)
+		return;
+
+	para.opflags = FG_EARLYCON_LPC;
+	para.csize = 1;
+	lpcdev.membase = port->membase;
+
+	(void)hisilpc_target_out(&lpcdev, &para,
+				port->iobase + (offset << port->regshift),
+				(unsigned char *)&value, 1);
+}
+
+
+/**
+ * early_hisilpc8250_setup - initilize the lpc earlycon
+ * @device: pointer to the elarycon device
+ * @options: a option string from earlycon kernel-parameter
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int __init early_hisilpc8250_setup(struct earlycon_device *device,
+						const char *options)
+{
+	char *p;
+	int ret;
+
+	if (!device->port.membase)
+		return -ENODEV;
+
+	if (device->port.iotype != UPIO_MEM)
+		return -EINVAL;
+
+	if (device->options) {
+		p = strchr(device->options, ',');
+		if (p && (p + 1) != '\0') {
+			ret = kstrtoul(++p, 0,
+				(unsigned long *)&device->port.iobase);
+			if (ret || device->port.iobase == 0)
+				return ret ?: -EFAULT;
+		} else
+			device->port.iobase = 0x2f8;
+	} else {
+		device->port.iobase = 0x2f8;
+		device->baud = 0;
+	}
+
+	device->port.serial_in = hisilpc_early_in;
+	device->port.serial_out = hisilpc_early_out;
+	/* must convert iotype to UPIO_PORT for Hip06 indirect-io */
+	device->port.iotype = UPIO_PORT;
+
+	/* disable interrupts from LPC */
+	writel(LPC_IRQ_CLEAR, device->port.membase + LPC_REG_IRQ_ST);
+	/* ensure the LPC is available */
+	while (!(readl(device->port.membase + LPC_REG_OP_STATUS) &
+			LPC_STATUS_IDLE))
+		cpu_relax();
+
+	return early_serial8250_setup(device, options);
+}
+
+
+
+EARLYCON_DECLARE(hisilpcuart, early_hisilpc8250_setup);
+OF_EARLYCON_DECLARE(hisilpcuart, "hisilicon,lpc-uart",
+					early_hisilpc8250_setup);
+
+
+
+/**
  * hisilpc_ischild_ipmi - check whether the designated device is ipmi
  * @dev: the device to be checked.
  * @data: the value used to match the acpi device in checking.
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 85a12f0..3b5d0a8 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -37,7 +37,7 @@
 #include <asm/io.h>
 #include <asm/serial.h>
 
-static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
+static unsigned int __init serial8250_early_in_raw(struct uart_port *port, int offset)
 {
 	offset <<= port->regshift;
 
@@ -57,7 +57,7 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
 	}
 }
 
-static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
+static void __init serial8250_early_out_raw(struct uart_port *port, int offset, int value)
 {
 	offset <<= port->regshift;
 
@@ -80,6 +80,28 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
 	}
 }
 
+static inline void __init serial8250_early_out(struct uart_port *port,
+					int offset, int value)
+{
+	if (port->serial_out)
+		port->serial_out(port, offset, value);
+	else {
+		port->serial_out = serial8250_early_out_raw;
+		serial8250_early_out_raw(port, offset, value);
+	}
+}
+
+static inline unsigned int __init serial8250_early_in(struct uart_port *port,
+					int offset)
+{
+	if (port->serial_in)
+		return port->serial_in(port, offset);
+
+	port->serial_in = serial8250_early_in_raw;
+	return serial8250_early_in_raw(port, offset);
+}
+
+
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
 static void __init serial_putc(struct uart_port *port, int c)
-- 
1.9.1

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

* [PATCH V3 4/4] ARM64 LPC: support earlycon for UART connected to LPC
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linuxarm
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, arnd, linux-pci,
	gabriele.paoloni, john.garry, will.deacon, xuwei5, zhichang.yuan,
	linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

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

This patch support the earlycon for UART connected to LPC on Hip06.
This patch is depended on the LPC driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 drivers/bus/hisi_lpc.c               | 113 +++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_early.c |  26 +++++++-
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 9b364d0..2269828 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -360,6 +360,119 @@ void hisilpc_comm_outb(void *devobj, unsigned long ptaddr,
 
 
 /**
+ * hisilpc_early_in - read/input operation specific for hisi LPC earlycon.
+ * @devobj: pointer to device relevant information of the caller.
+ * @inbuf: the buffer where the read back data is populated.
+ *
+ * for earlycon, dlen and count should be one.
+ *
+ * Return the data read from earlycon on success, error ID on fail.
+ *
+ */
+static unsigned int __init hisilpc_early_in(struct uart_port *port, int offset)
+{
+	unsigned int backval = 0;
+	unsigned int ret = 0;
+	struct lpc_cycle_para para;
+	struct hisilpc_dev lpcdev;
+
+	if (!port->mapbase || !port->iobase || !port->membase)
+		return -EINVAL;
+
+	para.opflags = FG_EARLYCON_LPC;
+	para.csize = 1;
+	lpcdev.membase = port->membase;
+
+	ret = hisilpc_target_in(&lpcdev, &para,
+				port->iobase + (offset << port->regshift),
+				(unsigned char *)&backval, 1);
+	return (ret) ? : backval;
+}
+
+/**
+ * hisilpc_early_out - write/output operation specific for hisi LPC earlycon.
+ * @port: pointer to uart_port of eralycon
+ *
+ * for earlycon, dlen and count should be one.
+ *
+ */
+static void __init hisilpc_early_out(struct uart_port *port, int offset,
+					int value)
+{
+	struct lpc_cycle_para para;
+	struct hisilpc_dev lpcdev;
+
+	if (!port->mapbase || !port->iobase || !port->membase)
+		return;
+
+	para.opflags = FG_EARLYCON_LPC;
+	para.csize = 1;
+	lpcdev.membase = port->membase;
+
+	(void)hisilpc_target_out(&lpcdev, &para,
+				port->iobase + (offset << port->regshift),
+				(unsigned char *)&value, 1);
+}
+
+
+/**
+ * early_hisilpc8250_setup - initilize the lpc earlycon
+ * @device: pointer to the elarycon device
+ * @options: a option string from earlycon kernel-parameter
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int __init early_hisilpc8250_setup(struct earlycon_device *device,
+						const char *options)
+{
+	char *p;
+	int ret;
+
+	if (!device->port.membase)
+		return -ENODEV;
+
+	if (device->port.iotype != UPIO_MEM)
+		return -EINVAL;
+
+	if (device->options) {
+		p = strchr(device->options, ',');
+		if (p && (p + 1) != '\0') {
+			ret = kstrtoul(++p, 0,
+				(unsigned long *)&device->port.iobase);
+			if (ret || device->port.iobase == 0)
+				return ret ?: -EFAULT;
+		} else
+			device->port.iobase = 0x2f8;
+	} else {
+		device->port.iobase = 0x2f8;
+		device->baud = 0;
+	}
+
+	device->port.serial_in = hisilpc_early_in;
+	device->port.serial_out = hisilpc_early_out;
+	/* must convert iotype to UPIO_PORT for Hip06 indirect-io */
+	device->port.iotype = UPIO_PORT;
+
+	/* disable interrupts from LPC */
+	writel(LPC_IRQ_CLEAR, device->port.membase + LPC_REG_IRQ_ST);
+	/* ensure the LPC is available */
+	while (!(readl(device->port.membase + LPC_REG_OP_STATUS) &
+			LPC_STATUS_IDLE))
+		cpu_relax();
+
+	return early_serial8250_setup(device, options);
+}
+
+
+
+EARLYCON_DECLARE(hisilpcuart, early_hisilpc8250_setup);
+OF_EARLYCON_DECLARE(hisilpcuart, "hisilicon,lpc-uart",
+					early_hisilpc8250_setup);
+
+
+
+/**
  * hisilpc_ischild_ipmi - check whether the designated device is ipmi
  * @dev: the device to be checked.
  * @data: the value used to match the acpi device in checking.
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 85a12f0..3b5d0a8 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -37,7 +37,7 @@
 #include <asm/io.h>
 #include <asm/serial.h>
 
-static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
+static unsigned int __init serial8250_early_in_raw(struct uart_port *port, int offset)
 {
 	offset <<= port->regshift;
 
@@ -57,7 +57,7 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
 	}
 }
 
-static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
+static void __init serial8250_early_out_raw(struct uart_port *port, int offset, int value)
 {
 	offset <<= port->regshift;
 
@@ -80,6 +80,28 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
 	}
 }
 
+static inline void __init serial8250_early_out(struct uart_port *port,
+					int offset, int value)
+{
+	if (port->serial_out)
+		port->serial_out(port, offset, value);
+	else {
+		port->serial_out = serial8250_early_out_raw;
+		serial8250_early_out_raw(port, offset, value);
+	}
+}
+
+static inline unsigned int __init serial8250_early_in(struct uart_port *port,
+					int offset)
+{
+	if (port->serial_in)
+		return port->serial_in(port, offset);
+
+	port->serial_in = serial8250_early_in_raw;
+	return serial8250_early_in_raw(port, offset);
+}
+
+
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
 static void __init serial_putc(struct uart_port *port, int c)
-- 
1.9.1

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

* [PATCH V3 4/4] ARM64 LPC: support earlycon for UART connected to LPC
@ 2016-09-14 12:15   ` Zhichang Yuan
  0 siblings, 0 replies; 160+ messages in thread
From: Zhichang Yuan @ 2016-09-14 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

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

This patch support the earlycon for UART connected to LPC on Hip06.
This patch is depended on the LPC driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
 drivers/bus/hisi_lpc.c               | 113 +++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_early.c |  26 +++++++-
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 9b364d0..2269828 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -360,6 +360,119 @@ void hisilpc_comm_outb(void *devobj, unsigned long ptaddr,
 
 
 /**
+ * hisilpc_early_in - read/input operation specific for hisi LPC earlycon.
+ * @devobj: pointer to device relevant information of the caller.
+ * @inbuf: the buffer where the read back data is populated.
+ *
+ * for earlycon, dlen and count should be one.
+ *
+ * Return the data read from earlycon on success, error ID on fail.
+ *
+ */
+static unsigned int __init hisilpc_early_in(struct uart_port *port, int offset)
+{
+	unsigned int backval = 0;
+	unsigned int ret = 0;
+	struct lpc_cycle_para para;
+	struct hisilpc_dev lpcdev;
+
+	if (!port->mapbase || !port->iobase || !port->membase)
+		return -EINVAL;
+
+	para.opflags = FG_EARLYCON_LPC;
+	para.csize = 1;
+	lpcdev.membase = port->membase;
+
+	ret = hisilpc_target_in(&lpcdev, &para,
+				port->iobase + (offset << port->regshift),
+				(unsigned char *)&backval, 1);
+	return (ret) ? : backval;
+}
+
+/**
+ * hisilpc_early_out - write/output operation specific for hisi LPC earlycon.
+ * @port: pointer to uart_port of eralycon
+ *
+ * for earlycon, dlen and count should be one.
+ *
+ */
+static void __init hisilpc_early_out(struct uart_port *port, int offset,
+					int value)
+{
+	struct lpc_cycle_para para;
+	struct hisilpc_dev lpcdev;
+
+	if (!port->mapbase || !port->iobase || !port->membase)
+		return;
+
+	para.opflags = FG_EARLYCON_LPC;
+	para.csize = 1;
+	lpcdev.membase = port->membase;
+
+	(void)hisilpc_target_out(&lpcdev, &para,
+				port->iobase + (offset << port->regshift),
+				(unsigned char *)&value, 1);
+}
+
+
+/**
+ * early_hisilpc8250_setup - initilize the lpc earlycon
+ * @device: pointer to the elarycon device
+ * @options: a option string from earlycon kernel-parameter
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int __init early_hisilpc8250_setup(struct earlycon_device *device,
+						const char *options)
+{
+	char *p;
+	int ret;
+
+	if (!device->port.membase)
+		return -ENODEV;
+
+	if (device->port.iotype != UPIO_MEM)
+		return -EINVAL;
+
+	if (device->options) {
+		p = strchr(device->options, ',');
+		if (p && (p + 1) != '\0') {
+			ret = kstrtoul(++p, 0,
+				(unsigned long *)&device->port.iobase);
+			if (ret || device->port.iobase == 0)
+				return ret ?: -EFAULT;
+		} else
+			device->port.iobase = 0x2f8;
+	} else {
+		device->port.iobase = 0x2f8;
+		device->baud = 0;
+	}
+
+	device->port.serial_in = hisilpc_early_in;
+	device->port.serial_out = hisilpc_early_out;
+	/* must convert iotype to UPIO_PORT for Hip06 indirect-io */
+	device->port.iotype = UPIO_PORT;
+
+	/* disable interrupts from LPC */
+	writel(LPC_IRQ_CLEAR, device->port.membase + LPC_REG_IRQ_ST);
+	/* ensure the LPC is available */
+	while (!(readl(device->port.membase + LPC_REG_OP_STATUS) &
+			LPC_STATUS_IDLE))
+		cpu_relax();
+
+	return early_serial8250_setup(device, options);
+}
+
+
+
+EARLYCON_DECLARE(hisilpcuart, early_hisilpc8250_setup);
+OF_EARLYCON_DECLARE(hisilpcuart, "hisilicon,lpc-uart",
+					early_hisilpc8250_setup);
+
+
+
+/**
  * hisilpc_ischild_ipmi - check whether the designated device is ipmi
  * @dev: the device to be checked.
  * @data: the value used to match the acpi device in checking.
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 85a12f0..3b5d0a8 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -37,7 +37,7 @@
 #include <asm/io.h>
 #include <asm/serial.h>
 
-static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
+static unsigned int __init serial8250_early_in_raw(struct uart_port *port, int offset)
 {
 	offset <<= port->regshift;
 
@@ -57,7 +57,7 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
 	}
 }
 
-static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
+static void __init serial8250_early_out_raw(struct uart_port *port, int offset, int value)
 {
 	offset <<= port->regshift;
 
@@ -80,6 +80,28 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
 	}
 }
 
+static inline void __init serial8250_early_out(struct uart_port *port,
+					int offset, int value)
+{
+	if (port->serial_out)
+		port->serial_out(port, offset, value);
+	else {
+		port->serial_out = serial8250_early_out_raw;
+		serial8250_early_out_raw(port, offset, value);
+	}
+}
+
+static inline unsigned int __init serial8250_early_in(struct uart_port *port,
+					int offset)
+{
+	if (port->serial_in)
+		return port->serial_in(port, offset);
+
+	port->serial_in = serial8250_early_in_raw;
+	return serial8250_early_in_raw(port, offset);
+}
+
+
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
 static void __init serial_putc(struct uart_port *port, int c)
-- 
1.9.1

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
  2016-09-14 12:15   ` Zhichang Yuan
@ 2016-09-14 12:24     ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Zhichang Yuan, linux-kernel, linuxarm, devicetree,
	lorenzo.pieralisi, benh, minyard, linux-pci, gabriele.paoloni,
	john.garry, will.deacon, xuwei5, linux-serial, gregkh,
	zourongrong, liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
> 
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>

Looks ok overall, but I have a couple of comments for details.

> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index bc3f00f..9579479 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>  
> +config ARM64_INDIRECT_PIO
> +	def_bool n

'def_bool n' is the same as the shorter and more common 'bool'.

> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 9b6e408..d3acf1f 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -34,6 +34,10 @@
>  
>  #include <xen/xen.h>
>  
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#include <linux/extio.h>
> +#endif

No need to guard includes with an #ifdef.

> +#define BUILDS_RW(bwl, type)						\
> +static inline void reads##bwl(const volatile void __iomem *addr,	\
> +				void *buffer, unsigned int count)	\
> +{									\
> +	if (count) {							\
> +		type *buf = buffer;					\
> +									\
> +		do {							\
> +			type x = __raw_read##bwl(addr);			\
> +			*buf++ = x;					\
> +		} while (--count);					\
> +	}								\
> +}									\
> +									\
> +static inline void writes##bwl(volatile void __iomem *addr,		\
> +				const void *buffer, unsigned int count)	\
> +{									\
> +	if (count) {							\
> +		const type *buf = buffer;				\
> +									\
> +		do {							\
> +			__raw_write##bwl(*buf++, addr);			\
> +		} while (--count);					\
> +	}								\
> +}
> +
> +BUILDS_RW(b, u8)

Why is this in here?

> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>  
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#define inb inb
> +static inline u8 inb(unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +			addr <= arm64_extio_ops->end)
> +		return extio_inb(addr);
> +#endif
> +	return readb(PCI_IOBASE + addr);
> +}
> +

Looks ok, but you only seem to do this for the 8-bit
accessors, when it should be done for 16-bit and 32-bit
ones as well for consistency.

> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> new file mode 100644
> index 0000000..1e7a9c5
> --- /dev/null
> +++ b/drivers/bus/extio.c
> @@ -0,0 +1,66 @@

This is in a globally visible directory

> +
> +struct extio_ops *arm64_extio_ops;

But the identifier uses an architecture specific prefix. Either
move the whole file into arch/arm64, or make the naming so that
it can be used for everything.

> +u8 __weak extio_inb(unsigned long addr)
> +{
> +	return arm64_extio_ops->pfin ?
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
> +			addr + arm64_extio_ops->ptoffset, NULL,
> +			sizeof(u8), 1) : -1;
> +}

No need for the __weak attribute, just make sure that the
code is always built-in when needed.

Also, it doesn't seem necessary to have an extern function if
all it does is call the one callback that you have already 
checked earlier. Either put it all into the inline
definition in asm/io.h, or put it all into the extern
version like this.

#ifdef CONFIG_ARM64_INDIRECT_PIO /* otherwise use default from asm-generic */
#define inb inb
extern u8 inb(unsigned long addr);
#endif

u8 inb(unsigned long addr)
{
	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
			addr <= arm64_extio_ops->end)
		arm64_extio_ops->pfin(arm64_extio_ops->devpara,addr + arm64_extio_ops->ptoffset, NULL,sizeof(u8), 1) : -1;
	return extio_inb(addr);
}

> +#define inb inb
> +static inline u8 inb(unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +			addr <= arm64_extio_ops->end)
> +		return extio_inb(addr);
> +#endif
> +	return readb(PCI_IOBASE + addr);
> +}

> diff --git a/include/linux/extio.h b/include/linux/extio.h
> new file mode 100644
> index 0000000..08d1fca
> --- /dev/null
> +++ b/include/linux/extio.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + * Author: Zou Rongrong <@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/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +
> +typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
> +				size_t dlen, unsigned int count);
> +typedef void (*outhook)(void *devobj, unsigned long ptaddr,
> +				const void *outbuf, size_t dlen,
> +				unsigned int count);

I would drop the typedef and just declare the types directly in the
only place that references them.

	Arnd

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 12:24     ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
> 
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>

Looks ok overall, but I have a couple of comments for details.

> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index bc3f00f..9579479 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>  
> +config ARM64_INDIRECT_PIO
> +	def_bool n

'def_bool n' is the same as the shorter and more common 'bool'.

> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 9b6e408..d3acf1f 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -34,6 +34,10 @@
>  
>  #include <xen/xen.h>
>  
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#include <linux/extio.h>
> +#endif

No need to guard includes with an #ifdef.

> +#define BUILDS_RW(bwl, type)						\
> +static inline void reads##bwl(const volatile void __iomem *addr,	\
> +				void *buffer, unsigned int count)	\
> +{									\
> +	if (count) {							\
> +		type *buf = buffer;					\
> +									\
> +		do {							\
> +			type x = __raw_read##bwl(addr);			\
> +			*buf++ = x;					\
> +		} while (--count);					\
> +	}								\
> +}									\
> +									\
> +static inline void writes##bwl(volatile void __iomem *addr,		\
> +				const void *buffer, unsigned int count)	\
> +{									\
> +	if (count) {							\
> +		const type *buf = buffer;				\
> +									\
> +		do {							\
> +			__raw_write##bwl(*buf++, addr);			\
> +		} while (--count);					\
> +	}								\
> +}
> +
> +BUILDS_RW(b, u8)

Why is this in here?

> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>  
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#define inb inb
> +static inline u8 inb(unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +			addr <= arm64_extio_ops->end)
> +		return extio_inb(addr);
> +#endif
> +	return readb(PCI_IOBASE + addr);
> +}
> +

Looks ok, but you only seem to do this for the 8-bit
accessors, when it should be done for 16-bit and 32-bit
ones as well for consistency.

> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> new file mode 100644
> index 0000000..1e7a9c5
> --- /dev/null
> +++ b/drivers/bus/extio.c
> @@ -0,0 +1,66 @@

This is in a globally visible directory

> +
> +struct extio_ops *arm64_extio_ops;

But the identifier uses an architecture specific prefix. Either
move the whole file into arch/arm64, or make the naming so that
it can be used for everything.

> +u8 __weak extio_inb(unsigned long addr)
> +{
> +	return arm64_extio_ops->pfin ?
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
> +			addr + arm64_extio_ops->ptoffset, NULL,
> +			sizeof(u8), 1) : -1;
> +}

No need for the __weak attribute, just make sure that the
code is always built-in when needed.

Also, it doesn't seem necessary to have an extern function if
all it does is call the one callback that you have already 
checked earlier. Either put it all into the inline
definition in asm/io.h, or put it all into the extern
version like this.

#ifdef CONFIG_ARM64_INDIRECT_PIO /* otherwise use default from asm-generic */
#define inb inb
extern u8 inb(unsigned long addr);
#endif

u8 inb(unsigned long addr)
{
	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
			addr <= arm64_extio_ops->end)
		arm64_extio_ops->pfin(arm64_extio_ops->devpara,addr + arm64_extio_ops->ptoffset, NULL,sizeof(u8), 1) : -1;
	return extio_inb(addr);
}

> +#define inb inb
> +static inline u8 inb(unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +			addr <= arm64_extio_ops->end)
> +		return extio_inb(addr);
> +#endif
> +	return readb(PCI_IOBASE + addr);
> +}

> diff --git a/include/linux/extio.h b/include/linux/extio.h
> new file mode 100644
> index 0000000..08d1fca
> --- /dev/null
> +++ b/include/linux/extio.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + * Author: Zou Rongrong <@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/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +
> +typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
> +				size_t dlen, unsigned int count);
> +typedef void (*outhook)(void *devobj, unsigned long ptaddr,
> +				const void *outbuf, size_t dlen,
> +				unsigned int count);

I would drop the typedef and just declare the types directly in the
only place that references them.

	Arnd

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 12:25     ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:25 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Zhichang Yuan, linux-kernel, linuxarm, devicetree,
	lorenzo.pieralisi, benh, minyard, linux-pci, gabriele.paoloni,
	john.garry, will.deacon, xuwei5, linux-serial, gregkh,
	zourongrong, liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
> controlled through the LPC I/O cycles. After registering the LPC uart specific
> serial_in/serial_out to 8250 core driver, serial data can be read/written
> through the LPC.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> 

I still think this should be handled by 8250_of.c after the addition of
support for IORESOURCE_IO.

	Arnd

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 12:25     ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:25 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Zhichang Yuan, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	john.garry-hv44wF8Li93QT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w, liviu.dudau-5wv7dgnIgG8,
	kantyzc-9Onoh4P/yGk, zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w

On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
> From: "zhichang.yuan" <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> 
> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
> controlled through the LPC I/O cycles. After registering the LPC uart specific
> serial_in/serial_out to 8250 core driver, serial data can be read/written
> through the LPC.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> 

I still think this should be handled by 8250_of.c after the addition of
support for IORESOURCE_IO.

	Arnd

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 12:25     ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
> controlled through the LPC I/O cycles. After registering the LPC uart specific
> serial_in/serial_out to 8250 core driver, serial data can be read/written
> through the LPC.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> 

I still think this should be handled by 8250_of.c after the addition of
support for IORESOURCE_IO.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-14 12:15   ` Zhichang Yuan
@ 2016-09-14 12:33     ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Zhichang Yuan, linux-kernel, linuxarm, devicetree,
	lorenzo.pieralisi, benh, minyard, linux-pci, gabriele.paoloni,
	john.garry, will.deacon, xuwei5, linux-serial, gregkh,
	zourongrong, liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:

> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #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 address and length of the register set for the device.
> +- ranges: define a 1:1 mapping between the I/O space of the child device and
> +	  the parent.

Do we still need the "ranges" here? The property in your example seems
wrong.

> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;

You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?

> +/**
> + * hisilpc_children_map_sysio - setup the mapping between system Io and
> + *			physical IO
> + *
> + * @child: the device whose IO is handling
> + * @data: some device specific data. For ACPI device, should be NULL.
> + *
> + * Returns >=0 means the mapping is successfully created;
> + * others mean some failures.
> + */
> +static int hisilpc_children_map_sysio(struct device * child, void * data)
> +{
> +	struct resource *iores;
> +	unsigned long cpuio;
> +	struct extio_ops *opsnode;
> +	int ret;
> +	struct hisilpc_dev *lpcdev;
> +
> +	if (!child || !child->parent)
> +		return -EINVAL;
> +
> +	iores = platform_get_resource_byname(to_platform_device(child),
> +					IORESOURCE_IO, "dev_io");
> +	if (!iores)
> +		return -ENODEV;
> +
> +	/*
> +	 * can not use devm_kzalloc to allocate slab for child before its driver
> +	 * start probing. Here allocate the slab with the name of parent.
> +	 */
> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
> +	if (!opsnode)
> +		return -ENOMEM;
> +
> +	cpuio = data ? *((unsigned long *)data) : 0;
> +
> +	opsnode->start = iores->start;
> +	opsnode->end = iores->end;
> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
> +
> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
> +				(unsigned long)iores->start,
> +				(unsigned long)iores->end,
> +				opsnode->ptoffset);
> +
> +	opsnode->pfin = hisilpc_comm_inb;
> +	opsnode->pfout = hisilpc_comm_outb;
> +
> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
> +	opsnode->devpara = lpcdev;
> +
> +	/* only apply indirect-IO to ipmi child device */

I don't get this part. The bus driver should not care what its
children are, just register and PIO ranges that the bus can handle
in theory, i.e. from 0x000 to 0xfff.

	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 12:33     ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:

> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #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 address and length of the register set for the device.
> +- ranges: define a 1:1 mapping between the I/O space of the child device and
> +	  the parent.

Do we still need the "ranges" here? The property in your example seems
wrong.

> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;

You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?

> +/**
> + * hisilpc_children_map_sysio - setup the mapping between system Io and
> + *			physical IO
> + *
> + * @child: the device whose IO is handling
> + * @data: some device specific data. For ACPI device, should be NULL.
> + *
> + * Returns >=0 means the mapping is successfully created;
> + * others mean some failures.
> + */
> +static int hisilpc_children_map_sysio(struct device * child, void * data)
> +{
> +	struct resource *iores;
> +	unsigned long cpuio;
> +	struct extio_ops *opsnode;
> +	int ret;
> +	struct hisilpc_dev *lpcdev;
> +
> +	if (!child || !child->parent)
> +		return -EINVAL;
> +
> +	iores = platform_get_resource_byname(to_platform_device(child),
> +					IORESOURCE_IO, "dev_io");
> +	if (!iores)
> +		return -ENODEV;
> +
> +	/*
> +	 * can not use devm_kzalloc to allocate slab for child before its driver
> +	 * start probing. Here allocate the slab with the name of parent.
> +	 */
> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
> +	if (!opsnode)
> +		return -ENOMEM;
> +
> +	cpuio = data ? *((unsigned long *)data) : 0;
> +
> +	opsnode->start = iores->start;
> +	opsnode->end = iores->end;
> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
> +
> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
> +				(unsigned long)iores->start,
> +				(unsigned long)iores->end,
> +				opsnode->ptoffset);
> +
> +	opsnode->pfin = hisilpc_comm_inb;
> +	opsnode->pfout = hisilpc_comm_outb;
> +
> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
> +	opsnode->devpara = lpcdev;
> +
> +	/* only apply indirect-IO to ipmi child device */

I don't get this part. The bus driver should not care what its
children are, just register and PIO ranges that the bus can handle
in theory, i.e. from 0x000 to 0xfff.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 14:09     ` kbuild test robot
  0 siblings, 0 replies; 160+ messages in thread
From: kbuild test robot @ 2016-09-14 14:09 UTC (permalink / raw)
  To: Zhichang Yuan
  Cc: kbuild-all, linux-arm-kernel, linux-kernel, linuxarm, arnd,
	gregkh, will.deacon, devicetree, linux-pci, linux-serial,
	minyard, benh, lorenzo.pieralisi, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.8-rc6 next-20160914]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Zhichang-Yuan/ARM64-LPC-legacy-ISA-I-O-support/20160914-202858
config: openrisc-or1ksim_defconfig (attached as .config)
compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=openrisc 

All errors (new ones prefixed by >>):

   drivers/of/address.c: In function '__of_address_to_resource':
>> drivers/of/address.c:702:5: error: implicit declaration of function 'of_bus_pci_match'

vim +/of_bus_pci_match +702 drivers/of/address.c

   696				return -EINVAL;
   697			/*
   698			 * special processing for non-pci device gurantee the linux start pio
   699			 * is not ZERO. Otherwise, some drivers' initialization will fail.
   700			 */
   701			if (!port && (!IS_ENABLED(CONFIG_OF_ADDRESS_PCI) ||
 > 702					!of_bus_pci_match(dev)))
   703				port += 1;
   704	
   705			r->start = port;

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 7187 bytes --]

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 14:09     ` kbuild test robot
  0 siblings, 0 replies; 160+ messages in thread
From: kbuild test robot @ 2016-09-14 14:09 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA, arnd-r2nGTMty4D4,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, will.deacon-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8, liviu.dudau-5wv7dgnIgG8,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, zhichang.yuan

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

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.8-rc6 next-20160914]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Zhichang-Yuan/ARM64-LPC-legacy-ISA-I-O-support/20160914-202858
config: openrisc-or1ksim_defconfig (attached as .config)
compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=openrisc 

All errors (new ones prefixed by >>):

   drivers/of/address.c: In function '__of_address_to_resource':
>> drivers/of/address.c:702:5: error: implicit declaration of function 'of_bus_pci_match'

vim +/of_bus_pci_match +702 drivers/of/address.c

   696				return -EINVAL;
   697			/*
   698			 * special processing for non-pci device gurantee the linux start pio
   699			 * is not ZERO. Otherwise, some drivers' initialization will fail.
   700			 */
   701			if (!port && (!IS_ENABLED(CONFIG_OF_ADDRESS_PCI) ||
 > 702					!of_bus_pci_match(dev)))
   703				port += 1;
   704	
   705			r->start = port;

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

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 7187 bytes --]

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 14:09     ` kbuild test robot
  0 siblings, 0 replies; 160+ messages in thread
From: kbuild test robot @ 2016-09-14 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi zhichang.yuan,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.8-rc6 next-20160914]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Zhichang-Yuan/ARM64-LPC-legacy-ISA-I-O-support/20160914-202858
config: openrisc-or1ksim_defconfig (attached as .config)
compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=openrisc 

All errors (new ones prefixed by >>):

   drivers/of/address.c: In function '__of_address_to_resource':
>> drivers/of/address.c:702:5: error: implicit declaration of function 'of_bus_pci_match'

vim +/of_bus_pci_match +702 drivers/of/address.c

   696				return -EINVAL;
   697			/*
   698			 * special processing for non-pci device gurantee the linux start pio
   699			 * is not ZERO. Otherwise, some drivers' initialization will fail.
   700			 */
   701			if (!port && (!IS_ENABLED(CONFIG_OF_ADDRESS_PCI) ||
 > 702					!of_bus_pci_match(dev)))
   703				port += 1;
   704	
   705			r->start = port;

---
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/octet-stream
Size: 7187 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160914/6b1ff665/attachment.obj>

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
  2016-09-14 12:24     ` Arnd Bergmann
  (?)
@ 2016-09-14 14:16       ` zhichang.yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 14:16 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: linux-kernel, linuxarm, devicetree, lorenzo.pieralisi, benh,
	minyard, linux-pci, gabriele.paoloni, john.garry, will.deacon,
	xuwei5, linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

Hi, Arnd

On 2016/9/14 20:24, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
>>
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> 
> Looks ok overall, but I have a couple of comments for details.
> 
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index bc3f00f..9579479 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>  
>> +config ARM64_INDIRECT_PIO
>> +	def_bool n
> 
> 'def_bool n' is the same as the shorter and more common 'bool'.
Yes. Will modify as bool "access peripherals with legacy I/O port"

> 
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 9b6e408..d3acf1f 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -34,6 +34,10 @@
>>  
>>  #include <xen/xen.h>
>>  
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#include <linux/extio.h>
>> +#endif
> 
> No need to guard includes with an #ifdef.
If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.


How about removing everything about the configure item "ARM64_INDIRECT_PIO"?
This will make the indirect-IO mechanism global on ARM64.
I worry about this mechanism is not so common, so using "ARM64_INDIRECT_PIO" make this feature optional.

> 
>> +#define BUILDS_RW(bwl, type)						\
>> +static inline void reads##bwl(const volatile void __iomem *addr,	\
>> +				void *buffer, unsigned int count)	\
>> +{									\
>> +	if (count) {							\
>> +		type *buf = buffer;					\
>> +									\
>> +		do {							\
>> +			type x = __raw_read##bwl(addr);			\
>> +			*buf++ = x;					\
>> +		} while (--count);					\
>> +	}								\
>> +}									\
>> +									\
>> +static inline void writes##bwl(volatile void __iomem *addr,		\
>> +				const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (count) {							\
>> +		const type *buf = buffer;				\
>> +									\
>> +		do {							\
>> +			__raw_write##bwl(*buf++, addr);			\
>> +		} while (--count);					\
>> +	}								\
>> +}
>> +
>> +BUILDS_RW(b, u8)
> 
> Why is this in here?
the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.

It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
those function needed here....

Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.

#ifdef CONFIG_ARM64_INDIRECT_PIO
#define inb inb
extern u8 inb(unsigned long addr);

#define outb outb
extern void outb(u8 value, unsigned long addr);

#define insb insb
extern void insb(unsigned long addr, void *buffer, unsigned int count);

#define outsb outsb
extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
#endif

and definitions of all these functions are in extio.c :

u8 inb(unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		return readb(PCI_IOBASE + addr);
	else
		return arm64_extio_ops->pfin ?
			arm64_extio_ops->pfin(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, NULL,
				sizeof(u8), 1) : -1;
}
.....


> 
>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>  
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#define inb inb
>> +static inline u8 inb(unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +			addr <= arm64_extio_ops->end)
>> +		return extio_inb(addr);
>> +#endif
>> +	return readb(PCI_IOBASE + addr);
>> +}
>> +
> 
> Looks ok, but you only seem to do this for the 8-bit
> accessors, when it should be done for 16-bit and 32-bit
> ones as well for consistency.
Hip06 LPC only support 8-bit I/O operations on the designated port.

> 
>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>> new file mode 100644
>> index 0000000..1e7a9c5
>> --- /dev/null
>> +++ b/drivers/bus/extio.c
>> @@ -0,0 +1,66 @@
> 
> This is in a globally visible directory
> 
>> +
>> +struct extio_ops *arm64_extio_ops;
> 
> But the identifier uses an architecture specific prefix. Either
> move the whole file into arch/arm64, or make the naming so that
> it can be used for everything.

I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

> 
>> +u8 __weak extio_inb(unsigned long addr)
>> +{
>> +	return arm64_extio_ops->pfin ?
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>> +			addr + arm64_extio_ops->ptoffset, NULL,
>> +			sizeof(u8), 1) : -1;
>> +}
> 
> No need for the __weak attribute, just make sure that the
> code is always built-in when needed.
> 
> Also, it doesn't seem necessary to have an extern function if
> all it does is call the one callback that you have already 
> checked earlier. Either put it all into the inline
> definition in asm/io.h, or put it all into the extern
> version like this.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO /* otherwise use default from asm-generic */
> #define inb inb
> extern u8 inb(unsigned long addr);
> #endif
> 
Yes. This is good!
Although the in(s)/out(s) are not inline anymore.

I had applied this way above.

> u8 inb(unsigned long addr)
> {
> 	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> 			addr <= arm64_extio_ops->end)
> 		arm64_extio_ops->pfin(arm64_extio_ops->devpara,addr + arm64_extio_ops->ptoffset, NULL,sizeof(u8), 1) : -1;
> 	return extio_inb(addr);
> }
> 
>> +#define inb inb
>> +static inline u8 inb(unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +			addr <= arm64_extio_ops->end)
>> +		return extio_inb(addr);
>> +#endif
>> +	return readb(PCI_IOBASE + addr);
>> +}
> 
>> diff --git a/include/linux/extio.h b/include/linux/extio.h
>> new file mode 100644
>> index 0000000..08d1fca
>> --- /dev/null
>> +++ b/include/linux/extio.h
>> @@ -0,0 +1,49 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + * Author: Zou Rongrong <@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/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +
>> +typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +typedef void (*outhook)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
> 
> I would drop the typedef and just declare the types directly in the
> only place that references them.
> 
Ok. Will apply it.

Thanks!
Zhichang

> 	Arnd
> 
> .
> 

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 14:16       ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 14:16 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	john.garry-hv44wF8Li93QT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w, liviu.dudau-5wv7dgnIgG8,
	kantyzc-9Onoh4P/yGk, zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w

Hi, Arnd

On 2016/9/14 20:24, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>>
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> 
> Looks ok overall, but I have a couple of comments for details.
> 
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index bc3f00f..9579479 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>  
>> +config ARM64_INDIRECT_PIO
>> +	def_bool n
> 
> 'def_bool n' is the same as the shorter and more common 'bool'.
Yes. Will modify as bool "access peripherals with legacy I/O port"

> 
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 9b6e408..d3acf1f 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -34,6 +34,10 @@
>>  
>>  #include <xen/xen.h>
>>  
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#include <linux/extio.h>
>> +#endif
> 
> No need to guard includes with an #ifdef.
If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.


How about removing everything about the configure item "ARM64_INDIRECT_PIO"?
This will make the indirect-IO mechanism global on ARM64.
I worry about this mechanism is not so common, so using "ARM64_INDIRECT_PIO" make this feature optional.

> 
>> +#define BUILDS_RW(bwl, type)						\
>> +static inline void reads##bwl(const volatile void __iomem *addr,	\
>> +				void *buffer, unsigned int count)	\
>> +{									\
>> +	if (count) {							\
>> +		type *buf = buffer;					\
>> +									\
>> +		do {							\
>> +			type x = __raw_read##bwl(addr);			\
>> +			*buf++ = x;					\
>> +		} while (--count);					\
>> +	}								\
>> +}									\
>> +									\
>> +static inline void writes##bwl(volatile void __iomem *addr,		\
>> +				const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (count) {							\
>> +		const type *buf = buffer;				\
>> +									\
>> +		do {							\
>> +			__raw_write##bwl(*buf++, addr);			\
>> +		} while (--count);					\
>> +	}								\
>> +}
>> +
>> +BUILDS_RW(b, u8)
> 
> Why is this in here?
the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.

It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
those function needed here....

Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.

#ifdef CONFIG_ARM64_INDIRECT_PIO
#define inb inb
extern u8 inb(unsigned long addr);

#define outb outb
extern void outb(u8 value, unsigned long addr);

#define insb insb
extern void insb(unsigned long addr, void *buffer, unsigned int count);

#define outsb outsb
extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
#endif

and definitions of all these functions are in extio.c :

u8 inb(unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		return readb(PCI_IOBASE + addr);
	else
		return arm64_extio_ops->pfin ?
			arm64_extio_ops->pfin(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, NULL,
				sizeof(u8), 1) : -1;
}
.....


> 
>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>  
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#define inb inb
>> +static inline u8 inb(unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +			addr <= arm64_extio_ops->end)
>> +		return extio_inb(addr);
>> +#endif
>> +	return readb(PCI_IOBASE + addr);
>> +}
>> +
> 
> Looks ok, but you only seem to do this for the 8-bit
> accessors, when it should be done for 16-bit and 32-bit
> ones as well for consistency.
Hip06 LPC only support 8-bit I/O operations on the designated port.

> 
>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>> new file mode 100644
>> index 0000000..1e7a9c5
>> --- /dev/null
>> +++ b/drivers/bus/extio.c
>> @@ -0,0 +1,66 @@
> 
> This is in a globally visible directory
> 
>> +
>> +struct extio_ops *arm64_extio_ops;
> 
> But the identifier uses an architecture specific prefix. Either
> move the whole file into arch/arm64, or make the naming so that
> it can be used for everything.

I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

> 
>> +u8 __weak extio_inb(unsigned long addr)
>> +{
>> +	return arm64_extio_ops->pfin ?
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>> +			addr + arm64_extio_ops->ptoffset, NULL,
>> +			sizeof(u8), 1) : -1;
>> +}
> 
> No need for the __weak attribute, just make sure that the
> code is always built-in when needed.
> 
> Also, it doesn't seem necessary to have an extern function if
> all it does is call the one callback that you have already 
> checked earlier. Either put it all into the inline
> definition in asm/io.h, or put it all into the extern
> version like this.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO /* otherwise use default from asm-generic */
> #define inb inb
> extern u8 inb(unsigned long addr);
> #endif
> 
Yes. This is good!
Although the in(s)/out(s) are not inline anymore.

I had applied this way above.

> u8 inb(unsigned long addr)
> {
> 	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> 			addr <= arm64_extio_ops->end)
> 		arm64_extio_ops->pfin(arm64_extio_ops->devpara,addr + arm64_extio_ops->ptoffset, NULL,sizeof(u8), 1) : -1;
> 	return extio_inb(addr);
> }
> 
>> +#define inb inb
>> +static inline u8 inb(unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +			addr <= arm64_extio_ops->end)
>> +		return extio_inb(addr);
>> +#endif
>> +	return readb(PCI_IOBASE + addr);
>> +}
> 
>> diff --git a/include/linux/extio.h b/include/linux/extio.h
>> new file mode 100644
>> index 0000000..08d1fca
>> --- /dev/null
>> +++ b/include/linux/extio.h
>> @@ -0,0 +1,49 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>> + * Author: Zou Rongrong <@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/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +
>> +typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +typedef void (*outhook)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
> 
> I would drop the typedef and just declare the types directly in the
> only place that references them.
> 
Ok. Will apply it.

Thanks!
Zhichang

> 	Arnd
> 
> .
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 14:16       ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 14:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd

On 2016/9/14 20:24, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:51 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
>>
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> 
> Looks ok overall, but I have a couple of comments for details.
> 
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index bc3f00f..9579479 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -161,6 +161,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>  
>> +config ARM64_INDIRECT_PIO
>> +	def_bool n
> 
> 'def_bool n' is the same as the shorter and more common 'bool'.
Yes. Will modify as bool "access peripherals with legacy I/O port"

> 
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 9b6e408..d3acf1f 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -34,6 +34,10 @@
>>  
>>  #include <xen/xen.h>
>>  
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#include <linux/extio.h>
>> +#endif
> 
> No need to guard includes with an #ifdef.
If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.


How about removing everything about the configure item "ARM64_INDIRECT_PIO"?
This will make the indirect-IO mechanism global on ARM64.
I worry about this mechanism is not so common, so using "ARM64_INDIRECT_PIO" make this feature optional.

> 
>> +#define BUILDS_RW(bwl, type)						\
>> +static inline void reads##bwl(const volatile void __iomem *addr,	\
>> +				void *buffer, unsigned int count)	\
>> +{									\
>> +	if (count) {							\
>> +		type *buf = buffer;					\
>> +									\
>> +		do {							\
>> +			type x = __raw_read##bwl(addr);			\
>> +			*buf++ = x;					\
>> +		} while (--count);					\
>> +	}								\
>> +}									\
>> +									\
>> +static inline void writes##bwl(volatile void __iomem *addr,		\
>> +				const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (count) {							\
>> +		const type *buf = buffer;				\
>> +									\
>> +		do {							\
>> +			__raw_write##bwl(*buf++, addr);			\
>> +		} while (--count);					\
>> +	}								\
>> +}
>> +
>> +BUILDS_RW(b, u8)
> 
> Why is this in here?
the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.

It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
those function needed here....

Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.

#ifdef CONFIG_ARM64_INDIRECT_PIO
#define inb inb
extern u8 inb(unsigned long addr);

#define outb outb
extern void outb(u8 value, unsigned long addr);

#define insb insb
extern void insb(unsigned long addr, void *buffer, unsigned int count);

#define outsb outsb
extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
#endif

and definitions of all these functions are in extio.c :

u8 inb(unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		return readb(PCI_IOBASE + addr);
	else
		return arm64_extio_ops->pfin ?
			arm64_extio_ops->pfin(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, NULL,
				sizeof(u8), 1) : -1;
}
.....


> 
>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>  
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#define inb inb
>> +static inline u8 inb(unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +			addr <= arm64_extio_ops->end)
>> +		return extio_inb(addr);
>> +#endif
>> +	return readb(PCI_IOBASE + addr);
>> +}
>> +
> 
> Looks ok, but you only seem to do this for the 8-bit
> accessors, when it should be done for 16-bit and 32-bit
> ones as well for consistency.
Hip06 LPC only support 8-bit I/O operations on the designated port.

> 
>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>> new file mode 100644
>> index 0000000..1e7a9c5
>> --- /dev/null
>> +++ b/drivers/bus/extio.c
>> @@ -0,0 +1,66 @@
> 
> This is in a globally visible directory
> 
>> +
>> +struct extio_ops *arm64_extio_ops;
> 
> But the identifier uses an architecture specific prefix. Either
> move the whole file into arch/arm64, or make the naming so that
> it can be used for everything.

I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

> 
>> +u8 __weak extio_inb(unsigned long addr)
>> +{
>> +	return arm64_extio_ops->pfin ?
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>> +			addr + arm64_extio_ops->ptoffset, NULL,
>> +			sizeof(u8), 1) : -1;
>> +}
> 
> No need for the __weak attribute, just make sure that the
> code is always built-in when needed.
> 
> Also, it doesn't seem necessary to have an extern function if
> all it does is call the one callback that you have already 
> checked earlier. Either put it all into the inline
> definition in asm/io.h, or put it all into the extern
> version like this.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO /* otherwise use default from asm-generic */
> #define inb inb
> extern u8 inb(unsigned long addr);
> #endif
> 
Yes. This is good!
Although the in(s)/out(s) are not inline anymore.

I had applied this way above.

> u8 inb(unsigned long addr)
> {
> 	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> 			addr <= arm64_extio_ops->end)
> 		arm64_extio_ops->pfin(arm64_extio_ops->devpara,addr + arm64_extio_ops->ptoffset, NULL,sizeof(u8), 1) : -1;
> 	return extio_inb(addr);
> }
> 
>> +#define inb inb
>> +static inline u8 inb(unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +			addr <= arm64_extio_ops->end)
>> +		return extio_inb(addr);
>> +#endif
>> +	return readb(PCI_IOBASE + addr);
>> +}
> 
>> diff --git a/include/linux/extio.h b/include/linux/extio.h
>> new file mode 100644
>> index 0000000..08d1fca
>> --- /dev/null
>> +++ b/include/linux/extio.h
>> @@ -0,0 +1,49 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + * Author: Zou Rongrong <@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/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +
>> +typedef u64 (*inhook)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +typedef void (*outhook)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
> 
> I would drop the typedef and just declare the types directly in the
> only place that references them.
> 
Ok. Will apply it.

Thanks!
Zhichang

> 	Arnd
> 
> .
> 

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 14:23         ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 14:23 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: linux-arm-kernel, linux-kernel, linuxarm, devicetree,
	lorenzo.pieralisi, benh, minyard, linux-pci, gabriele.paoloni,
	john.garry, will.deacon, xuwei5, linux-serial, gregkh,
	zourongrong, liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
> > 
> > No need to guard includes with an #ifdef.
> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
 
There is no problem with making declarations visible for functions that
are not part of the kernel, we do that all the time.

> >> +#define BUILDS_RW(bwl, type)                                                \
> >> +static inline void reads##bwl(const volatile void __iomem *addr,    \
> >> +                            void *buffer, unsigned int count)       \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            type *buf = buffer;                                     \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    type x = __raw_read##bwl(addr);                 \
> >> +                    *buf++ = x;                                     \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}                                                                   \
> >> +                                                                    \
> >> +static inline void writes##bwl(volatile void __iomem *addr,         \
> >> +                            const void *buffer, unsigned int count) \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            const type *buf = buffer;                               \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    __raw_write##bwl(*buf++, addr);                 \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}
> >> +
> >> +BUILDS_RW(b, u8)
> > 
> > Why is this in here?
> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
> 
> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
> those function needed here....
> 
> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO
> #define inb inb
> extern u8 inb(unsigned long addr);
> 
> #define outb outb
> extern void outb(u8 value, unsigned long addr);
> 
> #define insb insb
> extern void insb(unsigned long addr, void *buffer, unsigned int count);
> 
> #define outsb outsb
> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
> #endif
> 
> and definitions of all these functions are in extio.c :
> 
> u8 inb(unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 return readb(PCI_IOBASE + addr);
>         else
>                 return arm64_extio_ops->pfin ?
>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, NULL,
>                                 sizeof(u8), 1) : -1;
> }
> .....

Yes, sounds good.

> >> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> >>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
> >>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
> >>  
> >> +
> >> +/*
> >> + * redefine the in(s)b/out(s)b for indirect-IO.
> >> + */
> >> +#define inb inb
> >> +static inline u8 inb(unsigned long addr)
> >> +{
> >> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> >> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> >> +                    addr <= arm64_extio_ops->end)
> >> +            return extio_inb(addr);
> >> +#endif
> >> +    return readb(PCI_IOBASE + addr);
> >> +}
> >> +
> > 
> > Looks ok, but you only seem to do this for the 8-bit
> > accessors, when it should be done for 16-bit and 32-bit
> > ones as well for consistency.
> Hip06 LPC only support 8-bit I/O operations on the designated port.

That is an interesting limitation. Maybe still call the extio operations
and have them do WARN_ON_ONCE() instead?

If you get a driver that calls inw/outw on the range that is owned
by the LPC bus, you otherwise get an unhandled page fault in kernel
space, which is not as nice.

> >> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> >> new file mode 100644
> >> index 0000000..1e7a9c5
> >> --- /dev/null
> >> +++ b/drivers/bus/extio.c
> >> @@ -0,0 +1,66 @@
> > 
> > This is in a globally visible directory
> > 
> >> +
> >> +struct extio_ops *arm64_extio_ops;
> > 
> > But the identifier uses an architecture specific prefix. Either
> > move the whole file into arch/arm64, or make the naming so that
> > it can be used for everything.
> 
> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

Ok, that simplifies it a lot, you can just do everything in asm/io.h then.

	Arnd

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 14:23         ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 14:23 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	john.garry-hv44wF8Li93QT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w, liviu.dudau-5wv7dgnIgG8,
	kantyzc-9Onoh4P/yGk, zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w

On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
> > 
> > No need to guard includes with an #ifdef.
> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
 
There is no problem with making declarations visible for functions that
are not part of the kernel, we do that all the time.

> >> +#define BUILDS_RW(bwl, type)                                                \
> >> +static inline void reads##bwl(const volatile void __iomem *addr,    \
> >> +                            void *buffer, unsigned int count)       \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            type *buf = buffer;                                     \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    type x = __raw_read##bwl(addr);                 \
> >> +                    *buf++ = x;                                     \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}                                                                   \
> >> +                                                                    \
> >> +static inline void writes##bwl(volatile void __iomem *addr,         \
> >> +                            const void *buffer, unsigned int count) \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            const type *buf = buffer;                               \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    __raw_write##bwl(*buf++, addr);                 \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}
> >> +
> >> +BUILDS_RW(b, u8)
> > 
> > Why is this in here?
> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
> 
> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
> those function needed here....
> 
> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO
> #define inb inb
> extern u8 inb(unsigned long addr);
> 
> #define outb outb
> extern void outb(u8 value, unsigned long addr);
> 
> #define insb insb
> extern void insb(unsigned long addr, void *buffer, unsigned int count);
> 
> #define outsb outsb
> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
> #endif
> 
> and definitions of all these functions are in extio.c :
> 
> u8 inb(unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 return readb(PCI_IOBASE + addr);
>         else
>                 return arm64_extio_ops->pfin ?
>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, NULL,
>                                 sizeof(u8), 1) : -1;
> }
> .....

Yes, sounds good.

> >> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> >>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
> >>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
> >>  
> >> +
> >> +/*
> >> + * redefine the in(s)b/out(s)b for indirect-IO.
> >> + */
> >> +#define inb inb
> >> +static inline u8 inb(unsigned long addr)
> >> +{
> >> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> >> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> >> +                    addr <= arm64_extio_ops->end)
> >> +            return extio_inb(addr);
> >> +#endif
> >> +    return readb(PCI_IOBASE + addr);
> >> +}
> >> +
> > 
> > Looks ok, but you only seem to do this for the 8-bit
> > accessors, when it should be done for 16-bit and 32-bit
> > ones as well for consistency.
> Hip06 LPC only support 8-bit I/O operations on the designated port.

That is an interesting limitation. Maybe still call the extio operations
and have them do WARN_ON_ONCE() instead?

If you get a driver that calls inw/outw on the range that is owned
by the LPC bus, you otherwise get an unhandled page fault in kernel
space, which is not as nice.

> >> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> >> new file mode 100644
> >> index 0000000..1e7a9c5
> >> --- /dev/null
> >> +++ b/drivers/bus/extio.c
> >> @@ -0,0 +1,66 @@
> > 
> > This is in a globally visible directory
> > 
> >> +
> >> +struct extio_ops *arm64_extio_ops;
> > 
> > But the identifier uses an architecture specific prefix. Either
> > move the whole file into arch/arm64, or make the naming so that
> > it can be used for everything.
> 
> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

Ok, that simplifies it a lot, you can just do everything in asm/io.h then.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-14 14:23         ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 14:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
> > 
> > No need to guard includes with an #ifdef.
> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
 
There is no problem with making declarations visible for functions that
are not part of the kernel, we do that all the time.

> >> +#define BUILDS_RW(bwl, type)                                                \
> >> +static inline void reads##bwl(const volatile void __iomem *addr,    \
> >> +                            void *buffer, unsigned int count)       \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            type *buf = buffer;                                     \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    type x = __raw_read##bwl(addr);                 \
> >> +                    *buf++ = x;                                     \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}                                                                   \
> >> +                                                                    \
> >> +static inline void writes##bwl(volatile void __iomem *addr,         \
> >> +                            const void *buffer, unsigned int count) \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            const type *buf = buffer;                               \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    __raw_write##bwl(*buf++, addr);                 \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}
> >> +
> >> +BUILDS_RW(b, u8)
> > 
> > Why is this in here?
> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
> 
> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
> those function needed here....
> 
> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO
> #define inb inb
> extern u8 inb(unsigned long addr);
> 
> #define outb outb
> extern void outb(u8 value, unsigned long addr);
> 
> #define insb insb
> extern void insb(unsigned long addr, void *buffer, unsigned int count);
> 
> #define outsb outsb
> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
> #endif
> 
> and definitions of all these functions are in extio.c :
> 
> u8 inb(unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 return readb(PCI_IOBASE + addr);
>         else
>                 return arm64_extio_ops->pfin ?
>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, NULL,
>                                 sizeof(u8), 1) : -1;
> }
> .....

Yes, sounds good.

> >> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> >>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
> >>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
> >>  
> >> +
> >> +/*
> >> + * redefine the in(s)b/out(s)b for indirect-IO.
> >> + */
> >> +#define inb inb
> >> +static inline u8 inb(unsigned long addr)
> >> +{
> >> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> >> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> >> +                    addr <= arm64_extio_ops->end)
> >> +            return extio_inb(addr);
> >> +#endif
> >> +    return readb(PCI_IOBASE + addr);
> >> +}
> >> +
> > 
> > Looks ok, but you only seem to do this for the 8-bit
> > accessors, when it should be done for 16-bit and 32-bit
> > ones as well for consistency.
> Hip06 LPC only support 8-bit I/O operations on the designated port.

That is an interesting limitation. Maybe still call the extio operations
and have them do WARN_ON_ONCE() instead?

If you get a driver that calls inw/outw on the range that is owned
by the LPC bus, you otherwise get an unhandled page fault in kernel
space, which is not as nice.

> >> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> >> new file mode 100644
> >> index 0000000..1e7a9c5
> >> --- /dev/null
> >> +++ b/drivers/bus/extio.c
> >> @@ -0,0 +1,66 @@
> > 
> > This is in a globally visible directory
> > 
> >> +
> >> +struct extio_ops *arm64_extio_ops;
> > 
> > But the identifier uses an architecture specific prefix. Either
> > move the whole file into arch/arm64, or make the naming so that
> > it can be used for everything.
> 
> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

Ok, that simplifies it a lot, you can just do everything in asm/io.h then.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-14 12:33     ` Arnd Bergmann
  (?)
@ 2016-09-14 14:50       ` zhichang.yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 14:50 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: linux-kernel, linuxarm, devicetree, lorenzo.pieralisi, benh,
	minyard, linux-pci, gabriele.paoloni, john.garry, will.deacon,
	xuwei5, linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02



On 2016/9/14 20:33, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:
> 
>> +Required properties:
>> +- compatible: should be "hisilicon,low-pin-count"
>> +- #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 address and length of the register set for the device.
>> +- ranges: define a 1:1 mapping between the I/O space of the child device and
>> +	  the parent.
> 
> Do we still need the "ranges" here? The property in your example seems
> wrong.

I think "ranges" is needed.
without this, of_translate_address --> __of_translate_address --> of_translate_one will fail when translating the child's IO resource.

> 
>> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> 
> You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
The hip06 LPC is defined as isa type.
So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4 of child will be 1:1 mapped as 0xe4.
It means no translation.

> 
>> +/**
>> + * hisilpc_children_map_sysio - setup the mapping between system Io and
>> + *			physical IO
>> + *
>> + * @child: the device whose IO is handling
>> + * @data: some device specific data. For ACPI device, should be NULL.
>> + *
>> + * Returns >=0 means the mapping is successfully created;
>> + * others mean some failures.
>> + */
>> +static int hisilpc_children_map_sysio(struct device * child, void * data)
>> +{
>> +	struct resource *iores;
>> +	unsigned long cpuio;
>> +	struct extio_ops *opsnode;
>> +	int ret;
>> +	struct hisilpc_dev *lpcdev;
>> +
>> +	if (!child || !child->parent)
>> +		return -EINVAL;
>> +
>> +	iores = platform_get_resource_byname(to_platform_device(child),
>> +					IORESOURCE_IO, "dev_io");
>> +	if (!iores)
>> +		return -ENODEV;
>> +
>> +	/*
>> +	 * can not use devm_kzalloc to allocate slab for child before its driver
>> +	 * start probing. Here allocate the slab with the name of parent.
>> +	 */
>> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
>> +	if (!opsnode)
>> +		return -ENOMEM;
>> +
>> +	cpuio = data ? *((unsigned long *)data) : 0;
>> +
>> +	opsnode->start = iores->start;
>> +	opsnode->end = iores->end;
>> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
>> +
>> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
>> +				(unsigned long)iores->start,
>> +				(unsigned long)iores->end,
>> +				opsnode->ptoffset);
>> +
>> +	opsnode->pfin = hisilpc_comm_inb;
>> +	opsnode->pfout = hisilpc_comm_outb;
>> +
>> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
>> +	opsnode->devpara = lpcdev;
>> +
>> +	/* only apply indirect-IO to ipmi child device */
> 
> I don't get this part. The bus driver should not care what its
> children are, just register and PIO ranges that the bus can handle
> in theory, i.e. from 0x000 to 0xfff.

Just as we discussed in V2, the legacy PIO range is specific to some device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
I don't want to occupy a larger PIO range in which only small part PIOs are used by our LPC. At this moment, two PIO ranges are using
through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
If we configure 0-0x1000 for the LPC to cover those two ranges, most PIO are wasted and other PIO device on other buses lose the chance to use the PIO below 0x1000.
Otherwise, PIO conflict will happen. So, My idea is only occupied the PIO ranges which are really needed for the children.

And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
operation registering, serial driver has serial_in/serial_out to be registered. So, only the PIO range for ipmi device is stored in arm64_extio_ops and the indirect-IO
works well for ipmi device.

If we think it is nearly no chance that LPC PIO range conflict with other buses, we can allocate 0xe4 - 0x2ff to LPC and store it to arm64_extio_ops. In this case,
the special processing for ipmi device is not needed.

Best,
Zhichang

> 
> 	Arnd
> 
> 
> .
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 14:50       ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 14:50 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: linux-kernel, linuxarm, devicetree, lorenzo.pieralisi, benh,
	minyard, linux-pci, gabriele.paoloni, john.garry, will.deacon,
	xuwei5, linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02



On 2016/9/14 20:33, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:
> 
>> +Required properties:
>> +- compatible: should be "hisilicon,low-pin-count"
>> +- #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 address and length of the register set for the device.
>> +- ranges: define a 1:1 mapping between the I/O space of the child device and
>> +	  the parent.
> 
> Do we still need the "ranges" here? The property in your example seems
> wrong.

I think "ranges" is needed.
without this, of_translate_address --> __of_translate_address --> of_translate_one will fail when translating the child's IO resource.

> 
>> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> 
> You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
The hip06 LPC is defined as isa type.
So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4 of child will be 1:1 mapped as 0xe4.
It means no translation.

> 
>> +/**
>> + * hisilpc_children_map_sysio - setup the mapping between system Io and
>> + *			physical IO
>> + *
>> + * @child: the device whose IO is handling
>> + * @data: some device specific data. For ACPI device, should be NULL.
>> + *
>> + * Returns >=0 means the mapping is successfully created;
>> + * others mean some failures.
>> + */
>> +static int hisilpc_children_map_sysio(struct device * child, void * data)
>> +{
>> +	struct resource *iores;
>> +	unsigned long cpuio;
>> +	struct extio_ops *opsnode;
>> +	int ret;
>> +	struct hisilpc_dev *lpcdev;
>> +
>> +	if (!child || !child->parent)
>> +		return -EINVAL;
>> +
>> +	iores = platform_get_resource_byname(to_platform_device(child),
>> +					IORESOURCE_IO, "dev_io");
>> +	if (!iores)
>> +		return -ENODEV;
>> +
>> +	/*
>> +	 * can not use devm_kzalloc to allocate slab for child before its driver
>> +	 * start probing. Here allocate the slab with the name of parent.
>> +	 */
>> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
>> +	if (!opsnode)
>> +		return -ENOMEM;
>> +
>> +	cpuio = data ? *((unsigned long *)data) : 0;
>> +
>> +	opsnode->start = iores->start;
>> +	opsnode->end = iores->end;
>> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
>> +
>> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
>> +				(unsigned long)iores->start,
>> +				(unsigned long)iores->end,
>> +				opsnode->ptoffset);
>> +
>> +	opsnode->pfin = hisilpc_comm_inb;
>> +	opsnode->pfout = hisilpc_comm_outb;
>> +
>> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
>> +	opsnode->devpara = lpcdev;
>> +
>> +	/* only apply indirect-IO to ipmi child device */
> 
> I don't get this part. The bus driver should not care what its
> children are, just register and PIO ranges that the bus can handle
> in theory, i.e. from 0x000 to 0xfff.

Just as we discussed in V2, the legacy PIO range is specific to some device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
I don't want to occupy a larger PIO range in which only small part PIOs are used by our LPC. At this moment, two PIO ranges are using
through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
If we configure 0-0x1000 for the LPC to cover those two ranges, most PIO are wasted and other PIO device on other buses lose the chance to use the PIO below 0x1000.
Otherwise, PIO conflict will happen. So, My idea is only occupied the PIO ranges which are really needed for the children.

And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
operation registering, serial driver has serial_in/serial_out to be registered. So, only the PIO range for ipmi device is stored in arm64_extio_ops and the indirect-IO
works well for ipmi device.

If we think it is nearly no chance that LPC PIO range conflict with other buses, we can allocate 0xe4 - 0x2ff to LPC and store it to arm64_extio_ops. In this case,
the special processing for ipmi device is not needed.

Best,
Zhichang

> 
> 	Arnd
> 
> 
> .
> 

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 14:50       ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 14:50 UTC (permalink / raw)
  To: linux-arm-kernel



On 2016/9/14 20:33, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:
> 
>> +Required properties:
>> +- compatible: should be "hisilicon,low-pin-count"
>> +- #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 address and length of the register set for the device.
>> +- ranges: define a 1:1 mapping between the I/O space of the child device and
>> +	  the parent.
> 
> Do we still need the "ranges" here? The property in your example seems
> wrong.

I think "ranges" is needed.
without this, of_translate_address --> __of_translate_address --> of_translate_one will fail when translating the child's IO resource.

> 
>> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> 
> You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
The hip06 LPC is defined as isa type.
So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4 of child will be 1:1 mapped as 0xe4.
It means no translation.

> 
>> +/**
>> + * hisilpc_children_map_sysio - setup the mapping between system Io and
>> + *			physical IO
>> + *
>> + * @child: the device whose IO is handling
>> + * @data: some device specific data. For ACPI device, should be NULL.
>> + *
>> + * Returns >=0 means the mapping is successfully created;
>> + * others mean some failures.
>> + */
>> +static int hisilpc_children_map_sysio(struct device * child, void * data)
>> +{
>> +	struct resource *iores;
>> +	unsigned long cpuio;
>> +	struct extio_ops *opsnode;
>> +	int ret;
>> +	struct hisilpc_dev *lpcdev;
>> +
>> +	if (!child || !child->parent)
>> +		return -EINVAL;
>> +
>> +	iores = platform_get_resource_byname(to_platform_device(child),
>> +					IORESOURCE_IO, "dev_io");
>> +	if (!iores)
>> +		return -ENODEV;
>> +
>> +	/*
>> +	 * can not use devm_kzalloc to allocate slab for child before its driver
>> +	 * start probing. Here allocate the slab with the name of parent.
>> +	 */
>> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
>> +	if (!opsnode)
>> +		return -ENOMEM;
>> +
>> +	cpuio = data ? *((unsigned long *)data) : 0;
>> +
>> +	opsnode->start = iores->start;
>> +	opsnode->end = iores->end;
>> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
>> +
>> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
>> +				(unsigned long)iores->start,
>> +				(unsigned long)iores->end,
>> +				opsnode->ptoffset);
>> +
>> +	opsnode->pfin = hisilpc_comm_inb;
>> +	opsnode->pfout = hisilpc_comm_outb;
>> +
>> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
>> +	opsnode->devpara = lpcdev;
>> +
>> +	/* only apply indirect-IO to ipmi child device */
> 
> I don't get this part. The bus driver should not care what its
> children are, just register and PIO ranges that the bus can handle
> in theory, i.e. from 0x000 to 0xfff.

Just as we discussed in V2, the legacy PIO range is specific to some device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
I don't want to occupy a larger PIO range in which only small part PIOs are used by our LPC. At this moment, two PIO ranges are using
through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
If we configure 0-0x1000 for the LPC to cover those two ranges, most PIO are wasted and other PIO device on other buses lose the chance to use the PIO below 0x1000.
Otherwise, PIO conflict will happen. So, My idea is only occupied the PIO ranges which are really needed for the children.

And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
operation registering, serial driver has serial_in/serial_out to be registered. So, only the PIO range for ipmi device is stored in arm64_extio_ops and the indirect-IO
works well for ipmi device.

If we think it is nearly no chance that LPC PIO range conflict with other buses, we can allocate 0xe4 - 0x2ff to LPC and store it to arm64_extio_ops. In this case,
the special processing for ipmi device is not needed.

Best,
Zhichang

> 
> 	Arnd
> 
> 
> .
> 

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
  2016-09-14 12:25     ` Arnd Bergmann
  (?)
@ 2016-09-14 15:04       ` zhichang.yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 15:04 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: linux-kernel, linuxarm, devicetree, lorenzo.pieralisi, benh,
	minyard, linux-pci, gabriele.paoloni, john.garry, will.deacon,
	xuwei5, linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02



On 2016/9/14 20:25, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
>>
>> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
>> controlled through the LPC I/O cycles. After registering the LPC uart specific
>> serial_in/serial_out to 8250 core driver, serial data can be read/written
>> through the LPC.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>
> 
> I still think this should be handled by 8250_of.c after the addition of
> support for IORESOURCE_IO.

The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :

+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),

So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
driver file.

best,
Zhichang


> 
> 	Arnd
> 
> 
> .
> 

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 15:04       ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 15:04 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	john.garry-hv44wF8Li93QT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w, liviu.dudau-5wv7dgnIgG8,
	kantyzc-9Onoh4P/yGk, zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w



On 2016/9/14 20:25, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>>
>> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
>> controlled through the LPC I/O cycles. After registering the LPC uart specific
>> serial_in/serial_out to 8250 core driver, serial data can be read/written
>> through the LPC.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
>>
> 
> I still think this should be handled by 8250_of.c after the addition of
> support for IORESOURCE_IO.

The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :

+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),

So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
driver file.

best,
Zhichang


> 
> 	Arnd
> 
> 
> .
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 15:04       ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-14 15:04 UTC (permalink / raw)
  To: linux-arm-kernel



On 2016/9/14 20:25, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
>>
>> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
>> controlled through the LPC I/O cycles. After registering the LPC uart specific
>> serial_in/serial_out to 8250 core driver, serial data can be read/written
>> through the LPC.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>
> 
> I still think this should be handled by 8250_of.c after the addition of
> support for IORESOURCE_IO.

The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :

+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),

So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
driver file.

best,
Zhichang


> 
> 	Arnd
> 
> 
> .
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-14 14:50       ` zhichang.yuan
@ 2016-09-14 21:32         ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 21:32 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, benh, john.garry, will.deacon, linux-kernel,
	xuwei5, linuxarm, linux-serial, linux-pci, zourongrong,
	liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
> 
> On 2016/9/14 20:33, Arnd Bergmann wrote:
> > On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:
> > 
> >> +Required properties:
> >> +- compatible: should be "hisilicon,low-pin-count"
> >> +- #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 address and length of the register set for the device.
> >> +- ranges: define a 1:1 mapping between the I/O space of the child device and
> >> +	  the parent.
> > 
> > Do we still need the "ranges" here? The property in your example seems
> > wrong.
> 
> I think "ranges" is needed.
> without this, of_translate_address --> __of_translate_address --> of_translate_one will fail when translating the child's IO resource.
>
> > 
> >> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> > 
> > You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
> The hip06 LPC is defined as isa type.
> So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4 of child will be 1:1 mapped as 0xe4.
> It means no translation.

No, "no translation" would be leaving out the ranges, we should
fix the code so it handles this case according to the specification
of the ISA DT binding, rather than adding an incorrect ranges
property to make it work with the incorrect Linux implementation.

of_translate_address() should fail here, and whichever code calls
it should try something else, possibly something we have to
implement that can return the correct IORESOURCE_* type.

> > 
> > I don't get this part. The bus driver should not care what its
> > children are, just register and PIO ranges that the bus can handle
> > in theory, i.e. from 0x000 to 0xfff.
> 
> Just as we discussed in V2, the legacy PIO range is specific to some
> device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
> I don't want to occupy a larger PIO range in which only small part PIOs
> are used by our LPC. At this moment, two PIO ranges are using
> through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
>
> If we configure 0-0x1000 for the LPC to cover those two ranges, most
> PIO are wasted and other PIO device on other buses lose the chance to
> use the PIO below 0x1000.
> Otherwise, PIO conflict will happen. So, My idea is only occupied
> the PIO ranges which are really needed for the children.

The only thing it can realistically conflict with would be another
LPC bus behind on a PCI host bridge. On ARM64, all regular PCI
devices that have IORESOURCE_IO ports are intentionally moved
to (bus) port numbers above 0x1000.

> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
> operation registering, serial driver has serial_in/serial_out to
> be registered. So, only the PIO range for ipmi device is stored
> in arm64_extio_ops and the indirect-IO
> works well for ipmi device.

You should not do that in the serial driver, please just use the
normal 8250 driver that works fine once you handle the entire
port range.
 

	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-14 21:32         ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 21:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
> 
> On 2016/9/14 20:33, Arnd Bergmann wrote:
> > On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:
> > 
> >> +Required properties:
> >> +- compatible: should be "hisilicon,low-pin-count"
> >> +- #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 address and length of the register set for the device.
> >> +- ranges: define a 1:1 mapping between the I/O space of the child device and
> >> +	  the parent.
> > 
> > Do we still need the "ranges" here? The property in your example seems
> > wrong.
> 
> I think "ranges" is needed.
> without this, of_translate_address --> __of_translate_address --> of_translate_one will fail when translating the child's IO resource.
>
> > 
> >> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> > 
> > You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
> The hip06 LPC is defined as isa type.
> So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4 of child will be 1:1 mapped as 0xe4.
> It means no translation.

No, "no translation" would be leaving out the ranges, we should
fix the code so it handles this case according to the specification
of the ISA DT binding, rather than adding an incorrect ranges
property to make it work with the incorrect Linux implementation.

of_translate_address() should fail here, and whichever code calls
it should try something else, possibly something we have to
implement that can return the correct IORESOURCE_* type.

> > 
> > I don't get this part. The bus driver should not care what its
> > children are, just register and PIO ranges that the bus can handle
> > in theory, i.e. from 0x000 to 0xfff.
> 
> Just as we discussed in V2, the legacy PIO range is specific to some
> device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
> I don't want to occupy a larger PIO range in which only small part PIOs
> are used by our LPC. At this moment, two PIO ranges are using
> through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
>
> If we configure 0-0x1000 for the LPC to cover those two ranges, most
> PIO are wasted and other PIO device on other buses lose the chance to
> use the PIO below 0x1000.
> Otherwise, PIO conflict will happen. So, My idea is only occupied
> the PIO ranges which are really needed for the children.

The only thing it can realistically conflict with would be another
LPC bus behind on a PCI host bridge. On ARM64, all regular PCI
devices that have IORESOURCE_IO ports are intentionally moved
to (bus) port numbers above 0x1000.

> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
> operation registering, serial driver has serial_in/serial_out to
> be registered. So, only the PIO range for ipmi device is stored
> in arm64_extio_ops and the indirect-IO
> works well for ipmi device.

You should not do that in the serial driver, please just use the
normal 8250 driver that works fine once you handle the entire
port range.
 

	Arnd

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
  2016-09-14 15:04       ` zhichang.yuan
@ 2016-09-14 21:33         ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 21:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, benh, john.garry, will.deacon, linux-kernel,
	xuwei5, linuxarm, linux-serial, linux-pci, zourongrong,
	liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, September 14, 2016 11:04:33 PM CEST zhichang.yuan wrote:
> The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :
> 
> +static struct platform_driver hs_lpc8250_driver = {
> +       .driver = {
> +               .name           = "hisi-lpc-uart",
> +               .of_match_table = hs8250_of_match,
> +               .acpi_match_table = ACPI_PTR(hs8250_acpi_match),
> 
> So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
> driver file.
> 

After looking again, I'm pretty sure that drivers/tty/serial/8250/8250_pnp.c
will handle the ACPI case without modifications, you just need to adapt
the 8250_of driver to handle IORESOURCE_IO ports. This will be required
anyway with the next version once the LPC bridge is on the PCI bus.

	Arnd

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-14 21:33         ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-14 21:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 14, 2016 11:04:33 PM CEST zhichang.yuan wrote:
> The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :
> 
> +static struct platform_driver hs_lpc8250_driver = {
> +       .driver = {
> +               .name           = "hisi-lpc-uart",
> +               .of_match_table = hs8250_of_match,
> +               .acpi_match_table = ACPI_PTR(hs8250_acpi_match),
> 
> So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
> driver file.
> 

After looking again, I'm pretty sure that drivers/tty/serial/8250/8250_pnp.c
will handle the ACPI case without modifications, you just need to adapt
the 8250_of driver to handle IORESOURCE_IO ports. This will be required
anyway with the next version once the LPC bridge is on the PCI bus.

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-14 21:32         ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-15  8:02           ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15  8:02 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Yuanzhichang, devicetree, lorenzo.pieralisi, minyard, gregkh,
	benh, John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, linux-serial, linux-pci, zourongrong, liviu.dudau,
	kantyzc, zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 14 September 2016 22:32
> To: linux-arm-kernel@lists.infradead.org
> Cc: Yuanzhichang; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; Gabriele Paoloni; minyard@acm.org;
> gregkh@linuxfoundation.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial@vger.kernel.org; linux-pci@vger.kernel.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
> >
> > On 2016/9/14 20:33, Arnd Bergmann wrote:
> > > On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan
> wrote:
> > >
> > >> +Required properties:
> > >> +- compatible: should be "hisilicon,low-pin-count"
> > >> +- #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 address and length of the register set for the
> device.
> > >> +- ranges: define a 1:1 mapping between the I/O space of the child
> device and
> > >> +	  the parent.
> > >
> > > Do we still need the "ranges" here? The property in your example
> seems
> > > wrong.
> >
> > I think "ranges" is needed.
> > without this, of_translate_address --> __of_translate_address -->
> of_translate_one will fail when translating the child's IO resource.
> >
> > >
> > >> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> > >
> > > You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
> > The hip06 LPC is defined as isa type.
> > So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4
> of child will be 1:1 mapped as 0xe4.
> > It means no translation.
> 
> No, "no translation" would be leaving out the ranges, we should
> fix the code so it handles this case according to the specification
> of the ISA DT binding, rather than adding an incorrect ranges
> property to make it work with the incorrect Linux implementation.
> 
> of_translate_address() should fail here, and whichever code calls
> it should try something else, possibly something we have to
> implement that can return the correct IORESOURCE_* type.

>From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps

I quote:
"There shall be an entry in the "ranges" property for each
of the Memory and/or I/O spaces if that address space is
mapped through the bridge."

It seems to me that it is ok to have 1:1 address mapping and that
therefore of_translate_address() should fail if "ranges" is not
present.

This is also explained quite well in
http://lxr.free-electrons.com/source/drivers/of/address.c#L490

what do you think?

Thanks

Gab

> 
> > >
> > > I don't get this part. The bus driver should not care what its
> > > children are, just register and PIO ranges that the bus can handle
> > > in theory, i.e. from 0x000 to 0xfff.
> >
> > Just as we discussed in V2, the legacy PIO range is specific to some
> > device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
> > I don't want to occupy a larger PIO range in which only small part
> PIOs
> > are used by our LPC. At this moment, two PIO ranges are using
> > through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
> >
> > If we configure 0-0x1000 for the LPC to cover those two ranges, most
> > PIO are wasted and other PIO device on other buses lose the chance to
> > use the PIO below 0x1000.
> > Otherwise, PIO conflict will happen. So, My idea is only occupied
> > the PIO ranges which are really needed for the children.
> 
> The only thing it can realistically conflict with would be another
> LPC bus behind on a PCI host bridge. On ARM64, all regular PCI
> devices that have IORESOURCE_IO ports are intentionally moved
> to (bus) port numbers above 0x1000.
> 
> > And there are probably multiple child devices under LPC, the global
> arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi
> driver can not support I/O
> > operation registering, serial driver has serial_in/serial_out to
> > be registered. So, only the PIO range for ipmi device is stored
> > in arm64_extio_ops and the indirect-IO
> > works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.
> 
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15  8:02           ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15  8:02 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 14 September 2016 22:32
> To: linux-arm-kernel@lists.infradead.org
> Cc: Yuanzhichang; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; Gabriele Paoloni; minyard@acm.org;
> gregkh@linuxfoundation.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial@vger.kernel.org; linux-pci@vger.kernel.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
> >
> > On 2016/9/14 20:33, Arnd Bergmann wrote:
> > > On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan
> wrote:
> > >
> > >> +Required properties:
> > >> +- compatible: should be "hisilicon,low-pin-count"
> > >> +- #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 address and length of the register set for the
> device.
> > >> +- ranges: define a 1:1 mapping between the I/O space of the child
> device and
> > >> +	  the parent.
> > >
> > > Do we still need the "ranges" here? The property in your example
> seems
> > > wrong.
> >
> > I think "ranges" is needed.
> > without this, of_translate_address --> __of_translate_address -->
> of_translate_one will fail when translating the child's IO resource.
> >
> > >
> > >> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> > >
> > > You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
> > The hip06 LPC is defined as isa type.
> > So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4
> of child will be 1:1 mapped as 0xe4.
> > It means no translation.
> 
> No, "no translation" would be leaving out the ranges, we should
> fix the code so it handles this case according to the specification
> of the ISA DT binding, rather than adding an incorrect ranges
> property to make it work with the incorrect Linux implementation.
> 
> of_translate_address() should fail here, and whichever code calls
> it should try something else, possibly something we have to
> implement that can return the correct IORESOURCE_* type.

>From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps

I quote:
"There shall be an entry in the "ranges" property for each
of the Memory and/or I/O spaces if that address space is
mapped through the bridge."

It seems to me that it is ok to have 1:1 address mapping and that
therefore of_translate_address() should fail if "ranges" is not
present.

This is also explained quite well in
http://lxr.free-electrons.com/source/drivers/of/address.c#L490

what do you think?

Thanks

Gab

> 
> > >
> > > I don't get this part. The bus driver should not care what its
> > > children are, just register and PIO ranges that the bus can handle
> > > in theory, i.e. from 0x000 to 0xfff.
> >
> > Just as we discussed in V2, the legacy PIO range is specific to some
> > device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
> > I don't want to occupy a larger PIO range in which only small part
> PIOs
> > are used by our LPC. At this moment, two PIO ranges are using
> > through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
> >
> > If we configure 0-0x1000 for the LPC to cover those two ranges, most
> > PIO are wasted and other PIO device on other buses lose the chance to
> > use the PIO below 0x1000.
> > Otherwise, PIO conflict will happen. So, My idea is only occupied
> > the PIO ranges which are really needed for the children.
> 
> The only thing it can realistically conflict with would be another
> LPC bus behind on a PCI host bridge. On ARM64, all regular PCI
> devices that have IORESOURCE_IO ports are intentionally moved
> to (bus) port numbers above 0x1000.
> 
> > And there are probably multiple child devices under LPC, the global
> arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi
> driver can not support I/O
> > operation registering, serial driver has serial_in/serial_out to
> > be registered. So, only the PIO range for ipmi device is stored
> > in arm64_extio_ops and the indirect-IO
> > works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.
> 
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15  8:02           ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15  8:02 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 14 September 2016 22:32
> To: linux-arm-kernel@lists.infradead.org
> Cc: Yuanzhichang; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; Gabriele Paoloni; minyard@acm.org;
> gregkh@linuxfoundation.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial@vger.kernel.org; linux-pci@vger.kernel.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
> >
> > On 2016/9/14 20:33, Arnd Bergmann wrote:
> > > On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan
> wrote:
> > >
> > >> +Required properties:
> > >> +- compatible: should be "hisilicon,low-pin-count"
> > >> +- #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 address and length of the register set for the
> device.
> > >> +- ranges: define a 1:1 mapping between the I/O space of the child
> device and
> > >> +	  the parent.
> > >
> > > Do we still need the "ranges" here? The property in your example
> seems
> > > wrong.
> >
> > I think "ranges" is needed.
> > without this, of_translate_address --> __of_translate_address -->
> of_translate_one will fail when translating the child's IO resource.
> >
> > >
> > >> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> > >
> > > You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
> > The hip06 LPC is defined as isa type.
> > So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4
> of child will be 1:1 mapped as 0xe4.
> > It means no translation.
> 
> No, "no translation" would be leaving out the ranges, we should
> fix the code so it handles this case according to the specification
> of the ISA DT binding, rather than adding an incorrect ranges
> property to make it work with the incorrect Linux implementation.
> 
> of_translate_address() should fail here, and whichever code calls
> it should try something else, possibly something we have to
> implement that can return the correct IORESOURCE_* type.

>From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps

I quote:
"There shall be an entry in the "ranges" property for each
of the Memory and/or I/O spaces if that address space is
mapped through the bridge."

It seems to me that it is ok to have 1:1 address mapping and that
therefore of_translate_address() should fail if "ranges" is not
present.

This is also explained quite well in
http://lxr.free-electrons.com/source/drivers/of/address.c#L490

what do you think?

Thanks

Gab

> 
> > >
> > > I don't get this part. The bus driver should not care what its
> > > children are, just register and PIO ranges that the bus can handle
> > > in theory, i.e. from 0x000 to 0xfff.
> >
> > Just as we discussed in V2, the legacy PIO range is specific to some
> > device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
> > I don't want to occupy a larger PIO range in which only small part
> PIOs
> > are used by our LPC. At this moment, two PIO ranges are using
> > through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
> >
> > If we configure 0-0x1000 for the LPC to cover those two ranges, most
> > PIO are wasted and other PIO device on other buses lose the chance to
> > use the PIO below 0x1000.
> > Otherwise, PIO conflict will happen. So, My idea is only occupied
> > the PIO ranges which are really needed for the children.
> 
> The only thing it can realistically conflict with would be another
> LPC bus behind on a PCI host bridge. On ARM64, all regular PCI
> devices that have IORESOURCE_IO ports are intentionally moved
> to (bus) port numbers above 0x1000.
> 
> > And there are probably multiple child devices under LPC, the global
> arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi
> driver can not support I/O
> > operation registering, serial driver has serial_in/serial_out to
> > be registered. So, only the PIO range for ipmi device is stored
> > in arm64_extio_ops and the indirect-IO
> > works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.
> 
> 
> 	Arnd

_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15  8:02           ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15  8:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 14 September 2016 22:32
> To: linux-arm-kernel at lists.infradead.org
> Cc: Yuanzhichang; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; Gabriele Paoloni; minyard at acm.org;
> gregkh at linuxfoundation.org; benh at kernel.crashing.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial at vger.kernel.org; linux-pci at vger.kernel.org;
> zourongrong at gmail.com; liviu.dudau at arm.com; kantyzc at 163.com;
> zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
> >
> > On 2016/9/14 20:33, Arnd Bergmann wrote:
> > > On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan
> wrote:
> > >
> > >> +Required properties:
> > >> +- compatible: should be "hisilicon,low-pin-count"
> > >> +- #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 address and length of the register set for the
> device.
> > >> +- ranges: define a 1:1 mapping between the I/O space of the child
> device and
> > >> +	  the parent.
> > >
> > > Do we still need the "ranges" here? The property in your example
> seems
> > > wrong.
> >
> > I think "ranges" is needed.
> > without this, of_translate_address --> __of_translate_address -->
> of_translate_one will fail when translating the child's IO resource.
> >
> > >
> > >> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> > >
> > > You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
> > The hip06 LPC is defined as isa type.
> > So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4
> of child will be 1:1 mapped as 0xe4.
> > It means no translation.
> 
> No, "no translation" would be leaving out the ranges, we should
> fix the code so it handles this case according to the specification
> of the ISA DT binding, rather than adding an incorrect ranges
> property to make it work with the incorrect Linux implementation.
> 
> of_translate_address() should fail here, and whichever code calls
> it should try something else, possibly something we have to
> implement that can return the correct IORESOURCE_* type.

>From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps

I quote:
"There shall be an entry in the "ranges" property for each
of the Memory and/or I/O spaces if that address space is
mapped through the bridge."

It seems to me that it is ok to have 1:1 address mapping and that
therefore of_translate_address() should fail if "ranges" is not
present.

This is also explained quite well in
http://lxr.free-electrons.com/source/drivers/of/address.c#L490

what do you think?

Thanks

Gab

> 
> > >
> > > I don't get this part. The bus driver should not care what its
> > > children are, just register and PIO ranges that the bus can handle
> > > in theory, i.e. from 0x000 to 0xfff.
> >
> > Just as we discussed in V2, the legacy PIO range is specific to some
> > device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
> > I don't want to occupy a larger PIO range in which only small part
> PIOs
> > are used by our LPC. At this moment, two PIO ranges are using
> > through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
> >
> > If we configure 0-0x1000 for the LPC to cover those two ranges, most
> > PIO are wasted and other PIO device on other buses lose the chance to
> > use the PIO below 0x1000.
> > Otherwise, PIO conflict will happen. So, My idea is only occupied
> > the PIO ranges which are really needed for the children.
> 
> The only thing it can realistically conflict with would be another
> LPC bus behind on a PCI host bridge. On ARM64, all regular PCI
> devices that have IORESOURCE_IO ports are intentionally moved
> to (bus) port numbers above 0x1000.
> 
> > And there are probably multiple child devices under LPC, the global
> arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi
> driver can not support I/O
> > operation registering, serial driver has serial_in/serial_out to
> > be registered. So, only the PIO range for ipmi device is stored
> > in arm64_extio_ops and the indirect-IO
> > works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.
> 
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-15  8:02           ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-15  8:22             ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15  8:22 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, Yuanzhichang, devicetree, lorenzo.pieralisi,
	minyard, gregkh, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, linux-serial, linux-pci, zourongrong, liviu.dudau,
	kantyzc, zhichang.yuan02

On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> 
> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> 
> I quote:
> "There shall be an entry in the "ranges" property for each
> of the Memory and/or I/O spaces if that address space is
> mapped through the bridge."
> 
> It seems to me that it is ok to have 1:1 address mapping and that
> therefore of_translate_address() should fail if "ranges" is not
> present.

The key here is the definition of "mapped through the bridge".
I can only understand this as "directly mapped", i.e. an I/O
port of the child bus corresponds directly to a memory address
on the parent bus, but this is not the case here.

The problem with adding the mapping here is that it looks
like it should be valid to create a page table entry for
the address returned from the translation and access it through
a pointer dereference, but that is clearly not possible.

> This is also explained quite well in
> http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> 
> what do you think?

This is a separate issue, and only relevant for Apple Macintosh
machines as well as the PA-Semi sdc.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15  8:22             ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15  8:22 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, gregkh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02, linux-arm-kernel@lists.infradead.org

On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> 
> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> 
> I quote:
> "There shall be an entry in the "ranges" property for each
> of the Memory and/or I/O spaces if that address space is
> mapped through the bridge."
> 
> It seems to me that it is ok to have 1:1 address mapping and that
> therefore of_translate_address() should fail if "ranges" is not
> present.

The key here is the definition of "mapped through the bridge".
I can only understand this as "directly mapped", i.e. an I/O
port of the child bus corresponds directly to a memory address
on the parent bus, but this is not the case here.

The problem with adding the mapping here is that it looks
like it should be valid to create a page table entry for
the address returned from the translation and access it through
a pointer dereference, but that is clearly not possible.

> This is also explained quite well in
> http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> 
> what do you think?

This is a separate issue, and only relevant for Apple Macintosh
machines as well as the PA-Semi sdc.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15  8:22             ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15  8:22 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, Yuanzhichang, devicetree, lorenzo.pieralisi,
	minyard, gregkh, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, linux-serial, linux-pci, zourongrong, liviu.dudau,
	kantyzc, zhichang.yuan02

On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> 
> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> 
> I quote:
> "There shall be an entry in the "ranges" property for each
> of the Memory and/or I/O spaces if that address space is
> mapped through the bridge."
> 
> It seems to me that it is ok to have 1:1 address mapping and that
> therefore of_translate_address() should fail if "ranges" is not
> present.

The key here is the definition of "mapped through the bridge".
I can only understand this as "directly mapped", i.e. an I/O
port of the child bus corresponds directly to a memory address
on the parent bus, but this is not the case here.

The problem with adding the mapping here is that it looks
like it should be valid to create a page table entry for
the address returned from the translation and access it through
a pointer dereference, but that is clearly not possible.

> This is also explained quite well in
> http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> 
> what do you think?

This is a separate issue, and only relevant for Apple Macintosh
machines as well as the PA-Semi sdc.

	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15  8:22             ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15  8:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> 
> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in 
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> 
> I quote:
> "There shall be an entry in the "ranges" property for each
> of the Memory and/or I/O spaces if that address space is
> mapped through the bridge."
> 
> It seems to me that it is ok to have 1:1 address mapping and that
> therefore of_translate_address() should fail if "ranges" is not
> present.

The key here is the definition of "mapped through the bridge".
I can only understand this as "directly mapped", i.e. an I/O
port of the child bus corresponds directly to a memory address
on the parent bus, but this is not the case here.

The problem with adding the mapping here is that it looks
like it should be valid to create a page table entry for
the address returned from the translation and access it through
a pointer dereference, but that is clearly not possible.

> This is also explained quite well in
> http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> 
> what do you think?

This is a separate issue, and only relevant for Apple Macintosh
machines as well as the PA-Semi sdc.

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-15  8:22             ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-15 12:05               ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 12:05 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Yuanzhichang, devicetree, lorenzo.pieralisi,
	minyard, gregkh, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, linux-serial, linux-pci, zourongrong, liviu.dudau,
	kantyzc, zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 15 September 2016 09:22
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> gregkh@linuxfoundation.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial@vger.kernel.org; linux-pci@vger.kernel.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> >
> > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >
> > I quote:
> > "There shall be an entry in the "ranges" property for each
> > of the Memory and/or I/O spaces if that address space is
> > mapped through the bridge."
> >
> > It seems to me that it is ok to have 1:1 address mapping and that
> > therefore of_translate_address() should fail if "ranges" is not
> > present.
> 
> The key here is the definition of "mapped through the bridge".
> I can only understand this as "directly mapped", i.e. an I/O
> port of the child bus corresponds directly to a memory address
> on the parent bus, but this is not the case here.
> 
> The problem with adding the mapping here is that it looks
> like it should be valid to create a page table entry for
> the address returned from the translation and access it through
> a pointer dereference, but that is clearly not possible.

I understand that somehow we are abusing of the ranges property
here however the point is that with the current implementation ranges
is needed because otherwise the ipmi driver probe will fail here:

of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
-> of_translate_address -> __of_translate_address

Now we had a bit of discussion internally and to avoid
having ranges we came up with two possible solutions:

1) Using bit 3 of phys.hi cell in 2.2.1 of
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
This would mean reworking of_bus_isa_get_flags in 
http://lxr.free-electrons.com/source/drivers/of/address.c#L398
and setting a new flag to be checked in __of_address_to_resource

2) Adding a property in the bindings of each device that is
a child of our LPC bus and modify __of_address_to_resource
to check if the property is in the DT and eventually bypass
of_translate_address

However in both 1) and 2) there are some issues:
in 1) we are not complying with the isa binding doc (we use
a bit that should be zero); in 2) we need to modify the
bindings documentation of the devices that are connected
to our LPC controller (therefore modifying other devices
bindings to fit our special case).

I think that maybe having the 1:1 range mapping doesn't
reflect well the reality but it is the less painful
solution...

What's your view?
 
Many Thanks

Gab

> 
> > This is also explained quite well in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> >
> > what do you think?
> 
> This is a separate issue, and only relevant for Apple Macintosh
> machines as well as the PA-Semi sdc.
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 12:05               ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 12:05 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, gregkh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02, linux-arm-kernel@lists.infradead.org

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 15 September 2016 09:22
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> gregkh@linuxfoundation.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial@vger.kernel.org; linux-pci@vger.kernel.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> >
> > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >
> > I quote:
> > "There shall be an entry in the "ranges" property for each
> > of the Memory and/or I/O spaces if that address space is
> > mapped through the bridge."
> >
> > It seems to me that it is ok to have 1:1 address mapping and that
> > therefore of_translate_address() should fail if "ranges" is not
> > present.
> 
> The key here is the definition of "mapped through the bridge".
> I can only understand this as "directly mapped", i.e. an I/O
> port of the child bus corresponds directly to a memory address
> on the parent bus, but this is not the case here.
> 
> The problem with adding the mapping here is that it looks
> like it should be valid to create a page table entry for
> the address returned from the translation and access it through
> a pointer dereference, but that is clearly not possible.

I understand that somehow we are abusing of the ranges property
here however the point is that with the current implementation ranges
is needed because otherwise the ipmi driver probe will fail here:

of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
-> of_translate_address -> __of_translate_address

Now we had a bit of discussion internally and to avoid
having ranges we came up with two possible solutions:

1) Using bit 3 of phys.hi cell in 2.2.1 of
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
This would mean reworking of_bus_isa_get_flags in 
http://lxr.free-electrons.com/source/drivers/of/address.c#L398
and setting a new flag to be checked in __of_address_to_resource

2) Adding a property in the bindings of each device that is
a child of our LPC bus and modify __of_address_to_resource
to check if the property is in the DT and eventually bypass
of_translate_address

However in both 1) and 2) there are some issues:
in 1) we are not complying with the isa binding doc (we use
a bit that should be zero); in 2) we need to modify the
bindings documentation of the devices that are connected
to our LPC controller (therefore modifying other devices
bindings to fit our special case).

I think that maybe having the 1:1 range mapping doesn't
reflect well the reality but it is the less painful
solution...

What's your view?
 
Many Thanks

Gab

> 
> > This is also explained quite well in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> >
> > what do you think?
> 
> This is a separate issue, and only relevant for Apple Macintosh
> machines as well as the PA-Semi sdc.
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 12:05               ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 12:05 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Yuanzhichang, devicetree, lorenzo.pieralisi,
	minyard, gregkh, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, linux-serial, linux-pci, zourongrong, liviu.dudau,
	kantyzc, zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 15 September 2016 09:22
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> gregkh@linuxfoundation.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial@vger.kernel.org; linux-pci@vger.kernel.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> >
> > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >
> > I quote:
> > "There shall be an entry in the "ranges" property for each
> > of the Memory and/or I/O spaces if that address space is
> > mapped through the bridge."
> >
> > It seems to me that it is ok to have 1:1 address mapping and that
> > therefore of_translate_address() should fail if "ranges" is not
> > present.
> 
> The key here is the definition of "mapped through the bridge".
> I can only understand this as "directly mapped", i.e. an I/O
> port of the child bus corresponds directly to a memory address
> on the parent bus, but this is not the case here.
> 
> The problem with adding the mapping here is that it looks
> like it should be valid to create a page table entry for
> the address returned from the translation and access it through
> a pointer dereference, but that is clearly not possible.

I understand that somehow we are abusing of the ranges property
here however the point is that with the current implementation ranges
is needed because otherwise the ipmi driver probe will fail here:

of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
-> of_translate_address -> __of_translate_address

Now we had a bit of discussion internally and to avoid
having ranges we came up with two possible solutions:

1) Using bit 3 of phys.hi cell in 2.2.1 of
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
This would mean reworking of_bus_isa_get_flags in 
http://lxr.free-electrons.com/source/drivers/of/address.c#L398
and setting a new flag to be checked in __of_address_to_resource

2) Adding a property in the bindings of each device that is
a child of our LPC bus and modify __of_address_to_resource
to check if the property is in the DT and eventually bypass
of_translate_address

However in both 1) and 2) there are some issues:
in 1) we are not complying with the isa binding doc (we use
a bit that should be zero); in 2) we need to modify the
bindings documentation of the devices that are connected
to our LPC controller (therefore modifying other devices
bindings to fit our special case).

I think that maybe having the 1:1 range mapping doesn't
reflect well the reality but it is the less painful
solution...

What's your view?
 
Many Thanks

Gab

> 
> > This is also explained quite well in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> >
> > what do you think?
> 
> This is a separate issue, and only relevant for Apple Macintosh
> machines as well as the PA-Semi sdc.
> 
> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 12:05               ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 12:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 15 September 2016 09:22
> To: Gabriele Paoloni
> Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> gregkh at linuxfoundation.org; benh at kernel.crashing.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; xuwei (O); Linuxarm;
> linux-serial at vger.kernel.org; linux-pci at vger.kernel.org;
> zourongrong at gmail.com; liviu.dudau at arm.com; kantyzc at 163.com;
> zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> >
> > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >
> > I quote:
> > "There shall be an entry in the "ranges" property for each
> > of the Memory and/or I/O spaces if that address space is
> > mapped through the bridge."
> >
> > It seems to me that it is ok to have 1:1 address mapping and that
> > therefore of_translate_address() should fail if "ranges" is not
> > present.
> 
> The key here is the definition of "mapped through the bridge".
> I can only understand this as "directly mapped", i.e. an I/O
> port of the child bus corresponds directly to a memory address
> on the parent bus, but this is not the case here.
> 
> The problem with adding the mapping here is that it looks
> like it should be valid to create a page table entry for
> the address returned from the translation and access it through
> a pointer dereference, but that is clearly not possible.

I understand that somehow we are abusing of the ranges property
here however the point is that with the current implementation ranges
is needed because otherwise the ipmi driver probe will fail here:

of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
-> of_translate_address -> __of_translate_address

Now we had a bit of discussion internally and to avoid
having ranges we came up with two possible solutions:

1) Using bit 3 of phys.hi cell in 2.2.1 of
http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
This would mean reworking of_bus_isa_get_flags in 
http://lxr.free-electrons.com/source/drivers/of/address.c#L398
and setting a new flag to be checked in __of_address_to_resource

2) Adding a property in the bindings of each device that is
a child of our LPC bus and modify __of_address_to_resource
to check if the property is in the DT and eventually bypass
of_translate_address

However in both 1) and 2) there are some issues:
in 1) we are not complying with the isa binding doc (we use
a bit that should be zero); in 2) we need to modify the
bindings documentation of the devices that are connected
to our LPC controller (therefore modifying other devices
bindings to fit our special case).

I think that maybe having the 1:1 range mapping doesn't
reflect well the reality but it is the less painful
solution...

What's your view?
 
Many Thanks

Gab

> 
> > This is also explained quite well in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L490
> >
> > what do you think?
> 
> This is a separate issue, and only relevant for Apple Macintosh
> machines as well as the PA-Semi sdc.
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-15 12:05               ` Gabriele Paoloni
  (?)
@ 2016-09-15 12:24                 ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni wrote:
> > -----Original Message-----
> > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> > >
> > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > >
> > > I quote:
> > > "There shall be an entry in the "ranges" property for each
> > > of the Memory and/or I/O spaces if that address space is
> > > mapped through the bridge."
> > >
> > > It seems to me that it is ok to have 1:1 address mapping and that
> > > therefore of_translate_address() should fail if "ranges" is not
> > > present.
> > 
> > The key here is the definition of "mapped through the bridge".
> > I can only understand this as "directly mapped", i.e. an I/O
> > port of the child bus corresponds directly to a memory address
> > on the parent bus, but this is not the case here.
> > 
> > The problem with adding the mapping here is that it looks
> > like it should be valid to create a page table entry for
> > the address returned from the translation and access it through
> > a pointer dereference, but that is clearly not possible.
> 
> I understand that somehow we are abusing of the ranges property
> here however the point is that with the current implementation ranges
> is needed because otherwise the ipmi driver probe will fail here:
> 
> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> -> of_translate_address -> __of_translate_address
> 
> Now we had a bit of discussion internally and to avoid
> having ranges we came up with two possible solutions:
> 
> 1) Using bit 3 of phys.hi cell in 2.2.1 of
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> This would mean reworking of_bus_isa_get_flags in 
> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> and setting a new flag to be checked in __of_address_to_resource
> 
> 2) Adding a property in the bindings of each device that is
> a child of our LPC bus and modify __of_address_to_resource
> to check if the property is in the DT and eventually bypass
> of_translate_address
> 
> However in both 1) and 2) there are some issues:
> in 1) we are not complying with the isa binding doc (we use
> a bit that should be zero); in 2) we need to modify the
> bindings documentation of the devices that are connected
> to our LPC controller (therefore modifying other devices
> bindings to fit our special case).
> 
> I think that maybe having the 1:1 range mapping doesn't
> reflect well the reality but it is the less painful
> solution...
> 
> What's your view?

We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
and that should be enough to translate the I/O port number.

The only part we need to change here is to not go through
the crazy conversion all the way from PCI I/O space to a
physical address and back to a (logical) port number
that we do today with of_translate_address/pci_address_to_pio.

I can think of a several of ways to fix __of_address_to_resource
to just do the right thing according to the ISA binding to
make the normal drivers work.

The easiest solution is probably to hook into the
"taddr == OF_BAD_ADDR" case in __of_address_to_resource
and add a lookup for ISA buses there, and instead check
if some special I/O port operations were registered
for the port number, using an architecture specific
function that arm64 implements. Other architectures
like x86 that don't have a direct mapping between I/O
ports and MMIO addresses would implement that same
function differently.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 12:24                 ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau@arm.com

On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni wrote:
> > -----Original Message-----
> > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> > >
> > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > >
> > > I quote:
> > > "There shall be an entry in the "ranges" property for each
> > > of the Memory and/or I/O spaces if that address space is
> > > mapped through the bridge."
> > >
> > > It seems to me that it is ok to have 1:1 address mapping and that
> > > therefore of_translate_address() should fail if "ranges" is not
> > > present.
> > 
> > The key here is the definition of "mapped through the bridge".
> > I can only understand this as "directly mapped", i.e. an I/O
> > port of the child bus corresponds directly to a memory address
> > on the parent bus, but this is not the case here.
> > 
> > The problem with adding the mapping here is that it looks
> > like it should be valid to create a page table entry for
> > the address returned from the translation and access it through
> > a pointer dereference, but that is clearly not possible.
> 
> I understand that somehow we are abusing of the ranges property
> here however the point is that with the current implementation ranges
> is needed because otherwise the ipmi driver probe will fail here:
> 
> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> -> of_translate_address -> __of_translate_address
> 
> Now we had a bit of discussion internally and to avoid
> having ranges we came up with two possible solutions:
> 
> 1) Using bit 3 of phys.hi cell in 2.2.1 of
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> This would mean reworking of_bus_isa_get_flags in 
> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> and setting a new flag to be checked in __of_address_to_resource
> 
> 2) Adding a property in the bindings of each device that is
> a child of our LPC bus and modify __of_address_to_resource
> to check if the property is in the DT and eventually bypass
> of_translate_address
> 
> However in both 1) and 2) there are some issues:
> in 1) we are not complying with the isa binding doc (we use
> a bit that should be zero); in 2) we need to modify the
> bindings documentation of the devices that are connected
> to our LPC controller (therefore modifying other devices
> bindings to fit our special case).
> 
> I think that maybe having the 1:1 range mapping doesn't
> reflect well the reality but it is the less painful
> solution...
> 
> What's your view?

We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
and that should be enough to translate the I/O port number.

The only part we need to change here is to not go through
the crazy conversion all the way from PCI I/O space to a
physical address and back to a (logical) port number
that we do today with of_translate_address/pci_address_to_pio.

I can think of a several of ways to fix __of_address_to_resource
to just do the right thing according to the ISA binding to
make the normal drivers work.

The easiest solution is probably to hook into the
"taddr == OF_BAD_ADDR" case in __of_address_to_resource
and add a lookup for ISA buses there, and instead check
if some special I/O port operations were registered
for the port number, using an architecture specific
function that arm64 implements. Other architectures
like x86 that don't have a direct mapping between I/O
ports and MMIO addresses would implement that same
function differently.

	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 12:24                 ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-15 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni wrote:
> > -----Original Message-----
> > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
> > >
> > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > >
> > > I quote:
> > > "There shall be an entry in the "ranges" property for each
> > > of the Memory and/or I/O spaces if that address space is
> > > mapped through the bridge."
> > >
> > > It seems to me that it is ok to have 1:1 address mapping and that
> > > therefore of_translate_address() should fail if "ranges" is not
> > > present.
> > 
> > The key here is the definition of "mapped through the bridge".
> > I can only understand this as "directly mapped", i.e. an I/O
> > port of the child bus corresponds directly to a memory address
> > on the parent bus, but this is not the case here.
> > 
> > The problem with adding the mapping here is that it looks
> > like it should be valid to create a page table entry for
> > the address returned from the translation and access it through
> > a pointer dereference, but that is clearly not possible.
> 
> I understand that somehow we are abusing of the ranges property
> here however the point is that with the current implementation ranges
> is needed because otherwise the ipmi driver probe will fail here:
> 
> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> -> of_translate_address -> __of_translate_address
> 
> Now we had a bit of discussion internally and to avoid
> having ranges we came up with two possible solutions:
> 
> 1) Using bit 3 of phys.hi cell in 2.2.1 of
> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> This would mean reworking of_bus_isa_get_flags in 
> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> and setting a new flag to be checked in __of_address_to_resource
> 
> 2) Adding a property in the bindings of each device that is
> a child of our LPC bus and modify __of_address_to_resource
> to check if the property is in the DT and eventually bypass
> of_translate_address
> 
> However in both 1) and 2) there are some issues:
> in 1) we are not complying with the isa binding doc (we use
> a bit that should be zero); in 2) we need to modify the
> bindings documentation of the devices that are connected
> to our LPC controller (therefore modifying other devices
> bindings to fit our special case).
> 
> I think that maybe having the 1:1 range mapping doesn't
> reflect well the reality but it is the less painful
> solution...
> 
> What's your view?

We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
and that should be enough to translate the I/O port number.

The only part we need to change here is to not go through
the crazy conversion all the way from PCI I/O space to a
physical address and back to a (logical) port number
that we do today with of_translate_address/pci_address_to_pio.

I can think of a several of ways to fix __of_address_to_resource
to just do the right thing according to the ISA binding to
make the normal drivers work.

The easiest solution is probably to hook into the
"taddr == OF_BAD_ADDR" case in __of_address_to_resource
and add a lookup for ISA buses there, and instead check
if some special I/O port operations were registered
for the port number, using an architecture specific
function that arm64 implements. Other architectures
like x86 that don't have a direct mapping between I/O
ports and MMIO addresses would implement that same
function differently.

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-15 12:24                 ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-15 14:28                   ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 14:28 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, gregkh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 15 September 2016 13:25
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> gregkh@linuxfoundation.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial@vger.kernel.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> > > >
> > > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > >
> > > > I quote:
> > > > "There shall be an entry in the "ranges" property for each
> > > > of the Memory and/or I/O spaces if that address space is
> > > > mapped through the bridge."
> > > >
> > > > It seems to me that it is ok to have 1:1 address mapping and that
> > > > therefore of_translate_address() should fail if "ranges" is not
> > > > present.
> > >
> > > The key here is the definition of "mapped through the bridge".
> > > I can only understand this as "directly mapped", i.e. an I/O
> > > port of the child bus corresponds directly to a memory address
> > > on the parent bus, but this is not the case here.
> > >
> > > The problem with adding the mapping here is that it looks
> > > like it should be valid to create a page table entry for
> > > the address returned from the translation and access it through
> > > a pointer dereference, but that is clearly not possible.
> >
> > I understand that somehow we are abusing of the ranges property
> > here however the point is that with the current implementation ranges
> > is needed because otherwise the ipmi driver probe will fail here:
> >
> > of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> > -> of_translate_address -> __of_translate_address
> >
> > Now we had a bit of discussion internally and to avoid
> > having ranges we came up with two possible solutions:
> >
> > 1) Using bit 3 of phys.hi cell in 2.2.1 of
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > This would mean reworking of_bus_isa_get_flags in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> > and setting a new flag to be checked in __of_address_to_resource
> >
> > 2) Adding a property in the bindings of each device that is
> > a child of our LPC bus and modify __of_address_to_resource
> > to check if the property is in the DT and eventually bypass
> > of_translate_address
> >
> > However in both 1) and 2) there are some issues:
> > in 1) we are not complying with the isa binding doc (we use
> > a bit that should be zero); in 2) we need to modify the
> > bindings documentation of the devices that are connected
> > to our LPC controller (therefore modifying other devices
> > bindings to fit our special case).
> >
> > I think that maybe having the 1:1 range mapping doesn't
> > reflect well the reality but it is the less painful
> > solution...
> >
> > What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

So with respect to this patchset once we enter the
"taddr == OF_BAD_ADDR" case you would add an arch
specific function that checks if the resource is an I/O 
resource, if the parent node is an ISA bus (calling 
of_bus_isa_match) and if arm64_extio_ops is non NULL. 
 
I think it can work for us and it doesn't affect current
devices. I will talk to Zhichang about this for the next
patchset version.

Many Thanks for your ideas

Gab


> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 14:28                   ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 14:28 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, John Garry,
	will.deacon, linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 15 September 2016 13:25
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> gregkh@linuxfoundation.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial@vger.kernel.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> > > >
> > > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > >
> > > > I quote:
> > > > "There shall be an entry in the "ranges" property for each
> > > > of the Memory and/or I/O spaces if that address space is
> > > > mapped through the bridge."
> > > >
> > > > It seems to me that it is ok to have 1:1 address mapping and that
> > > > therefore of_translate_address() should fail if "ranges" is not
> > > > present.
> > >
> > > The key here is the definition of "mapped through the bridge".
> > > I can only understand this as "directly mapped", i.e. an I/O
> > > port of the child bus corresponds directly to a memory address
> > > on the parent bus, but this is not the case here.
> > >
> > > The problem with adding the mapping here is that it looks
> > > like it should be valid to create a page table entry for
> > > the address returned from the translation and access it through
> > > a pointer dereference, but that is clearly not possible.
> >
> > I understand that somehow we are abusing of the ranges property
> > here however the point is that with the current implementation ranges
> > is needed because otherwise the ipmi driver probe will fail here:
> >
> > of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> > -> of_translate_address -> __of_translate_address
> >
> > Now we had a bit of discussion internally and to avoid
> > having ranges we came up with two possible solutions:
> >
> > 1) Using bit 3 of phys.hi cell in 2.2.1 of
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > This would mean reworking of_bus_isa_get_flags in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> > and setting a new flag to be checked in __of_address_to_resource
> >
> > 2) Adding a property in the bindings of each device that is
> > a child of our LPC bus and modify __of_address_to_resource
> > to check if the property is in the DT and eventually bypass
> > of_translate_address
> >
> > However in both 1) and 2) there are some issues:
> > in 1) we are not complying with the isa binding doc (we use
> > a bit that should be zero); in 2) we need to modify the
> > bindings documentation of the devices that are connected
> > to our LPC controller (therefore modifying other devices
> > bindings to fit our special case).
> >
> > I think that maybe having the 1:1 range mapping doesn't
> > reflect well the reality but it is the less painful
> > solution...
> >
> > What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

So with respect to this patchset once we enter the
"taddr == OF_BAD_ADDR" case you would add an arch
specific function that checks if the resource is an I/O 
resource, if the parent node is an ISA bus (calling 
of_bus_isa_match) and if arm64_extio_ops is non NULL. 
 
I think it can work for us and it doesn't affect current
devices. I will talk to Zhichang about this for the next
patchset version.

Many Thanks for your ideas

Gab


> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 14:28                   ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 14:28 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, gregkh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 15 September 2016 13:25
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> gregkh@linuxfoundation.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial@vger.kernel.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> > > >
> > > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > >
> > > > I quote:
> > > > "There shall be an entry in the "ranges" property for each
> > > > of the Memory and/or I/O spaces if that address space is
> > > > mapped through the bridge."
> > > >
> > > > It seems to me that it is ok to have 1:1 address mapping and that
> > > > therefore of_translate_address() should fail if "ranges" is not
> > > > present.
> > >
> > > The key here is the definition of "mapped through the bridge".
> > > I can only understand this as "directly mapped", i.e. an I/O
> > > port of the child bus corresponds directly to a memory address
> > > on the parent bus, but this is not the case here.
> > >
> > > The problem with adding the mapping here is that it looks
> > > like it should be valid to create a page table entry for
> > > the address returned from the translation and access it through
> > > a pointer dereference, but that is clearly not possible.
> >
> > I understand that somehow we are abusing of the ranges property
> > here however the point is that with the current implementation ranges
> > is needed because otherwise the ipmi driver probe will fail here:
> >
> > of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> > -> of_translate_address -> __of_translate_address
> >
> > Now we had a bit of discussion internally and to avoid
> > having ranges we came up with two possible solutions:
> >
> > 1) Using bit 3 of phys.hi cell in 2.2.1 of
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > This would mean reworking of_bus_isa_get_flags in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> > and setting a new flag to be checked in __of_address_to_resource
> >
> > 2) Adding a property in the bindings of each device that is
> > a child of our LPC bus and modify __of_address_to_resource
> > to check if the property is in the DT and eventually bypass
> > of_translate_address
> >
> > However in both 1) and 2) there are some issues:
> > in 1) we are not complying with the isa binding doc (we use
> > a bit that should be zero); in 2) we need to modify the
> > bindings documentation of the devices that are connected
> > to our LPC controller (therefore modifying other devices
> > bindings to fit our special case).
> >
> > I think that maybe having the 1:1 range mapping doesn't
> > reflect well the reality but it is the less painful
> > solution...
> >
> > What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

So with respect to this patchset once we enter the
"taddr == OF_BAD_ADDR" case you would add an arch
specific function that checks if the resource is an I/O 
resource, if the parent node is an ISA bus (calling 
of_bus_isa_match) and if arm64_extio_ops is non NULL. 
 
I think it can work for us and it doesn't affect current
devices. I will talk to Zhichang about this for the next
patchset version.

Many Thanks for your ideas

Gab


> 
> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-15 14:28                   ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-15 14:28 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 15 September 2016 13:25
> To: linux-arm-kernel at lists.infradead.org
> Cc: Gabriele Paoloni; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> gregkh at linuxfoundation.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial at vger.kernel.org; benh at kernel.crashing.org;
> zourongrong at gmail.com; liviu.dudau at arm.com; kantyzc at 163.com;
> zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> > > >
> > > > From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> > > > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > >
> > > > I quote:
> > > > "There shall be an entry in the "ranges" property for each
> > > > of the Memory and/or I/O spaces if that address space is
> > > > mapped through the bridge."
> > > >
> > > > It seems to me that it is ok to have 1:1 address mapping and that
> > > > therefore of_translate_address() should fail if "ranges" is not
> > > > present.
> > >
> > > The key here is the definition of "mapped through the bridge".
> > > I can only understand this as "directly mapped", i.e. an I/O
> > > port of the child bus corresponds directly to a memory address
> > > on the parent bus, but this is not the case here.
> > >
> > > The problem with adding the mapping here is that it looks
> > > like it should be valid to create a page table entry for
> > > the address returned from the translation and access it through
> > > a pointer dereference, but that is clearly not possible.
> >
> > I understand that somehow we are abusing of the ranges property
> > here however the point is that with the current implementation ranges
> > is needed because otherwise the ipmi driver probe will fail here:
> >
> > of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> > -> of_translate_address -> __of_translate_address
> >
> > Now we had a bit of discussion internally and to avoid
> > having ranges we came up with two possible solutions:
> >
> > 1) Using bit 3 of phys.hi cell in 2.2.1 of
> > http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > This would mean reworking of_bus_isa_get_flags in
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> > and setting a new flag to be checked in __of_address_to_resource
> >
> > 2) Adding a property in the bindings of each device that is
> > a child of our LPC bus and modify __of_address_to_resource
> > to check if the property is in the DT and eventually bypass
> > of_translate_address
> >
> > However in both 1) and 2) there are some issues:
> > in 1) we are not complying with the isa binding doc (we use
> > a bit that should be zero); in 2) we need to modify the
> > bindings documentation of the devices that are connected
> > to our LPC controller (therefore modifying other devices
> > bindings to fit our special case).
> >
> > I think that maybe having the 1:1 range mapping doesn't
> > reflect well the reality but it is the less painful
> > solution...
> >
> > What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

So with respect to this patchset once we enter the
"taddr == OF_BAD_ADDR" case you would add an arch
specific function that checks if the resource is an I/O 
resource, if the parent node is an ISA bus (calling 
of_bus_isa_match) and if arm64_extio_ops is non NULL. 
 
I think it can work for us and it doesn't affect current
devices. I will talk to Zhichang about this for the next
patchset version.

Many Thanks for your ideas

Gab


> 
> 	Arnd

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
  2016-09-14 14:23         ` Arnd Bergmann
  (?)
@ 2016-09-18  3:38           ` zhichang
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-18  3:38 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: linux-arm-kernel, linux-kernel, linuxarm, devicetree,
	lorenzo.pieralisi, benh, minyard, linux-pci, gabriele.paoloni,
	john.garry, will.deacon, xuwei5, linux-serial, gregkh,
	zourongrong, liviu.dudau, kantyzc

Hi, Arnd,


On 2016年09月14日 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
>>>> +#define BUILDS_RW(bwl, type)                                                \
>>>> +static inline void reads##bwl(const volatile void __iomem *addr,    \
>>>> +                            void *buffer, unsigned int count)       \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            type *buf = buffer;                                     \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    type x = __raw_read##bwl(addr);                 \
>>>> +                    *buf++ = x;                                     \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}                                                                   \
>>>> +                                                                    \
>>>> +static inline void writes##bwl(volatile void __iomem *addr,         \
>>>> +                            const void *buffer, unsigned int count) \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            const type *buf = buffer;                               \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    __raw_write##bwl(*buf++, addr);                 \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}
>>>> +
>>>> +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
>> those function needed here....
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>>                         arm64_extio_ops->end < addr)
>>                 return readb(PCI_IOBASE + addr);
>>         else
>>                 return arm64_extio_ops->pfin ?
>>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>>                                 addr + arm64_extio_ops->ptoffset, NULL,
>>                                 sizeof(u8), 1) : -1;
>> }
>> .....
> 
> Yes, sounds good.
> 
>>>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
>>>>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
>>>>  
>>>> +
>>>> +/*
>>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>>> + */
>>>> +#define inb inb
>>>> +static inline u8 inb(unsigned long addr)
>>>> +{
>>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>>> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>>>> +                    addr <= arm64_extio_ops->end)
>>>> +            return extio_inb(addr);
>>>> +#endif
>>>> +    return readb(PCI_IOBASE + addr);
>>>> +}
>>>> +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in kernel
> space, which is not as nice.
> 
Yes. It probably cause kernel panic.
Will define the extio operations for other IO length and add the corresponding WARNINGS.

Best,
Zhichang


>>>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>>>> new file mode 100644
>>>> index 0000000..1e7a9c5
>>>> --- /dev/null
>>>> +++ b/drivers/bus/extio.c
>>>> @@ -0,0 +1,66 @@
>>>
>>> This is in a globally visible directory
>>>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>
>>> But the identifier uses an architecture specific prefix. Either
>>> move the whole file into arch/arm64, or make the naming so that
>>> it can be used for everything.
>>
>> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;
> 
> Ok, that simplifies it a lot, you can just do everything in asm/io.h then.
> 
> 	Arnd
> 

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-18  3:38           ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-18  3:38 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	john.garry-hv44wF8Li93QT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w, liviu.dudau-5wv7dgnIgG8,
	kantyzc-9Onoh4P/yGk

Hi, Arnd,


On 2016年09月14日 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
>>>> +#define BUILDS_RW(bwl, type)                                                \
>>>> +static inline void reads##bwl(const volatile void __iomem *addr,    \
>>>> +                            void *buffer, unsigned int count)       \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            type *buf = buffer;                                     \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    type x = __raw_read##bwl(addr);                 \
>>>> +                    *buf++ = x;                                     \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}                                                                   \
>>>> +                                                                    \
>>>> +static inline void writes##bwl(volatile void __iomem *addr,         \
>>>> +                            const void *buffer, unsigned int count) \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            const type *buf = buffer;                               \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    __raw_write##bwl(*buf++, addr);                 \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}
>>>> +
>>>> +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
>> those function needed here....
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>>                         arm64_extio_ops->end < addr)
>>                 return readb(PCI_IOBASE + addr);
>>         else
>>                 return arm64_extio_ops->pfin ?
>>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>>                                 addr + arm64_extio_ops->ptoffset, NULL,
>>                                 sizeof(u8), 1) : -1;
>> }
>> .....
> 
> Yes, sounds good.
> 
>>>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
>>>>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
>>>>  
>>>> +
>>>> +/*
>>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>>> + */
>>>> +#define inb inb
>>>> +static inline u8 inb(unsigned long addr)
>>>> +{
>>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>>> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>>>> +                    addr <= arm64_extio_ops->end)
>>>> +            return extio_inb(addr);
>>>> +#endif
>>>> +    return readb(PCI_IOBASE + addr);
>>>> +}
>>>> +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in kernel
> space, which is not as nice.
> 
Yes. It probably cause kernel panic.
Will define the extio operations for other IO length and add the corresponding WARNINGS.

Best,
Zhichang


>>>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>>>> new file mode 100644
>>>> index 0000000..1e7a9c5
>>>> --- /dev/null
>>>> +++ b/drivers/bus/extio.c
>>>> @@ -0,0 +1,66 @@
>>>
>>> This is in a globally visible directory
>>>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>
>>> But the identifier uses an architecture specific prefix. Either
>>> move the whole file into arch/arm64, or make the naming so that
>>> it can be used for everything.
>>
>> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;
> 
> Ok, that simplifies it a lot, you can just do everything in asm/io.h then.
> 
> 	Arnd
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-18  3:38           ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-18  3:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,


On 2016?09?14? 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
>>>> +#define BUILDS_RW(bwl, type)                                                \
>>>> +static inline void reads##bwl(const volatile void __iomem *addr,    \
>>>> +                            void *buffer, unsigned int count)       \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            type *buf = buffer;                                     \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    type x = __raw_read##bwl(addr);                 \
>>>> +                    *buf++ = x;                                     \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}                                                                   \
>>>> +                                                                    \
>>>> +static inline void writes##bwl(volatile void __iomem *addr,         \
>>>> +                            const void *buffer, unsigned int count) \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            const type *buf = buffer;                               \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    __raw_write##bwl(*buf++, addr);                 \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}
>>>> +
>>>> +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
>> those function needed here....
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>>                         arm64_extio_ops->end < addr)
>>                 return readb(PCI_IOBASE + addr);
>>         else
>>                 return arm64_extio_ops->pfin ?
>>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>>                                 addr + arm64_extio_ops->ptoffset, NULL,
>>                                 sizeof(u8), 1) : -1;
>> }
>> .....
> 
> Yes, sounds good.
> 
>>>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
>>>>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
>>>>  
>>>> +
>>>> +/*
>>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>>> + */
>>>> +#define inb inb
>>>> +static inline u8 inb(unsigned long addr)
>>>> +{
>>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>>> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>>>> +                    addr <= arm64_extio_ops->end)
>>>> +            return extio_inb(addr);
>>>> +#endif
>>>> +    return readb(PCI_IOBASE + addr);
>>>> +}
>>>> +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in kernel
> space, which is not as nice.
> 
Yes. It probably cause kernel panic.
Will define the extio operations for other IO length and add the corresponding WARNINGS.

Best,
Zhichang


>>>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>>>> new file mode 100644
>>>> index 0000000..1e7a9c5
>>>> --- /dev/null
>>>> +++ b/drivers/bus/extio.c
>>>> @@ -0,0 +1,66 @@
>>>
>>> This is in a globally visible directory
>>>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>
>>> But the identifier uses an architecture specific prefix. Either
>>> move the whole file into arch/arm64, or make the naming so that
>>> it can be used for everything.
>>
>> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;
> 
> Ok, that simplifies it a lot, you can just do everything in asm/io.h then.
> 
> 	Arnd
> 

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
  2016-09-14 14:23         ` Arnd Bergmann
  (?)
@ 2016-09-21  9:26           ` zhichang
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21  9:26 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: linux-arm-kernel, linux-kernel, linuxarm, devicetree,
	lorenzo.pieralisi, benh, minyard, linux-pci, gabriele.paoloni,
	john.garry, will.deacon, xuwei5, linux-serial, gregkh,
	zourongrong, liviu.dudau, kantyzc

Hi, Arnd,


On 2016年09月14日 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
>>>> +#define BUILDS_RW(bwl, type)                                                \
>>>> +static inline void reads##bwl(const volatile void __iomem *addr,    \
>>>> +                            void *buffer, unsigned int count)       \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            type *buf = buffer;                                     \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    type x = __raw_read##bwl(addr);                 \
>>>> +                    *buf++ = x;                                     \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}                                                                   \
>>>> +                                                                    \
>>>> +static inline void writes##bwl(volatile void __iomem *addr,         \
>>>> +                            const void *buffer, unsigned int count) \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            const type *buf = buffer;                               \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    __raw_write##bwl(*buf++, addr);                 \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}
>>>> +
>>>> +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
>> those function needed here....
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>>                         arm64_extio_ops->end < addr)
>>                 return readb(PCI_IOBASE + addr);
>>         else
>>                 return arm64_extio_ops->pfin ?
>>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>>                                 addr + arm64_extio_ops->ptoffset, NULL,
>>                                 sizeof(u8), 1) : -1;
>> }
>> .....
> 
> Yes, sounds good.
> 
>>>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
>>>>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
>>>>  
>>>> +
>>>> +/*
>>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>>> + */
>>>> +#define inb inb
>>>> +static inline u8 inb(unsigned long addr)
>>>> +{
>>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>>> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>>>> +                    addr <= arm64_extio_ops->end)
>>>> +            return extio_inb(addr);
>>>> +#endif
>>>> +    return readb(PCI_IOBASE + addr);
>>>> +}
>>>> +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in kernel
> space, which is not as nice.

As for this issue, I provided a wrong reply in the last email.
After double-checking with SoC guys, the inw(l)/outw(l) are OK with multiple 8-bit transfers to consecutive
I/O addresses.

Sorry for the wrong information!
Will support inw(l)/outw(l) in V4.

Best,
Zhichang


> 
>>>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>>>> new file mode 100644
>>>> index 0000000..1e7a9c5
>>>> --- /dev/null
>>>> +++ b/drivers/bus/extio.c
>>>> @@ -0,0 +1,66 @@
>>>
>>> This is in a globally visible directory
>>>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>
>>> But the identifier uses an architecture specific prefix. Either
>>> move the whole file into arch/arm64, or make the naming so that
>>> it can be used for everything.
>>
>> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;
> 
> Ok, that simplifies it a lot, you can just do everything in asm/io.h then.
> 
> 	Arnd
> 

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

* Re: [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-21  9:26           ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21  9:26 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard, gregkh,
	benh, john.garry, will.deacon, linux-kernel, xuwei5, linuxarm,
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel

SGksIEFybmQsCgoKT24gMjAxNuW5tDA55pyIMTTml6UgMjI6MjMsIEFybmQgQmVyZ21hbm4gd3Jv
dGU6Cj4gT24gV2VkbmVzZGF5LCBTZXB0ZW1iZXIgMTQsIDIwMTYgMTA6MTY6MjggUE0gQ0VTVCB6
aGljaGFuZy55dWFuIHdyb3RlOgo+Pj4KPj4+IE5vIG5lZWQgdG8gZ3VhcmQgaW5jbHVkZXMgd2l0
aCBhbiAjaWZkZWYuCj4+IElmIHJlbW92ZSAjaWZkZWYgaGVyZSwgZXh0aW8uaCBzaG91bGQgbm90
IGNvbnRhaW4gYW55IGZ1bmN0aW9uIGV4dGVybmFsIGRlY2xhcmF0aW9ucyB3aG9zZSBkZWZpbml0
aW9ucyBhcmUgaW4KPj4gZXh0aW8uYyBjb21waWxlZCBvbmx5IHdoZW4gQ09ORklHX0FSTTY0X0lO
RElSRUNUX1BJTyBpcyB5ZXMuCj4gIAo+IFRoZXJlIGlzIG5vIHByb2JsZW0gd2l0aCBtYWtpbmcg
ZGVjbGFyYXRpb25zIHZpc2libGUgZm9yIGZ1bmN0aW9ucyB0aGF0Cj4gYXJlIG5vdCBwYXJ0IG9m
IHRoZSBrZXJuZWwsIHdlIGRvIHRoYXQgYWxsIHRoZSB0aW1lLgo+IAo+Pj4+ICsjZGVmaW5lIEJV
SUxEU19SVyhid2wsIHR5cGUpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICtzdGF0aWMgaW5saW5lIHZvaWQgcmVhZHMjI2J3bChjb25zdCB2b2xh
dGlsZSB2b2lkIF9faW9tZW0gKmFkZHIsICAgIFwKPj4+PiArICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIHZvaWQgKmJ1ZmZlciwgdW5zaWduZWQgaW50IGNvdW50KSAgICAgICBcCj4+Pj4gK3sg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICsgICAgaWYgKGNvdW50KSB7ICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArICAgICAgICAgICAgdHlwZSAqYnVm
ID0gYnVmZmVyOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+Pj4gKyAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICsgICAgICAgICAgICBkbyB7ICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArICAgICAgICAgICAgICAgICAgICB0
eXBlIHggPSBfX3Jhd19yZWFkIyNid2woYWRkcik7ICAgICAgICAgICAgICAgICBcCj4+Pj4gKyAg
ICAgICAgICAgICAgICAgICAgKmJ1ZisrID0geDsgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICsgICAgICAgICAgICB9IHdoaWxlICgtLWNvdW50KTsgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArICAgIH0gICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+Pj4gK30g
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArc3RhdGljIGlubGluZSB2b2lkIHdy
aXRlcyMjYndsKHZvbGF0aWxlIHZvaWQgX19pb21lbSAqYWRkciwgICAgICAgICBcCj4+Pj4gKyAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2b2lkICpidWZmZXIsIHVuc2lnbmVkIGlu
dCBjb3VudCkgXAo+Pj4+ICt7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArICAgIGlmIChjb3VudCkgeyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+Pj4gKyAg
ICAgICAgICAgIGNvbnN0IHR5cGUgKmJ1ZiA9IGJ1ZmZlcjsgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArICAgICAgICAgICAgZG8geyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+Pj4gKyAg
ICAgICAgICAgICAgICAgICAgX19yYXdfd3JpdGUjI2J3bCgqYnVmKyssIGFkZHIpOyAgICAgICAg
ICAgICAgICAgXAo+Pj4+ICsgICAgICAgICAgICB9IHdoaWxlICgtLWNvdW50KTsgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4+PiArICAgIH0gICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+Pj4gK30K
Pj4+PiArCj4+Pj4gK0JVSUxEU19SVyhiLCB1OCkKPj4+Cj4+PiBXaHkgaXMgdGhpcyBpbiBoZXJl
Pwo+PiB0aGUgcmVhZHNiL3dyaXRlc2IgYXJlIGRlZmluZWQgaW4gYXNtLWdlbmVyaWMvaW8uaCB3
aGljaCBpcyBpbmNsdWRlZCBsYXRlciwgYnV0IHRoZSByZWRlZmluZWQgaW5zYi9vdXRzYiBuZWVk
Cj4+IHRvIGNhbGwgdGhlbS4gV2l0aG91dCB0aGVzZSByZWFkc2Ivd3JpdGVzYiBkZWZpbml0aW9u
IGJlZm9yZSBpbnNiL291dHNiIHJlZGVmaW5lZCwgY29tcGlsZSBlcnJvciBvY2N1ci4KPj4KPj4g
SXQgc2VlbXMgdGhhdCBjb3B5IGFsbCB0aGUgZGVmaW5pdGlvbnMgb2YgImFzbS1nZW5lcmljL2lv
LmgiIGlzIG5vdCBhIGdvb2QgaWRlYSwgc28gSSBtb3ZlIHRoZSBkZWZpbml0aW9ucyBvZgo+PiB0
aG9zZSBmdW5jdGlvbiBuZWVkZWQgaGVyZS4uLi4KPj4KPj4gT2suIEkgdGhpbmsgeW91ciBpZGVh
IGJlbG93IGRlZmluaW5nIGluKHMpL291dChzKSBpbiBhIGMgZmlsZSBjYW4gc29sdmUgdGhpcyBp
c3N1ZS4KPj4KPj4gI2lmZGVmIENPTkZJR19BUk02NF9JTkRJUkVDVF9QSU8KPj4gI2RlZmluZSBp
bmIgaW5iCj4+IGV4dGVybiB1OCBpbmIodW5zaWduZWQgbG9uZyBhZGRyKTsKPj4KPj4gI2RlZmlu
ZSBvdXRiIG91dGIKPj4gZXh0ZXJuIHZvaWQgb3V0Yih1OCB2YWx1ZSwgdW5zaWduZWQgbG9uZyBh
ZGRyKTsKPj4KPj4gI2RlZmluZSBpbnNiIGluc2IKPj4gZXh0ZXJuIHZvaWQgaW5zYih1bnNpZ25l
ZCBsb25nIGFkZHIsIHZvaWQgKmJ1ZmZlciwgdW5zaWduZWQgaW50IGNvdW50KTsKPj4KPj4gI2Rl
ZmluZSBvdXRzYiBvdXRzYgo+PiBleHRlcm4gdm9pZCBvdXRzYih1bnNpZ25lZCBsb25nIGFkZHIs
IGNvbnN0IHZvaWQgKmJ1ZmZlciwgdW5zaWduZWQgaW50IGNvdW50KTsKPj4gI2VuZGlmCj4+Cj4+
IGFuZCBkZWZpbml0aW9ucyBvZiBhbGwgdGhlc2UgZnVuY3Rpb25zIGFyZSBpbiBleHRpby5jIDoK
Pj4KPj4gdTggaW5iKHVuc2lnbmVkIGxvbmcgYWRkcikKPj4gewo+PiAgICAgICAgIGlmICghYXJt
NjRfZXh0aW9fb3BzIHx8IGFybTY0X2V4dGlvX29wcy0+c3RhcnQgPiBhZGRyIHx8Cj4+ICAgICAg
ICAgICAgICAgICAgICAgICAgIGFybTY0X2V4dGlvX29wcy0+ZW5kIDwgYWRkcikKPj4gICAgICAg
ICAgICAgICAgIHJldHVybiByZWFkYihQQ0lfSU9CQVNFICsgYWRkcik7Cj4+ICAgICAgICAgZWxz
ZQo+PiAgICAgICAgICAgICAgICAgcmV0dXJuIGFybTY0X2V4dGlvX29wcy0+cGZpbiA/Cj4+ICAg
ICAgICAgICAgICAgICAgICAgICAgIGFybTY0X2V4dGlvX29wcy0+cGZpbihhcm02NF9leHRpb19v
cHMtPmRldnBhcmEsCj4+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkciArIGFy
bTY0X2V4dGlvX29wcy0+cHRvZmZzZXQsIE5VTEwsCj4+ICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgc2l6ZW9mKHU4KSwgMSkgOiAtMTsKPj4gfQo+PiAuLi4uLgo+IAo+IFllcywgc291
bmRzIGdvb2QuCj4gCj4+Pj4gQEAgLTE0OSw2ICsxODUsNjAgQEAgc3RhdGljIGlubGluZSB1NjQg
X19yYXdfcmVhZHEoY29uc3Qgdm9sYXRpbGUgdm9pZCBfX2lvbWVtICphZGRyKQo+Pj4+ICAjZGVm
aW5lIElPX1NQQUNFX0xJTUlUICAgICAgICAgICAgICAoUENJX0lPX1NJWkUgLSAxKQo+Pj4+ICAj
ZGVmaW5lIFBDSV9JT0JBU0UgICAgICAgICAgKCh2b2lkIF9faW9tZW0gKilQQ0lfSU9fU1RBUlQp
Cj4+Pj4gIAo+Pj4+ICsKPj4+PiArLyoKPj4+PiArICogcmVkZWZpbmUgdGhlIGluKHMpYi9vdXQo
cyliIGZvciBpbmRpcmVjdC1JTy4KPj4+PiArICovCj4+Pj4gKyNkZWZpbmUgaW5iIGluYgo+Pj4+
ICtzdGF0aWMgaW5saW5lIHU4IGluYih1bnNpZ25lZCBsb25nIGFkZHIpCj4+Pj4gK3sKPj4+PiAr
I2lmZGVmIENPTkZJR19BUk02NF9JTkRJUkVDVF9QSU8KPj4+PiArICAgIGlmIChhcm02NF9leHRp
b19vcHMgJiYgYXJtNjRfZXh0aW9fb3BzLT5zdGFydCA8PSBhZGRyICYmCj4+Pj4gKyAgICAgICAg
ICAgICAgICAgICAgYWRkciA8PSBhcm02NF9leHRpb19vcHMtPmVuZCkKPj4+PiArICAgICAgICAg
ICAgcmV0dXJuIGV4dGlvX2luYihhZGRyKTsKPj4+PiArI2VuZGlmCj4+Pj4gKyAgICByZXR1cm4g
cmVhZGIoUENJX0lPQkFTRSArIGFkZHIpOwo+Pj4+ICt9Cj4+Pj4gKwo+Pj4KPj4+IExvb2tzIG9r
LCBidXQgeW91IG9ubHkgc2VlbSB0byBkbyB0aGlzIGZvciB0aGUgOC1iaXQKPj4+IGFjY2Vzc29y
cywgd2hlbiBpdCBzaG91bGQgYmUgZG9uZSBmb3IgMTYtYml0IGFuZCAzMi1iaXQKPj4+IG9uZXMg
YXMgd2VsbCBmb3IgY29uc2lzdGVuY3kuCj4+IEhpcDA2IExQQyBvbmx5IHN1cHBvcnQgOC1iaXQg
SS9PIG9wZXJhdGlvbnMgb24gdGhlIGRlc2lnbmF0ZWQgcG9ydC4KPiAKPiBUaGF0IGlzIGFuIGlu
dGVyZXN0aW5nIGxpbWl0YXRpb24uIE1heWJlIHN0aWxsIGNhbGwgdGhlIGV4dGlvIG9wZXJhdGlv
bnMKPiBhbmQgaGF2ZSB0aGVtIGRvIFdBUk5fT05fT05DRSgpIGluc3RlYWQ/Cj4gCj4gSWYgeW91
IGdldCBhIGRyaXZlciB0aGF0IGNhbGxzIGludy9vdXR3IG9uIHRoZSByYW5nZSB0aGF0IGlzIG93
bmVkCj4gYnkgdGhlIExQQyBidXMsIHlvdSBvdGhlcndpc2UgZ2V0IGFuIHVuaGFuZGxlZCBwYWdl
IGZhdWx0IGluIGtlcm5lbAo+IHNwYWNlLCB3aGljaCBpcyBub3QgYXMgbmljZS4KCkFzIGZvciB0
aGlzIGlzc3VlLCBJIHByb3ZpZGVkIGEgd3JvbmcgcmVwbHkgaW4gdGhlIGxhc3QgZW1haWwuCkFm
dGVyIGRvdWJsZS1jaGVja2luZyB3aXRoIFNvQyBndXlzLCB0aGUgaW53KGwpL291dHcobCkgYXJl
IE9LIHdpdGggbXVsdGlwbGUgOC1iaXQgdHJhbnNmZXJzIHRvIGNvbnNlY3V0aXZlCkkvTyBhZGRy
ZXNzZXMuCgpTb3JyeSBmb3IgdGhlIHdyb25nIGluZm9ybWF0aW9uIQpXaWxsIHN1cHBvcnQgaW53
KGwpL291dHcobCkgaW4gVjQuCgpCZXN0LApaaGljaGFuZwoKCj4gCj4+Pj4gZGlmZiAtLWdpdCBh
L2RyaXZlcnMvYnVzL2V4dGlvLmMgYi9kcml2ZXJzL2J1cy9leHRpby5jCj4+Pj4gbmV3IGZpbGUg
bW9kZSAxMDA2NDQKPj4+PiBpbmRleCAwMDAwMDAwLi4xZTdhOWM1Cj4+Pj4gLS0tIC9kZXYvbnVs
bAo+Pj4+ICsrKyBiL2RyaXZlcnMvYnVzL2V4dGlvLmMKPj4+PiBAQCAtMCwwICsxLDY2IEBACj4+
Pgo+Pj4gVGhpcyBpcyBpbiBhIGdsb2JhbGx5IHZpc2libGUgZGlyZWN0b3J5Cj4+Pgo+Pj4+ICsK
Pj4+PiArc3RydWN0IGV4dGlvX29wcyAqYXJtNjRfZXh0aW9fb3BzOwo+Pj4KPj4+IEJ1dCB0aGUg
aWRlbnRpZmllciB1c2VzIGFuIGFyY2hpdGVjdHVyZSBzcGVjaWZpYyBwcmVmaXguIEVpdGhlcgo+
Pj4gbW92ZSB0aGUgd2hvbGUgZmlsZSBpbnRvIGFyY2gvYXJtNjQsIG9yIG1ha2UgdGhlIG5hbWlu
ZyBzbyB0aGF0Cj4+PiBpdCBjYW4gYmUgdXNlZCBmb3IgZXZlcnl0aGluZy4KPj4KPj4gSSBwZXJm
ZXIgdG8gbW92ZSB0aGUgd2hvbGUgZmlsZSBpbnRvIGFyY2gvYXJtNjQsIGV4dGlvLmggd2lsbCBi
ZSBtb3ZlZCB0byBhcmNoL2FybTY0L2luY2x1ZGUvYXNtOwo+IAo+IE9rLCB0aGF0IHNpbXBsaWZp
ZXMgaXQgYSBsb3QsIHlvdSBjYW4ganVzdCBkbyBldmVyeXRoaW5nIGluIGFzbS9pby5oIHRoZW4u
Cj4gCj4gCUFybmQKPiAKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlz
dHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3Rp
bmZvL2xpbnV4LWFybS1rZXJuZWwK

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

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-09-21  9:26           ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,


On 2016?09?14? 22:23, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
>>>
>>> No need to guard includes with an #ifdef.
>> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
>> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
>  
> There is no problem with making declarations visible for functions that
> are not part of the kernel, we do that all the time.
> 
>>>> +#define BUILDS_RW(bwl, type)                                                \
>>>> +static inline void reads##bwl(const volatile void __iomem *addr,    \
>>>> +                            void *buffer, unsigned int count)       \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            type *buf = buffer;                                     \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    type x = __raw_read##bwl(addr);                 \
>>>> +                    *buf++ = x;                                     \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}                                                                   \
>>>> +                                                                    \
>>>> +static inline void writes##bwl(volatile void __iomem *addr,         \
>>>> +                            const void *buffer, unsigned int count) \
>>>> +{                                                                   \
>>>> +    if (count) {                                                    \
>>>> +            const type *buf = buffer;                               \
>>>> +                                                                    \
>>>> +            do {                                                    \
>>>> +                    __raw_write##bwl(*buf++, addr);                 \
>>>> +            } while (--count);                                      \
>>>> +    }                                                               \
>>>> +}
>>>> +
>>>> +BUILDS_RW(b, u8)
>>>
>>> Why is this in here?
>> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
>> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
>>
>> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
>> those function needed here....
>>
>> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
>>
>> #ifdef CONFIG_ARM64_INDIRECT_PIO
>> #define inb inb
>> extern u8 inb(unsigned long addr);
>>
>> #define outb outb
>> extern void outb(u8 value, unsigned long addr);
>>
>> #define insb insb
>> extern void insb(unsigned long addr, void *buffer, unsigned int count);
>>
>> #define outsb outsb
>> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
>> #endif
>>
>> and definitions of all these functions are in extio.c :
>>
>> u8 inb(unsigned long addr)
>> {
>>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>>                         arm64_extio_ops->end < addr)
>>                 return readb(PCI_IOBASE + addr);
>>         else
>>                 return arm64_extio_ops->pfin ?
>>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>>                                 addr + arm64_extio_ops->ptoffset, NULL,
>>                                 sizeof(u8), 1) : -1;
>> }
>> .....
> 
> Yes, sounds good.
> 
>>>> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
>>>>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
>>>>  
>>>> +
>>>> +/*
>>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>>> + */
>>>> +#define inb inb
>>>> +static inline u8 inb(unsigned long addr)
>>>> +{
>>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>>> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>>>> +                    addr <= arm64_extio_ops->end)
>>>> +            return extio_inb(addr);
>>>> +#endif
>>>> +    return readb(PCI_IOBASE + addr);
>>>> +}
>>>> +
>>>
>>> Looks ok, but you only seem to do this for the 8-bit
>>> accessors, when it should be done for 16-bit and 32-bit
>>> ones as well for consistency.
>> Hip06 LPC only support 8-bit I/O operations on the designated port.
> 
> That is an interesting limitation. Maybe still call the extio operations
> and have them do WARN_ON_ONCE() instead?
> 
> If you get a driver that calls inw/outw on the range that is owned
> by the LPC bus, you otherwise get an unhandled page fault in kernel
> space, which is not as nice.

As for this issue, I provided a wrong reply in the last email.
After double-checking with SoC guys, the inw(l)/outw(l) are OK with multiple 8-bit transfers to consecutive
I/O addresses.

Sorry for the wrong information!
Will support inw(l)/outw(l) in V4.

Best,
Zhichang


> 
>>>> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
>>>> new file mode 100644
>>>> index 0000000..1e7a9c5
>>>> --- /dev/null
>>>> +++ b/drivers/bus/extio.c
>>>> @@ -0,0 +1,66 @@
>>>
>>> This is in a globally visible directory
>>>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>
>>> But the identifier uses an architecture specific prefix. Either
>>> move the whole file into arch/arm64, or make the naming so that
>>> it can be used for everything.
>>
>> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;
> 
> Ok, that simplifies it a lot, you can just do everything in asm/io.h then.
> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-15 12:24                 ` Arnd Bergmann
  (?)
@ 2016-09-21 10:09                   ` zhichang
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21 10:09 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Gabriele Paoloni, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi, Arnd,



On 2016年09月15日 20:24, Arnd Bergmann wrote:
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni wrote:
>>> -----Original Message-----
>>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
>>>>
>>>> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
>>>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
>>>>
>>>> I quote:
>>>> "There shall be an entry in the "ranges" property for each
>>>> of the Memory and/or I/O spaces if that address space is
>>>> mapped through the bridge."
>>>>
>>>> It seems to me that it is ok to have 1:1 address mapping and that
>>>> therefore of_translate_address() should fail if "ranges" is not
>>>> present.
>>>
>>> The key here is the definition of "mapped through the bridge".
>>> I can only understand this as "directly mapped", i.e. an I/O
>>> port of the child bus corresponds directly to a memory address
>>> on the parent bus, but this is not the case here.
>>>
>>> The problem with adding the mapping here is that it looks
>>> like it should be valid to create a page table entry for
>>> the address returned from the translation and access it through
>>> a pointer dereference, but that is clearly not possible.
>>
>> I understand that somehow we are abusing of the ranges property
>> here however the point is that with the current implementation ranges
>> is needed because otherwise the ipmi driver probe will fail here:
>>
>> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
>> -> of_translate_address -> __of_translate_address
>>
>> Now we had a bit of discussion internally and to avoid
>> having ranges we came up with two possible solutions:
>>
>> 1) Using bit 3 of phys.hi cell in 2.2.1 of
>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
>> This would mean reworking of_bus_isa_get_flags in 
>> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
>> and setting a new flag to be checked in __of_address_to_resource
>>
>> 2) Adding a property in the bindings of each device that is
>> a child of our LPC bus and modify __of_address_to_resource
>> to check if the property is in the DT and eventually bypass
>> of_translate_address
>>
>> However in both 1) and 2) there are some issues:
>> in 1) we are not complying with the isa binding doc (we use
>> a bit that should be zero); in 2) we need to modify the
>> bindings documentation of the devices that are connected
>> to our LPC controller (therefore modifying other devices
>> bindings to fit our special case).
>>
>> I think that maybe having the 1:1 range mapping doesn't
>> reflect well the reality but it is the less painful
>> solution...
>>
>> What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
Sorry for the late response! Several days' leave....
Do you want to bypass of_translate_address and pci_address_to_pio for the registered specific PIO?
I think the bypass for of_translate_address is ok, but worry some new issues will emerge without the
conversion between physical address and logical/linux port number.

When PCI host bridge which support IO operations is configured and enabled, the pci_address_to_pio will
populate the logical IO range from ZERO for the first host bridge. Our LPC will also use part of the IO range
started from ZERO. It will make in/out enter the wrong branch possibly.

In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only. But it seems not so good. In this way,
PCI has no chance to use low 4K IO range(logical).

So, in V3, applying the conversion from physical/cpu address to logical/linux IO port for any IO ranges,
including the LPC, but recorded the logical IO range for LPC. When calling in/out with a logical port address,
we can check this port fall into LPC logical IO range and get back the real IO.

Do you have further comments about this??


> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

What about add the specific quirk for Hip06 LPC in of_empty_ranges_quirk()??

you know, there are several cases in which of_translate_address return OF_BAD_ADDR.
And if we only check the special port range, it seems a bit risky. If some device want to use this port range
when no hip06 LPC is configured, the checking does not work. I think we should also check the relevant device.


Best,
Zhichang


> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 10:09                   ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21 10:09 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Gabriele Paoloni, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau@arm.com

Hi, Arnd,



On 2016年09月15日 20:24, Arnd Bergmann wrote:
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni wrote:
>>> -----Original Message-----
>>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
>>>>
>>>> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
>>>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
>>>>
>>>> I quote:
>>>> "There shall be an entry in the "ranges" property for each
>>>> of the Memory and/or I/O spaces if that address space is
>>>> mapped through the bridge."
>>>>
>>>> It seems to me that it is ok to have 1:1 address mapping and that
>>>> therefore of_translate_address() should fail if "ranges" is not
>>>> present.
>>>
>>> The key here is the definition of "mapped through the bridge".
>>> I can only understand this as "directly mapped", i.e. an I/O
>>> port of the child bus corresponds directly to a memory address
>>> on the parent bus, but this is not the case here.
>>>
>>> The problem with adding the mapping here is that it looks
>>> like it should be valid to create a page table entry for
>>> the address returned from the translation and access it through
>>> a pointer dereference, but that is clearly not possible.
>>
>> I understand that somehow we are abusing of the ranges property
>> here however the point is that with the current implementation ranges
>> is needed because otherwise the ipmi driver probe will fail here:
>>
>> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
>> -> of_translate_address -> __of_translate_address
>>
>> Now we had a bit of discussion internally and to avoid
>> having ranges we came up with two possible solutions:
>>
>> 1) Using bit 3 of phys.hi cell in 2.2.1 of
>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
>> This would mean reworking of_bus_isa_get_flags in 
>> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
>> and setting a new flag to be checked in __of_address_to_resource
>>
>> 2) Adding a property in the bindings of each device that is
>> a child of our LPC bus and modify __of_address_to_resource
>> to check if the property is in the DT and eventually bypass
>> of_translate_address
>>
>> However in both 1) and 2) there are some issues:
>> in 1) we are not complying with the isa binding doc (we use
>> a bit that should be zero); in 2) we need to modify the
>> bindings documentation of the devices that are connected
>> to our LPC controller (therefore modifying other devices
>> bindings to fit our special case).
>>
>> I think that maybe having the 1:1 range mapping doesn't
>> reflect well the reality but it is the less painful
>> solution...
>>
>> What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
Sorry for the late response! Several days' leave....
Do you want to bypass of_translate_address and pci_address_to_pio for the registered specific PIO?
I think the bypass for of_translate_address is ok, but worry some new issues will emerge without the
conversion between physical address and logical/linux port number.

When PCI host bridge which support IO operations is configured and enabled, the pci_address_to_pio will
populate the logical IO range from ZERO for the first host bridge. Our LPC will also use part of the IO range
started from ZERO. It will make in/out enter the wrong branch possibly.

In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only. But it seems not so good. In this way,
PCI has no chance to use low 4K IO range(logical).

So, in V3, applying the conversion from physical/cpu address to logical/linux IO port for any IO ranges,
including the LPC, but recorded the logical IO range for LPC. When calling in/out with a logical port address,
we can check this port fall into LPC logical IO range and get back the real IO.

Do you have further comments about this??


> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

What about add the specific quirk for Hip06 LPC in of_empty_ranges_quirk()??

you know, there are several cases in which of_translate_address return OF_BAD_ADDR.
And if we only check the special port range, it seems a bit risky. If some device want to use this port range
when no hip06 LPC is configured, the checking does not work. I think we should also check the relevant device.


Best,
Zhichang


> 
> 	Arnd
> 

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 10:09                   ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,



On 2016?09?15? 20:24, Arnd Bergmann wrote:
> On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni wrote:
>>> -----Original Message-----
>>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni wrote:
>>>>
>>>> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
>>>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
>>>>
>>>> I quote:
>>>> "There shall be an entry in the "ranges" property for each
>>>> of the Memory and/or I/O spaces if that address space is
>>>> mapped through the bridge."
>>>>
>>>> It seems to me that it is ok to have 1:1 address mapping and that
>>>> therefore of_translate_address() should fail if "ranges" is not
>>>> present.
>>>
>>> The key here is the definition of "mapped through the bridge".
>>> I can only understand this as "directly mapped", i.e. an I/O
>>> port of the child bus corresponds directly to a memory address
>>> on the parent bus, but this is not the case here.
>>>
>>> The problem with adding the mapping here is that it looks
>>> like it should be valid to create a page table entry for
>>> the address returned from the translation and access it through
>>> a pointer dereference, but that is clearly not possible.
>>
>> I understand that somehow we are abusing of the ranges property
>> here however the point is that with the current implementation ranges
>> is needed because otherwise the ipmi driver probe will fail here:
>>
>> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
>> -> of_translate_address -> __of_translate_address
>>
>> Now we had a bit of discussion internally and to avoid
>> having ranges we came up with two possible solutions:
>>
>> 1) Using bit 3 of phys.hi cell in 2.2.1 of
>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
>> This would mean reworking of_bus_isa_get_flags in 
>> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
>> and setting a new flag to be checked in __of_address_to_resource
>>
>> 2) Adding a property in the bindings of each device that is
>> a child of our LPC bus and modify __of_address_to_resource
>> to check if the property is in the DT and eventually bypass
>> of_translate_address
>>
>> However in both 1) and 2) there are some issues:
>> in 1) we are not complying with the isa binding doc (we use
>> a bit that should be zero); in 2) we need to modify the
>> bindings documentation of the devices that are connected
>> to our LPC controller (therefore modifying other devices
>> bindings to fit our special case).
>>
>> I think that maybe having the 1:1 range mapping doesn't
>> reflect well the reality but it is the less painful
>> solution...
>>
>> What's your view?
> 
> We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> and that should be enough to translate the I/O port number.
> 
> The only part we need to change here is to not go through
> the crazy conversion all the way from PCI I/O space to a
> physical address and back to a (logical) port number
> that we do today with of_translate_address/pci_address_to_pio.
> 
Sorry for the late response! Several days' leave....
Do you want to bypass of_translate_address and pci_address_to_pio for the registered specific PIO?
I think the bypass for of_translate_address is ok, but worry some new issues will emerge without the
conversion between physical address and logical/linux port number.

When PCI host bridge which support IO operations is configured and enabled, the pci_address_to_pio will
populate the logical IO range from ZERO for the first host bridge. Our LPC will also use part of the IO range
started from ZERO. It will make in/out enter the wrong branch possibly.

In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only. But it seems not so good. In this way,
PCI has no chance to use low 4K IO range(logical).

So, in V3, applying the conversion from physical/cpu address to logical/linux IO port for any IO ranges,
including the LPC, but recorded the logical IO range for LPC. When calling in/out with a logical port address,
we can check this port fall into LPC logical IO range and get back the real IO.

Do you have further comments about this??


> I can think of a several of ways to fix __of_address_to_resource
> to just do the right thing according to the ISA binding to
> make the normal drivers work.
> 
> The easiest solution is probably to hook into the
> "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> and add a lookup for ISA buses there, and instead check
> if some special I/O port operations were registered
> for the port number, using an architecture specific
> function that arm64 implements. Other architectures
> like x86 that don't have a direct mapping between I/O
> ports and MMIO addresses would implement that same
> function differently.

What about add the specific quirk for Hip06 LPC in of_empty_ranges_quirk()??

you know, there are several cases in which of_translate_address return OF_BAD_ADDR.
And if we only check the special port range, it seems a bit risky. If some device want to use this port range
when no hip06 LPC is configured, the checking does not work. I think we should also check the relevant device.


Best,
Zhichang


> 
> 	Arnd
> 

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
  2016-09-14 21:33         ` Arnd Bergmann
  (?)
@ 2016-09-21 10:12           ` zhichang
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21 10:12 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard,
	linux-pci, gregkh, john.garry, will.deacon, linux-kernel,
	zhichang.yuan, linuxarm, xuwei5, linux-serial, benh, zourongrong,
	liviu.dudau, kantyzc



On 2016年09月15日 05:33, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 11:04:33 PM CEST zhichang.yuan wrote:
>> The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :
>>
>> +static struct platform_driver hs_lpc8250_driver = {
>> +       .driver = {
>> +               .name           = "hisi-lpc-uart",
>> +               .of_match_table = hs8250_of_match,
>> +               .acpi_match_table = ACPI_PTR(hs8250_acpi_match),
>>
>> So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
>> driver file.
>>
> 
> After looking again, I'm pretty sure that drivers/tty/serial/8250/8250_pnp.c
> will handle the ACPI case without modifications, you just need to adapt
> the 8250_of driver to handle IORESOURCE_IO ports. This will be required
> anyway with the next version once the LPC bridge is on the PCI bus.
> 

Yes. You are right.

When the indirectIO patch is accepted, no much changes needed in these two file to support LPC UART.

BTW, what is your target to change these two files to support LPC uart?
Do you think we don't need to add many new c files??

Best,
Zhichang



> 	Arnd
> 

_______________________________________________
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] 160+ messages in thread

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-21 10:12           ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21 10:12 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard,
	linux-pci, gregkh, john.garry, will.deacon, linux-kernel,
	zhichang.yuan, linuxarm, xuwei5, linux-serial, benh, zourongrong,
	liviu.dudau, kantyzc

CgpPbiAyMDE25bm0MDnmnIgxNeaXpSAwNTozMywgQXJuZCBCZXJnbWFubiB3cm90ZToKPiBPbiBX
ZWRuZXNkYXksIFNlcHRlbWJlciAxNCwgMjAxNiAxMTowNDozMyBQTSBDRVNUIHpoaWNoYW5nLnl1
YW4gd3JvdGU6Cj4+IFRoZSA4MjUwX2hpc2lfbHBjLmMgc3VwcG9ydCBib3RoIEFDUEkgYW5kIGR0
cyBzaW1pbGFyIHRvIDgyNTBfZHcgOgo+Pgo+PiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2
ZXIgaHNfbHBjODI1MF9kcml2ZXIgPSB7Cj4+ICsgICAgICAgLmRyaXZlciA9IHsKPj4gKyAgICAg
ICAgICAgICAgIC5uYW1lICAgICAgICAgICA9ICJoaXNpLWxwYy11YXJ0IiwKPj4gKyAgICAgICAg
ICAgICAgIC5vZl9tYXRjaF90YWJsZSA9IGhzODI1MF9vZl9tYXRjaCwKPj4gKyAgICAgICAgICAg
ICAgIC5hY3BpX21hdGNoX3RhYmxlID0gQUNQSV9QVFIoaHM4MjUwX2FjcGlfbWF0Y2gpLAo+Pgo+
PiBTbywgSSBhbSBhIGxpdHRsZSBjb25mdXNlZCB3aHkgd2UgbmVlZCB0byBzdXBwb3J0IGR0cyBp
biA4MjUwX29mLmMgYW5kIHN1cHBvcnQgQUNQSSBpbiBhbm90aGVyCj4+IGRyaXZlciBmaWxlLgo+
Pgo+IAo+IEFmdGVyIGxvb2tpbmcgYWdhaW4sIEknbSBwcmV0dHkgc3VyZSB0aGF0IGRyaXZlcnMv
dHR5L3NlcmlhbC84MjUwLzgyNTBfcG5wLmMKPiB3aWxsIGhhbmRsZSB0aGUgQUNQSSBjYXNlIHdp
dGhvdXQgbW9kaWZpY2F0aW9ucywgeW91IGp1c3QgbmVlZCB0byBhZGFwdAo+IHRoZSA4MjUwX29m
IGRyaXZlciB0byBoYW5kbGUgSU9SRVNPVVJDRV9JTyBwb3J0cy4gVGhpcyB3aWxsIGJlIHJlcXVp
cmVkCj4gYW55d2F5IHdpdGggdGhlIG5leHQgdmVyc2lvbiBvbmNlIHRoZSBMUEMgYnJpZGdlIGlz
IG9uIHRoZSBQQ0kgYnVzLgo+IAoKWWVzLiBZb3UgYXJlIHJpZ2h0LgoKV2hlbiB0aGUgaW5kaXJl
Y3RJTyBwYXRjaCBpcyBhY2NlcHRlZCwgbm8gbXVjaCBjaGFuZ2VzIG5lZWRlZCBpbiB0aGVzZSB0
d28gZmlsZSB0byBzdXBwb3J0IExQQyBVQVJULgoKQlRXLCB3aGF0IGlzIHlvdXIgdGFyZ2V0IHRv
IGNoYW5nZSB0aGVzZSB0d28gZmlsZXMgdG8gc3VwcG9ydCBMUEMgdWFydD8KRG8geW91IHRoaW5r
IHdlIGRvbid0IG5lZWQgdG8gYWRkIG1hbnkgbmV3IGMgZmlsZXM/PwoKQmVzdCwKWmhpY2hhbmcK
CgoKPiAJQXJuZAo+IAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0
cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGlu
Zm8vbGludXgtYXJtLWtlcm5lbAo=

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-21 10:12           ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-21 10:12 UTC (permalink / raw)
  To: linux-arm-kernel



On 2016?09?15? 05:33, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 11:04:33 PM CEST zhichang.yuan wrote:
>> The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :
>>
>> +static struct platform_driver hs_lpc8250_driver = {
>> +       .driver = {
>> +               .name           = "hisi-lpc-uart",
>> +               .of_match_table = hs8250_of_match,
>> +               .acpi_match_table = ACPI_PTR(hs8250_acpi_match),
>>
>> So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
>> driver file.
>>
> 
> After looking again, I'm pretty sure that drivers/tty/serial/8250/8250_pnp.c
> will handle the ACPI case without modifications, you just need to adapt
> the 8250_of driver to handle IORESOURCE_IO ports. This will be required
> anyway with the next version once the LPC bridge is on the PCI bus.
> 

Yes. You are right.

When the indirectIO patch is accepted, no much changes needed in these two file to support LPC UART.

BTW, what is your target to change these two files to support LPC uart?
Do you think we don't need to add many new c files??

Best,
Zhichang



> 	Arnd
> 

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-21 10:09                   ` zhichang
  (?)
  (?)
@ 2016-09-21 16:20                     ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-21 16:20 UTC (permalink / raw)
  To: zhichang, Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, minyard, linux-pci, gregkh,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Zhichang

> -----Original Message-----
> From: zhichang [mailto:zhichang.yuan02@gmail.com]
> Sent: 21 September 2016 11:09
> To: Arnd Bergmann; linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> gregkh@linuxfoundation.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial@vger.kernel.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> Hi, Arnd,
> 
> 
> 
> On 2016年09月15日 20:24, Arnd Bergmann wrote:
> > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> >>> -----Original Message-----
> >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> >>>>
> >>>> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> >>>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >>>>
> >>>> I quote:
> >>>> "There shall be an entry in the "ranges" property for each
> >>>> of the Memory and/or I/O spaces if that address space is
> >>>> mapped through the bridge."
> >>>>
> >>>> It seems to me that it is ok to have 1:1 address mapping and that
> >>>> therefore of_translate_address() should fail if "ranges" is not
> >>>> present.
> >>>
> >>> The key here is the definition of "mapped through the bridge".
> >>> I can only understand this as "directly mapped", i.e. an I/O
> >>> port of the child bus corresponds directly to a memory address
> >>> on the parent bus, but this is not the case here.
> >>>
> >>> The problem with adding the mapping here is that it looks
> >>> like it should be valid to create a page table entry for
> >>> the address returned from the translation and access it through
> >>> a pointer dereference, but that is clearly not possible.
> >>
> >> I understand that somehow we are abusing of the ranges property
> >> here however the point is that with the current implementation
> ranges
> >> is needed because otherwise the ipmi driver probe will fail here:
> >>
> >> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> >> -> of_translate_address -> __of_translate_address
> >>
> >> Now we had a bit of discussion internally and to avoid
> >> having ranges we came up with two possible solutions:
> >>
> >> 1) Using bit 3 of phys.hi cell in 2.2.1 of
> >> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >> This would mean reworking of_bus_isa_get_flags in
> >> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> >> and setting a new flag to be checked in __of_address_to_resource
> >>
> >> 2) Adding a property in the bindings of each device that is
> >> a child of our LPC bus and modify __of_address_to_resource
> >> to check if the property is in the DT and eventually bypass
> >> of_translate_address
> >>
> >> However in both 1) and 2) there are some issues:
> >> in 1) we are not complying with the isa binding doc (we use
> >> a bit that should be zero); in 2) we need to modify the
> >> bindings documentation of the devices that are connected
> >> to our LPC controller (therefore modifying other devices
> >> bindings to fit our special case).
> >>
> >> I think that maybe having the 1:1 range mapping doesn't
> >> reflect well the reality but it is the less painful
> >> solution...
> >>
> >> What's your view?
> >
> > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > and that should be enough to translate the I/O port number.
> >
> > The only part we need to change here is to not go through
> > the crazy conversion all the way from PCI I/O space to a
> > physical address and back to a (logical) port number
> > that we do today with of_translate_address/pci_address_to_pio.
> >
> Sorry for the late response! Several days' leave....
> Do you want to bypass of_translate_address and pci_address_to_pio for
> the registered specific PIO?
> I think the bypass for of_translate_address is ok, but worry some new
> issues will emerge without the
> conversion between physical address and logical/linux port number.
> 
> When PCI host bridge which support IO operations is configured and
> enabled, the pci_address_to_pio will
> populate the logical IO range from ZERO for the first host bridge. Our
> LPC will also use part of the IO range
> started from ZERO. It will make in/out enter the wrong branch possibly.
> 
> In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only.
> But it seems not so good. In this way,
> PCI has no chance to use low 4K IO range(logical).
> 
> So, in V3, applying the conversion from physical/cpu address to
> logical/linux IO port for any IO ranges,
> including the LPC, but recorded the logical IO range for LPC. When
> calling in/out with a logical port address,
> we can check this port fall into LPC logical IO range and get back the
> real IO.
> 
> Do you have further comments about this??

I think there are two separate issues to be discussed:

The first issue is about having of_translate_address failing due to
"range" missing. About this Arnd suggested that it is not appropriate
to have a range describing a bridge 1:1 mapping and this was discussed
before in this thread. Arnd had a suggestion about this (see below) 
however (looking twice at the code) it seems to me that such solution 
would lead to quite some duplication from __of_translate_address()
in order to retrieve the actual addr from dt...

I think extending of_empty_ranges_quirk() may be a reasonable solution.
What do you think Arnd?
  
The second issue is a conflict between cpu addresses used by the LPC
controller and i/o tokens from pci endpoints.

About this what if we modify armn64_extio_ops to have a list of ranges
rather than only one range (now we have just start/end); then in the
LPC driver we can scan the LPC child devices and 
1) populate such list of ranges
2) call pci_register_io_range for such ranges

Then when calling __of_address_to_resource we retrieve I/O tokens 
for the devices on top of the LPC driver and in the I/O accessors
we call pci_pio_to_address to figure out the cpu address and compare
it to the list of ranges in armn64_extio_ops.
  
What about this?

Thanks

Gab

> 
> 
> > I can think of a several of ways to fix __of_address_to_resource
> > to just do the right thing according to the ISA binding to
> > make the normal drivers work.
> >
> > The easiest solution is probably to hook into the
> > "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> > and add a lookup for ISA buses there, and instead check
> > if some special I/O port operations were registered
> > for the port number, using an architecture specific
> > function that arm64 implements. Other architectures
> > like x86 that don't have a direct mapping between I/O
> > ports and MMIO addresses would implement that same
> > function differently.
> 
> What about add the specific quirk for Hip06 LPC in
> of_empty_ranges_quirk()??
> 
> you know, there are several cases in which of_translate_address return
> OF_BAD_ADDR.
> And if we only check the special port range, it seems a bit risky. If
> some device want to use this port range
> when no hip06 LPC is configured, the checking does not work. I think we
> should also check the relevant device.
> 
> 
> Best,
> Zhichang
> 
> 
> >
> > 	Arnd
> >

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 16:20                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-21 16:20 UTC (permalink / raw)
  To: zhichang, Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, John Garry,
	will.deacon, linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc

Hi Zhichang

> -----Original Message-----
> From: zhichang [mailto:zhichang.yuan02@gmail.com]
> Sent: 21 September 2016 11:09
> To: Arnd Bergmann; linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> gregkh@linuxfoundation.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial@vger.kernel.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; liviu.dudau@arm.com; kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> Hi, Arnd,
> 
> 
> 
> On 2016年09月15日 20:24, Arnd Bergmann wrote:
> > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> >>> -----Original Message-----
> >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> >>>>
> >>>> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> >>>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >>>>
> >>>> I quote:
> >>>> "There shall be an entry in the "ranges" property for each
> >>>> of the Memory and/or I/O spaces if that address space is
> >>>> mapped through the bridge."
> >>>>
> >>>> It seems to me that it is ok to have 1:1 address mapping and that
> >>>> therefore of_translate_address() should fail if "ranges" is not
> >>>> present.
> >>>
> >>> The key here is the definition of "mapped through the bridge".
> >>> I can only understand this as "directly mapped", i.e. an I/O
> >>> port of the child bus corresponds directly to a memory address
> >>> on the parent bus, but this is not the case here.
> >>>
> >>> The problem with adding the mapping here is that it looks
> >>> like it should be valid to create a page table entry for
> >>> the address returned from the translation and access it through
> >>> a pointer dereference, but that is clearly not possible.
> >>
> >> I understand that somehow we are abusing of the ranges property
> >> here however the point is that with the current implementation
> ranges
> >> is needed because otherwise the ipmi driver probe will fail here:
> >>
> >> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> >> -> of_translate_address -> __of_translate_address
> >>
> >> Now we had a bit of discussion internally and to avoid
> >> having ranges we came up with two possible solutions:
> >>
> >> 1) Using bit 3 of phys.hi cell in 2.2.1 of
> >> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >> This would mean reworking of_bus_isa_get_flags in
> >> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> >> and setting a new flag to be checked in __of_address_to_resource
> >>
> >> 2) Adding a property in the bindings of each device that is
> >> a child of our LPC bus and modify __of_address_to_resource
> >> to check if the property is in the DT and eventually bypass
> >> of_translate_address
> >>
> >> However in both 1) and 2) there are some issues:
> >> in 1) we are not complying with the isa binding doc (we use
> >> a bit that should be zero); in 2) we need to modify the
> >> bindings documentation of the devices that are connected
> >> to our LPC controller (therefore modifying other devices
> >> bindings to fit our special case).
> >>
> >> I think that maybe having the 1:1 range mapping doesn't
> >> reflect well the reality but it is the less painful
> >> solution...
> >>
> >> What's your view?
> >
> > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > and that should be enough to translate the I/O port number.
> >
> > The only part we need to change here is to not go through
> > the crazy conversion all the way from PCI I/O space to a
> > physical address and back to a (logical) port number
> > that we do today with of_translate_address/pci_address_to_pio.
> >
> Sorry for the late response! Several days' leave....
> Do you want to bypass of_translate_address and pci_address_to_pio for
> the registered specific PIO?
> I think the bypass for of_translate_address is ok, but worry some new
> issues will emerge without the
> conversion between physical address and logical/linux port number.
> 
> When PCI host bridge which support IO operations is configured and
> enabled, the pci_address_to_pio will
> populate the logical IO range from ZERO for the first host bridge. Our
> LPC will also use part of the IO range
> started from ZERO. It will make in/out enter the wrong branch possibly.
> 
> In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only.
> But it seems not so good. In this way,
> PCI has no chance to use low 4K IO range(logical).
> 
> So, in V3, applying the conversion from physical/cpu address to
> logical/linux IO port for any IO ranges,
> including the LPC, but recorded the logical IO range for LPC. When
> calling in/out with a logical port address,
> we can check this port fall into LPC logical IO range and get back the
> real IO.
> 
> Do you have further comments about this??

I think there are two separate issues to be discussed:

The first issue is about having of_translate_address failing due to
"range" missing. About this Arnd suggested that it is not appropriate
to have a range describing a bridge 1:1 mapping and this was discussed
before in this thread. Arnd had a suggestion about this (see below) 
however (looking twice at the code) it seems to me that such solution 
would lead to quite some duplication from __of_translate_address()
in order to retrieve the actual addr from dt...

I think extending of_empty_ranges_quirk() may be a reasonable solution.
What do you think Arnd?
  
The second issue is a conflict between cpu addresses used by the LPC
controller and i/o tokens from pci endpoints.

About this what if we modify armn64_extio_ops to have a list of ranges
rather than only one range (now we have just start/end); then in the
LPC driver we can scan the LPC child devices and 
1) populate such list of ranges
2) call pci_register_io_range for such ranges

Then when calling __of_address_to_resource we retrieve I/O tokens 
for the devices on top of the LPC driver and in the I/O accessors
we call pci_pio_to_address to figure out the cpu address and compare
it to the list of ranges in armn64_extio_ops.
  
What about this?

Thanks

Gab

> 
> 
> > I can think of a several of ways to fix __of_address_to_resource
> > to just do the right thing according to the ISA binding to
> > make the normal drivers work.
> >
> > The easiest solution is probably to hook into the
> > "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> > and add a lookup for ISA buses there, and instead check
> > if some special I/O port operations were registered
> > for the port number, using an architecture specific
> > function that arm64 implements. Other architectures
> > like x86 that don't have a direct mapping between I/O
> > ports and MMIO addresses would implement that same
> > function differently.
> 
> What about add the specific quirk for Hip06 LPC in
> of_empty_ranges_quirk()??
> 
> you know, there are several cases in which of_translate_address return
> OF_BAD_ADDR.
> And if we only check the special port range, it seems a bit risky. If
> some device want to use this port range
> when no hip06 LPC is configured, the checking does not work. I think we
> should also check the relevant device.
> 
> 
> Best,
> Zhichang
> 
> 
> >
> > 	Arnd
> >
_______________________________________________
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] 160+ messages in thread

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 16:20                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-21 16:20 UTC (permalink / raw)
  To: zhichang, Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, John Garry,
	will.deacon, linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc

SGkgWmhpY2hhbmcNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiB6aGlj
aGFuZyBbbWFpbHRvOnpoaWNoYW5nLnl1YW4wMkBnbWFpbC5jb21dDQo+IFNlbnQ6IDIxIFNlcHRl
bWJlciAyMDE2IDExOjA5DQo+IFRvOiBBcm5kIEJlcmdtYW5uOyBsaW51eC1hcm0ta2VybmVsQGxp
c3RzLmluZnJhZGVhZC5vcmcNCj4gQ2M6IEdhYnJpZWxlIFBhb2xvbmk7IGRldmljZXRyZWVAdmdl
ci5rZXJuZWwub3JnOw0KPiBsb3JlbnpvLnBpZXJhbGlzaUBhcm0uY29tOyBtaW55YXJkQGFjbS5v
cmc7IGxpbnV4LXBjaUB2Z2VyLmtlcm5lbC5vcmc7DQo+IGdyZWdraEBsaW51eGZvdW5kYXRpb24u
b3JnOyBKb2huIEdhcnJ5OyB3aWxsLmRlYWNvbkBhcm0uY29tOyBsaW51eC0NCj4ga2VybmVsQHZn
ZXIua2VybmVsLm9yZzsgWXVhbnpoaWNoYW5nOyBMaW51eGFybTsgeHV3ZWkgKE8pOyBsaW51eC0N
Cj4gc2VyaWFsQHZnZXIua2VybmVsLm9yZzsgYmVuaEBrZXJuZWwuY3Jhc2hpbmcub3JnOw0KPiB6
b3Vyb25ncm9uZ0BnbWFpbC5jb207IGxpdml1LmR1ZGF1QGFybS5jb207IGthbnR5emNAMTYzLmNv
bQ0KPiBTdWJqZWN0OiBSZTogW1BBVENIIFYzIDIvNF0gQVJNNjQgTFBDOiBMUEMgZHJpdmVyIGlt
cGxlbWVudGF0aW9uIG9uDQo+IEhpcDA2DQo+IA0KPiBIaSwgQXJuZCwNCj4gDQo+IA0KPiANCj4g
T24gMjAxNuW5tDA55pyIMTXml6UgMjA6MjQsIEFybmQgQmVyZ21hbm4gd3JvdGU6DQo+ID4gT24g
VGh1cnNkYXksIFNlcHRlbWJlciAxNSwgMjAxNiAxMjowNTo1MSBQTSBDRVNUIEdhYnJpZWxlIFBh
b2xvbmkNCj4gd3JvdGU6DQo+ID4+PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+Pj4g
T24gVGh1cnNkYXksIFNlcHRlbWJlciAxNSwgMjAxNiA4OjAyOjI3IEFNIENFU1QgR2FicmllbGUg
UGFvbG9uaQ0KPiB3cm90ZToNCj4gPj4+Pg0KPiA+Pj4+IEZyb20gPDwzLjEuMS4gT3BlbiBGaXJt
d2FyZSBQcm9wZXJ0aWVzIGZvciBCdXMgTm9kZXM+PiBpbg0KPiA+Pj4+IGh0dHA6Ly93d3cuZmly
bXdhcmUub3JnLzEyNzUvYmluZGluZ3MvaXNhL2lzYTBfNGQucHMNCj4gPj4+Pg0KPiA+Pj4+IEkg
cXVvdGU6DQo+ID4+Pj4gIlRoZXJlIHNoYWxsIGJlIGFuIGVudHJ5IGluIHRoZSAicmFuZ2VzIiBw
cm9wZXJ0eSBmb3IgZWFjaA0KPiA+Pj4+IG9mIHRoZSBNZW1vcnkgYW5kL29yIEkvTyBzcGFjZXMg
aWYgdGhhdCBhZGRyZXNzIHNwYWNlIGlzDQo+ID4+Pj4gbWFwcGVkIHRocm91Z2ggdGhlIGJyaWRn
ZS4iDQo+ID4+Pj4NCj4gPj4+PiBJdCBzZWVtcyB0byBtZSB0aGF0IGl0IGlzIG9rIHRvIGhhdmUg
MToxIGFkZHJlc3MgbWFwcGluZyBhbmQgdGhhdA0KPiA+Pj4+IHRoZXJlZm9yZSBvZl90cmFuc2xh
dGVfYWRkcmVzcygpIHNob3VsZCBmYWlsIGlmICJyYW5nZXMiIGlzIG5vdA0KPiA+Pj4+IHByZXNl
bnQuDQo+ID4+Pg0KPiA+Pj4gVGhlIGtleSBoZXJlIGlzIHRoZSBkZWZpbml0aW9uIG9mICJtYXBw
ZWQgdGhyb3VnaCB0aGUgYnJpZGdlIi4NCj4gPj4+IEkgY2FuIG9ubHkgdW5kZXJzdGFuZCB0aGlz
IGFzICJkaXJlY3RseSBtYXBwZWQiLCBpLmUuIGFuIEkvTw0KPiA+Pj4gcG9ydCBvZiB0aGUgY2hp
bGQgYnVzIGNvcnJlc3BvbmRzIGRpcmVjdGx5IHRvIGEgbWVtb3J5IGFkZHJlc3MNCj4gPj4+IG9u
IHRoZSBwYXJlbnQgYnVzLCBidXQgdGhpcyBpcyBub3QgdGhlIGNhc2UgaGVyZS4NCj4gPj4+DQo+
ID4+PiBUaGUgcHJvYmxlbSB3aXRoIGFkZGluZyB0aGUgbWFwcGluZyBoZXJlIGlzIHRoYXQgaXQg
bG9va3MNCj4gPj4+IGxpa2UgaXQgc2hvdWxkIGJlIHZhbGlkIHRvIGNyZWF0ZSBhIHBhZ2UgdGFi
bGUgZW50cnkgZm9yDQo+ID4+PiB0aGUgYWRkcmVzcyByZXR1cm5lZCBmcm9tIHRoZSB0cmFuc2xh
dGlvbiBhbmQgYWNjZXNzIGl0IHRocm91Z2gNCj4gPj4+IGEgcG9pbnRlciBkZXJlZmVyZW5jZSwg
YnV0IHRoYXQgaXMgY2xlYXJseSBub3QgcG9zc2libGUuDQo+ID4+DQo+ID4+IEkgdW5kZXJzdGFu
ZCB0aGF0IHNvbWVob3cgd2UgYXJlIGFidXNpbmcgb2YgdGhlIHJhbmdlcyBwcm9wZXJ0eQ0KPiA+
PiBoZXJlIGhvd2V2ZXIgdGhlIHBvaW50IGlzIHRoYXQgd2l0aCB0aGUgY3VycmVudCBpbXBsZW1l
bnRhdGlvbg0KPiByYW5nZXMNCj4gPj4gaXMgbmVlZGVkIGJlY2F1c2Ugb3RoZXJ3aXNlIHRoZSBp
cG1pIGRyaXZlciBwcm9iZSB3aWxsIGZhaWwgaGVyZToNCj4gPj4NCj4gPj4gb2ZfaXBtaV9wcm9i
ZSAtPiBvZl9hZGRyZXNzX3RvX3Jlc291cmNlIC0+IF9fb2ZfYWRkcmVzc190b19yZXNvdXJjZQ0K
PiA+PiAtPiBvZl90cmFuc2xhdGVfYWRkcmVzcyAtPiBfX29mX3RyYW5zbGF0ZV9hZGRyZXNzDQo+
ID4+DQo+ID4+IE5vdyB3ZSBoYWQgYSBiaXQgb2YgZGlzY3Vzc2lvbiBpbnRlcm5hbGx5IGFuZCB0
byBhdm9pZA0KPiA+PiBoYXZpbmcgcmFuZ2VzIHdlIGNhbWUgdXAgd2l0aCB0d28gcG9zc2libGUg
c29sdXRpb25zOg0KPiA+Pg0KPiA+PiAxKSBVc2luZyBiaXQgMyBvZiBwaHlzLmhpIGNlbGwgaW4g
Mi4yLjEgb2YNCj4gPj4gaHR0cDovL3d3dy5maXJtd2FyZS5vcmcvMTI3NS9iaW5kaW5ncy9pc2Ev
aXNhMF80ZC5wcw0KPiA+PiBUaGlzIHdvdWxkIG1lYW4gcmV3b3JraW5nIG9mX2J1c19pc2FfZ2V0
X2ZsYWdzIGluDQo+ID4+IGh0dHA6Ly9seHIuZnJlZS1lbGVjdHJvbnMuY29tL3NvdXJjZS9kcml2
ZXJzL29mL2FkZHJlc3MuYyNMMzk4DQo+ID4+IGFuZCBzZXR0aW5nIGEgbmV3IGZsYWcgdG8gYmUg
Y2hlY2tlZCBpbiBfX29mX2FkZHJlc3NfdG9fcmVzb3VyY2UNCj4gPj4NCj4gPj4gMikgQWRkaW5n
IGEgcHJvcGVydHkgaW4gdGhlIGJpbmRpbmdzIG9mIGVhY2ggZGV2aWNlIHRoYXQgaXMNCj4gPj4g
YSBjaGlsZCBvZiBvdXIgTFBDIGJ1cyBhbmQgbW9kaWZ5IF9fb2ZfYWRkcmVzc190b19yZXNvdXJj
ZQ0KPiA+PiB0byBjaGVjayBpZiB0aGUgcHJvcGVydHkgaXMgaW4gdGhlIERUIGFuZCBldmVudHVh
bGx5IGJ5cGFzcw0KPiA+PiBvZl90cmFuc2xhdGVfYWRkcmVzcw0KPiA+Pg0KPiA+PiBIb3dldmVy
IGluIGJvdGggMSkgYW5kIDIpIHRoZXJlIGFyZSBzb21lIGlzc3VlczoNCj4gPj4gaW4gMSkgd2Ug
YXJlIG5vdCBjb21wbHlpbmcgd2l0aCB0aGUgaXNhIGJpbmRpbmcgZG9jICh3ZSB1c2UNCj4gPj4g
YSBiaXQgdGhhdCBzaG91bGQgYmUgemVybyk7IGluIDIpIHdlIG5lZWQgdG8gbW9kaWZ5IHRoZQ0K
PiA+PiBiaW5kaW5ncyBkb2N1bWVudGF0aW9uIG9mIHRoZSBkZXZpY2VzIHRoYXQgYXJlIGNvbm5l
Y3RlZA0KPiA+PiB0byBvdXIgTFBDIGNvbnRyb2xsZXIgKHRoZXJlZm9yZSBtb2RpZnlpbmcgb3Ro
ZXIgZGV2aWNlcw0KPiA+PiBiaW5kaW5ncyB0byBmaXQgb3VyIHNwZWNpYWwgY2FzZSkuDQo+ID4+
DQo+ID4+IEkgdGhpbmsgdGhhdCBtYXliZSBoYXZpbmcgdGhlIDE6MSByYW5nZSBtYXBwaW5nIGRv
ZXNuJ3QNCj4gPj4gcmVmbGVjdCB3ZWxsIHRoZSByZWFsaXR5IGJ1dCBpdCBpcyB0aGUgbGVzcyBw
YWluZnVsDQo+ID4+IHNvbHV0aW9uLi4uDQo+ID4+DQo+ID4+IFdoYXQncyB5b3VyIHZpZXc/DQo+
ID4NCj4gPiBXZSBjYW4gY2hlY2sgdGhlICdpJyBiaXQgZm9yIEkvTyBzcGFjZSBpbiBvZl9idXNf
aXNhX2dldF9mbGFncywNCj4gPiBhbmQgdGhhdCBzaG91bGQgYmUgZW5vdWdoIHRvIHRyYW5zbGF0
ZSB0aGUgSS9PIHBvcnQgbnVtYmVyLg0KPiA+DQo+ID4gVGhlIG9ubHkgcGFydCB3ZSBuZWVkIHRv
IGNoYW5nZSBoZXJlIGlzIHRvIG5vdCBnbyB0aHJvdWdoDQo+ID4gdGhlIGNyYXp5IGNvbnZlcnNp
b24gYWxsIHRoZSB3YXkgZnJvbSBQQ0kgSS9PIHNwYWNlIHRvIGENCj4gPiBwaHlzaWNhbCBhZGRy
ZXNzIGFuZCBiYWNrIHRvIGEgKGxvZ2ljYWwpIHBvcnQgbnVtYmVyDQo+ID4gdGhhdCB3ZSBkbyB0
b2RheSB3aXRoIG9mX3RyYW5zbGF0ZV9hZGRyZXNzL3BjaV9hZGRyZXNzX3RvX3Bpby4NCj4gPg0K
PiBTb3JyeSBmb3IgdGhlIGxhdGUgcmVzcG9uc2UhIFNldmVyYWwgZGF5cycgbGVhdmUuLi4uDQo+
IERvIHlvdSB3YW50IHRvIGJ5cGFzcyBvZl90cmFuc2xhdGVfYWRkcmVzcyBhbmQgcGNpX2FkZHJl
c3NfdG9fcGlvIGZvcg0KPiB0aGUgcmVnaXN0ZXJlZCBzcGVjaWZpYyBQSU8/DQo+IEkgdGhpbmsg
dGhlIGJ5cGFzcyBmb3Igb2ZfdHJhbnNsYXRlX2FkZHJlc3MgaXMgb2ssIGJ1dCB3b3JyeSBzb21l
IG5ldw0KPiBpc3N1ZXMgd2lsbCBlbWVyZ2Ugd2l0aG91dCB0aGUNCj4gY29udmVyc2lvbiBiZXR3
ZWVuIHBoeXNpY2FsIGFkZHJlc3MgYW5kIGxvZ2ljYWwvbGludXggcG9ydCBudW1iZXIuDQo+IA0K
PiBXaGVuIFBDSSBob3N0IGJyaWRnZSB3aGljaCBzdXBwb3J0IElPIG9wZXJhdGlvbnMgaXMgY29u
ZmlndXJlZCBhbmQNCj4gZW5hYmxlZCwgdGhlIHBjaV9hZGRyZXNzX3RvX3BpbyB3aWxsDQo+IHBv
cHVsYXRlIHRoZSBsb2dpY2FsIElPIHJhbmdlIGZyb20gWkVSTyBmb3IgdGhlIGZpcnN0IGhvc3Qg
YnJpZGdlLiBPdXINCj4gTFBDIHdpbGwgYWxzbyB1c2UgcGFydCBvZiB0aGUgSU8gcmFuZ2UNCj4g
c3RhcnRlZCBmcm9tIFpFUk8uIEl0IHdpbGwgbWFrZSBpbi9vdXQgZW50ZXIgdGhlIHdyb25nIGJy
YW5jaCBwb3NzaWJseS4NCj4gDQo+IEluIFYyLCB0aGUgMCAtIDB4MTAwMCBsb2dpY2FsIElPIHJh
bmdlIGlzIHJlc2VydmVkIGZvciBMUEMgdXNlIG9ubHkuDQo+IEJ1dCBpdCBzZWVtcyBub3Qgc28g
Z29vZC4gSW4gdGhpcyB3YXksDQo+IFBDSSBoYXMgbm8gY2hhbmNlIHRvIHVzZSBsb3cgNEsgSU8g
cmFuZ2UobG9naWNhbCkuDQo+IA0KPiBTbywgaW4gVjMsIGFwcGx5aW5nIHRoZSBjb252ZXJzaW9u
IGZyb20gcGh5c2ljYWwvY3B1IGFkZHJlc3MgdG8NCj4gbG9naWNhbC9saW51eCBJTyBwb3J0IGZv
ciBhbnkgSU8gcmFuZ2VzLA0KPiBpbmNsdWRpbmcgdGhlIExQQywgYnV0IHJlY29yZGVkIHRoZSBs
b2dpY2FsIElPIHJhbmdlIGZvciBMUEMuIFdoZW4NCj4gY2FsbGluZyBpbi9vdXQgd2l0aCBhIGxv
Z2ljYWwgcG9ydCBhZGRyZXNzLA0KPiB3ZSBjYW4gY2hlY2sgdGhpcyBwb3J0IGZhbGwgaW50byBM
UEMgbG9naWNhbCBJTyByYW5nZSBhbmQgZ2V0IGJhY2sgdGhlDQo+IHJlYWwgSU8uDQo+IA0KPiBE
byB5b3UgaGF2ZSBmdXJ0aGVyIGNvbW1lbnRzIGFib3V0IHRoaXM/Pw0KDQpJIHRoaW5rIHRoZXJl
IGFyZSB0d28gc2VwYXJhdGUgaXNzdWVzIHRvIGJlIGRpc2N1c3NlZDoNCg0KVGhlIGZpcnN0IGlz
c3VlIGlzIGFib3V0IGhhdmluZyBvZl90cmFuc2xhdGVfYWRkcmVzcyBmYWlsaW5nIGR1ZSB0bw0K
InJhbmdlIiBtaXNzaW5nLiBBYm91dCB0aGlzIEFybmQgc3VnZ2VzdGVkIHRoYXQgaXQgaXMgbm90
IGFwcHJvcHJpYXRlDQp0byBoYXZlIGEgcmFuZ2UgZGVzY3JpYmluZyBhIGJyaWRnZSAxOjEgbWFw
cGluZyBhbmQgdGhpcyB3YXMgZGlzY3Vzc2VkDQpiZWZvcmUgaW4gdGhpcyB0aHJlYWQuIEFybmQg
aGFkIGEgc3VnZ2VzdGlvbiBhYm91dCB0aGlzIChzZWUgYmVsb3cpIA0KaG93ZXZlciAobG9va2lu
ZyB0d2ljZSBhdCB0aGUgY29kZSkgaXQgc2VlbXMgdG8gbWUgdGhhdCBzdWNoIHNvbHV0aW9uIA0K
d291bGQgbGVhZCB0byBxdWl0ZSBzb21lIGR1cGxpY2F0aW9uIGZyb20gX19vZl90cmFuc2xhdGVf
YWRkcmVzcygpDQppbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgYWN0dWFsIGFkZHIgZnJvbSBkdC4u
Lg0KDQpJIHRoaW5rIGV4dGVuZGluZyBvZl9lbXB0eV9yYW5nZXNfcXVpcmsoKSBtYXkgYmUgYSBy
ZWFzb25hYmxlIHNvbHV0aW9uLg0KV2hhdCBkbyB5b3UgdGhpbmsgQXJuZD8NCiAgDQpUaGUgc2Vj
b25kIGlzc3VlIGlzIGEgY29uZmxpY3QgYmV0d2VlbiBjcHUgYWRkcmVzc2VzIHVzZWQgYnkgdGhl
IExQQw0KY29udHJvbGxlciBhbmQgaS9vIHRva2VucyBmcm9tIHBjaSBlbmRwb2ludHMuDQoNCkFi
b3V0IHRoaXMgd2hhdCBpZiB3ZSBtb2RpZnkgYXJtbjY0X2V4dGlvX29wcyB0byBoYXZlIGEgbGlz
dCBvZiByYW5nZXMNCnJhdGhlciB0aGFuIG9ubHkgb25lIHJhbmdlIChub3cgd2UgaGF2ZSBqdXN0
IHN0YXJ0L2VuZCk7IHRoZW4gaW4gdGhlDQpMUEMgZHJpdmVyIHdlIGNhbiBzY2FuIHRoZSBMUEMg
Y2hpbGQgZGV2aWNlcyBhbmQgDQoxKSBwb3B1bGF0ZSBzdWNoIGxpc3Qgb2YgcmFuZ2VzDQoyKSBj
YWxsIHBjaV9yZWdpc3Rlcl9pb19yYW5nZSBmb3Igc3VjaCByYW5nZXMNCg0KVGhlbiB3aGVuIGNh
bGxpbmcgX19vZl9hZGRyZXNzX3RvX3Jlc291cmNlIHdlIHJldHJpZXZlIEkvTyB0b2tlbnMgDQpm
b3IgdGhlIGRldmljZXMgb24gdG9wIG9mIHRoZSBMUEMgZHJpdmVyIGFuZCBpbiB0aGUgSS9PIGFj
Y2Vzc29ycw0Kd2UgY2FsbCBwY2lfcGlvX3RvX2FkZHJlc3MgdG8gZmlndXJlIG91dCB0aGUgY3B1
IGFkZHJlc3MgYW5kIGNvbXBhcmUNCml0IHRvIHRoZSBsaXN0IG9mIHJhbmdlcyBpbiBhcm1uNjRf
ZXh0aW9fb3BzLg0KICANCldoYXQgYWJvdXQgdGhpcz8NCg0KVGhhbmtzDQoNCkdhYg0KDQo+IA0K
PiANCj4gPiBJIGNhbiB0aGluayBvZiBhIHNldmVyYWwgb2Ygd2F5cyB0byBmaXggX19vZl9hZGRy
ZXNzX3RvX3Jlc291cmNlDQo+ID4gdG8ganVzdCBkbyB0aGUgcmlnaHQgdGhpbmcgYWNjb3JkaW5n
IHRvIHRoZSBJU0EgYmluZGluZyB0bw0KPiA+IG1ha2UgdGhlIG5vcm1hbCBkcml2ZXJzIHdvcmsu
DQo+ID4NCj4gPiBUaGUgZWFzaWVzdCBzb2x1dGlvbiBpcyBwcm9iYWJseSB0byBob29rIGludG8g
dGhlDQo+ID4gInRhZGRyID09IE9GX0JBRF9BRERSIiBjYXNlIGluIF9fb2ZfYWRkcmVzc190b19y
ZXNvdXJjZQ0KPiA+IGFuZCBhZGQgYSBsb29rdXAgZm9yIElTQSBidXNlcyB0aGVyZSwgYW5kIGlu
c3RlYWQgY2hlY2sNCj4gPiBpZiBzb21lIHNwZWNpYWwgSS9PIHBvcnQgb3BlcmF0aW9ucyB3ZXJl
IHJlZ2lzdGVyZWQNCj4gPiBmb3IgdGhlIHBvcnQgbnVtYmVyLCB1c2luZyBhbiBhcmNoaXRlY3R1
cmUgc3BlY2lmaWMNCj4gPiBmdW5jdGlvbiB0aGF0IGFybTY0IGltcGxlbWVudHMuIE90aGVyIGFy
Y2hpdGVjdHVyZXMNCj4gPiBsaWtlIHg4NiB0aGF0IGRvbid0IGhhdmUgYSBkaXJlY3QgbWFwcGlu
ZyBiZXR3ZWVuIEkvTw0KPiA+IHBvcnRzIGFuZCBNTUlPIGFkZHJlc3NlcyB3b3VsZCBpbXBsZW1l
bnQgdGhhdCBzYW1lDQo+ID4gZnVuY3Rpb24gZGlmZmVyZW50bHkuDQo+IA0KPiBXaGF0IGFib3V0
IGFkZCB0aGUgc3BlY2lmaWMgcXVpcmsgZm9yIEhpcDA2IExQQyBpbg0KPiBvZl9lbXB0eV9yYW5n
ZXNfcXVpcmsoKT8/DQo+IA0KPiB5b3Uga25vdywgdGhlcmUgYXJlIHNldmVyYWwgY2FzZXMgaW4g
d2hpY2ggb2ZfdHJhbnNsYXRlX2FkZHJlc3MgcmV0dXJuDQo+IE9GX0JBRF9BRERSLg0KPiBBbmQg
aWYgd2Ugb25seSBjaGVjayB0aGUgc3BlY2lhbCBwb3J0IHJhbmdlLCBpdCBzZWVtcyBhIGJpdCBy
aXNreS4gSWYNCj4gc29tZSBkZXZpY2Ugd2FudCB0byB1c2UgdGhpcyBwb3J0IHJhbmdlDQo+IHdo
ZW4gbm8gaGlwMDYgTFBDIGlzIGNvbmZpZ3VyZWQsIHRoZSBjaGVja2luZyBkb2VzIG5vdCB3b3Jr
LiBJIHRoaW5rIHdlDQo+IHNob3VsZCBhbHNvIGNoZWNrIHRoZSByZWxldmFudCBkZXZpY2UuDQo+
IA0KPiANCj4gQmVzdCwNCj4gWmhpY2hhbmcNCj4gDQo+IA0KPiA+DQo+ID4gCUFybmQNCj4gPg0K
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJt
LWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3Jn
Cmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtl
cm5lbAo=

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 16:20                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-21 16:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Zhichang

> -----Original Message-----
> From: zhichang [mailto:zhichang.yuan02 at gmail.com]
> Sent: 21 September 2016 11:09
> To: Arnd Bergmann; linux-arm-kernel at lists.infradead.org
> Cc: Gabriele Paoloni; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> gregkh at linuxfoundation.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; Yuanzhichang; Linuxarm; xuwei (O); linux-
> serial at vger.kernel.org; benh at kernel.crashing.org;
> zourongrong at gmail.com; liviu.dudau at arm.com; kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> Hi, Arnd,
> 
> 
> 
> On 2016?09?15? 20:24, Arnd Bergmann wrote:
> > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> wrote:
> >>> -----Original Message-----
> >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> wrote:
> >>>>
> >>>> From <<3.1.1. Open Firmware Properties for Bus Nodes>> in
> >>>> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >>>>
> >>>> I quote:
> >>>> "There shall be an entry in the "ranges" property for each
> >>>> of the Memory and/or I/O spaces if that address space is
> >>>> mapped through the bridge."
> >>>>
> >>>> It seems to me that it is ok to have 1:1 address mapping and that
> >>>> therefore of_translate_address() should fail if "ranges" is not
> >>>> present.
> >>>
> >>> The key here is the definition of "mapped through the bridge".
> >>> I can only understand this as "directly mapped", i.e. an I/O
> >>> port of the child bus corresponds directly to a memory address
> >>> on the parent bus, but this is not the case here.
> >>>
> >>> The problem with adding the mapping here is that it looks
> >>> like it should be valid to create a page table entry for
> >>> the address returned from the translation and access it through
> >>> a pointer dereference, but that is clearly not possible.
> >>
> >> I understand that somehow we are abusing of the ranges property
> >> here however the point is that with the current implementation
> ranges
> >> is needed because otherwise the ipmi driver probe will fail here:
> >>
> >> of_ipmi_probe -> of_address_to_resource -> __of_address_to_resource
> >> -> of_translate_address -> __of_translate_address
> >>
> >> Now we had a bit of discussion internally and to avoid
> >> having ranges we came up with two possible solutions:
> >>
> >> 1) Using bit 3 of phys.hi cell in 2.2.1 of
> >> http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> >> This would mean reworking of_bus_isa_get_flags in
> >> http://lxr.free-electrons.com/source/drivers/of/address.c#L398
> >> and setting a new flag to be checked in __of_address_to_resource
> >>
> >> 2) Adding a property in the bindings of each device that is
> >> a child of our LPC bus and modify __of_address_to_resource
> >> to check if the property is in the DT and eventually bypass
> >> of_translate_address
> >>
> >> However in both 1) and 2) there are some issues:
> >> in 1) we are not complying with the isa binding doc (we use
> >> a bit that should be zero); in 2) we need to modify the
> >> bindings documentation of the devices that are connected
> >> to our LPC controller (therefore modifying other devices
> >> bindings to fit our special case).
> >>
> >> I think that maybe having the 1:1 range mapping doesn't
> >> reflect well the reality but it is the less painful
> >> solution...
> >>
> >> What's your view?
> >
> > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > and that should be enough to translate the I/O port number.
> >
> > The only part we need to change here is to not go through
> > the crazy conversion all the way from PCI I/O space to a
> > physical address and back to a (logical) port number
> > that we do today with of_translate_address/pci_address_to_pio.
> >
> Sorry for the late response! Several days' leave....
> Do you want to bypass of_translate_address and pci_address_to_pio for
> the registered specific PIO?
> I think the bypass for of_translate_address is ok, but worry some new
> issues will emerge without the
> conversion between physical address and logical/linux port number.
> 
> When PCI host bridge which support IO operations is configured and
> enabled, the pci_address_to_pio will
> populate the logical IO range from ZERO for the first host bridge. Our
> LPC will also use part of the IO range
> started from ZERO. It will make in/out enter the wrong branch possibly.
> 
> In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only.
> But it seems not so good. In this way,
> PCI has no chance to use low 4K IO range(logical).
> 
> So, in V3, applying the conversion from physical/cpu address to
> logical/linux IO port for any IO ranges,
> including the LPC, but recorded the logical IO range for LPC. When
> calling in/out with a logical port address,
> we can check this port fall into LPC logical IO range and get back the
> real IO.
> 
> Do you have further comments about this??

I think there are two separate issues to be discussed:

The first issue is about having of_translate_address failing due to
"range" missing. About this Arnd suggested that it is not appropriate
to have a range describing a bridge 1:1 mapping and this was discussed
before in this thread. Arnd had a suggestion about this (see below) 
however (looking twice at the code) it seems to me that such solution 
would lead to quite some duplication from __of_translate_address()
in order to retrieve the actual addr from dt...

I think extending of_empty_ranges_quirk() may be a reasonable solution.
What do you think Arnd?
  
The second issue is a conflict between cpu addresses used by the LPC
controller and i/o tokens from pci endpoints.

About this what if we modify armn64_extio_ops to have a list of ranges
rather than only one range (now we have just start/end); then in the
LPC driver we can scan the LPC child devices and 
1) populate such list of ranges
2) call pci_register_io_range for such ranges

Then when calling __of_address_to_resource we retrieve I/O tokens 
for the devices on top of the LPC driver and in the I/O accessors
we call pci_pio_to_address to figure out the cpu address and compare
it to the list of ranges in armn64_extio_ops.
  
What about this?

Thanks

Gab

> 
> 
> > I can think of a several of ways to fix __of_address_to_resource
> > to just do the right thing according to the ISA binding to
> > make the normal drivers work.
> >
> > The easiest solution is probably to hook into the
> > "taddr == OF_BAD_ADDR" case in __of_address_to_resource
> > and add a lookup for ISA buses there, and instead check
> > if some special I/O port operations were registered
> > for the port number, using an architecture specific
> > function that arm64 implements. Other architectures
> > like x86 that don't have a direct mapping between I/O
> > ports and MMIO addresses would implement that same
> > function differently.
> 
> What about add the specific quirk for Hip06 LPC in
> of_empty_ranges_quirk()??
> 
> you know, there are several cases in which of_translate_address return
> OF_BAD_ADDR.
> And if we only check the special port range, it seems a bit risky. If
> some device want to use this port range
> when no hip06 LPC is configured, the checking does not work. I think we
> should also check the relevant device.
> 
> 
> Best,
> Zhichang
> 
> 
> >
> > 	Arnd
> >

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
  2016-09-21 10:12           ` zhichang
  (?)
@ 2016-09-21 19:29             ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 19:29 UTC (permalink / raw)
  To: zhichang
  Cc: linux-arm-kernel, zhichang.yuan, devicetree, lorenzo.pieralisi,
	gabriele.paoloni, minyard, gregkh, benh, john.garry, will.deacon,
	linux-kernel, xuwei5, linuxarm, linux-serial, linux-pci,
	zourongrong, liviu.dudau, kantyzc

On Wednesday, September 21, 2016 6:12:28 PM CEST zhichang wrote:
> On 2016年09月15日 05:33, Arnd Bergmann wrote:
> > On Wednesday, September 14, 2016 11:04:33 PM CEST zhichang.yuan wrote:
> >> The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :
> >>
> >> +static struct platform_driver hs_lpc8250_driver = {
> >> +       .driver = {
> >> +               .name           = "hisi-lpc-uart",
> >> +               .of_match_table = hs8250_of_match,
> >> +               .acpi_match_table = ACPI_PTR(hs8250_acpi_match),
> >>
> >> So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
> >> driver file.
> >>
> > 
> > After looking again, I'm pretty sure that drivers/tty/serial/8250/8250_pnp.c
> > will handle the ACPI case without modifications, you just need to adapt
> > the 8250_of driver to handle IORESOURCE_IO ports. This will be required
> > anyway with the next version once the LPC bridge is on the PCI bus.
> > 
> 
> Yes. You are right.
> 
> When the indirectIO patch is accepted, no much changes needed in these two file to support LPC UART.
> 
> BTW, what is your target to change these two files to support LPC uart?
> Do you think we don't need to add many new c files??

I think by modifying 8250_of.c, you should be able to make any UART on
some LPC bus work, regardless of what controller is used.

The ACPI version (8250_pnp.c) shouldn't need any changes at all if I
read that correctly.

	Arnd

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

* Re: [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-21 19:29             ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 19:29 UTC (permalink / raw)
  To: zhichang
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard,
	linux-pci, gregkh, john.garry, will.deacon, linux-kernel,
	zhichang.yuan, linuxarm, xuwei5, linux-serial, benh, zourongrong,
	liviu.dudau, kantyzc, linux-arm-kernel

T24gV2VkbmVzZGF5LCBTZXB0ZW1iZXIgMjEsIDIwMTYgNjoxMjoyOCBQTSBDRVNUIHpoaWNoYW5n
IHdyb3RlOgo+IE9uIDIwMTblubQwOeaciDE15pelIDA1OjMzLCBBcm5kIEJlcmdtYW5uIHdyb3Rl
Ogo+ID4gT24gV2VkbmVzZGF5LCBTZXB0ZW1iZXIgMTQsIDIwMTYgMTE6MDQ6MzMgUE0gQ0VTVCB6
aGljaGFuZy55dWFuIHdyb3RlOgo+ID4+IFRoZSA4MjUwX2hpc2lfbHBjLmMgc3VwcG9ydCBib3Ro
IEFDUEkgYW5kIGR0cyBzaW1pbGFyIHRvIDgyNTBfZHcgOgo+ID4+Cj4gPj4gK3N0YXRpYyBzdHJ1
Y3QgcGxhdGZvcm1fZHJpdmVyIGhzX2xwYzgyNTBfZHJpdmVyID0gewo+ID4+ICsgICAgICAgLmRy
aXZlciA9IHsKPiA+PiArICAgICAgICAgICAgICAgLm5hbWUgICAgICAgICAgID0gImhpc2ktbHBj
LXVhcnQiLAo+ID4+ICsgICAgICAgICAgICAgICAub2ZfbWF0Y2hfdGFibGUgPSBoczgyNTBfb2Zf
bWF0Y2gsCj4gPj4gKyAgICAgICAgICAgICAgIC5hY3BpX21hdGNoX3RhYmxlID0gQUNQSV9QVFIo
aHM4MjUwX2FjcGlfbWF0Y2gpLAo+ID4+Cj4gPj4gU28sIEkgYW0gYSBsaXR0bGUgY29uZnVzZWQg
d2h5IHdlIG5lZWQgdG8gc3VwcG9ydCBkdHMgaW4gODI1MF9vZi5jIGFuZCBzdXBwb3J0IEFDUEkg
aW4gYW5vdGhlcgo+ID4+IGRyaXZlciBmaWxlLgo+ID4+Cj4gPiAKPiA+IEFmdGVyIGxvb2tpbmcg
YWdhaW4sIEknbSBwcmV0dHkgc3VyZSB0aGF0IGRyaXZlcnMvdHR5L3NlcmlhbC84MjUwLzgyNTBf
cG5wLmMKPiA+IHdpbGwgaGFuZGxlIHRoZSBBQ1BJIGNhc2Ugd2l0aG91dCBtb2RpZmljYXRpb25z
LCB5b3UganVzdCBuZWVkIHRvIGFkYXB0Cj4gPiB0aGUgODI1MF9vZiBkcml2ZXIgdG8gaGFuZGxl
IElPUkVTT1VSQ0VfSU8gcG9ydHMuIFRoaXMgd2lsbCBiZSByZXF1aXJlZAo+ID4gYW55d2F5IHdp
dGggdGhlIG5leHQgdmVyc2lvbiBvbmNlIHRoZSBMUEMgYnJpZGdlIGlzIG9uIHRoZSBQQ0kgYnVz
Lgo+ID4gCj4gCj4gWWVzLiBZb3UgYXJlIHJpZ2h0Lgo+IAo+IFdoZW4gdGhlIGluZGlyZWN0SU8g
cGF0Y2ggaXMgYWNjZXB0ZWQsIG5vIG11Y2ggY2hhbmdlcyBuZWVkZWQgaW4gdGhlc2UgdHdvIGZp
bGUgdG8gc3VwcG9ydCBMUEMgVUFSVC4KPiAKPiBCVFcsIHdoYXQgaXMgeW91ciB0YXJnZXQgdG8g
Y2hhbmdlIHRoZXNlIHR3byBmaWxlcyB0byBzdXBwb3J0IExQQyB1YXJ0Pwo+IERvIHlvdSB0aGlu
ayB3ZSBkb24ndCBuZWVkIHRvIGFkZCBtYW55IG5ldyBjIGZpbGVzPz8KCkkgdGhpbmsgYnkgbW9k
aWZ5aW5nIDgyNTBfb2YuYywgeW91IHNob3VsZCBiZSBhYmxlIHRvIG1ha2UgYW55IFVBUlQgb24K
c29tZSBMUEMgYnVzIHdvcmssIHJlZ2FyZGxlc3Mgb2Ygd2hhdCBjb250cm9sbGVyIGlzIHVzZWQu
CgpUaGUgQUNQSSB2ZXJzaW9uICg4MjUwX3BucC5jKSBzaG91bGRuJ3QgbmVlZCBhbnkgY2hhbmdl
cyBhdCBhbGwgaWYgSQpyZWFkIHRoYXQgY29ycmVjdGx5LgoKCUFybmQKCl9fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGlu
ZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMu
aW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK

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

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
@ 2016-09-21 19:29             ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 19:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 21, 2016 6:12:28 PM CEST zhichang wrote:
> On 2016?09?15? 05:33, Arnd Bergmann wrote:
> > On Wednesday, September 14, 2016 11:04:33 PM CEST zhichang.yuan wrote:
> >> The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :
> >>
> >> +static struct platform_driver hs_lpc8250_driver = {
> >> +       .driver = {
> >> +               .name           = "hisi-lpc-uart",
> >> +               .of_match_table = hs8250_of_match,
> >> +               .acpi_match_table = ACPI_PTR(hs8250_acpi_match),
> >>
> >> So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
> >> driver file.
> >>
> > 
> > After looking again, I'm pretty sure that drivers/tty/serial/8250/8250_pnp.c
> > will handle the ACPI case without modifications, you just need to adapt
> > the 8250_of driver to handle IORESOURCE_IO ports. This will be required
> > anyway with the next version once the LPC bridge is on the PCI bus.
> > 
> 
> Yes. You are right.
> 
> When the indirectIO patch is accepted, no much changes needed in these two file to support LPC UART.
> 
> BTW, what is your target to change these two files to support LPC uart?
> Do you think we don't need to add many new c files??

I think by modifying 8250_of.c, you should be able to make any UART on
some LPC bus work, regardless of what controller is used.

The ACPI version (8250_pnp.c) shouldn't need any changes at all if I
read that correctly.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-21 16:20                     ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-21 20:18                       ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 20:18 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni wrote:
> > -----Original Message-----
> > From: zhichang [mailto:zhichang.yuan02@gmail.com]
> > On 2016年09月15日 20:24, Arnd Bergmann wrote:
> > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > wrote:
> > >>> -----Original Message-----
> > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> > wrote:
> > >> I think that maybe having the 1:1 range mapping doesn't
> > >> reflect well the reality but it is the less painful
> > >> solution...
> > >>
> > >> What's your view?
> > >
> > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > and that should be enough to translate the I/O port number.
> > >
> > > The only part we need to change here is to not go through
> > > the crazy conversion all the way from PCI I/O space to a
> > > physical address and back to a (logical) port number
> > > that we do today with of_translate_address/pci_address_to_pio.
> > >
> > Sorry for the late response! Several days' leave....
> > Do you want to bypass of_translate_address and pci_address_to_pio for
> > the registered specific PIO?
> > I think the bypass for of_translate_address is ok, but worry some new
> > issues will emerge without the
> > conversion between physical address and logical/linux port number.

The same function that handles the non-translated region would
do that conversion.

> > When PCI host bridge which support IO operations is configured and
> > enabled, the pci_address_to_pio will
> > populate the logical IO range from ZERO for the first host bridge. Our
> > LPC will also use part of the IO range
> > started from ZERO. It will make in/out enter the wrong branch possibly.
> > 
> > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only.
> > But it seems not so good. In this way,
> > PCI has no chance to use low 4K IO range(logical).
> > 
> > So, in V3, applying the conversion from physical/cpu address to
> > logical/linux IO port for any IO ranges,
> > including the LPC, but recorded the logical IO range for LPC. When
> > calling in/out with a logical port address,
> > we can check this port fall into LPC logical IO range and get back the
> > real IO.

Right, and the same translation can be used in __of_address_to_resource()
going the opposite way.

> > Do you have further comments about this??
> 
> I think there are two separate issues to be discussed:
> 
> The first issue is about having of_translate_address failing due to
> "range" missing. About this Arnd suggested that it is not appropriate
> to have a range describing a bridge 1:1 mapping and this was discussed
> before in this thread. Arnd had a suggestion about this (see below) 
> however (looking twice at the code) it seems to me that such solution 
> would lead to quite some duplication from __of_translate_address()
> in order to retrieve the actual addr from dt...

I don't think we need to duplicate much, we can probably safely
assume that there are no nontrivial ranges in devices below the LPC
node, so we just walk up the bus to see if the node is a child
(or possibly grandchild etc) of the LPC bus, and treat any IO port
number under there as a physical port number, which has a known
offset from the Linux I/O port number.

> I think extending of_empty_ranges_quirk() may be a reasonable solution.
> What do you think Arnd?

I don't really like that idea, that quirk is meant to work around
broken DTs, but we can just make the DT valid and implement the
code properly.

> The second issue is a conflict between cpu addresses used by the LPC
> controller and i/o tokens from pci endpoints.
> 
> About this what if we modify armn64_extio_ops to have a list of ranges
> rather than only one range (now we have just start/end); then in the
> LPC driver we can scan the LPC child devices and 
> 1) populate such list of ranges
> 2) call pci_register_io_range for such ranges

Scanning the child devices sounds really wrong, please register just
one range that covers the bus to keep the workaround as simple
as possible.

> Then when calling __of_address_to_resource we retrieve I/O tokens 
> for the devices on top of the LPC driver and in the I/O accessors
> we call pci_pio_to_address to figure out the cpu address and compare
> it to the list of ranges in armn64_extio_ops.
>   
> What about this?

That seems really complex for something that can be quite simple.
The only thing we need to worry about is that the io_range_list
contains an entry for the LPC bus so we don't conflict with the
PCI buses.

	Arnd

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 20:18                       ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 20:18 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, linux-pci,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, zhichang, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel@lists.infradead.org

On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni wrote:
> > -----Original Message-----
> > From: zhichang [mailto:zhichang.yuan02@gmail.com]
> > On 2016年09月15日 20:24, Arnd Bergmann wrote:
> > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > wrote:
> > >>> -----Original Message-----
> > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> > wrote:
> > >> I think that maybe having the 1:1 range mapping doesn't
> > >> reflect well the reality but it is the less painful
> > >> solution...
> > >>
> > >> What's your view?
> > >
> > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > and that should be enough to translate the I/O port number.
> > >
> > > The only part we need to change here is to not go through
> > > the crazy conversion all the way from PCI I/O space to a
> > > physical address and back to a (logical) port number
> > > that we do today with of_translate_address/pci_address_to_pio.
> > >
> > Sorry for the late response! Several days' leave....
> > Do you want to bypass of_translate_address and pci_address_to_pio for
> > the registered specific PIO?
> > I think the bypass for of_translate_address is ok, but worry some new
> > issues will emerge without the
> > conversion between physical address and logical/linux port number.

The same function that handles the non-translated region would
do that conversion.

> > When PCI host bridge which support IO operations is configured and
> > enabled, the pci_address_to_pio will
> > populate the logical IO range from ZERO for the first host bridge. Our
> > LPC will also use part of the IO range
> > started from ZERO. It will make in/out enter the wrong branch possibly.
> > 
> > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only.
> > But it seems not so good. In this way,
> > PCI has no chance to use low 4K IO range(logical).
> > 
> > So, in V3, applying the conversion from physical/cpu address to
> > logical/linux IO port for any IO ranges,
> > including the LPC, but recorded the logical IO range for LPC. When
> > calling in/out with a logical port address,
> > we can check this port fall into LPC logical IO range and get back the
> > real IO.

Right, and the same translation can be used in __of_address_to_resource()
going the opposite way.

> > Do you have further comments about this??
> 
> I think there are two separate issues to be discussed:
> 
> The first issue is about having of_translate_address failing due to
> "range" missing. About this Arnd suggested that it is not appropriate
> to have a range describing a bridge 1:1 mapping and this was discussed
> before in this thread. Arnd had a suggestion about this (see below) 
> however (looking twice at the code) it seems to me that such solution 
> would lead to quite some duplication from __of_translate_address()
> in order to retrieve the actual addr from dt...

I don't think we need to duplicate much, we can probably safely
assume that there are no nontrivial ranges in devices below the LPC
node, so we just walk up the bus to see if the node is a child
(or possibly grandchild etc) of the LPC bus, and treat any IO port
number under there as a physical port number, which has a known
offset from the Linux I/O port number.

> I think extending of_empty_ranges_quirk() may be a reasonable solution.
> What do you think Arnd?

I don't really like that idea, that quirk is meant to work around
broken DTs, but we can just make the DT valid and implement the
code properly.

> The second issue is a conflict between cpu addresses used by the LPC
> controller and i/o tokens from pci endpoints.
> 
> About this what if we modify armn64_extio_ops to have a list of ranges
> rather than only one range (now we have just start/end); then in the
> LPC driver we can scan the LPC child devices and 
> 1) populate such list of ranges
> 2) call pci_register_io_range for such ranges

Scanning the child devices sounds really wrong, please register just
one range that covers the bus to keep the workaround as simple
as possible.

> Then when calling __of_address_to_resource we retrieve I/O tokens 
> for the devices on top of the LPC driver and in the I/O accessors
> we call pci_pio_to_address to figure out the cpu address and compare
> it to the list of ranges in armn64_extio_ops.
>   
> What about this?

That seems really complex for something that can be quite simple.
The only thing we need to worry about is that the io_range_list
contains an entry for the LPC bus so we don't conflict with the
PCI buses.

	Arnd

	Arnd

_______________________________________________
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] 160+ messages in thread

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 20:18                       ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 20:18 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, linux-pci,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, zhichang, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel

T24gV2VkbmVzZGF5LCBTZXB0ZW1iZXIgMjEsIDIwMTYgNDoyMDo1NSBQTSBDRVNUIEdhYnJpZWxl
IFBhb2xvbmkgd3JvdGU6Cj4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQo+ID4gRnJvbTog
emhpY2hhbmcgW21haWx0bzp6aGljaGFuZy55dWFuMDJAZ21haWwuY29tXQo+ID4gT24gMjAxNuW5
tDA55pyIMTXml6UgMjA6MjQsIEFybmQgQmVyZ21hbm4gd3JvdGU6Cj4gPiA+IE9uIFRodXJzZGF5
LCBTZXB0ZW1iZXIgMTUsIDIwMTYgMTI6MDU6NTEgUE0gQ0VTVCBHYWJyaWVsZSBQYW9sb25pCj4g
PiB3cm90ZToKPiA+ID4+PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQo+ID4gPj4+IE9uIFRo
dXJzZGF5LCBTZXB0ZW1iZXIgMTUsIDIwMTYgODowMjoyNyBBTSBDRVNUIEdhYnJpZWxlIFBhb2xv
bmkKPiA+IHdyb3RlOgo+ID4gPj4gSSB0aGluayB0aGF0IG1heWJlIGhhdmluZyB0aGUgMToxIHJh
bmdlIG1hcHBpbmcgZG9lc24ndAo+ID4gPj4gcmVmbGVjdCB3ZWxsIHRoZSByZWFsaXR5IGJ1dCBp
dCBpcyB0aGUgbGVzcyBwYWluZnVsCj4gPiA+PiBzb2x1dGlvbi4uLgo+ID4gPj4KPiA+ID4+IFdo
YXQncyB5b3VyIHZpZXc/Cj4gPiA+Cj4gPiA+IFdlIGNhbiBjaGVjayB0aGUgJ2knIGJpdCBmb3Ig
SS9PIHNwYWNlIGluIG9mX2J1c19pc2FfZ2V0X2ZsYWdzLAo+ID4gPiBhbmQgdGhhdCBzaG91bGQg
YmUgZW5vdWdoIHRvIHRyYW5zbGF0ZSB0aGUgSS9PIHBvcnQgbnVtYmVyLgo+ID4gPgo+ID4gPiBU
aGUgb25seSBwYXJ0IHdlIG5lZWQgdG8gY2hhbmdlIGhlcmUgaXMgdG8gbm90IGdvIHRocm91Z2gK
PiA+ID4gdGhlIGNyYXp5IGNvbnZlcnNpb24gYWxsIHRoZSB3YXkgZnJvbSBQQ0kgSS9PIHNwYWNl
IHRvIGEKPiA+ID4gcGh5c2ljYWwgYWRkcmVzcyBhbmQgYmFjayB0byBhIChsb2dpY2FsKSBwb3J0
IG51bWJlcgo+ID4gPiB0aGF0IHdlIGRvIHRvZGF5IHdpdGggb2ZfdHJhbnNsYXRlX2FkZHJlc3Mv
cGNpX2FkZHJlc3NfdG9fcGlvLgo+ID4gPgo+ID4gU29ycnkgZm9yIHRoZSBsYXRlIHJlc3BvbnNl
ISBTZXZlcmFsIGRheXMnIGxlYXZlLi4uLgo+ID4gRG8geW91IHdhbnQgdG8gYnlwYXNzIG9mX3Ry
YW5zbGF0ZV9hZGRyZXNzIGFuZCBwY2lfYWRkcmVzc190b19waW8gZm9yCj4gPiB0aGUgcmVnaXN0
ZXJlZCBzcGVjaWZpYyBQSU8/Cj4gPiBJIHRoaW5rIHRoZSBieXBhc3MgZm9yIG9mX3RyYW5zbGF0
ZV9hZGRyZXNzIGlzIG9rLCBidXQgd29ycnkgc29tZSBuZXcKPiA+IGlzc3VlcyB3aWxsIGVtZXJn
ZSB3aXRob3V0IHRoZQo+ID4gY29udmVyc2lvbiBiZXR3ZWVuIHBoeXNpY2FsIGFkZHJlc3MgYW5k
IGxvZ2ljYWwvbGludXggcG9ydCBudW1iZXIuCgpUaGUgc2FtZSBmdW5jdGlvbiB0aGF0IGhhbmRs
ZXMgdGhlIG5vbi10cmFuc2xhdGVkIHJlZ2lvbiB3b3VsZApkbyB0aGF0IGNvbnZlcnNpb24uCgo+
ID4gV2hlbiBQQ0kgaG9zdCBicmlkZ2Ugd2hpY2ggc3VwcG9ydCBJTyBvcGVyYXRpb25zIGlzIGNv
bmZpZ3VyZWQgYW5kCj4gPiBlbmFibGVkLCB0aGUgcGNpX2FkZHJlc3NfdG9fcGlvIHdpbGwKPiA+
IHBvcHVsYXRlIHRoZSBsb2dpY2FsIElPIHJhbmdlIGZyb20gWkVSTyBmb3IgdGhlIGZpcnN0IGhv
c3QgYnJpZGdlLiBPdXIKPiA+IExQQyB3aWxsIGFsc28gdXNlIHBhcnQgb2YgdGhlIElPIHJhbmdl
Cj4gPiBzdGFydGVkIGZyb20gWkVSTy4gSXQgd2lsbCBtYWtlIGluL291dCBlbnRlciB0aGUgd3Jv
bmcgYnJhbmNoIHBvc3NpYmx5Lgo+ID4gCj4gPiBJbiBWMiwgdGhlIDAgLSAweDEwMDAgbG9naWNh
bCBJTyByYW5nZSBpcyByZXNlcnZlZCBmb3IgTFBDIHVzZSBvbmx5Lgo+ID4gQnV0IGl0IHNlZW1z
IG5vdCBzbyBnb29kLiBJbiB0aGlzIHdheSwKPiA+IFBDSSBoYXMgbm8gY2hhbmNlIHRvIHVzZSBs
b3cgNEsgSU8gcmFuZ2UobG9naWNhbCkuCj4gPiAKPiA+IFNvLCBpbiBWMywgYXBwbHlpbmcgdGhl
IGNvbnZlcnNpb24gZnJvbSBwaHlzaWNhbC9jcHUgYWRkcmVzcyB0bwo+ID4gbG9naWNhbC9saW51
eCBJTyBwb3J0IGZvciBhbnkgSU8gcmFuZ2VzLAo+ID4gaW5jbHVkaW5nIHRoZSBMUEMsIGJ1dCBy
ZWNvcmRlZCB0aGUgbG9naWNhbCBJTyByYW5nZSBmb3IgTFBDLiBXaGVuCj4gPiBjYWxsaW5nIGlu
L291dCB3aXRoIGEgbG9naWNhbCBwb3J0IGFkZHJlc3MsCj4gPiB3ZSBjYW4gY2hlY2sgdGhpcyBw
b3J0IGZhbGwgaW50byBMUEMgbG9naWNhbCBJTyByYW5nZSBhbmQgZ2V0IGJhY2sgdGhlCj4gPiBy
ZWFsIElPLgoKUmlnaHQsIGFuZCB0aGUgc2FtZSB0cmFuc2xhdGlvbiBjYW4gYmUgdXNlZCBpbiBf
X29mX2FkZHJlc3NfdG9fcmVzb3VyY2UoKQpnb2luZyB0aGUgb3Bwb3NpdGUgd2F5LgoKPiA+IERv
IHlvdSBoYXZlIGZ1cnRoZXIgY29tbWVudHMgYWJvdXQgdGhpcz8/Cj4gCj4gSSB0aGluayB0aGVy
ZSBhcmUgdHdvIHNlcGFyYXRlIGlzc3VlcyB0byBiZSBkaXNjdXNzZWQ6Cj4gCj4gVGhlIGZpcnN0
IGlzc3VlIGlzIGFib3V0IGhhdmluZyBvZl90cmFuc2xhdGVfYWRkcmVzcyBmYWlsaW5nIGR1ZSB0
bwo+ICJyYW5nZSIgbWlzc2luZy4gQWJvdXQgdGhpcyBBcm5kIHN1Z2dlc3RlZCB0aGF0IGl0IGlz
IG5vdCBhcHByb3ByaWF0ZQo+IHRvIGhhdmUgYSByYW5nZSBkZXNjcmliaW5nIGEgYnJpZGdlIDE6
MSBtYXBwaW5nIGFuZCB0aGlzIHdhcyBkaXNjdXNzZWQKPiBiZWZvcmUgaW4gdGhpcyB0aHJlYWQu
IEFybmQgaGFkIGEgc3VnZ2VzdGlvbiBhYm91dCB0aGlzIChzZWUgYmVsb3cpIAo+IGhvd2V2ZXIg
KGxvb2tpbmcgdHdpY2UgYXQgdGhlIGNvZGUpIGl0IHNlZW1zIHRvIG1lIHRoYXQgc3VjaCBzb2x1
dGlvbiAKPiB3b3VsZCBsZWFkIHRvIHF1aXRlIHNvbWUgZHVwbGljYXRpb24gZnJvbSBfX29mX3Ry
YW5zbGF0ZV9hZGRyZXNzKCkKPiBpbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgYWN0dWFsIGFkZHIg
ZnJvbSBkdC4uLgoKSSBkb24ndCB0aGluayB3ZSBuZWVkIHRvIGR1cGxpY2F0ZSBtdWNoLCB3ZSBj
YW4gcHJvYmFibHkgc2FmZWx5CmFzc3VtZSB0aGF0IHRoZXJlIGFyZSBubyBub250cml2aWFsIHJh
bmdlcyBpbiBkZXZpY2VzIGJlbG93IHRoZSBMUEMKbm9kZSwgc28gd2UganVzdCB3YWxrIHVwIHRo
ZSBidXMgdG8gc2VlIGlmIHRoZSBub2RlIGlzIGEgY2hpbGQKKG9yIHBvc3NpYmx5IGdyYW5kY2hp
bGQgZXRjKSBvZiB0aGUgTFBDIGJ1cywgYW5kIHRyZWF0IGFueSBJTyBwb3J0Cm51bWJlciB1bmRl
ciB0aGVyZSBhcyBhIHBoeXNpY2FsIHBvcnQgbnVtYmVyLCB3aGljaCBoYXMgYSBrbm93bgpvZmZz
ZXQgZnJvbSB0aGUgTGludXggSS9PIHBvcnQgbnVtYmVyLgoKPiBJIHRoaW5rIGV4dGVuZGluZyBv
Zl9lbXB0eV9yYW5nZXNfcXVpcmsoKSBtYXkgYmUgYSByZWFzb25hYmxlIHNvbHV0aW9uLgo+IFdo
YXQgZG8geW91IHRoaW5rIEFybmQ/CgpJIGRvbid0IHJlYWxseSBsaWtlIHRoYXQgaWRlYSwgdGhh
dCBxdWlyayBpcyBtZWFudCB0byB3b3JrIGFyb3VuZApicm9rZW4gRFRzLCBidXQgd2UgY2FuIGp1
c3QgbWFrZSB0aGUgRFQgdmFsaWQgYW5kIGltcGxlbWVudCB0aGUKY29kZSBwcm9wZXJseS4KCj4g
VGhlIHNlY29uZCBpc3N1ZSBpcyBhIGNvbmZsaWN0IGJldHdlZW4gY3B1IGFkZHJlc3NlcyB1c2Vk
IGJ5IHRoZSBMUEMKPiBjb250cm9sbGVyIGFuZCBpL28gdG9rZW5zIGZyb20gcGNpIGVuZHBvaW50
cy4KPiAKPiBBYm91dCB0aGlzIHdoYXQgaWYgd2UgbW9kaWZ5IGFybW42NF9leHRpb19vcHMgdG8g
aGF2ZSBhIGxpc3Qgb2YgcmFuZ2VzCj4gcmF0aGVyIHRoYW4gb25seSBvbmUgcmFuZ2UgKG5vdyB3
ZSBoYXZlIGp1c3Qgc3RhcnQvZW5kKTsgdGhlbiBpbiB0aGUKPiBMUEMgZHJpdmVyIHdlIGNhbiBz
Y2FuIHRoZSBMUEMgY2hpbGQgZGV2aWNlcyBhbmQgCj4gMSkgcG9wdWxhdGUgc3VjaCBsaXN0IG9m
IHJhbmdlcwo+IDIpIGNhbGwgcGNpX3JlZ2lzdGVyX2lvX3JhbmdlIGZvciBzdWNoIHJhbmdlcwoK
U2Nhbm5pbmcgdGhlIGNoaWxkIGRldmljZXMgc291bmRzIHJlYWxseSB3cm9uZywgcGxlYXNlIHJl
Z2lzdGVyIGp1c3QKb25lIHJhbmdlIHRoYXQgY292ZXJzIHRoZSBidXMgdG8ga2VlcCB0aGUgd29y
a2Fyb3VuZCBhcyBzaW1wbGUKYXMgcG9zc2libGUuCgo+IFRoZW4gd2hlbiBjYWxsaW5nIF9fb2Zf
YWRkcmVzc190b19yZXNvdXJjZSB3ZSByZXRyaWV2ZSBJL08gdG9rZW5zIAo+IGZvciB0aGUgZGV2
aWNlcyBvbiB0b3Agb2YgdGhlIExQQyBkcml2ZXIgYW5kIGluIHRoZSBJL08gYWNjZXNzb3JzCj4g
d2UgY2FsbCBwY2lfcGlvX3RvX2FkZHJlc3MgdG8gZmlndXJlIG91dCB0aGUgY3B1IGFkZHJlc3Mg
YW5kIGNvbXBhcmUKPiBpdCB0byB0aGUgbGlzdCBvZiByYW5nZXMgaW4gYXJtbjY0X2V4dGlvX29w
cy4KPiAgIAo+IFdoYXQgYWJvdXQgdGhpcz8KClRoYXQgc2VlbXMgcmVhbGx5IGNvbXBsZXggZm9y
IHNvbWV0aGluZyB0aGF0IGNhbiBiZSBxdWl0ZSBzaW1wbGUuClRoZSBvbmx5IHRoaW5nIHdlIG5l
ZWQgdG8gd29ycnkgYWJvdXQgaXMgdGhhdCB0aGUgaW9fcmFuZ2VfbGlzdApjb250YWlucyBhbiBl
bnRyeSBmb3IgdGhlIExQQyBidXMgc28gd2UgZG9uJ3QgY29uZmxpY3Qgd2l0aCB0aGUKUENJIGJ1
c2VzLgoKCUFybmQKCglBcm5kCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVs
QGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9s
aXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-21 20:18                       ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-21 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni wrote:
> > -----Original Message-----
> > From: zhichang [mailto:zhichang.yuan02 at gmail.com]
> > On 2016?09?15? 20:24, Arnd Bergmann wrote:
> > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > wrote:
> > >>> -----Original Message-----
> > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele Paoloni
> > wrote:
> > >> I think that maybe having the 1:1 range mapping doesn't
> > >> reflect well the reality but it is the less painful
> > >> solution...
> > >>
> > >> What's your view?
> > >
> > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > and that should be enough to translate the I/O port number.
> > >
> > > The only part we need to change here is to not go through
> > > the crazy conversion all the way from PCI I/O space to a
> > > physical address and back to a (logical) port number
> > > that we do today with of_translate_address/pci_address_to_pio.
> > >
> > Sorry for the late response! Several days' leave....
> > Do you want to bypass of_translate_address and pci_address_to_pio for
> > the registered specific PIO?
> > I think the bypass for of_translate_address is ok, but worry some new
> > issues will emerge without the
> > conversion between physical address and logical/linux port number.

The same function that handles the non-translated region would
do that conversion.

> > When PCI host bridge which support IO operations is configured and
> > enabled, the pci_address_to_pio will
> > populate the logical IO range from ZERO for the first host bridge. Our
> > LPC will also use part of the IO range
> > started from ZERO. It will make in/out enter the wrong branch possibly.
> > 
> > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use only.
> > But it seems not so good. In this way,
> > PCI has no chance to use low 4K IO range(logical).
> > 
> > So, in V3, applying the conversion from physical/cpu address to
> > logical/linux IO port for any IO ranges,
> > including the LPC, but recorded the logical IO range for LPC. When
> > calling in/out with a logical port address,
> > we can check this port fall into LPC logical IO range and get back the
> > real IO.

Right, and the same translation can be used in __of_address_to_resource()
going the opposite way.

> > Do you have further comments about this??
> 
> I think there are two separate issues to be discussed:
> 
> The first issue is about having of_translate_address failing due to
> "range" missing. About this Arnd suggested that it is not appropriate
> to have a range describing a bridge 1:1 mapping and this was discussed
> before in this thread. Arnd had a suggestion about this (see below) 
> however (looking twice at the code) it seems to me that such solution 
> would lead to quite some duplication from __of_translate_address()
> in order to retrieve the actual addr from dt...

I don't think we need to duplicate much, we can probably safely
assume that there are no nontrivial ranges in devices below the LPC
node, so we just walk up the bus to see if the node is a child
(or possibly grandchild etc) of the LPC bus, and treat any IO port
number under there as a physical port number, which has a known
offset from the Linux I/O port number.

> I think extending of_empty_ranges_quirk() may be a reasonable solution.
> What do you think Arnd?

I don't really like that idea, that quirk is meant to work around
broken DTs, but we can just make the DT valid and implement the
code properly.

> The second issue is a conflict between cpu addresses used by the LPC
> controller and i/o tokens from pci endpoints.
> 
> About this what if we modify armn64_extio_ops to have a list of ranges
> rather than only one range (now we have just start/end); then in the
> LPC driver we can scan the LPC child devices and 
> 1) populate such list of ranges
> 2) call pci_register_io_range for such ranges

Scanning the child devices sounds really wrong, please register just
one range that covers the bus to keep the workaround as simple
as possible.

> Then when calling __of_address_to_resource we retrieve I/O tokens 
> for the devices on top of the LPC driver and in the I/O accessors
> we call pci_pio_to_address to figure out the cpu address and compare
> it to the list of ranges in armn64_extio_ops.
>   
> What about this?

That seems really complex for something that can be quite simple.
The only thing we need to worry about is that the io_range_list
contains an entry for the LPC bus so we don't conflict with the
PCI buses.

	Arnd

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-21 20:18                       ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-22 11:55                         ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 11:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 21 September 2016 21:18
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > From: zhichang [mailto:zhichang.yuan02@gmail.com]
> > > On 2016年09月15日 20:24, Arnd Bergmann wrote:
> > > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > > wrote:
> > > >>> -----Original Message-----
> > > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele
> Paoloni
> > > wrote:
> > > >> I think that maybe having the 1:1 range mapping doesn't
> > > >> reflect well the reality but it is the less painful
> > > >> solution...
> > > >>
> > > >> What's your view?
> > > >
> > > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > > and that should be enough to translate the I/O port number.
> > > >
> > > > The only part we need to change here is to not go through
> > > > the crazy conversion all the way from PCI I/O space to a
> > > > physical address and back to a (logical) port number
> > > > that we do today with of_translate_address/pci_address_to_pio.
> > > >
> > > Sorry for the late response! Several days' leave....
> > > Do you want to bypass of_translate_address and pci_address_to_pio
> for
> > > the registered specific PIO?
> > > I think the bypass for of_translate_address is ok, but worry some
> new
> > > issues will emerge without the
> > > conversion between physical address and logical/linux port number.
> 
> The same function that handles the non-translated region would
> do that conversion.
> 
> > > When PCI host bridge which support IO operations is configured and
> > > enabled, the pci_address_to_pio will
> > > populate the logical IO range from ZERO for the first host bridge.
> Our
> > > LPC will also use part of the IO range
> > > started from ZERO. It will make in/out enter the wrong branch
> possibly.
> > >
> > > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use
> only.
> > > But it seems not so good. In this way,
> > > PCI has no chance to use low 4K IO range(logical).
> > >
> > > So, in V3, applying the conversion from physical/cpu address to
> > > logical/linux IO port for any IO ranges,
> > > including the LPC, but recorded the logical IO range for LPC. When
> > > calling in/out with a logical port address,
> > > we can check this port fall into LPC logical IO range and get back
> the
> > > real IO.
> 
> Right, and the same translation can be used in
> __of_address_to_resource()
> going the opposite way.
> 
> > > Do you have further comments about this??
> >
> > I think there are two separate issues to be discussed:
> >
> > The first issue is about having of_translate_address failing due to
> > "range" missing. About this Arnd suggested that it is not appropriate
> > to have a range describing a bridge 1:1 mapping and this was
> discussed
> > before in this thread. Arnd had a suggestion about this (see below)
> > however (looking twice at the code) it seems to me that such solution
> > would lead to quite some duplication from __of_translate_address()
> > in order to retrieve the actual addr from dt...
> 
> I don't think we need to duplicate much, we can probably safely
> assume that there are no nontrivial ranges in devices below the LPC
> node, so we just walk up the bus to see if the node is a child
> (or possibly grandchild etc) of the LPC bus, and treat any IO port
> number under there as a physical port number, which has a known
> offset from the Linux I/O port number.
> 
> > I think extending of_empty_ranges_quirk() may be a reasonable
> solution.
> > What do you think Arnd?
> 
> I don't really like that idea, that quirk is meant to work around
> broken DTs, but we can just make the DT valid and implement the
> code properly.

Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
As a quirk is used to work around broken HW or broken FW (as in this case)
rather than to fix code

What about the following? I think adding the check you suggested next to
of_empty_ranges_quirk() is adding the case we need in the right point (thus
avoiding any duplication)
 
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
        return NULL;
 }
 
+static inline int of_isa_indirect_io(struct device_node *np)
+{
+       /*
+        * check if the current node is an isa bus and if indirectio operation
+        * are registered
+        */
+       return (of_bus_isa_match(np) && arm64_extio_ops);
+}
+
 static int of_empty_ranges_quirk(struct device_node *np)
 {
        if (IS_ENABLED(CONFIG_PPC)) {
@@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * This code is only enabled on powerpc. --gcl
         */
        ranges = of_get_property(parent, rprop, &rlen);
-       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
+       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
                pr_debug("OF: no ranges; cannot translate\n");
                return 1;
        }


> 
> > The second issue is a conflict between cpu addresses used by the LPC
> > controller and i/o tokens from pci endpoints.
> >
> > About this what if we modify armn64_extio_ops to have a list of
> ranges
> > rather than only one range (now we have just start/end); then in the
> > LPC driver we can scan the LPC child devices and
> > 1) populate such list of ranges
> > 2) call pci_register_io_range for such ranges
> 
> Scanning the child devices sounds really wrong, please register just
> one range that covers the bus to keep the workaround as simple
> as possible.
> 
> > Then when calling __of_address_to_resource we retrieve I/O tokens
> > for the devices on top of the LPC driver and in the I/O accessors
> > we call pci_pio_to_address to figure out the cpu address and compare
> > it to the list of ranges in armn64_extio_ops.
> >
> > What about this?
> 
> That seems really complex for something that can be quite simple.
> The only thing we need to worry about is that the io_range_list
> contains an entry for the LPC bus so we don't conflict with the
> PCI buses.

Thanks

I discussed with Zhichang and we agreed to use only one LPC range
to be registered with pci_register_io_range.

We'll rework the accessors to check if the retrieved I/O tokens
belong to LPC or PCI IO range...

Cheers

Gab


> 
> 	Arnd
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 11:55                         ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 11:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourong

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 21 September 2016 21:18
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > From: zhichang [mailto:zhichang.yuan02@gmail.com]
> > > On 2016年09月15日 20:24, Arnd Bergmann wrote:
> > > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > > wrote:
> > > >>> -----Original Message-----
> > > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele
> Paoloni
> > > wrote:
> > > >> I think that maybe having the 1:1 range mapping doesn't
> > > >> reflect well the reality but it is the less painful
> > > >> solution...
> > > >>
> > > >> What's your view?
> > > >
> > > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > > and that should be enough to translate the I/O port number.
> > > >
> > > > The only part we need to change here is to not go through
> > > > the crazy conversion all the way from PCI I/O space to a
> > > > physical address and back to a (logical) port number
> > > > that we do today with of_translate_address/pci_address_to_pio.
> > > >
> > > Sorry for the late response! Several days' leave....
> > > Do you want to bypass of_translate_address and pci_address_to_pio
> for
> > > the registered specific PIO?
> > > I think the bypass for of_translate_address is ok, but worry some
> new
> > > issues will emerge without the
> > > conversion between physical address and logical/linux port number.
> 
> The same function that handles the non-translated region would
> do that conversion.
> 
> > > When PCI host bridge which support IO operations is configured and
> > > enabled, the pci_address_to_pio will
> > > populate the logical IO range from ZERO for the first host bridge.
> Our
> > > LPC will also use part of the IO range
> > > started from ZERO. It will make in/out enter the wrong branch
> possibly.
> > >
> > > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use
> only.
> > > But it seems not so good. In this way,
> > > PCI has no chance to use low 4K IO range(logical).
> > >
> > > So, in V3, applying the conversion from physical/cpu address to
> > > logical/linux IO port for any IO ranges,
> > > including the LPC, but recorded the logical IO range for LPC. When
> > > calling in/out with a logical port address,
> > > we can check this port fall into LPC logical IO range and get back
> the
> > > real IO.
> 
> Right, and the same translation can be used in
> __of_address_to_resource()
> going the opposite way.
> 
> > > Do you have further comments about this??
> >
> > I think there are two separate issues to be discussed:
> >
> > The first issue is about having of_translate_address failing due to
> > "range" missing. About this Arnd suggested that it is not appropriate
> > to have a range describing a bridge 1:1 mapping and this was
> discussed
> > before in this thread. Arnd had a suggestion about this (see below)
> > however (looking twice at the code) it seems to me that such solution
> > would lead to quite some duplication from __of_translate_address()
> > in order to retrieve the actual addr from dt...
> 
> I don't think we need to duplicate much, we can probably safely
> assume that there are no nontrivial ranges in devices below the LPC
> node, so we just walk up the bus to see if the node is a child
> (or possibly grandchild etc) of the LPC bus, and treat any IO port
> number under there as a physical port number, which has a known
> offset from the Linux I/O port number.
> 
> > I think extending of_empty_ranges_quirk() may be a reasonable
> solution.
> > What do you think Arnd?
> 
> I don't really like that idea, that quirk is meant to work around
> broken DTs, but we can just make the DT valid and implement the
> code properly.

Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
As a quirk is used to work around broken HW or broken FW (as in this case)
rather than to fix code

What about the following? I think adding the check you suggested next to
of_empty_ranges_quirk() is adding the case we need in the right point (thus
avoiding any duplication)
 
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
        return NULL;
 }
 
+static inline int of_isa_indirect_io(struct device_node *np)
+{
+       /*
+        * check if the current node is an isa bus and if indirectio operation
+        * are registered
+        */
+       return (of_bus_isa_match(np) && arm64_extio_ops);
+}
+
 static int of_empty_ranges_quirk(struct device_node *np)
 {
        if (IS_ENABLED(CONFIG_PPC)) {
@@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * This code is only enabled on powerpc. --gcl
         */
        ranges = of_get_property(parent, rprop, &rlen);
-       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
+       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
                pr_debug("OF: no ranges; cannot translate\n");
                return 1;
        }


> 
> > The second issue is a conflict between cpu addresses used by the LPC
> > controller and i/o tokens from pci endpoints.
> >
> > About this what if we modify armn64_extio_ops to have a list of
> ranges
> > rather than only one range (now we have just start/end); then in the
> > LPC driver we can scan the LPC child devices and
> > 1) populate such list of ranges
> > 2) call pci_register_io_range for such ranges
> 
> Scanning the child devices sounds really wrong, please register just
> one range that covers the bus to keep the workaround as simple
> as possible.
> 
> > Then when calling __of_address_to_resource we retrieve I/O tokens
> > for the devices on top of the LPC driver and in the I/O accessors
> > we call pci_pio_to_address to figure out the cpu address and compare
> > it to the list of ranges in armn64_extio_ops.
> >
> > What about this?
> 
> That seems really complex for something that can be quite simple.
> The only thing we need to worry about is that the io_range_list
> contains an entry for the LPC bus so we don't conflict with the
> PCI buses.

Thanks

I discussed with Zhichang and we agreed to use only one LPC range
to be registered with pci_register_io_range.

We'll rework the accessors to check if the retrieved I/O tokens
belong to LPC or PCI IO range...

Cheers

Gab


> 
> 	Arnd
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 11:55                         ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 11:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

SGkgQXJuZA0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IEFybmQgQmVy
Z21hbm4gW21haWx0bzphcm5kQGFybmRiLmRlXQ0KPiBTZW50OiAyMSBTZXB0ZW1iZXIgMjAxNiAy
MToxOA0KPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiBDYzogemhpY2hhbmc7IGxpbnV4LWFybS1r
ZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmc7
IGxvcmVuem8ucGllcmFsaXNpQGFybS5jb207IG1pbnlhcmRAYWNtLm9yZzsNCj4gbGludXgtcGNp
QHZnZXIua2VybmVsLm9yZzsgZ3JlZ2toQGxpbnV4Zm91bmRhdGlvbi5vcmc7IEpvaG4gR2Fycnk7
DQo+IHdpbGwuZGVhY29uQGFybS5jb207IGxpbnV4LWtlcm5lbEB2Z2VyLmtlcm5lbC5vcmc7IFl1
YW56aGljaGFuZzsNCj4gTGludXhhcm07IHh1d2VpIChPKTsgbGludXgtc2VyaWFsQHZnZXIua2Vy
bmVsLm9yZzsNCj4gYmVuaEBrZXJuZWwuY3Jhc2hpbmcub3JnOyB6b3Vyb25ncm9uZ0BnbWFpbC5j
b207IGxpdml1LmR1ZGF1QGFybS5jb207DQo+IGthbnR5emNAMTYzLmNvbQ0KPiBTdWJqZWN0OiBS
ZTogW1BBVENIIFYzIDIvNF0gQVJNNjQgTFBDOiBMUEMgZHJpdmVyIGltcGxlbWVudGF0aW9uIG9u
DQo+IEhpcDA2DQo+IA0KPiBPbiBXZWRuZXNkYXksIFNlcHRlbWJlciAyMSwgMjAxNiA0OjIwOjU1
IFBNIENFU1QgR2FicmllbGUgUGFvbG9uaQ0KPiB3cm90ZToNCj4gPiA+IC0tLS0tT3JpZ2luYWwg
TWVzc2FnZS0tLS0tDQo+ID4gPiBGcm9tOiB6aGljaGFuZyBbbWFpbHRvOnpoaWNoYW5nLnl1YW4w
MkBnbWFpbC5jb21dDQo+ID4gPiBPbiAyMDE25bm0MDnmnIgxNeaXpSAyMDoyNCwgQXJuZCBCZXJn
bWFubiB3cm90ZToNCj4gPiA+ID4gT24gVGh1cnNkYXksIFNlcHRlbWJlciAxNSwgMjAxNiAxMjow
NTo1MSBQTSBDRVNUIEdhYnJpZWxlIFBhb2xvbmkNCj4gPiA+IHdyb3RlOg0KPiA+ID4gPj4+IC0t
LS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiA+Pj4gT24gVGh1cnNkYXksIFNlcHRlbWJl
ciAxNSwgMjAxNiA4OjAyOjI3IEFNIENFU1QgR2FicmllbGUNCj4gUGFvbG9uaQ0KPiA+ID4gd3Jv
dGU6DQo+ID4gPiA+PiBJIHRoaW5rIHRoYXQgbWF5YmUgaGF2aW5nIHRoZSAxOjEgcmFuZ2UgbWFw
cGluZyBkb2Vzbid0DQo+ID4gPiA+PiByZWZsZWN0IHdlbGwgdGhlIHJlYWxpdHkgYnV0IGl0IGlz
IHRoZSBsZXNzIHBhaW5mdWwNCj4gPiA+ID4+IHNvbHV0aW9uLi4uDQo+ID4gPiA+Pg0KPiA+ID4g
Pj4gV2hhdCdzIHlvdXIgdmlldz8NCj4gPiA+ID4NCj4gPiA+ID4gV2UgY2FuIGNoZWNrIHRoZSAn
aScgYml0IGZvciBJL08gc3BhY2UgaW4gb2ZfYnVzX2lzYV9nZXRfZmxhZ3MsDQo+ID4gPiA+IGFu
ZCB0aGF0IHNob3VsZCBiZSBlbm91Z2ggdG8gdHJhbnNsYXRlIHRoZSBJL08gcG9ydCBudW1iZXIu
DQo+ID4gPiA+DQo+ID4gPiA+IFRoZSBvbmx5IHBhcnQgd2UgbmVlZCB0byBjaGFuZ2UgaGVyZSBp
cyB0byBub3QgZ28gdGhyb3VnaA0KPiA+ID4gPiB0aGUgY3JhenkgY29udmVyc2lvbiBhbGwgdGhl
IHdheSBmcm9tIFBDSSBJL08gc3BhY2UgdG8gYQ0KPiA+ID4gPiBwaHlzaWNhbCBhZGRyZXNzIGFu
ZCBiYWNrIHRvIGEgKGxvZ2ljYWwpIHBvcnQgbnVtYmVyDQo+ID4gPiA+IHRoYXQgd2UgZG8gdG9k
YXkgd2l0aCBvZl90cmFuc2xhdGVfYWRkcmVzcy9wY2lfYWRkcmVzc190b19waW8uDQo+ID4gPiA+
DQo+ID4gPiBTb3JyeSBmb3IgdGhlIGxhdGUgcmVzcG9uc2UhIFNldmVyYWwgZGF5cycgbGVhdmUu
Li4uDQo+ID4gPiBEbyB5b3Ugd2FudCB0byBieXBhc3Mgb2ZfdHJhbnNsYXRlX2FkZHJlc3MgYW5k
IHBjaV9hZGRyZXNzX3RvX3Bpbw0KPiBmb3INCj4gPiA+IHRoZSByZWdpc3RlcmVkIHNwZWNpZmlj
IFBJTz8NCj4gPiA+IEkgdGhpbmsgdGhlIGJ5cGFzcyBmb3Igb2ZfdHJhbnNsYXRlX2FkZHJlc3Mg
aXMgb2ssIGJ1dCB3b3JyeSBzb21lDQo+IG5ldw0KPiA+ID4gaXNzdWVzIHdpbGwgZW1lcmdlIHdp
dGhvdXQgdGhlDQo+ID4gPiBjb252ZXJzaW9uIGJldHdlZW4gcGh5c2ljYWwgYWRkcmVzcyBhbmQg
bG9naWNhbC9saW51eCBwb3J0IG51bWJlci4NCj4gDQo+IFRoZSBzYW1lIGZ1bmN0aW9uIHRoYXQg
aGFuZGxlcyB0aGUgbm9uLXRyYW5zbGF0ZWQgcmVnaW9uIHdvdWxkDQo+IGRvIHRoYXQgY29udmVy
c2lvbi4NCj4gDQo+ID4gPiBXaGVuIFBDSSBob3N0IGJyaWRnZSB3aGljaCBzdXBwb3J0IElPIG9w
ZXJhdGlvbnMgaXMgY29uZmlndXJlZCBhbmQNCj4gPiA+IGVuYWJsZWQsIHRoZSBwY2lfYWRkcmVz
c190b19waW8gd2lsbA0KPiA+ID4gcG9wdWxhdGUgdGhlIGxvZ2ljYWwgSU8gcmFuZ2UgZnJvbSBa
RVJPIGZvciB0aGUgZmlyc3QgaG9zdCBicmlkZ2UuDQo+IE91cg0KPiA+ID4gTFBDIHdpbGwgYWxz
byB1c2UgcGFydCBvZiB0aGUgSU8gcmFuZ2UNCj4gPiA+IHN0YXJ0ZWQgZnJvbSBaRVJPLiBJdCB3
aWxsIG1ha2UgaW4vb3V0IGVudGVyIHRoZSB3cm9uZyBicmFuY2gNCj4gcG9zc2libHkuDQo+ID4g
Pg0KPiA+ID4gSW4gVjIsIHRoZSAwIC0gMHgxMDAwIGxvZ2ljYWwgSU8gcmFuZ2UgaXMgcmVzZXJ2
ZWQgZm9yIExQQyB1c2UNCj4gb25seS4NCj4gPiA+IEJ1dCBpdCBzZWVtcyBub3Qgc28gZ29vZC4g
SW4gdGhpcyB3YXksDQo+ID4gPiBQQ0kgaGFzIG5vIGNoYW5jZSB0byB1c2UgbG93IDRLIElPIHJh
bmdlKGxvZ2ljYWwpLg0KPiA+ID4NCj4gPiA+IFNvLCBpbiBWMywgYXBwbHlpbmcgdGhlIGNvbnZl
cnNpb24gZnJvbSBwaHlzaWNhbC9jcHUgYWRkcmVzcyB0bw0KPiA+ID4gbG9naWNhbC9saW51eCBJ
TyBwb3J0IGZvciBhbnkgSU8gcmFuZ2VzLA0KPiA+ID4gaW5jbHVkaW5nIHRoZSBMUEMsIGJ1dCBy
ZWNvcmRlZCB0aGUgbG9naWNhbCBJTyByYW5nZSBmb3IgTFBDLiBXaGVuDQo+ID4gPiBjYWxsaW5n
IGluL291dCB3aXRoIGEgbG9naWNhbCBwb3J0IGFkZHJlc3MsDQo+ID4gPiB3ZSBjYW4gY2hlY2sg
dGhpcyBwb3J0IGZhbGwgaW50byBMUEMgbG9naWNhbCBJTyByYW5nZSBhbmQgZ2V0IGJhY2sNCj4g
dGhlDQo+ID4gPiByZWFsIElPLg0KPiANCj4gUmlnaHQsIGFuZCB0aGUgc2FtZSB0cmFuc2xhdGlv
biBjYW4gYmUgdXNlZCBpbg0KPiBfX29mX2FkZHJlc3NfdG9fcmVzb3VyY2UoKQ0KPiBnb2luZyB0
aGUgb3Bwb3NpdGUgd2F5Lg0KPiANCj4gPiA+IERvIHlvdSBoYXZlIGZ1cnRoZXIgY29tbWVudHMg
YWJvdXQgdGhpcz8/DQo+ID4NCj4gPiBJIHRoaW5rIHRoZXJlIGFyZSB0d28gc2VwYXJhdGUgaXNz
dWVzIHRvIGJlIGRpc2N1c3NlZDoNCj4gPg0KPiA+IFRoZSBmaXJzdCBpc3N1ZSBpcyBhYm91dCBo
YXZpbmcgb2ZfdHJhbnNsYXRlX2FkZHJlc3MgZmFpbGluZyBkdWUgdG8NCj4gPiAicmFuZ2UiIG1p
c3NpbmcuIEFib3V0IHRoaXMgQXJuZCBzdWdnZXN0ZWQgdGhhdCBpdCBpcyBub3QgYXBwcm9wcmlh
dGUNCj4gPiB0byBoYXZlIGEgcmFuZ2UgZGVzY3JpYmluZyBhIGJyaWRnZSAxOjEgbWFwcGluZyBh
bmQgdGhpcyB3YXMNCj4gZGlzY3Vzc2VkDQo+ID4gYmVmb3JlIGluIHRoaXMgdGhyZWFkLiBBcm5k
IGhhZCBhIHN1Z2dlc3Rpb24gYWJvdXQgdGhpcyAoc2VlIGJlbG93KQ0KPiA+IGhvd2V2ZXIgKGxv
b2tpbmcgdHdpY2UgYXQgdGhlIGNvZGUpIGl0IHNlZW1zIHRvIG1lIHRoYXQgc3VjaCBzb2x1dGlv
bg0KPiA+IHdvdWxkIGxlYWQgdG8gcXVpdGUgc29tZSBkdXBsaWNhdGlvbiBmcm9tIF9fb2ZfdHJh
bnNsYXRlX2FkZHJlc3MoKQ0KPiA+IGluIG9yZGVyIHRvIHJldHJpZXZlIHRoZSBhY3R1YWwgYWRk
ciBmcm9tIGR0Li4uDQo+IA0KPiBJIGRvbid0IHRoaW5rIHdlIG5lZWQgdG8gZHVwbGljYXRlIG11
Y2gsIHdlIGNhbiBwcm9iYWJseSBzYWZlbHkNCj4gYXNzdW1lIHRoYXQgdGhlcmUgYXJlIG5vIG5v
bnRyaXZpYWwgcmFuZ2VzIGluIGRldmljZXMgYmVsb3cgdGhlIExQQw0KPiBub2RlLCBzbyB3ZSBq
dXN0IHdhbGsgdXAgdGhlIGJ1cyB0byBzZWUgaWYgdGhlIG5vZGUgaXMgYSBjaGlsZA0KPiAob3Ig
cG9zc2libHkgZ3JhbmRjaGlsZCBldGMpIG9mIHRoZSBMUEMgYnVzLCBhbmQgdHJlYXQgYW55IElP
IHBvcnQNCj4gbnVtYmVyIHVuZGVyIHRoZXJlIGFzIGEgcGh5c2ljYWwgcG9ydCBudW1iZXIsIHdo
aWNoIGhhcyBhIGtub3duDQo+IG9mZnNldCBmcm9tIHRoZSBMaW51eCBJL08gcG9ydCBudW1iZXIu
DQo+IA0KPiA+IEkgdGhpbmsgZXh0ZW5kaW5nIG9mX2VtcHR5X3Jhbmdlc19xdWlyaygpIG1heSBi
ZSBhIHJlYXNvbmFibGUNCj4gc29sdXRpb24uDQo+ID4gV2hhdCBkbyB5b3UgdGhpbmsgQXJuZD8N
Cj4gDQo+IEkgZG9uJ3QgcmVhbGx5IGxpa2UgdGhhdCBpZGVhLCB0aGF0IHF1aXJrIGlzIG1lYW50
IHRvIHdvcmsgYXJvdW5kDQo+IGJyb2tlbiBEVHMsIGJ1dCB3ZSBjYW4ganVzdCBtYWtlIHRoZSBE
VCB2YWxpZCBhbmQgaW1wbGVtZW50IHRoZQ0KPiBjb2RlIHByb3Blcmx5Lg0KDQpPayAgSSB1bmRl
cnN0YW5kIHlvdXIgcG9pbnQgd2hlcmUgaXQgaXMgbm90IHJpZ2h0IHRvIHVzZSBvZl9lbXB0eV9y
YW5nZXNfcXVpcmsoKQ0KQXMgYSBxdWlyayBpcyB1c2VkIHRvIHdvcmsgYXJvdW5kIGJyb2tlbiBI
VyBvciBicm9rZW4gRlcgKGFzIGluIHRoaXMgY2FzZSkNCnJhdGhlciB0aGFuIHRvIGZpeCBjb2Rl
DQoNCldoYXQgYWJvdXQgdGhlIGZvbGxvd2luZz8gSSB0aGluayBhZGRpbmcgdGhlIGNoZWNrIHlv
dSBzdWdnZXN0ZWQgbmV4dCB0bw0Kb2ZfZW1wdHlfcmFuZ2VzX3F1aXJrKCkgaXMgYWRkaW5nIHRo
ZSBjYXNlIHdlIG5lZWQgaW4gdGhlIHJpZ2h0IHBvaW50ICh0aHVzDQphdm9pZGluZyBhbnkgZHVw
bGljYXRpb24pDQogDQotLS0gYS9kcml2ZXJzL29mL2FkZHJlc3MuYw0KKysrIGIvZHJpdmVycy9v
Zi9hZGRyZXNzLmMNCkBAIC00NTcsNiArNDU3LDE1IEBAIHN0YXRpYyBzdHJ1Y3Qgb2ZfYnVzICpv
Zl9tYXRjaF9idXMoc3RydWN0IGRldmljZV9ub2RlICpucCkNCiAgICAgICAgcmV0dXJuIE5VTEw7
DQogfQ0KIA0KK3N0YXRpYyBpbmxpbmUgaW50IG9mX2lzYV9pbmRpcmVjdF9pbyhzdHJ1Y3QgZGV2
aWNlX25vZGUgKm5wKQ0KK3sNCisgICAgICAgLyoNCisgICAgICAgICogY2hlY2sgaWYgdGhlIGN1
cnJlbnQgbm9kZSBpcyBhbiBpc2EgYnVzIGFuZCBpZiBpbmRpcmVjdGlvIG9wZXJhdGlvbg0KKyAg
ICAgICAgKiBhcmUgcmVnaXN0ZXJlZA0KKyAgICAgICAgKi8NCisgICAgICAgcmV0dXJuIChvZl9i
dXNfaXNhX21hdGNoKG5wKSAmJiBhcm02NF9leHRpb19vcHMpOw0KK30NCisNCiBzdGF0aWMgaW50
IG9mX2VtcHR5X3Jhbmdlc19xdWlyayhzdHJ1Y3QgZGV2aWNlX25vZGUgKm5wKQ0KIHsNCiAgICAg
ICAgaWYgKElTX0VOQUJMRUQoQ09ORklHX1BQQykpIHsNCkBAIC01MDMsNyArNTEyLDcgQEAgc3Rh
dGljIGludCBvZl90cmFuc2xhdGVfb25lKHN0cnVjdCBkZXZpY2Vfbm9kZSAqcGFyZW50LCBzdHJ1
Y3Qgb2ZfYnVzICpidXMsDQogICAgICAgICAqIFRoaXMgY29kZSBpcyBvbmx5IGVuYWJsZWQgb24g
cG93ZXJwYy4gLS1nY2wNCiAgICAgICAgICovDQogICAgICAgIHJhbmdlcyA9IG9mX2dldF9wcm9w
ZXJ0eShwYXJlbnQsIHJwcm9wLCAmcmxlbik7DQotICAgICAgIGlmIChyYW5nZXMgPT0gTlVMTCAm
JiAhb2ZfZW1wdHlfcmFuZ2VzX3F1aXJrKHBhcmVudCkpIHsNCisgICAgICAgaWYgKHJhbmdlcyA9
PSBOVUxMICYmICFvZl9lbXB0eV9yYW5nZXNfcXVpcmsocGFyZW50KSAmJiAhb2ZfaXNhX2luZGly
ZWN0X2lvKHBhcmVudCkpIHsNCiAgICAgICAgICAgICAgICBwcl9kZWJ1ZygiT0Y6IG5vIHJhbmdl
czsgY2Fubm90IHRyYW5zbGF0ZVxuIik7DQogICAgICAgICAgICAgICAgcmV0dXJuIDE7DQogICAg
ICAgIH0NCg0KDQo+IA0KPiA+IFRoZSBzZWNvbmQgaXNzdWUgaXMgYSBjb25mbGljdCBiZXR3ZWVu
IGNwdSBhZGRyZXNzZXMgdXNlZCBieSB0aGUgTFBDDQo+ID4gY29udHJvbGxlciBhbmQgaS9vIHRv
a2VucyBmcm9tIHBjaSBlbmRwb2ludHMuDQo+ID4NCj4gPiBBYm91dCB0aGlzIHdoYXQgaWYgd2Ug
bW9kaWZ5IGFybW42NF9leHRpb19vcHMgdG8gaGF2ZSBhIGxpc3Qgb2YNCj4gcmFuZ2VzDQo+ID4g
cmF0aGVyIHRoYW4gb25seSBvbmUgcmFuZ2UgKG5vdyB3ZSBoYXZlIGp1c3Qgc3RhcnQvZW5kKTsg
dGhlbiBpbiB0aGUNCj4gPiBMUEMgZHJpdmVyIHdlIGNhbiBzY2FuIHRoZSBMUEMgY2hpbGQgZGV2
aWNlcyBhbmQNCj4gPiAxKSBwb3B1bGF0ZSBzdWNoIGxpc3Qgb2YgcmFuZ2VzDQo+ID4gMikgY2Fs
bCBwY2lfcmVnaXN0ZXJfaW9fcmFuZ2UgZm9yIHN1Y2ggcmFuZ2VzDQo+IA0KPiBTY2FubmluZyB0
aGUgY2hpbGQgZGV2aWNlcyBzb3VuZHMgcmVhbGx5IHdyb25nLCBwbGVhc2UgcmVnaXN0ZXIganVz
dA0KPiBvbmUgcmFuZ2UgdGhhdCBjb3ZlcnMgdGhlIGJ1cyB0byBrZWVwIHRoZSB3b3JrYXJvdW5k
IGFzIHNpbXBsZQ0KPiBhcyBwb3NzaWJsZS4NCj4gDQo+ID4gVGhlbiB3aGVuIGNhbGxpbmcgX19v
Zl9hZGRyZXNzX3RvX3Jlc291cmNlIHdlIHJldHJpZXZlIEkvTyB0b2tlbnMNCj4gPiBmb3IgdGhl
IGRldmljZXMgb24gdG9wIG9mIHRoZSBMUEMgZHJpdmVyIGFuZCBpbiB0aGUgSS9PIGFjY2Vzc29y
cw0KPiA+IHdlIGNhbGwgcGNpX3Bpb190b19hZGRyZXNzIHRvIGZpZ3VyZSBvdXQgdGhlIGNwdSBh
ZGRyZXNzIGFuZCBjb21wYXJlDQo+ID4gaXQgdG8gdGhlIGxpc3Qgb2YgcmFuZ2VzIGluIGFybW42
NF9leHRpb19vcHMuDQo+ID4NCj4gPiBXaGF0IGFib3V0IHRoaXM/DQo+IA0KPiBUaGF0IHNlZW1z
IHJlYWxseSBjb21wbGV4IGZvciBzb21ldGhpbmcgdGhhdCBjYW4gYmUgcXVpdGUgc2ltcGxlLg0K
PiBUaGUgb25seSB0aGluZyB3ZSBuZWVkIHRvIHdvcnJ5IGFib3V0IGlzIHRoYXQgdGhlIGlvX3Jh
bmdlX2xpc3QNCj4gY29udGFpbnMgYW4gZW50cnkgZm9yIHRoZSBMUEMgYnVzIHNvIHdlIGRvbid0
IGNvbmZsaWN0IHdpdGggdGhlDQo+IFBDSSBidXNlcy4NCg0KVGhhbmtzDQoNCkkgZGlzY3Vzc2Vk
IHdpdGggWmhpY2hhbmcgYW5kIHdlIGFncmVlZCB0byB1c2Ugb25seSBvbmUgTFBDIHJhbmdlDQp0
byBiZSByZWdpc3RlcmVkIHdpdGggcGNpX3JlZ2lzdGVyX2lvX3JhbmdlLg0KDQpXZSdsbCByZXdv
cmsgdGhlIGFjY2Vzc29ycyB0byBjaGVjayBpZiB0aGUgcmV0cmlldmVkIEkvTyB0b2tlbnMNCmJl
bG9uZyB0byBMUEMgb3IgUENJIElPIHJhbmdlLi4uDQoNCkNoZWVycw0KDQpHYWINCg0KDQo+IA0K
PiAJQXJuZA0KPiANCj4gCUFybmQNCg==

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 11:55                         ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 21 September 2016 21:18
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, September 21, 2016 4:20:55 PM CEST Gabriele Paoloni
> wrote:
> > > -----Original Message-----
> > > From: zhichang [mailto:zhichang.yuan02 at gmail.com]
> > > On 2016?09?15? 20:24, Arnd Bergmann wrote:
> > > > On Thursday, September 15, 2016 12:05:51 PM CEST Gabriele Paoloni
> > > wrote:
> > > >>> -----Original Message-----
> > > >>> On Thursday, September 15, 2016 8:02:27 AM CEST Gabriele
> Paoloni
> > > wrote:
> > > >> I think that maybe having the 1:1 range mapping doesn't
> > > >> reflect well the reality but it is the less painful
> > > >> solution...
> > > >>
> > > >> What's your view?
> > > >
> > > > We can check the 'i' bit for I/O space in of_bus_isa_get_flags,
> > > > and that should be enough to translate the I/O port number.
> > > >
> > > > The only part we need to change here is to not go through
> > > > the crazy conversion all the way from PCI I/O space to a
> > > > physical address and back to a (logical) port number
> > > > that we do today with of_translate_address/pci_address_to_pio.
> > > >
> > > Sorry for the late response! Several days' leave....
> > > Do you want to bypass of_translate_address and pci_address_to_pio
> for
> > > the registered specific PIO?
> > > I think the bypass for of_translate_address is ok, but worry some
> new
> > > issues will emerge without the
> > > conversion between physical address and logical/linux port number.
> 
> The same function that handles the non-translated region would
> do that conversion.
> 
> > > When PCI host bridge which support IO operations is configured and
> > > enabled, the pci_address_to_pio will
> > > populate the logical IO range from ZERO for the first host bridge.
> Our
> > > LPC will also use part of the IO range
> > > started from ZERO. It will make in/out enter the wrong branch
> possibly.
> > >
> > > In V2, the 0 - 0x1000 logical IO range is reserved for LPC use
> only.
> > > But it seems not so good. In this way,
> > > PCI has no chance to use low 4K IO range(logical).
> > >
> > > So, in V3, applying the conversion from physical/cpu address to
> > > logical/linux IO port for any IO ranges,
> > > including the LPC, but recorded the logical IO range for LPC. When
> > > calling in/out with a logical port address,
> > > we can check this port fall into LPC logical IO range and get back
> the
> > > real IO.
> 
> Right, and the same translation can be used in
> __of_address_to_resource()
> going the opposite way.
> 
> > > Do you have further comments about this??
> >
> > I think there are two separate issues to be discussed:
> >
> > The first issue is about having of_translate_address failing due to
> > "range" missing. About this Arnd suggested that it is not appropriate
> > to have a range describing a bridge 1:1 mapping and this was
> discussed
> > before in this thread. Arnd had a suggestion about this (see below)
> > however (looking twice at the code) it seems to me that such solution
> > would lead to quite some duplication from __of_translate_address()
> > in order to retrieve the actual addr from dt...
> 
> I don't think we need to duplicate much, we can probably safely
> assume that there are no nontrivial ranges in devices below the LPC
> node, so we just walk up the bus to see if the node is a child
> (or possibly grandchild etc) of the LPC bus, and treat any IO port
> number under there as a physical port number, which has a known
> offset from the Linux I/O port number.
> 
> > I think extending of_empty_ranges_quirk() may be a reasonable
> solution.
> > What do you think Arnd?
> 
> I don't really like that idea, that quirk is meant to work around
> broken DTs, but we can just make the DT valid and implement the
> code properly.

Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
As a quirk is used to work around broken HW or broken FW (as in this case)
rather than to fix code

What about the following? I think adding the check you suggested next to
of_empty_ranges_quirk() is adding the case we need in the right point (thus
avoiding any duplication)
 
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
        return NULL;
 }
 
+static inline int of_isa_indirect_io(struct device_node *np)
+{
+       /*
+        * check if the current node is an isa bus and if indirectio operation
+        * are registered
+        */
+       return (of_bus_isa_match(np) && arm64_extio_ops);
+}
+
 static int of_empty_ranges_quirk(struct device_node *np)
 {
        if (IS_ENABLED(CONFIG_PPC)) {
@@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * This code is only enabled on powerpc. --gcl
         */
        ranges = of_get_property(parent, rprop, &rlen);
-       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
+       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
                pr_debug("OF: no ranges; cannot translate\n");
                return 1;
        }


> 
> > The second issue is a conflict between cpu addresses used by the LPC
> > controller and i/o tokens from pci endpoints.
> >
> > About this what if we modify armn64_extio_ops to have a list of
> ranges
> > rather than only one range (now we have just start/end); then in the
> > LPC driver we can scan the LPC child devices and
> > 1) populate such list of ranges
> > 2) call pci_register_io_range for such ranges
> 
> Scanning the child devices sounds really wrong, please register just
> one range that covers the bus to keep the workaround as simple
> as possible.
> 
> > Then when calling __of_address_to_resource we retrieve I/O tokens
> > for the devices on top of the LPC driver and in the I/O accessors
> > we call pci_pio_to_address to figure out the cpu address and compare
> > it to the list of ranges in armn64_extio_ops.
> >
> > What about this?
> 
> That seems really complex for something that can be quite simple.
> The only thing we need to worry about is that the io_range_list
> contains an entry for the LPC bus so we don't conflict with the
> PCI buses.

Thanks

I discussed with Zhichang and we agreed to use only one LPC range
to be registered with pci_register_io_range.

We'll rework the accessors to check if the retrieved I/O tokens
belong to LPC or PCI IO range...

Cheers

Gab


> 
> 	Arnd
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-22 11:55                         ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-22 12:14                           ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 12:14 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
> > > I think extending of_empty_ranges_quirk() may be a reasonable
> > solution.
> > > What do you think Arnd?
> > 
> > I don't really like that idea, that quirk is meant to work around
> > broken DTs, but we can just make the DT valid and implement the
> > code properly.
> 
> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
> As a quirk is used to work around broken HW or broken FW (as in this case)
> rather than to fix code
> 
> What about the following? I think adding the check you suggested next to
> of_empty_ranges_quirk() is adding the case we need in the right point (thus
> avoiding any duplication)
>  
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>         return NULL;
>  }
>  
> +static inline int of_isa_indirect_io(struct device_node *np)
> +{
> +       /*
> +        * check if the current node is an isa bus and if indirectio operation
> +        * are registered
> +        */
> +       return (of_bus_isa_match(np) && arm64_extio_ops);
> +}
> +
>  static int of_empty_ranges_quirk(struct device_node *np)
>  {
>         if (IS_ENABLED(CONFIG_PPC)) {
> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>          * This code is only enabled on powerpc. --gcl
>          */
>         ranges = of_get_property(parent, rprop, &rlen);
> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>                 pr_debug("OF: no ranges; cannot translate\n");
>                 return 1;
>         }

I don't see what effect that would have. What do you want to
achieve with this?

I think all we need from this function is to return '1' if
we hit an ISA I/O window, and that should happen for the two
interesting cases, either no 'ranges' at all, or no translation
for the range in question, so that __of_translate_address can
return OF_BAD_ADDR, and we can enter the special case
handling in the caller, that handles it like

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..a18d96843fae 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
 	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
 		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 (taddr == OF_BAD_ADDR)
+			port = arch_of_address_to_pio(dev, addrp)
+		else
+			port = pci_address_to_pio(taddr);
+
 		if (port == (unsigned long)-1)
 			return -EINVAL;
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
+		if (taddr == OF_BAD_ADDR)
+			return -EINVAL;
+
 		r->start = taddr;
 		r->end = taddr + size - 1;
 	}



	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 12:14                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 12:14 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourong

On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
> > > I think extending of_empty_ranges_quirk() may be a reasonable
> > solution.
> > > What do you think Arnd?
> > 
> > I don't really like that idea, that quirk is meant to work around
> > broken DTs, but we can just make the DT valid and implement the
> > code properly.
> 
> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
> As a quirk is used to work around broken HW or broken FW (as in this case)
> rather than to fix code
> 
> What about the following? I think adding the check you suggested next to
> of_empty_ranges_quirk() is adding the case we need in the right point (thus
> avoiding any duplication)
>  
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>         return NULL;
>  }
>  
> +static inline int of_isa_indirect_io(struct device_node *np)
> +{
> +       /*
> +        * check if the current node is an isa bus and if indirectio operation
> +        * are registered
> +        */
> +       return (of_bus_isa_match(np) && arm64_extio_ops);
> +}
> +
>  static int of_empty_ranges_quirk(struct device_node *np)
>  {
>         if (IS_ENABLED(CONFIG_PPC)) {
> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>          * This code is only enabled on powerpc. --gcl
>          */
>         ranges = of_get_property(parent, rprop, &rlen);
> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>                 pr_debug("OF: no ranges; cannot translate\n");
>                 return 1;
>         }

I don't see what effect that would have. What do you want to
achieve with this?

I think all we need from this function is to return '1' if
we hit an ISA I/O window, and that should happen for the two
interesting cases, either no 'ranges' at all, or no translation
for the range in question, so that __of_translate_address can
return OF_BAD_ADDR, and we can enter the special case
handling in the caller, that handles it like

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..a18d96843fae 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
 	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
 		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 (taddr == OF_BAD_ADDR)
+			port = arch_of_address_to_pio(dev, addrp)
+		else
+			port = pci_address_to_pio(taddr);
+
 		if (port == (unsigned long)-1)
 			return -EINVAL;
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
+		if (taddr == OF_BAD_ADDR)
+			return -EINVAL;
+
 		r->start = taddr;
 		r->end = taddr + size - 1;
 	}



	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 12:14                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 12:14 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, linux-pci,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, zhichang, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel

On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
> > > I think extending of_empty_ranges_quirk() may be a reasonable
> > solution.
> > > What do you think Arnd?
> > 
> > I don't really like that idea, that quirk is meant to work around
> > broken DTs, but we can just make the DT valid and implement the
> > code properly.
> 
> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
> As a quirk is used to work around broken HW or broken FW (as in this case)
> rather than to fix code
> 
> What about the following? I think adding the check you suggested next to
> of_empty_ranges_quirk() is adding the case we need in the right point (thus
> avoiding any duplication)
>  
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>         return NULL;
>  }
>  
> +static inline int of_isa_indirect_io(struct device_node *np)
> +{
> +       /*
> +        * check if the current node is an isa bus and if indirectio operation
> +        * are registered
> +        */
> +       return (of_bus_isa_match(np) && arm64_extio_ops);
> +}
> +
>  static int of_empty_ranges_quirk(struct device_node *np)
>  {
>         if (IS_ENABLED(CONFIG_PPC)) {
> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>          * This code is only enabled on powerpc. --gcl
>          */
>         ranges = of_get_property(parent, rprop, &rlen);
> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>                 pr_debug("OF: no ranges; cannot translate\n");
>                 return 1;
>         }

I don't see what effect that would have. What do you want to
achieve with this?

I think all we need from this function is to return '1' if
we hit an ISA I/O window, and that should happen for the two
interesting cases, either no 'ranges' at all, or no translation
for the range in question, so that __of_translate_address can
return OF_BAD_ADDR, and we can enter the special case
handling in the caller, that handles it like

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..a18d96843fae 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
 	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
 		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 (taddr == OF_BAD_ADDR)
+			port = arch_of_address_to_pio(dev, addrp)
+		else
+			port = pci_address_to_pio(taddr);
+
 		if (port == (unsigned long)-1)
 			return -EINVAL;
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
+		if (taddr == OF_BAD_ADDR)
+			return -EINVAL;
+
 		r->start = taddr;
 		r->end = taddr + size - 1;
 	}



	Arnd

_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 12:14                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
> > > I think extending of_empty_ranges_quirk() may be a reasonable
> > solution.
> > > What do you think Arnd?
> > 
> > I don't really like that idea, that quirk is meant to work around
> > broken DTs, but we can just make the DT valid and implement the
> > code properly.
> 
> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
> As a quirk is used to work around broken HW or broken FW (as in this case)
> rather than to fix code
> 
> What about the following? I think adding the check you suggested next to
> of_empty_ranges_quirk() is adding the case we need in the right point (thus
> avoiding any duplication)
>  
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>         return NULL;
>  }
>  
> +static inline int of_isa_indirect_io(struct device_node *np)
> +{
> +       /*
> +        * check if the current node is an isa bus and if indirectio operation
> +        * are registered
> +        */
> +       return (of_bus_isa_match(np) && arm64_extio_ops);
> +}
> +
>  static int of_empty_ranges_quirk(struct device_node *np)
>  {
>         if (IS_ENABLED(CONFIG_PPC)) {
> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>          * This code is only enabled on powerpc. --gcl
>          */
>         ranges = of_get_property(parent, rprop, &rlen);
> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>                 pr_debug("OF: no ranges; cannot translate\n");
>                 return 1;
>         }

I don't see what effect that would have. What do you want to
achieve with this?

I think all we need from this function is to return '1' if
we hit an ISA I/O window, and that should happen for the two
interesting cases, either no 'ranges' at all, or no translation
for the range in question, so that __of_translate_address can
return OF_BAD_ADDR, and we can enter the special case
handling in the caller, that handles it like

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..a18d96843fae 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
 	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
 		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 (taddr == OF_BAD_ADDR)
+			port = arch_of_address_to_pio(dev, addrp)
+		else
+			port = pci_address_to_pio(taddr);
+
 		if (port == (unsigned long)-1)
 			return -EINVAL;
 		r->start = port;
 		r->end = port + size - 1;
 	} else {
+		if (taddr == OF_BAD_ADDR)
+			return -EINVAL;
+
 		r->start = taddr;
 		r->end = taddr + size - 1;
 	}



	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-22 12:14                           ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-22 14:47                             ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 14:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 22 September 2016 13:15
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni
> wrote:
> > > > I think extending of_empty_ranges_quirk() may be a reasonable
> > > solution.
> > > > What do you think Arnd?
> > >
> > > I don't really like that idea, that quirk is meant to work around
> > > broken DTs, but we can just make the DT valid and implement the
> > > code properly.
> >
> > Ok  I understand your point where it is not right to use
> of_empty_ranges_quirk()
> > As a quirk is used to work around broken HW or broken FW (as in this
> case)
> > rather than to fix code
> >
> > What about the following? I think adding the check you suggested next
> to
> > of_empty_ranges_quirk() is adding the case we need in the right point
> (thus
> > avoiding any duplication)
> >
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct
> device_node *np)
> >         return NULL;
> >  }
> >
> > +static inline int of_isa_indirect_io(struct device_node *np)
> > +{
> > +       /*
> > +        * check if the current node is an isa bus and if indirectio
> operation
> > +        * are registered
> > +        */
> > +       return (of_bus_isa_match(np) && arm64_extio_ops);
> > +}
> > +
> >  static int of_empty_ranges_quirk(struct device_node *np)
> >  {
> >         if (IS_ENABLED(CONFIG_PPC)) {
> > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
> >          * This code is only enabled on powerpc. --gcl
> >          */
> >         ranges = of_get_property(parent, rprop, &rlen);
> > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> !of_isa_indirect_io(parent)) {
> >                 pr_debug("OF: no ranges; cannot translate\n");
> >                 return 1;
> >         }
> 
> I don't see what effect that would have. What do you want to
> achieve with this?

If I read the code correctly adding the function above would end
up in a 1:1 mapping:
http://lxr.free-electrons.com/source/drivers/of/address.c#L513

so taddr will be assigned with the cpu address space specified
in the children nodes of LPC and we are not using a quirk function
(we are just checking that we have the indirect io assigned and
that we are on a ISA bus). Now probably there is a nit in my 
code sketch where of_isa_indirect_io should be probably an architecture
specific function...

> 
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
> 

I don't think this is very right as you may fail for different
reasons other than a missing range property, e.g:
http://lxr.free-electrons.com/source/drivers/of/address.c#L575

And even if the only failure case was a missing range if in the
future __of_translate_address had to be reworked we would again
make a wrong assumption...you get my point?

Thanks

Gab

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct
> device_node *dev,
>  	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>  		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
>  		r->start = port;
>  		r->end = port + size - 1;
>  	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>  		r->start = taddr;
>  		r->end = taddr + size - 1;
>  	}
> 
> 
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 14:47                             ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 14:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourong

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 22 September 2016 13:15
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni
> wrote:
> > > > I think extending of_empty_ranges_quirk() may be a reasonable
> > > solution.
> > > > What do you think Arnd?
> > >
> > > I don't really like that idea, that quirk is meant to work around
> > > broken DTs, but we can just make the DT valid and implement the
> > > code properly.
> >
> > Ok  I understand your point where it is not right to use
> of_empty_ranges_quirk()
> > As a quirk is used to work around broken HW or broken FW (as in this
> case)
> > rather than to fix code
> >
> > What about the following? I think adding the check you suggested next
> to
> > of_empty_ranges_quirk() is adding the case we need in the right point
> (thus
> > avoiding any duplication)
> >
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct
> device_node *np)
> >         return NULL;
> >  }
> >
> > +static inline int of_isa_indirect_io(struct device_node *np)
> > +{
> > +       /*
> > +        * check if the current node is an isa bus and if indirectio
> operation
> > +        * are registered
> > +        */
> > +       return (of_bus_isa_match(np) && arm64_extio_ops);
> > +}
> > +
> >  static int of_empty_ranges_quirk(struct device_node *np)
> >  {
> >         if (IS_ENABLED(CONFIG_PPC)) {
> > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
> >          * This code is only enabled on powerpc. --gcl
> >          */
> >         ranges = of_get_property(parent, rprop, &rlen);
> > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> !of_isa_indirect_io(parent)) {
> >                 pr_debug("OF: no ranges; cannot translate\n");
> >                 return 1;
> >         }
> 
> I don't see what effect that would have. What do you want to
> achieve with this?

If I read the code correctly adding the function above would end
up in a 1:1 mapping:
http://lxr.free-electrons.com/source/drivers/of/address.c#L513

so taddr will be assigned with the cpu address space specified
in the children nodes of LPC and we are not using a quirk function
(we are just checking that we have the indirect io assigned and
that we are on a ISA bus). Now probably there is a nit in my 
code sketch where of_isa_indirect_io should be probably an architecture
specific function...

> 
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
> 

I don't think this is very right as you may fail for different
reasons other than a missing range property, e.g:
http://lxr.free-electrons.com/source/drivers/of/address.c#L575

And even if the only failure case was a missing range if in the
future __of_translate_address had to be reworked we would again
make a wrong assumption...you get my point?

Thanks

Gab

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct
> device_node *dev,
>  	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>  		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
>  		r->start = port;
>  		r->end = port + size - 1;
>  	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>  		r->start = taddr;
>  		r->end = taddr + size - 1;
>  	}
> 
> 
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 14:47                             ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 14:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 22 September 2016 13:15
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni
> wrote:
> > > > I think extending of_empty_ranges_quirk() may be a reasonable
> > > solution.
> > > > What do you think Arnd?
> > >
> > > I don't really like that idea, that quirk is meant to work around
> > > broken DTs, but we can just make the DT valid and implement the
> > > code properly.
> >
> > Ok  I understand your point where it is not right to use
> of_empty_ranges_quirk()
> > As a quirk is used to work around broken HW or broken FW (as in this
> case)
> > rather than to fix code
> >
> > What about the following? I think adding the check you suggested next
> to
> > of_empty_ranges_quirk() is adding the case we need in the right point
> (thus
> > avoiding any duplication)
> >
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct
> device_node *np)
> >         return NULL;
> >  }
> >
> > +static inline int of_isa_indirect_io(struct device_node *np)
> > +{
> > +       /*
> > +        * check if the current node is an isa bus and if indirectio
> operation
> > +        * are registered
> > +        */
> > +       return (of_bus_isa_match(np) && arm64_extio_ops);
> > +}
> > +
> >  static int of_empty_ranges_quirk(struct device_node *np)
> >  {
> >         if (IS_ENABLED(CONFIG_PPC)) {
> > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
> >          * This code is only enabled on powerpc. --gcl
> >          */
> >         ranges = of_get_property(parent, rprop, &rlen);
> > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> !of_isa_indirect_io(parent)) {
> >                 pr_debug("OF: no ranges; cannot translate\n");
> >                 return 1;
> >         }
> 
> I don't see what effect that would have. What do you want to
> achieve with this?

If I read the code correctly adding the function above would end
up in a 1:1 mapping:
http://lxr.free-electrons.com/source/drivers/of/address.c#L513

so taddr will be assigned with the cpu address space specified
in the children nodes of LPC and we are not using a quirk function
(we are just checking that we have the indirect io assigned and
that we are on a ISA bus). Now probably there is a nit in my 
code sketch where of_isa_indirect_io should be probably an architecture
specific function...

> 
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
> 

I don't think this is very right as you may fail for different
reasons other than a missing range property, e.g:
http://lxr.free-electrons.com/source/drivers/of/address.c#L575

And even if the only failure case was a missing range if in the
future __of_translate_address had to be reworked we would again
make a wrong assumption...you get my point?

Thanks

Gab

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct
> device_node *dev,
>  	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>  		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
>  		r->start = port;
>  		r->end = port + size - 1;
>  	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>  		r->start = taddr;
>  		r->end = taddr + size - 1;
>  	}
> 
> 
> 
> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 14:47                             ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 22 September 2016 13:15
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni
> wrote:
> > > > I think extending of_empty_ranges_quirk() may be a reasonable
> > > solution.
> > > > What do you think Arnd?
> > >
> > > I don't really like that idea, that quirk is meant to work around
> > > broken DTs, but we can just make the DT valid and implement the
> > > code properly.
> >
> > Ok  I understand your point where it is not right to use
> of_empty_ranges_quirk()
> > As a quirk is used to work around broken HW or broken FW (as in this
> case)
> > rather than to fix code
> >
> > What about the following? I think adding the check you suggested next
> to
> > of_empty_ranges_quirk() is adding the case we need in the right point
> (thus
> > avoiding any duplication)
> >
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct
> device_node *np)
> >         return NULL;
> >  }
> >
> > +static inline int of_isa_indirect_io(struct device_node *np)
> > +{
> > +       /*
> > +        * check if the current node is an isa bus and if indirectio
> operation
> > +        * are registered
> > +        */
> > +       return (of_bus_isa_match(np) && arm64_extio_ops);
> > +}
> > +
> >  static int of_empty_ranges_quirk(struct device_node *np)
> >  {
> >         if (IS_ENABLED(CONFIG_PPC)) {
> > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
> >          * This code is only enabled on powerpc. --gcl
> >          */
> >         ranges = of_get_property(parent, rprop, &rlen);
> > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> !of_isa_indirect_io(parent)) {
> >                 pr_debug("OF: no ranges; cannot translate\n");
> >                 return 1;
> >         }
> 
> I don't see what effect that would have. What do you want to
> achieve with this?

If I read the code correctly adding the function above would end
up in a 1:1 mapping:
http://lxr.free-electrons.com/source/drivers/of/address.c#L513

so taddr will be assigned with the cpu address space specified
in the children nodes of LPC and we are not using a quirk function
(we are just checking that we have the indirect io assigned and
that we are on a ISA bus). Now probably there is a nit in my 
code sketch where of_isa_indirect_io should be probably an architecture
specific function...

> 
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
> 

I don't think this is very right as you may fail for different
reasons other than a missing range property, e.g:
http://lxr.free-electrons.com/source/drivers/of/address.c#L575

And even if the only failure case was a missing range if in the
future __of_translate_address had to be reworked we would again
make a wrong assumption...you get my point?

Thanks

Gab

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct
> device_node *dev,
>  	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>  		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
>  		r->start = port;
>  		r->end = port + size - 1;
>  	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>  		r->start = taddr;
>  		r->end = taddr + size - 1;
>  	}
> 
> 
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-22 14:47                             ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-22 14:59                               ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 14:59 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > >  static int of_empty_ranges_quirk(struct device_node *np)
> > >  {
> > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> > *parent, struct of_bus *bus,
> > >          * This code is only enabled on powerpc. --gcl
> > >          */
> > >         ranges = of_get_property(parent, rprop, &rlen);
> > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > !of_isa_indirect_io(parent)) {
> > >                 pr_debug("OF: no ranges; cannot translate\n");
> > >                 return 1;
> > >         }
> > 
> > I don't see what effect that would have. What do you want to
> > achieve with this?
> 
> If I read the code correctly adding the function above would end
> up in a 1:1 mapping:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> 
> so taddr will be assigned with the cpu address space specified
> in the children nodes of LPC and we are not using a quirk function
> (we are just checking that we have the indirect io assigned and
> that we are on a ISA bus). Now probably there is a nit in my 
> code sketch where of_isa_indirect_io should be probably an architecture
> specific function...

But the point is that it would then return an incorrect address,
which in the worst case could be the same as another I/O space
if that happens to be at CPU address zero.

> > I think all we need from this function is to return '1' if
> > we hit an ISA I/O window, and that should happen for the two
> > interesting cases, either no 'ranges' at all, or no translation
> > for the range in question, so that __of_translate_address can
> > return OF_BAD_ADDR, and we can enter the special case
> > handling in the caller, that handles it like
> > 
> 
> I don't think this is very right as you may fail for different
> reasons other than a missing range property, e.g:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> 
> And even if the only failure case was a missing range if in the
> future __of_translate_address had to be reworked we would again
> make a wrong assumption...you get my point?

The newly introduced function would clearly have to make
some sanity checks. The idea is that treat the case of
not being able to translate a bus specific I/O address
into a CPU address literally and fall back to another method
of translating that address.

This matches my mental model of how we find the resource:

- start with the bus address
- try to translate that into a CPU address
- if we arrive at a CPU physical address for IORESOURCE_MEM, use that
- if we arrive at a CPU physical address for IORESOURCE_IO, translate
  that into a Linux IORESOURCE_IO token
- if there is no valid CPU physical address, try to translate
  the address into an IORESOURCE_IO using the ISA accessor
- if that fails too, give up.

If you try to fake a CPU physical address inbetween, it just
gets more confusing.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 14:59                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 14:59 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourong

On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > >  static int of_empty_ranges_quirk(struct device_node *np)
> > >  {
> > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> > *parent, struct of_bus *bus,
> > >          * This code is only enabled on powerpc. --gcl
> > >          */
> > >         ranges = of_get_property(parent, rprop, &rlen);
> > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > !of_isa_indirect_io(parent)) {
> > >                 pr_debug("OF: no ranges; cannot translate\n");
> > >                 return 1;
> > >         }
> > 
> > I don't see what effect that would have. What do you want to
> > achieve with this?
> 
> If I read the code correctly adding the function above would end
> up in a 1:1 mapping:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> 
> so taddr will be assigned with the cpu address space specified
> in the children nodes of LPC and we are not using a quirk function
> (we are just checking that we have the indirect io assigned and
> that we are on a ISA bus). Now probably there is a nit in my 
> code sketch where of_isa_indirect_io should be probably an architecture
> specific function...

But the point is that it would then return an incorrect address,
which in the worst case could be the same as another I/O space
if that happens to be at CPU address zero.

> > I think all we need from this function is to return '1' if
> > we hit an ISA I/O window, and that should happen for the two
> > interesting cases, either no 'ranges' at all, or no translation
> > for the range in question, so that __of_translate_address can
> > return OF_BAD_ADDR, and we can enter the special case
> > handling in the caller, that handles it like
> > 
> 
> I don't think this is very right as you may fail for different
> reasons other than a missing range property, e.g:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> 
> And even if the only failure case was a missing range if in the
> future __of_translate_address had to be reworked we would again
> make a wrong assumption...you get my point?

The newly introduced function would clearly have to make
some sanity checks. The idea is that treat the case of
not being able to translate a bus specific I/O address
into a CPU address literally and fall back to another method
of translating that address.

This matches my mental model of how we find the resource:

- start with the bus address
- try to translate that into a CPU address
- if we arrive at a CPU physical address for IORESOURCE_MEM, use that
- if we arrive at a CPU physical address for IORESOURCE_IO, translate
  that into a Linux IORESOURCE_IO token
- if there is no valid CPU physical address, try to translate
  the address into an IORESOURCE_IO using the ISA accessor
- if that fails too, give up.

If you try to fake a CPU physical address inbetween, it just
gets more confusing.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 14:59                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 14:59 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > >  static int of_empty_ranges_quirk(struct device_node *np)
> > >  {
> > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> > *parent, struct of_bus *bus,
> > >          * This code is only enabled on powerpc. --gcl
> > >          */
> > >         ranges = of_get_property(parent, rprop, &rlen);
> > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > !of_isa_indirect_io(parent)) {
> > >                 pr_debug("OF: no ranges; cannot translate\n");
> > >                 return 1;
> > >         }
> > 
> > I don't see what effect that would have. What do you want to
> > achieve with this?
> 
> If I read the code correctly adding the function above would end
> up in a 1:1 mapping:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> 
> so taddr will be assigned with the cpu address space specified
> in the children nodes of LPC and we are not using a quirk function
> (we are just checking that we have the indirect io assigned and
> that we are on a ISA bus). Now probably there is a nit in my 
> code sketch where of_isa_indirect_io should be probably an architecture
> specific function...

But the point is that it would then return an incorrect address,
which in the worst case could be the same as another I/O space
if that happens to be at CPU address zero.

> > I think all we need from this function is to return '1' if
> > we hit an ISA I/O window, and that should happen for the two
> > interesting cases, either no 'ranges' at all, or no translation
> > for the range in question, so that __of_translate_address can
> > return OF_BAD_ADDR, and we can enter the special case
> > handling in the caller, that handles it like
> > 
> 
> I don't think this is very right as you may fail for different
> reasons other than a missing range property, e.g:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> 
> And even if the only failure case was a missing range if in the
> future __of_translate_address had to be reworked we would again
> make a wrong assumption...you get my point?

The newly introduced function would clearly have to make
some sanity checks. The idea is that treat the case of
not being able to translate a bus specific I/O address
into a CPU address literally and fall back to another method
of translating that address.

This matches my mental model of how we find the resource:

- start with the bus address
- try to translate that into a CPU address
- if we arrive at a CPU physical address for IORESOURCE_MEM, use that
- if we arrive at a CPU physical address for IORESOURCE_IO, translate
  that into a Linux IORESOURCE_IO token
- if there is no valid CPU physical address, try to translate
  the address into an IORESOURCE_IO using the ISA accessor
- if that fails too, give up.

If you try to fake a CPU physical address inbetween, it just
gets more confusing.

	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 14:59                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-22 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > >  static int of_empty_ranges_quirk(struct device_node *np)
> > >  {
> > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node
> > *parent, struct of_bus *bus,
> > >          * This code is only enabled on powerpc. --gcl
> > >          */
> > >         ranges = of_get_property(parent, rprop, &rlen);
> > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > !of_isa_indirect_io(parent)) {
> > >                 pr_debug("OF: no ranges; cannot translate\n");
> > >                 return 1;
> > >         }
> > 
> > I don't see what effect that would have. What do you want to
> > achieve with this?
> 
> If I read the code correctly adding the function above would end
> up in a 1:1 mapping:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> 
> so taddr will be assigned with the cpu address space specified
> in the children nodes of LPC and we are not using a quirk function
> (we are just checking that we have the indirect io assigned and
> that we are on a ISA bus). Now probably there is a nit in my 
> code sketch where of_isa_indirect_io should be probably an architecture
> specific function...

But the point is that it would then return an incorrect address,
which in the worst case could be the same as another I/O space
if that happens to be at CPU address zero.

> > I think all we need from this function is to return '1' if
> > we hit an ISA I/O window, and that should happen for the two
> > interesting cases, either no 'ranges' at all, or no translation
> > for the range in question, so that __of_translate_address can
> > return OF_BAD_ADDR, and we can enter the special case
> > handling in the caller, that handles it like
> > 
> 
> I don't think this is very right as you may fail for different
> reasons other than a missing range property, e.g:
> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> 
> And even if the only failure case was a missing range if in the
> future __of_translate_address had to be reworked we would again
> make a wrong assumption...you get my point?

The newly introduced function would clearly have to make
some sanity checks. The idea is that treat the case of
not being able to translate a bus specific I/O address
into a CPU address literally and fall back to another method
of translating that address.

This matches my mental model of how we find the resource:

- start with the bus address
- try to translate that into a CPU address
- if we arrive at a CPU physical address for IORESOURCE_MEM, use that
- if we arrive at a CPU physical address for IORESOURCE_IO, translate
  that into a Linux IORESOURCE_IO token
- if there is no valid CPU physical address, try to translate
  the address into an IORESOURCE_IO using the ISA accessor
- if that fails too, give up.

If you try to fake a CPU physical address inbetween, it just
gets more confusing.

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-22 14:59                               ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-22 15:20                                 ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 15:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 22 September 2016 15:59
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > > >  static int of_empty_ranges_quirk(struct device_node *np)
> > > >  {
> > > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > > @@ -503,7 +512,7 @@ static int of_translate_one(struct
> device_node
> > > *parent, struct of_bus *bus,
> > > >          * This code is only enabled on powerpc. --gcl
> > > >          */
> > > >         ranges = of_get_property(parent, rprop, &rlen);
> > > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > > !of_isa_indirect_io(parent)) {
> > > >                 pr_debug("OF: no ranges; cannot translate\n");
> > > >                 return 1;
> > > >         }
> > >
> > > I don't see what effect that would have. What do you want to
> > > achieve with this?
> >
> > If I read the code correctly adding the function above would end
> > up in a 1:1 mapping:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> >
> > so taddr will be assigned with the cpu address space specified
> > in the children nodes of LPC and we are not using a quirk function
> > (we are just checking that we have the indirect io assigned and
> > that we are on a ISA bus). Now probably there is a nit in my
> > code sketch where of_isa_indirect_io should be probably an
> architecture
> > specific function...
> 
> But the point is that it would then return an incorrect address,
> which in the worst case could be the same as another I/O space
> if that happens to be at CPU address zero.

If we do not touch __of_address_to_resource after taddr is returned
by of_translate_address we will check for (flags & IORESOURCE_IO),
then we call pci_address_to_pio to retrieve the unique token (remember
that LPC driver will register the LPC io range to pci io_range_list).

I do not think that we can have any conflict with any other I/O space
as pci_register_io_range will guarantee that the LPC range does not
overlap with any other I/O range... 

> 
> > > I think all we need from this function is to return '1' if
> > > we hit an ISA I/O window, and that should happen for the two
> > > interesting cases, either no 'ranges' at all, or no translation
> > > for the range in question, so that __of_translate_address can
> > > return OF_BAD_ADDR, and we can enter the special case
> > > handling in the caller, that handles it like
> > >
> >
> > I don't think this is very right as you may fail for different
> > reasons other than a missing range property, e.g:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> >
> > And even if the only failure case was a missing range if in the
> > future __of_translate_address had to be reworked we would again
> > make a wrong assumption...you get my point?
> 
> The newly introduced function would clearly have to make
> some sanity checks. The idea is that treat the case of
> not being able to translate a bus specific I/O address
> into a CPU address literally and fall back to another method
> of translating that address.
> 
> This matches my mental model of how we find the resource:
> 
> - start with the bus address
> - try to translate that into a CPU address
> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>   that into a Linux IORESOURCE_IO token
> - if there is no valid CPU physical address, try to translate
>   the address into an IORESOURCE_IO using the ISA accessor
> - if that fails too, give up.
> 
> If you try to fake a CPU physical address inbetween, it just
> gets more confusing.
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 15:20                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 15:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourong



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 22 September 2016 15:59
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > > >  static int of_empty_ranges_quirk(struct device_node *np)
> > > >  {
> > > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > > @@ -503,7 +512,7 @@ static int of_translate_one(struct
> device_node
> > > *parent, struct of_bus *bus,
> > > >          * This code is only enabled on powerpc. --gcl
> > > >          */
> > > >         ranges = of_get_property(parent, rprop, &rlen);
> > > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > > !of_isa_indirect_io(parent)) {
> > > >                 pr_debug("OF: no ranges; cannot translate\n");
> > > >                 return 1;
> > > >         }
> > >
> > > I don't see what effect that would have. What do you want to
> > > achieve with this?
> >
> > If I read the code correctly adding the function above would end
> > up in a 1:1 mapping:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> >
> > so taddr will be assigned with the cpu address space specified
> > in the children nodes of LPC and we are not using a quirk function
> > (we are just checking that we have the indirect io assigned and
> > that we are on a ISA bus). Now probably there is a nit in my
> > code sketch where of_isa_indirect_io should be probably an
> architecture
> > specific function...
> 
> But the point is that it would then return an incorrect address,
> which in the worst case could be the same as another I/O space
> if that happens to be at CPU address zero.

If we do not touch __of_address_to_resource after taddr is returned
by of_translate_address we will check for (flags & IORESOURCE_IO),
then we call pci_address_to_pio to retrieve the unique token (remember
that LPC driver will register the LPC io range to pci io_range_list).

I do not think that we can have any conflict with any other I/O space
as pci_register_io_range will guarantee that the LPC range does not
overlap with any other I/O range... 

> 
> > > I think all we need from this function is to return '1' if
> > > we hit an ISA I/O window, and that should happen for the two
> > > interesting cases, either no 'ranges' at all, or no translation
> > > for the range in question, so that __of_translate_address can
> > > return OF_BAD_ADDR, and we can enter the special case
> > > handling in the caller, that handles it like
> > >
> >
> > I don't think this is very right as you may fail for different
> > reasons other than a missing range property, e.g:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> >
> > And even if the only failure case was a missing range if in the
> > future __of_translate_address had to be reworked we would again
> > make a wrong assumption...you get my point?
> 
> The newly introduced function would clearly have to make
> some sanity checks. The idea is that treat the case of
> not being able to translate a bus specific I/O address
> into a CPU address literally and fall back to another method
> of translating that address.
> 
> This matches my mental model of how we find the resource:
> 
> - start with the bus address
> - try to translate that into a CPU address
> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>   that into a Linux IORESOURCE_IO token
> - if there is no valid CPU physical address, try to translate
>   the address into an IORESOURCE_IO using the ISA accessor
> - if that fails too, give up.
> 
> If you try to fake a CPU physical address inbetween, it just
> gets more confusing.
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 15:20                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 15:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 22 September 2016 15:59
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > > >  static int of_empty_ranges_quirk(struct device_node *np)
> > > >  {
> > > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > > @@ -503,7 +512,7 @@ static int of_translate_one(struct
> device_node
> > > *parent, struct of_bus *bus,
> > > >          * This code is only enabled on powerpc. --gcl
> > > >          */
> > > >         ranges = of_get_property(parent, rprop, &rlen);
> > > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > > !of_isa_indirect_io(parent)) {
> > > >                 pr_debug("OF: no ranges; cannot translate\n");
> > > >                 return 1;
> > > >         }
> > >
> > > I don't see what effect that would have. What do you want to
> > > achieve with this?
> >
> > If I read the code correctly adding the function above would end
> > up in a 1:1 mapping:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> >
> > so taddr will be assigned with the cpu address space specified
> > in the children nodes of LPC and we are not using a quirk function
> > (we are just checking that we have the indirect io assigned and
> > that we are on a ISA bus). Now probably there is a nit in my
> > code sketch where of_isa_indirect_io should be probably an
> architecture
> > specific function...
> 
> But the point is that it would then return an incorrect address,
> which in the worst case could be the same as another I/O space
> if that happens to be at CPU address zero.

If we do not touch __of_address_to_resource after taddr is returned
by of_translate_address we will check for (flags & IORESOURCE_IO),
then we call pci_address_to_pio to retrieve the unique token (remember
that LPC driver will register the LPC io range to pci io_range_list).

I do not think that we can have any conflict with any other I/O space
as pci_register_io_range will guarantee that the LPC range does not
overlap with any other I/O range... 

> 
> > > I think all we need from this function is to return '1' if
> > > we hit an ISA I/O window, and that should happen for the two
> > > interesting cases, either no 'ranges' at all, or no translation
> > > for the range in question, so that __of_translate_address can
> > > return OF_BAD_ADDR, and we can enter the special case
> > > handling in the caller, that handles it like
> > >
> >
> > I don't think this is very right as you may fail for different
> > reasons other than a missing range property, e.g:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> >
> > And even if the only failure case was a missing range if in the
> > future __of_translate_address had to be reworked we would again
> > make a wrong assumption...you get my point?
> 
> The newly introduced function would clearly have to make
> some sanity checks. The idea is that treat the case of
> not being able to translate a bus specific I/O address
> into a CPU address literally and fall back to another method
> of translating that address.
> 
> This matches my mental model of how we find the resource:
> 
> - start with the bus address
> - try to translate that into a CPU address
> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>   that into a Linux IORESOURCE_IO token
> - if there is no valid CPU physical address, try to translate
>   the address into an IORESOURCE_IO using the ISA accessor
> - if that fails too, give up.
> 
> If you try to fake a CPU physical address inbetween, it just
> gets more confusing.
> 
> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 15:20                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-22 15:20 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 22 September 2016 15:59
> To: Gabriele Paoloni
> Cc: zhichang; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
> > > >  static int of_empty_ranges_quirk(struct device_node *np)
> > > >  {
> > > >         if (IS_ENABLED(CONFIG_PPC)) {
> > > > @@ -503,7 +512,7 @@ static int of_translate_one(struct
> device_node
> > > *parent, struct of_bus *bus,
> > > >          * This code is only enabled on powerpc. --gcl
> > > >          */
> > > >         ranges = of_get_property(parent, rprop, &rlen);
> > > > -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
> > > > +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
> > > !of_isa_indirect_io(parent)) {
> > > >                 pr_debug("OF: no ranges; cannot translate\n");
> > > >                 return 1;
> > > >         }
> > >
> > > I don't see what effect that would have. What do you want to
> > > achieve with this?
> >
> > If I read the code correctly adding the function above would end
> > up in a 1:1 mapping:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L513
> >
> > so taddr will be assigned with the cpu address space specified
> > in the children nodes of LPC and we are not using a quirk function
> > (we are just checking that we have the indirect io assigned and
> > that we are on a ISA bus). Now probably there is a nit in my
> > code sketch where of_isa_indirect_io should be probably an
> architecture
> > specific function...
> 
> But the point is that it would then return an incorrect address,
> which in the worst case could be the same as another I/O space
> if that happens to be at CPU address zero.

If we do not touch __of_address_to_resource after taddr is returned
by of_translate_address we will check for (flags & IORESOURCE_IO),
then we call pci_address_to_pio to retrieve the unique token (remember
that LPC driver will register the LPC io range to pci io_range_list).

I do not think that we can have any conflict with any other I/O space
as pci_register_io_range will guarantee that the LPC range does not
overlap with any other I/O range... 

> 
> > > I think all we need from this function is to return '1' if
> > > we hit an ISA I/O window, and that should happen for the two
> > > interesting cases, either no 'ranges' at all, or no translation
> > > for the range in question, so that __of_translate_address can
> > > return OF_BAD_ADDR, and we can enter the special case
> > > handling in the caller, that handles it like
> > >
> >
> > I don't think this is very right as you may fail for different
> > reasons other than a missing range property, e.g:
> > http://lxr.free-electrons.com/source/drivers/of/address.c#L575
> >
> > And even if the only failure case was a missing range if in the
> > future __of_translate_address had to be reworked we would again
> > make a wrong assumption...you get my point?
> 
> The newly introduced function would clearly have to make
> some sanity checks. The idea is that treat the case of
> not being able to translate a bus specific I/O address
> into a CPU address literally and fall back to another method
> of translating that address.
> 
> This matches my mental model of how we find the resource:
> 
> - start with the bus address
> - try to translate that into a CPU address
> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>   that into a Linux IORESOURCE_IO token
> - if there is no valid CPU physical address, try to translate
>   the address into an IORESOURCE_IO using the ISA accessor
> - if that fails too, give up.
> 
> If you try to fake a CPU physical address inbetween, it just
> gets more confusing.
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-22 15:20                                 ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-22 15:46                                   ` zhichang.yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 15:46 UTC (permalink / raw)
  To: Gabriele Paoloni, Arnd Bergmann
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc


On 09/22/2016 11:20 PM, Gabriele Paoloni wrote:
>
>> -----Original Message-----
>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>> Sent: 22 September 2016 15:59
>> To: Gabriele Paoloni
>> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
>> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
>> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
>> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
>> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
>> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
>> kantyzc@163.com
>> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
>> Hip06
>>
>> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
>>>>>   static int of_empty_ranges_quirk(struct device_node *np)
>>>>>   {
>>>>>          if (IS_ENABLED(CONFIG_PPC)) {
>>>>> @@ -503,7 +512,7 @@ static int of_translate_one(struct
>> device_node
>>>> *parent, struct of_bus *bus,
>>>>>           * This code is only enabled on powerpc. --gcl
>>>>>           */
>>>>>          ranges = of_get_property(parent, rprop, &rlen);
>>>>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>>>>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
>>>> !of_isa_indirect_io(parent)) {
>>>>>                  pr_debug("OF: no ranges; cannot translate\n");
>>>>>                  return 1;
>>>>>          }
>>>> I don't see what effect that would have. What do you want to
>>>> achieve with this?
>>> If I read the code correctly adding the function above would end
>>> up in a 1:1 mapping:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
>>>
>>> so taddr will be assigned with the cpu address space specified
>>> in the children nodes of LPC and we are not using a quirk function
>>> (we are just checking that we have the indirect io assigned and
>>> that we are on a ISA bus). Now probably there is a nit in my
>>> code sketch where of_isa_indirect_io should be probably an
>> architecture
>>> specific function...
>> But the point is that it would then return an incorrect address,
>> which in the worst case could be the same as another I/O space
>> if that happens to be at CPU address zero.
> If we do not touch __of_address_to_resource after taddr is returned
> by of_translate_address we will check for (flags & IORESOURCE_IO),
> then we call pci_address_to_pio to retrieve the unique token (remember
> that LPC driver will register the LPC io range to pci io_range_list).
>
> I do not think that we can have any conflict with any other I/O space
> as pci_register_io_range will guarantee that the LPC range does not
> overlap with any other I/O range...
If we don't bypass the calling of pci_address_to_pio after 
of_translate_address,
there should no conflict between LPC logical IO range and other logical 
IO ranges
of other devices.
I guess Arnd want to skip all the translation for our LPC IO address. 
But if we do it
like that, it seems we can't avoid the possible conflict with the 
logical IO ranges of
PCI host bridges without any changes on the pci_register_io_range and 
pci_address_to_pio.
Because two completely separate I/O spaces are created without 
synchronization.

Best,
Zhichang
>>>> I think all we need from this function is to return '1' if
>>>> we hit an ISA I/O window, and that should happen for the two
>>>> interesting cases, either no 'ranges' at all, or no translation
>>>> for the range in question, so that __of_translate_address can
>>>> return OF_BAD_ADDR, and we can enter the special case
>>>> handling in the caller, that handles it like
>>>>
>>> I don't think this is very right as you may fail for different
>>> reasons other than a missing range property, e.g:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
>>>
>>> And even if the only failure case was a missing range if in the
>>> future __of_translate_address had to be reworked we would again
>>> make a wrong assumption...you get my point?
>> The newly introduced function would clearly have to make
>> some sanity checks. The idea is that treat the case of
>> not being able to translate a bus specific I/O address
>> into a CPU address literally and fall back to another method
>> of translating that address.
>>
>> This matches my mental model of how we find the resource:
>>
>> - start with the bus address
>> - try to translate that into a CPU address
>> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
>> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>>    that into a Linux IORESOURCE_IO token
>> - if there is no valid CPU physical address, try to translate
>>    the address into an IORESOURCE_IO using the ISA accessor
>> - if that fails too, give up.
>>
>> If you try to fake a CPU physical address inbetween, it just
>> gets more confusing.
>>
>> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 15:46                                   ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 15:46 UTC (permalink / raw)
  To: Gabriele Paoloni, Arnd Bergmann
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong


On 09/22/2016 11:20 PM, Gabriele Paoloni wrote:
>
>> -----Original Message-----
>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>> Sent: 22 September 2016 15:59
>> To: Gabriele Paoloni
>> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
>> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
>> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
>> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
>> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
>> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
>> kantyzc@163.com
>> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
>> Hip06
>>
>> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
>>>>>   static int of_empty_ranges_quirk(struct device_node *np)
>>>>>   {
>>>>>          if (IS_ENABLED(CONFIG_PPC)) {
>>>>> @@ -503,7 +512,7 @@ static int of_translate_one(struct
>> device_node
>>>> *parent, struct of_bus *bus,
>>>>>           * This code is only enabled on powerpc. --gcl
>>>>>           */
>>>>>          ranges = of_get_property(parent, rprop, &rlen);
>>>>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>>>>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
>>>> !of_isa_indirect_io(parent)) {
>>>>>                  pr_debug("OF: no ranges; cannot translate\n");
>>>>>                  return 1;
>>>>>          }
>>>> I don't see what effect that would have. What do you want to
>>>> achieve with this?
>>> If I read the code correctly adding the function above would end
>>> up in a 1:1 mapping:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
>>>
>>> so taddr will be assigned with the cpu address space specified
>>> in the children nodes of LPC and we are not using a quirk function
>>> (we are just checking that we have the indirect io assigned and
>>> that we are on a ISA bus). Now probably there is a nit in my
>>> code sketch where of_isa_indirect_io should be probably an
>> architecture
>>> specific function...
>> But the point is that it would then return an incorrect address,
>> which in the worst case could be the same as another I/O space
>> if that happens to be at CPU address zero.
> If we do not touch __of_address_to_resource after taddr is returned
> by of_translate_address we will check for (flags & IORESOURCE_IO),
> then we call pci_address_to_pio to retrieve the unique token (remember
> that LPC driver will register the LPC io range to pci io_range_list).
>
> I do not think that we can have any conflict with any other I/O space
> as pci_register_io_range will guarantee that the LPC range does not
> overlap with any other I/O range...
If we don't bypass the calling of pci_address_to_pio after 
of_translate_address,
there should no conflict between LPC logical IO range and other logical 
IO ranges
of other devices.
I guess Arnd want to skip all the translation for our LPC IO address. 
But if we do it
like that, it seems we can't avoid the possible conflict with the 
logical IO ranges of
PCI host bridges without any changes on the pci_register_io_range and 
pci_address_to_pio.
Because two completely separate I/O spaces are created without 
synchronization.

Best,
Zhichang
>>>> I think all we need from this function is to return '1' if
>>>> we hit an ISA I/O window, and that should happen for the two
>>>> interesting cases, either no 'ranges' at all, or no translation
>>>> for the range in question, so that __of_translate_address can
>>>> return OF_BAD_ADDR, and we can enter the special case
>>>> handling in the caller, that handles it like
>>>>
>>> I don't think this is very right as you may fail for different
>>> reasons other than a missing range property, e.g:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
>>>
>>> And even if the only failure case was a missing range if in the
>>> future __of_translate_address had to be reworked we would again
>>> make a wrong assumption...you get my point?
>> The newly introduced function would clearly have to make
>> some sanity checks. The idea is that treat the case of
>> not being able to translate a bus specific I/O address
>> into a CPU address literally and fall back to another method
>> of translating that address.
>>
>> This matches my mental model of how we find the resource:
>>
>> - start with the bus address
>> - try to translate that into a CPU address
>> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
>> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>>    that into a Linux IORESOURCE_IO token
>> - if there is no valid CPU physical address, try to translate
>>    the address into an IORESOURCE_IO using the ISA accessor
>> - if that fails too, give up.
>>
>> If you try to fake a CPU physical address inbetween, it just
>> gets more confusing.
>>
>> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 15:46                                   ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 15:46 UTC (permalink / raw)
  To: Gabriele Paoloni, Arnd Bergmann
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc


On 09/22/2016 11:20 PM, Gabriele Paoloni wrote:
>
>> -----Original Message-----
>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>> Sent: 22 September 2016 15:59
>> To: Gabriele Paoloni
>> Cc: zhichang; linux-arm-kernel@lists.infradead.org;
>> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
>> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
>> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
>> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
>> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
>> kantyzc@163.com
>> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
>> Hip06
>>
>> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
>>>>>   static int of_empty_ranges_quirk(struct device_node *np)
>>>>>   {
>>>>>          if (IS_ENABLED(CONFIG_PPC)) {
>>>>> @@ -503,7 +512,7 @@ static int of_translate_one(struct
>> device_node
>>>> *parent, struct of_bus *bus,
>>>>>           * This code is only enabled on powerpc. --gcl
>>>>>           */
>>>>>          ranges = of_get_property(parent, rprop, &rlen);
>>>>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>>>>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
>>>> !of_isa_indirect_io(parent)) {
>>>>>                  pr_debug("OF: no ranges; cannot translate\n");
>>>>>                  return 1;
>>>>>          }
>>>> I don't see what effect that would have. What do you want to
>>>> achieve with this?
>>> If I read the code correctly adding the function above would end
>>> up in a 1:1 mapping:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
>>>
>>> so taddr will be assigned with the cpu address space specified
>>> in the children nodes of LPC and we are not using a quirk function
>>> (we are just checking that we have the indirect io assigned and
>>> that we are on a ISA bus). Now probably there is a nit in my
>>> code sketch where of_isa_indirect_io should be probably an
>> architecture
>>> specific function...
>> But the point is that it would then return an incorrect address,
>> which in the worst case could be the same as another I/O space
>> if that happens to be at CPU address zero.
> If we do not touch __of_address_to_resource after taddr is returned
> by of_translate_address we will check for (flags & IORESOURCE_IO),
> then we call pci_address_to_pio to retrieve the unique token (remember
> that LPC driver will register the LPC io range to pci io_range_list).
>
> I do not think that we can have any conflict with any other I/O space
> as pci_register_io_range will guarantee that the LPC range does not
> overlap with any other I/O range...
If we don't bypass the calling of pci_address_to_pio after 
of_translate_address,
there should no conflict between LPC logical IO range and other logical 
IO ranges
of other devices.
I guess Arnd want to skip all the translation for our LPC IO address. 
But if we do it
like that, it seems we can't avoid the possible conflict with the 
logical IO ranges of
PCI host bridges without any changes on the pci_register_io_range and 
pci_address_to_pio.
Because two completely separate I/O spaces are created without 
synchronization.

Best,
Zhichang
>>>> I think all we need from this function is to return '1' if
>>>> we hit an ISA I/O window, and that should happen for the two
>>>> interesting cases, either no 'ranges' at all, or no translation
>>>> for the range in question, so that __of_translate_address can
>>>> return OF_BAD_ADDR, and we can enter the special case
>>>> handling in the caller, that handles it like
>>>>
>>> I don't think this is very right as you may fail for different
>>> reasons other than a missing range property, e.g:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
>>>
>>> And even if the only failure case was a missing range if in the
>>> future __of_translate_address had to be reworked we would again
>>> make a wrong assumption...you get my point?
>> The newly introduced function would clearly have to make
>> some sanity checks. The idea is that treat the case of
>> not being able to translate a bus specific I/O address
>> into a CPU address literally and fall back to another method
>> of translating that address.
>>
>> This matches my mental model of how we find the resource:
>>
>> - start with the bus address
>> - try to translate that into a CPU address
>> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
>> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>>    that into a Linux IORESOURCE_IO token
>> - if there is no valid CPU physical address, try to translate
>>    the address into an IORESOURCE_IO using the ISA accessor
>> - if that fails too, give up.
>>
>> If you try to fake a CPU physical address inbetween, it just
>> gets more confusing.
>>
>> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 15:46                                   ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 15:46 UTC (permalink / raw)
  To: linux-arm-kernel


On 09/22/2016 11:20 PM, Gabriele Paoloni wrote:
>
>> -----Original Message-----
>> From: Arnd Bergmann [mailto:arnd at arndb.de]
>> Sent: 22 September 2016 15:59
>> To: Gabriele Paoloni
>> Cc: zhichang; linux-arm-kernel at lists.infradead.org;
>> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
>> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
>> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
>> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
>> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
>> kantyzc at 163.com
>> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
>> Hip06
>>
>> On Thursday, September 22, 2016 2:47:14 PM CEST Gabriele Paoloni wrote:
>>>>>   static int of_empty_ranges_quirk(struct device_node *np)
>>>>>   {
>>>>>          if (IS_ENABLED(CONFIG_PPC)) {
>>>>> @@ -503,7 +512,7 @@ static int of_translate_one(struct
>> device_node
>>>> *parent, struct of_bus *bus,
>>>>>           * This code is only enabled on powerpc. --gcl
>>>>>           */
>>>>>          ranges = of_get_property(parent, rprop, &rlen);
>>>>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>>>>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
>>>> !of_isa_indirect_io(parent)) {
>>>>>                  pr_debug("OF: no ranges; cannot translate\n");
>>>>>                  return 1;
>>>>>          }
>>>> I don't see what effect that would have. What do you want to
>>>> achieve with this?
>>> If I read the code correctly adding the function above would end
>>> up in a 1:1 mapping:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L513
>>>
>>> so taddr will be assigned with the cpu address space specified
>>> in the children nodes of LPC and we are not using a quirk function
>>> (we are just checking that we have the indirect io assigned and
>>> that we are on a ISA bus). Now probably there is a nit in my
>>> code sketch where of_isa_indirect_io should be probably an
>> architecture
>>> specific function...
>> But the point is that it would then return an incorrect address,
>> which in the worst case could be the same as another I/O space
>> if that happens to be at CPU address zero.
> If we do not touch __of_address_to_resource after taddr is returned
> by of_translate_address we will check for (flags & IORESOURCE_IO),
> then we call pci_address_to_pio to retrieve the unique token (remember
> that LPC driver will register the LPC io range to pci io_range_list).
>
> I do not think that we can have any conflict with any other I/O space
> as pci_register_io_range will guarantee that the LPC range does not
> overlap with any other I/O range...
If we don't bypass the calling of pci_address_to_pio after 
of_translate_address,
there should no conflict between LPC logical IO range and other logical 
IO ranges
of other devices.
I guess Arnd want to skip all the translation for our LPC IO address. 
But if we do it
like that, it seems we can't avoid the possible conflict with the 
logical IO ranges of
PCI host bridges without any changes on the pci_register_io_range and 
pci_address_to_pio.
Because two completely separate I/O spaces are created without 
synchronization.

Best,
Zhichang
>>>> I think all we need from this function is to return '1' if
>>>> we hit an ISA I/O window, and that should happen for the two
>>>> interesting cases, either no 'ranges' at all, or no translation
>>>> for the range in question, so that __of_translate_address can
>>>> return OF_BAD_ADDR, and we can enter the special case
>>>> handling in the caller, that handles it like
>>>>
>>> I don't think this is very right as you may fail for different
>>> reasons other than a missing range property, e.g:
>>> http://lxr.free-electrons.com/source/drivers/of/address.c#L575
>>>
>>> And even if the only failure case was a missing range if in the
>>> future __of_translate_address had to be reworked we would again
>>> make a wrong assumption...you get my point?
>> The newly introduced function would clearly have to make
>> some sanity checks. The idea is that treat the case of
>> not being able to translate a bus specific I/O address
>> into a CPU address literally and fall back to another method
>> of translating that address.
>>
>> This matches my mental model of how we find the resource:
>>
>> - start with the bus address
>> - try to translate that into a CPU address
>> - if we arrive at a CPU physical address for IORESOURCE_MEM, use that
>> - if we arrive at a CPU physical address for IORESOURCE_IO, translate
>>    that into a Linux IORESOURCE_IO token
>> - if there is no valid CPU physical address, try to translate
>>    the address into an IORESOURCE_IO using the ISA accessor
>> - if that fails too, give up.
>>
>> If you try to fake a CPU physical address inbetween, it just
>> gets more confusing.
>>
>> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-22 12:14                           ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-22 16:27                             ` zhichang.yuan
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 16:27 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc


On 09/22/2016 08:14 PM, Arnd Bergmann wrote:
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
>>>> I think extending of_empty_ranges_quirk() may be a reasonable
>>> solution.
>>>> What do you think Arnd?
>>> I don't really like that idea, that quirk is meant to work around
>>> broken DTs, but we can just make the DT valid and implement the
>>> code properly.
>> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
>> As a quirk is used to work around broken HW or broken FW (as in this case)
>> rather than to fix code
>>
>> What about the following? I think adding the check you suggested next to
>> of_empty_ranges_quirk() is adding the case we need in the right point (thus
>> avoiding any duplication)
>>   
>> --- a/drivers/of/address.c
>> +++ b/drivers/of/address.c
>> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>>          return NULL;
>>   }
>>   
>> +static inline int of_isa_indirect_io(struct device_node *np)
>> +{
>> +       /*
>> +        * check if the current node is an isa bus and if indirectio operation
>> +        * are registered
>> +        */
>> +       return (of_bus_isa_match(np) && arm64_extio_ops);
>> +}
>> +
>>   static int of_empty_ranges_quirk(struct device_node *np)
>>   {
>>          if (IS_ENABLED(CONFIG_PPC)) {
>> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>>           * This code is only enabled on powerpc. --gcl
>>           */
>>          ranges = of_get_property(parent, rprop, &rlen);
>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>>                  pr_debug("OF: no ranges; cannot translate\n");
>>                  return 1;
>>          }
> I don't see what effect that would have. What do you want to
> achieve with this?
>
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
>   	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>   		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>   		if (port == (unsigned long)-1)
>   			return -EINVAL;
>   		r->start = port;
>   		r->end = port + size - 1;
>   	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>   		r->start = taddr;
>   		r->end = taddr + size - 1;
>   	}
>
For this patch sketch, I have a question.
Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
corresponding logical IO port
for LPC??

If we don't, it seems the LPC specific IO address will conflict with PCI 
host bridges' logical IO.
Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
normal for ISA similar
devices), after arch_of_address_to_pio(), the r->start will be set as 
0x100, r->end will be set as
0x3FF.  And if there is one PCI host bridge who request a IO window size 
over 0x400 at the same
time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
after of_address_to_resource
for this host bridge.  Then the IO conflict happens.

cheers,
Zhichang

>
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 16:27                             ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 16:27 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong


On 09/22/2016 08:14 PM, Arnd Bergmann wrote:
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
>>>> I think extending of_empty_ranges_quirk() may be a reasonable
>>> solution.
>>>> What do you think Arnd?
>>> I don't really like that idea, that quirk is meant to work around
>>> broken DTs, but we can just make the DT valid and implement the
>>> code properly.
>> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
>> As a quirk is used to work around broken HW or broken FW (as in this case)
>> rather than to fix code
>>
>> What about the following? I think adding the check you suggested next to
>> of_empty_ranges_quirk() is adding the case we need in the right point (thus
>> avoiding any duplication)
>>   
>> --- a/drivers/of/address.c
>> +++ b/drivers/of/address.c
>> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>>          return NULL;
>>   }
>>   
>> +static inline int of_isa_indirect_io(struct device_node *np)
>> +{
>> +       /*
>> +        * check if the current node is an isa bus and if indirectio operation
>> +        * are registered
>> +        */
>> +       return (of_bus_isa_match(np) && arm64_extio_ops);
>> +}
>> +
>>   static int of_empty_ranges_quirk(struct device_node *np)
>>   {
>>          if (IS_ENABLED(CONFIG_PPC)) {
>> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>>           * This code is only enabled on powerpc. --gcl
>>           */
>>          ranges = of_get_property(parent, rprop, &rlen);
>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>>                  pr_debug("OF: no ranges; cannot translate\n");
>>                  return 1;
>>          }
> I don't see what effect that would have. What do you want to
> achieve with this?
>
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
>   	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>   		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>   		if (port == (unsigned long)-1)
>   			return -EINVAL;
>   		r->start = port;
>   		r->end = port + size - 1;
>   	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>   		r->start = taddr;
>   		r->end = taddr + size - 1;
>   	}
>
For this patch sketch, I have a question.
Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
corresponding logical IO port
for LPC??

If we don't, it seems the LPC specific IO address will conflict with PCI 
host bridges' logical IO.
Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
normal for ISA similar
devices), after arch_of_address_to_pio(), the r->start will be set as 
0x100, r->end will be set as
0x3FF.  And if there is one PCI host bridge who request a IO window size 
over 0x400 at the same
time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
after of_address_to_resource
for this host bridge.  Then the IO conflict happens.

cheers,
Zhichang

>
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 16:27                             ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 16:27 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, John Garry,
	will.deacon, linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel


On 09/22/2016 08:14 PM, Arnd Bergmann wrote:
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
>>>> I think extending of_empty_ranges_quirk() may be a reasonable
>>> solution.
>>>> What do you think Arnd?
>>> I don't really like that idea, that quirk is meant to work around
>>> broken DTs, but we can just make the DT valid and implement the
>>> code properly.
>> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
>> As a quirk is used to work around broken HW or broken FW (as in this case)
>> rather than to fix code
>>
>> What about the following? I think adding the check you suggested next to
>> of_empty_ranges_quirk() is adding the case we need in the right point (thus
>> avoiding any duplication)
>>   
>> --- a/drivers/of/address.c
>> +++ b/drivers/of/address.c
>> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>>          return NULL;
>>   }
>>   
>> +static inline int of_isa_indirect_io(struct device_node *np)
>> +{
>> +       /*
>> +        * check if the current node is an isa bus and if indirectio operation
>> +        * are registered
>> +        */
>> +       return (of_bus_isa_match(np) && arm64_extio_ops);
>> +}
>> +
>>   static int of_empty_ranges_quirk(struct device_node *np)
>>   {
>>          if (IS_ENABLED(CONFIG_PPC)) {
>> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>>           * This code is only enabled on powerpc. --gcl
>>           */
>>          ranges = of_get_property(parent, rprop, &rlen);
>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>>                  pr_debug("OF: no ranges; cannot translate\n");
>>                  return 1;
>>          }
> I don't see what effect that would have. What do you want to
> achieve with this?
>
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
>   	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>   		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>   		if (port == (unsigned long)-1)
>   			return -EINVAL;
>   		r->start = port;
>   		r->end = port + size - 1;
>   	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>   		r->start = taddr;
>   		r->end = taddr + size - 1;
>   	}
>
For this patch sketch, I have a question.
Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
corresponding logical IO port
for LPC??

If we don't, it seems the LPC specific IO address will conflict with PCI 
host bridges' logical IO.
Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
normal for ISA similar
devices), after arch_of_address_to_pio(), the r->start will be set as 
0x100, r->end will be set as
0x3FF.  And if there is one PCI host bridge who request a IO window size 
over 0x400 at the same
time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
after of_address_to_resource
for this host bridge.  Then the IO conflict happens.

cheers,
Zhichang

>
> 	Arnd


_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-22 16:27                             ` zhichang.yuan
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang.yuan @ 2016-09-22 16:27 UTC (permalink / raw)
  To: linux-arm-kernel


On 09/22/2016 08:14 PM, Arnd Bergmann wrote:
> On Thursday, September 22, 2016 11:55:45 AM CEST Gabriele Paoloni wrote:
>>>> I think extending of_empty_ranges_quirk() may be a reasonable
>>> solution.
>>>> What do you think Arnd?
>>> I don't really like that idea, that quirk is meant to work around
>>> broken DTs, but we can just make the DT valid and implement the
>>> code properly.
>> Ok  I understand your point where it is not right to use of_empty_ranges_quirk()
>> As a quirk is used to work around broken HW or broken FW (as in this case)
>> rather than to fix code
>>
>> What about the following? I think adding the check you suggested next to
>> of_empty_ranges_quirk() is adding the case we need in the right point (thus
>> avoiding any duplication)
>>   
>> --- a/drivers/of/address.c
>> +++ b/drivers/of/address.c
>> @@ -457,6 +457,15 @@ static struct of_bus *of_match_bus(struct device_node *np)
>>          return NULL;
>>   }
>>   
>> +static inline int of_isa_indirect_io(struct device_node *np)
>> +{
>> +       /*
>> +        * check if the current node is an isa bus and if indirectio operation
>> +        * are registered
>> +        */
>> +       return (of_bus_isa_match(np) && arm64_extio_ops);
>> +}
>> +
>>   static int of_empty_ranges_quirk(struct device_node *np)
>>   {
>>          if (IS_ENABLED(CONFIG_PPC)) {
>> @@ -503,7 +512,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>>           * This code is only enabled on powerpc. --gcl
>>           */
>>          ranges = of_get_property(parent, rprop, &rlen);
>> -       if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>> +       if (ranges == NULL && !of_empty_ranges_quirk(parent) && !of_isa_indirect_io(parent)) {
>>                  pr_debug("OF: no ranges; cannot translate\n");
>>                  return 1;
>>          }
> I don't see what effect that would have. What do you want to
> achieve with this?
>
> I think all we need from this function is to return '1' if
> we hit an ISA I/O window, and that should happen for the two
> interesting cases, either no 'ranges' at all, or no translation
> for the range in question, so that __of_translate_address can
> return OF_BAD_ADDR, and we can enter the special case
> handling in the caller, that handles it like
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..a18d96843fae 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -685,17 +685,24 @@ static int __of_address_to_resource(struct device_node *dev,
>   	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
>   		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 (taddr == OF_BAD_ADDR)
> +			port = arch_of_address_to_pio(dev, addrp)
> +		else
> +			port = pci_address_to_pio(taddr);
> +
>   		if (port == (unsigned long)-1)
>   			return -EINVAL;
>   		r->start = port;
>   		r->end = port + size - 1;
>   	} else {
> +		if (taddr == OF_BAD_ADDR)
> +			return -EINVAL;
> +
>   		r->start = taddr;
>   		r->end = taddr + size - 1;
>   	}
>
For this patch sketch, I have a question.
Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
corresponding logical IO port
for LPC??

If we don't, it seems the LPC specific IO address will conflict with PCI 
host bridges' logical IO.
Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
normal for ISA similar
devices), after arch_of_address_to_pio(), the r->start will be set as 
0x100, r->end will be set as
0x3FF.  And if there is one PCI host bridge who request a IO window size 
over 0x400 at the same
time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
after of_address_to_resource
for this host bridge.  Then the IO conflict happens.

cheers,
Zhichang

>
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23  9:51                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23  9:51 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Gabriele Paoloni, linux-arm-kernel, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, gregkh, John Garry,
	will.deacon, linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> For this patch sketch, I have a question.
> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
> corresponding logical IO port
> for LPC??


No, of course not, that would be silly:

The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
have one because there is no address associated with your PIO, that
is the entire point of your driver!

Also, we already know the mapping because this is what the inb/outb
workaround is looking at, so there is absolutely no reason to call it
either.

> If we don't, it seems the LPC specific IO address will conflict with PCI 
> host bridges' logical IO.
>
> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
> normal for ISA similar
> devices), after arch_of_address_to_pio(), the r->start will be set as 
> 0x100, r->end will be set as
> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
> over 0x400 at the same
> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
> after of_address_to_resource
> for this host bridge.  Then the IO conflict happens.

You would still need to reserve some space in the io_range_list
to avoid possible conflicts, which is a bit ugly with the current
definition of pci_register_io_range, but I'm sure can be done.

One way I can think of would be to change pci_register_io_range()
to just return the logical port number directly (it already
knows it!), and pass an invalid physical address (e.g. 
#define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
invalid translations.

Another alternative that just occurred to me would be to move
the pci_address_to_pio() call from __of_address_to_resource()
into of_bus_pci_translate() and then do the special handling
for the ISA/LPC bus in of_bus_isa_translate().

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23  9:51                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23  9:51 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Gabriele Paoloni,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r

On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> For this patch sketch, I have a question.
> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
> corresponding logical IO port
> for LPC??


No, of course not, that would be silly:

The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
have one because there is no address associated with your PIO, that
is the entire point of your driver!

Also, we already know the mapping because this is what the inb/outb
workaround is looking at, so there is absolutely no reason to call it
either.

> If we don't, it seems the LPC specific IO address will conflict with PCI 
> host bridges' logical IO.
>
> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
> normal for ISA similar
> devices), after arch_of_address_to_pio(), the r->start will be set as 
> 0x100, r->end will be set as
> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
> over 0x400 at the same
> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
> after of_address_to_resource
> for this host bridge.  Then the IO conflict happens.

You would still need to reserve some space in the io_range_list
to avoid possible conflicts, which is a bit ugly with the current
definition of pci_register_io_range, but I'm sure can be done.

One way I can think of would be to change pci_register_io_range()
to just return the logical port number directly (it already
knows it!), and pass an invalid physical address (e.g. 
#define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
invalid translations.

Another alternative that just occurred to me would be to move
the pci_address_to_pio() call from __of_address_to_resource()
into of_bus_pci_translate() and then do the special handling
for the ISA/LPC bus in of_bus_isa_translate().

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23  9:51                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23  9:51 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: devicetree, lorenzo.pieralisi, benh, Gabriele Paoloni, minyard,
	linux-pci, John Garry, will.deacon, linux-kernel, Yuanzhichang,
	Linuxarm, xuwei (O),
	linux-serial, gregkh, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel

On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> For this patch sketch, I have a question.
> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
> corresponding logical IO port
> for LPC??


No, of course not, that would be silly:

The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
have one because there is no address associated with your PIO, that
is the entire point of your driver!

Also, we already know the mapping because this is what the inb/outb
workaround is looking at, so there is absolutely no reason to call it
either.

> If we don't, it seems the LPC specific IO address will conflict with PCI 
> host bridges' logical IO.
>
> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
> normal for ISA similar
> devices), after arch_of_address_to_pio(), the r->start will be set as 
> 0x100, r->end will be set as
> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
> over 0x400 at the same
> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
> after of_address_to_resource
> for this host bridge.  Then the IO conflict happens.

You would still need to reserve some space in the io_range_list
to avoid possible conflicts, which is a bit ugly with the current
definition of pci_register_io_range, but I'm sure can be done.

One way I can think of would be to change pci_register_io_range()
to just return the logical port number directly (it already
knows it!), and pass an invalid physical address (e.g. 
#define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
invalid translations.

Another alternative that just occurred to me would be to move
the pci_address_to_pio() call from __of_address_to_resource()
into of_bus_pci_translate() and then do the special handling
for the ISA/LPC bus in of_bus_isa_translate().

	Arnd

_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23  9:51                               ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23  9:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> For this patch sketch, I have a question.
> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
> corresponding logical IO port
> for LPC??


No, of course not, that would be silly:

The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
have one because there is no address associated with your PIO, that
is the entire point of your driver!

Also, we already know the mapping because this is what the inb/outb
workaround is looking at, so there is absolutely no reason to call it
either.

> If we don't, it seems the LPC specific IO address will conflict with PCI 
> host bridges' logical IO.
>
> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
> normal for ISA similar
> devices), after arch_of_address_to_pio(), the r->start will be set as 
> 0x100, r->end will be set as
> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
> over 0x400 at the same
> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
> after of_address_to_resource
> for this host bridge.  Then the IO conflict happens.

You would still need to reserve some space in the io_range_list
to avoid possible conflicts, which is a bit ugly with the current
definition of pci_register_io_range, but I'm sure can be done.

One way I can think of would be to change pci_register_io_range()
to just return the logical port number directly (it already
knows it!), and pass an invalid physical address (e.g. 
#define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
invalid translations.

Another alternative that just occurred to me would be to move
the pci_address_to_pio() call from __of_address_to_resource()
into of_bus_pci_translate() and then do the special handling
for the ISA/LPC bus in of_bus_isa_translate().

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23  9:51                               ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-23 10:23                                 ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 10:23 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 September 2016 10:52
> To: zhichang.yuan
> Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > For this patch sketch, I have a question.
> > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > corresponding logical IO port
> > for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.

Ok assume that we do not call pci_address_to_pio() for the ISA bus...
The LPC driver will register its phys address range in io_range_list,
then the IPMI driver probe will retrieve its physical address calling
of_address_to_resource and will use the indirect io to access this
address.

>From the perspective of the indirect IO function the input parameter
is an unsigned long addr that (now) can be either:
1) an IO token coming from a legacy pci device
2) a phys address that lives on the LPC bus

These are conceptually two separate address spaces (and actually they 
both start from 0).

If the input parameter can live on different address spaces that are
overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
there is no way for the indirect IO to tell if the input parameter is
an I/O token or a phys address that belongs to LPC...  

Am I missing something?

Thanks

Gab

> 
> > If we don't, it seems the LPC specific IO address will conflict with
> PCI
> > host bridges' logical IO.
> >
> > Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is
> > normal for ISA similar
> > devices), after arch_of_address_to_pio(), the r->start will be set as
> > 0x100, r->end will be set as
> > 0x3FF.  And if there is one PCI host bridge who request a IO window
> size
> > over 0x400 at the same
> > time, the  corresponding r->start and r->end will be set as 0x0,
> 0x3FF
> > after of_address_to_resource
> > for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 
> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g.
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 
> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 10:23                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 10:23 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 23 September 2016 10:52
> To: zhichang.yuan
> Cc: Gabriele Paoloni; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org;
> linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org; John Garry;
> will.deacon-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> kantyzc-9Onoh4P/yGk@public.gmane.org
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > For this patch sketch, I have a question.
> > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > corresponding logical IO port
> > for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.

Ok assume that we do not call pci_address_to_pio() for the ISA bus...
The LPC driver will register its phys address range in io_range_list,
then the IPMI driver probe will retrieve its physical address calling
of_address_to_resource and will use the indirect io to access this
address.

>From the perspective of the indirect IO function the input parameter
is an unsigned long addr that (now) can be either:
1) an IO token coming from a legacy pci device
2) a phys address that lives on the LPC bus

These are conceptually two separate address spaces (and actually they 
both start from 0).

If the input parameter can live on different address spaces that are
overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
there is no way for the indirect IO to tell if the input parameter is
an I/O token or a phys address that belongs to LPC...  

Am I missing something?

Thanks

Gab

> 
> > If we don't, it seems the LPC specific IO address will conflict with
> PCI
> > host bridges' logical IO.
> >
> > Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is
> > normal for ISA similar
> > devices), after arch_of_address_to_pio(), the r->start will be set as
> > 0x100, r->end will be set as
> > 0x3FF.  And if there is one PCI host bridge who request a IO window
> size
> > over 0x400 at the same
> > time, the  corresponding r->start and r->end will be set as 0x0,
> 0x3FF
> > after of_address_to_resource
> > for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 
> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g.
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 
> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().
> 
> 	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 10:23                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 10:23 UTC (permalink / raw)
  To: Arnd Bergmann, zhichang.yuan
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 September 2016 10:52
> To: zhichang.yuan
> Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > For this patch sketch, I have a question.
> > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > corresponding logical IO port
> > for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.

Ok assume that we do not call pci_address_to_pio() for the ISA bus...
The LPC driver will register its phys address range in io_range_list,
then the IPMI driver probe will retrieve its physical address calling
of_address_to_resource and will use the indirect io to access this
address.

>From the perspective of the indirect IO function the input parameter
is an unsigned long addr that (now) can be either:
1) an IO token coming from a legacy pci device
2) a phys address that lives on the LPC bus

These are conceptually two separate address spaces (and actually they 
both start from 0).

If the input parameter can live on different address spaces that are
overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
there is no way for the indirect IO to tell if the input parameter is
an I/O token or a phys address that belongs to LPC...  

Am I missing something?

Thanks

Gab

> 
> > If we don't, it seems the LPC specific IO address will conflict with
> PCI
> > host bridges' logical IO.
> >
> > Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is
> > normal for ISA similar
> > devices), after arch_of_address_to_pio(), the r->start will be set as
> > 0x100, r->end will be set as
> > 0x3FF.  And if there is one PCI host bridge who request a IO window
> size
> > over 0x400 at the same
> > time, the  corresponding r->start and r->end will be set as 0x0,
> 0x3FF
> > after of_address_to_resource
> > for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 
> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g.
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 
> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().
> 
> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 10:23                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 10:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 23 September 2016 10:52
> To: zhichang.yuan
> Cc: Gabriele Paoloni; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > For this patch sketch, I have a question.
> > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > corresponding logical IO port
> > for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.

Ok assume that we do not call pci_address_to_pio() for the ISA bus...
The LPC driver will register its phys address range in io_range_list,
then the IPMI driver probe will retrieve its physical address calling
of_address_to_resource and will use the indirect io to access this
address.

>From the perspective of the indirect IO function the input parameter
is an unsigned long addr that (now) can be either:
1) an IO token coming from a legacy pci device
2) a phys address that lives on the LPC bus

These are conceptually two separate address spaces (and actually they 
both start from 0).

If the input parameter can live on different address spaces that are
overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
there is no way for the indirect IO to tell if the input parameter is
an I/O token or a phys address that belongs to LPC...  

Am I missing something?

Thanks

Gab

> 
> > If we don't, it seems the LPC specific IO address will conflict with
> PCI
> > host bridges' logical IO.
> >
> > Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is
> > normal for ISA similar
> > devices), after arch_of_address_to_pio(), the r->start will be set as
> > 0x100, r->end will be set as
> > 0x3FF.  And if there is one PCI host bridge who request a IO window
> size
> > over 0x400 at the same
> > time, the  corresponding r->start and r->end will be set as 0x0,
> 0x3FF
> > after of_address_to_resource
> > for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 
> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g.
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 
> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23 10:23                                 ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-23 13:42                                   ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 13:42 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > Sent: 23 September 2016 10:52
> > To: zhichang.yuan
> > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> > kantyzc@163.com
> > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > For this patch sketch, I have a question.
> > > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > > corresponding logical IO port
> > > for LPC??
> > 
> > 
> > No, of course not, that would be silly:
> > 
> > The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> > have one because there is no address associated with your PIO, that
> > is the entire point of your driver!
> > 
> > Also, we already know the mapping because this is what the inb/outb
> > workaround is looking at, so there is absolutely no reason to call it
> > either.
> 
> Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> The LPC driver will register its phys address range in io_range_list,
> then the IPMI driver probe will retrieve its physical address calling
> of_address_to_resource and will use the indirect io to access this
> address.
> 
> From the perspective of the indirect IO function the input parameter
> is an unsigned long addr that (now) can be either:
> 1) an IO token coming from a legacy pci device
> 2) a phys address that lives on the LPC bus
> 
> These are conceptually two separate address spaces (and actually they 
> both start from 0).

Why? Any IORESOURCE_IO address always refers to the logical I/O port
range in Linux, not the physical address that is used on a bus.

> If the input parameter can live on different address spaces that are
> overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
> there is no way for the indirect IO to tell if the input parameter is
> an I/O token or a phys address that belongs to LPC...  

The start address is the offset: if you get an address between 'start'
and 'end', you subtract the 'start' from it, and use that to call
the registered driver function. That works because we can safely
assume that the bus address range that the LPC driver registers starts
zero.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 13:42                                   ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 13:42 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh

On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > Sent: 23 September 2016 10:52
> > To: zhichang.yuan
> > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> > kantyzc@163.com
> > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > For this patch sketch, I have a question.
> > > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > > corresponding logical IO port
> > > for LPC??
> > 
> > 
> > No, of course not, that would be silly:
> > 
> > The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> > have one because there is no address associated with your PIO, that
> > is the entire point of your driver!
> > 
> > Also, we already know the mapping because this is what the inb/outb
> > workaround is looking at, so there is absolutely no reason to call it
> > either.
> 
> Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> The LPC driver will register its phys address range in io_range_list,
> then the IPMI driver probe will retrieve its physical address calling
> of_address_to_resource and will use the indirect io to access this
> address.
> 
> From the perspective of the indirect IO function the input parameter
> is an unsigned long addr that (now) can be either:
> 1) an IO token coming from a legacy pci device
> 2) a phys address that lives on the LPC bus
> 
> These are conceptually two separate address spaces (and actually they 
> both start from 0).

Why? Any IORESOURCE_IO address always refers to the logical I/O port
range in Linux, not the physical address that is used on a bus.

> If the input parameter can live on different address spaces that are
> overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
> there is no way for the indirect IO to tell if the input parameter is
> an I/O token or a phys address that belongs to LPC...  

The start address is the offset: if you get an address between 'start'
and 'end', you subtract the 'start' from it, and use that to call
the registered driver function. That works because we can safely
assume that the bus address range that the LPC driver registers starts
zero.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 13:42                                   ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 13:42 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > Sent: 23 September 2016 10:52
> > To: zhichang.yuan
> > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> > kantyzc@163.com
> > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > For this patch sketch, I have a question.
> > > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > > corresponding logical IO port
> > > for LPC??
> > 
> > 
> > No, of course not, that would be silly:
> > 
> > The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> > have one because there is no address associated with your PIO, that
> > is the entire point of your driver!
> > 
> > Also, we already know the mapping because this is what the inb/outb
> > workaround is looking at, so there is absolutely no reason to call it
> > either.
> 
> Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> The LPC driver will register its phys address range in io_range_list,
> then the IPMI driver probe will retrieve its physical address calling
> of_address_to_resource and will use the indirect io to access this
> address.
> 
> From the perspective of the indirect IO function the input parameter
> is an unsigned long addr that (now) can be either:
> 1) an IO token coming from a legacy pci device
> 2) a phys address that lives on the LPC bus
> 
> These are conceptually two separate address spaces (and actually they 
> both start from 0).

Why? Any IORESOURCE_IO address always refers to the logical I/O port
range in Linux, not the physical address that is used on a bus.

> If the input parameter can live on different address spaces that are
> overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
> there is no way for the indirect IO to tell if the input parameter is
> an I/O token or a phys address that belongs to LPC...  

The start address is the offset: if you get an address between 'start'
and 'end', you subtract the 'start' from it, and use that to call
the registered driver function. That works because we can safely
assume that the bus address range that the LPC driver registers starts
zero.

	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 13:42                                   ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 13:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > Sent: 23 September 2016 10:52
> > To: zhichang.yuan
> > Cc: Gabriele Paoloni; linux-arm-kernel at lists.infradead.org;
> > devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> > linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> > will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> > Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> > benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> > kantyzc at 163.com
> > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > For this patch sketch, I have a question.
> > > Do we call pci_address_to_pio in arch_of_address_to_pio to get the
> > > corresponding logical IO port
> > > for LPC??
> > 
> > 
> > No, of course not, that would be silly:
> > 
> > The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> > have one because there is no address associated with your PIO, that
> > is the entire point of your driver!
> > 
> > Also, we already know the mapping because this is what the inb/outb
> > workaround is looking at, so there is absolutely no reason to call it
> > either.
> 
> Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> The LPC driver will register its phys address range in io_range_list,
> then the IPMI driver probe will retrieve its physical address calling
> of_address_to_resource and will use the indirect io to access this
> address.
> 
> From the perspective of the indirect IO function the input parameter
> is an unsigned long addr that (now) can be either:
> 1) an IO token coming from a legacy pci device
> 2) a phys address that lives on the LPC bus
> 
> These are conceptually two separate address spaces (and actually they 
> both start from 0).

Why? Any IORESOURCE_IO address always refers to the logical I/O port
range in Linux, not the physical address that is used on a bus.

> If the input parameter can live on different address spaces that are
> overlapped, even if I save the used LPC range in arm64_extio_ops->start/end
> there is no way for the indirect IO to tell if the input parameter is
> an I/O token or a phys address that belongs to LPC...  

The start address is the offset: if you get an address between 'start'
and 'end', you subtract the 'start' from it, and use that to call
the registered driver function. That works because we can safely
assume that the bus address range that the LPC driver registers starts
zero.

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23 13:42                                   ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-23 14:59                                     ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 14:59 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com;
> minyard@acm.org;
> > > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > > benh@kernel.crashing.org; zourongrong@gmail.com;
> liviu.dudau@arm.com;
> > > kantyzc@163.com
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.

If I read the code correctly when you get an I/O token you just add it
to PCI_IOBASE.
This is enough since pci_remap_iospace set the virtual address to 
PCI_IOBASE + the I/O token offset; so we can read/write to
vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
to the respective PCI cpu address (that is set in the I/O range property
of the host controller)

In the patchset accessors LPC operates directly on the cpu addresses
and the input parameter of the accessors can be either an IO token or
a cpu address

+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)

Here below we operate on cpu address

+		extio_outb(value, addr);
+	else
+#endif

In the case below we have an I/O token added to PCI_IOBASE
to calculate the virtual address 

+		writeb(value, PCI_IOBASE + addr);
+}

My point is that if do not call pci_address_to_pio() in 
__of_address_to_resource for the ISA LPC exception then the accessors
are called either by passing an IO token or a cpu address...and from
the accessors perspective we do not know...

Thanks
Gab 

> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
> 
> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.
> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 14:59                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 14:59 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org;
> linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org; John Garry;
> will.deacon-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> kantyzc-9Onoh4P/yGk@public.gmane.org
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> > > devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org;
> minyard-HInyCGIudOg@public.gmane.org;
> > > linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org; John Garry;
> > > will.deacon-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > > benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> > > kantyzc-9Onoh4P/yGk@public.gmane.org
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.

If I read the code correctly when you get an I/O token you just add it
to PCI_IOBASE.
This is enough since pci_remap_iospace set the virtual address to 
PCI_IOBASE + the I/O token offset; so we can read/write to
vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
to the respective PCI cpu address (that is set in the I/O range property
of the host controller)

In the patchset accessors LPC operates directly on the cpu addresses
and the input parameter of the accessors can be either an IO token or
a cpu address

+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)

Here below we operate on cpu address

+		extio_outb(value, addr);
+	else
+#endif

In the case below we have an I/O token added to PCI_IOBASE
to calculate the virtual address 

+		writeb(value, PCI_IOBASE + addr);
+}

My point is that if do not call pci_address_to_pio() in 
__of_address_to_resource for the ISA LPC exception then the accessors
are called either by passing an IO token or a cpu address...and from
the accessors perspective we do not know...

Thanks
Gab 

> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
> 
> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.
> 
> 	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 14:59                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 14:59 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com;
> minyard@acm.org;
> > > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > > benh@kernel.crashing.org; zourongrong@gmail.com;
> liviu.dudau@arm.com;
> > > kantyzc@163.com
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.

If I read the code correctly when you get an I/O token you just add it
to PCI_IOBASE.
This is enough since pci_remap_iospace set the virtual address to 
PCI_IOBASE + the I/O token offset; so we can read/write to
vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
to the respective PCI cpu address (that is set in the I/O range property
of the host controller)

In the patchset accessors LPC operates directly on the cpu addresses
and the input parameter of the accessors can be either an IO token or
a cpu address

+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)

Here below we operate on cpu address

+		extio_outb(value, addr);
+	else
+#endif

In the case below we have an I/O token added to PCI_IOBASE
to calculate the virtual address 

+		writeb(value, PCI_IOBASE + addr);
+}

My point is that if do not call pci_address_to_pio() in 
__of_address_to_resource for the ISA LPC exception then the accessors
are called either by passing an IO token or a cpu address...and from
the accessors perspective we do not know...

Thanks
Gab 

> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
> 
> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.
> 
> 	Arnd

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 14:59                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-23 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel at lists.infradead.org;
> > > devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com;
> minyard at acm.org;
> > > linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> > > will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> > > benh at kernel.crashing.org; zourongrong at gmail.com;
> liviu.dudau at arm.com;
> > > kantyzc at 163.com
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.

If I read the code correctly when you get an I/O token you just add it
to PCI_IOBASE.
This is enough since pci_remap_iospace set the virtual address to 
PCI_IOBASE + the I/O token offset; so we can read/write to
vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
to the respective PCI cpu address (that is set in the I/O range property
of the host controller)

In the patchset accessors LPC operates directly on the cpu addresses
and the input parameter of the accessors can be either an IO token or
a cpu address

+static inline void outb(u8 value, unsigned long addr)
+{
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+	if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
+			addr <= arm64_extio_ops->end)

Here below we operate on cpu address

+		extio_outb(value, addr);
+	else
+#endif

In the case below we have an I/O token added to PCI_IOBASE
to calculate the virtual address 

+		writeb(value, PCI_IOBASE + addr);
+}

My point is that if do not call pci_address_to_pio() in 
__of_address_to_resource for the ISA LPC exception then the accessors
are called either by passing an IO token or a cpu address...and from
the accessors perspective we do not know...

Thanks
Gab 

> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
> 
> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.
> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23 14:59                                     ` Gabriele Paoloni
  (?)
  (?)
@ 2016-09-23 15:55                                       ` Arnd Bergmann
  -1 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 15:55 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
> 
> > > From the perspective of the indirect IO function the input parameter
> > > is an unsigned long addr that (now) can be either:
> > > 1) an IO token coming from a legacy pci device
> > > 2) a phys address that lives on the LPC bus
> > >
> > > These are conceptually two separate address spaces (and actually they
> > > both start from 0).
> > 
> > Why? Any IORESOURCE_IO address always refers to the logical I/O port
> > range in Linux, not the physical address that is used on a bus.
> 
> If I read the code correctly when you get an I/O token you just add it
> to PCI_IOBASE.
> This is enough since pci_remap_iospace set the virtual address to 
> PCI_IOBASE + the I/O token offset; so we can read/write to
> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
> to the respective PCI cpu address (that is set in the I/O range property
> of the host controller)
> 
> In the patchset accessors LPC operates directly on the cpu addresses
> and the input parameter of the accessors can be either an IO token or
> a cpu address
> 
> +static inline void outb(u8 value, unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +                       addr <= arm64_extio_ops->end)
> 
> Here below we operate on cpu address
> 
> +               extio_outb(value, addr);
> +       else
> +#endif

I missed this bug earlier, this obviously needs to be

		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);

or possibly

		arm64_extio_ops->outb(arm64_extio_ops, value, addr);

as the outb function won't know what the offset is, but
that needed to be fixed regardless.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 15:55                                       ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 15:55 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh

On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
> 
> > > From the perspective of the indirect IO function the input parameter
> > > is an unsigned long addr that (now) can be either:
> > > 1) an IO token coming from a legacy pci device
> > > 2) a phys address that lives on the LPC bus
> > >
> > > These are conceptually two separate address spaces (and actually they
> > > both start from 0).
> > 
> > Why? Any IORESOURCE_IO address always refers to the logical I/O port
> > range in Linux, not the physical address that is used on a bus.
> 
> If I read the code correctly when you get an I/O token you just add it
> to PCI_IOBASE.
> This is enough since pci_remap_iospace set the virtual address to 
> PCI_IOBASE + the I/O token offset; so we can read/write to
> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
> to the respective PCI cpu address (that is set in the I/O range property
> of the host controller)
> 
> In the patchset accessors LPC operates directly on the cpu addresses
> and the input parameter of the accessors can be either an IO token or
> a cpu address
> 
> +static inline void outb(u8 value, unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +                       addr <= arm64_extio_ops->end)
> 
> Here below we operate on cpu address
> 
> +               extio_outb(value, addr);
> +       else
> +#endif

I missed this bug earlier, this obviously needs to be

		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);

or possibly

		arm64_extio_ops->outb(arm64_extio_ops, value, addr);

as the outb function won't know what the offset is, but
that needed to be fixed regardless.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 15:55                                       ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 15:55 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, linux-pci,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, zhichang.yuan, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel

On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
> 
> > > From the perspective of the indirect IO function the input parameter
> > > is an unsigned long addr that (now) can be either:
> > > 1) an IO token coming from a legacy pci device
> > > 2) a phys address that lives on the LPC bus
> > >
> > > These are conceptually two separate address spaces (and actually they
> > > both start from 0).
> > 
> > Why? Any IORESOURCE_IO address always refers to the logical I/O port
> > range in Linux, not the physical address that is used on a bus.
> 
> If I read the code correctly when you get an I/O token you just add it
> to PCI_IOBASE.
> This is enough since pci_remap_iospace set the virtual address to 
> PCI_IOBASE + the I/O token offset; so we can read/write to
> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
> to the respective PCI cpu address (that is set in the I/O range property
> of the host controller)
> 
> In the patchset accessors LPC operates directly on the cpu addresses
> and the input parameter of the accessors can be either an IO token or
> a cpu address
> 
> +static inline void outb(u8 value, unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +                       addr <= arm64_extio_ops->end)
> 
> Here below we operate on cpu address
> 
> +               extio_outb(value, addr);
> +       else
> +#endif

I missed this bug earlier, this obviously needs to be

		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);

or possibly

		arm64_extio_ops->outb(arm64_extio_ops, value, addr);

as the outb function won't know what the offset is, but
that needed to be fixed regardless.

	Arnd

_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-23 15:55                                       ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-23 15:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
> 
> > > From the perspective of the indirect IO function the input parameter
> > > is an unsigned long addr that (now) can be either:
> > > 1) an IO token coming from a legacy pci device
> > > 2) a phys address that lives on the LPC bus
> > >
> > > These are conceptually two separate address spaces (and actually they
> > > both start from 0).
> > 
> > Why? Any IORESOURCE_IO address always refers to the logical I/O port
> > range in Linux, not the physical address that is used on a bus.
> 
> If I read the code correctly when you get an I/O token you just add it
> to PCI_IOBASE.
> This is enough since pci_remap_iospace set the virtual address to 
> PCI_IOBASE + the I/O token offset; so we can read/write to
> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
> to the respective PCI cpu address (that is set in the I/O range property
> of the host controller)
> 
> In the patchset accessors LPC operates directly on the cpu addresses
> and the input parameter of the accessors can be either an IO token or
> a cpu address
> 
> +static inline void outb(u8 value, unsigned long addr)
> +{
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> +                       addr <= arm64_extio_ops->end)
> 
> Here below we operate on cpu address
> 
> +               extio_outb(value, addr);
> +       else
> +#endif

I missed this bug earlier, this obviously needs to be

		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);

or possibly

		arm64_extio_ops->outb(arm64_extio_ops, value, addr);

as the outb function won't know what the offset is, but
that needed to be fixed regardless.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23  9:51                               ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-24  8:00                                 ` zhichang
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:00 UTC (permalink / raw)
  To: Arnd Bergmann, will.deacon, liviu.dudau, bhelgaas
  Cc: Gabriele Paoloni, linux-arm-kernel, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, gregkh, John Garry,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, kantyzc

Hi, Arnd,


On 2016年09月23日 17:51, Arnd Bergmann wrote:
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
>> For this patch sketch, I have a question.
>> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
>> corresponding logical IO port
>> for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
ok. I think I know you points. The physical addresses of LPC are only the LPC
domain addresses, not the really CPU physical addresses. That is just why you
don't support the ranges property usage in patch V3. Consequently, It is not so
reasonable to call pci_address_to_pio() with LPC address because that function
is only suitable for cpu physical address.

But just as you said in the next email reply to Gabriele, "Any IORESOURCE_IO
address always refers to the logical I/O port range in Linux, not the physical
address that is used on a bus.", Any devices which support IO accesses should
have their own unique logical IO range to drive the corresponding hardware. It
means that the drivers should know the mapping between physical port/memory
address and logical IO depend on the device specific I/O mode. At this moment,
only PCI host bridge setup a logical IO range allocation mechanism to manipulate
this logical IO range, and this way applies cpu physical address(memory) as the
input. Now, our LPC also need subrange from this common logical IO range, but
with legacy I/O port rather than CPU memory address. Ok, it break the
precondition of pci_register_io_range/pci_pio_to_address, we should not use them
directly for LPC although the calling of pci_pio_to_address is simple and less
change on the relevant code. We had done like that in V3...

So, the key issue is how to get a logical IO subrange which is not conflicted
with others, such as pci host bridges??

I list several ideas for discussion:

1. reserve a specific logical IO subrange for LPC

I describe this in "Note 1" below. Please check it.
This way seems simple without much changes, but it is not generic.

2. setup a separate logical IO subrange allocation mechanism specific for LPC/ISA

Just as your suggestion before, add the arch_of_address_to_pio() for the devices
which operate I/O with legacy I/O port address rather than memory address in
MMIO mode. That arch_of_address_to_pio() will return non-conflict logical IO
with PCI host bridge at last. But the logical IO range is global, those
functions for LPC/ISA specific logical IO subrange allocation must be
synchronized with pci_register_io_range/pci_pio_to_address to know what logical
ranges had been populated. It is not good for the implement dispersion on same
issue.

3. setup a new underlying method to control the logical IO range management

Based on the existing resource management, add a simplified logical IO range
management support which only request the logical IO ranges according the IO
range size ( similar to IORESOURCE_SIZEALIGN mode ), no matter what type the
physical address is. Then revise the current pci_register_io_range to adopt this
new method. Of-course, LPC/ISA request the logical IO with this new method too.

This is just a proposition. It is more workload compared with other solutions.

What do you think about these? Any more ideas?


> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.
> 
>> If we don't, it seems the LPC specific IO address will conflict with PCI 
>> host bridges' logical IO.
>>
>> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
>> normal for ISA similar
>> devices), after arch_of_address_to_pio(), the r->start will be set as 
>> 0x100, r->end will be set as
>> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
>> over 0x400 at the same
>> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
>> after of_address_to_resource
>> for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 

Note 1) Do you remember patch V2? There, I modified the pci.c like that to
reserve 0 - PCIBIOS_MIN_IO (it is 0x1000) :

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index aab9d51..ac2e569 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3221,7 +3221,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resourc

 #ifdef PCI_IOBASE
        struct io_range *range;
-       resource_size_t allocated_size = 0;
+       resource_size_t allocated_size = PCIBIOS_MIN_IO;

        /* check if the range hasn't been previously recorded */
        spin_lock(&io_range_lock);
@@ -3270,7 +3270,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)

 #ifdef PCI_IOBASE
        struct io_range *range;
-       resource_size_t allocated_size = 0;
+       resource_size_t allocated_size = PCIBIOS_MIN_IO;

        if (pio > IO_SPACE_LIMIT)
                return address;
@@ -3293,7 +3293,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t addres
 {
 #ifdef PCI_IOBASE
        struct io_range *res;
-       resource_size_t offset = 0;
+       resource_size_t offset = PCIBIOS_MIN_IO;
        unsigned long addr = -1;

        spin_lock(&io_range_lock);

Based on this, a exclusive logical IO subrange is for LPC now. Then we certainly
can add some special handling in __of_address_to_resource or
__of_translate_address --> of_translate_one to return the untranslated LPC/ISA
IO address. But to be honest, I think we don't need this special handling in
address.c anymore. We had known the LPC/ISA IO is 1:1 to logical IO, just think
any logical IO port among 0 - 0x1000 should call the LPC registered I/O hooks in
the new in/out().

Furthermore, we can make the reservation is not fixed as PCIBIOS_MIN_IO. If the
LPC/ISA probing is run before PCI host bridge probing, we can reserve a
non-fixed logcial IO subrange what LPC/ISA ask for.

This solution is based on an assumption that no any other devices have to
request the specific logical IO subrange for LPC/ISA. Probably this assumption
is ok on arm64, you known, there is no real IO space as X86. But anyway, this
reservation is not so generic, depended on some special handling.

Does this idea match your comments??


> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g. 
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 

I am not so clear know your idea here.  Do you want to select an unpopulated CPU
address as the parent address in range property?? or anything else???


> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().

As for this idea, do you mean that of_translate_address will directly return the
final logical IO start address?? It seems to extend the definition of
of_translate_address.


Thanks,
Zhichang

> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24  8:00                                 ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:00 UTC (permalink / raw)
  To: Arnd Bergmann, will.deacon-5wv7dgnIgG8, liviu.dudau-5wv7dgnIgG8,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA
  Cc: Gabriele Paoloni,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, John Garry,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w

Hi, Arnd,


On 2016年09月23日 17:51, Arnd Bergmann wrote:
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
>> For this patch sketch, I have a question.
>> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
>> corresponding logical IO port
>> for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
ok. I think I know you points. The physical addresses of LPC are only the LPC
domain addresses, not the really CPU physical addresses. That is just why you
don't support the ranges property usage in patch V3. Consequently, It is not so
reasonable to call pci_address_to_pio() with LPC address because that function
is only suitable for cpu physical address.

But just as you said in the next email reply to Gabriele, "Any IORESOURCE_IO
address always refers to the logical I/O port range in Linux, not the physical
address that is used on a bus.", Any devices which support IO accesses should
have their own unique logical IO range to drive the corresponding hardware. It
means that the drivers should know the mapping between physical port/memory
address and logical IO depend on the device specific I/O mode. At this moment,
only PCI host bridge setup a logical IO range allocation mechanism to manipulate
this logical IO range, and this way applies cpu physical address(memory) as the
input. Now, our LPC also need subrange from this common logical IO range, but
with legacy I/O port rather than CPU memory address. Ok, it break the
precondition of pci_register_io_range/pci_pio_to_address, we should not use them
directly for LPC although the calling of pci_pio_to_address is simple and less
change on the relevant code. We had done like that in V3...

So, the key issue is how to get a logical IO subrange which is not conflicted
with others, such as pci host bridges??

I list several ideas for discussion:

1. reserve a specific logical IO subrange for LPC

I describe this in "Note 1" below. Please check it.
This way seems simple without much changes, but it is not generic.

2. setup a separate logical IO subrange allocation mechanism specific for LPC/ISA

Just as your suggestion before, add the arch_of_address_to_pio() for the devices
which operate I/O with legacy I/O port address rather than memory address in
MMIO mode. That arch_of_address_to_pio() will return non-conflict logical IO
with PCI host bridge at last. But the logical IO range is global, those
functions for LPC/ISA specific logical IO subrange allocation must be
synchronized with pci_register_io_range/pci_pio_to_address to know what logical
ranges had been populated. It is not good for the implement dispersion on same
issue.

3. setup a new underlying method to control the logical IO range management

Based on the existing resource management, add a simplified logical IO range
management support which only request the logical IO ranges according the IO
range size ( similar to IORESOURCE_SIZEALIGN mode ), no matter what type the
physical address is. Then revise the current pci_register_io_range to adopt this
new method. Of-course, LPC/ISA request the logical IO with this new method too.

This is just a proposition. It is more workload compared with other solutions.

What do you think about these? Any more ideas?


> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.
> 
>> If we don't, it seems the LPC specific IO address will conflict with PCI 
>> host bridges' logical IO.
>>
>> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
>> normal for ISA similar
>> devices), after arch_of_address_to_pio(), the r->start will be set as 
>> 0x100, r->end will be set as
>> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
>> over 0x400 at the same
>> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
>> after of_address_to_resource
>> for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 

Note 1) Do you remember patch V2? There, I modified the pci.c like that to
reserve 0 - PCIBIOS_MIN_IO (it is 0x1000) :

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index aab9d51..ac2e569 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3221,7 +3221,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resourc

 #ifdef PCI_IOBASE
        struct io_range *range;
-       resource_size_t allocated_size = 0;
+       resource_size_t allocated_size = PCIBIOS_MIN_IO;

        /* check if the range hasn't been previously recorded */
        spin_lock(&io_range_lock);
@@ -3270,7 +3270,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)

 #ifdef PCI_IOBASE
        struct io_range *range;
-       resource_size_t allocated_size = 0;
+       resource_size_t allocated_size = PCIBIOS_MIN_IO;

        if (pio > IO_SPACE_LIMIT)
                return address;
@@ -3293,7 +3293,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t addres
 {
 #ifdef PCI_IOBASE
        struct io_range *res;
-       resource_size_t offset = 0;
+       resource_size_t offset = PCIBIOS_MIN_IO;
        unsigned long addr = -1;

        spin_lock(&io_range_lock);

Based on this, a exclusive logical IO subrange is for LPC now. Then we certainly
can add some special handling in __of_address_to_resource or
__of_translate_address --> of_translate_one to return the untranslated LPC/ISA
IO address. But to be honest, I think we don't need this special handling in
address.c anymore. We had known the LPC/ISA IO is 1:1 to logical IO, just think
any logical IO port among 0 - 0x1000 should call the LPC registered I/O hooks in
the new in/out().

Furthermore, we can make the reservation is not fixed as PCIBIOS_MIN_IO. If the
LPC/ISA probing is run before PCI host bridge probing, we can reserve a
non-fixed logcial IO subrange what LPC/ISA ask for.

This solution is based on an assumption that no any other devices have to
request the specific logical IO subrange for LPC/ISA. Probably this assumption
is ok on arm64, you known, there is no real IO space as X86. But anyway, this
reservation is not so generic, depended on some special handling.

Does this idea match your comments??


> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g. 
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 

I am not so clear know your idea here.  Do you want to select an unpopulated CPU
address as the parent address in range property?? or anything else???


> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().

As for this idea, do you mean that of_translate_address will directly return the
final logical IO start address?? It seems to extend the definition of
of_translate_address.


Thanks,
Zhichang

> 
> 	Arnd
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24  8:00                                 ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:00 UTC (permalink / raw)
  To: Arnd Bergmann, will.deacon, liviu.dudau, bhelgaas
  Cc: devicetree, lorenzo.pieralisi, benh, Gabriele Paoloni, minyard,
	linux-pci, John Garry, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, gregkh, zourongrong, kantyzc, linux-arm-kernel

SGksIEFybmQsCgoKT24gMjAxNuW5tDA55pyIMjPml6UgMTc6NTEsIEFybmQgQmVyZ21hbm4gd3Jv
dGU6Cj4gT24gRnJpZGF5LCBTZXB0ZW1iZXIgMjMsIDIwMTYgMTI6Mjc6MTcgQU0gQ0VTVCB6aGlj
aGFuZy55dWFuIHdyb3RlOgo+PiBGb3IgdGhpcyBwYXRjaCBza2V0Y2gsIEkgaGF2ZSBhIHF1ZXN0
aW9uLgo+PiBEbyB3ZSBjYWxsIHBjaV9hZGRyZXNzX3RvX3BpbyBpbiBhcmNoX29mX2FkZHJlc3Nf
dG9fcGlvIHRvIGdldCB0aGUgCj4+IGNvcnJlc3BvbmRpbmcgbG9naWNhbCBJTyBwb3J0Cj4+IGZv
ciBMUEM/Pwo+IAo+IAo+IE5vLCBvZiBjb3Vyc2Ugbm90LCB0aGF0IHdvdWxkIGJlIHNpbGx5Ogo+
IAo+IFRoZSBhcmd1bWVudCB0byBwY2lfYWRkcmVzc190b19waW8oKSBpcyBhIHBoeXNfYWRkcl90
LCBhbmQgd2Ugd2UgZG9uJ3QKPiBoYXZlIG9uZSBiZWNhdXNlIHRoZXJlIGlzIG5vIGFkZHJlc3Mg
YXNzb2NpYXRlZCB3aXRoIHlvdXIgUElPLCB0aGF0Cj4gaXMgdGhlIGVudGlyZSBwb2ludCBvZiB5
b3VyIGRyaXZlciEKPiAKb2suIEkgdGhpbmsgSSBrbm93IHlvdSBwb2ludHMuIFRoZSBwaHlzaWNh
bCBhZGRyZXNzZXMgb2YgTFBDIGFyZSBvbmx5IHRoZSBMUEMKZG9tYWluIGFkZHJlc3Nlcywgbm90
IHRoZSByZWFsbHkgQ1BVIHBoeXNpY2FsIGFkZHJlc3Nlcy4gVGhhdCBpcyBqdXN0IHdoeSB5b3UK
ZG9uJ3Qgc3VwcG9ydCB0aGUgcmFuZ2VzIHByb3BlcnR5IHVzYWdlIGluIHBhdGNoIFYzLiBDb25z
ZXF1ZW50bHksIEl0IGlzIG5vdCBzbwpyZWFzb25hYmxlIHRvIGNhbGwgcGNpX2FkZHJlc3NfdG9f
cGlvKCkgd2l0aCBMUEMgYWRkcmVzcyBiZWNhdXNlIHRoYXQgZnVuY3Rpb24KaXMgb25seSBzdWl0
YWJsZSBmb3IgY3B1IHBoeXNpY2FsIGFkZHJlc3MuCgpCdXQganVzdCBhcyB5b3Ugc2FpZCBpbiB0
aGUgbmV4dCBlbWFpbCByZXBseSB0byBHYWJyaWVsZSwgIkFueSBJT1JFU09VUkNFX0lPCmFkZHJl
c3MgYWx3YXlzIHJlZmVycyB0byB0aGUgbG9naWNhbCBJL08gcG9ydCByYW5nZSBpbiBMaW51eCwg
bm90IHRoZSBwaHlzaWNhbAphZGRyZXNzIHRoYXQgaXMgdXNlZCBvbiBhIGJ1cy4iLCBBbnkgZGV2
aWNlcyB3aGljaCBzdXBwb3J0IElPIGFjY2Vzc2VzIHNob3VsZApoYXZlIHRoZWlyIG93biB1bmlx
dWUgbG9naWNhbCBJTyByYW5nZSB0byBkcml2ZSB0aGUgY29ycmVzcG9uZGluZyBoYXJkd2FyZS4g
SXQKbWVhbnMgdGhhdCB0aGUgZHJpdmVycyBzaG91bGQga25vdyB0aGUgbWFwcGluZyBiZXR3ZWVu
IHBoeXNpY2FsIHBvcnQvbWVtb3J5CmFkZHJlc3MgYW5kIGxvZ2ljYWwgSU8gZGVwZW5kIG9uIHRo
ZSBkZXZpY2Ugc3BlY2lmaWMgSS9PIG1vZGUuIEF0IHRoaXMgbW9tZW50LApvbmx5IFBDSSBob3N0
IGJyaWRnZSBzZXR1cCBhIGxvZ2ljYWwgSU8gcmFuZ2UgYWxsb2NhdGlvbiBtZWNoYW5pc20gdG8g
bWFuaXB1bGF0ZQp0aGlzIGxvZ2ljYWwgSU8gcmFuZ2UsIGFuZCB0aGlzIHdheSBhcHBsaWVzIGNw
dSBwaHlzaWNhbCBhZGRyZXNzKG1lbW9yeSkgYXMgdGhlCmlucHV0LiBOb3csIG91ciBMUEMgYWxz
byBuZWVkIHN1YnJhbmdlIGZyb20gdGhpcyBjb21tb24gbG9naWNhbCBJTyByYW5nZSwgYnV0Cndp
dGggbGVnYWN5IEkvTyBwb3J0IHJhdGhlciB0aGFuIENQVSBtZW1vcnkgYWRkcmVzcy4gT2ssIGl0
IGJyZWFrIHRoZQpwcmVjb25kaXRpb24gb2YgcGNpX3JlZ2lzdGVyX2lvX3JhbmdlL3BjaV9waW9f
dG9fYWRkcmVzcywgd2Ugc2hvdWxkIG5vdCB1c2UgdGhlbQpkaXJlY3RseSBmb3IgTFBDIGFsdGhv
dWdoIHRoZSBjYWxsaW5nIG9mIHBjaV9waW9fdG9fYWRkcmVzcyBpcyBzaW1wbGUgYW5kIGxlc3MK
Y2hhbmdlIG9uIHRoZSByZWxldmFudCBjb2RlLiBXZSBoYWQgZG9uZSBsaWtlIHRoYXQgaW4gVjMu
Li4KClNvLCB0aGUga2V5IGlzc3VlIGlzIGhvdyB0byBnZXQgYSBsb2dpY2FsIElPIHN1YnJhbmdl
IHdoaWNoIGlzIG5vdCBjb25mbGljdGVkCndpdGggb3RoZXJzLCBzdWNoIGFzIHBjaSBob3N0IGJy
aWRnZXM/PwoKSSBsaXN0IHNldmVyYWwgaWRlYXMgZm9yIGRpc2N1c3Npb246CgoxLiByZXNlcnZl
IGEgc3BlY2lmaWMgbG9naWNhbCBJTyBzdWJyYW5nZSBmb3IgTFBDCgpJIGRlc2NyaWJlIHRoaXMg
aW4gIk5vdGUgMSIgYmVsb3cuIFBsZWFzZSBjaGVjayBpdC4KVGhpcyB3YXkgc2VlbXMgc2ltcGxl
IHdpdGhvdXQgbXVjaCBjaGFuZ2VzLCBidXQgaXQgaXMgbm90IGdlbmVyaWMuCgoyLiBzZXR1cCBh
IHNlcGFyYXRlIGxvZ2ljYWwgSU8gc3VicmFuZ2UgYWxsb2NhdGlvbiBtZWNoYW5pc20gc3BlY2lm
aWMgZm9yIExQQy9JU0EKCkp1c3QgYXMgeW91ciBzdWdnZXN0aW9uIGJlZm9yZSwgYWRkIHRoZSBh
cmNoX29mX2FkZHJlc3NfdG9fcGlvKCkgZm9yIHRoZSBkZXZpY2VzCndoaWNoIG9wZXJhdGUgSS9P
IHdpdGggbGVnYWN5IEkvTyBwb3J0IGFkZHJlc3MgcmF0aGVyIHRoYW4gbWVtb3J5IGFkZHJlc3Mg
aW4KTU1JTyBtb2RlLiBUaGF0IGFyY2hfb2ZfYWRkcmVzc190b19waW8oKSB3aWxsIHJldHVybiBu
b24tY29uZmxpY3QgbG9naWNhbCBJTwp3aXRoIFBDSSBob3N0IGJyaWRnZSBhdCBsYXN0LiBCdXQg
dGhlIGxvZ2ljYWwgSU8gcmFuZ2UgaXMgZ2xvYmFsLCB0aG9zZQpmdW5jdGlvbnMgZm9yIExQQy9J
U0Egc3BlY2lmaWMgbG9naWNhbCBJTyBzdWJyYW5nZSBhbGxvY2F0aW9uIG11c3QgYmUKc3luY2hy
b25pemVkIHdpdGggcGNpX3JlZ2lzdGVyX2lvX3JhbmdlL3BjaV9waW9fdG9fYWRkcmVzcyB0byBr
bm93IHdoYXQgbG9naWNhbApyYW5nZXMgaGFkIGJlZW4gcG9wdWxhdGVkLiBJdCBpcyBub3QgZ29v
ZCBmb3IgdGhlIGltcGxlbWVudCBkaXNwZXJzaW9uIG9uIHNhbWUKaXNzdWUuCgozLiBzZXR1cCBh
IG5ldyB1bmRlcmx5aW5nIG1ldGhvZCB0byBjb250cm9sIHRoZSBsb2dpY2FsIElPIHJhbmdlIG1h
bmFnZW1lbnQKCkJhc2VkIG9uIHRoZSBleGlzdGluZyByZXNvdXJjZSBtYW5hZ2VtZW50LCBhZGQg
YSBzaW1wbGlmaWVkIGxvZ2ljYWwgSU8gcmFuZ2UKbWFuYWdlbWVudCBzdXBwb3J0IHdoaWNoIG9u
bHkgcmVxdWVzdCB0aGUgbG9naWNhbCBJTyByYW5nZXMgYWNjb3JkaW5nIHRoZSBJTwpyYW5nZSBz
aXplICggc2ltaWxhciB0byBJT1JFU09VUkNFX1NJWkVBTElHTiBtb2RlICksIG5vIG1hdHRlciB3
aGF0IHR5cGUgdGhlCnBoeXNpY2FsIGFkZHJlc3MgaXMuIFRoZW4gcmV2aXNlIHRoZSBjdXJyZW50
IHBjaV9yZWdpc3Rlcl9pb19yYW5nZSB0byBhZG9wdCB0aGlzCm5ldyBtZXRob2QuIE9mLWNvdXJz
ZSwgTFBDL0lTQSByZXF1ZXN0IHRoZSBsb2dpY2FsIElPIHdpdGggdGhpcyBuZXcgbWV0aG9kIHRv
by4KClRoaXMgaXMganVzdCBhIHByb3Bvc2l0aW9uLiBJdCBpcyBtb3JlIHdvcmtsb2FkIGNvbXBh
cmVkIHdpdGggb3RoZXIgc29sdXRpb25zLgoKV2hhdCBkbyB5b3UgdGhpbmsgYWJvdXQgdGhlc2U/
IEFueSBtb3JlIGlkZWFzPwoKCj4gQWxzbywgd2UgYWxyZWFkeSBrbm93IHRoZSBtYXBwaW5nIGJl
Y2F1c2UgdGhpcyBpcyB3aGF0IHRoZSBpbmIvb3V0Ygo+IHdvcmthcm91bmQgaXMgbG9va2luZyBh
dCwgc28gdGhlcmUgaXMgYWJzb2x1dGVseSBubyByZWFzb24gdG8gY2FsbCBpdAo+IGVpdGhlci4K
PiAKPj4gSWYgd2UgZG9uJ3QsIGl0IHNlZW1zIHRoZSBMUEMgc3BlY2lmaWMgSU8gYWRkcmVzcyB3
aWxsIGNvbmZsaWN0IHdpdGggUENJIAo+PiBob3N0IGJyaWRnZXMnIGxvZ2ljYWwgSU8uCj4+Cj4+
IFN1cHBvc2VkIG91ciBMUEMgcG9wdWxhdGVkIHRoZSBJTyByYW5nZSBmcm9tIDB4MTAwIHRvIDB4
M0ZGKCB0aGlzIGlzIAo+PiBub3JtYWwgZm9yIElTQSBzaW1pbGFyCj4+IGRldmljZXMpLCBhZnRl
ciBhcmNoX29mX2FkZHJlc3NfdG9fcGlvKCksIHRoZSByLT5zdGFydCB3aWxsIGJlIHNldCBhcyAK
Pj4gMHgxMDAsIHItPmVuZCB3aWxsIGJlIHNldCBhcwo+PiAweDNGRi4gIEFuZCBpZiB0aGVyZSBp
cyBvbmUgUENJIGhvc3QgYnJpZGdlIHdobyByZXF1ZXN0IGEgSU8gd2luZG93IHNpemUgCj4+IG92
ZXIgMHg0MDAgYXQgdGhlIHNhbWUKPj4gdGltZSwgdGhlICBjb3JyZXNwb25kaW5nIHItPnN0YXJ0
IGFuZCByLT5lbmQgd2lsbCBiZSBzZXQgYXMgMHgwLCAweDNGRiAKPj4gYWZ0ZXIgb2ZfYWRkcmVz
c190b19yZXNvdXJjZQo+PiBmb3IgdGhpcyBob3N0IGJyaWRnZS4gIFRoZW4gdGhlIElPIGNvbmZs
aWN0IGhhcHBlbnMuCj4gCj4gWW91IHdvdWxkIHN0aWxsIG5lZWQgdG8gcmVzZXJ2ZSBzb21lIHNw
YWNlIGluIHRoZSBpb19yYW5nZV9saXN0Cj4gdG8gYXZvaWQgcG9zc2libGUgY29uZmxpY3RzLCB3
aGljaCBpcyBhIGJpdCB1Z2x5IHdpdGggdGhlIGN1cnJlbnQKPiBkZWZpbml0aW9uIG9mIHBjaV9y
ZWdpc3Rlcl9pb19yYW5nZSwgYnV0IEknbSBzdXJlIGNhbiBiZSBkb25lLgo+IAoKTm90ZSAxKSBE
byB5b3UgcmVtZW1iZXIgcGF0Y2ggVjI/IFRoZXJlLCBJIG1vZGlmaWVkIHRoZSBwY2kuYyBsaWtl
IHRoYXQgdG8KcmVzZXJ2ZSAwIC0gUENJQklPU19NSU5fSU8gKGl0IGlzIDB4MTAwMCkgOgoKZGlm
ZiAtLWdpdCBhL2RyaXZlcnMvcGNpL3BjaS5jIGIvZHJpdmVycy9wY2kvcGNpLmMKaW5kZXggYWFi
OWQ1MS4uYWMyZTU2OSAxMDA2NDQKLS0tIGEvZHJpdmVycy9wY2kvcGNpLmMKKysrIGIvZHJpdmVy
cy9wY2kvcGNpLmMKQEAgLTMyMjEsNyArMzIyMSw3IEBAIGludCBfX3dlYWsgcGNpX3JlZ2lzdGVy
X2lvX3JhbmdlKHBoeXNfYWRkcl90IGFkZHIsIHJlc291cmMKCiAjaWZkZWYgUENJX0lPQkFTRQog
ICAgICAgIHN0cnVjdCBpb19yYW5nZSAqcmFuZ2U7Ci0gICAgICAgcmVzb3VyY2Vfc2l6ZV90IGFs
bG9jYXRlZF9zaXplID0gMDsKKyAgICAgICByZXNvdXJjZV9zaXplX3QgYWxsb2NhdGVkX3NpemUg
PSBQQ0lCSU9TX01JTl9JTzsKCiAgICAgICAgLyogY2hlY2sgaWYgdGhlIHJhbmdlIGhhc24ndCBi
ZWVuIHByZXZpb3VzbHkgcmVjb3JkZWQgKi8KICAgICAgICBzcGluX2xvY2soJmlvX3JhbmdlX2xv
Y2spOwpAQCAtMzI3MCw3ICszMjcwLDcgQEAgcGh5c19hZGRyX3QgcGNpX3Bpb190b19hZGRyZXNz
KHVuc2lnbmVkIGxvbmcgcGlvKQoKICNpZmRlZiBQQ0lfSU9CQVNFCiAgICAgICAgc3RydWN0IGlv
X3JhbmdlICpyYW5nZTsKLSAgICAgICByZXNvdXJjZV9zaXplX3QgYWxsb2NhdGVkX3NpemUgPSAw
OworICAgICAgIHJlc291cmNlX3NpemVfdCBhbGxvY2F0ZWRfc2l6ZSA9IFBDSUJJT1NfTUlOX0lP
OwoKICAgICAgICBpZiAocGlvID4gSU9fU1BBQ0VfTElNSVQpCiAgICAgICAgICAgICAgICByZXR1
cm4gYWRkcmVzczsKQEAgLTMyOTMsNyArMzI5Myw3IEBAIHVuc2lnbmVkIGxvbmcgX193ZWFrIHBj
aV9hZGRyZXNzX3RvX3BpbyhwaHlzX2FkZHJfdCBhZGRyZXMKIHsKICNpZmRlZiBQQ0lfSU9CQVNF
CiAgICAgICAgc3RydWN0IGlvX3JhbmdlICpyZXM7Ci0gICAgICAgcmVzb3VyY2Vfc2l6ZV90IG9m
ZnNldCA9IDA7CisgICAgICAgcmVzb3VyY2Vfc2l6ZV90IG9mZnNldCA9IFBDSUJJT1NfTUlOX0lP
OwogICAgICAgIHVuc2lnbmVkIGxvbmcgYWRkciA9IC0xOwoKICAgICAgICBzcGluX2xvY2soJmlv
X3JhbmdlX2xvY2spOwoKQmFzZWQgb24gdGhpcywgYSBleGNsdXNpdmUgbG9naWNhbCBJTyBzdWJy
YW5nZSBpcyBmb3IgTFBDIG5vdy4gVGhlbiB3ZSBjZXJ0YWlubHkKY2FuIGFkZCBzb21lIHNwZWNp
YWwgaGFuZGxpbmcgaW4gX19vZl9hZGRyZXNzX3RvX3Jlc291cmNlIG9yCl9fb2ZfdHJhbnNsYXRl
X2FkZHJlc3MgLS0+IG9mX3RyYW5zbGF0ZV9vbmUgdG8gcmV0dXJuIHRoZSB1bnRyYW5zbGF0ZWQg
TFBDL0lTQQpJTyBhZGRyZXNzLiBCdXQgdG8gYmUgaG9uZXN0LCBJIHRoaW5rIHdlIGRvbid0IG5l
ZWQgdGhpcyBzcGVjaWFsIGhhbmRsaW5nIGluCmFkZHJlc3MuYyBhbnltb3JlLiBXZSBoYWQga25v
d24gdGhlIExQQy9JU0EgSU8gaXMgMToxIHRvIGxvZ2ljYWwgSU8sIGp1c3QgdGhpbmsKYW55IGxv
Z2ljYWwgSU8gcG9ydCBhbW9uZyAwIC0gMHgxMDAwIHNob3VsZCBjYWxsIHRoZSBMUEMgcmVnaXN0
ZXJlZCBJL08gaG9va3MgaW4KdGhlIG5ldyBpbi9vdXQoKS4KCkZ1cnRoZXJtb3JlLCB3ZSBjYW4g
bWFrZSB0aGUgcmVzZXJ2YXRpb24gaXMgbm90IGZpeGVkIGFzIFBDSUJJT1NfTUlOX0lPLiBJZiB0
aGUKTFBDL0lTQSBwcm9iaW5nIGlzIHJ1biBiZWZvcmUgUENJIGhvc3QgYnJpZGdlIHByb2Jpbmcs
IHdlIGNhbiByZXNlcnZlIGEKbm9uLWZpeGVkIGxvZ2NpYWwgSU8gc3VicmFuZ2Ugd2hhdCBMUEMv
SVNBIGFzayBmb3IuCgpUaGlzIHNvbHV0aW9uIGlzIGJhc2VkIG9uIGFuIGFzc3VtcHRpb24gdGhh
dCBubyBhbnkgb3RoZXIgZGV2aWNlcyBoYXZlIHRvCnJlcXVlc3QgdGhlIHNwZWNpZmljIGxvZ2lj
YWwgSU8gc3VicmFuZ2UgZm9yIExQQy9JU0EuIFByb2JhYmx5IHRoaXMgYXNzdW1wdGlvbgppcyBv
ayBvbiBhcm02NCwgeW91IGtub3duLCB0aGVyZSBpcyBubyByZWFsIElPIHNwYWNlIGFzIFg4Ni4g
QnV0IGFueXdheSwgdGhpcwpyZXNlcnZhdGlvbiBpcyBub3Qgc28gZ2VuZXJpYywgZGVwZW5kZWQg
b24gc29tZSBzcGVjaWFsIGhhbmRsaW5nLgoKRG9lcyB0aGlzIGlkZWEgbWF0Y2ggeW91ciBjb21t
ZW50cz8/CgoKPiBPbmUgd2F5IEkgY2FuIHRoaW5rIG9mIHdvdWxkIGJlIHRvIGNoYW5nZSBwY2lf
cmVnaXN0ZXJfaW9fcmFuZ2UoKQo+IHRvIGp1c3QgcmV0dXJuIHRoZSBsb2dpY2FsIHBvcnQgbnVt
YmVyIGRpcmVjdGx5IChpdCBhbHJlYWR5Cj4ga25vd3MgaXQhKSwgYW5kIHBhc3MgYW4gaW52YWxp
ZCBwaHlzaWNhbCBhZGRyZXNzIChlLmcuIAo+ICNkZWZpbmUgSVNBX1dPUktBUk9VTkRfSU9fUE9S
VF9XSU5ET1cgLTB4MTAwMDApIGludG8gaXQgZm9yCj4gaW52YWxpZCB0cmFuc2xhdGlvbnMuCj4g
CgpJIGFtIG5vdCBzbyBjbGVhciBrbm93IHlvdXIgaWRlYSBoZXJlLiAgRG8geW91IHdhbnQgdG8g
c2VsZWN0IGFuIHVucG9wdWxhdGVkIENQVQphZGRyZXNzIGFzIHRoZSBwYXJlbnQgYWRkcmVzcyBp
biByYW5nZSBwcm9wZXJ0eT8/IG9yIGFueXRoaW5nIGVsc2U/Pz8KCgo+IEFub3RoZXIgYWx0ZXJu
YXRpdmUgdGhhdCBqdXN0IG9jY3VycmVkIHRvIG1lIHdvdWxkIGJlIHRvIG1vdmUKPiB0aGUgcGNp
X2FkZHJlc3NfdG9fcGlvKCkgY2FsbCBmcm9tIF9fb2ZfYWRkcmVzc190b19yZXNvdXJjZSgpCj4g
aW50byBvZl9idXNfcGNpX3RyYW5zbGF0ZSgpIGFuZCB0aGVuIGRvIHRoZSBzcGVjaWFsIGhhbmRs
aW5nCj4gZm9yIHRoZSBJU0EvTFBDIGJ1cyBpbiBvZl9idXNfaXNhX3RyYW5zbGF0ZSgpLgoKQXMg
Zm9yIHRoaXMgaWRlYSwgZG8geW91IG1lYW4gdGhhdCBvZl90cmFuc2xhdGVfYWRkcmVzcyB3aWxs
IGRpcmVjdGx5IHJldHVybiB0aGUKZmluYWwgbG9naWNhbCBJTyBzdGFydCBhZGRyZXNzPz8gSXQg
c2VlbXMgdG8gZXh0ZW5kIHRoZSBkZWZpbml0aW9uIG9mCm9mX3RyYW5zbGF0ZV9hZGRyZXNzLgoK
ClRoYW5rcywKWmhpY2hhbmcKCj4gCj4gCUFybmQKPiAKCl9fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0Cmxp
bnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFk
Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24  8:00                                 ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,


On 2016?09?23? 17:51, Arnd Bergmann wrote:
> On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
>> For this patch sketch, I have a question.
>> Do we call pci_address_to_pio in arch_of_address_to_pio to get the 
>> corresponding logical IO port
>> for LPC??
> 
> 
> No, of course not, that would be silly:
> 
> The argument to pci_address_to_pio() is a phys_addr_t, and we we don't
> have one because there is no address associated with your PIO, that
> is the entire point of your driver!
> 
ok. I think I know you points. The physical addresses of LPC are only the LPC
domain addresses, not the really CPU physical addresses. That is just why you
don't support the ranges property usage in patch V3. Consequently, It is not so
reasonable to call pci_address_to_pio() with LPC address because that function
is only suitable for cpu physical address.

But just as you said in the next email reply to Gabriele, "Any IORESOURCE_IO
address always refers to the logical I/O port range in Linux, not the physical
address that is used on a bus.", Any devices which support IO accesses should
have their own unique logical IO range to drive the corresponding hardware. It
means that the drivers should know the mapping between physical port/memory
address and logical IO depend on the device specific I/O mode. At this moment,
only PCI host bridge setup a logical IO range allocation mechanism to manipulate
this logical IO range, and this way applies cpu physical address(memory) as the
input. Now, our LPC also need subrange from this common logical IO range, but
with legacy I/O port rather than CPU memory address. Ok, it break the
precondition of pci_register_io_range/pci_pio_to_address, we should not use them
directly for LPC although the calling of pci_pio_to_address is simple and less
change on the relevant code. We had done like that in V3...

So, the key issue is how to get a logical IO subrange which is not conflicted
with others, such as pci host bridges??

I list several ideas for discussion:

1. reserve a specific logical IO subrange for LPC

I describe this in "Note 1" below. Please check it.
This way seems simple without much changes, but it is not generic.

2. setup a separate logical IO subrange allocation mechanism specific for LPC/ISA

Just as your suggestion before, add the arch_of_address_to_pio() for the devices
which operate I/O with legacy I/O port address rather than memory address in
MMIO mode. That arch_of_address_to_pio() will return non-conflict logical IO
with PCI host bridge at last. But the logical IO range is global, those
functions for LPC/ISA specific logical IO subrange allocation must be
synchronized with pci_register_io_range/pci_pio_to_address to know what logical
ranges had been populated. It is not good for the implement dispersion on same
issue.

3. setup a new underlying method to control the logical IO range management

Based on the existing resource management, add a simplified logical IO range
management support which only request the logical IO ranges according the IO
range size ( similar to IORESOURCE_SIZEALIGN mode ), no matter what type the
physical address is. Then revise the current pci_register_io_range to adopt this
new method. Of-course, LPC/ISA request the logical IO with this new method too.

This is just a proposition. It is more workload compared with other solutions.

What do you think about these? Any more ideas?


> Also, we already know the mapping because this is what the inb/outb
> workaround is looking at, so there is absolutely no reason to call it
> either.
> 
>> If we don't, it seems the LPC specific IO address will conflict with PCI 
>> host bridges' logical IO.
>>
>> Supposed our LPC populated the IO range from 0x100 to 0x3FF( this is 
>> normal for ISA similar
>> devices), after arch_of_address_to_pio(), the r->start will be set as 
>> 0x100, r->end will be set as
>> 0x3FF.  And if there is one PCI host bridge who request a IO window size 
>> over 0x400 at the same
>> time, the  corresponding r->start and r->end will be set as 0x0, 0x3FF 
>> after of_address_to_resource
>> for this host bridge.  Then the IO conflict happens.
> 
> You would still need to reserve some space in the io_range_list
> to avoid possible conflicts, which is a bit ugly with the current
> definition of pci_register_io_range, but I'm sure can be done.
> 

Note 1) Do you remember patch V2? There, I modified the pci.c like that to
reserve 0 - PCIBIOS_MIN_IO (it is 0x1000) :

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index aab9d51..ac2e569 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3221,7 +3221,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resourc

 #ifdef PCI_IOBASE
        struct io_range *range;
-       resource_size_t allocated_size = 0;
+       resource_size_t allocated_size = PCIBIOS_MIN_IO;

        /* check if the range hasn't been previously recorded */
        spin_lock(&io_range_lock);
@@ -3270,7 +3270,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)

 #ifdef PCI_IOBASE
        struct io_range *range;
-       resource_size_t allocated_size = 0;
+       resource_size_t allocated_size = PCIBIOS_MIN_IO;

        if (pio > IO_SPACE_LIMIT)
                return address;
@@ -3293,7 +3293,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t addres
 {
 #ifdef PCI_IOBASE
        struct io_range *res;
-       resource_size_t offset = 0;
+       resource_size_t offset = PCIBIOS_MIN_IO;
        unsigned long addr = -1;

        spin_lock(&io_range_lock);

Based on this, a exclusive logical IO subrange is for LPC now. Then we certainly
can add some special handling in __of_address_to_resource or
__of_translate_address --> of_translate_one to return the untranslated LPC/ISA
IO address. But to be honest, I think we don't need this special handling in
address.c anymore. We had known the LPC/ISA IO is 1:1 to logical IO, just think
any logical IO port among 0 - 0x1000 should call the LPC registered I/O hooks in
the new in/out().

Furthermore, we can make the reservation is not fixed as PCIBIOS_MIN_IO. If the
LPC/ISA probing is run before PCI host bridge probing, we can reserve a
non-fixed logcial IO subrange what LPC/ISA ask for.

This solution is based on an assumption that no any other devices have to
request the specific logical IO subrange for LPC/ISA. Probably this assumption
is ok on arm64, you known, there is no real IO space as X86. But anyway, this
reservation is not so generic, depended on some special handling.

Does this idea match your comments??


> One way I can think of would be to change pci_register_io_range()
> to just return the logical port number directly (it already
> knows it!), and pass an invalid physical address (e.g. 
> #define ISA_WORKAROUND_IO_PORT_WINDOW -0x10000) into it for
> invalid translations.
> 

I am not so clear know your idea here.  Do you want to select an unpopulated CPU
address as the parent address in range property?? or anything else???


> Another alternative that just occurred to me would be to move
> the pci_address_to_pio() call from __of_address_to_resource()
> into of_bus_pci_translate() and then do the special handling
> for the ISA/LPC bus in of_bus_isa_translate().

As for this idea, do you mean that of_translate_address will directly return the
final logical IO start address?? It seems to extend the definition of
of_translate_address.


Thanks,
Zhichang

> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23 15:55                                       ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-24  8:14                                         ` zhichang
  -1 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:14 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi, Arnd,

On 2016年09月23日 23:55, Arnd Bergmann wrote:
> On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
>>
>>>> From the perspective of the indirect IO function the input parameter
>>>> is an unsigned long addr that (now) can be either:
>>>> 1) an IO token coming from a legacy pci device
>>>> 2) a phys address that lives on the LPC bus
>>>>
>>>> These are conceptually two separate address spaces (and actually they
>>>> both start from 0).
>>>
>>> Why? Any IORESOURCE_IO address always refers to the logical I/O port
>>> range in Linux, not the physical address that is used on a bus.
>>
>> If I read the code correctly when you get an I/O token you just add it
>> to PCI_IOBASE.
>> This is enough since pci_remap_iospace set the virtual address to 
>> PCI_IOBASE + the I/O token offset; so we can read/write to
>> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
>> to the respective PCI cpu address (that is set in the I/O range property
>> of the host controller)
>>
>> In the patchset accessors LPC operates directly on the cpu addresses
>> and the input parameter of the accessors can be either an IO token or
>> a cpu address
>>
>> +static inline void outb(u8 value, unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +                       addr <= arm64_extio_ops->end)
>>
>> Here below we operate on cpu address
>>
>> +               extio_outb(value, addr);
>> +       else
>> +#endif
> 
> I missed this bug earlier, this obviously needs to be
> 
> 		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);
> 
> or possibly
> 
> 		arm64_extio_ops->outb(arm64_extio_ops, value, addr);
> 
> as the outb function won't know what the offset is, but
> that needed to be fixed regardless.

In V3, the outb is :

void outb(u8 value, unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		writeb(value, PCI_IOBASE + addr);
	else
		if (arm64_extio_ops->pfout)
			arm64_extio_ops->pfout(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, &value,
				sizeof(u8), 1);
}

here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
and the logical IO address, similar to the offset of primary address and
secondary address in PCI bridge.

But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
host bridge during its probing.


cheers,
Zhichang



> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24  8:14                                         ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:14 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong

Hi, Arnd,

On 2016年09月23日 23:55, Arnd Bergmann wrote:
> On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
>>
>>>> From the perspective of the indirect IO function the input parameter
>>>> is an unsigned long addr that (now) can be either:
>>>> 1) an IO token coming from a legacy pci device
>>>> 2) a phys address that lives on the LPC bus
>>>>
>>>> These are conceptually two separate address spaces (and actually they
>>>> both start from 0).
>>>
>>> Why? Any IORESOURCE_IO address always refers to the logical I/O port
>>> range in Linux, not the physical address that is used on a bus.
>>
>> If I read the code correctly when you get an I/O token you just add it
>> to PCI_IOBASE.
>> This is enough since pci_remap_iospace set the virtual address to 
>> PCI_IOBASE + the I/O token offset; so we can read/write to
>> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
>> to the respective PCI cpu address (that is set in the I/O range property
>> of the host controller)
>>
>> In the patchset accessors LPC operates directly on the cpu addresses
>> and the input parameter of the accessors can be either an IO token or
>> a cpu address
>>
>> +static inline void outb(u8 value, unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +                       addr <= arm64_extio_ops->end)
>>
>> Here below we operate on cpu address
>>
>> +               extio_outb(value, addr);
>> +       else
>> +#endif
> 
> I missed this bug earlier, this obviously needs to be
> 
> 		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);
> 
> or possibly
> 
> 		arm64_extio_ops->outb(arm64_extio_ops, value, addr);
> 
> as the outb function won't know what the offset is, but
> that needed to be fixed regardless.

In V3, the outb is :

void outb(u8 value, unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		writeb(value, PCI_IOBASE + addr);
	else
		if (arm64_extio_ops->pfout)
			arm64_extio_ops->pfout(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, &value,
				sizeof(u8), 1);
}

here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
and the logical IO address, similar to the offset of primary address and
secondary address in PCI bridge.

But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
host bridge during its probing.


cheers,
Zhichang



> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24  8:14                                         ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:14 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, devicetree, lorenzo.pieralisi, minyard,
	linux-pci, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi, Arnd,

On 2016年09月23日 23:55, Arnd Bergmann wrote:
> On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
>>
>>>> From the perspective of the indirect IO function the input parameter
>>>> is an unsigned long addr that (now) can be either:
>>>> 1) an IO token coming from a legacy pci device
>>>> 2) a phys address that lives on the LPC bus
>>>>
>>>> These are conceptually two separate address spaces (and actually they
>>>> both start from 0).
>>>
>>> Why? Any IORESOURCE_IO address always refers to the logical I/O port
>>> range in Linux, not the physical address that is used on a bus.
>>
>> If I read the code correctly when you get an I/O token you just add it
>> to PCI_IOBASE.
>> This is enough since pci_remap_iospace set the virtual address to 
>> PCI_IOBASE + the I/O token offset; so we can read/write to
>> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
>> to the respective PCI cpu address (that is set in the I/O range property
>> of the host controller)
>>
>> In the patchset accessors LPC operates directly on the cpu addresses
>> and the input parameter of the accessors can be either an IO token or
>> a cpu address
>>
>> +static inline void outb(u8 value, unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +                       addr <= arm64_extio_ops->end)
>>
>> Here below we operate on cpu address
>>
>> +               extio_outb(value, addr);
>> +       else
>> +#endif
> 
> I missed this bug earlier, this obviously needs to be
> 
> 		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);
> 
> or possibly
> 
> 		arm64_extio_ops->outb(arm64_extio_ops, value, addr);
> 
> as the outb function won't know what the offset is, but
> that needed to be fixed regardless.

In V3, the outb is :

void outb(u8 value, unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		writeb(value, PCI_IOBASE + addr);
	else
		if (arm64_extio_ops->pfout)
			arm64_extio_ops->pfout(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, &value,
				sizeof(u8), 1);
}

here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
and the logical IO address, similar to the offset of primary address and
secondary address in PCI bridge.

But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
host bridge during its probing.


cheers,
Zhichang



> 
> 	Arnd
> 

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24  8:14                                         ` zhichang
  0 siblings, 0 replies; 160+ messages in thread
From: zhichang @ 2016-09-24  8:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,

On 2016?09?23? 23:55, Arnd Bergmann wrote:
> On Friday, September 23, 2016 2:59:55 PM CEST Gabriele Paoloni wrote:
>>
>>>> From the perspective of the indirect IO function the input parameter
>>>> is an unsigned long addr that (now) can be either:
>>>> 1) an IO token coming from a legacy pci device
>>>> 2) a phys address that lives on the LPC bus
>>>>
>>>> These are conceptually two separate address spaces (and actually they
>>>> both start from 0).
>>>
>>> Why? Any IORESOURCE_IO address always refers to the logical I/O port
>>> range in Linux, not the physical address that is used on a bus.
>>
>> If I read the code correctly when you get an I/O token you just add it
>> to PCI_IOBASE.
>> This is enough since pci_remap_iospace set the virtual address to 
>> PCI_IOBASE + the I/O token offset; so we can read/write to
>> vaddr = PCI_IOBASE + token as pci_remap_iospace has mapped it correctly
>> to the respective PCI cpu address (that is set in the I/O range property
>> of the host controller)
>>
>> In the patchset accessors LPC operates directly on the cpu addresses
>> and the input parameter of the accessors can be either an IO token or
>> a cpu address
>>
>> +static inline void outb(u8 value, unsigned long addr)
>> +{
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +       if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
>> +                       addr <= arm64_extio_ops->end)
>>
>> Here below we operate on cpu address
>>
>> +               extio_outb(value, addr);
>> +       else
>> +#endif
> 
> I missed this bug earlier, this obviously needs to be
> 
> 		arm64_extio_ops->outb(value, addr - arm64_extio_ops->start);
> 
> or possibly
> 
> 		arm64_extio_ops->outb(arm64_extio_ops, value, addr);
> 
> as the outb function won't know what the offset is, but
> that needed to be fixed regardless.

In V3, the outb is :

void outb(u8 value, unsigned long addr)
{
	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
			arm64_extio_ops->end < addr)
		writeb(value, PCI_IOBASE + addr);
	else
		if (arm64_extio_ops->pfout)
			arm64_extio_ops->pfout(arm64_extio_ops->devpara,
				addr + arm64_extio_ops->ptoffset, &value,
				sizeof(u8), 1);
}

here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
and the logical IO address, similar to the offset of primary address and
secondary address in PCI bridge.

But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
host bridge during its probing.


cheers,
Zhichang



> 
> 	Arnd
> 

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24 21:00                                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-24 21:00 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: zhichang, Gabriele Paoloni, devicetree, lorenzo.pieralisi, benh,
	minyard, gregkh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc

On Saturday, September 24, 2016 4:14:15 PM CEST zhichang wrote:
> 
> In V3, the outb is :
> 
> void outb(u8 value, unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 writeb(value, PCI_IOBASE + addr);
>         else
>                 if (arm64_extio_ops->pfout)
>                         arm64_extio_ops->pfout(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, &value,
>                                 sizeof(u8), 1);
> }
> 
> here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
> and the logical IO address, similar to the offset of primary address and
> secondary address in PCI bridge.

Ok, though we can probably simplify this by making the assumption that
'ptoffset' is the negative of 'start', as the bus we register should
always start at port zero.

> But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
> host bridge during its probing.

Right, so this still needs to be fixed.

	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24 21:00                                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-24 21:00 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: zhichang, Gabriele Paoloni, devicetree-u79uwXL29TY76Z2rM5mHXA,
	lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w

On Saturday, September 24, 2016 4:14:15 PM CEST zhichang wrote:
> 
> In V3, the outb is :
> 
> void outb(u8 value, unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 writeb(value, PCI_IOBASE + addr);
>         else
>                 if (arm64_extio_ops->pfout)
>                         arm64_extio_ops->pfout(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, &value,
>                                 sizeof(u8), 1);
> }
> 
> here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
> and the logical IO address, similar to the offset of primary address and
> secondary address in PCI bridge.

Ok, though we can probably simplify this by making the assumption that
'ptoffset' is the negative of 'start', as the bus we register should
always start at port zero.

> But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
> host bridge during its probing.

Right, so this still needs to be fixed.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24 21:00                                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-24 21:00 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, Gabriele Paoloni, minyard, gregkh,
	linux-pci, benh, John Garry, will.deacon, linux-kernel,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, zhichang, zourongrong, liviu.dudau, kantyzc

On Saturday, September 24, 2016 4:14:15 PM CEST zhichang wrote:
> 
> In V3, the outb is :
> 
> void outb(u8 value, unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 writeb(value, PCI_IOBASE + addr);
>         else
>                 if (arm64_extio_ops->pfout)
>                         arm64_extio_ops->pfout(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, &value,
>                                 sizeof(u8), 1);
> }
> 
> here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
> and the logical IO address, similar to the offset of primary address and
> secondary address in PCI bridge.

Ok, though we can probably simplify this by making the assumption that
'ptoffset' is the negative of 'start', as the bus we register should
always start at port zero.

> But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
> host bridge during its probing.

Right, so this still needs to be fixed.

	Arnd

_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-24 21:00                                           ` Arnd Bergmann
  0 siblings, 0 replies; 160+ messages in thread
From: Arnd Bergmann @ 2016-09-24 21:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday, September 24, 2016 4:14:15 PM CEST zhichang wrote:
> 
> In V3, the outb is :
> 
> void outb(u8 value, unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 writeb(value, PCI_IOBASE + addr);
>         else
>                 if (arm64_extio_ops->pfout)
>                         arm64_extio_ops->pfout(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, &value,
>                                 sizeof(u8), 1);
> }
> 
> here, arm64_extio_ops->ptoffset is the offset between the real legacy IO address
> and the logical IO address, similar to the offset of primary address and
> secondary address in PCI bridge.

Ok, though we can probably simplify this by making the assumption that
'ptoffset' is the negative of 'start', as the bus we register should
always start at port zero.

> But in V3, LPC driver call pci_address_to_pio to request the logical IO as PCI
> host bridge during its probing.

Right, so this still needs to be fixed.

	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-23 13:42                                   ` Arnd Bergmann
  (?)
  (?)
@ 2016-09-26 13:21                                     ` Gabriele Paoloni
  -1 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-26 13:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, linux-arm-kernel, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, gregkh, John Garry, will.deacon,
	linux-kernel, Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial, benh, zourongrong, liviu.dudau, kantyzc

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com;
> minyard@acm.org;
> > > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > > benh@kernel.crashing.org; zourongrong@gmail.com;
> liviu.dudau@arm.com;
> > > kantyzc@163.com
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.
> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
>

Assume that in the probe function the LPC drivers calls pci_register_io_range
for the LPC cpu address range (0 to PCIBIOS_MIN_I0) and does not scan
the children DT nodes.

Consider for example the ipmi driver:
When the reg property is read to retrieve the ipmi <<i/o port>> in
http://lxr.free-electrons.com/source/drivers/char/ipmi/ipmi_si_intf.c#L2622
if we do not call pci_address_to_pio in __of_address_to_resource the input
parameter of inb/outb will be the cpu address of the ipmi (not translated
to a unique token id).

So inb/outb at this stage can be called passing either a cpu address or a
token io port.

If we set arm64_extio_ops->start/end to 0 and PCIBIOS_MIN_I0 respectively
we still cannot tell inside inb/outb if the passed address is a token or
an LPC cpu address as the ipmi cpu address can overlap with another device
I/O token...

My suggestion is to call pci_address_to_pio even for devices living on
the LPC bus; then in the LPC probe we set arm64_extio_ops->start/end to
the I/O tokens that correspond to the LPC cpu address range (in the LPC probe
function we call pci_address_to_pio after we have called pci_register_io_range);
finally in inb/outb we know that we can get only an I/O token as input
parameter and we check it against arm64_extio_ops->start/end to decide
whether to call the LPC accessors or readb/writeb...

> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.

Sorry I cannot follow what you said here above: <<if you get an address 
between 'start' and 'end'>>...in which function?

Thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-26 13:21                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-26 13:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Yuanzhichang, Linuxarm, xuwei (O),
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org;
> linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org; John Garry;
> will.deacon-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> kantyzc-9Onoh4P/yGk@public.gmane.org
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> > > devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org;
> minyard-HInyCGIudOg@public.gmane.org;
> > > linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org; John Garry;
> > > will.deacon-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > > benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> > > kantyzc-9Onoh4P/yGk@public.gmane.org
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.
> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
>

Assume that in the probe function the LPC drivers calls pci_register_io_range
for the LPC cpu address range (0 to PCIBIOS_MIN_I0) and does not scan
the children DT nodes.

Consider for example the ipmi driver:
When the reg property is read to retrieve the ipmi <<i/o port>> in
http://lxr.free-electrons.com/source/drivers/char/ipmi/ipmi_si_intf.c#L2622
if we do not call pci_address_to_pio in __of_address_to_resource the input
parameter of inb/outb will be the cpu address of the ipmi (not translated
to a unique token id).

So inb/outb at this stage can be called passing either a cpu address or a
token io port.

If we set arm64_extio_ops->start/end to 0 and PCIBIOS_MIN_I0 respectively
we still cannot tell inside inb/outb if the passed address is a token or
an LPC cpu address as the ipmi cpu address can overlap with another device
I/O token...

My suggestion is to call pci_address_to_pio even for devices living on
the LPC bus; then in the LPC probe we set arm64_extio_ops->start/end to
the I/O tokens that correspond to the LPC cpu address range (in the LPC probe
function we call pci_address_to_pio after we have called pci_register_io_range);
finally in inb/outb we know that we can get only an I/O token as input
parameter and we check it against arm64_extio_ops->start/end to decide
whether to call the LPC accessors or readb/writeb...

> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.

Sorry I cannot follow what you said here above: <<if you get an address 
between 'start' and 'end'>>...in which function?

Thanks

Gab

> 
> 	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-26 13:21                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-26 13:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: devicetree, lorenzo.pieralisi, benh, minyard, gregkh, linux-pci,
	John Garry, will.deacon, linux-kernel, Yuanzhichang, Linuxarm,
	xuwei (O),
	linux-serial, zhichang.yuan, zourongrong, liviu.dudau, kantyzc,
	linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com; minyard@acm.org;
> linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; zourongrong@gmail.com; liviu.dudau@arm.com;
> kantyzc@163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; lorenzo.pieralisi@arm.com;
> minyard@acm.org;
> > > linux-pci@vger.kernel.org; gregkh@linuxfoundation.org; John Garry;
> > > will.deacon@arm.com; linux-kernel@vger.kernel.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial@vger.kernel.org;
> > > benh@kernel.crashing.org; zourongrong@gmail.com;
> liviu.dudau@arm.com;
> > > kantyzc@163.com
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.
> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
>

Assume that in the probe function the LPC drivers calls pci_register_io_range
for the LPC cpu address range (0 to PCIBIOS_MIN_I0) and does not scan
the children DT nodes.

Consider for example the ipmi driver:
When the reg property is read to retrieve the ipmi <<i/o port>> in
http://lxr.free-electrons.com/source/drivers/char/ipmi/ipmi_si_intf.c#L2622
if we do not call pci_address_to_pio in __of_address_to_resource the input
parameter of inb/outb will be the cpu address of the ipmi (not translated
to a unique token id).

So inb/outb at this stage can be called passing either a cpu address or a
token io port.

If we set arm64_extio_ops->start/end to 0 and PCIBIOS_MIN_I0 respectively
we still cannot tell inside inb/outb if the passed address is a token or
an LPC cpu address as the ipmi cpu address can overlap with another device
I/O token...

My suggestion is to call pci_address_to_pio even for devices living on
the LPC bus; then in the LPC probe we set arm64_extio_ops->start/end to
the I/O tokens that correspond to the LPC cpu address range (in the LPC probe
function we call pci_address_to_pio after we have called pci_register_io_range);
finally in inb/outb we know that we can get only an I/O token as input
parameter and we check it against arm64_extio_ops->start/end to decide
whether to call the LPC accessors or readb/writeb...

> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.

Sorry I cannot follow what you said here above: <<if you get an address 
between 'start' and 'end'>>...in which function?

Thanks

Gab

> 
> 	Arnd

_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-09-26 13:21                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 160+ messages in thread
From: Gabriele Paoloni @ 2016-09-26 13:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 23 September 2016 14:43
> To: Gabriele Paoloni
> Cc: zhichang.yuan; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com; minyard at acm.org;
> linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; zourongrong at gmail.com; liviu.dudau at arm.com;
> kantyzc at 163.com
> Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, September 23, 2016 10:23:30 AM CEST Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > Sent: 23 September 2016 10:52
> > > To: zhichang.yuan
> > > Cc: Gabriele Paoloni; linux-arm-kernel at lists.infradead.org;
> > > devicetree at vger.kernel.org; lorenzo.pieralisi at arm.com;
> minyard at acm.org;
> > > linux-pci at vger.kernel.org; gregkh at linuxfoundation.org; John Garry;
> > > will.deacon at arm.com; linux-kernel at vger.kernel.org; Yuanzhichang;
> > > Linuxarm; xuwei (O); linux-serial at vger.kernel.org;
> > > benh at kernel.crashing.org; zourongrong at gmail.com;
> liviu.dudau at arm.com;
> > > kantyzc at 163.com
> > > Subject: Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Friday, September 23, 2016 12:27:17 AM CEST zhichang.yuan wrote:
> > > > For this patch sketch, I have a question.
> > > > Do we call pci_address_to_pio in arch_of_address_to_pio to get
> the
> > > > corresponding logical IO port
> > > > for LPC??
> > >
> > >
> > > No, of course not, that would be silly:
> > >
> > > The argument to pci_address_to_pio() is a phys_addr_t, and we we
> don't
> > > have one because there is no address associated with your PIO, that
> > > is the entire point of your driver!
> > >
> > > Also, we already know the mapping because this is what the inb/outb
> > > workaround is looking at, so there is absolutely no reason to call
> it
> > > either.
> >
> > Ok assume that we do not call pci_address_to_pio() for the ISA bus...
> > The LPC driver will register its phys address range in io_range_list,
> > then the IPMI driver probe will retrieve its physical address calling
> > of_address_to_resource and will use the indirect io to access this
> > address.
> >
> > From the perspective of the indirect IO function the input parameter
> > is an unsigned long addr that (now) can be either:
> > 1) an IO token coming from a legacy pci device
> > 2) a phys address that lives on the LPC bus
> >
> > These are conceptually two separate address spaces (and actually they
> > both start from 0).
> 
> Why? Any IORESOURCE_IO address always refers to the logical I/O port
> range in Linux, not the physical address that is used on a bus.
> 
> > If the input parameter can live on different address spaces that are
> > overlapped, even if I save the used LPC range in arm64_extio_ops-
> >start/end
> > there is no way for the indirect IO to tell if the input parameter is
> > an I/O token or a phys address that belongs to LPC...
>

Assume that in the probe function the LPC drivers calls pci_register_io_range
for the LPC cpu address range (0 to PCIBIOS_MIN_I0) and does not scan
the children DT nodes.

Consider for example the ipmi driver:
When the reg property is read to retrieve the ipmi <<i/o port>> in
http://lxr.free-electrons.com/source/drivers/char/ipmi/ipmi_si_intf.c#L2622
if we do not call pci_address_to_pio in __of_address_to_resource the input
parameter of inb/outb will be the cpu address of the ipmi (not translated
to a unique token id).

So inb/outb at this stage can be called passing either a cpu address or a
token io port.

If we set arm64_extio_ops->start/end to 0 and PCIBIOS_MIN_I0 respectively
we still cannot tell inside inb/outb if the passed address is a token or
an LPC cpu address as the ipmi cpu address can overlap with another device
I/O token...

My suggestion is to call pci_address_to_pio even for devices living on
the LPC bus; then in the LPC probe we set arm64_extio_ops->start/end to
the I/O tokens that correspond to the LPC cpu address range (in the LPC probe
function we call pci_address_to_pio after we have called pci_register_io_range);
finally in inb/outb we know that we can get only an I/O token as input
parameter and we check it against arm64_extio_ops->start/end to decide
whether to call the LPC accessors or readb/writeb...

> The start address is the offset: if you get an address between 'start'
> and 'end', you subtract the 'start' from it, and use that to call
> the registered driver function. That works because we can safely
> assume that the bus address range that the LPC driver registers starts
> zero.

Sorry I cannot follow what you said here above: <<if you get an address 
between 'start' and 'end'>>...in which function?

Thanks

Gab

> 
> 	Arnd

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-09-14 21:32         ` Arnd Bergmann
  (?)
  (?)
@ 2016-10-02 22:03           ` Jon Masters
  -1 siblings, 0 replies; 160+ messages in thread
From: Jon Masters @ 2016-10-02 22:03 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, benh, john.garry, will.deacon, linux-kernel,
	xuwei5, linuxarm, linux-serial, linux-pci, zourongrong,
	liviu.dudau, kantyzc, zhichang.yuan02

On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:

>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>> operation registering, serial driver has serial_in/serial_out to
>> be registered. So, only the PIO range for ipmi device is stored
>> in arm64_extio_ops and the indirect-IO
>> works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.

Just for the record, Arnd has the right idea. There is only one type of
UART permitted by SBSA (PL011). We carved out an exception for a design
that was already in flight and allowed it to be 16550. That other design
was then corrected in future generations to be PL011 as we required it
to be. Then there's the Hip06. I've given feedback elsewhere about the
need for there to be (at most) two types of UART in the wild. This "LPC"
stuff needs cleaning up (feedback given elsewhere already on that), but
we won't be adding a third serial driver into the mix in order to make
it work. There will be standard ARM servers. There will not be the
kinda-sorta-standard. Thanks.

Jon.

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-02 22:03           ` Jon Masters
  0 siblings, 0 replies; 160+ messages in thread
From: Jon Masters @ 2016-10-02 22:03 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard,
	linux-pci, gregkh, john.garry, will.deacon, linux-kernel,
	zhichang.yuan, linuxarm, xuwei5, linux-serial, benh, zourongrong,
	liviu.dudau, kantyzc, zhichang.yuan02

On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:

>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>> operation registering, serial driver has serial_in/serial_out to
>> be registered. So, only the PIO range for ipmi device is stored
>> in arm64_extio_ops and the indirect-IO
>> works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.

Just for the record, Arnd has the right idea. There is only one type of
UART permitted by SBSA (PL011). We carved out an exception for a design
that was already in flight and allowed it to be 16550. That other design
was then corrected in future generations to be PL011 as we required it
to be. Then there's the Hip06. I've given feedback elsewhere about the
need for there to be (at most) two types of UART in the wild. This "LPC"
stuff needs cleaning up (feedback given elsewhere already on that), but
we won't be adding a third serial driver into the mix in order to make
it work. There will be standard ARM servers. There will not be the
kinda-sorta-standard. Thanks.

Jon.

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-02 22:03           ` Jon Masters
  0 siblings, 0 replies; 160+ messages in thread
From: Jon Masters @ 2016-10-02 22:03 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard,
	linux-pci, gregkh, john.garry, will.deacon, linux-kernel,
	zhichang.yuan, linuxarm, xuwei5, linux-serial, benh, zourongrong,
	liviu.dudau, kantyzc, zhichang.yuan02

On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:

>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>> operation registering, serial driver has serial_in/serial_out to
>> be registered. So, only the PIO range for ipmi device is stored
>> in arm64_extio_ops and the indirect-IO
>> works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.

Just for the record, Arnd has the right idea. There is only one type of
UART permitted by SBSA (PL011). We carved out an exception for a design
that was already in flight and allowed it to be 16550. That other design
was then corrected in future generations to be PL011 as we required it
to be. Then there's the Hip06. I've given feedback elsewhere about the
need for there to be (at most) two types of UART in the wild. This "LPC"
stuff needs cleaning up (feedback given elsewhere already on that), but
we won't be adding a third serial driver into the mix in order to make
it work. There will be standard ARM servers. There will not be the
kinda-sorta-standard. Thanks.

Jon.


_______________________________________________
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] 160+ messages in thread

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-02 22:03           ` Jon Masters
  0 siblings, 0 replies; 160+ messages in thread
From: Jon Masters @ 2016-10-02 22:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:

>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>> operation registering, serial driver has serial_in/serial_out to
>> be registered. So, only the PIO range for ipmi device is stored
>> in arm64_extio_ops and the indirect-IO
>> works well for ipmi device.
> 
> You should not do that in the serial driver, please just use the
> normal 8250 driver that works fine once you handle the entire
> port range.

Just for the record, Arnd has the right idea. There is only one type of
UART permitted by SBSA (PL011). We carved out an exception for a design
that was already in flight and allowed it to be 16550. That other design
was then corrected in future generations to be PL011 as we required it
to be. Then there's the Hip06. I've given feedback elsewhere about the
need for there to be (at most) two types of UART in the wild. This "LPC"
stuff needs cleaning up (feedback given elsewhere already on that), but
we won't be adding a third serial driver into the mix in order to make
it work. There will be standard ARM servers. There will not be the
kinda-sorta-standard. Thanks.

Jon.

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-04 12:02             ` John Garry
  0 siblings, 0 replies; 160+ messages in thread
From: John Garry @ 2016-10-04 12:02 UTC (permalink / raw)
  To: Jon Masters, Arnd Bergmann, linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, benh, will.deacon, linux-kernel, xuwei5,
	linuxarm, linux-serial, linux-pci, zourongrong, liviu.dudau,
	kantyzc, zhichang.yuan02

On 02/10/2016 23:03, Jon Masters wrote:
> On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
>> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
>
>>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>>> operation registering, serial driver has serial_in/serial_out to
>>> be registered. So, only the PIO range for ipmi device is stored
>>> in arm64_extio_ops and the indirect-IO
>>> works well for ipmi device.
>>
>> You should not do that in the serial driver, please just use the
>> normal 8250 driver that works fine once you handle the entire
>> port range.
>
> Just for the record, Arnd has the right idea. There is only one type of
> UART permitted by SBSA (PL011). We carved out an exception for a design
> that was already in flight and allowed it to be 16550. That other design
> was then corrected in future generations to be PL011 as we required it
> to be. Then there's the Hip06. I've given feedback elsewhere about the
> need for there to be (at most) two types of UART in the wild. This "LPC"
> stuff needs cleaning up (feedback given elsewhere already on that), but
> we won't be adding a third serial driver into the mix in order to make
> it work. There will be standard ARM servers. There will not be the
> kinda-sorta-standard. Thanks.
>

Right, so I think Zhichang can make the necessary generic changes to 
8250 OF driver to support IO port as well as MMIO-based.

However an LPC-based earlycon driver is still required.

A note on hip07-based D05 (for those unaware): this does not use 
LPC-based uart. It uses PL011. The hardware guys have managed some 
trickery where they loopback the serial line around the BMC/CPLD. But we 
still need it for hip06 D03 and any other boards which want to use LPC 
bus for uart.

A question on SBSA: does it propose how to provide serial via BMC for SOL?


> Jon.
>
>
> .
>

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-04 12:02             ` John Garry
  0 siblings, 0 replies; 160+ messages in thread
From: John Garry @ 2016-10-04 12:02 UTC (permalink / raw)
  To: Jon Masters, Arnd Bergmann,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: zhichang.yuan, devicetree-u79uwXL29TY76Z2rM5mHXA,
	lorenzo.pieralisi-5wv7dgnIgG8,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA, minyard-HInyCGIudOg,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, will.deacon-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, linuxarm-hv44wF8Li93QT0dZR+AlfA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w, liviu.dudau-5wv7dgnIgG8,
	kantyzc-9Onoh4P/yGk, zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w

On 02/10/2016 23:03, Jon Masters wrote:
> On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
>> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
>
>>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>>> operation registering, serial driver has serial_in/serial_out to
>>> be registered. So, only the PIO range for ipmi device is stored
>>> in arm64_extio_ops and the indirect-IO
>>> works well for ipmi device.
>>
>> You should not do that in the serial driver, please just use the
>> normal 8250 driver that works fine once you handle the entire
>> port range.
>
> Just for the record, Arnd has the right idea. There is only one type of
> UART permitted by SBSA (PL011). We carved out an exception for a design
> that was already in flight and allowed it to be 16550. That other design
> was then corrected in future generations to be PL011 as we required it
> to be. Then there's the Hip06. I've given feedback elsewhere about the
> need for there to be (at most) two types of UART in the wild. This "LPC"
> stuff needs cleaning up (feedback given elsewhere already on that), but
> we won't be adding a third serial driver into the mix in order to make
> it work. There will be standard ARM servers. There will not be the
> kinda-sorta-standard. Thanks.
>

Right, so I think Zhichang can make the necessary generic changes to 
8250 OF driver to support IO port as well as MMIO-based.

However an LPC-based earlycon driver is still required.

A note on hip07-based D05 (for those unaware): this does not use 
LPC-based uart. It uses PL011. The hardware guys have managed some 
trickery where they loopback the serial line around the BMC/CPLD. But we 
still need it for hip06 D03 and any other boards which want to use LPC 
bus for uart.

A question on SBSA: does it propose how to provide serial via BMC for SOL?


> Jon.
>
>
> .
>


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-04 12:02             ` John Garry
  0 siblings, 0 replies; 160+ messages in thread
From: John Garry @ 2016-10-04 12:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/10/2016 23:03, Jon Masters wrote:
> On 09/14/2016 02:32 PM, Arnd Bergmann wrote:
>> On Wednesday, September 14, 2016 10:50:44 PM CEST zhichang.yuan wrote:
>
>>> And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
>>> operation registering, serial driver has serial_in/serial_out to
>>> be registered. So, only the PIO range for ipmi device is stored
>>> in arm64_extio_ops and the indirect-IO
>>> works well for ipmi device.
>>
>> You should not do that in the serial driver, please just use the
>> normal 8250 driver that works fine once you handle the entire
>> port range.
>
> Just for the record, Arnd has the right idea. There is only one type of
> UART permitted by SBSA (PL011). We carved out an exception for a design
> that was already in flight and allowed it to be 16550. That other design
> was then corrected in future generations to be PL011 as we required it
> to be. Then there's the Hip06. I've given feedback elsewhere about the
> need for there to be (at most) two types of UART in the wild. This "LPC"
> stuff needs cleaning up (feedback given elsewhere already on that), but
> we won't be adding a third serial driver into the mix in order to make
> it work. There will be standard ARM servers. There will not be the
> kinda-sorta-standard. Thanks.
>

Right, so I think Zhichang can make the necessary generic changes to 
8250 OF driver to support IO port as well as MMIO-based.

However an LPC-based earlycon driver is still required.

A note on hip07-based D05 (for those unaware): this does not use 
LPC-based uart. It uses PL011. The hardware guys have managed some 
trickery where they loopback the serial line around the BMC/CPLD. But we 
still need it for hip06 D03 and any other boards which want to use LPC 
bus for uart.

A question on SBSA: does it propose how to provide serial via BMC for SOL?


> Jon.
>
>
> .
>

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-10-04 12:02             ` John Garry
  (?)
@ 2016-10-06  0:18               ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 160+ messages in thread
From: Benjamin Herrenschmidt @ 2016-10-06  0:18 UTC (permalink / raw)
  To: John Garry, Jon Masters, Arnd Bergmann, linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, will.deacon, linux-kernel, xuwei5, linuxarm,
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

On Tue, 2016-10-04 at 13:02 +0100, John Garry wrote:
> Right, so I think Zhichang can make the necessary generic changes to 
> 8250 OF driver to support IO port as well as MMIO-based.
> 
> However an LPC-based earlycon driver is still required.
> 
> A note on hip07-based D05 (for those unaware): this does not use 
> LPC-based uart. It uses PL011. The hardware guys have managed some 
> trickery where they loopback the serial line around the BMC/CPLD. But we 
> still need it for hip06 D03 and any other boards which want to use LPC 
> bus for uart.
> 
> A question on SBSA: does it propose how to provide serial via BMC for SOL?

Probably another reason to keep 8250 as a legal option ... The (very
popular) Aspeed BMCs tend to do this via a 8250-looking virtual UART on
LPC.

Cheers,
Ben,

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-06  0:18               ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 160+ messages in thread
From: Benjamin Herrenschmidt @ 2016-10-06  0:18 UTC (permalink / raw)
  To: John Garry, Jon Masters, Arnd Bergmann, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard, gregkh,
	zhichang.yuan02, will.deacon, linux-kernel, zhichang.yuan,
	linuxarm, xuwei5, linux-serial, linux-pci, zourongrong,
	liviu.dudau, kantyzc

T24gVHVlLCAyMDE2LTEwLTA0IGF0IDEzOjAyICswMTAwLCBKb2huIEdhcnJ5IHdyb3RlOgo+IFJp
Z2h0LCBzbyBJIHRoaW5rIFpoaWNoYW5nIGNhbiBtYWtlIHRoZSBuZWNlc3NhcnkgZ2VuZXJpYyBj
aGFuZ2VzIHRvwqAKPiA4MjUwIE9GIGRyaXZlciB0byBzdXBwb3J0IElPIHBvcnQgYXMgd2VsbCBh
cyBNTUlPLWJhc2VkLgo+IAo+IEhvd2V2ZXIgYW4gTFBDLWJhc2VkIGVhcmx5Y29uIGRyaXZlciBp
cyBzdGlsbCByZXF1aXJlZC4KPiAKPiBBIG5vdGUgb24gaGlwMDctYmFzZWQgRDA1IChmb3IgdGhv
c2UgdW5hd2FyZSk6IHRoaXMgZG9lcyBub3QgdXNlwqAKPiBMUEMtYmFzZWQgdWFydC4gSXQgdXNl
cyBQTDAxMS4gVGhlIGhhcmR3YXJlIGd1eXMgaGF2ZSBtYW5hZ2VkIHNvbWXCoAo+IHRyaWNrZXJ5
IHdoZXJlIHRoZXkgbG9vcGJhY2sgdGhlIHNlcmlhbCBsaW5lIGFyb3VuZCB0aGUgQk1DL0NQTEQu
IEJ1dCB3ZcKgCj4gc3RpbGwgbmVlZCBpdCBmb3IgaGlwMDYgRDAzIGFuZCBhbnkgb3RoZXIgYm9h
cmRzIHdoaWNoIHdhbnQgdG8gdXNlIExQQ8KgCj4gYnVzIGZvciB1YXJ0Lgo+IAo+IEEgcXVlc3Rp
b24gb24gU0JTQTogZG9lcyBpdCBwcm9wb3NlIGhvdyB0byBwcm92aWRlIHNlcmlhbCB2aWEgQk1D
IGZvciBTT0w/CgpQcm9iYWJseSBhbm90aGVyIHJlYXNvbiB0byBrZWVwIDgyNTAgYXMgYSBsZWdh
bCBvcHRpb24gLi4uIFRoZSAodmVyeQpwb3B1bGFyKSBBc3BlZWQgQk1DcyB0ZW5kIHRvIGRvIHRo
aXMgdmlhIGEgODI1MC1sb29raW5nIHZpcnR1YWwgVUFSVCBvbgpMUEMuCgpDaGVlcnMsCkJlbiwK
CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1h
cm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5v
cmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0t
a2VybmVsCg==

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-06  0:18               ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 160+ messages in thread
From: Benjamin Herrenschmidt @ 2016-10-06  0:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2016-10-04 at 13:02 +0100, John Garry wrote:
> Right, so I think Zhichang can make the necessary generic changes to?
> 8250 OF driver to support IO port as well as MMIO-based.
> 
> However an LPC-based earlycon driver is still required.
> 
> A note on hip07-based D05 (for those unaware): this does not use?
> LPC-based uart. It uses PL011. The hardware guys have managed some?
> trickery where they loopback the serial line around the BMC/CPLD. But we?
> still need it for hip06 D03 and any other boards which want to use LPC?
> bus for uart.
> 
> A question on SBSA: does it propose how to provide serial via BMC for SOL?

Probably another reason to keep 8250 as a legal option ... The (very
popular) Aspeed BMCs tend to do this via a 8250-looking virtual UART on
LPC.

Cheers,
Ben,

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
  2016-10-06  0:18               ` Benjamin Herrenschmidt
  (?)
@ 2016-10-06 13:31                 ` John Garry
  -1 siblings, 0 replies; 160+ messages in thread
From: John Garry @ 2016-10-06 13:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Jon Masters, Arnd Bergmann, linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, will.deacon, linux-kernel, xuwei5, linuxarm,
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

On 06/10/2016 01:18, Benjamin Herrenschmidt wrote:
> On Tue, 2016-10-04 at 13:02 +0100, John Garry wrote:
>> Right, so I think Zhichang can make the necessary generic changes to
>> 8250 OF driver to support IO port as well as MMIO-based.
>>
>> However an LPC-based earlycon driver is still required.
>>
>> A note on hip07-based D05 (for those unaware): this does not use
>> LPC-based uart. It uses PL011. The hardware guys have managed some
>> trickery where they loopback the serial line around the BMC/CPLD. But we
>> still need it for hip06 D03 and any other boards which want to use LPC
>> bus for uart.
>>
>> A question on SBSA: does it propose how to provide serial via BMC for SOL?
>
> Probably another reason to keep 8250 as a legal option ... The (very
> popular) Aspeed BMCs tend to do this via a 8250-looking virtual UART on
> LPC.
>
> Cheers,
> Ben,

I think we're talking about the same thing for our LPC-based UART.

John

>
>
> .
>

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

* Re: [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-06 13:31                 ` John Garry
  0 siblings, 0 replies; 160+ messages in thread
From: John Garry @ 2016-10-06 13:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Jon Masters, Arnd Bergmann, linux-arm-kernel
  Cc: zhichang.yuan, devicetree, lorenzo.pieralisi, gabriele.paoloni,
	minyard, gregkh, will.deacon, linux-kernel, xuwei5, linuxarm,
	linux-serial, linux-pci, zourongrong, liviu.dudau, kantyzc,
	zhichang.yuan02

On 06/10/2016 01:18, Benjamin Herrenschmidt wrote:
> On Tue, 2016-10-04 at 13:02 +0100, John Garry wrote:
>> Right, so I think Zhichang can make the necessary generic changes to
>> 8250 OF driver to support IO port as well as MMIO-based.
>>
>> However an LPC-based earlycon driver is still required.
>>
>> A note on hip07-based D05 (for those unaware): this does not use
>> LPC-based uart. It uses PL011. The hardware guys have managed some
>> trickery where they loopback the serial line around the BMC/CPLD. But we
>> still need it for hip06 D03 and any other boards which want to use LPC
>> bus for uart.
>>
>> A question on SBSA: does it propose how to provide serial via BMC for SOL?
>
> Probably another reason to keep 8250 as a legal option ... The (very
> popular) Aspeed BMCs tend to do this via a 8250-looking virtual UART on
> LPC.
>
> Cheers,
> Ben,

I think we're talking about the same thing for our LPC-based UART.

John

>
>
> .
>

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

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-10-06 13:31                 ` John Garry
  0 siblings, 0 replies; 160+ messages in thread
From: John Garry @ 2016-10-06 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/10/2016 01:18, Benjamin Herrenschmidt wrote:
> On Tue, 2016-10-04 at 13:02 +0100, John Garry wrote:
>> Right, so I think Zhichang can make the necessary generic changes to
>> 8250 OF driver to support IO port as well as MMIO-based.
>>
>> However an LPC-based earlycon driver is still required.
>>
>> A note on hip07-based D05 (for those unaware): this does not use
>> LPC-based uart. It uses PL011. The hardware guys have managed some
>> trickery where they loopback the serial line around the BMC/CPLD. But we
>> still need it for hip06 D03 and any other boards which want to use LPC
>> bus for uart.
>>
>> A question on SBSA: does it propose how to provide serial via BMC for SOL?
>
> Probably another reason to keep 8250 as a legal option ... The (very
> popular) Aspeed BMCs tend to do this via a 8250-looking virtual UART on
> LPC.
>
> Cheers,
> Ben,

I think we're talking about the same thing for our LPC-based UART.

John

>
>
> .
>

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

end of thread, other threads:[~2016-10-06 13:33 UTC | newest]

Thread overview: 160+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-14 12:15 [PATCH V3 0/4] ARM64 LPC: legacy ISA I/O support Zhichang Yuan
2016-09-14 12:15 ` Zhichang Yuan
2016-09-14 12:15 ` Zhichang Yuan
2016-09-14 12:15 ` [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:24   ` Arnd Bergmann
2016-09-14 12:24     ` Arnd Bergmann
2016-09-14 14:16     ` zhichang.yuan
2016-09-14 14:16       ` zhichang.yuan
2016-09-14 14:16       ` zhichang.yuan
2016-09-14 14:23       ` Arnd Bergmann
2016-09-14 14:23         ` Arnd Bergmann
2016-09-14 14:23         ` Arnd Bergmann
2016-09-18  3:38         ` zhichang
2016-09-18  3:38           ` zhichang
2016-09-18  3:38           ` zhichang
2016-09-21  9:26         ` zhichang
2016-09-21  9:26           ` zhichang
2016-09-21  9:26           ` zhichang
2016-09-14 12:15 ` [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06 Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:33   ` Arnd Bergmann
2016-09-14 12:33     ` Arnd Bergmann
2016-09-14 14:50     ` zhichang.yuan
2016-09-14 14:50       ` zhichang.yuan
2016-09-14 14:50       ` zhichang.yuan
2016-09-14 21:32       ` Arnd Bergmann
2016-09-14 21:32         ` Arnd Bergmann
2016-09-15  8:02         ` Gabriele Paoloni
2016-09-15  8:02           ` Gabriele Paoloni
2016-09-15  8:02           ` Gabriele Paoloni
2016-09-15  8:02           ` Gabriele Paoloni
2016-09-15  8:22           ` Arnd Bergmann
2016-09-15  8:22             ` Arnd Bergmann
2016-09-15  8:22             ` Arnd Bergmann
2016-09-15  8:22             ` Arnd Bergmann
2016-09-15 12:05             ` Gabriele Paoloni
2016-09-15 12:05               ` Gabriele Paoloni
2016-09-15 12:05               ` Gabriele Paoloni
2016-09-15 12:05               ` Gabriele Paoloni
2016-09-15 12:24               ` Arnd Bergmann
2016-09-15 12:24                 ` Arnd Bergmann
2016-09-15 12:24                 ` Arnd Bergmann
2016-09-15 14:28                 ` Gabriele Paoloni
2016-09-15 14:28                   ` Gabriele Paoloni
2016-09-15 14:28                   ` Gabriele Paoloni
2016-09-15 14:28                   ` Gabriele Paoloni
2016-09-21 10:09                 ` zhichang
2016-09-21 10:09                   ` zhichang
2016-09-21 10:09                   ` zhichang
2016-09-21 16:20                   ` Gabriele Paoloni
2016-09-21 16:20                     ` Gabriele Paoloni
2016-09-21 16:20                     ` Gabriele Paoloni
2016-09-21 16:20                     ` Gabriele Paoloni
2016-09-21 20:18                     ` Arnd Bergmann
2016-09-21 20:18                       ` Arnd Bergmann
2016-09-21 20:18                       ` Arnd Bergmann
2016-09-21 20:18                       ` Arnd Bergmann
2016-09-22 11:55                       ` Gabriele Paoloni
2016-09-22 11:55                         ` Gabriele Paoloni
2016-09-22 11:55                         ` Gabriele Paoloni
2016-09-22 11:55                         ` Gabriele Paoloni
2016-09-22 12:14                         ` Arnd Bergmann
2016-09-22 12:14                           ` Arnd Bergmann
2016-09-22 12:14                           ` Arnd Bergmann
2016-09-22 12:14                           ` Arnd Bergmann
2016-09-22 14:47                           ` Gabriele Paoloni
2016-09-22 14:47                             ` Gabriele Paoloni
2016-09-22 14:47                             ` Gabriele Paoloni
2016-09-22 14:47                             ` Gabriele Paoloni
2016-09-22 14:59                             ` Arnd Bergmann
2016-09-22 14:59                               ` Arnd Bergmann
2016-09-22 14:59                               ` Arnd Bergmann
2016-09-22 14:59                               ` Arnd Bergmann
2016-09-22 15:20                               ` Gabriele Paoloni
2016-09-22 15:20                                 ` Gabriele Paoloni
2016-09-22 15:20                                 ` Gabriele Paoloni
2016-09-22 15:20                                 ` Gabriele Paoloni
2016-09-22 15:46                                 ` zhichang.yuan
2016-09-22 15:46                                   ` zhichang.yuan
2016-09-22 15:46                                   ` zhichang.yuan
2016-09-22 15:46                                   ` zhichang.yuan
2016-09-22 16:27                           ` zhichang.yuan
2016-09-22 16:27                             ` zhichang.yuan
2016-09-22 16:27                             ` zhichang.yuan
2016-09-22 16:27                             ` zhichang.yuan
2016-09-23  9:51                             ` Arnd Bergmann
2016-09-23  9:51                               ` Arnd Bergmann
2016-09-23  9:51                               ` Arnd Bergmann
2016-09-23  9:51                               ` Arnd Bergmann
2016-09-23 10:23                               ` Gabriele Paoloni
2016-09-23 10:23                                 ` Gabriele Paoloni
2016-09-23 10:23                                 ` Gabriele Paoloni
2016-09-23 10:23                                 ` Gabriele Paoloni
2016-09-23 13:42                                 ` Arnd Bergmann
2016-09-23 13:42                                   ` Arnd Bergmann
2016-09-23 13:42                                   ` Arnd Bergmann
2016-09-23 13:42                                   ` Arnd Bergmann
2016-09-23 14:59                                   ` Gabriele Paoloni
2016-09-23 14:59                                     ` Gabriele Paoloni
2016-09-23 14:59                                     ` Gabriele Paoloni
2016-09-23 14:59                                     ` Gabriele Paoloni
2016-09-23 15:55                                     ` Arnd Bergmann
2016-09-23 15:55                                       ` Arnd Bergmann
2016-09-23 15:55                                       ` Arnd Bergmann
2016-09-23 15:55                                       ` Arnd Bergmann
2016-09-24  8:14                                       ` zhichang
2016-09-24  8:14                                         ` zhichang
2016-09-24  8:14                                         ` zhichang
2016-09-24  8:14                                         ` zhichang
2016-09-24 21:00                                         ` Arnd Bergmann
2016-09-24 21:00                                           ` Arnd Bergmann
2016-09-24 21:00                                           ` Arnd Bergmann
2016-09-24 21:00                                           ` Arnd Bergmann
2016-09-26 13:21                                   ` Gabriele Paoloni
2016-09-26 13:21                                     ` Gabriele Paoloni
2016-09-26 13:21                                     ` Gabriele Paoloni
2016-09-26 13:21                                     ` Gabriele Paoloni
2016-09-24  8:00                               ` zhichang
2016-09-24  8:00                                 ` zhichang
2016-09-24  8:00                                 ` zhichang
2016-09-24  8:00                                 ` zhichang
2016-10-02 22:03         ` Jon Masters
2016-10-02 22:03           ` Jon Masters
2016-10-02 22:03           ` Jon Masters
2016-10-02 22:03           ` Jon Masters
2016-10-04 12:02           ` John Garry
2016-10-04 12:02             ` John Garry
2016-10-04 12:02             ` John Garry
2016-10-06  0:18             ` Benjamin Herrenschmidt
2016-10-06  0:18               ` Benjamin Herrenschmidt
2016-10-06  0:18               ` Benjamin Herrenschmidt
2016-10-06 13:31               ` John Garry
2016-10-06 13:31                 ` John Garry
2016-10-06 13:31                 ` John Garry
2016-09-14 14:09   ` kbuild test robot
2016-09-14 14:09     ` kbuild test robot
2016-09-14 14:09     ` kbuild test robot
2016-09-14 12:15 ` [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:25   ` Arnd Bergmann
2016-09-14 12:25     ` Arnd Bergmann
2016-09-14 12:25     ` Arnd Bergmann
2016-09-14 15:04     ` zhichang.yuan
2016-09-14 15:04       ` zhichang.yuan
2016-09-14 15:04       ` zhichang.yuan
2016-09-14 21:33       ` Arnd Bergmann
2016-09-14 21:33         ` Arnd Bergmann
2016-09-21 10:12         ` zhichang
2016-09-21 10:12           ` zhichang
2016-09-21 10:12           ` zhichang
2016-09-21 19:29           ` Arnd Bergmann
2016-09-21 19:29             ` Arnd Bergmann
2016-09-21 19:29             ` Arnd Bergmann
2016-09-14 12:15 ` [PATCH V3 4/4] ARM64 LPC: support earlycon for UART connected to LPC Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan
2016-09-14 12:15   ` Zhichang Yuan

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.