All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs
@ 2018-06-12  5:40 Songjun Wu
  2018-06-12  5:40 ` [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial Songjun Wu
                   ` (6 more replies)
  0 siblings, 7 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, Michael Turquette, James Hogan, Stephen Boyd,
	Jiri Slaby, linux-kernel, Thomas Gleixner, Philippe Ombredanne,
	Rob Herring, Kate Stewart, Greg Kroah-Hartman, Mark Rutland,
	Ralf Baechle

This patch series is for adding the support for Intel MIPS interAptiv SoC GRX500 family.
It includes CCF support, serial driver optimization and DTS modification.

This patch series is applied on top of v4.17.1. Basic verification is performed on GRX500 board.
Any comments on this would be appreciated.

We propose merging this patch series into MIPS Linux tree.


Hua Ma (1):
  MIPS: intel: Add initial support for Intel MIPS SoCs

Songjun Wu (5):
  MIPS: dts: Add aliases node for lantiq danube serial
  tty: serial: lantiq: Always use readl()/writel()
  tty: serial: lantiq: Convert global lock to per device lock
  tty: serial: lantiq: Remove unneeded header includes and macros
  tty: serial: lantiq: Add CCF support

Yixin Zhu (1):
  clk: intel: Add clock driver for GRX500 SoC

 .../devicetree/bindings/clock/intel,grx500-clk.txt |  46 ++
 .../devicetree/bindings/serial/lantiq_asc.txt      |  15 +
 arch/mips/Kbuild.platforms                         |   1 +
 arch/mips/Kconfig                                  |  37 +-
 arch/mips/boot/dts/Makefile                        |   1 +
 arch/mips/boot/dts/intel-mips/Makefile             |   3 +
 arch/mips/boot/dts/intel-mips/easy350_anywan.dts   |  20 +
 arch/mips/boot/dts/intel-mips/xrx500.dtsi          | 196 ++++++
 arch/mips/boot/dts/lantiq/danube.dtsi              |   6 +-
 arch/mips/configs/grx500_defconfig                 | 165 +++++
 .../asm/mach-intel-mips/cpu-feature-overrides.h    |  61 ++
 arch/mips/include/asm/mach-intel-mips/ioremap.h    |  39 ++
 arch/mips/include/asm/mach-intel-mips/irq.h        |  17 +
 .../asm/mach-intel-mips/kernel-entry-init.h        |  76 +++
 arch/mips/include/asm/mach-intel-mips/spaces.h     |  29 +
 arch/mips/include/asm/mach-intel-mips/war.h        |  18 +
 arch/mips/intel-mips/Kconfig                       |  22 +
 arch/mips/intel-mips/Makefile                      |   3 +
 arch/mips/intel-mips/Platform                      |  11 +
 arch/mips/intel-mips/irq.c                         |  36 ++
 arch/mips/intel-mips/prom.c                        | 184 ++++++
 arch/mips/intel-mips/time.c                        |  56 ++
 drivers/clk/Kconfig                                |   1 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/intel/Kconfig                          |  21 +
 drivers/clk/intel/Makefile                         |   7 +
 drivers/clk/intel/clk-cgu-api.c                    | 676 +++++++++++++++++++++
 drivers/clk/intel/clk-cgu-api.h                    | 120 ++++
 drivers/clk/intel/clk-grx500.c                     | 236 +++++++
 drivers/tty/serial/Kconfig                         |   2 +-
 drivers/tty/serial/lantiq.c                        | 415 ++++++++-----
 include/dt-bindings/clock/intel,grx500-clk.h       |  61 ++
 32 files changed, 2418 insertions(+), 164 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
 create mode 100644 arch/mips/boot/dts/intel-mips/Makefile
 create mode 100644 arch/mips/boot/dts/intel-mips/easy350_anywan.dts
 create mode 100644 arch/mips/boot/dts/intel-mips/xrx500.dtsi
 create mode 100644 arch/mips/configs/grx500_defconfig
 create mode 100644 arch/mips/include/asm/mach-intel-mips/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/ioremap.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/irq.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/spaces.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/war.h
 create mode 100644 arch/mips/intel-mips/Kconfig
 create mode 100644 arch/mips/intel-mips/Makefile
 create mode 100644 arch/mips/intel-mips/Platform
 create mode 100644 arch/mips/intel-mips/irq.c
 create mode 100644 arch/mips/intel-mips/prom.c
 create mode 100644 arch/mips/intel-mips/time.c
 create mode 100644 drivers/clk/intel/Kconfig
 create mode 100644 drivers/clk/intel/Makefile
 create mode 100644 drivers/clk/intel/clk-cgu-api.c
 create mode 100644 drivers/clk/intel/clk-cgu-api.h
 create mode 100644 drivers/clk/intel/clk-grx500.c
 create mode 100644 include/dt-bindings/clock/intel,grx500-clk.h

-- 
2.11.0


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

* [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12 22:24   ` Rob Herring
  2018-06-14 10:03   ` Arnd Bergmann
  2018-06-12  5:40 ` [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC Songjun Wu
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, James Hogan, linux-kernel, Thomas Gleixner,
	Philippe Ombredanne, Rob Herring, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle

Previous implementation uses a hard-coded register value to check if
the current serial entity is the console entity.
Now the lantiq serial driver uses the aliases for the index of the
serial port.
The lantiq danube serial dts are updated with aliases to support this.

Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
---

 arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi
index 2dd950181f8a..7a9e15da6bd0 100644
--- a/arch/mips/boot/dts/lantiq/danube.dtsi
+++ b/arch/mips/boot/dts/lantiq/danube.dtsi
@@ -4,6 +4,10 @@
 	#size-cells = <1>;
 	compatible = "lantiq,xway", "lantiq,danube";
 
+	aliases {
+		serial0 = &asc1;
+	};
+
 	cpus {
 		cpu@0 {
 			compatible = "mips,mips24Kc";
@@ -74,7 +78,7 @@
 			reg = <0xE100A00 0x100>;
 		};
 
-		serial@E100C00 {
+		asc1: serial@E100C00 {
 			compatible = "lantiq,asc";
 			reg = <0xE100C00 0x400>;
 			interrupt-parent = <&icu0>;
-- 
2.11.0


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

* [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
  2018-06-12  5:40 ` [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12 22:37   ` Rob Herring
  2018-06-12  5:40 ` [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs Songjun Wu
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, Michael Turquette, Stephen Boyd, linux-kernel,
	Rob Herring, Mark Rutland

From: Yixin Zhu <yixin.zhu@linux.intel.com>

PLL of GRX500 provide clock to DDR, CPU, and peripherals as show below

                 +---------+
	    |--->| LCPLL3 0|--PCIe clk-->
   XO       |    +---------+
+-----------|
            |    +---------+
            |    |        3|--PAE clk-->
            |--->| PLL0B  2|--GSWIP clk-->
            |    |        1|--DDR clk-->DDR PHY clk-->
            |    |        0|--CPU1 clk--+   +-----+
            |    +---------+            |--->0    |
            |                               | MUX |--CPU clk-->
            |    +---------+            |--->1    |
            |    |        0|--CPU0 clk--+   +-----+
            |--->| PLLOA  1|--SSX4 clk-->
                 |        2|--NGI clk-->
                 |        3|--CBM clk-->
                 +---------+

VCO of all PLLs of GRX500 is not supposed to be reprogrammed.
DDR PHY clock is created to show correct clock rate in software
point of view.
CPU clock of 1Ghz from PLL0B otherwise from PLL0A.
Signed-off-by: Yixin Zhu <yixin.zhu@linux.intel.com>

Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
---

 .../devicetree/bindings/clock/intel,grx500-clk.txt |  46 ++
 drivers/clk/Kconfig                                |   1 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/intel/Kconfig                          |  21 +
 drivers/clk/intel/Makefile                         |   7 +
 drivers/clk/intel/clk-cgu-api.c                    | 676 +++++++++++++++++++++
 drivers/clk/intel/clk-cgu-api.h                    | 120 ++++
 drivers/clk/intel/clk-grx500.c                     | 236 +++++++
 include/dt-bindings/clock/intel,grx500-clk.h       |  61 ++
 9 files changed, 1169 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
 create mode 100644 drivers/clk/intel/Kconfig
 create mode 100644 drivers/clk/intel/Makefile
 create mode 100644 drivers/clk/intel/clk-cgu-api.c
 create mode 100644 drivers/clk/intel/clk-cgu-api.h
 create mode 100644 drivers/clk/intel/clk-grx500.c
 create mode 100644 include/dt-bindings/clock/intel,grx500-clk.h

diff --git a/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt b/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
new file mode 100644
index 000000000000..dd761d900dc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
@@ -0,0 +1,46 @@
+Device Tree Clock bindings for GRX500 PLL controller.
+
+This binding uses the common clock binding:
+	Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+This GRX500 PLL controller provides the 5 main clock domain of the SoC: CPU/DDR, XBAR,
+Voice, WLAN, PCIe and gate clocks for HW modules.
+
+Required properties for osc clock node
+- compatible: Should be intel,grx500-xxx-clk
+- reg: offset address of the controller memory area.
+- clocks: phandle of the external reference clock
+- #clock-cells: can be one or zero.
+- clock-output-names: Names of the output clocks.
+
+Example:
+	pll0aclk: pll0aclk {
+		#clock-cells = <1>;
+		compatible = "intel,grx500-pll0a-clk";
+		clocks = <&pll0a>;
+		reg = <0x8>;
+		clock-output-names = "cbmclk", "ngiclk", "ssx4clk", "cpu0clk";
+	};
+
+	cpuclk: cpuclk {
+		#clock-cells = <0>;
+		compatible = "intel,grx500-cpu-clk";
+		clocks = <&pll0aclk CPU0_CLK>, <&pll0bclk CPU1_CLK>;
+		reg = <0x8>;
+		clock-output-names = "cpu";
+	};
+
+Required properties for gate node:
+- compatible: Should be intel,grx500-gatex-clk
+- reg: offset address of the controller memory area.
+- #clock-cells: Should be <1>
+- clock-output-names: Names of the output clocks.
+
+Example:
+	clkgate0: clkgate0 {
+		#clock-cells = <1>;
+		compatible = "intel,grx500-gate0-clk";
+		reg = <0x114>;
+		clock-output-names = "gate_xbar0", "gate_xbar1", "gate_xbar2",
+		"gate_xbar3", "gate_xbar6", "gate_xbar7";
+	};
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 34968a381d0f..9e2e19a1170a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -280,6 +280,7 @@ config COMMON_CLK_STM32H7
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
+source "drivers/clk/intel/Kconfig"
 source "drivers/clk/keystone/Kconfig"
 source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/meson/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index de6d06ac790b..ef3e270005a1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -105,3 +105,4 @@ obj-$(CONFIG_X86)			+= x86/
 endif
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
+obj-$(CONFIG_COMMON_CLK_INTEL)		+= intel/
diff --git a/drivers/clk/intel/Kconfig b/drivers/clk/intel/Kconfig
new file mode 100644
index 000000000000..d40a92ae7462
--- /dev/null
+++ b/drivers/clk/intel/Kconfig
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0
+config COMMON_CLK_INTEL
+	depends on COMMON_CLK
+	depends on INTEL_MIPS || COMPILE_TEST
+	select MFD_SYSCON
+	bool "Intel clock controller support"
+	help
+	  This driver support Intel GRX500 crystal oscillator clock
+	  using common clock framework.
+
+choice
+	prompt "SoC platform selection"
+	depends on COMMON_CLK_INTEL
+	default INTEL_GRX500_CLK
+
+config INTEL_GRX500_CLK
+	bool "GRX500 CLK"
+	help
+	  Clock driver of GRX500 platform.
+
+endchoice
diff --git a/drivers/clk/intel/Makefile b/drivers/clk/intel/Makefile
new file mode 100644
index 000000000000..1eaa37f797ea
--- /dev/null
+++ b/drivers/clk/intel/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for intel specific clk
+
+obj-y += clk-cgu-api.o
+ifneq ($(CONFIG_INTEL_GRX500_CLK),)
+	obj-y += clk-grx500.o
+endif
diff --git a/drivers/clk/intel/clk-cgu-api.c b/drivers/clk/intel/clk-cgu-api.c
new file mode 100644
index 000000000000..ab0590cb8b60
--- /dev/null
+++ b/drivers/clk/intel/clk-cgu-api.c
@@ -0,0 +1,676 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2016 Intel Corporation.
+ *  Zhu YiXin <Yixin.zhu@intel.com>
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "clk-cgu-api.h"
+
+#define to_gate_clk(_hw) container_of(_hw, struct gate_clk, hw)
+#define to_clk_gate_dummy(_hw) container_of(_hw, struct gate_dummy_clk, hw)
+#define to_div_clk(_hw) container_of(_hw, struct div_clk, hw)
+#define to_mux_clk(_hw) container_of(_hw, struct mux_clk, hw)
+
+static void set_clk_val(struct regmap *map, u32 reg, u8 shift,
+			u8 width, u32 set_val)
+{
+	u32 mask = GENMASK(width + shift, shift);
+
+	regmap_update_bits(map, reg, mask,
+			   (set_val << shift));
+}
+
+static u32 get_clk_val(struct regmap *map, u32 reg, u8 shift,
+		       u8 width)
+{
+	u32 val;
+
+	regmap_read(map, reg, &val);
+	val >>= shift;
+	val &= (BIT(width) - 1);
+
+	return val;
+}
+
+static struct regmap *regmap_from_node(struct device_node *np)
+{
+	struct regmap *map;
+
+	for ( ; np; ) {
+		np = of_get_parent(np);
+		if (!np)
+			return ERR_PTR(-EINVAL);
+
+		map = syscon_node_to_regmap(np);
+		if (!IS_ERR(map))
+			return map;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+#define GATE_STAT_REG(reg)	(reg)
+#define GATE_EN_REG(reg)	((reg) + 0x4)
+#define GATE_DIS_REG(reg)	((reg) + 0x8)
+
+static int get_gate(struct regmap *map, u32 reg, u8 shift)
+{
+	unsigned int val;
+
+	regmap_read(map, GATE_STAT_REG(reg), &val);
+
+	return !!(val & BIT(shift));
+}
+
+static void set_gate(struct regmap *map, u32 reg, u8 shift, int enable)
+{
+	if (enable)
+		regmap_write(map, GATE_EN_REG(reg), BIT(shift));
+	else
+		regmap_write(map, GATE_DIS_REG(reg), BIT(shift));
+}
+
+void
+intel_fixed_rate_clk_setup(struct device_node *node,
+			   const struct fixed_rate_clk_data *data)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	unsigned long rate;
+	struct regmap *regmap;
+	u32 reg;
+
+	if (!data)
+		return;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	if (of_property_read_u32(node, "clock-frequency", (u32 *)&rate))
+		rate = data->fixed_rate;
+	if (!rate) {
+		pr_err("clk(%s): Could not get fixed rate\n", clk_name);
+		return;
+	}
+
+	regmap = regmap_from_node(node);
+	if (IS_ERR(regmap))
+		return;
+
+	/* Register the fixed rate clock */
+	clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, rate);
+	if (IS_ERR(clk))
+		return;
+
+	/* Clock init */
+	if (of_property_read_u32(node, "reg", &reg)) {
+		pr_err("%s no reg definition\n", node->name);
+		return;
+	}
+
+	set_clk_val(regmap, reg, data->shift, data->width, data->setval);
+
+	/* Register clock provider */
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+static int gate_clk_enable(struct clk_hw *hw)
+{
+	struct gate_clk *clk;
+
+	clk = to_gate_clk(hw);
+	set_gate(clk->map, clk->reg, clk->bit_idx, 1);
+	return 0;
+}
+
+static void gate_clk_disable(struct clk_hw *hw)
+{
+	struct gate_clk *clk;
+
+	clk = to_gate_clk(hw);
+	set_gate(clk->map, clk->reg, clk->bit_idx, 0);
+}
+
+static int gate_clk_is_enabled(struct clk_hw *hw)
+{
+	struct gate_clk *clk;
+
+	clk = to_gate_clk(hw);
+	return get_gate(clk->map, clk->reg, clk->bit_idx);
+}
+
+static const struct clk_ops gate_clk_ops = {
+	.enable = gate_clk_enable,
+	.disable = gate_clk_disable,
+	.is_enabled = gate_clk_is_enabled,
+};
+
+static struct clk *gate_clk_register(struct device *dev, const char *name,
+				     const char *parent_name,
+				     unsigned long flags,
+				     struct regmap *map, unsigned int reg,
+				     u8 bit_idx, unsigned int clk_gate_flags)
+{
+	struct gate_clk *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* Allocate the gate */
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &gate_clk_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* Struct gate_clk assignments */
+	gate->map = map;
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+	gate->hw.init = &init;
+
+	clk = clk_register(dev, &gate->hw);
+	if (IS_ERR(clk)) {
+		pr_err("0x%4x %d %s %d %d %s\n", (u32)reg, init.num_parents,
+		       parent_name, bit_idx, clk_gate_flags, name);
+		kfree(gate);
+	}
+
+	return clk;
+}
+
+void
+intel_gate_clk_setup(struct device_node *node, const struct gate_clk_data *data)
+{
+	struct clk_onecell_data *clk_data;
+	const char *clk_parent;
+	const char *clk_name = node->name;
+	struct regmap *regmap;
+	unsigned int reg;
+	int i, j, num;
+	unsigned int val;
+
+	if (!data || !data->reg_size) {
+		pr_err("%s: register bit size cannot be 0!\n", __func__);
+		return;
+	}
+
+	regmap = regmap_from_node(node);
+	if (IS_ERR(regmap))
+		return;
+
+	if (of_property_read_u32(node, "reg", &reg)) {
+		pr_err("%s no reg definition\n", node->name);
+		return;
+	}
+
+	clk_parent = of_clk_get_parent_name(node, 0);
+
+	/* Size probe and memory allocation */
+	num = find_last_bit(&data->mask, data->reg_size);
+	clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clks = kcalloc(num + 1, sizeof(struct clk *), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto __clkarr_alloc_fail;
+
+	i = 0;
+	j = 0;
+	for_each_set_bit(i, &data->mask, data->reg_size) {
+		of_property_read_string_index(node, "clock-output-names",
+					      j, &clk_name);
+
+		clk_data->clks[j] = gate_clk_register(NULL, clk_name,
+						      clk_parent, 0, regmap,
+						      reg, i, 0);
+		WARN_ON(IS_ERR(clk_data->clks[j]));
+
+		j++;
+	}
+
+	/* Adjust to the real max */
+	clk_data->clk_num = num + 1;
+
+	/* Initial gate default setting */
+	if (data->flags & CLK_INIT_DEF_CFG_REQ) {
+		val = (unsigned int)data->def_onoff;
+		if (val)
+			regmap_write(regmap, GATE_EN_REG(reg), val);
+		val = (((unsigned int)(~data->def_onoff)) & data->mask);
+		if (val)
+			regmap_write(regmap, GATE_DIS_REG(reg), val);
+	}
+
+	/* Register to clock provider */
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	return;
+
+__clkarr_alloc_fail:
+	kfree(clk_data);
+}
+
+static unsigned long div_recalc_rate(struct div_clk *div,
+				     unsigned long parent_rate,
+				     unsigned int val)
+{
+	return divider_recalc_rate(&div->hw, parent_rate,
+			val, div->div_table, div->flags, div->width);
+}
+
+static unsigned long div_clk_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct div_clk *div = to_div_clk(hw);
+	unsigned int val;
+
+	val = get_clk_val(div->map, div->reg, div->shift, div->width);
+
+	return div_recalc_rate(div, parent_rate, val);
+}
+
+static long div_clk_round_rate(struct clk_hw *hw,
+			       unsigned long rate, unsigned long *prate)
+{
+	struct div_clk *div = to_div_clk(hw);
+
+	return divider_round_rate(hw, rate, prate,
+				  div->div_table, div->width, div->flags);
+}
+
+static int div_set_rate(struct div_clk *div, unsigned long rate,
+			unsigned long parent_rate)
+{
+	unsigned int val;
+
+	val = divider_get_val(rate, parent_rate, div->div_table,
+			      div->width, div->flags);
+	set_clk_val(div->map, div->reg, div->shift, div->width, val);
+
+	return 0;
+}
+
+static int div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct div_clk *div = to_div_clk(hw);
+
+	return div_set_rate(div, rate, parent_rate);
+}
+
+static const struct clk_ops clk_div_ops = {
+	.recalc_rate = div_clk_recalc_rate,
+	.round_rate = div_clk_round_rate,
+	.set_rate = div_clk_set_rate,
+};
+
+static struct clk *div_clk_register(struct device *dev, const char *name,
+				    const char *parent_name,
+				    unsigned long flags,
+				    struct regmap *map, unsigned int reg,
+				    const struct div_clk_data *data)
+{
+	struct div_clk *div;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* Allocate the divider clock*/
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_div_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* Struct clk_divider assignments */
+	div->map = map;
+	div->reg = reg;
+	div->shift = data->shift;
+	div->width = data->width;
+	div->flags = data->flags;
+	div->div_table = data->div_table;
+	div->hw.init = &init;
+	div->tbl_sz = data->tbl_sz;
+
+	/* Register the clock */
+	clk = clk_register(dev, &div->hw);
+	if (IS_ERR(clk))
+		kfree(div);
+
+	return clk;
+}
+
+void
+intel_div_clk_setup(struct device_node *node, const struct div_clk_data *data)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	const char *clk_parent;
+	struct regmap *map;
+	unsigned int reg;
+
+	if (!data)
+		return;
+
+	map = regmap_from_node(node);
+	if (IS_ERR(map))
+		return;
+
+	if (of_property_read_u32(node, "reg", &reg)) {
+		pr_err("%s no reg definition\n", node->name);
+		return;
+	}
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+	clk_parent = of_clk_get_parent_name(node, 0);
+
+	clk = div_clk_register(NULL, clk_name, clk_parent, 0, map, reg, data);
+	if (IS_ERR(clk))
+		return;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+void
+intel_cluster_div_clk_setup(struct device_node *node,
+			    const struct div_clk_data *data, u32 num)
+{
+	struct clk_onecell_data *clk_data;
+	const char *clk_name;
+	const char *clk_parent;
+	struct regmap *regmap;
+	unsigned int reg;
+	int i;
+
+	if (!data || !num) {
+		pr_err("%s: invalid array or array size!\n", __func__);
+		return;
+	}
+
+	regmap = regmap_from_node(node);
+	if (IS_ERR(regmap))
+		return;
+
+	if (of_property_read_u32(node, "reg", &reg)) {
+		pr_err("%s no reg definition\n", node->name);
+		return;
+	}
+
+	clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+	clk_data->clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto __clkarr_alloc_fail;
+
+	clk_parent = of_clk_get_parent_name(node, 0);
+
+	for (i = 0; i < num; i++) {
+		of_property_read_string_index(node, "clock-output-names",
+					      i, &clk_name);
+		clk_data->clks[i] = div_clk_register(NULL, clk_name, clk_parent,
+						     0, regmap, reg, &data[i]);
+		WARN_ON(IS_ERR(clk_data->clks[i]));
+	}
+	clk_data->clk_num = num + 1;
+
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	return;
+
+__clkarr_alloc_fail:
+	kfree(clk_data);
+}
+
+static unsigned int mux_parent_from_table(const u32 *table,
+					  unsigned int val, unsigned int num)
+{
+	unsigned int i;
+
+	for (i = 0; i < num; i++)
+		if (table[i] == val)
+			return i;
+
+	return -EINVAL;
+}
+
+static u8 mux_clk_get_parent(struct clk_hw *hw)
+{
+	struct mux_clk *mux = to_mux_clk(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	unsigned int val;
+
+	val = get_clk_val(mux->map, mux->reg, mux->shift, mux->width);
+	if (mux->table)
+		return mux_parent_from_table(mux->table, val, num_parents);
+
+	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+		val = ffs(val) - 1;
+	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+		val -= 1;
+	if (val >= num_parents)
+		return -EINVAL;
+
+	return val;
+}
+
+static int mux_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct mux_clk *mux = to_mux_clk(hw);
+
+	if (mux->table) {
+		index = mux->table[index];
+	} else {
+		if (mux->flags & CLK_MUX_INDEX_BIT)
+			index = BIT(index);
+		if (mux->flags & CLK_MUX_INDEX_ONE)
+			index += 1;
+	}
+
+	set_clk_val(mux->map, mux->reg, mux->shift, mux->width, index);
+
+	return 0;
+}
+
+static const struct clk_ops mux_clk_ops = {
+	.get_parent = mux_clk_get_parent,
+	.set_parent = mux_clk_set_parent,
+	.determine_rate = __clk_mux_determine_rate,
+};
+
+static struct clk *mux_clk_register(struct device *dev, const char *name,
+				    const char * const *parent_names,
+				    u8 num_parents, unsigned long flags,
+				    struct regmap *map, unsigned int reg,
+				    const struct mux_clk_data *data)
+{
+	struct mux_clk *mux;
+	struct clk_init_data init;
+	struct clk *clk;
+
+	/* allocate mux clk */
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return ERR_PTR(-ENOMEM);
+
+	/* struct init assignments */
+	init.name = name;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.ops = &mux_clk_ops;
+
+	/* struct mux_clk assignments */
+	mux->map = map;
+	mux->reg = reg;
+	mux->shift = data->shift;
+	mux->width = data->width;
+	mux->flags = data->clk_flags;
+	mux->table = data->table;
+	mux->hw.init = &init;
+
+	clk = clk_register(dev, &mux->hw);
+	if (IS_ERR(clk))
+		kfree(mux);
+
+	return clk;
+}
+
+void
+intel_mux_clk_setup(struct device_node *node, const struct mux_clk_data *data)
+{
+	struct clk *clk;
+	const char *clk_name;
+	const char **parents;
+	unsigned int num_parents;
+	struct regmap *map;
+	unsigned int reg;
+
+	if (!data)
+		return;
+
+	map = regmap_from_node(node);
+	if (IS_ERR(map))
+		return;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name)) {
+		pr_err("%s: no output clock name!\n", node->name);
+		return;
+	}
+
+	if (of_property_read_u32(node, "reg", &reg)) {
+		pr_err("%s no reg definition\n", node->name);
+		return;
+	}
+
+	num_parents = of_clk_get_parent_count(node);
+	if (num_parents) {
+		parents = kmalloc_array(num_parents,
+					sizeof(char *), GFP_KERNEL);
+		if (!parents)
+			return;
+		of_clk_parent_fill(node, parents, num_parents);
+	} else {
+		pr_err("%s: mux clk no parent!\n", __func__);
+		return;
+	}
+
+	clk = mux_clk_register(NULL, clk_name, parents, num_parents,
+			       data->flags, map, reg, data);
+	if (IS_ERR(clk))
+		goto __mux_clk_fail;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return;
+
+__mux_clk_fail:
+	kfree(parents);
+}
+
+static int gate_clk_dummy_enable(struct clk_hw *hw)
+{
+	struct gate_dummy_clk *clk;
+
+	clk = to_clk_gate_dummy(hw);
+	clk->clk_status = 1;
+
+	return 0;
+}
+
+static void gate_clk_dummy_disable(struct clk_hw *hw)
+{
+	struct gate_dummy_clk *clk;
+
+	clk = to_clk_gate_dummy(hw);
+	clk->clk_status = 0;
+}
+
+static int gate_clk_dummy_is_enabled(struct clk_hw *hw)
+{
+	struct gate_dummy_clk *clk;
+
+	clk = to_clk_gate_dummy(hw);
+	return clk->clk_status;
+}
+
+static const struct clk_ops clk_gate_dummy_ops = {
+	.enable = gate_clk_dummy_enable,
+	.disable = gate_clk_dummy_disable,
+	.is_enabled = gate_clk_dummy_is_enabled,
+};
+
+static struct clk
+*clk_register_gate_dummy(struct device *dev,
+			 const char *name,
+			 const char *parent_name,
+			 unsigned long flags,
+			 const struct gate_dummy_clk_data *data)
+{
+	struct gate_dummy_clk *gate_clk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* Allocate the gate_dummy clock*/
+	gate_clk = kzalloc(sizeof(*gate_clk), GFP_KERNEL);
+	if (!gate_clk)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_gate_dummy_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	gate_clk->hw.init = &init;
+
+	/* Struct gate_clk assignments */
+	if (data->flags & CLK_INIT_DEF_CFG_REQ)
+		gate_clk->clk_status = data->def_val & 0x1;
+
+	/* Register the clock */
+	clk = clk_register(dev, &gate_clk->hw);
+	if (IS_ERR(clk))
+		kfree(gate_clk);
+
+	return clk;
+}
+
+void
+intel_gate_dummy_clk_setup(struct device_node *node,
+			   const struct gate_dummy_clk_data *data)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+
+	if (!data)
+		return;
+
+	if (of_property_read_string(node, "clock-output-names", &clk_name))
+		return;
+
+	clk = clk_register_gate_dummy(NULL, clk_name, NULL, 0, data);
+	if (IS_ERR(clk)) {
+		pr_err("%s: dummy gate clock register fail!\n", __func__);
+		return;
+	}
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
diff --git a/drivers/clk/intel/clk-cgu-api.h b/drivers/clk/intel/clk-cgu-api.h
new file mode 100644
index 000000000000..3a8d7e47ba58
--- /dev/null
+++ b/drivers/clk/intel/clk-cgu-api.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __INTEL_CLK_API_H
+#define __INTEL_CLK_API_H
+
+/*
+ *  Copyright(c) 2016 Intel Corporation.
+ *  Zhu YiXin <Yixin.zhu@intel.com>
+ *
+ */
+
+struct div_clk_data {
+	u8 shift;
+	u8 width;
+	const unsigned int tbl_sz;
+	const struct clk_div_table *div_table;
+	unsigned long flags;
+};
+
+struct mux_clk_data {
+	u8 shift;
+	u8 width;
+	const u32 *table;
+	unsigned long flags;
+	unsigned long clk_flags;
+};
+
+struct gate_clk_data {
+	unsigned long mask;
+	unsigned long def_onoff;
+	u8 reg_size;
+	unsigned long flags;
+};
+
+struct gate_dummy_clk_data {
+	unsigned int def_val;
+	unsigned long flags;
+};
+
+struct fixed_rate_clk_data {
+	u8 shift;
+	u8 width;
+	unsigned long fixed_rate;
+	unsigned int setval;
+};
+
+struct gate_dummy_clk {
+	struct clk_hw hw;
+	unsigned int clk_status;
+};
+
+struct div_clk {
+	struct clk_hw hw;
+	struct regmap *map;
+	unsigned int reg;
+	u8 shift;
+	u8 width;
+	unsigned int flags;
+	const struct clk_div_table *div_table;
+	unsigned int tbl_sz;
+};
+
+struct gate_clk {
+	struct clk_hw hw;
+	struct regmap *map;
+	unsigned int reg;
+	u8 bit_idx;
+	unsigned int flags;
+};
+
+struct mux_clk {
+	struct clk_hw hw;
+	struct regmap *map;
+	unsigned int reg;
+	const u32 *table;
+	u8 shift;
+	u8 width;
+	unsigned int flags;
+};
+
+/**
+ * struct clk_fixed_factor_frac - fixed multiplier/divider/fraction clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @mult:	multiplier(N)
+ * @div:	divider(M)
+ * @frac:	fraction(K)
+ * @frac_div:	fraction divider(D)
+ *
+ * Clock with a fixed multiplier, divider and fraction.
+ * The output frequency formula is clk = parent clk * (N+K/D)/M.
+ * Implements .recalc_rate, .set_rate and .round_rate
+ */
+
+struct clk_fixed_factor_frac {
+	struct clk_hw	hw;
+	unsigned int	mult;
+	unsigned int	div;
+	unsigned int	frac;
+	unsigned int	frac_div;
+};
+
+#define INTEL_FIXED_FACTOR_PLLCLK	"intel,fixed-factor-pllclk"
+#define INTEL_FIXED_FACTOR_FRAC_PLLCLK	"intel,fixed-factor-frac-pllclk"
+
+#define CLK_INIT_DEF_CFG_REQ		BIT(0)
+
+void intel_gate_clk_setup(struct device_node *np,
+			  const struct gate_clk_data *data);
+void intel_mux_clk_setup(struct device_node *np,
+			 const struct mux_clk_data *data);
+void intel_fixed_rate_clk_setup(struct device_node *np,
+				const struct fixed_rate_clk_data *data);
+void intel_div_clk_setup(struct device_node *np,
+			 const struct div_clk_data *data);
+void intel_gate_dummy_clk_setup(struct device_node *np,
+				const struct gate_dummy_clk_data *data);
+void intel_cluster_div_clk_setup(struct device_node *np,
+				 const struct div_clk_data *data, u32 num);
+
+#endif /* __INTEL_CLK_API_H */
diff --git a/drivers/clk/intel/clk-grx500.c b/drivers/clk/intel/clk-grx500.c
new file mode 100644
index 000000000000..c61b7ba06758
--- /dev/null
+++ b/drivers/clk/intel/clk-grx500.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2016 Intel Corporation.
+ *  Zhu YiXin <Yixin.zhu@intel.com>
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+#include <dt-bindings/clock/intel,grx500-clk.h>
+#include "clk-cgu-api.h"
+
+/* Intel GRX500 CGU device tree "compatible" strings */
+#define INTEL_GRX500_DT_PLL0A_CLK	"intel,grx500-pll0a-clk"
+#define INTEL_GRX500_DT_PLL0B_CLK	"intel,grx500-pll0b-clk"
+#define INTEL_GRX500_DT_PCIE_CLK	"intel,grx500-pcie-clk"
+#define INTEL_GRX500_DT_CPU_CLK		"intel,grx500-cpu-clk"
+#define INTEL_GRX500_DT_GATE0_CLK	"intel,grx500-gate0-clk"
+#define INTEL_GRX500_DT_GATE1_CLK	"intel,grx500-gate1-clk"
+#define INTEL_GRX500_DT_GATE2_CLK	"intel,grx500-gate2-clk"
+#define INTEL_GRX500_DT_VOICE_CLK	"intel,grx500-voice-clk"
+#define INTEL_GRX500_DT_GATE_I2C_CLK	"intel,grx500-gate-dummy-clk"
+
+/* clock shift and width */
+#define CBM_CLK_SHIFT		0
+#define CBM_CLK_WIDTH		4
+#define NGI_CLK_SHIFT		4
+#define NGI_CLK_WIDTH		4
+#define SSX4_CLK_SHIFT		8
+#define SSX4_CLK_WIDTH		4
+#define CPU0_CLK_SHIFT		12
+#define CPU0_CLK_WIDTH		4
+
+#define PAE_CLK_SHIFT		0
+#define PAE_CLK_WIDTH		4
+#define GSWIP_CLK_SHIFT		4
+#define GSWIP_CLK_WIDTH		4
+#define DDR_CLK_SHIFT		8
+#define DDR_CLK_WIDTH		4
+#define CPU1_CLK_SHIFT		12
+#define CPU1_CLK_WIDTH		4
+
+#define PCIE_CLK_SHIFT		12
+#define PCIE_CLK_WIDTH		2
+
+#define CPU_CLK_SHIFT		29
+#define CPU_CLK_WIDTH		1
+
+#define VOICE_CLK_SHIFT		14
+#define VOICE_CLK_WIDTH		2
+
+/* Gate clock mask */
+#define GATE0_CLK_MASK		0xCF
+#define GATE1_CLK_MASK		0x1EF27FE4
+#define GATE2_CLK_MASK		0x2020002
+
+static const struct clk_div_table pll_div[] = {
+	{1,	2},
+	{2,	3},
+	{3,	4},
+	{4,	5},
+	{5,	6},
+	{6,	8},
+	{7,	10},
+	{8,	12},
+	{9,	16},
+	{10,	20},
+	{11,	24},
+	{12,	32},
+	{13,	40},
+	{14,	48},
+	{15,	64}
+};
+
+static const struct gate_dummy_clk_data grx500_clk_gate_i2c_data __initconst = {
+	0
+};
+
+static void __init grx500_clk_gate_i2c_setup(struct device_node *node)
+{
+	intel_gate_dummy_clk_setup(node, &grx500_clk_gate_i2c_data);
+}
+
+CLK_OF_DECLARE(grx500_gatei2cclk, INTEL_GRX500_DT_GATE_I2C_CLK,
+	       grx500_clk_gate_i2c_setup);
+
+static const struct fixed_rate_clk_data grx500_clk_voice_data __initconst = {
+	.shift = VOICE_CLK_SHIFT,
+	.width = VOICE_CLK_WIDTH,
+	.setval = 0x2,
+};
+
+static void __init grx500_clk_voice_setup(struct device_node *node)
+{
+	intel_fixed_rate_clk_setup(node, &grx500_clk_voice_data);
+}
+
+CLK_OF_DECLARE(grx500_voiceclk, INTEL_GRX500_DT_VOICE_CLK,
+	       grx500_clk_voice_setup);
+
+static const struct gate_clk_data grx500_clk_gate2_data __initconst = {
+	.mask = GATE2_CLK_MASK,
+	.reg_size = 32,
+};
+
+static void __init grx500_clk_gate2_setup(struct device_node *node)
+{
+	intel_gate_clk_setup(node, &grx500_clk_gate2_data);
+}
+
+CLK_OF_DECLARE(grx500_gate2clk, INTEL_GRX500_DT_GATE2_CLK,
+	       grx500_clk_gate2_setup);
+
+static const struct gate_clk_data grx500_clk_gate1_data __initconst = {
+	.mask = GATE1_CLK_MASK,
+	.def_onoff = 0x14000600,
+	.reg_size = 32,
+	.flags = CLK_INIT_DEF_CFG_REQ,
+};
+
+static void __init grx500_clk_gate1_setup(struct device_node *node)
+{
+	intel_gate_clk_setup(node, &grx500_clk_gate1_data);
+}
+
+CLK_OF_DECLARE(grx500_gate1clk, INTEL_GRX500_DT_GATE1_CLK,
+	       grx500_clk_gate1_setup);
+
+static const struct gate_clk_data grx500_clk_gate0_data __initconst = {
+	.mask = GATE0_CLK_MASK,
+	.def_onoff = GATE0_CLK_MASK,
+	.reg_size = 32,
+	.flags = CLK_INIT_DEF_CFG_REQ,
+};
+
+static void __init grx500_clk_gate0_setup(struct device_node *node)
+{
+	intel_gate_clk_setup(node, &grx500_clk_gate0_data);
+}
+
+CLK_OF_DECLARE(grx500_gate0clk, INTEL_GRX500_DT_GATE0_CLK,
+	       grx500_clk_gate0_setup);
+
+static const struct mux_clk_data grx500_clk_cpu_data __initconst = {
+	.shift = CPU_CLK_SHIFT,
+	.width = CPU_CLK_WIDTH,
+	.flags = CLK_SET_RATE_PARENT,
+};
+
+static void __init grx500_clk_cpu_setup(struct device_node *node)
+{
+	intel_mux_clk_setup(node, &grx500_clk_cpu_data);
+}
+
+CLK_OF_DECLARE(grx500_cpuclk, INTEL_GRX500_DT_CPU_CLK,
+	       grx500_clk_cpu_setup);
+
+static const struct div_clk_data grx500_clk_pcie_data __initconst = {
+	.shift = PCIE_CLK_SHIFT,
+	.width = PCIE_CLK_WIDTH,
+	.div_table = pll_div,
+};
+
+static void __init grx500_clk_pcie_setup(struct device_node *node)
+{
+	intel_div_clk_setup(node, &grx500_clk_pcie_data);
+}
+
+CLK_OF_DECLARE(grx500_pcieclk, INTEL_GRX500_DT_PCIE_CLK,
+	       grx500_clk_pcie_setup);
+
+static const struct div_clk_data grx500_clk_pll0b[] __initconst = {
+	{
+		.shift = PAE_CLK_SHIFT,
+		.width = PAE_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+	{
+		.shift = GSWIP_CLK_SHIFT,
+		.width = GSWIP_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+	{
+		.shift = DDR_CLK_SHIFT,
+		.width = DDR_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+	{
+		.shift = CPU1_CLK_SHIFT,
+		.width = CPU1_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+};
+
+static void __init grx500_clk_pll0b_setup(struct device_node *node)
+{
+	intel_cluster_div_clk_setup(node, grx500_clk_pll0b,
+				    ARRAY_SIZE(grx500_clk_pll0b));
+}
+
+CLK_OF_DECLARE(grx500_pll0bclk, INTEL_GRX500_DT_PLL0B_CLK,
+	       grx500_clk_pll0b_setup);
+
+static const struct div_clk_data grx500_clk_pll0a[] __initconst = {
+	{
+		.shift = CBM_CLK_SHIFT,
+		.width = CBM_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+	{
+		.shift = NGI_CLK_SHIFT,
+		.width = NGI_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+	{
+		.shift = SSX4_CLK_SHIFT,
+		.width = SSX4_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+	{
+		.shift = CPU0_CLK_SHIFT,
+		.width = CPU0_CLK_WIDTH,
+		.div_table = pll_div,
+	},
+};
+
+static void __init grx500_clk_pll0a_setup(struct device_node *node)
+{
+	intel_cluster_div_clk_setup(node, grx500_clk_pll0a,
+				    ARRAY_SIZE(grx500_clk_pll0a));
+}
+
+CLK_OF_DECLARE(grx500_pll0aclk, INTEL_GRX500_DT_PLL0A_CLK,
+	       grx500_clk_pll0a_setup);
diff --git a/include/dt-bindings/clock/intel,grx500-clk.h b/include/dt-bindings/clock/intel,grx500-clk.h
new file mode 100644
index 000000000000..eb1114636504
--- /dev/null
+++ b/include/dt-bindings/clock/intel,grx500-clk.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2016 Intel Corporation.
+ *  Zhu YiXin <Yixin.zhu@intel.com>
+ *
+ */
+
+#ifndef __INTEL_GRX500_CLK_H
+#define __INTEL_GRX500_CLK_H
+
+/* clocks under pll0a-clk */
+#define CBM_CLK			0
+#define NGI_CLK			1
+#define SSX4_CLK		2
+#define CPU0_CLK		3
+
+/* clocks under pll0b-clk */
+#define PAE_CLK			0
+#define GSWIP_CLK		1
+#define DDR_CLK			2
+#define CPU1_CLK		3
+
+/* clocks under lcpll-clk */
+#define GRX500_PCIE_CLK		0
+
+/* clocks under gate0-clk */
+#define GATE_XBAR0_CLK		0
+#define GATE_XBAR1_CLK		1
+#define GATE_XBAR2_CLK		2
+#define GATE_XBAR3_CLK		3
+#define GATE_XBAR6_CLK		4
+#define GATE_XBAR7_CLK		5
+
+/* clocks under gate1-clk */
+#define GATE_V_CODEC_CLK	0
+#define GATE_DMA0_CLK		1
+#define GATE_USB0_CLK		2
+#define GATE_SPI1_CLK		3
+#define GATE_SPI0_CLK		4
+#define GATE_CBM_CLK		5
+#define GATE_EBU_CLK		6
+#define GATE_SSO_CLK		7
+#define GATE_GPTC0_CLK		8
+#define GATE_GPTC1_CLK		9
+#define GATE_GPTC2_CLK		10
+#define GATE_URT_CLK		11
+#define GATE_EIP97_CLK		12
+#define GATE_EIP123_CLK		13
+#define GATE_TOE_CLK		14
+#define GATE_MPE_CLK		15
+#define GATE_TDM_CLK		16
+#define GATE_PAE_CLK		17
+#define GATE_USB1_CLK		18
+#define GATE_GSWIP_CLK		19
+
+/* clocks under gate2-clk */
+#define GATE_PCIE0_CLK		0
+#define GATE_PCIE1_CLK		1
+#define GATE_PCIE2_CLK		2
+
+#endif /* __INTEL_GRX500_CLK_H */
-- 
2.11.0


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

* [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
  2018-06-12  5:40 ` [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial Songjun Wu
  2018-06-12  5:40 ` [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12 11:23   ` James Hogan
  2018-06-12 22:31   ` Rob Herring
  2018-06-12  5:40 ` [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel() Songjun Wu
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, James Hogan, linux-kernel, Rob Herring, Ralf Baechle,
	Mark Rutland

From: Hua Ma <hua.ma@linux.intel.com>

Add initial support for Intel MIPS interAptiv SoCs made by Intel.
This series will add support for the GRX500 family.

The series allows booting a minimal system using a initramfs.

Signed-off-by: Hua ma <hua.ma@linux.intel.com>
Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
---

 arch/mips/Kbuild.platforms                         |   1 +
 arch/mips/Kconfig                                  |  36 ++++
 arch/mips/boot/dts/Makefile                        |   1 +
 arch/mips/boot/dts/intel-mips/Makefile             |   3 +
 arch/mips/boot/dts/intel-mips/easy350_anywan.dts   |  20 +++
 arch/mips/boot/dts/intel-mips/xrx500.dtsi          | 196 +++++++++++++++++++++
 arch/mips/configs/grx500_defconfig                 | 165 +++++++++++++++++
 .../asm/mach-intel-mips/cpu-feature-overrides.h    |  61 +++++++
 arch/mips/include/asm/mach-intel-mips/ioremap.h    |  39 ++++
 arch/mips/include/asm/mach-intel-mips/irq.h        |  17 ++
 .../asm/mach-intel-mips/kernel-entry-init.h        |  76 ++++++++
 arch/mips/include/asm/mach-intel-mips/spaces.h     |  29 +++
 arch/mips/include/asm/mach-intel-mips/war.h        |  18 ++
 arch/mips/intel-mips/Kconfig                       |  22 +++
 arch/mips/intel-mips/Makefile                      |   3 +
 arch/mips/intel-mips/Platform                      |  11 ++
 arch/mips/intel-mips/irq.c                         |  36 ++++
 arch/mips/intel-mips/prom.c                        | 184 +++++++++++++++++++
 arch/mips/intel-mips/time.c                        |  56 ++++++
 19 files changed, 974 insertions(+)
 create mode 100644 arch/mips/boot/dts/intel-mips/Makefile
 create mode 100644 arch/mips/boot/dts/intel-mips/easy350_anywan.dts
 create mode 100644 arch/mips/boot/dts/intel-mips/xrx500.dtsi
 create mode 100644 arch/mips/configs/grx500_defconfig
 create mode 100644 arch/mips/include/asm/mach-intel-mips/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/ioremap.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/irq.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/spaces.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/war.h
 create mode 100644 arch/mips/intel-mips/Kconfig
 create mode 100644 arch/mips/intel-mips/Makefile
 create mode 100644 arch/mips/intel-mips/Platform
 create mode 100644 arch/mips/intel-mips/irq.c
 create mode 100644 arch/mips/intel-mips/prom.c
 create mode 100644 arch/mips/intel-mips/time.c

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index ac7ad54f984f..bcd647060f3e 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -12,6 +12,7 @@ platforms += cobalt
 platforms += dec
 platforms += emma
 platforms += generic
+platforms += intel-mips
 platforms += jazz
 platforms += jz4740
 platforms += lantiq
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 225c95da23ce..c82cebeb6192 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -404,6 +404,41 @@ config LANTIQ
 	select ARCH_HAS_RESET_CONTROLLER
 	select RESET_CONTROLLER
 
+config INTEL_MIPS
+	bool "Intel MIPS interAptiv SoC based platforms"
+	select ARCH_HAS_RESET_CONTROLLER
+	select ARCH_SUPPORTS_MSI
+	select BOOT_RAW
+	select CEVT_R4K
+	select COMMON_CLK
+	select CPU_MIPS32_3_5_EVA
+	select CPU_MIPS32_3_5_FEATURES
+	select CPU_MIPSR2_IRQ_EI
+	select CPU_MIPSR2_IRQ_VI
+	select CSRC_R4K
+	select DMA_NONCOHERENT
+	select GENERIC_ISA_DMA
+	select GPIOLIB
+	select HW_HAS_PCI
+	select IRQ_MIPS_CPU
+	select MFD_CORE
+	select MFD_SYSCON
+	select MIPS_CPU_SCACHE
+	select MIPS_GIC
+	select PCI_DRIVERS_GENERIC
+	select RESET_CONTROLLER
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS32_R3_5
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_MIPS_CPS
+	select SYS_SUPPORTS_MULTITHREADING
+	select SYS_SUPPORTS_ZBOOT
+	select TIMER_OF
+	select USE_OF
+
 config LASAT
 	bool "LASAT Networks platforms"
 	select CEVT_R4K
@@ -1010,6 +1045,7 @@ source "arch/mips/bcm47xx/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/bmips/Kconfig"
 source "arch/mips/generic/Kconfig"
+source "arch/mips/intel-mips/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
 source "arch/mips/lantiq/Kconfig"
diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile
index 1e79cab8e269..05f52f279047 100644
--- a/arch/mips/boot/dts/Makefile
+++ b/arch/mips/boot/dts/Makefile
@@ -3,6 +3,7 @@ subdir-y	+= brcm
 subdir-y	+= cavium-octeon
 subdir-y	+= img
 subdir-y	+= ingenic
+subdir-y	+= intel-mips
 subdir-y	+= lantiq
 subdir-y	+= mscc
 subdir-y	+= mti
diff --git a/arch/mips/boot/dts/intel-mips/Makefile b/arch/mips/boot/dts/intel-mips/Makefile
new file mode 100644
index 000000000000..b16c0081639c
--- /dev/null
+++ b/arch/mips/boot/dts/intel-mips/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_DTB_INTEL_MIPS_GRX500)	+= easy350_anywan.dtb
+obj-y	+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/arch/mips/boot/dts/intel-mips/easy350_anywan.dts b/arch/mips/boot/dts/intel-mips/easy350_anywan.dts
new file mode 100644
index 000000000000..40177f6cee1e
--- /dev/null
+++ b/arch/mips/boot/dts/intel-mips/easy350_anywan.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/mips-gic.h>
+#include <dt-bindings/clock/intel,grx500-clk.h>
+
+#include "xrx500.dtsi"
+
+/ {
+	model = "EASY350 ANYWAN (GRX350) Main model";
+	chosen {
+		bootargs = "earlycon=lantiq,0x16600000 clk_ignore_unused";
+		stdout-path = "serial0";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x20000000 0x0e000000>;
+	};
+};
diff --git a/arch/mips/boot/dts/intel-mips/xrx500.dtsi b/arch/mips/boot/dts/intel-mips/xrx500.dtsi
new file mode 100644
index 000000000000..04a068d6d96b
--- /dev/null
+++ b/arch/mips/boot/dts/intel-mips/xrx500.dtsi
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "intel,xrx500";
+
+	aliases {
+		serial0 = &asc0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "mti,interaptiv";
+			clocks = <&cpuclk>;
+			reg = <0>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "mti,interaptiv";
+			reg = <1>;
+		};
+	};
+
+	cpu_intc: interrupt-controller {
+		compatible = "mti,cpu-interrupt-controller";
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
+
+	gic: gic@12320000 {
+		compatible = "mti,gic";
+		reg = <0x12320000 0x20000>;
+
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		/*
+		 * Declare the interrupt-parent even though the mti,gic
+		 * binding doesn't require it, such that the kernel can
+		 * figure out that cpu_intc is the root interrupt
+		 * controller & should be probed first.
+		 */
+		interrupt-parent = <&cpu_intc>;
+		mti,reserved-ipi-vectors = <56 8>;
+	};
+
+	cgu0: cgu@16200000 {
+		compatible = "syscon";
+		reg = <0x16200000 0x100000>;
+
+		clock {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			osc0: osc0 {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <40000000>;
+				clock-output-names = "osc40M";
+			};
+
+			pll0a: pll0a {
+				#clock-cells = <0>;
+				compatible = "fixed-factor-clock";
+				clock-mult = <0x3C>;
+				clock-div = <1>;
+				clocks = <&osc0>;
+				clock-output-names = "pll0a";
+			};
+
+			pll0b: pll0b {
+				#clock-cells = <0>;
+				compatible = "fixed-factor-clock";
+				clock-mult = <0x32>;
+				clock-div = <1>;
+				clocks = <&osc0>;
+				clock-output-names = "pll0b";
+			};
+
+			pll3: pll3 {
+				#clock-cells = <0>;
+				compatible = "fixed-factor-clock";
+				clock-mult = <0x64>;
+				clock-div = <1>;
+				clocks = <&osc0>;
+				clock-output-names = "lcpll3";
+			};
+
+			pll0aclk: pll0aclk {
+				#clock-cells = <1>;
+				compatible = "intel,grx500-pll0a-clk";
+				clocks = <&pll0a>;
+				reg = <0x8>;
+				clock-output-names = "cbm", "ngi",
+				"ssx4", "cpu0";
+			};
+
+			pll0bclk: pll0bclk {
+				#clock-cells = <1>;
+				compatible = "intel,grx500-pll0b-clk";
+				clocks = <&pll0b>;
+				reg = <0x38>;
+				clock-output-names = "pae", "gswip", "ddr",
+				"cpu1";
+			};
+
+			ddrphyclk: ddrphyclk {
+				#clock-cells = <0>;
+				compatible = "fixed-factor-clock";
+				clock-mult = <2>;
+				clock-div = <1>;
+				clocks = <&pll0bclk DDR_CLK>;
+				clock-output-names = "ddrphy";
+			};
+
+			pcieclk: pcieclk {
+				#clock-cells = <0>;
+				compatible = "intel,grx500-pcie-clk";
+				clocks = <&pll3>;
+				reg = <0x98>;
+				clock-output-names = "pcie";
+			};
+
+			cpuclk: cpuclk {
+				#clock-cells = <0>;
+				compatible = "intel,grx500-cpu-clk";
+				clocks = <&pll0aclk CPU0_CLK>,
+				<&pll0bclk CPU1_CLK>;
+				reg = <0x8>;
+				clock-output-names = "cpu";
+			};
+
+			clkgate0: clkgate0 {
+				#clock-cells = <1>;
+				compatible = "intel,grx500-gate0-clk";
+				reg = <0x114>;
+				clock-output-names = "gate_xbar0", "gate_xbar1",
+				"gate_xbar2", "gate_xbar3", "gate_xbar6",
+				"gate_xbar7";
+			};
+
+			clkgate1: clkgate1 {
+				#clock-cells = <1>;
+				compatible = "intel,grx500-gate1-clk";
+				reg = <0x120>;
+				clock-output-names = "gate_vcodec", "gate_dma0",
+				"gate_usb0", "gate_spi1", "gate_spi0",
+				"gate_cbm", "gate_ebu", "gate_sso",
+				"gate_gptc0", "gate_gptc1", "gate_gptc2",
+				"gate_urt", "gate_eip97", "gate_eip123",
+				"gate_toe", "gate_mpe", "gate_tdm", "gate_pae",
+				"gate_usb1", "gate_gswip";
+			};
+
+			clkgate2: clkgate2 {
+				#clock-cells = <1>;
+				compatible = "intel,grx500-gate2-clk";
+				reg = <0x130>;
+				clock-output-names = "gate_pcie0", "gate_pcie1",
+				"gate_pcie2";
+			};
+
+			voiceclk: voiceclk {
+				#clock-cells = <0>;
+				compatible = "intel,grx500-voice-clk";
+				clock-frequency = <8192000>;
+				reg = <0xc4>;
+				clock-output-names = "voice";
+			};
+
+			i2cclk: i2cclk {
+				#clock-cells = <0>;
+				compatible = "intel,grx500-gate-dummy-clk";
+				clock-output-names = "gate_i2c";
+			};
+		};
+	};
+
+	asc0: serial@16600000 {
+		compatible = "lantiq,asc";
+		reg = <0x16600000 0x100000>;
+
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&pll0aclk SSX4_CLK>, <&clkgate1 GATE_URT_CLK>;
+		clock-names = "freq", "asc";
+	};
+};
diff --git a/arch/mips/configs/grx500_defconfig b/arch/mips/configs/grx500_defconfig
new file mode 100644
index 000000000000..d353b74dddcd
--- /dev/null
+++ b/arch/mips/configs/grx500_defconfig
@@ -0,0 +1,165 @@
+CONFIG_INTEL_MIPS=y
+CONFIG_DTB_INTEL_MIPS_GRX500=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_SCHED_SMT=y
+# CONFIG_MIPS_MT_FPAFF is not set
+CONFIG_MIPS_CPS=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=y
+CONFIG_Z3FOLD=y
+CONFIG_ZSMALLOC=y
+CONFIG_PGTABLE_MAPPING=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_NR_CPUS=2
+CONFIG_HZ_100=y
+# CONFIG_SECCOMP is not set
+CONFIG_CROSS_COMPILE=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="GRX500"
+CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_EXPERT=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INITRAMFS_ROOT_UID=11609386
+CONFIG_INITRAMFS_ROOT_GID=2222
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_INITRAMFS_COMPRESSION_XZ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AIO is not set
+CONFIG_BPF_SYSCALL=y
+CONFIG_USERFAULTFD=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_ATM=m
+CONFIG_ATM_BR2684=m
+CONFIG_DMA_CMA=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+CONFIG_SERIAL_LANTIQ=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_VIRTIO_MENU is not set
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+CONFIG_COMMON_CLK_INTEL=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXPORTFS_BLOCK_OPS=y
+# CONFIG_MANDATORY_FILE_LOCKING is not set
+CONFIG_QUOTA=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FSCACHE=y
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_OBJECT_LIST=y
+CONFIG_CACHEFILES=y
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_PROC_CHILDREN=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NLS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+CONFIG_FRAME_WARN=2048
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+# CONFIG_RCU_TRACE is not set
+CONFIG_LATENCYTOP=y
+# CONFIG_FTRACE is not set
+CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_TEST_KSTRTOX=y
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+# CONFIG_CRYPTO_ECHAINIV is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_LIBCRC32C=y
+CONFIG_IRQ_POLL=y
diff --git a/arch/mips/include/asm/mach-intel-mips/cpu-feature-overrides.h b/arch/mips/include/asm/mach-intel-mips/cpu-feature-overrides.h
new file mode 100644
index 000000000000..ac5f3b943d2a
--- /dev/null
+++ b/arch/mips/include/asm/mach-intel-mips/cpu-feature-overrides.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file was derived from: include/asm-mips/cpu-features.h
+ *	Copyright (C) 2003, 2004 Ralf Baechle
+ *	Copyright (C) 2004 Maciej W. Rozycki
+ *	Copyright (C) 2018 Intel Corporation.
+ */
+
+#ifndef __ASM_MACH_INTEL_MIPS_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_INTEL_MIPS_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_3k_cache	0
+#define cpu_has_4k_cache	1
+#define cpu_has_tx39_cache	0
+#define cpu_has_sb1_cache	0
+#define cpu_has_fpu		0
+#define cpu_has_32fpr		0
+#define cpu_has_counter		1
+#define cpu_has_watch		1
+#define cpu_has_divec		1
+
+#define cpu_has_prefetch	1
+#define cpu_has_ejtag		1
+#define cpu_has_llsc		1
+
+#define cpu_has_mips16		0
+#define cpu_has_mdmx		0
+#define cpu_has_mips3d		0
+#define cpu_has_smartmips	0
+#define cpu_has_mmips		0
+#define cpu_has_vz		0
+
+#define cpu_has_mips32r1	1
+#define cpu_has_mips32r2	1
+#define cpu_has_mips64r1	0
+#define cpu_has_mips64r2	0
+
+#define cpu_has_dsp		1
+#define cpu_has_dsp2		0
+#define cpu_has_mipsmt		1
+
+#define cpu_has_vint		1
+#define cpu_has_veic		0
+
+#define cpu_has_64bits		0
+#define cpu_has_64bit_zero_reg	0
+#define cpu_has_64bit_gp_regs	0
+#define cpu_has_64bit_addresses	0
+
+#define cpu_has_cm2		1
+#define cpu_has_cm2_l2sync	1
+#define cpu_has_eva		1
+#define cpu_has_tlbinv		1
+
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	32
+#define cpu_scache_line_size()	32
+
+#endif /* __ASM_MACH_INTEL_MIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-intel-mips/ioremap.h b/arch/mips/include/asm/mach-intel-mips/ioremap.h
new file mode 100644
index 000000000000..99b20ed0b457
--- /dev/null
+++ b/arch/mips/include/asm/mach-intel-mips/ioremap.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2014 Lei Chuanhua <Chuanhua.lei@lantiq.com>
+ *  Copyright (C) 2018 Intel Corporation.
+ */
+#ifndef __ASM_MACH_INTEL_MIPS_IOREMAP_H
+#define __ASM_MACH_INTEL_MIPS_IOREMAP_H
+
+#include <linux/types.h>
+
+static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr,
+					     phys_addr_t size)
+{
+	return phys_addr;
+}
+
+/*
+ * TOP IO Space definition for SSX7 components /PCIe/ToE/Memcpy
+ * physical 0xa0000000 --> virtual 0xe0000000
+ */
+#define GRX500_TOP_IOREMAP_BASE			0xA0000000
+#define GRX500_TOP_IOREMAP_SIZE			0x20000000
+#define GRX500_TOP_IOREMAP_PHYS_VIRT_OFFSET	0x40000000
+
+static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
+					 unsigned long flags)
+{
+	if (offset >= GRX500_TOP_IOREMAP_BASE &&
+	    offset < (GRX500_TOP_IOREMAP_BASE + GRX500_TOP_IOREMAP_SIZE))
+		return (void __iomem *)(unsigned long)
+			(offset + GRX500_TOP_IOREMAP_PHYS_VIRT_OFFSET);
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= (unsigned long)GRX500_TOP_IOREMAP_BASE;
+}
+#endif /* __ASM_MACH_INTEL_MIPS_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-intel-mips/irq.h b/arch/mips/include/asm/mach-intel-mips/irq.h
new file mode 100644
index 000000000000..12a949084856
--- /dev/null
+++ b/arch/mips/include/asm/mach-intel-mips/irq.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2014 Lei Chuanhua <Chuanhua.lei@lantiq.com>
+ *  Copyright (C) 2018 Intel Corporation.
+ */
+
+#ifndef __INTEL_MIPS_IRQ_H
+#define __INTEL_MIPS_IRQ_H
+
+#define MIPS_CPU_IRQ_BASE	0
+#define MIPS_GIC_IRQ_BASE	(MIPS_CPU_IRQ_BASE + 8)
+
+#define NR_IRQS 256
+
+#include_next <irq.h>
+
+#endif /* __INTEL_MIPS_IRQ_H */
diff --git a/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h b/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
new file mode 100644
index 000000000000..3893855b60c6
--- /dev/null
+++ b/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Chris Dearman (chris@mips.com)
+ * Leonid Yegoshin (yegoshin@mips.com)
+ * Copyright (C) 2012 Mips Technologies, Inc.
+ * Copyright (C) 2018 Intel Corporation.
+ */
+#ifndef __ASM_MACH_INTEL_MIPS_KERNEL_ENTRY_INIT_H
+#define __ASM_MACH_INTEL_MIPS_KERNEL_ENTRY_INIT_H
+
+	.macro  platform_eva_init
+
+	.set    push
+	.set    reorder
+	/*
+	 * Get Config.K0 value and use it to program
+	 * the segmentation registers
+	 */
+	mfc0    t1, CP0_CONFIG
+	andi    t1, 0x7 /* CCA */
+	move    t2, t1
+	ins     t2, t1, 16, 3
+	/* SegCtl0 */
+	li      t0, ((MIPS_SEGCFG_UK << MIPS_SEGCFG_AM_SHIFT) |              \
+		(5 << MIPS_SEGCFG_PA_SHIFT) | (2 << MIPS_SEGCFG_C_SHIFT) |   \
+		(1 << MIPS_SEGCFG_EU_SHIFT)) |                               \
+		(((MIPS_SEGCFG_MSK << MIPS_SEGCFG_AM_SHIFT) |                \
+		(0 << MIPS_SEGCFG_PA_SHIFT) |                                \
+		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+	ins     t0, t1, 16, 3
+	mtc0    t0, $5, 2
+
+	/* SegCtl1 */
+	li      t0, ((MIPS_SEGCFG_UK << MIPS_SEGCFG_AM_SHIFT) |              \
+		(1 << MIPS_SEGCFG_PA_SHIFT) | (2 << MIPS_SEGCFG_C_SHIFT) |   \
+		(1 << MIPS_SEGCFG_EU_SHIFT)) |                               \
+		(((MIPS_SEGCFG_UK << MIPS_SEGCFG_AM_SHIFT) |                 \
+		(2 << MIPS_SEGCFG_PA_SHIFT) |                                \
+		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+	ins     t0, t1, 16, 3
+	mtc0    t0, $5, 3
+
+	/* SegCtl2 */
+	li      t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |           \
+		(0 << MIPS_SEGCFG_PA_SHIFT) |                                \
+		(1 << MIPS_SEGCFG_EU_SHIFT)) |                               \
+		(((MIPS_SEGCFG_MUSK << MIPS_SEGCFG_AM_SHIFT) |               \
+		(0 << MIPS_SEGCFG_PA_SHIFT)/*| (2 << MIPS_SEGCFG_C_SHIFT)*/ | \
+		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+	ins     t0, t1, 0, 3
+	mtc0    t0, $5, 4
+
+	jal     mips_ihb
+	mfc0    t0, $16, 5
+	li      t2, 0x40000000      /* K bit */
+	or      t0, t0, t2
+	mtc0    t0, $16, 5
+	sync
+	jal     mips_ihb
+
+	.set    pop
+	.endm
+
+	.macro	kernel_entry_setup
+	sync
+	ehb
+	platform_eva_init
+	.endm
+
+	.macro	smp_slave_setup
+	sync
+	ehb
+	platform_eva_init
+	.endm
+
+#endif /* __ASM_MACH_INTEL_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/arch/mips/include/asm/mach-intel-mips/spaces.h b/arch/mips/include/asm/mach-intel-mips/spaces.h
new file mode 100644
index 000000000000..abce53a65157
--- /dev/null
+++ b/arch/mips/include/asm/mach-intel-mips/spaces.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Author: Leonid Yegoshin (yegoshin@mips.com)
+ * Copyright (C) 2012 MIPS Technologies, Inc.
+ * Copyright (C) 2014 Lei Chuanhua <Chuanhua.lei@lantiq.com>
+ * Copyright (C) 2018 Intel Corporation.
+ */
+
+#ifndef _ASM_INTEL_MIPS_SPACES_H
+#define _ASM_INTEL_MIPS_SPACES_H
+
+#include <linux/sizes.h>
+
+#define PAGE_OFFSET		_AC(0x60000000, UL)
+#define PHYS_OFFSET		_AC(0x20000000, UL)
+
+/* No Highmem Support */
+#define HIGHMEM_START		_AC(0xffff0000, UL)
+
+#define FIXADDR_TOP		((unsigned long)(long)(int)0xcffe0000)
+
+#define IO_SIZE			_AC(0x10000000, UL)
+#define IO_SHIFT		_AC(0x10000000, UL)
+
+/* IO space one */
+#define __pa_symbol(x)		__pa(x)
+
+#include <asm/mach-generic/spaces.h>
+#endif /* __ASM_INTEL_MIPS_SPACES_H */
diff --git a/arch/mips/include/asm/mach-intel-mips/war.h b/arch/mips/include/asm/mach-intel-mips/war.h
new file mode 100644
index 000000000000..1c95553151e1
--- /dev/null
+++ b/arch/mips/include/asm/mach-intel-mips/war.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_MIPS_MACH_INTEL_MIPS_WAR_H
+#define __ASM_MIPS_MACH_INTEL_MIPS_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#define MIPS_CACHE_SYNC_WAR		0
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MIPS_MACH_INTEL_MIPS_WAR_H */
diff --git a/arch/mips/intel-mips/Kconfig b/arch/mips/intel-mips/Kconfig
new file mode 100644
index 000000000000..35d2ae2b5408
--- /dev/null
+++ b/arch/mips/intel-mips/Kconfig
@@ -0,0 +1,22 @@
+if INTEL_MIPS
+
+choice
+	prompt "Built-in device tree"
+	help
+	  Legacy bootloaders do not pass a DTB pointer to the kernel, so
+	  if a "wrapper" is not being used, the kernel will need to include
+	  a device tree that matches the target board.
+
+	  The builtin DTB will only be used if the firmware does not supply
+	  a valid DTB.
+
+config DTB_INTEL_MIPS_NONE
+	bool "None"
+
+config DTB_INTEL_MIPS_GRX500
+	bool "Intel MIPS GRX500 Board"
+	select BUILTIN_DTB
+
+endchoice
+
+endif
diff --git a/arch/mips/intel-mips/Makefile b/arch/mips/intel-mips/Makefile
new file mode 100644
index 000000000000..9f272d06eecd
--- /dev/null
+++ b/arch/mips/intel-mips/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_INTEL_MIPS)	+= prom.o irq.o time.o
diff --git a/arch/mips/intel-mips/Platform b/arch/mips/intel-mips/Platform
new file mode 100644
index 000000000000..b34750eeaeb0
--- /dev/null
+++ b/arch/mips/intel-mips/Platform
@@ -0,0 +1,11 @@
+#
+# MIPs SoC platform
+#
+
+platform-$(CONFIG_INTEL_MIPS)			+= intel-mips/
+cflags-$(CONFIG_INTEL_MIPS)			+= -I$(srctree)/arch/mips/include/asm/mach-intel-mips
+ifdef CONFIG_EVA
+	load-$(CONFIG_INTEL_MIPS)		= 0xffffffff60020000
+else
+	load-$(CONFIG_INTEL_MIPS)		= 0xffffffff80020000
+endif
diff --git a/arch/mips/intel-mips/irq.c b/arch/mips/intel-mips/irq.c
new file mode 100644
index 000000000000..00637a5cdd20
--- /dev/null
+++ b/arch/mips/intel-mips/irq.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+#include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/of_irq.h>
+#include <asm/irq.h>
+
+#include <asm/irq_cpu.h>
+
+void __init arch_init_irq(void)
+{
+	struct device_node *intc_node;
+
+	pr_info("EIC is %s\n", cpu_has_veic ? "on" : "off");
+	pr_info("VINT is %s\n", cpu_has_vint ? "on" : "off");
+
+	intc_node = of_find_compatible_node(NULL, NULL,
+					    "mti,cpu-interrupt-controller");
+	if (!cpu_has_veic && !intc_node)
+		mips_cpu_irq_init();
+
+	irqchip_init();
+}
+
+int get_c0_perfcount_int(void)
+{
+	return gic_get_c0_perfcount_int();
+}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
+
+unsigned int get_c0_compare_int(void)
+{
+	return gic_get_c0_compare_int();
+}
diff --git a/arch/mips/intel-mips/prom.c b/arch/mips/intel-mips/prom.c
new file mode 100644
index 000000000000..9407858ddc94
--- /dev/null
+++ b/arch/mips/intel-mips/prom.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014 Lei Chuanhua <Chuanhua.lei@lantiq.com>
+ * Copyright (C) 2016 Intel Corporation.
+ */
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <asm/mips-cps.h>
+#include <asm/smp-ops.h>
+#include <asm/dma-coherence.h>
+#include <asm/prom.h>
+
+#define IOPORT_RESOURCE_START   0x10000000
+#define IOPORT_RESOURCE_END     0xffffffff
+#define IOMEM_RESOURCE_START    0x10000000
+#define IOMEM_RESOURCE_END      0xffffffff
+
+const char *get_system_type(void)
+{
+	return "Intel MIPS interAptiv SoC";
+}
+
+void prom_free_prom_memory(void)
+{
+}
+
+static void __init prom_init_cmdline(void)
+{
+	int i;
+	int argc;
+	char **argv;
+
+	/*
+	 * If u-boot pass parameters, it is ok, however, if without u-boot
+	 * JTAG or other tool has to reset all register value before it goes
+	 * emulation most likely belongs to this category
+	 */
+	if (fw_arg0 == 0 || fw_arg1 == 0)
+		return;
+
+	argc = fw_arg0;
+	argv = (char **)KSEG1ADDR(fw_arg1);
+
+	arcs_cmdline[0] = '\0';
+
+	for (i = 0; i < argc; i++) {
+		char *p = (char *)KSEG1ADDR(argv[i]);
+
+		if (argv[i] && *p) {
+			strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
+			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+		}
+	}
+}
+
+static int __init plat_enable_iocoherency(void)
+{
+	int supported = 0;
+
+	if (mips_cps_numiocu(0) != 0) {
+		/* Nothing special needs to be done to enable coherency */
+		pr_info("Coherence Manager IOCU detected\n");
+		/* Second IOCU for MPE or other master access register */
+		write_gcr_reg0_base(0xa0000000);
+		write_gcr_reg0_mask(0xf8000000 | CM_GCR_REGn_MASK_CMTGT_IOCU1);
+		supported = 1;
+	}
+
+	/* hw_coherentio = supported; */
+
+	return supported;
+}
+
+static void __init plat_setup_iocoherency(void)
+{
+#ifdef CONFIG_DMA_NONCOHERENT
+	/*
+	 * Kernel has been configured with software coherency
+	 * but we might choose to turn it off and use hardware
+	 * coherency instead.
+	 */
+	if (plat_enable_iocoherency()) {
+		if (coherentio == IO_COHERENCE_DISABLED)
+			pr_info("Hardware DMA cache coherency disabled\n");
+		else
+			pr_info("Hardware DMA cache coherency enabled\n");
+	} else {
+		if (coherentio == IO_COHERENCE_ENABLED)
+			pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
+		else
+			pr_info("Software DMA cache coherency enabled\n");
+	}
+#else
+	if (!plat_enable_iocoherency())
+		panic("Hardware DMA cache coherency not supported!");
+#endif
+}
+
+static void free_init_pages_eva_intel(void *begin, void *end)
+{
+	free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
+			__pa_symbol((unsigned long *)end));
+}
+
+static void plat_early_init_devtree(void)
+{
+	void *dtb;
+
+	/*
+	 * Load the builtin devicetree. This causes the chosen node to be
+	 * parsed resulting in our memory appearing
+	 */
+	if (fw_passed_dtb) /* used by CONFIG_MIPS_APPENDED_RAW_DTB as well */
+		dtb = (void *)fw_passed_dtb;
+	else if (__dtb_start != __dtb_end)
+		dtb = (void *)__dtb_start;
+
+	if (dtb)
+		__dt_setup_arch(dtb);
+}
+
+void __init plat_mem_setup(void)
+{
+	ioport_resource.start = IOPORT_RESOURCE_START;
+	ioport_resource.end = ~0UL; /* No limit */
+	iomem_resource.start = IOMEM_RESOURCE_START;
+	iomem_resource.end = ~0UL; /* No limit */
+
+	set_io_port_base((unsigned long)KSEG1);
+
+	strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+
+	plat_early_init_devtree();
+	plat_setup_iocoherency();
+
+	if (IS_ENABLED(CONFIG_EVA))
+		free_init_pages_eva = free_init_pages_eva_intel;
+	else
+		free_init_pages_eva = 0;
+}
+
+void __init device_tree_init(void)
+{
+	if (!initial_boot_params)
+		return;
+
+	unflatten_and_copy_device_tree();
+}
+
+#define CPC_BASE_ADDR		0x12310000
+
+phys_addr_t mips_cpc_default_phys_base(void)
+{
+	return CPC_BASE_ADDR;
+}
+
+void __init prom_init(void)
+{
+	prom_init_cmdline();
+
+	mips_cpc_probe();
+
+	if (!register_cps_smp_ops())
+		return;
+
+	if (!register_cmp_smp_ops())
+		return;
+
+	if (!register_vsmp_smp_ops())
+		return;
+}
+
+static int __init plat_publish_devices(void)
+{
+	if (!of_have_populated_dt())
+		return 0;
+	return of_platform_populate(NULL, of_default_bus_match_table, NULL,
+				    NULL);
+}
+arch_initcall(plat_publish_devices);
diff --git a/arch/mips/intel-mips/time.c b/arch/mips/intel-mips/time.c
new file mode 100644
index 000000000000..77ad4014fe9d
--- /dev/null
+++ b/arch/mips/intel-mips/time.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Intel Corporation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/of.h>
+
+#include <asm/time.h>
+
+static inline u32 get_counter_resolution(void)
+{
+	u32 res;
+
+	__asm__ __volatile__(".set	push\n"
+			     ".set	mips32r2\n"
+			     "rdhwr	%0, $3\n"
+			     ".set pop\n"
+			     : "=&r" (res)
+			     : /* no input */
+			     : "memory");
+
+	return res;
+}
+
+void __init plat_time_init(void)
+{
+	unsigned long cpuclk;
+	struct device_node *np;
+	struct clk *clk;
+
+	of_clk_init(NULL);
+
+	np = of_get_cpu_node(0, NULL);
+	if (!np) {
+		pr_err("Failed to get CPU node\n");
+		return;
+	}
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+		return;
+	}
+
+	cpuclk = clk_get_rate(clk);
+	mips_hpt_frequency = cpuclk / get_counter_resolution();
+	clk_put(clk);
+
+	write_c0_compare(read_c0_count());
+	pr_info("CPU Clock: %ldHz  mips_hpt_frequency %dHz\n",
+		cpuclk, mips_hpt_frequency);
+	timer_probe();
+}
-- 
2.11.0


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

* [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel()
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
                   ` (2 preceding siblings ...)
  2018-06-12  5:40 ` [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12  8:13   ` Andy Shevchenko
  2018-06-14 10:07   ` Arnd Bergmann
  2018-06-12  5:40 ` [PATCH 5/7] tty: serial: lantiq: Convert global lock to per device lock Songjun Wu
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, James Hogan, Jiri Slaby, linux-kernel,
	Greg Kroah-Hartman, Ralf Baechle

Previous implementation uses platform-dependent functions
ltq_w32()/ltq_r32() to access registers. Those functions are not
available for other SoC which uses the same IP.
Change to OS provided readl()/writel() and readb()/writeb(), so
that different SoCs can use the same driver.

Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
---

 arch/mips/Kconfig           |   1 -
 drivers/tty/serial/lantiq.c | 236 ++++++++++++++++++++++++--------------------
 2 files changed, 128 insertions(+), 109 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c82cebeb6192..7bae259edd0b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -395,7 +395,6 @@ config LANTIQ
 	select SYS_SUPPORTS_VPE_LOADER
 	select SYS_HAS_EARLY_PRINTK
 	select GPIOLIB
-	select SWAP_IO_SPACE
 	select BOOT_RAW
 	select CLKDEV_LOOKUP
 	select USE_OF
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 044128277248..1127586dbc94 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -49,7 +49,8 @@
 #define LTQ_ASC_RXFCON		0x0040
 #define LTQ_ASC_CON		0x0010
 #define LTQ_ASC_BG		0x0050
-#define LTQ_ASC_IRNREN		0x00F4
+#define LTQ_ASC_FDV		0x0058
+#define LTQ_ASC_IRNEN		0x00F4
 
 #define ASC_IRNREN_TX		0x1
 #define ASC_IRNREN_RX		0x2
@@ -62,6 +63,7 @@
 #define ASCOPT_CSIZE		0x3
 #define TXFIFO_FL		1
 #define RXFIFO_FL		1
+#define ASCCLC_DISR		0x1
 #define ASCCLC_DISS		0x2
 #define ASCCLC_RMCMASK		0x0000FF00
 #define ASCCLC_RMCOFFSET	8
@@ -84,6 +86,7 @@
 #define ASCWHBSTATE_CLRPE	0x00000004
 #define ASCWHBSTATE_CLRFE	0x00000008
 #define ASCWHBSTATE_CLRROE	0x00000020
+#define ASCWHBSTATE_CLRALL	0x000000FC
 #define ASCTXFCON_TXFEN		0x0001
 #define ASCTXFCON_TXFFLU	0x0002
 #define ASCTXFCON_TXFITLMASK	0x3F00
@@ -97,6 +100,10 @@
 #define ASCFSTAT_TXFREEMASK	0x3F000000
 #define ASCFSTAT_TXFREEOFF	24
 
+#define asc_w32_mask(clear, set, reg)	\
+	({ typeof(reg) reg_ = (reg);	\
+	writel((readl(reg_) & ~(clear)) | (set), reg_); })
+
 static void lqasc_tx_chars(struct uart_port *port);
 static struct ltq_uart_port *lqasc_port[MAXPORTS];
 static struct uart_driver lqasc_reg;
@@ -113,20 +120,17 @@ struct ltq_uart_port {
 	unsigned int		err_irq;
 };
 
-static inline struct
-ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
+static inline struct ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
 {
 	return container_of(port, struct ltq_uart_port, port);
 }
 
-static void
-lqasc_stop_tx(struct uart_port *port)
+static void lqasc_stop_tx(struct uart_port *port)
 {
 	return;
 }
 
-static void
-lqasc_start_tx(struct uart_port *port)
+static void lqasc_start_tx(struct uart_port *port)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&ltq_asc_lock, flags);
@@ -135,23 +139,21 @@ lqasc_start_tx(struct uart_port *port)
 	return;
 }
 
-static void
-lqasc_stop_rx(struct uart_port *port)
+static void lqasc_stop_rx(struct uart_port *port)
 {
-	ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
+	writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 }
 
-static int
-lqasc_rx_chars(struct uart_port *port)
+static int lqasc_rx_chars(struct uart_port *port)
 {
 	struct tty_port *tport = &port->state->port;
 	unsigned int ch = 0, rsr = 0, fifocnt;
 
-	fifocnt = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
+	fifocnt = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
 	while (fifocnt--) {
 		u8 flag = TTY_NORMAL;
-		ch = ltq_r8(port->membase + LTQ_ASC_RBUF);
-		rsr = (ltq_r32(port->membase + LTQ_ASC_STATE)
+		ch = readb(port->membase + LTQ_ASC_RBUF);
+		rsr = (readl(port->membase + LTQ_ASC_STATE)
 			& ASCSTATE_ANY) | UART_DUMMY_UER_RX;
 		tty_flip_buffer_push(tport);
 		port->icount.rx++;
@@ -163,16 +165,16 @@ lqasc_rx_chars(struct uart_port *port)
 		if (rsr & ASCSTATE_ANY) {
 			if (rsr & ASCSTATE_PE) {
 				port->icount.parity++;
-				ltq_w32_mask(0, ASCWHBSTATE_CLRPE,
+				asc_w32_mask(0, ASCWHBSTATE_CLRPE,
 					port->membase + LTQ_ASC_WHBSTATE);
 			} else if (rsr & ASCSTATE_FE) {
 				port->icount.frame++;
-				ltq_w32_mask(0, ASCWHBSTATE_CLRFE,
+				asc_w32_mask(0, ASCWHBSTATE_CLRFE,
 					port->membase + LTQ_ASC_WHBSTATE);
 			}
 			if (rsr & ASCSTATE_ROE) {
 				port->icount.overrun++;
-				ltq_w32_mask(0, ASCWHBSTATE_CLRROE,
+				asc_w32_mask(0, ASCWHBSTATE_CLRROE,
 					port->membase + LTQ_ASC_WHBSTATE);
 			}
 
@@ -202,8 +204,7 @@ lqasc_rx_chars(struct uart_port *port)
 	return 0;
 }
 
-static void
-lqasc_tx_chars(struct uart_port *port)
+static void lqasc_tx_chars(struct uart_port *port)
 {
 	struct circ_buf *xmit = &port->state->xmit;
 	if (uart_tx_stopped(port)) {
@@ -211,10 +212,10 @@ lqasc_tx_chars(struct uart_port *port)
 		return;
 	}
 
-	while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) &
+	while (((readl(port->membase + LTQ_ASC_FSTAT) &
 		ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
 		if (port->x_char) {
-			ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF);
+			writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
 			port->icount.tx++;
 			port->x_char = 0;
 			continue;
@@ -223,8 +224,8 @@ lqasc_tx_chars(struct uart_port *port)
 		if (uart_circ_empty(xmit))
 			break;
 
-		ltq_w8(port->state->xmit.buf[port->state->xmit.tail],
-			port->membase + LTQ_ASC_TBUF);
+		writeb(port->state->xmit.buf[port->state->xmit.tail],
+		       port->membase + LTQ_ASC_TBUF);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 	}
@@ -233,48 +234,58 @@ lqasc_tx_chars(struct uart_port *port)
 		uart_write_wakeup(port);
 }
 
-static irqreturn_t
-lqasc_tx_int(int irq, void *_port)
+static irqreturn_t lqasc_tx_int(int irq, void *_port)
 {
 	unsigned long flags;
 	struct uart_port *port = (struct uart_port *)_port;
 	spin_lock_irqsave(&ltq_asc_lock, flags);
-	ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
+	writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
 	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 	lqasc_start_tx(port);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-lqasc_err_int(int irq, void *_port)
+static irqreturn_t lqasc_err_int(int irq, void *_port)
 {
 	unsigned long flags;
+	u32 stat;
 	struct uart_port *port = (struct uart_port *)_port;
+
 	spin_lock_irqsave(&ltq_asc_lock, flags);
 	/* clear any pending interrupts */
-	ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
-		ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
+	writel(ASC_IRNCR_EIR, port->membase + LTQ_ASC_IRNCR);
+	stat = readl(port->membase + LTQ_ASC_STATE);
+	if ((stat & ASCCON_ROEN)) {
+		asc_w32_mask(0, ASCRXFCON_RXFFLU,
+			     port->membase + LTQ_ASC_RXFCON);
+		port->icount.overrun++;
+	}
+	if (stat & ASCCON_TOEN) {
+		asc_w32_mask(0, ASCTXFCON_TXFFLU,
+			     port->membase + LTQ_ASC_TXFCON);
+		port->icount.overrun++;
+	}
+	asc_w32_mask(0, ASCWHBSTATE_CLRALL, port->membase + LTQ_ASC_WHBSTATE);
 	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-lqasc_rx_int(int irq, void *_port)
+static irqreturn_t lqasc_rx_int(int irq, void *_port)
 {
 	unsigned long flags;
 	struct uart_port *port = (struct uart_port *)_port;
 	spin_lock_irqsave(&ltq_asc_lock, flags);
-	ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
+	writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
 	lqasc_rx_chars(port);
 	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 	return IRQ_HANDLED;
 }
 
-static unsigned int
-lqasc_tx_empty(struct uart_port *port)
+static unsigned int lqasc_tx_empty(struct uart_port *port)
 {
 	int status;
-	status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
+	status = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
 	return status ? 0 : TIOCSER_TEMT;
 }
 
@@ -284,8 +295,7 @@ lqasc_get_mctrl(struct uart_port *port)
 	return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
 }
 
-static void
-lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
+static void lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 }
 
@@ -304,48 +314,49 @@ lqasc_startup(struct uart_port *port)
 		clk_enable(ltq_port->clk);
 	port->uartclk = clk_get_rate(ltq_port->fpiclk);
 
-	ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
+	asc_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
 		port->membase + LTQ_ASC_CLC);
 
-	ltq_w32(0, port->membase + LTQ_ASC_PISEL);
-	ltq_w32(
-		((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
-		ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
-		port->membase + LTQ_ASC_TXFCON);
-	ltq_w32(
-		((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
-		| ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
-		port->membase + LTQ_ASC_RXFCON);
+	writel(0, port->membase + LTQ_ASC_PISEL);
+	writel(((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
+		 ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
+		 port->membase + LTQ_ASC_TXFCON);
+	writel(((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) |
+		 ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
+		 port->membase + LTQ_ASC_RXFCON);
 	/* make sure other settings are written to hardware before
 	 * setting enable bits
 	 */
 	wmb();
-	ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
-		ASCCON_ROEN, port->membase + LTQ_ASC_CON);
+	asc_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
+		     ASCCON_ROEN, port->membase + LTQ_ASC_CON);
 
 	retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
-		0, "asc_tx", port);
+			     0, "asc_tx", port);
 	if (retval) {
 		pr_err("failed to request lqasc_tx_int\n");
 		return retval;
 	}
 
 	retval = request_irq(ltq_port->rx_irq, lqasc_rx_int,
-		0, "asc_rx", port);
+			     0, "asc_rx", port);
 	if (retval) {
 		pr_err("failed to request lqasc_rx_int\n");
 		goto err1;
 	}
 
 	retval = request_irq(ltq_port->err_irq, lqasc_err_int,
-		0, "asc_err", port);
+			     0, "asc_err", port);
 	if (retval) {
 		pr_err("failed to request lqasc_err_int\n");
 		goto err2;
 	}
 
-	ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
-		port->membase + LTQ_ASC_IRNREN);
+	writel(ASC_IRNCR_RIR | ASC_IRNCR_EIR | ASC_IRNCR_TIR,
+	       port->membase + LTQ_ASC_IRNCR);
+	writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
+	       port->membase + LTQ_ASC_IRNEN);
+
 	return 0;
 
 err2:
@@ -355,26 +366,41 @@ lqasc_startup(struct uart_port *port)
 	return retval;
 }
 
-static void
-lqasc_shutdown(struct uart_port *port)
+static void lqasc_shutdown(struct uart_port *port)
 {
+	unsigned long flags;
 	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+	int i = 100;
+
+	writel(0, port->membase + LTQ_ASC_CON);
 	free_irq(ltq_port->tx_irq, port);
 	free_irq(ltq_port->rx_irq, port);
 	free_irq(ltq_port->err_irq, port);
 
-	ltq_w32(0, port->membase + LTQ_ASC_CON);
-	ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
-		port->membase + LTQ_ASC_RXFCON);
-	ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
-		port->membase + LTQ_ASC_TXFCON);
+	spin_lock_irqsave(&ltq_port->lock, flags);
+	/* TX/RX FIFO disable will flush TX/RX FIFO automatically */
+	asc_w32_mask(ASCRXFCON_RXFEN, 0, port->membase + LTQ_ASC_RXFCON);
+	asc_w32_mask(ASCTXFCON_TXFEN, 0, port->membase + LTQ_ASC_TXFCON);
+
+	/* Make sure flush is done, FIFO empty */
+	while ((readl(port->membase + LTQ_ASC_FSTAT) & (ASCFSTAT_RXFFLMASK |
+		ASCFSTAT_TXFFLMASK)) && i--)
+		;
+
+	/*
+	 * Clock off it, TX/RX free FIFO will be always one byte
+	 * Console TX free FIFO check will always pass
+	 */
+	asc_w32_mask(ASCCLC_DISR | ASCCLC_RMCMASK, 0,
+		     port->membase + LTQ_ASC_CLC);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
+
 	if (!IS_ERR(ltq_port->clk))
 		clk_disable(ltq_port->clk);
 }
 
-static void
-lqasc_set_termios(struct uart_port *port,
-	struct ktermios *new, struct ktermios *old)
+static void lqasc_set_termios(struct uart_port *port,
+			      struct ktermios *new, struct ktermios *old)
 {
 	unsigned int cflag;
 	unsigned int iflag;
@@ -382,6 +408,8 @@ lqasc_set_termios(struct uart_port *port,
 	unsigned int baud;
 	unsigned int con = 0;
 	unsigned long flags;
+	u32 fdv = 0;
+	u32 reload = 0;
 
 	cflag = new->c_cflag;
 	iflag = new->c_iflag;
@@ -394,7 +422,7 @@ lqasc_set_termios(struct uart_port *port,
 	case CS5:
 	case CS6:
 	default:
-		new->c_cflag &= ~ CSIZE;
+		new->c_cflag &= ~CSIZE;
 		new->c_cflag |= CS8;
 		con = ASCCON_M_8ASYNC;
 		break;
@@ -438,30 +466,29 @@ lqasc_set_termios(struct uart_port *port,
 	spin_lock_irqsave(&ltq_asc_lock, flags);
 
 	/* set up CON */
-	ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON);
+	asc_w32_mask(0, con, port->membase + LTQ_ASC_CON);
 
 	/* Set baud rate - take a divider of 2 into account */
 	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
 	divisor = uart_get_divisor(port, baud);
 	divisor = divisor / 2 - 1;
 
-	/* disable the baudrate generator */
-	ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
-
-	/* make sure the fractional divider is off */
-	ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON);
-
-	/* set up to use divisor of 2 */
-	ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
+	asc_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
+	/* Ensure the setting is effect before enabling */
+	wmb();
+	/* make sure the fractional divider is enabled */
+	asc_w32_mask(0, ASCCON_FDE, port->membase + LTQ_ASC_CON);
 
 	/* now we can write the new baudrate into the register */
-	ltq_w32(divisor, port->membase + LTQ_ASC_BG);
+	writel(reload, port->membase + LTQ_ASC_BG);
+	/* now we can write the new baudrate into the register */
+	writel(fdv, port->membase + LTQ_ASC_FDV);
 
 	/* turn the baudrate generator back on */
-	ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
+	asc_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
 
 	/* enable rx */
-	ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
+	writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
 
 	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 
@@ -472,8 +499,7 @@ lqasc_set_termios(struct uart_port *port,
 	uart_update_timeout(port, cflag, baud);
 }
 
-static const char*
-lqasc_type(struct uart_port *port)
+static const char *lqasc_type(struct uart_port *port)
 {
 	if (port->type == PORT_LTQ_ASC)
 		return DRVNAME;
@@ -481,8 +507,7 @@ lqasc_type(struct uart_port *port)
 		return NULL;
 }
 
-static void
-lqasc_release_port(struct uart_port *port)
+static void lqasc_release_port(struct uart_port *port)
 {
 	struct platform_device *pdev = to_platform_device(port->dev);
 
@@ -492,8 +517,7 @@ lqasc_release_port(struct uart_port *port)
 	}
 }
 
-static int
-lqasc_request_port(struct uart_port *port)
+static int lqasc_request_port(struct uart_port *port)
 {
 	struct platform_device *pdev = to_platform_device(port->dev);
 	struct resource *res;
@@ -507,7 +531,7 @@ lqasc_request_port(struct uart_port *port)
 	size = resource_size(res);
 
 	res = devm_request_mem_region(&pdev->dev, res->start,
-		size, dev_name(&pdev->dev));
+				      size, dev_name(&pdev->dev));
 	if (!res) {
 		dev_err(&pdev->dev, "cannot request I/O memory region");
 		return -EBUSY;
@@ -515,15 +539,14 @@ lqasc_request_port(struct uart_port *port)
 
 	if (port->flags & UPF_IOREMAP) {
 		port->membase = devm_ioremap_nocache(&pdev->dev,
-			port->mapbase, size);
+						     port->mapbase, size);
 		if (port->membase == NULL)
 			return -ENOMEM;
 	}
 	return 0;
 }
 
-static void
-lqasc_config_port(struct uart_port *port, int flags)
+static void lqasc_config_port(struct uart_port *port, int flags)
 {
 	if (flags & UART_CONFIG_TYPE) {
 		port->type = PORT_LTQ_ASC;
@@ -531,17 +554,17 @@ lqasc_config_port(struct uart_port *port, int flags)
 	}
 }
 
-static int
-lqasc_verify_port(struct uart_port *port,
-	struct serial_struct *ser)
+static int lqasc_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
 	int ret = 0;
+
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC)
 		ret = -EINVAL;
 	if (ser->irq < 0 || ser->irq >= NR_IRQS)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
+
 	return ret;
 }
 
@@ -563,8 +586,7 @@ static const struct uart_ops lqasc_pops = {
 	.verify_port =	lqasc_verify_port,
 };
 
-static void
-lqasc_console_putchar(struct uart_port *port, int ch)
+static void lqasc_console_putchar(struct uart_port *port, int ch)
 {
 	int fifofree;
 
@@ -572,10 +594,11 @@ lqasc_console_putchar(struct uart_port *port, int ch)
 		return;
 
 	do {
-		fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT)
+		fifofree = (readl(port->membase + LTQ_ASC_FSTAT)
 			& ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
 	} while (fifofree == 0);
-	ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
+
+	writeb(ch, port->membase + LTQ_ASC_TBUF);
 }
 
 static void lqasc_serial_port_write(struct uart_port *port, const char *s,
@@ -588,8 +611,7 @@ static void lqasc_serial_port_write(struct uart_port *port, const char *s,
 	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 }
 
-static void
-lqasc_console_write(struct console *co, const char *s, u_int count)
+static void lqasc_console_write(struct console *co, const char *s, u_int count)
 {
 	struct ltq_uart_port *ltq_port;
 
@@ -603,8 +625,7 @@ lqasc_console_write(struct console *co, const char *s, u_int count)
 	lqasc_serial_port_write(&ltq_port->port, s, count);
 }
 
-static int __init
-lqasc_console_setup(struct console *co, char *options)
+static int __init lqasc_console_setup(struct console *co, char *options)
 {
 	struct ltq_uart_port *ltq_port;
 	struct uart_port *port;
@@ -629,6 +650,7 @@ lqasc_console_setup(struct console *co, char *options)
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
@@ -642,8 +664,7 @@ static struct console lqasc_console = {
 	.data =		&lqasc_reg,
 };
 
-static int __init
-lqasc_console_init(void)
+static int __init lqasc_console_init(void)
 {
 	register_console(&lqasc_console);
 	return 0;
@@ -667,6 +688,7 @@ lqasc_serial_early_console_setup(struct earlycon_device *device,
 		return -ENODEV;
 
 	device->con->write = lqasc_serial_early_console_write;
+
 	return 0;
 }
 OF_EARLYCON_DECLARE(lantiq, DRVNAME, lqasc_serial_early_console_setup);
@@ -681,8 +703,7 @@ static struct uart_driver lqasc_reg = {
 	.cons =		&lqasc_console,
 };
 
-static int __init
-lqasc_probe(struct platform_device *pdev)
+static int __init lqasc_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct ltq_uart_port *ltq_port;
@@ -693,7 +714,7 @@ lqasc_probe(struct platform_device *pdev)
 
 	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ret = of_irq_to_resource_table(node, irqres, 3);
-	if (!mmres || (ret != 3)) {
+	if (!mmres || ret != 3) {
 		dev_err(&pdev->dev,
 			"failed to get memory/irq for serial port\n");
 		return -ENODEV;
@@ -709,7 +730,7 @@ lqasc_probe(struct platform_device *pdev)
 	}
 
 	ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port),
-			GFP_KERNEL);
+				GFP_KERNEL);
 	if (!ltq_port)
 		return -ENOMEM;
 
@@ -759,8 +780,7 @@ static struct platform_driver lqasc_driver = {
 	},
 };
 
-int __init
-init_lqasc(void)
+int __init init_lqasc(void)
 {
 	int ret;
 
-- 
2.11.0


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

* [PATCH 5/7] tty: serial: lantiq: Convert global lock to per device lock
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
                   ` (3 preceding siblings ...)
  2018-06-12  5:40 ` [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel() Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12  5:40 ` [PATCH 6/7] tty: serial: lantiq: Remove unneeded header includes and macros Songjun Wu
  2018-06-12  5:40 ` [PATCH 7/7] tty: serial: lantiq: Add CCF support Songjun Wu
  6 siblings, 0 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, Greg Kroah-Hartman, linux-kernel, Jiri Slaby

Previous implementation uses one global lock to protect the resource.
If the serial driver have multiple entries, this kind of lock will
slow down the performance.
Add the lock at device level. This will lock only when the function
calling only to the same device.
So that it can avoid useless lock protection.

Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
---

 drivers/tty/serial/lantiq.c | 51 ++++++++++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 1127586dbc94..72aab1b05265 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -107,7 +107,6 @@
 static void lqasc_tx_chars(struct uart_port *port);
 static struct ltq_uart_port *lqasc_port[MAXPORTS];
 static struct uart_driver lqasc_reg;
-static DEFINE_SPINLOCK(ltq_asc_lock);
 
 struct ltq_uart_port {
 	struct uart_port	port;
@@ -118,6 +117,7 @@ struct ltq_uart_port {
 	unsigned int		tx_irq;
 	unsigned int		rx_irq;
 	unsigned int		err_irq;
+	spinlock_t		lock;  /* exclusive access for multi core */
 };
 
 static inline struct ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
@@ -133,10 +133,11 @@ static void lqasc_stop_tx(struct uart_port *port)
 static void lqasc_start_tx(struct uart_port *port)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&ltq_asc_lock, flags);
+	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+
+	spin_lock_irqsave(&ltq_port->lock, flags);
 	lqasc_tx_chars(port);
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
-	return;
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
 }
 
 static void lqasc_stop_rx(struct uart_port *port)
@@ -238,10 +239,14 @@ static irqreturn_t lqasc_tx_int(int irq, void *_port)
 {
 	unsigned long flags;
 	struct uart_port *port = (struct uart_port *)_port;
-	spin_lock_irqsave(&ltq_asc_lock, flags);
+	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+
+	spin_lock_irqsave(&ltq_port->lock, flags);
 	writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
+
 	lqasc_start_tx(port);
+
 	return IRQ_HANDLED;
 }
 
@@ -250,8 +255,9 @@ static irqreturn_t lqasc_err_int(int irq, void *_port)
 	unsigned long flags;
 	u32 stat;
 	struct uart_port *port = (struct uart_port *)_port;
+	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 
-	spin_lock_irqsave(&ltq_asc_lock, flags);
+	spin_lock_irqsave(&ltq_port->lock, flags);
 	/* clear any pending interrupts */
 	writel(ASC_IRNCR_EIR, port->membase + LTQ_ASC_IRNCR);
 	stat = readl(port->membase + LTQ_ASC_STATE);
@@ -266,7 +272,7 @@ static irqreturn_t lqasc_err_int(int irq, void *_port)
 		port->icount.overrun++;
 	}
 	asc_w32_mask(0, ASCWHBSTATE_CLRALL, port->membase + LTQ_ASC_WHBSTATE);
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
 
 	return IRQ_HANDLED;
 }
@@ -275,10 +281,13 @@ static irqreturn_t lqasc_rx_int(int irq, void *_port)
 {
 	unsigned long flags;
 	struct uart_port *port = (struct uart_port *)_port;
-	spin_lock_irqsave(&ltq_asc_lock, flags);
+	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+
+	spin_lock_irqsave(&ltq_port->lock, flags);
 	writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
 	lqasc_rx_chars(port);
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
@@ -309,11 +318,13 @@ lqasc_startup(struct uart_port *port)
 {
 	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 	int retval;
+	unsigned long flags;
 
 	if (!IS_ERR(ltq_port->clk))
 		clk_enable(ltq_port->clk);
 	port->uartclk = clk_get_rate(ltq_port->fpiclk);
 
+	spin_lock_irqsave(&ltq_port->lock, flags);
 	asc_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
 		port->membase + LTQ_ASC_CLC);
 
@@ -330,6 +341,7 @@ lqasc_startup(struct uart_port *port)
 	wmb();
 	asc_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
 		     ASCCON_ROEN, port->membase + LTQ_ASC_CON);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
 
 	retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
 			     0, "asc_tx", port);
@@ -410,6 +422,7 @@ static void lqasc_set_termios(struct uart_port *port,
 	unsigned long flags;
 	u32 fdv = 0;
 	u32 reload = 0;
+	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 
 	cflag = new->c_cflag;
 	iflag = new->c_iflag;
@@ -463,7 +476,7 @@ static void lqasc_set_termios(struct uart_port *port,
 	/* set error signals  - framing, parity  and overrun, enable receiver */
 	con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
 
-	spin_lock_irqsave(&ltq_asc_lock, flags);
+	spin_lock_irqsave(&ltq_port->lock, flags);
 
 	/* set up CON */
 	asc_w32_mask(0, con, port->membase + LTQ_ASC_CON);
@@ -490,7 +503,7 @@ static void lqasc_set_termios(struct uart_port *port,
 	/* enable rx */
 	writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
 
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
 
 	/* Don't rewrite B0 */
 	if (tty_termios_baud_rate(new))
@@ -604,16 +617,14 @@ static void lqasc_console_putchar(struct uart_port *port, int ch)
 static void lqasc_serial_port_write(struct uart_port *port, const char *s,
 				    u_int count)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&ltq_asc_lock, flags);
 	uart_console_write(port, s, count, lqasc_console_putchar);
-	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 }
 
 static void lqasc_console_write(struct console *co, const char *s, u_int count)
 {
+	unsigned long flags;
 	struct ltq_uart_port *ltq_port;
+	struct uart_port *port;
 
 	if (co->index >= MAXPORTS)
 		return;
@@ -622,7 +633,11 @@ static void lqasc_console_write(struct console *co, const char *s, u_int count)
 	if (!ltq_port)
 		return;
 
-	lqasc_serial_port_write(&ltq_port->port, s, count);
+	port = &ltq_port->port;
+
+	spin_lock_irqsave(&ltq_port->lock, flags);
+	lqasc_serial_port_write(port, s, count);
+	spin_unlock_irqrestore(&ltq_port->lock, flags);
 }
 
 static int __init lqasc_console_setup(struct console *co, char *options)
@@ -760,6 +775,8 @@ static int __init lqasc_probe(struct platform_device *pdev)
 	ltq_port->rx_irq = irqres[1].start;
 	ltq_port->err_irq = irqres[2].start;
 
+	spin_lock_init(&ltq_port->lock);
+
 	lqasc_port[line] = ltq_port;
 	platform_set_drvdata(pdev, ltq_port);
 
-- 
2.11.0


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

* [PATCH 6/7] tty: serial: lantiq: Remove unneeded header includes and macros
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
                   ` (4 preceding siblings ...)
  2018-06-12  5:40 ` [PATCH 5/7] tty: serial: lantiq: Convert global lock to per device lock Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12  5:40 ` [PATCH 7/7] tty: serial: lantiq: Add CCF support Songjun Wu
  6 siblings, 0 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, Greg Kroah-Hartman, linux-kernel, Jiri Slaby

Update the author list with Intel Corporation.
Sort the header includes in alphabetical orders.
Remove unneeded header includes and macros.

Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
---

 drivers/tty/serial/lantiq.c | 29 +++++++++++------------------
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 72aab1b05265..cc33208c93ac 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -6,24 +6,23 @@
  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
  * Copyright (C) 2007 John Crispin <john@phrozen.org>
  * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
+ * Copyright (C) 2017 Intel Corporation.
  */
 
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/console.h>
-#include <linux/sysrq.h>
 #include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
 
 #include <lantiq_soc.h>
 
@@ -43,7 +42,6 @@
 #define LTQ_ASC_STATE		0x0014
 #define LTQ_ASC_IRNCR		0x00F8
 #define LTQ_ASC_CLC		0x0000
-#define LTQ_ASC_ID		0x0008
 #define LTQ_ASC_PISEL		0x0004
 #define LTQ_ASC_TXFCON		0x0044
 #define LTQ_ASC_RXFCON		0x0040
@@ -51,16 +49,12 @@
 #define LTQ_ASC_BG		0x0050
 #define LTQ_ASC_FDV		0x0058
 #define LTQ_ASC_IRNEN		0x00F4
-
 #define ASC_IRNREN_TX		0x1
 #define ASC_IRNREN_RX		0x2
 #define ASC_IRNREN_ERR		0x4
-#define ASC_IRNREN_TX_BUF	0x8
 #define ASC_IRNCR_TIR		0x1
 #define ASC_IRNCR_RIR		0x2
 #define ASC_IRNCR_EIR		0x4
-
-#define ASCOPT_CSIZE		0x3
 #define TXFIFO_FL		1
 #define RXFIFO_FL		1
 #define ASCCLC_DISR		0x1
@@ -71,7 +65,6 @@
 #define ASCCON_M_7ASYNC		0x2
 #define ASCCON_ODD		0x00000020
 #define ASCCON_STP		0x00000080
-#define ASCCON_BRS		0x00000100
 #define ASCCON_FDE		0x00000200
 #define ASCCON_R		0x00008000
 #define ASCCON_FEN		0x00020000
@@ -80,7 +73,7 @@
 #define ASCSTATE_PE		0x00010000
 #define ASCSTATE_FE		0x00020000
 #define ASCSTATE_ROE		0x00080000
-#define ASCSTATE_ANY		(ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
+#define ASCSTATE_ANY		(ASCSTATE_ROE | ASCSTATE_PE | ASCSTATE_FE)
 #define ASCWHBSTATE_CLRREN	0x00000001
 #define ASCWHBSTATE_SETREN	0x00000002
 #define ASCWHBSTATE_CLRPE	0x00000004
-- 
2.11.0


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

* [PATCH 7/7] tty: serial: lantiq: Add CCF support
  2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
                   ` (5 preceding siblings ...)
  2018-06-12  5:40 ` [PATCH 6/7] tty: serial: lantiq: Remove unneeded header includes and macros Songjun Wu
@ 2018-06-12  5:40 ` Songjun Wu
  2018-06-12  8:07     ` kbuild test robot
  2018-06-12 22:39   ` Rob Herring
  6 siblings, 2 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-12  5:40 UTC (permalink / raw)
  To: hua.ma, yixin.zhu, chuanhua.lei
  Cc: linux-mips, qi-ming.wu, linux-clk, linux-serial, devicetree,
	Songjun Wu, Jiri Slaby, linux-kernel, Rob Herring,
	Greg Kroah-Hartman, Mark Rutland

Previous implementation uses platform-dependent API to get the clock.
Those functions are not available for other SoC which uses the same IP.
The CCF (Common Clock Framework) have an abstraction based APIs
for clock.
Change to use CCF APIs to get clock and rate.
So that different SoCs can use the same driver.
Clocks and clock-names are updated in device tree binding.

Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>

---

 .../devicetree/bindings/serial/lantiq_asc.txt      |  15 +++
 drivers/tty/serial/Kconfig                         |   2 +-
 drivers/tty/serial/lantiq.c                        | 101 +++++++++++++++++----
 3 files changed, 98 insertions(+), 20 deletions(-)

diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
index 3acbd309ab9d..608f0c87a4af 100644
--- a/Documentation/devicetree/bindings/serial/lantiq_asc.txt
+++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
@@ -6,6 +6,10 @@ Required properties:
 - interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier
   depends on the interrupt-parent interrupt controller.
 
+Optional properties:
+- clocks: Should contain frequency clock and gate clock
+- clock-names: Should be "freq" and "asc"
+
 Example:
 
 asc1: serial@e100c00 {
@@ -14,3 +18,14 @@ asc1: serial@e100c00 {
 	interrupt-parent = <&icu0>;
 	interrupts = <112 113 114>;
 };
+
+asc0: serial@600000 {
+	compatible = "lantiq,asc";
+	reg = <0x600000 0x100000>;
+	interrupt-parent = <&gic>;
+	interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>,
+	<GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>,
+	<GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&pll0aclk SSX4_CLK>, <&clkgate1 GATE_URT_CLK>;
+	clock-names = "freq", "asc";
+};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 0f058df0b070..0f8ac5872a54 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1062,7 +1062,7 @@ config SERIAL_OMAP_CONSOLE
 
 config SERIAL_LANTIQ
 	bool "Lantiq serial driver"
-	depends on LANTIQ
+	depends on LANTIQ || INTEL_MIPS || COMPILE_TEST
 	select SERIAL_CORE
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_EARLYCON
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index cc33208c93ac..fd7ba89daaa2 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -24,7 +24,9 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
+#ifndef CONFIG_COMMON_CLK
 #include <lantiq_soc.h>
+#endif
 
 #define PORT_LTQ_ASC		111
 #define MAXPORTS		2
@@ -104,7 +106,7 @@ static struct uart_driver lqasc_reg;
 struct ltq_uart_port {
 	struct uart_port	port;
 	/* clock used to derive divider */
-	struct clk		*fpiclk;
+	struct clk		*freqclk;
 	/* clock gating of the ASC core */
 	struct clk		*clk;
 	unsigned int		tx_irq;
@@ -120,7 +122,6 @@ static inline struct ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
 
 static void lqasc_stop_tx(struct uart_port *port)
 {
-	return;
 }
 
 static void lqasc_start_tx(struct uart_port *port)
@@ -291,8 +292,7 @@ static unsigned int lqasc_tx_empty(struct uart_port *port)
 	return status ? 0 : TIOCSER_TEMT;
 }
 
-static unsigned int
-lqasc_get_mctrl(struct uart_port *port)
+static unsigned int lqasc_get_mctrl(struct uart_port *port)
 {
 	return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
 }
@@ -301,21 +301,65 @@ static void lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 }
 
-static void
-lqasc_break_ctl(struct uart_port *port, int break_state)
+static void lqasc_break_ctl(struct uart_port *port, int break_state)
 {
 }
 
-static int
-lqasc_startup(struct uart_port *port)
+static void lqasc_fdv_and_reload_get(struct ltq_uart_port *ltq_port,
+				     unsigned int baudrate, unsigned int *fdv,
+				     unsigned int *reload)
+{
+	unsigned int asc_clk = clk_get_rate(ltq_port->freqclk);
+	unsigned int baudrate1 = baudrate * 8192;
+	unsigned long long baudrate2 = (unsigned long long)baudrate * 1000;
+	unsigned long long fdv_over_bg_fpi;
+	unsigned long long fdv_over_bg;
+	unsigned long long difference;
+	unsigned long long min_difference;
+	unsigned int bg;
+
+	/* Sanity check first */
+	if (baudrate >= (asc_clk >> 4)) {
+		pr_err("%s current fpi clock %u can't provide baudrate %u!!!\n",
+		       __func__, asc_clk, baudrate);
+		return;
+	}
+
+	min_difference = UINT_MAX;
+	fdv_over_bg_fpi = baudrate1;
+
+	for (bg = 1; bg <= 8192; bg++, fdv_over_bg_fpi += baudrate1) {
+		fdv_over_bg = fdv_over_bg_fpi + asc_clk / 2;
+		do_div(fdv_over_bg, asc_clk);
+		if (fdv_over_bg <= 512) {
+			difference = fdv_over_bg * asc_clk * 1000;
+			do_div(difference, 8192 * bg);
+			if (difference < baudrate2)
+				difference = baudrate2 - difference;
+			else
+				difference -= baudrate2;
+			if (difference < min_difference) {
+				*fdv = (unsigned int)fdv_over_bg & 511;
+				*reload = bg - 1;
+				min_difference = difference;
+			}
+			/* Perfect one found */
+			if (min_difference == 0)
+				break;
+		}
+	}
+}
+
+static int lqasc_startup(struct uart_port *port)
 {
 	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 	int retval;
 	unsigned long flags;
 
 	if (!IS_ERR(ltq_port->clk))
-		clk_enable(ltq_port->clk);
-	port->uartclk = clk_get_rate(ltq_port->fpiclk);
+		clk_prepare_enable(ltq_port->clk);
+
+	port->uartclk = clk_get_rate(ltq_port->freqclk);
 
 	spin_lock_irqsave(&ltq_port->lock, flags);
 	asc_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
@@ -378,6 +422,7 @@ static void lqasc_shutdown(struct uart_port *port)
 	int i = 100;
 
 	writel(0, port->membase + LTQ_ASC_CON);
+	writel(0, port->membase + LTQ_ASC_IRNEN);
 	free_irq(ltq_port->tx_irq, port);
 	free_irq(ltq_port->rx_irq, port);
 	free_irq(ltq_port->err_irq, port);
@@ -401,7 +446,7 @@ static void lqasc_shutdown(struct uart_port *port)
 	spin_unlock_irqrestore(&ltq_port->lock, flags);
 
 	if (!IS_ERR(ltq_port->clk))
-		clk_disable(ltq_port->clk);
+		clk_disable_unprepare(ltq_port->clk);
 }
 
 static void lqasc_set_termios(struct uart_port *port,
@@ -476,9 +521,13 @@ static void lqasc_set_termios(struct uart_port *port,
 
 	/* Set baud rate - take a divider of 2 into account */
 	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+	if (baud)
+		lqasc_fdv_and_reload_get(ltq_port, baud, &fdv, &reload);
+
 	divisor = uart_get_divisor(port, baud);
 	divisor = divisor / 2 - 1;
 
+	/* Disable the baudrate generator */
 	asc_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
 	/* Ensure the setting is effect before enabling */
 	wmb();
@@ -490,6 +539,9 @@ static void lqasc_set_termios(struct uart_port *port,
 	/* now we can write the new baudrate into the register */
 	writel(fdv, port->membase + LTQ_ASC_FDV);
 
+	/* Ensure baud configuration takes effetive before enabling */
+	wmb();
+
 	/* turn the baudrate generator back on */
 	asc_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
 
@@ -546,7 +598,7 @@ static int lqasc_request_port(struct uart_port *port)
 	if (port->flags & UPF_IOREMAP) {
 		port->membase = devm_ioremap_nocache(&pdev->dev,
 						     port->mapbase, size);
-		if (port->membase == NULL)
+		if (!port->membase)
 			return -ENOMEM;
 	}
 	return 0;
@@ -652,9 +704,9 @@ static int __init lqasc_console_setup(struct console *co, char *options)
 	port = &ltq_port->port;
 
 	if (!IS_ERR(ltq_port->clk))
-		clk_enable(ltq_port->clk);
+		clk_prepare_enable(ltq_port->clk);
 
-	port->uartclk = clk_get_rate(ltq_port->fpiclk);
+	port->uartclk = clk_get_rate(ltq_port->freqclk);
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -729,8 +781,11 @@ static int __init lqasc_probe(struct platform_device *pdev)
 	}
 
 	/* check if this is the console port */
-	if (mmres->start != CPHYSADDR(LTQ_EARLY_ASC))
-		line = 1;
+	line = of_alias_get_id(node, "serial");
+	if (line < 0) {
+		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", line);
+		return line;
+	}
 
 	if (lqasc_port[line]) {
 		dev_err(&pdev->dev, "port %d already allocated\n", line);
@@ -755,14 +810,22 @@ static int __init lqasc_probe(struct platform_device *pdev)
 	port->irq	= irqres[0].start;
 	port->mapbase	= mmres->start;
 
-	ltq_port->fpiclk = clk_get_fpi();
-	if (IS_ERR(ltq_port->fpiclk)) {
+#ifdef CONFIG_COMMON_CLK
+	ltq_port->freqclk = devm_clk_get(&pdev->dev, "freq");
+#else
+	ltq_port->freqclk = clk_get_fpi();
+#endif
+	if (IS_ERR(ltq_port->freqclk)) {
 		pr_err("failed to get fpi clk\n");
 		return -ENOENT;
 	}
 
 	/* not all asc ports have clock gates, lets ignore the return code */
+#ifdef CONFIG_COMMON_CLK
+	ltq_port->clk = devm_clk_get(&pdev->dev, "asc");
+#else
 	ltq_port->clk = clk_get(&pdev->dev, NULL);
+#endif
 
 	ltq_port->tx_irq = irqres[0].start;
 	ltq_port->rx_irq = irqres[1].start;
@@ -790,7 +853,7 @@ static struct platform_driver lqasc_driver = {
 	},
 };
 
-int __init init_lqasc(void)
+static int __init init_lqasc(void)
 {
 	int ret;
 
-- 
2.11.0


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

* Re: [PATCH 7/7] tty: serial: lantiq: Add CCF support
  2018-06-12  5:40 ` [PATCH 7/7] tty: serial: lantiq: Add CCF support Songjun Wu
  2018-06-12  8:07     ` kbuild test robot
@ 2018-06-12  8:07     ` kbuild test robot
  1 sibling, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2018-06-12  8:07 UTC (permalink / raw)
  To: Songjun Wu
  Cc: kbuild-all, hua.ma, yixin.zhu, chuanhua.lei, linux-mips,
	qi-ming.wu, linux-clk, linux-serial, devicetree, Songjun Wu,
	Jiri Slaby, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Mark Rutland

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

Hi Songjun,

I love your patch! Yet something to improve:

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

url:    https://github.com/0day-ci/linux/commits/Songjun-Wu/MIPS-intel-add-initial-support-for-Intel-MIPS-SoCs/20180612-134457
config: s390-allmodconfig (attached as .config)
compiler: s390x-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=s390 

All errors (new ones prefixed by >>):

>> drivers/tty/serial/lantiq.c:28:10: fatal error: lantiq_soc.h: No such file or directory
    #include <lantiq_soc.h>
             ^~~~~~~~~~~~~~
   compilation terminated.

vim +28 drivers/tty/serial/lantiq.c

2f0fc415 John Crispin 2011-04-05  26  
c17405a9 Songjun Wu   2018-06-12  27  #ifndef CONFIG_COMMON_CLK
2f0fc415 John Crispin 2011-04-05 @28  #include <lantiq_soc.h>
c17405a9 Songjun Wu   2018-06-12  29  #endif
2f0fc415 John Crispin 2011-04-05  30  

:::::: The code at line 28 was first introduced by commit
:::::: 2f0fc4159a6abc20b13569522c545150b99485cf SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.

:::::: TO: John Crispin <blogic@openwrt.org>
:::::: CC: Ralf Baechle <ralf@linux-mips.org>

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

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

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

* Re: [PATCH 7/7] tty: serial: lantiq: Add CCF support
@ 2018-06-12  8:07     ` kbuild test robot
  0 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2018-06-12  8:07 UTC (permalink / raw)
  Cc: kbuild-all, hua.ma, yixin.zhu, chuanhua.lei, linux-mips,
	qi-ming.wu, linux-clk, linux-serial, devicetree, Songjun Wu,
	Jiri Slaby, linux-kernel, Rob Herring, Greg Kroah-Hartman,
	Mark Rutland

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

Hi Songjun,

I love your patch! Yet something to improve:

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

url:    https://github.com/0day-ci/linux/commits/Songjun-Wu/MIPS-intel-add-initial-support-for-Intel-MIPS-SoCs/20180612-134457
config: s390-allmodconfig (attached as .config)
compiler: s390x-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=s390 

All errors (new ones prefixed by >>):

>> drivers/tty/serial/lantiq.c:28:10: fatal error: lantiq_soc.h: No such file or directory
    #include <lantiq_soc.h>
             ^~~~~~~~~~~~~~
   compilation terminated.

vim +28 drivers/tty/serial/lantiq.c

2f0fc415 John Crispin 2011-04-05  26  
c17405a9 Songjun Wu   2018-06-12  27  #ifndef CONFIG_COMMON_CLK
2f0fc415 John Crispin 2011-04-05 @28  #include <lantiq_soc.h>
c17405a9 Songjun Wu   2018-06-12  29  #endif
2f0fc415 John Crispin 2011-04-05  30  

:::::: The code at line 28 was first introduced by commit
:::::: 2f0fc4159a6abc20b13569522c545150b99485cf SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.

:::::: TO: John Crispin <blogic@openwrt.org>
:::::: CC: Ralf Baechle <ralf@linux-mips.org>

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

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

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

* Re: [PATCH 7/7] tty: serial: lantiq: Add CCF support
@ 2018-06-12  8:07     ` kbuild test robot
  0 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2018-06-12  8:07 UTC (permalink / raw)
  To: Songjun Wu
  Cc: kbuild-all, hua.ma, yixin.zhu, chuanhua.lei, linux-mips,
	qi-ming.wu, linux-clk, linux-serial, devicetree, Jiri Slaby,
	linux-kernel, Rob Herring, Greg Kroah-Hartman, Mark Rutland

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

Hi Songjun,

I love your patch! Yet something to improve:

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

url:    https://github.com/0day-ci/linux/commits/Songjun-Wu/MIPS-intel-add-initial-support-for-Intel-MIPS-SoCs/20180612-134457
config: s390-allmodconfig (attached as .config)
compiler: s390x-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=s390 

All errors (new ones prefixed by >>):

>> drivers/tty/serial/lantiq.c:28:10: fatal error: lantiq_soc.h: No such file or directory
    #include <lantiq_soc.h>
             ^~~~~~~~~~~~~~
   compilation terminated.

vim +28 drivers/tty/serial/lantiq.c

2f0fc415 John Crispin 2011-04-05  26  
c17405a9 Songjun Wu   2018-06-12  27  #ifndef CONFIG_COMMON_CLK
2f0fc415 John Crispin 2011-04-05 @28  #include <lantiq_soc.h>
c17405a9 Songjun Wu   2018-06-12  29  #endif
2f0fc415 John Crispin 2011-04-05  30  

:::::: The code at line 28 was first introduced by commit
:::::: 2f0fc4159a6abc20b13569522c545150b99485cf SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.

:::::: TO: John Crispin <blogic@openwrt.org>
:::::: CC: Ralf Baechle <ralf@linux-mips.org>

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

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

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

* Re: [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel()
  2018-06-12  5:40 ` [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel() Songjun Wu
@ 2018-06-12  8:13   ` Andy Shevchenko
  2018-06-14  7:05     ` Wu, Songjun
  2018-06-14 10:07   ` Arnd Bergmann
  1 sibling, 1 reply; 33+ messages in thread
From: Andy Shevchenko @ 2018-06-12  8:13 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei, Linux MIPS Mailing List,
	qi-ming.wu, linux-clk, open list:SERIAL DRIVERS, devicetree,
	James Hogan, Jiri Slaby, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Ralf Baechle

On Tue, Jun 12, 2018 at 8:40 AM, Songjun Wu <songjun.wu@linux.intel.com> wrote:
> Previous implementation uses platform-dependent functions
> ltq_w32()/ltq_r32() to access registers. Those functions are not
> available for other SoC which uses the same IP.
> Change to OS provided readl()/writel() and readb()/writeb(), so
> that different SoCs can use the same driver.

This patch consists 2 or even 3 ones:
- whitespace shuffling (indentation fixes, blank lines), I dunno if
it's needed at all
- some new registers / bits
- actual switch to readl() / writel()

Please, split.

> +#define asc_w32_mask(clear, set, reg)  \
> +       ({ typeof(reg) reg_ = (reg);    \
> +       writel((readl(reg_) & ~(clear)) | (set), reg_); })

This would be better as a static inline helper, and name is completely
misleading, it doesn't mask the register bits, it _updates_ them.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs
  2018-06-12  5:40 ` [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs Songjun Wu
@ 2018-06-12 11:23   ` James Hogan
  2018-06-14  9:24     ` yixin zhu
  2018-06-12 22:31   ` Rob Herring
  1 sibling, 1 reply; 33+ messages in thread
From: James Hogan @ 2018-06-12 11:23 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, linux-kernel, Rob Herring,
	Ralf Baechle, Mark Rutland

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

Hi,

Good to see this patch!

On Tue, Jun 12, 2018 at 01:40:30PM +0800, Songjun Wu wrote:
> diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
> index ac7ad54f984f..bcd647060f3e 100644
> --- a/arch/mips/Kbuild.platforms
> +++ b/arch/mips/Kbuild.platforms
> @@ -12,6 +12,7 @@ platforms += cobalt
>  platforms += dec
>  platforms += emma
>  platforms += generic
> +platforms += intel-mips

What are the main things preventing this from moving to the generic
platform? Is it mainly the use of EVA (which generic doesn't yet
support)?

> diff --git a/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h b/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
> new file mode 100644
> index 000000000000..3893855b60c6
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
...
> +	/*
> +	 * Get Config.K0 value and use it to program
> +	 * the segmentation registers

Please can you describe (maybe with a table) the segment layout in human
readable terms so the reader doesn't need to decode the SegCtl registers
to understand where everything is in the virtual address space?

> diff --git a/arch/mips/boot/dts/intel-mips/Makefile b/arch/mips/boot/dts/intel-mips/Makefile
> new file mode 100644
> index 000000000000..b16c0081639c
> --- /dev/null
> +++ b/arch/mips/boot/dts/intel-mips/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +dtb-$(CONFIG_DTB_INTEL_MIPS_GRX500)	+= easy350_anywan.dtb
> +obj-y	+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))

This needs updating to obj-$(CONFIG_BUILTIN_DTB) as per commit
fca3aa166422 ("MIPS: dts: Avoid unneeded built-in.a in DTS dirs") in
linux-next.

> diff --git a/arch/mips/intel-mips/Makefile b/arch/mips/intel-mips/Makefile
> new file mode 100644
> index 000000000000..9f272d06eecd
> --- /dev/null
> +++ b/arch/mips/intel-mips/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_INTEL_MIPS)	+= prom.o irq.o time.o

You can use obj-y, since this Makefile is only included if
CONFIG_INTEL_MIPS=y (i.e. via the platform-$(CONFIG_INTEL_MIPS) below).

Also please split each file onto separate "obj-y += whatever.o" lines.

> diff --git a/arch/mips/intel-mips/Platform b/arch/mips/intel-mips/Platform
> new file mode 100644
> index 000000000000..b34750eeaeb0
> --- /dev/null
> +++ b/arch/mips/intel-mips/Platform
> @@ -0,0 +1,11 @@
> +#
> +# MIPs SoC platform
> +#
> +
> +platform-$(CONFIG_INTEL_MIPS)			+= intel-mips/

^^^ (this is what ensures the Makefile is only included for this
platform)

> diff --git a/arch/mips/intel-mips/irq.c b/arch/mips/intel-mips/irq.c
> new file mode 100644
> index 000000000000..00637a5cdd20
> --- /dev/null
> +++ b/arch/mips/intel-mips/irq.c
> @@ -0,0 +1,36 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2016 Intel Corporation.
> + */
> +#include <linux/init.h>
> +#include <linux/irqchip.h>
> +#include <linux/of_irq.h>
> +#include <asm/irq.h>
> +
> +#include <asm/irq_cpu.h>
> +
> +void __init arch_init_irq(void)
> +{
> +	struct device_node *intc_node;
> +
> +	pr_info("EIC is %s\n", cpu_has_veic ? "on" : "off");
> +	pr_info("VINT is %s\n", cpu_has_vint ? "on" : "off");
> +
> +	intc_node = of_find_compatible_node(NULL, NULL,
> +					    "mti,cpu-interrupt-controller");
> +	if (!cpu_has_veic && !intc_node)
> +		mips_cpu_irq_init();
> +
> +	irqchip_init();
> +}
> +
> +int get_c0_perfcount_int(void)
> +{
> +	return gic_get_c0_perfcount_int();
> +}
> +EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
> +
> +unsigned int get_c0_compare_int(void)
> +{
> +	return gic_get_c0_compare_int();
> +}

Worth having get_c0_fdc_int() too for the "Fast Debug Channel"?

> diff --git a/arch/mips/intel-mips/prom.c b/arch/mips/intel-mips/prom.c
> new file mode 100644
> index 000000000000..9407858ddc94
> --- /dev/null
> +++ b/arch/mips/intel-mips/prom.c
> @@ -0,0 +1,184 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2014 Lei Chuanhua <Chuanhua.lei@lantiq.com>
> + * Copyright (C) 2016 Intel Corporation.
> + */
> +#include <linux/init.h>
> +#include <linux/export.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_fdt.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +#include <asm/mips-cps.h>
> +#include <asm/smp-ops.h>
> +#include <asm/dma-coherence.h>
> +#include <asm/prom.h>
> +
> +#define IOPORT_RESOURCE_START   0x10000000
> +#define IOPORT_RESOURCE_END     0xffffffff
> +#define IOMEM_RESOURCE_START    0x10000000
> +#define IOMEM_RESOURCE_END      0xffffffff

The _END ones seem to be unused?

> +static void __init prom_init_cmdline(void)
> +{
> +	int i;
> +	int argc;
> +	char **argv;
> +
> +	/*
> +	 * If u-boot pass parameters, it is ok, however, if without u-boot
> +	 * JTAG or other tool has to reset all register value before it goes
> +	 * emulation most likely belongs to this category
> +	 */
> +	if (fw_arg0 == 0 || fw_arg1 == 0)
> +		return;
> +
> +	argc = fw_arg0;
> +	argv = (char **)KSEG1ADDR(fw_arg1);
> +
> +	arcs_cmdline[0] = '\0';
> +
> +	for (i = 0; i < argc; i++) {
> +		char *p = (char *)KSEG1ADDR(argv[i]);
> +
> +		if (argv[i] && *p) {
> +			strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
> +			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
> +		}
> +	}

Please describe the boot register protocol in the commit message and/or
a comment in this function.

Is it compatible with the UHI boot protocol, such that this could
potentially be converted to use the generic platform in future?

> +}
> +
> +static int __init plat_enable_iocoherency(void)
> +{
> +	int supported = 0;
> +
> +	if (mips_cps_numiocu(0) != 0) {
> +		/* Nothing special needs to be done to enable coherency */
> +		pr_info("Coherence Manager IOCU detected\n");
> +		/* Second IOCU for MPE or other master access register */
> +		write_gcr_reg0_base(0xa0000000);
> +		write_gcr_reg0_mask(0xf8000000 | CM_GCR_REGn_MASK_CMTGT_IOCU1);
> +		supported = 1;
> +	}
> +
> +	/* hw_coherentio = supported; */
> +
> +	return supported;
> +}
> +
> +static void __init plat_setup_iocoherency(void)
> +{
> +#ifdef CONFIG_DMA_NONCOHERENT
> +	/*
> +	 * Kernel has been configured with software coherency
> +	 * but we might choose to turn it off and use hardware
> +	 * coherency instead.

That sounds a big risky. Software coherency will I think perform cache
line invalidation when syncing buffers from device to CPU (see
__dma_sync_virtual), so that the underlying RAM written by the
supposedly incoherent DMA is visible. If its coherent afterall then it
may be sat in a dirty line in the cache, and not have been written back
to RAM yet before it gets invalidated?

> +	 */
> +	if (plat_enable_iocoherency()) {
> +		if (coherentio == IO_COHERENCE_DISABLED)
> +			pr_info("Hardware DMA cache coherency disabled\n");
> +		else
> +			pr_info("Hardware DMA cache coherency enabled\n");
> +	} else {
> +		if (coherentio == IO_COHERENCE_ENABLED)
> +			pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
> +		else
> +			pr_info("Software DMA cache coherency enabled\n");
> +	}
> +#else
> +	if (!plat_enable_iocoherency())
> +		panic("Hardware DMA cache coherency not supported!");
> +#endif
> +}


> +void __init device_tree_init(void)
> +{
> +	if (!initial_boot_params)
> +		return;

Redundant check. unflatten_and_copy_device_tree() now handles that and
emits a message.

> +
> +	unflatten_and_copy_device_tree();
> +}
> +
> +#define CPC_BASE_ADDR		0x12310000

Please put this at the top of the file with other #defines.

> +
> +phys_addr_t mips_cpc_default_phys_base(void)
> +{
> +	return CPC_BASE_ADDR;
> +}

> diff --git a/arch/mips/intel-mips/time.c b/arch/mips/intel-mips/time.c
> new file mode 100644
> index 000000000000..77ad4014fe9d
> --- /dev/null
> +++ b/arch/mips/intel-mips/time.c
> @@ -0,0 +1,56 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2016 Intel Corporation.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clocksource.h>
> +#include <linux/of.h>
> +
> +#include <asm/time.h>
> +
> +static inline u32 get_counter_resolution(void)
> +{
> +	u32 res;
> +
> +	__asm__ __volatile__(".set	push\n"

Preferably each line of asm should end \n\t and the final line doesn't
need \n or \t. Look at the .s compiler output to see the difference.

> +			     ".set	mips32r2\n"
> +			     "rdhwr	%0, $3\n"

Hmm, it'd be nice to abstract this in mipsregs.h, but that can always
wait. You could use MIPS_HWR_CCRES though (i.e. off top of my head
something like "%0, $%1\n" and have a "i" (MIPS_HWR_CCRES) input.

> +			     ".set pop\n"
> +			     : "=&r" (res)

I don't think you strictly need an early clobber there since there are
no register inputs, "=r" should do fine.

> +			     : /* no input */
> +			     : "memory");

I don't think that operation clobbers any memory?

Thanks
James

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-12  5:40 ` [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial Songjun Wu
@ 2018-06-12 22:24   ` Rob Herring
  2018-06-14  6:19     ` Wu, Songjun
  2018-06-14 10:03   ` Arnd Bergmann
  1 sibling, 1 reply; 33+ messages in thread
From: Rob Herring @ 2018-06-12 22:24 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, James Hogan, linux-kernel,
	Thomas Gleixner, Philippe Ombredanne, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle

On Tue, Jun 12, 2018 at 01:40:28PM +0800, Songjun Wu wrote:
> Previous implementation uses a hard-coded register value to check if
> the current serial entity is the console entity.
> Now the lantiq serial driver uses the aliases for the index of the
> serial port.
> The lantiq danube serial dts are updated with aliases to support this.
> 
> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
> ---
> 
>  arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi
> index 2dd950181f8a..7a9e15da6bd0 100644
> --- a/arch/mips/boot/dts/lantiq/danube.dtsi
> +++ b/arch/mips/boot/dts/lantiq/danube.dtsi
> @@ -4,6 +4,10 @@
>  	#size-cells = <1>;
>  	compatible = "lantiq,xway", "lantiq,danube";
>  
> +	aliases {
> +		serial0 = &asc1;
> +	};
> +
>  	cpus {
>  		cpu@0 {
>  			compatible = "mips,mips24Kc";
> @@ -74,7 +78,7 @@
>  			reg = <0xE100A00 0x100>;
>  		};
>  
> -		serial@E100C00 {
> +		asc1: serial@E100C00 {

Fix this to be lower case hex while you are at it.

>  			compatible = "lantiq,asc";
>  			reg = <0xE100C00 0x400>;
>  			interrupt-parent = <&icu0>;
> -- 
> 2.11.0
> 

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

* Re: [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs
  2018-06-12  5:40 ` [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs Songjun Wu
  2018-06-12 11:23   ` James Hogan
@ 2018-06-12 22:31   ` Rob Herring
  2018-06-14  8:01     ` Hua Ma
  1 sibling, 1 reply; 33+ messages in thread
From: Rob Herring @ 2018-06-12 22:31 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, James Hogan, linux-kernel,
	Ralf Baechle, Mark Rutland

On Tue, Jun 12, 2018 at 01:40:30PM +0800, Songjun Wu wrote:
> From: Hua Ma <hua.ma@linux.intel.com>
> 
> Add initial support for Intel MIPS interAptiv SoCs made by Intel.
> This series will add support for the GRX500 family.
> 
> The series allows booting a minimal system using a initramfs.
> 
> Signed-off-by: Hua ma <hua.ma@linux.intel.com>
> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
> ---
> 
>  arch/mips/Kbuild.platforms                         |   1 +
>  arch/mips/Kconfig                                  |  36 ++++
>  arch/mips/boot/dts/Makefile                        |   1 +
>  arch/mips/boot/dts/intel-mips/Makefile             |   3 +
>  arch/mips/boot/dts/intel-mips/easy350_anywan.dts   |  20 +++
>  arch/mips/boot/dts/intel-mips/xrx500.dtsi          | 196 +++++++++++++++++++++

Please split dts files to separate patch.


> diff --git a/arch/mips/boot/dts/intel-mips/easy350_anywan.dts b/arch/mips/boot/dts/intel-mips/easy350_anywan.dts
> new file mode 100644
> index 000000000000..40177f6cee1e
> --- /dev/null
> +++ b/arch/mips/boot/dts/intel-mips/easy350_anywan.dts
> @@ -0,0 +1,20 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/dts-v1/;
> +
> +#include <dt-bindings/interrupt-controller/mips-gic.h>
> +#include <dt-bindings/clock/intel,grx500-clk.h>
> +
> +#include "xrx500.dtsi"
> +
> +/ {
> +	model = "EASY350 ANYWAN (GRX350) Main model";

A board should have a board specific compatible, too. 

> +	chosen {
> +		bootargs = "earlycon=lantiq,0x16600000 clk_ignore_unused";
> +		stdout-path = "serial0";
> +	};
> +
> +	memory@0 {

memory@20000000

> +		device_type = "memory";
> +		reg = <0x20000000 0x0e000000>;
> +	};
> +};
> diff --git a/arch/mips/boot/dts/intel-mips/xrx500.dtsi b/arch/mips/boot/dts/intel-mips/xrx500.dtsi
> new file mode 100644
> index 000000000000..04a068d6d96b
> --- /dev/null
> +++ b/arch/mips/boot/dts/intel-mips/xrx500.dtsi
> @@ -0,0 +1,196 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/ {
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +	compatible = "intel,xrx500";

This needs to be documented.

> +
> +	aliases {
> +		serial0 = &asc0;
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@0 {
> +			device_type = "cpu";
> +			compatible = "mti,interaptiv";
> +			clocks = <&cpuclk>;
> +			reg = <0>;
> +		};
> +
> +		cpu1: cpu@1 {
> +			device_type = "cpu";
> +			compatible = "mti,interaptiv";
> +			reg = <1>;
> +		};
> +	};
> +
> +	cpu_intc: interrupt-controller {
> +		compatible = "mti,cpu-interrupt-controller";
> +
> +		interrupt-controller;
> +		#interrupt-cells = <1>;
> +	};
> +
> +	gic: gic@12320000 {
> +		compatible = "mti,gic";
> +		reg = <0x12320000 0x20000>;
> +
> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		/*
> +		 * Declare the interrupt-parent even though the mti,gic
> +		 * binding doesn't require it, such that the kernel can
> +		 * figure out that cpu_intc is the root interrupt
> +		 * controller & should be probed first.
> +		 */
> +		interrupt-parent = <&cpu_intc>;
> +		mti,reserved-ipi-vectors = <56 8>;
> +	};
> +
> +	cgu0: cgu@16200000 {
> +		compatible = "syscon";
> +		reg = <0x16200000 0x100000>;
> +
> +		clock {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			osc0: osc0 {
> +				#clock-cells = <0>;
> +				compatible = "fixed-clock";
> +				clock-frequency = <40000000>;
> +				clock-output-names = "osc40M";
> +			};
> +
> +			pll0a: pll0a {
> +				#clock-cells = <0>;
> +				compatible = "fixed-factor-clock";
> +				clock-mult = <0x3C>;
> +				clock-div = <1>;
> +				clocks = <&osc0>;
> +				clock-output-names = "pll0a";
> +			};
> +
> +			pll0b: pll0b {
> +				#clock-cells = <0>;
> +				compatible = "fixed-factor-clock";
> +				clock-mult = <0x32>;
> +				clock-div = <1>;
> +				clocks = <&osc0>;
> +				clock-output-names = "pll0b";
> +			};
> +
> +			pll3: pll3 {
> +				#clock-cells = <0>;
> +				compatible = "fixed-factor-clock";
> +				clock-mult = <0x64>;
> +				clock-div = <1>;
> +				clocks = <&osc0>;
> +				clock-output-names = "lcpll3";
> +			};
> +
> +			pll0aclk: pll0aclk {
> +				#clock-cells = <1>;
> +				compatible = "intel,grx500-pll0a-clk";
> +				clocks = <&pll0a>;
> +				reg = <0x8>;
> +				clock-output-names = "cbm", "ngi",
> +				"ssx4", "cpu0";
> +			};
> +
> +			pll0bclk: pll0bclk {
> +				#clock-cells = <1>;
> +				compatible = "intel,grx500-pll0b-clk";
> +				clocks = <&pll0b>;
> +				reg = <0x38>;
> +				clock-output-names = "pae", "gswip", "ddr",
> +				"cpu1";
> +			};
> +
> +			ddrphyclk: ddrphyclk {
> +				#clock-cells = <0>;
> +				compatible = "fixed-factor-clock";
> +				clock-mult = <2>;
> +				clock-div = <1>;
> +				clocks = <&pll0bclk DDR_CLK>;
> +				clock-output-names = "ddrphy";
> +			};
> +
> +			pcieclk: pcieclk {
> +				#clock-cells = <0>;
> +				compatible = "intel,grx500-pcie-clk";
> +				clocks = <&pll3>;
> +				reg = <0x98>;
> +				clock-output-names = "pcie";
> +			};
> +
> +			cpuclk: cpuclk {
> +				#clock-cells = <0>;
> +				compatible = "intel,grx500-cpu-clk";
> +				clocks = <&pll0aclk CPU0_CLK>,
> +				<&pll0bclk CPU1_CLK>;
> +				reg = <0x8>;
> +				clock-output-names = "cpu";
> +			};
> +
> +			clkgate0: clkgate0 {
> +				#clock-cells = <1>;
> +				compatible = "intel,grx500-gate0-clk";
> +				reg = <0x114>;
> +				clock-output-names = "gate_xbar0", "gate_xbar1",
> +				"gate_xbar2", "gate_xbar3", "gate_xbar6",
> +				"gate_xbar7";
> +			};
> +
> +			clkgate1: clkgate1 {
> +				#clock-cells = <1>;
> +				compatible = "intel,grx500-gate1-clk";
> +				reg = <0x120>;
> +				clock-output-names = "gate_vcodec", "gate_dma0",
> +				"gate_usb0", "gate_spi1", "gate_spi0",
> +				"gate_cbm", "gate_ebu", "gate_sso",
> +				"gate_gptc0", "gate_gptc1", "gate_gptc2",
> +				"gate_urt", "gate_eip97", "gate_eip123",
> +				"gate_toe", "gate_mpe", "gate_tdm", "gate_pae",
> +				"gate_usb1", "gate_gswip";
> +			};
> +
> +			clkgate2: clkgate2 {
> +				#clock-cells = <1>;
> +				compatible = "intel,grx500-gate2-clk";
> +				reg = <0x130>;
> +				clock-output-names = "gate_pcie0", "gate_pcie1",
> +				"gate_pcie2";
> +			};
> +
> +			voiceclk: voiceclk {
> +				#clock-cells = <0>;
> +				compatible = "intel,grx500-voice-clk";
> +				clock-frequency = <8192000>;
> +				reg = <0xc4>;
> +				clock-output-names = "voice";
> +			};
> +
> +			i2cclk: i2cclk {
> +				#clock-cells = <0>;
> +				compatible = "intel,grx500-gate-dummy-clk";
> +				clock-output-names = "gate_i2c";
> +			};
> +		};
> +	};
> +
> +	asc0: serial@16600000 {
> +		compatible = "lantiq,asc";
> +		reg = <0x16600000 0x100000>;
> +
> +		interrupt-parent = <&gic>;
> +		interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>,
> +			<GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>,
> +			<GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&pll0aclk SSX4_CLK>, <&clkgate1 GATE_URT_CLK>;
> +		clock-names = "freq", "asc";
> +	};
> +};

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

* Re: [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC
  2018-06-12  5:40 ` [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC Songjun Wu
@ 2018-06-12 22:37   ` Rob Herring
  2018-06-14  8:40     ` yixin zhu
  0 siblings, 1 reply; 33+ messages in thread
From: Rob Herring @ 2018-06-12 22:37 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, Michael Turquette,
	Stephen Boyd, linux-kernel, Mark Rutland

On Tue, Jun 12, 2018 at 01:40:29PM +0800, Songjun Wu wrote:
> From: Yixin Zhu <yixin.zhu@linux.intel.com>
> 
> PLL of GRX500 provide clock to DDR, CPU, and peripherals as show below
> 
>                  +---------+
> 	    |--->| LCPLL3 0|--PCIe clk-->
>    XO       |    +---------+
> +-----------|
>             |    +---------+
>             |    |        3|--PAE clk-->
>             |--->| PLL0B  2|--GSWIP clk-->
>             |    |        1|--DDR clk-->DDR PHY clk-->
>             |    |        0|--CPU1 clk--+   +-----+
>             |    +---------+            |--->0    |
>             |                               | MUX |--CPU clk-->
>             |    +---------+            |--->1    |
>             |    |        0|--CPU0 clk--+   +-----+
>             |--->| PLLOA  1|--SSX4 clk-->
>                  |        2|--NGI clk-->
>                  |        3|--CBM clk-->
>                  +---------+
> 
> VCO of all PLLs of GRX500 is not supposed to be reprogrammed.
> DDR PHY clock is created to show correct clock rate in software
> point of view.
> CPU clock of 1Ghz from PLL0B otherwise from PLL0A.
> Signed-off-by: Yixin Zhu <yixin.zhu@linux.intel.com>
> 
> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>

Need a blank line before the SoB's and not one in the middle.

> ---
> 
>  .../devicetree/bindings/clock/intel,grx500-clk.txt |  46 ++

Please split bindings to separate patch.

>  drivers/clk/Kconfig                                |   1 +
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/intel/Kconfig                          |  21 +
>  drivers/clk/intel/Makefile                         |   7 +
>  drivers/clk/intel/clk-cgu-api.c                    | 676 +++++++++++++++++++++
>  drivers/clk/intel/clk-cgu-api.h                    | 120 ++++
>  drivers/clk/intel/clk-grx500.c                     | 236 +++++++
>  include/dt-bindings/clock/intel,grx500-clk.h       |  61 ++
>  9 files changed, 1169 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
>  create mode 100644 drivers/clk/intel/Kconfig
>  create mode 100644 drivers/clk/intel/Makefile
>  create mode 100644 drivers/clk/intel/clk-cgu-api.c
>  create mode 100644 drivers/clk/intel/clk-cgu-api.h
>  create mode 100644 drivers/clk/intel/clk-grx500.c
>  create mode 100644 include/dt-bindings/clock/intel,grx500-clk.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt b/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
> new file mode 100644
> index 000000000000..dd761d900dc9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
> @@ -0,0 +1,46 @@
> +Device Tree Clock bindings for GRX500 PLL controller.
> +
> +This binding uses the common clock binding:
> +	Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +This GRX500 PLL controller provides the 5 main clock domain of the SoC: CPU/DDR, XBAR,
> +Voice, WLAN, PCIe and gate clocks for HW modules.
> +
> +Required properties for osc clock node
> +- compatible: Should be intel,grx500-xxx-clk

These would need to be enumerated with all possible values. However, see 
below.

> +- reg: offset address of the controller memory area.
> +- clocks: phandle of the external reference clock
> +- #clock-cells: can be one or zero.
> +- clock-output-names: Names of the output clocks.
> +
> +Example:
> +	pll0aclk: pll0aclk {
> +		#clock-cells = <1>;
> +		compatible = "intel,grx500-pll0a-clk";
> +		clocks = <&pll0a>;
> +		reg = <0x8>;
> +		clock-output-names = "cbmclk", "ngiclk", "ssx4clk", "cpu0clk";
> +	};
> +
> +	cpuclk: cpuclk {
> +		#clock-cells = <0>;
> +		compatible = "intel,grx500-cpu-clk";
> +		clocks = <&pll0aclk CPU0_CLK>, <&pll0bclk CPU1_CLK>;
> +		reg = <0x8>;
> +		clock-output-names = "cpu";
> +	};
> +
> +Required properties for gate node:
> +- compatible: Should be intel,grx500-gatex-clk
> +- reg: offset address of the controller memory area.
> +- #clock-cells: Should be <1>
> +- clock-output-names: Names of the output clocks.
> +
> +Example:
> +	clkgate0: clkgate0 {
> +		#clock-cells = <1>;
> +		compatible = "intel,grx500-gate0-clk";
> +		reg = <0x114>;
> +		clock-output-names = "gate_xbar0", "gate_xbar1", "gate_xbar2",
> +		"gate_xbar3", "gate_xbar6", "gate_xbar7";
> +	};

We generally don't do a clock node per clock or few clocks but rather 1 
clock node per clock controller block. See any recent clock bindings.

Rob

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

* Re: [PATCH 7/7] tty: serial: lantiq: Add CCF support
  2018-06-12  5:40 ` [PATCH 7/7] tty: serial: lantiq: Add CCF support Songjun Wu
  2018-06-12  8:07     ` kbuild test robot
@ 2018-06-12 22:39   ` Rob Herring
  2018-06-14  6:38     ` Wu, Songjun
  1 sibling, 1 reply; 33+ messages in thread
From: Rob Herring @ 2018-06-12 22:39 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, Jiri Slaby, linux-kernel,
	Greg Kroah-Hartman, Mark Rutland

On Tue, Jun 12, 2018 at 01:40:34PM +0800, Songjun Wu wrote:
> Previous implementation uses platform-dependent API to get the clock.
> Those functions are not available for other SoC which uses the same IP.
> The CCF (Common Clock Framework) have an abstraction based APIs
> for clock.
> Change to use CCF APIs to get clock and rate.
> So that different SoCs can use the same driver.
> Clocks and clock-names are updated in device tree binding.
> 
> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
> 
> ---
> 
>  .../devicetree/bindings/serial/lantiq_asc.txt      |  15 +++

Please split bindings to separate patch.

>  drivers/tty/serial/Kconfig                         |   2 +-
>  drivers/tty/serial/lantiq.c                        | 101 +++++++++++++++++----
>  3 files changed, 98 insertions(+), 20 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
> index 3acbd309ab9d..608f0c87a4af 100644
> --- a/Documentation/devicetree/bindings/serial/lantiq_asc.txt
> +++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
> @@ -6,6 +6,10 @@ Required properties:
>  - interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier
>    depends on the interrupt-parent interrupt controller.
>  
> +Optional properties:
> +- clocks: Should contain frequency clock and gate clock
> +- clock-names: Should be "freq" and "asc"
> +
>  Example:
>  
>  asc1: serial@e100c00 {
> @@ -14,3 +18,14 @@ asc1: serial@e100c00 {
>  	interrupt-parent = <&icu0>;
>  	interrupts = <112 113 114>;
>  };
> +
> +asc0: serial@600000 {
> +	compatible = "lantiq,asc";
> +	reg = <0x600000 0x100000>;

1MB of address space? That wastes a lot of virtual space on 32-bit 
systems. Just make the size the actual used range.

> +	interrupt-parent = <&gic>;
> +	interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>,
> +	<GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>,
> +	<GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>;
> +	clocks = <&pll0aclk SSX4_CLK>, <&clkgate1 GATE_URT_CLK>;
> +	clock-names = "freq", "asc";
> +};

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

* Re: [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-12 22:24   ` Rob Herring
@ 2018-06-14  6:19     ` Wu, Songjun
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Songjun @ 2018-06-14  6:19 UTC (permalink / raw)
  To: Rob Herring
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, James Hogan, linux-kernel,
	Thomas Gleixner, Philippe Ombredanne, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle

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



On 6/13/2018 6:24 AM, Rob Herring wrote:
> On Tue, Jun 12, 2018 at 01:40:28PM +0800, Songjun Wu wrote:
>> Previous implementation uses a hard-coded register value to check if
>> the current serial entity is the console entity.
>> Now the lantiq serial driver uses the aliases for the index of the
>> serial port.
>> The lantiq danube serial dts are updated with aliases to support this.
>>
>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>> ---
>>
>>   arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi
>> index 2dd950181f8a..7a9e15da6bd0 100644
>> --- a/arch/mips/boot/dts/lantiq/danube.dtsi
>> +++ b/arch/mips/boot/dts/lantiq/danube.dtsi
>> @@ -4,6 +4,10 @@
>>   	#size-cells = <1>;
>>   	compatible = "lantiq,xway", "lantiq,danube";
>>   
>> +	aliases {
>> +		serial0 = &asc1;
>> +	};
>> +
>>   	cpus {
>>   		cpu@0 {
>>   			compatible = "mips,mips24Kc";
>> @@ -74,7 +78,7 @@
>>   			reg = <0xE100A00 0x100>;
>>   		};
>>   
>> -		serial@E100C00 {
>> +		asc1: serial@E100C00 {
> Fix this to be lower case hex while you are at it.
Thanks.
All the upper case in unit-address and hex constants will be changed to 
lower case according to the Linux conventions.
>
>>   			compatible = "lantiq,asc";
>>   			reg = <0xE100C00 0x400>;
>>   			interrupt-parent = <&icu0>;
>> -- 
>> 2.11.0
>>


[-- Attachment #2: Type: text/html, Size: 2545 bytes --]

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

* Re: [PATCH 7/7] tty: serial: lantiq: Add CCF support
  2018-06-12 22:39   ` Rob Herring
@ 2018-06-14  6:38     ` Wu, Songjun
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Songjun @ 2018-06-14  6:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: hua.ma, yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu,
	linux-clk, linux-serial, devicetree, Jiri Slaby, linux-kernel,
	Greg Kroah-Hartman, Mark Rutland



On 6/13/2018 6:39 AM, Rob Herring wrote:
> On Tue, Jun 12, 2018 at 01:40:34PM +0800, Songjun Wu wrote:
>> Previous implementation uses platform-dependent API to get the clock.
>> Those functions are not available for other SoC which uses the same IP.
>> The CCF (Common Clock Framework) have an abstraction based APIs
>> for clock.
>> Change to use CCF APIs to get clock and rate.
>> So that different SoCs can use the same driver.
>> Clocks and clock-names are updated in device tree binding.
>>
>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>>
>> ---
>>
>>   .../devicetree/bindings/serial/lantiq_asc.txt      |  15 +++
> Please split bindings to separate patch.
Thanks.
It will be split to two separate patches, one for bindings, the other 
for code.
>>   drivers/tty/serial/Kconfig                         |   2 +-
>>   drivers/tty/serial/lantiq.c                        | 101 +++++++++++++++++----
>>   3 files changed, 98 insertions(+), 20 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
>> index 3acbd309ab9d..608f0c87a4af 100644
>> --- a/Documentation/devicetree/bindings/serial/lantiq_asc.txt
>> +++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
>> @@ -6,6 +6,10 @@ Required properties:
>>   - interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier
>>     depends on the interrupt-parent interrupt controller.
>>   
>> +Optional properties:
>> +- clocks: Should contain frequency clock and gate clock
>> +- clock-names: Should be "freq" and "asc"
>> +
>>   Example:
>>   
>>   asc1: serial@e100c00 {
>> @@ -14,3 +18,14 @@ asc1: serial@e100c00 {
>>   	interrupt-parent = <&icu0>;
>>   	interrupts = <112 113 114>;
>>   };
>> +
>> +asc0: serial@600000 {
>> +	compatible = "lantiq,asc";
>> +	reg = <0x600000 0x100000>;
> 1MB of address space? That wastes a lot of virtual space on 32-bit
> systems. Just make the size the actual used range.
The size of address space will be updated to the actual used range.
>> +	interrupt-parent = <&gic>;
>> +	interrupts = <GIC_SHARED 103 IRQ_TYPE_LEVEL_HIGH>,
>> +	<GIC_SHARED 105 IRQ_TYPE_LEVEL_HIGH>,
>> +	<GIC_SHARED 106 IRQ_TYPE_LEVEL_HIGH>;
>> +	clocks = <&pll0aclk SSX4_CLK>, <&clkgate1 GATE_URT_CLK>;
>> +	clock-names = "freq", "asc";
>> +};


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

* Re: [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel()
  2018-06-12  8:13   ` Andy Shevchenko
@ 2018-06-14  7:05     ` Wu, Songjun
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Songjun @ 2018-06-14  7:05 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: hua.ma, yixin.zhu, chuanhua.lei, Linux MIPS Mailing List,
	qi-ming.wu, linux-clk, open list:SERIAL DRIVERS, devicetree,
	James Hogan, Jiri Slaby, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Ralf Baechle



On 6/12/2018 4:13 PM, Andy Shevchenko wrote:
> On Tue, Jun 12, 2018 at 8:40 AM, Songjun Wu <songjun.wu@linux.intel.com> wrote:
>> Previous implementation uses platform-dependent functions
>> ltq_w32()/ltq_r32() to access registers. Those functions are not
>> available for other SoC which uses the same IP.
>> Change to OS provided readl()/writel() and readb()/writeb(), so
>> that different SoCs can use the same driver.
> This patch consists 2 or even 3 ones:
> - whitespace shuffling (indentation fixes, blank lines), I dunno if
> it's needed at all
> - some new registers / bits
> - actual switch to readl() / writel()
>
> Please, split.
It will be split to four patches, coding style, new registers, 
readl()/writel() and asc_update_bits.
>> +#define asc_w32_mask(clear, set, reg)  \
>> +       ({ typeof(reg) reg_ = (reg);    \
>> +       writel((readl(reg_) & ~(clear)) | (set), reg_); })
> This would be better as a static inline helper, and name is completely
> misleading, it doesn't mask the register bits, it _updates_ them.
It will be changed to asc_update_bits.


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

* Re: [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs
  2018-06-12 22:31   ` Rob Herring
@ 2018-06-14  8:01     ` Hua Ma
  0 siblings, 0 replies; 33+ messages in thread
From: Hua Ma @ 2018-06-14  8:01 UTC (permalink / raw)
  To: Rob Herring, Songjun Wu
  Cc: yixin.zhu, chuanhua.lei, linux-mips, qi-ming.wu, linux-clk,
	linux-serial, devicetree, James Hogan, linux-kernel,
	Ralf Baechle, Mark Rutland


On 6/13/2018 6:31 AM, Rob Herring wrote:
> On Tue, Jun 12, 2018 at 01:40:30PM +0800, Songjun Wu wrote:
>> From: Hua Ma <hua.ma@linux.intel.com>
>>
>> Add initial support for Intel MIPS interAptiv SoCs made by Intel.
>> This series will add support for the GRX500 family.
>>
>> The series allows booting a minimal system using a initramfs.
>>
>> Signed-off-by: Hua ma <hua.ma@linux.intel.com>
>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>> ---
>>
>>   arch/mips/Kbuild.platforms                         |   1 +
>>   arch/mips/Kconfig                                  |  36 ++++
>>   arch/mips/boot/dts/Makefile                        |   1 +
>>   arch/mips/boot/dts/intel-mips/Makefile             |   3 +
>>   arch/mips/boot/dts/intel-mips/easy350_anywan.dts   |  20 +++
>>   arch/mips/boot/dts/intel-mips/xrx500.dtsi          | 196 +++++++++++++++++++++
> Please split dts files to separate patch.
Thanks,
it will be split into separate patches: one for dts, one for mips codes 
and one for the document.
>> diff --git a/arch/mips/boot/dts/intel-mips/easy350_anywan.dts b/arch/mips/boot/dts/intel-mips/easy350_anywan.dts
>> new file mode 100644
>> index 000000000000..40177f6cee1e
>> --- /dev/null
>> +++ b/arch/mips/boot/dts/intel-mips/easy350_anywan.dts
>> @@ -0,0 +1,20 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/dts-v1/;
>> +
>> +#include <dt-bindings/interrupt-controller/mips-gic.h>
>> +#include <dt-bindings/clock/intel,grx500-clk.h>
>> +
>> +#include "xrx500.dtsi"
>> +
>> +/ {
>> +	model = "EASY350 ANYWAN (GRX350) Main model";
> A board should have a board specific compatible, too.
The board compatible will be added.
>
>> +	chosen {
>> +		bootargs = "earlycon=lantiq,0x16600000 clk_ignore_unused";
>> +		stdout-path = "serial0";
>> +	};
>> +
>> +	memory@0 {
> memory@20000000
The memory address will be changed to @20000000.
>
>> +		device_type = "memory";
>> +		reg = <0x20000000 0x0e000000>;
>> +	};
>> +};
>> diff --git a/arch/mips/boot/dts/intel-mips/xrx500.dtsi b/arch/mips/boot/dts/intel-mips/xrx500.dtsi
>> new file mode 100644
>> index 000000000000..04a068d6d96b
>> --- /dev/null
>> +++ b/arch/mips/boot/dts/intel-mips/xrx500.dtsi
>> @@ -0,0 +1,196 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/ {
>> +	#address-cells = <1>;
>> +	#size-cells = <1>;
>> +	compatible = "intel,xrx500";
> This needs to be documented.
The compatible will be updated in the document.


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

* Re: [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC
  2018-06-12 22:37   ` Rob Herring
@ 2018-06-14  8:40     ` yixin zhu
  2018-06-14 14:09       ` Rob Herring
  0 siblings, 1 reply; 33+ messages in thread
From: yixin zhu @ 2018-06-14  8:40 UTC (permalink / raw)
  To: Rob Herring, Songjun Wu
  Cc: hua.ma, chuanhua.lei, linux-mips, qi-ming.wu, linux-clk,
	linux-serial, devicetree, Michael Turquette, Stephen Boyd,
	linux-kernel, Mark Rutland



On 6/13/2018 6:37 AM, Rob Herring wrote:
> On Tue, Jun 12, 2018 at 01:40:29PM +0800, Songjun Wu wrote:
>> From: Yixin Zhu <yixin.zhu@linux.intel.com>
>>
>> PLL of GRX500 provide clock to DDR, CPU, and peripherals as show below
>>
>>                   +---------+
>> 	    |--->| LCPLL3 0|--PCIe clk-->
>>     XO       |    +---------+
>> +-----------|
>>              |    +---------+
>>              |    |        3|--PAE clk-->
>>              |--->| PLL0B  2|--GSWIP clk-->
>>              |    |        1|--DDR clk-->DDR PHY clk-->
>>              |    |        0|--CPU1 clk--+   +-----+
>>              |    +---------+            |--->0    |
>>              |                               | MUX |--CPU clk-->
>>              |    +---------+            |--->1    |
>>              |    |        0|--CPU0 clk--+   +-----+
>>              |--->| PLLOA  1|--SSX4 clk-->
>>                   |        2|--NGI clk-->
>>                   |        3|--CBM clk-->
>>                   +---------+
>>
>> VCO of all PLLs of GRX500 is not supposed to be reprogrammed.
>> DDR PHY clock is created to show correct clock rate in software
>> point of view.
>> CPU clock of 1Ghz from PLL0B otherwise from PLL0A.
>> Signed-off-by: Yixin Zhu <yixin.zhu@linux.intel.com>
>>
>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
> 
> Need a blank line before the SoB's and not one in the middle.
Thanks.
Blank line in the middle of sign-off will be removed.
A new blank line will be added before SoB's.

> 
>> ---
>>
>>   .../devicetree/bindings/clock/intel,grx500-clk.txt |  46 ++
> 
> Please split bindings to separate patch.
> 
>>   drivers/clk/Kconfig                                |   1 +
>>   drivers/clk/Makefile                               |   1 +
>>   drivers/clk/intel/Kconfig                          |  21 +
>>   drivers/clk/intel/Makefile                         |   7 +
>>   drivers/clk/intel/clk-cgu-api.c                    | 676 +++++++++++++++++++++
>>   drivers/clk/intel/clk-cgu-api.h                    | 120 ++++
>>   drivers/clk/intel/clk-grx500.c                     | 236 +++++++
>>   include/dt-bindings/clock/intel,grx500-clk.h       |  61 ++
>>   9 files changed, 1169 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
>>   create mode 100644 drivers/clk/intel/Kconfig
>>   create mode 100644 drivers/clk/intel/Makefile
>>   create mode 100644 drivers/clk/intel/clk-cgu-api.c
>>   create mode 100644 drivers/clk/intel/clk-cgu-api.h
>>   create mode 100644 drivers/clk/intel/clk-grx500.c
>>   create mode 100644 include/dt-bindings/clock/intel,grx500-clk.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt b/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
>> new file mode 100644
>> index 000000000000..dd761d900dc9
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
>> @@ -0,0 +1,46 @@
>> +Device Tree Clock bindings for GRX500 PLL controller.
>> +
>> +This binding uses the common clock binding:
>> +	Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +This GRX500 PLL controller provides the 5 main clock domain of the SoC: CPU/DDR, XBAR,
>> +Voice, WLAN, PCIe and gate clocks for HW modules.
>> +
>> +Required properties for osc clock node
>> +- compatible: Should be intel,grx500-xxx-clk
> 
> These would need to be enumerated with all possible values. However, see
> below.
All possible values will be listed.

> 
>> +- reg: offset address of the controller memory area.
>> +- clocks: phandle of the external reference clock
>> +- #clock-cells: can be one or zero.
>> +- clock-output-names: Names of the output clocks.
>> +
>> +Example:
>> +	pll0aclk: pll0aclk {
>> +		#clock-cells = <1>;
>> +		compatible = "intel,grx500-pll0a-clk";
>> +		clocks = <&pll0a>;
>> +		reg = <0x8>;
>> +		clock-output-names = "cbmclk", "ngiclk", "ssx4clk", "cpu0clk";
>> +	};
>> +
>> +	cpuclk: cpuclk {
>> +		#clock-cells = <0>;
>> +		compatible = "intel,grx500-cpu-clk";
>> +		clocks = <&pll0aclk CPU0_CLK>, <&pll0bclk CPU1_CLK>;
>> +		reg = <0x8>;
>> +		clock-output-names = "cpu";
>> +	};
>> +
>> +Required properties for gate node:
>> +- compatible: Should be intel,grx500-gatex-clk
>> +- reg: offset address of the controller memory area.
>> +- #clock-cells: Should be <1>
>> +- clock-output-names: Names of the output clocks.
>> +
>> +Example:
>> +	clkgate0: clkgate0 {
>> +		#clock-cells = <1>;
>> +		compatible = "intel,grx500-gate0-clk";
>> +		reg = <0x114>;
>> +		clock-output-names = "gate_xbar0", "gate_xbar1", "gate_xbar2",
>> +		"gate_xbar3", "gate_xbar6", "gate_xbar7";
>> +	};
> 
> We generally don't do a clock node per clock or few clocks but rather 1
> clock node per clock controller block. See any recent clock bindings.
> 
> Rob
Do you mean only one example is needed per clock controller block?
cpuclk is not needed in the document?

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

* Re: [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs
  2018-06-12 11:23   ` James Hogan
@ 2018-06-14  9:24     ` yixin zhu
  0 siblings, 0 replies; 33+ messages in thread
From: yixin zhu @ 2018-06-14  9:24 UTC (permalink / raw)
  To: James Hogan, Songjun Wu
  Cc: hua.ma, chuanhua.lei, linux-mips, qi-ming.wu, linux-clk,
	linux-serial, devicetree, linux-kernel, Rob Herring,
	Ralf Baechle, Mark Rutland



On 6/12/2018 7:23 PM, James Hogan wrote:
> Hi,
> 
> Good to see this patch!
> 
> On Tue, Jun 12, 2018 at 01:40:30PM +0800, Songjun Wu wrote:
>> diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
>> index ac7ad54f984f..bcd647060f3e 100644
>> --- a/arch/mips/Kbuild.platforms
>> +++ b/arch/mips/Kbuild.platforms
>> @@ -12,6 +12,7 @@ platforms += cobalt
>>   platforms += dec
>>   platforms += emma
>>   platforms += generic
>> +platforms += intel-mips
> 
> What are the main things preventing this from moving to the generic
> platform? Is it mainly the use of EVA (which generic doesn't yet
> support)?
> 
Yes. It's mainly because of EVA.

>> diff --git a/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h b/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
>> new file mode 100644
>> index 000000000000..3893855b60c6
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
> ...
>> +	/*
>> +	 * Get Config.K0 value and use it to program
>> +	 * the segmentation registers
> 
> Please can you describe (maybe with a table) the segment layout in human
> readable terms so the reader doesn't need to decode the SegCtl registers
> to understand where everything is in the virtual address space?
> 
Will add detailed EVA mapping description in code comments.

>> diff --git a/arch/mips/boot/dts/intel-mips/Makefile b/arch/mips/boot/dts/intel-mips/Makefile
>> new file mode 100644
>> index 000000000000..b16c0081639c
>> --- /dev/null
>> +++ b/arch/mips/boot/dts/intel-mips/Makefile
>> @@ -0,0 +1,3 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +dtb-$(CONFIG_DTB_INTEL_MIPS_GRX500)	+= easy350_anywan.dtb
>> +obj-y	+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
> 
> This needs updating to obj-$(CONFIG_BUILTIN_DTB) as per commit
> fca3aa166422 ("MIPS: dts: Avoid unneeded built-in.a in DTS dirs") in
> linux-next.
> 
>> diff --git a/arch/mips/intel-mips/Makefile b/arch/mips/intel-mips/Makefile
>> new file mode 100644
>> index 000000000000..9f272d06eecd
>> --- /dev/null
>> +++ b/arch/mips/intel-mips/Makefile
>> @@ -0,0 +1,3 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +
>> +obj-$(CONFIG_INTEL_MIPS)	+= prom.o irq.o time.o
> 
> You can use obj-y, since this Makefile is only included if
> CONFIG_INTEL_MIPS=y (i.e. via the platform-$(CONFIG_INTEL_MIPS) below).
> 
> Also please split each file onto separate "obj-y += whatever.o" lines.
> 
Will use obj-y.
Will split it into per line per .o.

>> diff --git a/arch/mips/intel-mips/Platform b/arch/mips/intel-mips/Platform
>> new file mode 100644
>> index 000000000000..b34750eeaeb0
>> --- /dev/null
>> +++ b/arch/mips/intel-mips/Platform
>> @@ -0,0 +1,11 @@
>> +#
>> +# MIPs SoC platform
>> +#
>> +
>> +platform-$(CONFIG_INTEL_MIPS)			+= intel-mips/
> 
> ^^^ (this is what ensures the Makefile is only included for this
> platform)
> 
>> diff --git a/arch/mips/intel-mips/irq.c b/arch/mips/intel-mips/irq.c
>> new file mode 100644
>> index 000000000000..00637a5cdd20
>> --- /dev/null
>> +++ b/arch/mips/intel-mips/irq.c
>> @@ -0,0 +1,36 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2016 Intel Corporation.
>> + */
>> +#include <linux/init.h>
>> +#include <linux/irqchip.h>
>> +#include <linux/of_irq.h>
>> +#include <asm/irq.h>
>> +
>> +#include <asm/irq_cpu.h>
>> +
>> +void __init arch_init_irq(void)
>> +{
>> +	struct device_node *intc_node;
>> +
>> +	pr_info("EIC is %s\n", cpu_has_veic ? "on" : "off");
>> +	pr_info("VINT is %s\n", cpu_has_vint ? "on" : "off");
>> +
>> +	intc_node = of_find_compatible_node(NULL, NULL,
>> +					    "mti,cpu-interrupt-controller");
>> +	if (!cpu_has_veic && !intc_node)
>> +		mips_cpu_irq_init();
>> +
>> +	irqchip_init();
>> +}
>> +
>> +int get_c0_perfcount_int(void)
>> +{
>> +	return gic_get_c0_perfcount_int();
>> +}
>> +EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
>> +
>> +unsigned int get_c0_compare_int(void)
>> +{
>> +	return gic_get_c0_compare_int();
>> +}
> 
> Worth having get_c0_fdc_int() too for the "Fast Debug Channel"?
> 
FDC not used in our product.

>> diff --git a/arch/mips/intel-mips/prom.c b/arch/mips/intel-mips/prom.c
>> new file mode 100644
>> index 000000000000..9407858ddc94
>> --- /dev/null
>> +++ b/arch/mips/intel-mips/prom.c
>> @@ -0,0 +1,184 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2014 Lei Chuanhua <Chuanhua.lei@lantiq.com>
>> + * Copyright (C) 2016 Intel Corporation.
>> + */
>> +#include <linux/init.h>
>> +#include <linux/export.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/of_fdt.h>
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <asm/mips-cps.h>
>> +#include <asm/smp-ops.h>
>> +#include <asm/dma-coherence.h>
>> +#include <asm/prom.h>
>> +
>> +#define IOPORT_RESOURCE_START   0x10000000
>> +#define IOPORT_RESOURCE_END     0xffffffff
>> +#define IOMEM_RESOURCE_START    0x10000000
>> +#define IOMEM_RESOURCE_END      0xffffffff
> 
> The _END ones seem to be unused?
> 
Will remove unused _END macros.

>> +static void __init prom_init_cmdline(void)
>> +{
>> +	int i;
>> +	int argc;
>> +	char **argv;
>> +
>> +	/*
>> +	 * If u-boot pass parameters, it is ok, however, if without u-boot
>> +	 * JTAG or other tool has to reset all register value before it goes
>> +	 * emulation most likely belongs to this category
>> +	 */
>> +	if (fw_arg0 == 0 || fw_arg1 == 0)
>> +		return;
>> +
>> +	argc = fw_arg0;
>> +	argv = (char **)KSEG1ADDR(fw_arg1);
>> +
>> +	arcs_cmdline[0] = '\0';
>> +
>> +	for (i = 0; i < argc; i++) {
>> +		char *p = (char *)KSEG1ADDR(argv[i]);
>> +
>> +		if (argv[i] && *p) {
>> +			strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
>> +			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
>> +		}
>> +	}
> 
> Please describe the boot register protocol in the commit message and/or
> a comment in this function.
>Will add boot register protocol description in code comment.

> Is it compatible with the UHI boot protocol, such that this could
> potentially be converted to use the generic platform in future?
> 
It is compatible with the UHI boot protocol.

>> +}
>> +
>> +static int __init plat_enable_iocoherency(void)
>> +{
>> +	int supported = 0;
>> +
>> +	if (mips_cps_numiocu(0) != 0) {
>> +		/* Nothing special needs to be done to enable coherency */
>> +		pr_info("Coherence Manager IOCU detected\n");
>> +		/* Second IOCU for MPE or other master access register */
>> +		write_gcr_reg0_base(0xa0000000);
>> +		write_gcr_reg0_mask(0xf8000000 | CM_GCR_REGn_MASK_CMTGT_IOCU1);
>> +		supported = 1;
>> +	}
>> +
>> +	/* hw_coherentio = supported; */
>> +
>> +	return supported;
>> +}
>> +
>> +static void __init plat_setup_iocoherency(void)
>> +{
>> +#ifdef CONFIG_DMA_NONCOHERENT
>> +	/*
>> +	 * Kernel has been configured with software coherency
>> +	 * but we might choose to turn it off and use hardware
>> +	 * coherency instead.
> 
> That sounds a big risky. Software coherency will I think perform cache
> line invalidation when syncing buffers from device to CPU (see
> __dma_sync_virtual), so that the underlying RAM written by the
> supposedly incoherent DMA is visible. If its coherent afterall then it
> may be sat in a dirty line in the cache, and not have been written back
> to RAM yet before it gets invalidated?
> 
The comment in code is not accurate.
HW coherence is not supported and software coherence is always enabled.
Will correct the comments and clean the code.

>> +	 */
>> +	if (plat_enable_iocoherency()) {
>> +		if (coherentio == IO_COHERENCE_DISABLED)
>> +			pr_info("Hardware DMA cache coherency disabled\n");
>> +		else
>> +			pr_info("Hardware DMA cache coherency enabled\n");
>> +	} else {
>> +		if (coherentio == IO_COHERENCE_ENABLED)
>> +			pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
>> +		else
>> +			pr_info("Software DMA cache coherency enabled\n");
>> +	}
>> +#else
>> +	if (!plat_enable_iocoherency())
>> +		panic("Hardware DMA cache coherency not supported!");
>> +#endif
>> +}
> 
> 
>> +void __init device_tree_init(void)
>> +{
>> +	if (!initial_boot_params)
>> +		return;
> 
> Redundant check. unflatten_and_copy_device_tree() now handles that and
> emits a message.
> 
Will remove the redundant check.

>> +
>> +	unflatten_and_copy_device_tree();
>> +}
>> +
>> +#define CPC_BASE_ADDR		0x12310000
> 
> Please put this at the top of the file with other #defines.
> 
Will move this to the top with other #defines.

>> +
>> +phys_addr_t mips_cpc_default_phys_base(void)
>> +{
>> +	return CPC_BASE_ADDR;
>> +}
> 
>> diff --git a/arch/mips/intel-mips/time.c b/arch/mips/intel-mips/time.c
>> new file mode 100644
>> index 000000000000..77ad4014fe9d
>> --- /dev/null
>> +++ b/arch/mips/intel-mips/time.c
>> @@ -0,0 +1,56 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2016 Intel Corporation.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/clocksource.h>
>> +#include <linux/of.h>
>> +
>> +#include <asm/time.h>
>> +
>> +static inline u32 get_counter_resolution(void)
>> +{
>> +	u32 res;
>> +
>> +	__asm__ __volatile__(".set	push\n"
> 
> Preferably each line of asm should end \n\t and the final line doesn't
> need \n or \t. Look at the .s compiler output to see the difference.
> 
>> +			     ".set	mips32r2\n"
>> +			     "rdhwr	%0, $3\n"
> 
> Hmm, it'd be nice to abstract this in mipsregs.h, but that can always
> wait. You could use MIPS_HWR_CCRES though (i.e. off top of my head
> something like "%0, $%1\n" and have a "i" (MIPS_HWR_CCRES) input.
> 
>> +			     ".set pop\n"
>> +			     : "=&r" (res)
> 
> I don't think you strictly need an early clobber there since there are
> no register inputs, "=r" should do fine.
> 
>> +			     : /* no input */
>> +			     : "memory");
> 
> I don't think that operation clobbers any memory?
>
Will replace the assembly code with fixed value 2 as the chip resolution 
is the half of the clock.

> Thanks
> James
>
Thanks
Yixin

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

* Re: [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-12  5:40 ` [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial Songjun Wu
  2018-06-12 22:24   ` Rob Herring
@ 2018-06-14 10:03   ` Arnd Bergmann
  2018-06-18  9:42     ` Wu, Songjun
  1 sibling, 1 reply; 33+ messages in thread
From: Arnd Bergmann @ 2018-06-14 10:03 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Linux Kernel Mailing List,
	Thomas Gleixner, Philippe Ombredanne, Rob Herring, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle

On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com> wrote:
> Previous implementation uses a hard-coded register value to check if
> the current serial entity is the console entity.
> Now the lantiq serial driver uses the aliases for the index of the
> serial port.
> The lantiq danube serial dts are updated with aliases to support this.
>
> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
> ---
>
>  arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi
> index 2dd950181f8a..7a9e15da6bd0 100644
> --- a/arch/mips/boot/dts/lantiq/danube.dtsi
> +++ b/arch/mips/boot/dts/lantiq/danube.dtsi
> @@ -4,6 +4,10 @@
>         #size-cells = <1>;
>         compatible = "lantiq,xway", "lantiq,danube";
>
> +       aliases {
> +               serial0 = &asc1;
> +       };
> +

You generally want the aliases to be part of the board specific file,
not every board numbers their serial ports in the same way.

       Arnd

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

* Re: [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel()
  2018-06-12  5:40 ` [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel() Songjun Wu
  2018-06-12  8:13   ` Andy Shevchenko
@ 2018-06-14 10:07   ` Arnd Bergmann
  2018-06-18  9:39     ` Wu, Songjun
  1 sibling, 1 reply; 33+ messages in thread
From: Arnd Bergmann @ 2018-06-14 10:07 UTC (permalink / raw)
  To: Songjun Wu
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Jiri Slaby,
	Linux Kernel Mailing List, Greg Kroah-Hartman, Ralf Baechle

On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com> wrote:
> Previous implementation uses platform-dependent functions
> ltq_w32()/ltq_r32() to access registers. Those functions are not
> available for other SoC which uses the same IP.
> Change to OS provided readl()/writel() and readb()/writeb(), so
> that different SoCs can use the same driver.
>
> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>

Are there any big-endian machines using this driver? The original definition
of ltq_r32() uses non-byteswapping __raw_readl() etc, which suggests
that the registers might be wired up in a way that matches the CPU
endianess (this is usally a bad idea in hardware design, but nothing
we can influence in the OS).

When you change it to readl(), that will breaks all machines that rely
on the old behavior on big-endian kernels.

      Arnd

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

* Re: [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC
  2018-06-14  8:40     ` yixin zhu
@ 2018-06-14 14:09       ` Rob Herring
  2018-06-18 10:05         ` yixin zhu
  0 siblings, 1 reply; 33+ messages in thread
From: Rob Herring @ 2018-06-14 14:09 UTC (permalink / raw)
  To: yixin zhu
  Cc: Songjun Wu, hua.ma, chuanhua.lei, Linux-MIPS, qi-ming.wu,
	linux-clk, open list:SERIAL DRIVERS, devicetree,
	Michael Turquette, Stephen Boyd, linux-kernel, Mark Rutland

On Thu, Jun 14, 2018 at 2:40 AM, yixin zhu <yixin.zhu@linux.intel.com> wrote:
>
>
> On 6/13/2018 6:37 AM, Rob Herring wrote:
>>
>> On Tue, Jun 12, 2018 at 01:40:29PM +0800, Songjun Wu wrote:
>>>
>>> From: Yixin Zhu <yixin.zhu@linux.intel.com>
>>>
>>> PLL of GRX500 provide clock to DDR, CPU, and peripherals as show below

[...]

>>> +Example:
>>> +       clkgate0: clkgate0 {
>>> +               #clock-cells = <1>;
>>> +               compatible = "intel,grx500-gate0-clk";
>>> +               reg = <0x114>;
>>> +               clock-output-names = "gate_xbar0", "gate_xbar1",
>>> "gate_xbar2",
>>> +               "gate_xbar3", "gate_xbar6", "gate_xbar7";
>>> +       };
>>
>>
>> We generally don't do a clock node per clock or few clocks but rather 1
>> clock node per clock controller block. See any recent clock bindings.
>>
>> Rob
>
> Do you mean only one example is needed per clock controller block?
> cpuclk is not needed in the document?

No, I mean generally we have 1 DT node for the h/w block with all the
clock control registers rather than nodes with a single register and 1
or a couple of clocks. Sometimes the clock registers are mixed with
other functions which complicates things a bit. But I can't tell that
here because you haven't documented what's in the rest of the register
space.

Rob

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

* Re: [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel()
  2018-06-14 10:07   ` Arnd Bergmann
@ 2018-06-18  9:39     ` Wu, Songjun
  2018-06-18 11:52       ` Arnd Bergmann
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Songjun @ 2018-06-18  9:39 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Jiri Slaby,
	Linux Kernel Mailing List, Greg Kroah-Hartman, Ralf Baechle



On 6/14/2018 6:07 PM, Arnd Bergmann wrote:
> On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com> wrote:
>> Previous implementation uses platform-dependent functions
>> ltq_w32()/ltq_r32() to access registers. Those functions are not
>> available for other SoC which uses the same IP.
>> Change to OS provided readl()/writel() and readb()/writeb(), so
>> that different SoCs can use the same driver.
>>
>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
> Are there any big-endian machines using this driver? The original definition
> of ltq_r32() uses non-byteswapping __raw_readl() etc, which suggests
> that the registers might be wired up in a way that matches the CPU
> endianess (this is usally a bad idea in hardware design, but nothing
> we can influence in the OS).
>
> When you change it to readl(), that will breaks all machines that rely
> on the old behavior on big-endian kernels.
>
>        Arnd
It will not break existing big-endian SoC as SWAP_IO_SPACE is disabled.

Disable SWAP_IO_SPACE will not impact ltq_r32 as it uses non-byte 
swapping __raw_readl() and it makes readl work in big-endian kernel too.

The old Lantiq platform enable SWAP_IO_SPACE to support PCI as it's a 
little-endian bus plus PCI TX/RX swap enable impacted both data and 
control path.
Alternatively PCI device driver has to do endian swap, It is better to 
let PCI device driver to do endian swap instead because SWAP_IO_SPACE is 
global wide macro.
Once we set it, other peripheral such as USB has to change its register 
access as well


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

* Re: [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-14 10:03   ` Arnd Bergmann
@ 2018-06-18  9:42     ` Wu, Songjun
  2018-06-18 10:59       ` Arnd Bergmann
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Songjun @ 2018-06-18  9:42 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Linux Kernel Mailing List,
	Thomas Gleixner, Philippe Ombredanne, Rob Herring, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle



On 6/14/2018 6:03 PM, Arnd Bergmann wrote:
> On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com> wrote:
>> Previous implementation uses a hard-coded register value to check if
>> the current serial entity is the console entity.
>> Now the lantiq serial driver uses the aliases for the index of the
>> serial port.
>> The lantiq danube serial dts are updated with aliases to support this.
>>
>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>> ---
>>
>>   arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi
>> index 2dd950181f8a..7a9e15da6bd0 100644
>> --- a/arch/mips/boot/dts/lantiq/danube.dtsi
>> +++ b/arch/mips/boot/dts/lantiq/danube.dtsi
>> @@ -4,6 +4,10 @@
>>          #size-cells = <1>;
>>          compatible = "lantiq,xway", "lantiq,danube";
>>
>> +       aliases {
>> +               serial0 = &asc1;
>> +       };
>> +
> You generally want the aliases to be part of the board specific file,
> not every board numbers their serial ports in the same way.
>
>         Arnd
In this chip only asc1 can be used as console,  so serial0 is defined in 
chip specific file.

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

* Re: [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC
  2018-06-14 14:09       ` Rob Herring
@ 2018-06-18 10:05         ` yixin zhu
  0 siblings, 0 replies; 33+ messages in thread
From: yixin zhu @ 2018-06-18 10:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: Songjun Wu, hua.ma, chuanhua.lei, Linux-MIPS, qi-ming.wu,
	linux-clk, open list:SERIAL DRIVERS, devicetree,
	Michael Turquette, Stephen Boyd, linux-kernel, Mark Rutland



On 6/14/2018 10:09 PM, Rob Herring wrote:
> On Thu, Jun 14, 2018 at 2:40 AM, yixin zhu <yixin.zhu@linux.intel.com> wrote:
>>
>>
>> On 6/13/2018 6:37 AM, Rob Herring wrote:
>>>
>>> On Tue, Jun 12, 2018 at 01:40:29PM +0800, Songjun Wu wrote:
>>>>
>>>> From: Yixin Zhu <yixin.zhu@linux.intel.com>
>>>>
>>>> PLL of GRX500 provide clock to DDR, CPU, and peripherals as show below
> 
> [...]
> 
>>>> +Example:
>>>> +       clkgate0: clkgate0 {
>>>> +               #clock-cells = <1>;
>>>> +               compatible = "intel,grx500-gate0-clk";
>>>> +               reg = <0x114>;
>>>> +               clock-output-names = "gate_xbar0", "gate_xbar1",
>>>> "gate_xbar2",
>>>> +               "gate_xbar3", "gate_xbar6", "gate_xbar7";
>>>> +       };
>>>
>>>
>>> We generally don't do a clock node per clock or few clocks but rather 1
>>> clock node per clock controller block. See any recent clock bindings.
>>>
>>> Rob
>>
>> Do you mean only one example is needed per clock controller block?
>> cpuclk is not needed in the document?
> 
> No, I mean generally we have 1 DT node for the h/w block with all the
> clock control registers rather than nodes with a single register and 1
> or a couple of clocks. Sometimes the clock registers are mixed with
> other functions which complicates things a bit. But I can't tell that
> here because you haven't documented what's in the rest of the register
> space.
> 
> Rob
> 
Thanks
Will update to use one DT node for the whole clock controller.

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

* Re: [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-18  9:42     ` Wu, Songjun
@ 2018-06-18 10:59       ` Arnd Bergmann
  2018-06-19  6:46         ` Wu, Songjun
  0 siblings, 1 reply; 33+ messages in thread
From: Arnd Bergmann @ 2018-06-18 10:59 UTC (permalink / raw)
  To: Wu, Songjun
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Linux Kernel Mailing List,
	Thomas Gleixner, Philippe Ombredanne, Rob Herring, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle

On Mon, Jun 18, 2018 at 11:42 AM, Wu, Songjun
<songjun.wu@linux.intel.com> wrote:
> On 6/14/2018 6:03 PM, Arnd Bergmann wrote:
>>
>> On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com>
>> wrote:
>>>
>>> Previous implementation uses a hard-coded register value to check if
>>> the current serial entity is the console entity.
>>> Now the lantiq serial driver uses the aliases for the index of the
>>> serial port.
>>> The lantiq danube serial dts are updated with aliases to support this.
>>>
>>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>>> ---
>>>
>>>   arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
>>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi
>>> b/arch/mips/boot/dts/lantiq/danube.dtsi
>>> index 2dd950181f8a..7a9e15da6bd0 100644
>>> --- a/arch/mips/boot/dts/lantiq/danube.dtsi
>>> +++ b/arch/mips/boot/dts/lantiq/danube.dtsi
>>> @@ -4,6 +4,10 @@
>>>          #size-cells = <1>;
>>>          compatible = "lantiq,xway", "lantiq,danube";
>>>
>>> +       aliases {
>>> +               serial0 = &asc1;
>>> +       };
>>> +
>>
>> You generally want the aliases to be part of the board specific file,
>> not every board numbers their serial ports in the same way.
>>
>
> In this chip only asc1 can be used as console,  so serial0 is defined in
> chip specific file.

This was a more general comment about 'aliases' being board specific
in principle (though we've had exceptions in the past). Even if there
is only one uart on the chip, I'd recommend following the same
conventions as the other chips that have more than one uart.

       Arnd

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

* Re: [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel()
  2018-06-18  9:39     ` Wu, Songjun
@ 2018-06-18 11:52       ` Arnd Bergmann
  0 siblings, 0 replies; 33+ messages in thread
From: Arnd Bergmann @ 2018-06-18 11:52 UTC (permalink / raw)
  To: Wu, Songjun
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Jiri Slaby,
	Linux Kernel Mailing List, Greg Kroah-Hartman, Ralf Baechle

On Mon, Jun 18, 2018 at 11:39 AM, Wu, Songjun
<songjun.wu@linux.intel.com> wrote:
>
>
> On 6/14/2018 6:07 PM, Arnd Bergmann wrote:
>>
>> On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com>
>> wrote:
>>>
>>> Previous implementation uses platform-dependent functions
>>> ltq_w32()/ltq_r32() to access registers. Those functions are not
>>> available for other SoC which uses the same IP.
>>> Change to OS provided readl()/writel() and readb()/writeb(), so
>>> that different SoCs can use the same driver.
>>>
>>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>>
>> Are there any big-endian machines using this driver? The original
>> definition
>> of ltq_r32() uses non-byteswapping __raw_readl() etc, which suggests
>> that the registers might be wired up in a way that matches the CPU
>> endianess (this is usally a bad idea in hardware design, but nothing
>> we can influence in the OS).
>>
>> When you change it to readl(), that will breaks all machines that rely
>> on the old behavior on big-endian kernels.
>
> It will not break existing big-endian SoC as SWAP_IO_SPACE is disabled.
>
> Disable SWAP_IO_SPACE will not impact ltq_r32 as it uses non-byte swapping
> __raw_readl() and it makes readl work in big-endian kernel too.
>
> The old Lantiq platform enable SWAP_IO_SPACE to support PCI as it's a
> little-endian bus plus PCI TX/RX swap enable impacted both data and control
> path.

Right, I see now what you mean. I was getting confused by how MIPS
defines the __raw_* accessors differently from other big-endian
architectures when CONFIG_SWAP_IO_SPACE is disabled.

I suppose this just means you can't use any PCI drivers using __raw_
accessors or memcpy_fromio(), but your patch to the serial driver is fine.

> Alternatively PCI device driver has to do endian swap, It is better to let
> PCI device driver to do endian swap instead because SWAP_IO_SPACE is global
> wide macro.
> Once we set it, other peripheral such as USB has to change its register
> access as well

I'm not entirely sure what you mean here, I would assume that aiming for
maximum compatibility with existing drivers would be the main goal here.
The USB platform drivers can already deal with being compiled for either
(or both) endianess.

      Arnd

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

* Re: [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial
  2018-06-18 10:59       ` Arnd Bergmann
@ 2018-06-19  6:46         ` Wu, Songjun
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Songjun @ 2018-06-19  6:46 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: hua.ma, yixin.zhu, chuanhua.lei,
	open list:RALINK MIPS ARCHITECTURE, qi-ming.wu, linux-clk,
	linux-serial, DTML, James Hogan, Linux Kernel Mailing List,
	Thomas Gleixner, Philippe Ombredanne, Rob Herring, Kate Stewart,
	Greg Kroah-Hartman, Mark Rutland, Ralf Baechle



On 6/18/2018 6:59 PM, Arnd Bergmann wrote:
> On Mon, Jun 18, 2018 at 11:42 AM, Wu, Songjun
> <songjun.wu@linux.intel.com> wrote:
>> On 6/14/2018 6:03 PM, Arnd Bergmann wrote:
>>> On Tue, Jun 12, 2018 at 7:40 AM, Songjun Wu <songjun.wu@linux.intel.com>
>>> wrote:
>>>> Previous implementation uses a hard-coded register value to check if
>>>> the current serial entity is the console entity.
>>>> Now the lantiq serial driver uses the aliases for the index of the
>>>> serial port.
>>>> The lantiq danube serial dts are updated with aliases to support this.
>>>>
>>>> Signed-off-by: Songjun Wu <songjun.wu@linux.intel.com>
>>>> ---
>>>>
>>>>    arch/mips/boot/dts/lantiq/danube.dtsi | 6 +++++-
>>>>    1 file changed, 5 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi
>>>> b/arch/mips/boot/dts/lantiq/danube.dtsi
>>>> index 2dd950181f8a..7a9e15da6bd0 100644
>>>> --- a/arch/mips/boot/dts/lantiq/danube.dtsi
>>>> +++ b/arch/mips/boot/dts/lantiq/danube.dtsi
>>>> @@ -4,6 +4,10 @@
>>>>           #size-cells = <1>;
>>>>           compatible = "lantiq,xway", "lantiq,danube";
>>>>
>>>> +       aliases {
>>>> +               serial0 = &asc1;
>>>> +       };
>>>> +
>>> You generally want the aliases to be part of the board specific file,
>>> not every board numbers their serial ports in the same way.
>>>
>> In this chip only asc1 can be used as console,  so serial0 is defined in
>> chip specific file.
> This was a more general comment about 'aliases' being board specific
> in principle (though we've had exceptions in the past). Even if there
> is only one uart on the chip, I'd recommend following the same
> conventions as the other chips that have more than one uart.
>
>         Arnd
Accept, 'aliases' will be move to the board specific file.

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

* [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs
@ 2018-06-01  5:55 Songjun Wu
  0 siblings, 0 replies; 33+ messages in thread
From: Songjun Wu @ 2018-06-01  5:55 UTC (permalink / raw)
  To: yixin.zhu, hua.ma, chuanhua.lei
  Cc: hauke.mehrtens, thomas.langer, Songjun Wu, devicetree,
	Ralf Baechle, Michael Turquette, Kate Stewart, James Hogan,
	linux-mips, Stephen Boyd, Jiri Slaby, linux-kernel,
	Thomas Gleixner, Philippe Ombredanne, Rob Herring, linux-serial,
	Greg Kroah-Hartman, GitAuthor:Ma, Mark Rutland, linux-clk

This patch series is for adding the support for Intel MIPS
Interaptive SoC GRX500 family.
It mainly includes CCF support, serial driver optimization
and DTS modification.


Ma, Hua (1):
  MIPS: intel: Add initial support for Intel MIPS SoCs

Songjun Wu (5):
  tty: serial: lantiq: Always use readl()/writel()
  tty: serial: lantiq: Convert global lock to per device lock
  tty: serial: lantiq: Remove unneeded header includes and macros
  tty: serial: lantiq: Add CCF support
  MIPS: dts: Add aliases node for lantiq danube serial

Zhu Yixin (1):
  clk: intel: Add clock driver for GRX500 SoC

 .../devicetree/bindings/clock/intel,grx500-clk.txt |  46 ++
 .../devicetree/bindings/serial/lantiq_asc.txt      |  15 +
 arch/mips/Kbuild.platforms                         |   1 +
 arch/mips/Kconfig                                  |  37 +-
 arch/mips/boot/dts/Makefile                        |   1 +
 arch/mips/boot/dts/intel-mips/Makefile             |   3 +
 arch/mips/boot/dts/intel-mips/easy350_anywan.dts   |  20 +
 arch/mips/boot/dts/intel-mips/xrx500.dtsi          | 196 ++++++
 arch/mips/boot/dts/lantiq/danube.dtsi              |   6 +-
 arch/mips/configs/grx500_defconfig                 | 165 +++++
 .../asm/mach-intel-mips/cpu-feature-overrides.h    |  61 ++
 arch/mips/include/asm/mach-intel-mips/ioremap.h    |  39 ++
 arch/mips/include/asm/mach-intel-mips/irq.h        |  17 +
 .../asm/mach-intel-mips/kernel-entry-init.h        |  76 +++
 arch/mips/include/asm/mach-intel-mips/spaces.h     |  29 +
 arch/mips/include/asm/mach-intel-mips/war.h        |  18 +
 arch/mips/intel-mips/Kconfig                       |  22 +
 arch/mips/intel-mips/Makefile                      |   3 +
 arch/mips/intel-mips/Platform                      |  11 +
 arch/mips/intel-mips/irq.c                         |  36 ++
 arch/mips/intel-mips/prom.c                        | 184 ++++++
 arch/mips/intel-mips/time.c                        |  56 ++
 drivers/clk/Kconfig                                |   1 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/intel/Kconfig                          |  21 +
 drivers/clk/intel/Makefile                         |   7 +
 drivers/clk/intel/clk-cgu-api.c                    | 676 +++++++++++++++++++++
 drivers/clk/intel/clk-cgu-api.h                    | 120 ++++
 drivers/clk/intel/clk-grx500.c                     | 236 +++++++
 drivers/tty/serial/Kconfig                         |   2 +-
 drivers/tty/serial/lantiq.c                        | 415 ++++++++-----
 include/dt-bindings/clock/intel,grx500-clk.h       |  61 ++
 32 files changed, 2418 insertions(+), 164 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/intel,grx500-clk.txt
 create mode 100644 arch/mips/boot/dts/intel-mips/Makefile
 create mode 100644 arch/mips/boot/dts/intel-mips/easy350_anywan.dts
 create mode 100644 arch/mips/boot/dts/intel-mips/xrx500.dtsi
 create mode 100644 arch/mips/configs/grx500_defconfig
 create mode 100644 arch/mips/include/asm/mach-intel-mips/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/ioremap.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/irq.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/kernel-entry-init.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/spaces.h
 create mode 100644 arch/mips/include/asm/mach-intel-mips/war.h
 create mode 100644 arch/mips/intel-mips/Kconfig
 create mode 100644 arch/mips/intel-mips/Makefile
 create mode 100644 arch/mips/intel-mips/Platform
 create mode 100644 arch/mips/intel-mips/irq.c
 create mode 100644 arch/mips/intel-mips/prom.c
 create mode 100644 arch/mips/intel-mips/time.c
 create mode 100644 drivers/clk/intel/Kconfig
 create mode 100644 drivers/clk/intel/Makefile
 create mode 100644 drivers/clk/intel/clk-cgu-api.c
 create mode 100644 drivers/clk/intel/clk-cgu-api.h
 create mode 100644 drivers/clk/intel/clk-grx500.c
 create mode 100644 include/dt-bindings/clock/intel,grx500-clk.h

-- 
2.11.0

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

end of thread, other threads:[~2018-06-19  6:47 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-12  5:40 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu
2018-06-12  5:40 ` [PATCH 1/7] MIPS: dts: Add aliases node for lantiq danube serial Songjun Wu
2018-06-12 22:24   ` Rob Herring
2018-06-14  6:19     ` Wu, Songjun
2018-06-14 10:03   ` Arnd Bergmann
2018-06-18  9:42     ` Wu, Songjun
2018-06-18 10:59       ` Arnd Bergmann
2018-06-19  6:46         ` Wu, Songjun
2018-06-12  5:40 ` [PATCH 2/7] clk: intel: Add clock driver for GRX500 SoC Songjun Wu
2018-06-12 22:37   ` Rob Herring
2018-06-14  8:40     ` yixin zhu
2018-06-14 14:09       ` Rob Herring
2018-06-18 10:05         ` yixin zhu
2018-06-12  5:40 ` [PATCH 3/7] MIPS: intel: Add initial support for Intel MIPS SoCs Songjun Wu
2018-06-12 11:23   ` James Hogan
2018-06-14  9:24     ` yixin zhu
2018-06-12 22:31   ` Rob Herring
2018-06-14  8:01     ` Hua Ma
2018-06-12  5:40 ` [PATCH 4/7] tty: serial: lantiq: Always use readl()/writel() Songjun Wu
2018-06-12  8:13   ` Andy Shevchenko
2018-06-14  7:05     ` Wu, Songjun
2018-06-14 10:07   ` Arnd Bergmann
2018-06-18  9:39     ` Wu, Songjun
2018-06-18 11:52       ` Arnd Bergmann
2018-06-12  5:40 ` [PATCH 5/7] tty: serial: lantiq: Convert global lock to per device lock Songjun Wu
2018-06-12  5:40 ` [PATCH 6/7] tty: serial: lantiq: Remove unneeded header includes and macros Songjun Wu
2018-06-12  5:40 ` [PATCH 7/7] tty: serial: lantiq: Add CCF support Songjun Wu
2018-06-12  8:07   ` kbuild test robot
2018-06-12  8:07     ` kbuild test robot
2018-06-12  8:07     ` kbuild test robot
2018-06-12 22:39   ` Rob Herring
2018-06-14  6:38     ` Wu, Songjun
  -- strict thread matches above, loose matches on Subject: below --
2018-06-01  5:55 [PATCH 0/7] MIPS: intel: add initial support for Intel MIPS SoCs Songjun Wu

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.