2018-01-02 15:09:05

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 01/15] clk: ingenic: Use const pointer to clk_ops in struct

The CGU common code does not modify the pointed clk_ops structure, so it
should be marked as const.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.h | 2 +-
drivers/clk/ingenic/jz4780-cgu.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

v2: New patch in this series
v3: No change
v4: No change
v5: No change

diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index e78b586536ea..f1527cf75b3f 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -120,7 +120,7 @@ struct ingenic_cgu_gate_info {
* @clk_ops: custom clock operation callbacks
*/
struct ingenic_cgu_custom_info {
- struct clk_ops *clk_ops;
+ const struct clk_ops *clk_ops;
};

/**
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
index ac3585ed8228..6427be117ff1 100644
--- a/drivers/clk/ingenic/jz4780-cgu.c
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -203,7 +203,7 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0;
}

-static struct clk_ops jz4780_otg_phy_ops = {
+static const struct clk_ops jz4780_otg_phy_ops = {
.get_parent = jz4780_otg_phy_get_parent,
.set_parent = jz4780_otg_phy_set_parent,

--
2.11.0


2018-01-02 15:09:07

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 04/15] clk: ingenic: Add code to enable/disable PLLs

This commit permits the PLLs to be dynamically enabled and disabled when
their children clocks are enabled and disabled.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 89 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 74 insertions(+), 15 deletions(-)

v2: No change
v3: No change
v4: No change
v5: No change

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 381c4a17a1fc..56a712c9075f 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -107,9 +107,6 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
if (bypass)
return parent_rate;

- if (!enable)
- return 0;
-
for (od = 0; od < pll_info->od_max; od++) {
if (pll_info->od_encoding[od] == od_enc)
break;
@@ -153,17 +150,25 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
return div_u64((u64)parent_rate * m, n * od);
}

-static long
-ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
- unsigned long *prate)
+static inline const struct ingenic_cgu_clk_info *to_clk_info(
+ struct ingenic_clk *ingenic_clk)
{
- struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;

clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);

+ return clk_info;
+}
+
+static long
+ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
+ unsigned long *prate)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+
return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
}

@@ -171,19 +176,14 @@ static int
ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long parent_rate)
{
- const unsigned timeout = 100;
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
- const struct ingenic_cgu_clk_info *clk_info;
- const struct ingenic_cgu_pll_info *pll_info;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long rate, flags;
- unsigned m, n, od, i;
+ unsigned int m, n, od;
u32 ctl;

- clk_info = &cgu->clock_info[ingenic_clk->idx];
- BUG_ON(clk_info->type != CGU_CLK_PLL);
- pll_info = &clk_info->pll;
-
rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
&m, &n, &od);
if (rate != req_rate)
@@ -202,6 +202,26 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;

+ writel(ctl, cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+
+ return 0;
+}
+
+static int ingenic_pll_enable(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ const unsigned int timeout = 100;
+ unsigned long flags;
+ unsigned int i;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+
ctl &= ~BIT(pll_info->bypass_bit);
ctl |= BIT(pll_info->enable_bit);

@@ -223,10 +243,48 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0;
}

+static void ingenic_pll_disable(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ unsigned long flags;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+
+ ctl &= ~BIT(pll_info->enable_bit);
+
+ writel(ctl, cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+}
+
+static int ingenic_pll_is_enabled(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ unsigned long flags;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+
+ return !!(ctl & BIT(pll_info->enable_bit));
+}
+
static const struct clk_ops ingenic_pll_ops = {
.recalc_rate = ingenic_pll_recalc_rate,
.round_rate = ingenic_pll_round_rate,
.set_rate = ingenic_pll_set_rate,
+
+ .enable = ingenic_pll_enable,
+ .disable = ingenic_pll_disable,
+ .is_enabled = ingenic_pll_is_enabled,
};

/*
@@ -601,6 +659,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
}
} else if (caps & CGU_CLK_PLL) {
clk_init.ops = &ingenic_pll_ops;
+ clk_init.flags |= CLK_SET_RATE_GATE;

caps &= ~CGU_CLK_PLL;

--
2.11.0

2018-01-02 15:09:16

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 15/15] MIPS: ingenic: Initial GCW Zero support

The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
handheld game console, successfully kickstarted in ~2012, running Linux.

Signed-off-by: Paul Cercueil <[email protected]>
---
arch/mips/boot/dts/ingenic/Makefile | 1 +
arch/mips/boot/dts/ingenic/gcw0.dts | 61 +++++++++++++++++++++++++++++++++++++
arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
arch/mips/jz4740/Kconfig | 4 +++
arch/mips/jz4740/boards.c | 1 +
5 files changed, 94 insertions(+)
create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
create mode 100644 arch/mips/configs/gcw0_defconfig

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
Drop custom CROSS_COMPILE from defconfig

diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
index 6a31759839b4..5b1361a89e02 100644
--- a/arch/mips/boot/dts/ingenic/Makefile
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb
+dtb-$(CONFIG_JZ4770_GCW0) += gcw0.dtb
dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb

obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts b/arch/mips/boot/dts/ingenic/gcw0.dts
new file mode 100644
index 000000000000..4dc72de387db
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/gcw0.dts
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "jz4770.dtsi"
+
+/ {
+ compatible = "gcw,zero", "ingenic,jz4770";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial2:57600n8";
+ };
+
+ board {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <>;
+
+ otg_phy: otg-phy {
+ compatible = "usb-nop-xceiv";
+ clocks = <&cgu JZ4770_CLK_OTG_PHY>;
+ clock-names = "main_clk";
+ };
+ };
+};
+
+&ext {
+ clock-frequency = <12000000>;
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&cgu {
+ /* Put high-speed peripherals under PLL1, such that we can change the
+ * PLL0 frequency on demand without having to suspend peripherals.
+ * We use a rate of 432 MHz, which is the least common multiple of
+ * 27 MHz (required by TV encoder) and 48 MHz (required by USB host).
+ */
+ assigned-clocks =
+ <&cgu JZ4770_CLK_PLL1>,
+ <&cgu JZ4770_CLK_UHC>;
+ assigned-clock-parents =
+ <0>,
+ <&cgu JZ4770_CLK_PLL1>;
+ assigned-clock-rates =
+ <432000000>;
+};
+
+&uhc {
+ /* The WiFi module is connected to the UHC. */
+ status = "okay";
+};
diff --git a/arch/mips/configs/gcw0_defconfig b/arch/mips/configs/gcw0_defconfig
new file mode 100644
index 000000000000..99ac1fa3b35f
--- /dev/null
+++ b/arch/mips/configs/gcw0_defconfig
@@ -0,0 +1,27 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4770_GCW0=y
+CONFIG_HIGHMEM=y
+# CONFIG_BOUNCE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_SECCOMP is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EMBEDDED=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_TMPFS=y
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 29a9361a2b77..4dd0c446ecec 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -8,6 +8,10 @@ config JZ4740_QI_LB60
bool "Qi Hardware Ben NanoNote"
select MACH_JZ4740

+config JZ4770_GCW0
+ bool "Game Consoles Worldwide GCW Zero"
+ select MACH_JZ4770
+
config JZ4780_CI20
bool "MIPS Creator CI20"
select MACH_JZ4780
diff --git a/arch/mips/jz4740/boards.c b/arch/mips/jz4740/boards.c
index 13b0bddd8cb7..1389d6eec80f 100644
--- a/arch/mips/jz4740/boards.c
+++ b/arch/mips/jz4740/boards.c
@@ -8,5 +8,6 @@
#include <asm/mips_machine.h>

MIPS_MACHINE(MACH_INGENIC_JZ4740, "qi,lb60", "Qi Hardware Ben Nanonote", NULL);
+MIPS_MACHINE(MACH_INGENIC_JZ4770, "gcw,zero", "GCW Zero", NULL);
MIPS_MACHINE(MACH_INGENIC_JZ4780, "img,ci20",
"Imagination Technologies CI20", NULL);
--
2.11.0

2018-01-02 15:09:13

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 10/15] MIPS: ingenic: Add machine info for supported boards

This makes sure that 'mips_machtype' will be initialized to the SoC
version used on the board.

Signed-off-by: Paul Cercueil <[email protected]>
---
arch/mips/Kconfig | 1 +
arch/mips/jz4740/Makefile | 2 +-
arch/mips/jz4740/boards.c | 12 ++++++++++++
arch/mips/jz4740/setup.c | 34 +++++++++++++++++++++++++++++-----
4 files changed, 43 insertions(+), 6 deletions(-)
create mode 100644 arch/mips/jz4740/boards.c

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 350a990fc719..83243e427e36 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -376,6 +376,7 @@ config MACH_INGENIC
select BUILTIN_DTB
select USE_OF
select LIBFDT
+ select MIPS_MACHINE

config LANTIQ
bool "Lantiq based platforms"
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 88d6aa7d000b..fc2d3b3c4a80 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -6,7 +6,7 @@
# Object file lists.

obj-y += prom.o time.o reset.o setup.o \
- platform.o timer.o
+ platform.o timer.o boards.o

CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt

diff --git a/arch/mips/jz4740/boards.c b/arch/mips/jz4740/boards.c
new file mode 100644
index 000000000000..13b0bddd8cb7
--- /dev/null
+++ b/arch/mips/jz4740/boards.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ingenic boards support
+ * Copyright 2017, Paul Cercueil <[email protected]>
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/mips_machine.h>
+
+MIPS_MACHINE(MACH_INGENIC_JZ4740, "qi,lb60", "Qi Hardware Ben Nanonote", NULL);
+MIPS_MACHINE(MACH_INGENIC_JZ4780, "img,ci20",
+ "Imagination Technologies CI20", NULL);
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 6d0152321819..afd84ee966e8 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -22,6 +22,7 @@
#include <linux/of_fdt.h>

#include <asm/bootinfo.h>
+#include <asm/mips_machine.h>
#include <asm/prom.h>

#include <asm/mach-jz4740/base.h>
@@ -53,16 +54,34 @@ static void __init jz4740_detect_mem(void)
add_memory_region(0, size, BOOT_MEM_RAM);
}

+static unsigned long __init get_board_mach_type(const void *fdt)
+{
+ const struct mips_machine *mach;
+
+ for (mach = (struct mips_machine *)&__mips_machines_start;
+ mach < (struct mips_machine *)&__mips_machines_end;
+ mach++) {
+ if (!fdt_node_check_compatible(fdt, 0, mach->mach_id))
+ return mach->mach_type;
+ }
+
+ return MACH_INGENIC_JZ4740;
+}
+
void __init plat_mem_setup(void)
{
int offset;

+ if (!early_init_dt_scan(__dtb_start))
+ return;
+
jz4740_reset_init();
- __dt_setup_arch(__dtb_start);

offset = fdt_path_offset(__dtb_start, "/memory");
if (offset < 0)
jz4740_detect_mem();
+
+ mips_machtype = get_board_mach_type(__dtb_start);
}

void __init device_tree_init(void)
@@ -75,13 +94,18 @@ void __init device_tree_init(void)

const char *get_system_type(void)
{
- if (IS_ENABLED(CONFIG_MACH_JZ4780))
- return "JZ4780";
-
- return "JZ4740";
+ return mips_get_machine_name();
}

void __init arch_init_irq(void)
{
irqchip_init();
}
+
+static int __init jz4740_machine_setup(void)
+{
+ mips_machine_setup();
+
+ return 0;
+}
+arch_initcall(jz4740_machine_setup);
--
2.11.0

2018-01-02 15:09:39

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 14/15] devicetree/bindings: Add GCW vendor prefix

Game Consoles Worldwide, mostly known under the acronym GCW, is the
creator of the GCW Zero open-source video game system.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)

v2: It's 'Game Consoles Worldwide', not 'Games Consoles Worldwide'
v3: No change
v4: No change
v5: No change

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0994bdd82cd3..f40f4da39937 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -123,6 +123,7 @@ focaltech FocalTech Systems Co.,Ltd
friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
fsl Freescale Semiconductor
fujitsu Fujitsu Ltd.
+gcw Game Consoles Worldwide
ge General Electric Company
geekbuying GeekBuying
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
--
2.11.0

2018-01-02 15:09:59

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 11/15] MIPS: ingenic: Initial JZ4770 support

Provide just enough bits (clocks, clocksource, uart) to allow a kernel
to boot on the JZ4770 SoC to a initramfs userspace.

Signed-off-by: Paul Cercueil <[email protected]>
---
arch/mips/boot/dts/ingenic/jz4770.dtsi | 212 +++++++++++++++++++++++++++++++++
arch/mips/jz4740/Kconfig | 6 +
arch/mips/jz4740/time.c | 2 +-
3 files changed, 219 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/boot/dts/ingenic/jz4770.dtsi

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier

diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
new file mode 100644
index 000000000000..7c2804f3f5f1
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/clock/jz4770-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4770";
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-controller@10001000 {
+ compatible = "ingenic,jz4770-intc";
+ reg = <0x10001000 0x40>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ osc32k: osc32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4770-cgu@10000000 {
+ compatible = "ingenic,jz4770-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&osc32k>;
+ clock-names = "ext", "osc32k";
+
+ #clock-cells = <1>;
+ };
+
+ pinctrl: pin-controller@10010000 {
+ compatible = "ingenic,jz4770-pinctrl";
+ reg = <0x10010000 0x600>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpa: gpio@0 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <0>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 0 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <17>;
+ };
+
+ gpb: gpio@1 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <1>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 32 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ };
+
+ gpc: gpio@2 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <2>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 64 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <15>;
+ };
+
+ gpd: gpio@3 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <3>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 96 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <14>;
+ };
+
+ gpe: gpio@4 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <4>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 128 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <13>;
+ };
+
+ gpf: gpio@5 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <5>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 160 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <12>;
+ };
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10030000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART0>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <5>;
+
+ status = "disabled";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10031000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART1>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <4>;
+
+ status = "disabled";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10032000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART2>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <3>;
+
+ status = "disabled";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10033000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART3>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <2>;
+
+ status = "disabled";
+ };
+
+ uhc: uhc@13430000 {
+ compatible = "generic-ohci";
+ reg = <0x13430000 0x1000>;
+
+ clocks = <&cgu JZ4770_CLK_UHC>, <&cgu JZ4770_CLK_UHC_PHY>;
+ assigned-clocks = <&cgu JZ4770_CLK_UHC>;
+ assigned-clock-rates = <48000000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <20>;
+
+ status = "disabled";
+ };
+};
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 643af2012e14..29a9361a2b77 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -18,6 +18,12 @@ config MACH_JZ4740
bool
select SYS_HAS_CPU_MIPS32_R1

+config MACH_JZ4770
+ bool
+ select MIPS_CPU_SCACHE
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_HIGHMEM
+
config MACH_JZ4780
bool
select MIPS_CPU_SCACHE
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index bb1ad5119da4..2ca9160f642a 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
#ifdef CONFIG_MACH_JZ4740
.irq = JZ4740_IRQ_TCU0,
#endif
-#ifdef CONFIG_MACH_JZ4780
+#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
.irq = JZ4780_IRQ_TCU2,
#endif
};
--
2.11.0

2018-01-02 15:09:57

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 12/15] MIPS: JZ4770: Work around config2 misreporting associativity

From: Maarten ter Huurne <[email protected]>

According to config2, the associativity would be 5-ways, but the
documentation states 4-ways, which also matches the documented
L2 cache size of 256 kB.

Signed-off-by: Maarten ter Huurne <[email protected]>
---
arch/mips/mm/sc-mips.c | 9 +++++++++
1 file changed, 9 insertions(+)

v2: No change
v3: No change
v4: Rebased on top of Linux 4.15-rc5
v5: No change

diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 548acb7f8557..394673991bab 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -16,6 +16,7 @@
#include <asm/mmu_context.h>
#include <asm/r4kcache.h>
#include <asm/mips-cps.h>
+#include <asm/bootinfo.h>

/*
* MIPS32/MIPS64 L2 cache handling
@@ -220,6 +221,14 @@ static inline int __init mips_sc_probe(void)
else
return 0;

+ /*
+ * According to config2 it would be 5-ways, but that is contradicted
+ * by all documentation.
+ */
+ if (current_cpu_type() == CPU_JZRISC &&
+ mips_machtype == MACH_INGENIC_JZ4770)
+ c->scache.ways = 4;
+
c->scache.waysize = c->scache.sets * c->scache.linesz;
c->scache.waybit = __ffs(c->scache.waysize);

--
2.11.0

2018-01-02 15:09:55

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 13/15] MIPS: JZ4770: Workaround for corrupted DMA transfers

From: Maarten ter Huurne <[email protected]>

We have seen MMC DMA transfers read corrupted data from SDRAM when
a burst interval ends at physical address 0x10000000. To avoid this
problem, we remove the final page of low memory from the memory map.

Signed-off-by: Maarten ter Huurne <[email protected]>
---
arch/mips/jz4740/setup.c | 24 ++++++++++++++++++++++++
arch/mips/kernel/setup.c | 8 ++++++++
2 files changed, 32 insertions(+)

v2: No change
v3: No change
v4: No change
v5: No change

diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index afd84ee966e8..6948b133a15d 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -23,6 +23,7 @@

#include <asm/bootinfo.h>
#include <asm/mips_machine.h>
+#include <asm/page.h>
#include <asm/prom.h>

#include <asm/mach-jz4740/base.h>
@@ -102,6 +103,29 @@ void __init arch_init_irq(void)
irqchip_init();
}

+/*
+ * We have seen MMC DMA transfers read corrupted data from SDRAM when a burst
+ * interval ends at physical address 0x10000000. To avoid this problem, we
+ * remove the final page of low memory from the memory map.
+ */
+void __init jz4770_reserve_unsafe_for_dma(void)
+{
+ int i;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+
+ if (entry->type != BOOT_MEM_RAM)
+ continue;
+
+ if (entry->addr + entry->size != 0x10000000)
+ continue;
+
+ entry->size -= PAGE_SIZE;
+ break;
+ }
+}
+
static int __init jz4740_machine_setup(void)
{
mips_machine_setup();
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 85bc601e9a0d..5a2c20145aee 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -879,6 +879,14 @@ static void __init arch_mem_init(char **cmdline_p)

parse_early_param();

+#ifdef CONFIG_MACH_JZ4770
+ if (current_cpu_type() == CPU_JZRISC &&
+ mips_machtype == MACH_INGENIC_JZ4770) {
+ extern void __init jz4770_reserve_unsafe_for_dma(void);
+ jz4770_reserve_unsafe_for_dma();
+ }
+#endif
+
if (usermem) {
pr_info("User-defined physical RAM map:\n");
print_memory_map();
--
2.11.0

2018-01-02 15:09:10

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 07/15] MIPS: Setup boot_command_line before plat_mem_setup

From: Paul Burton <[email protected]>

Platforms using DT will typically call __dt_setup_arch from
plat_mem_setup. This in turn calls early_init_dt_scan. When
CONFIG_CMDLINE is set, this leads to its value being copied into
boot_command_line by early_init_dt_scan_chosen. If this happens before
the code setting up boot_command_line in arch_mem_init runs, that code
will go on to append CONFIG_CMDLINE (via builtin_cmdline) to
boot_command_line again, duplicating it. For some command line
parameters (eg. earlycon) this can be a problem. Set up
boot_command_line before early_init_dt_scan_chosen gets called such that
it will not write CONFIG_CMDLINE in this scenario & the arguments aren't
duplicated.

Signed-off-by: Paul Burton <[email protected]>
---
arch/mips/kernel/setup.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)

v2: New patch in this series
v3: No change
v4: No change
v5: No change

diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 702c678de116..85bc601e9a0d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -826,25 +826,6 @@ static void __init arch_mem_init(char **cmdline_p)
struct memblock_region *reg;
extern void plat_mem_setup(void);

- /* call board setup routine */
- plat_mem_setup();
-
- /*
- * Make sure all kernel memory is in the maps. The "UP" and
- * "DOWN" are opposite for initdata since if it crosses over
- * into another memory section you don't want that to be
- * freed when the initdata is freed.
- */
- arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
- PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
- BOOT_MEM_RAM);
- arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
- PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
- BOOT_MEM_INIT_RAM);
-
- pr_info("Determined physical RAM map:\n");
- print_memory_map();
-
#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
@@ -872,6 +853,26 @@ static void __init arch_mem_init(char **cmdline_p)
}
#endif
#endif
+
+ /* call board setup routine */
+ plat_mem_setup();
+
+ /*
+ * Make sure all kernel memory is in the maps. The "UP" and
+ * "DOWN" are opposite for initdata since if it crosses over
+ * into another memory section you don't want that to be
+ * freed when the initdata is freed.
+ */
+ arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
+ PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+ arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
+ PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
+ BOOT_MEM_INIT_RAM);
+
+ pr_info("Determined physical RAM map:\n");
+ print_memory_map();
+
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);

*cmdline_p = command_line;
--
2.11.0

2018-01-02 15:11:01

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 09/15] MIPS: platform: add machtype IDs for more Ingenic SoCs

Add a machtype ID for the JZ4780 SoC, which was missing, and one for the
newly supported JZ4770 SoC.

Signed-off-by: Paul Cercueil <[email protected]>
---
arch/mips/include/asm/bootinfo.h | 2 ++
1 file changed, 2 insertions(+)

v2: No change
v3: No change
v5: No change

diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index e26a093bb17a..a301a8f4bc66 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -79,6 +79,8 @@ enum loongson_machine_type {
*/
#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */
#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */
+#define MACH_INGENIC_JZ4770 2 /* JZ4770 SOC */
+#define MACH_INGENIC_JZ4780 3 /* JZ4780 SOC */

extern char *system_type;
const char *get_system_type(void);
--
2.11.0

2018-01-02 15:11:19

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 06/15] clk: Add Ingenic jz4770 CGU driver

Add support for the clocks provided by the CGU in the Ingenic JZ4770
SoC.

Signed-off-by: Paul Cercueil <[email protected]>
Signed-off-by: Maarten ter Huurne <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/Makefile | 1 +
drivers/clk/ingenic/jz4770-cgu.c | 483 +++++++++++++++++++++++++++++++++++++++
2 files changed, 484 insertions(+)
create mode 100644 drivers/clk/ingenic/jz4770-cgu.c

v2: Make structures static const
v3: <dt-bindings/clock/jz4770-cgu.h> is now added in a separate patch
v4: No change
v5: Use SPDX license identifier

diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index cd47b0664c2b..1456e4cdb562 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,3 +1,4 @@
obj-y += cgu.o
obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
+obj-$(CONFIG_MACH_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o
diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c
new file mode 100644
index 000000000000..c78d369b9403
--- /dev/null
+++ b/drivers/clk/ingenic/jz4770-cgu.c
@@ -0,0 +1,483 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ4770 SoC CGU driver
+ * Copyright 2018, Paul Cercueil <[email protected]>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/jz4770-cgu.h>
+#include "cgu.h"
+
+/*
+ * CPM registers offset address definition
+ */
+#define CGU_REG_CPCCR 0x00
+#define CGU_REG_LCR 0x04
+#define CGU_REG_CPPCR0 0x10
+#define CGU_REG_CLKGR0 0x20
+#define CGU_REG_OPCR 0x24
+#define CGU_REG_CLKGR1 0x28
+#define CGU_REG_CPPCR1 0x30
+#define CGU_REG_USBPCR1 0x48
+#define CGU_REG_USBCDR 0x50
+#define CGU_REG_I2SCDR 0x60
+#define CGU_REG_LPCDR 0x64
+#define CGU_REG_MSC0CDR 0x68
+#define CGU_REG_UHCCDR 0x6c
+#define CGU_REG_SSICDR 0x74
+#define CGU_REG_CIMCDR 0x7c
+#define CGU_REG_GPSCDR 0x80
+#define CGU_REG_PCMCDR 0x84
+#define CGU_REG_GPUCDR 0x88
+#define CGU_REG_MSC1CDR 0xA4
+#define CGU_REG_MSC2CDR 0xA8
+#define CGU_REG_BCHCDR 0xAC
+
+/* bits within the LCR register */
+#define LCR_LPM BIT(0) /* Low Power Mode */
+
+/* bits within the OPCR register */
+#define OPCR_SPENDH BIT(5) /* UHC PHY suspend */
+#define OPCR_SPENDN BIT(7) /* OTG PHY suspend */
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_UHC_POWER BIT(5) /* UHC PHY power down */
+
+static struct ingenic_cgu *cgu;
+
+static int jz4770_uhc_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
+ writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
+ return 0;
+}
+
+static void jz4770_uhc_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
+ writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
+}
+
+static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ return !(readl(reg_opcr) & OPCR_SPENDH) &&
+ (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
+}
+
+static const struct clk_ops jz4770_uhc_phy_ops = {
+ .enable = jz4770_uhc_phy_enable,
+ .disable = jz4770_uhc_phy_disable,
+ .is_enabled = jz4770_uhc_phy_is_enabled,
+};
+
+static int jz4770_otg_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ writel(readl(reg_opcr) | OPCR_SPENDN, reg_opcr);
+
+ /* Wait for the clock to be stable */
+ udelay(50);
+ return 0;
+}
+
+static void jz4770_otg_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDN, reg_opcr);
+}
+
+static int jz4770_otg_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ return !!(readl(reg_opcr) & OPCR_SPENDN);
+}
+
+static const struct clk_ops jz4770_otg_phy_ops = {
+ .enable = jz4770_otg_phy_enable,
+ .disable = jz4770_otg_phy_disable,
+ .is_enabled = jz4770_otg_phy_is_enabled,
+};
+
+static const s8 pll_od_encoding[8] = {
+ 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+};
+
+static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
+
+ /* External clocks */
+
+ [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
+ [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
+
+ /* PLLs */
+
+ [JZ4770_CLK_PLL0] = {
+ "pll0", CGU_CLK_PLL,
+ .parents = { JZ4770_CLK_EXT },
+ .pll = {
+ .reg = CGU_REG_CPPCR0,
+ .m_shift = 24,
+ .m_bits = 7,
+ .m_offset = 1,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 1,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 8,
+ .od_encoding = pll_od_encoding,
+ .bypass_bit = 9,
+ .enable_bit = 8,
+ .stable_bit = 10,
+ },
+ },
+
+ [JZ4770_CLK_PLL1] = {
+ /* TODO: PLL1 can depend on PLL0 */
+ "pll1", CGU_CLK_PLL,
+ .parents = { JZ4770_CLK_EXT },
+ .pll = {
+ .reg = CGU_REG_CPPCR1,
+ .m_shift = 24,
+ .m_bits = 7,
+ .m_offset = 1,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 1,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 8,
+ .od_encoding = pll_od_encoding,
+ .enable_bit = 7,
+ .stable_bit = 6,
+ .no_bypass_bit = true,
+ },
+ },
+
+ /* Main clocks */
+
+ [JZ4770_CLK_CCLK] = {
+ "cclk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_H0CLK] = {
+ "h0clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_H1CLK] = {
+ "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1 },
+ .gate = { CGU_REG_LCR, 30 },
+ },
+ [JZ4770_CLK_H2CLK] = {
+ "h2clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_C1CLK] = {
+ "c1clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_PCLK] = {
+ "pclk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
+ },
+
+ /* Those divided clocks can connect to PLL0 or PLL1 */
+
+ [JZ4770_CLK_MMC0_MUX] = {
+ "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC0CDR, 30, 1 },
+ .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC0CDR, 31 },
+ },
+ [JZ4770_CLK_MMC1_MUX] = {
+ "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC1CDR, 30, 1 },
+ .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC1CDR, 31 },
+ },
+ [JZ4770_CLK_MMC2_MUX] = {
+ "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC2CDR, 30, 1 },
+ .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC2CDR, 31 },
+ },
+ [JZ4770_CLK_CIM] = {
+ "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_CIMCDR, 31, 1 },
+ .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 26 },
+ },
+ [JZ4770_CLK_UHC] = {
+ "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_UHCCDR, 29, 1 },
+ .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 24 },
+ },
+ [JZ4770_CLK_GPU] = {
+ "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
+ .mux = { CGU_REG_GPUCDR, 31, 1 },
+ .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 9 },
+ },
+ [JZ4770_CLK_BCH] = {
+ "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_BCHCDR, 31, 1 },
+ .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 1 },
+ },
+ [JZ4770_CLK_LPCLK_MUX] = {
+ "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_LPCDR, 29, 1 },
+ .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 28 },
+ },
+ [JZ4770_CLK_GPS] = {
+ "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_GPSCDR, 31, 1 },
+ .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 22 },
+ },
+
+ /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
+
+ [JZ4770_CLK_SSI_MUX] = {
+ "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_SSICDR, 30, 2 },
+ .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
+ },
+ [JZ4770_CLK_PCM_MUX] = {
+ "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_PCMCDR, 30, 2 },
+ .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
+ },
+ [JZ4770_CLK_I2S] = {
+ "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_I2SCDR, 30, 2 },
+ .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 13 },
+ },
+ [JZ4770_CLK_OTG] = {
+ "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_USBCDR, 30, 2 },
+ .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 2 },
+ },
+
+ /* Gate-only clocks */
+
+ [JZ4770_CLK_SSI0] = {
+ "ssi0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 4 },
+ },
+ [JZ4770_CLK_SSI1] = {
+ "ssi1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 19 },
+ },
+ [JZ4770_CLK_SSI2] = {
+ "ssi2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 20 },
+ },
+ [JZ4770_CLK_PCM0] = {
+ "pcm0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PCM_MUX, },
+ .gate = { CGU_REG_CLKGR1, 8 },
+ },
+ [JZ4770_CLK_PCM1] = {
+ "pcm1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PCM_MUX, },
+ .gate = { CGU_REG_CLKGR1, 10 },
+ },
+ [JZ4770_CLK_DMA] = {
+ "dma", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H2CLK, },
+ .gate = { CGU_REG_CLKGR0, 21 },
+ },
+ [JZ4770_CLK_I2C0] = {
+ "i2c0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 5 },
+ },
+ [JZ4770_CLK_I2C1] = {
+ "i2c1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 6 },
+ },
+ [JZ4770_CLK_I2C2] = {
+ "i2c2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR1, 15 },
+ },
+ [JZ4770_CLK_UART0] = {
+ "uart0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 15 },
+ },
+ [JZ4770_CLK_UART1] = {
+ "uart1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 16 },
+ },
+ [JZ4770_CLK_UART2] = {
+ "uart2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 17 },
+ },
+ [JZ4770_CLK_UART3] = {
+ "uart3", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 18 },
+ },
+ [JZ4770_CLK_IPU] = {
+ "ipu", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H0CLK, },
+ .gate = { CGU_REG_CLKGR0, 29 },
+ },
+ [JZ4770_CLK_ADC] = {
+ "adc", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 14 },
+ },
+ [JZ4770_CLK_AIC] = {
+ "aic", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 8 },
+ },
+ [JZ4770_CLK_AUX] = {
+ "aux", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_C1CLK, },
+ .gate = { CGU_REG_CLKGR1, 14 },
+ },
+ [JZ4770_CLK_VPU] = {
+ "vpu", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR1, 7 },
+ },
+ [JZ4770_CLK_MMC0] = {
+ "mmc0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC0_MUX, },
+ .gate = { CGU_REG_CLKGR0, 3 },
+ },
+ [JZ4770_CLK_MMC1] = {
+ "mmc1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC1_MUX, },
+ .gate = { CGU_REG_CLKGR0, 11 },
+ },
+ [JZ4770_CLK_MMC2] = {
+ "mmc2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC2_MUX, },
+ .gate = { CGU_REG_CLKGR0, 12 },
+ },
+
+ /* Custom clocks */
+
+ [JZ4770_CLK_UHC_PHY] = {
+ "uhc_phy", CGU_CLK_CUSTOM,
+ .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
+ .custom = { &jz4770_uhc_phy_ops },
+ },
+ [JZ4770_CLK_OTG_PHY] = {
+ "usb_phy", CGU_CLK_CUSTOM,
+ .parents = { JZ4770_CLK_OTG, -1, -1, -1 },
+ .custom = { &jz4770_otg_phy_ops },
+ },
+
+ [JZ4770_CLK_EXT512] = {
+ "ext/512", CGU_CLK_FIXDIV,
+ .parents = { JZ4770_CLK_EXT },
+ .fixdiv = { 512 },
+ },
+
+ [JZ4770_CLK_RTC] = {
+ "rtc", CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
+ .mux = { CGU_REG_OPCR, 2, 1},
+ },
+};
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+static int jz4770_cgu_pm_suspend(void)
+{
+ u32 val;
+
+ val = readl(cgu->base + CGU_REG_LCR);
+ writel(val | LCR_LPM, cgu->base + CGU_REG_LCR);
+ return 0;
+}
+
+static void jz4770_cgu_pm_resume(void)
+{
+ u32 val;
+
+ val = readl(cgu->base + CGU_REG_LCR);
+ writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR);
+}
+
+static struct syscore_ops jz4770_cgu_pm_ops = {
+ .suspend = jz4770_cgu_pm_suspend,
+ .resume = jz4770_cgu_pm_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static void __init jz4770_cgu_init(struct device_node *np)
+{
+ int retval;
+
+ cgu = ingenic_cgu_new(jz4770_cgu_clocks,
+ ARRAY_SIZE(jz4770_cgu_clocks), np);
+ if (!cgu)
+ pr_err("%s: failed to initialise CGU\n", __func__);
+
+ retval = ingenic_cgu_register_clocks(cgu);
+ if (retval)
+ pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+ register_syscore_ops(&jz4770_cgu_pm_ops);
+#endif
+}
+
+/* We only probe via devicetree, no need for a platform driver */
+CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
--
2.11.0

2018-01-02 15:11:17

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 08/15] MIPS: ingenic: Use common cmdline handling code

From: Paul Burton <[email protected]>

jz4740_init_cmdline appends all arguments from argv (in fw_arg1) to
arcs_cmdline, up to argc (in fw_arg0). The common code in
fw_init_cmdline will do the exact same thing when run on a system where
fw_arg0 isn't a pointer to kseg0 (it'll also set _fw_envp but we don't
use it). Remove the custom implementation & use the generic code.

Signed-off-by: Paul Burton <[email protected]>
---
arch/mips/jz4740/prom.c | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)

v2: No change
v3: No change
v4: No change
v5: No change

diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index 47e857194ce6..a62dd8e6ecf9 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -20,33 +20,13 @@
#include <linux/serial_reg.h>

#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
#include <asm/mach-jz4740/base.h>

-static __init void jz4740_init_cmdline(int argc, char *argv[])
-{
- unsigned int count = COMMAND_LINE_SIZE - 1;
- int i;
- char *dst = &(arcs_cmdline[0]);
- char *src;
-
- for (i = 1; i < argc && count; ++i) {
- src = argv[i];
- while (*src && count) {
- *dst++ = *src++;
- --count;
- }
- *dst++ = ' ';
- }
- if (i > 1)
- --dst;
-
- *dst = 0;
-}
-
void __init prom_init(void)
{
- jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
mips_machtype = MACH_INGENIC_JZ4740;
+ fw_init_cmdline();
}

void __init prom_free_prom_memory(void)
--
2.11.0

2018-01-02 15:12:31

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 05/15] dt-bindings: clock: Add jz4770-cgu.h header

This will be used from the devicetree bindings to specify the clocks
that should be obtained from the jz4770-cgu driver.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
include/dt-bindings/clock/jz4770-cgu.h | 58 ++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 include/dt-bindings/clock/jz4770-cgu.h

v3: New patch in this series
v4: No change
v5: Use SPDX license identifier

diff --git a/include/dt-bindings/clock/jz4770-cgu.h b/include/dt-bindings/clock/jz4770-cgu.h
new file mode 100644
index 000000000000..d68a7695a1f8
--- /dev/null
+++ b/include/dt-bindings/clock/jz4770-cgu.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides clock numbers for the ingenic,jz4770-cgu DT binding.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+
+#define JZ4770_CLK_EXT 0
+#define JZ4770_CLK_OSC32K 1
+#define JZ4770_CLK_PLL0 2
+#define JZ4770_CLK_PLL1 3
+#define JZ4770_CLK_CCLK 4
+#define JZ4770_CLK_H0CLK 5
+#define JZ4770_CLK_H1CLK 6
+#define JZ4770_CLK_H2CLK 7
+#define JZ4770_CLK_C1CLK 8
+#define JZ4770_CLK_PCLK 9
+#define JZ4770_CLK_MMC0_MUX 10
+#define JZ4770_CLK_MMC0 11
+#define JZ4770_CLK_MMC1_MUX 12
+#define JZ4770_CLK_MMC1 13
+#define JZ4770_CLK_MMC2_MUX 14
+#define JZ4770_CLK_MMC2 15
+#define JZ4770_CLK_CIM 16
+#define JZ4770_CLK_UHC 17
+#define JZ4770_CLK_GPU 18
+#define JZ4770_CLK_BCH 19
+#define JZ4770_CLK_LPCLK_MUX 20
+#define JZ4770_CLK_GPS 21
+#define JZ4770_CLK_SSI_MUX 22
+#define JZ4770_CLK_PCM_MUX 23
+#define JZ4770_CLK_I2S 24
+#define JZ4770_CLK_OTG 25
+#define JZ4770_CLK_SSI0 26
+#define JZ4770_CLK_SSI1 27
+#define JZ4770_CLK_SSI2 28
+#define JZ4770_CLK_PCM0 29
+#define JZ4770_CLK_PCM1 30
+#define JZ4770_CLK_DMA 31
+#define JZ4770_CLK_I2C0 32
+#define JZ4770_CLK_I2C1 33
+#define JZ4770_CLK_I2C2 34
+#define JZ4770_CLK_UART0 35
+#define JZ4770_CLK_UART1 36
+#define JZ4770_CLK_UART2 37
+#define JZ4770_CLK_UART3 38
+#define JZ4770_CLK_IPU 39
+#define JZ4770_CLK_ADC 40
+#define JZ4770_CLK_AIC 41
+#define JZ4770_CLK_AUX 42
+#define JZ4770_CLK_VPU 43
+#define JZ4770_CLK_UHC_PHY 44
+#define JZ4770_CLK_OTG_PHY 45
+#define JZ4770_CLK_EXT512 46
+#define JZ4770_CLK_RTC 47
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4770_CGU_H__ */
--
2.11.0

2018-01-02 15:12:50

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 03/15] clk: ingenic: support PLLs with no bypass bit

The second PLL of the JZ4770 does not have a bypass bit.
This commit makes it possible to support it with the current common CGU
code.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 3 ++-
drivers/clk/ingenic/cgu.h | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)

v2: No change
v3: No change
v4: No change
v5: No change

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index a2e73a6d60fd..381c4a17a1fc 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -100,7 +100,8 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0);
- bypass = !!(ctl & BIT(pll_info->bypass_bit));
+ bypass = !pll_info->no_bypass_bit &&
+ !!(ctl & BIT(pll_info->bypass_bit));
enable = !!(ctl & BIT(pll_info->enable_bit));

if (bypass)
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index f1527cf75b3f..9da34910bd80 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -48,6 +48,7 @@
* @bypass_bit: the index of the bypass bit in the PLL control register
* @enable_bit: the index of the enable bit in the PLL control register
* @stable_bit: the index of the stable bit in the PLL control register
+ * @no_bypass_bit: if set, the PLL has no bypass functionality
*/
struct ingenic_cgu_pll_info {
unsigned reg;
@@ -58,6 +59,7 @@ struct ingenic_cgu_pll_info {
u8 bypass_bit;
u8 enable_bit;
u8 stable_bit;
+ bool no_bypass_bit;
};

/**
--
2.11.0

2018-01-02 15:13:11

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v5 02/15] clk: ingenic: Fix recalc_rate for clocks with fixed divider

Previously, the clocks with a fixed divider would report their rate
as being the same as the one of their parent, independently of the
divider in use. This commit fixes this behaviour.

This went unnoticed as neither the jz4740 nor the jz4780 CGU code
have clocks with fixed dividers yet.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 2 ++
1 file changed, 2 insertions(+)

v2: No changes
v3: No changes
v4: No changes
v5: No changes

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index ab393637f7b0..a2e73a6d60fd 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -328,6 +328,8 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
div *= clk_info->div.div;

rate /= div;
+ } else if (clk_info->type & CGU_CLK_FIXDIV) {
+ rate /= clk_info->fixdiv.div;
}

return rate;
--
2.11.0

Subject: Re: [PATCH v5 08/15] MIPS: ingenic: Use common cmdline handling code

Hi Paul,

On 2 January 2018 at 20:38, Paul Cercueil <[email protected]> wrote:
> From: Paul Burton <[email protected]>
>
> jz4740_init_cmdline appends all arguments from argv (in fw_arg1) to
> arcs_cmdline, up to argc (in fw_arg0). The common code in
> fw_init_cmdline will do the exact same thing when run on a system where
> fw_arg0 isn't a pointer to kseg0 (it'll also set _fw_envp but we don't
> use it). Remove the custom implementation & use the generic code.
>
> Signed-off-by: Paul Burton <[email protected]>
> ---
> arch/mips/jz4740/prom.c | 24 ++----------------------
> 1 file changed, 2 insertions(+), 22 deletions(-)
>
> v2: No change
> v3: No change
> v4: No change
> v5: No change
>
> diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
> index 47e857194ce6..a62dd8e6ecf9 100644
> --- a/arch/mips/jz4740/prom.c
> +++ b/arch/mips/jz4740/prom.c
> @@ -20,33 +20,13 @@
> #include <linux/serial_reg.h>
>
> #include <asm/bootinfo.h>
> +#include <asm/fw/fw.h>
> #include <asm/mach-jz4740/base.h>
>
> -static __init void jz4740_init_cmdline(int argc, char *argv[])
> -{
> - unsigned int count = COMMAND_LINE_SIZE - 1;
> - int i;
> - char *dst = &(arcs_cmdline[0]);
> - char *src;
> -
> - for (i = 1; i < argc && count; ++i) {
> - src = argv[i];
> - while (*src && count) {
> - *dst++ = *src++;
> - --count;
> - }
> - *dst++ = ' ';
> - }
> - if (i > 1)
> - --dst;
> -
> - *dst = 0;
> -}
> -
> void __init prom_init(void)
> {
> - jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
> mips_machtype = MACH_INGENIC_JZ4740;
> + fw_init_cmdline();
> }
>
> void __init prom_free_prom_memory(void)
> --
> 2.11.0
>
>

Looks good to me.
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>

Subject: Re: [PATCH v5 09/15] MIPS: platform: add machtype IDs for more Ingenic SoCs

On 2 January 2018 at 20:38, Paul Cercueil <[email protected]> wrote:
> Add a machtype ID for the JZ4780 SoC, which was missing, and one for the
> newly supported JZ4770 SoC.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> ---
> arch/mips/include/asm/bootinfo.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> v2: No change
> v3: No change
> v5: No change
>
> diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
> index e26a093bb17a..a301a8f4bc66 100644
> --- a/arch/mips/include/asm/bootinfo.h
> +++ b/arch/mips/include/asm/bootinfo.h
> @@ -79,6 +79,8 @@ enum loongson_machine_type {
> */
> #define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */
> #define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */
> +#define MACH_INGENIC_JZ4770 2 /* JZ4770 SOC */
> +#define MACH_INGENIC_JZ4780 3 /* JZ4780 SOC */
>
> extern char *system_type;
> const char *get_system_type(void);
> --
> 2.11.0
>
>

Reviewed-by: PrasannaKumar Muralidharan <[email protected]>

Subject: Re: [PATCH v5 10/15] MIPS: ingenic: Add machine info for supported boards

Hi Paul,

On 2 January 2018 at 20:38, Paul Cercueil <[email protected]> wrote:
> This makes sure that 'mips_machtype' will be initialized to the SoC
> version used on the board.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> ---
> arch/mips/Kconfig | 1 +
> arch/mips/jz4740/Makefile | 2 +-
> arch/mips/jz4740/boards.c | 12 ++++++++++++
> arch/mips/jz4740/setup.c | 34 +++++++++++++++++++++++++++++-----
> 4 files changed, 43 insertions(+), 6 deletions(-)
> create mode 100644 arch/mips/jz4740/boards.c
>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 350a990fc719..83243e427e36 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -376,6 +376,7 @@ config MACH_INGENIC
> select BUILTIN_DTB
> select USE_OF
> select LIBFDT
> + select MIPS_MACHINE
>
> config LANTIQ
> bool "Lantiq based platforms"
> diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
> index 88d6aa7d000b..fc2d3b3c4a80 100644
> --- a/arch/mips/jz4740/Makefile
> +++ b/arch/mips/jz4740/Makefile
> @@ -6,7 +6,7 @@
> # Object file lists.
>
> obj-y += prom.o time.o reset.o setup.o \
> - platform.o timer.o
> + platform.o timer.o boards.o
>
> CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
>
> diff --git a/arch/mips/jz4740/boards.c b/arch/mips/jz4740/boards.c
> new file mode 100644
> index 000000000000..13b0bddd8cb7
> --- /dev/null
> +++ b/arch/mips/jz4740/boards.c
> @@ -0,0 +1,12 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Ingenic boards support
> + * Copyright 2017, Paul Cercueil <[email protected]>
> + */
> +
> +#include <asm/bootinfo.h>
> +#include <asm/mips_machine.h>
> +
> +MIPS_MACHINE(MACH_INGENIC_JZ4740, "qi,lb60", "Qi Hardware Ben Nanonote", NULL);
> +MIPS_MACHINE(MACH_INGENIC_JZ4780, "img,ci20",
> + "Imagination Technologies CI20", NULL);
> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
> index 6d0152321819..afd84ee966e8 100644
> --- a/arch/mips/jz4740/setup.c
> +++ b/arch/mips/jz4740/setup.c
> @@ -22,6 +22,7 @@
> #include <linux/of_fdt.h>
>
> #include <asm/bootinfo.h>
> +#include <asm/mips_machine.h>
> #include <asm/prom.h>
>
> #include <asm/mach-jz4740/base.h>
> @@ -53,16 +54,34 @@ static void __init jz4740_detect_mem(void)
> add_memory_region(0, size, BOOT_MEM_RAM);
> }
>
> +static unsigned long __init get_board_mach_type(const void *fdt)
> +{
> + const struct mips_machine *mach;
> +
> + for (mach = (struct mips_machine *)&__mips_machines_start;
> + mach < (struct mips_machine *)&__mips_machines_end;
> + mach++) {
> + if (!fdt_node_check_compatible(fdt, 0, mach->mach_id))
> + return mach->mach_type;
> + }
> +
> + return MACH_INGENIC_JZ4740;
> +}
> +
> void __init plat_mem_setup(void)
> {
> int offset;
>
> + if (!early_init_dt_scan(__dtb_start))
> + return;
> +
> jz4740_reset_init();
> - __dt_setup_arch(__dtb_start);
>
> offset = fdt_path_offset(__dtb_start, "/memory");
> if (offset < 0)
> jz4740_detect_mem();
> +
> + mips_machtype = get_board_mach_type(__dtb_start);
> }
>
> void __init device_tree_init(void)
> @@ -75,13 +94,18 @@ void __init device_tree_init(void)
>
> const char *get_system_type(void)
> {
> - if (IS_ENABLED(CONFIG_MACH_JZ4780))
> - return "JZ4780";
> -
> - return "JZ4740";
> + return mips_get_machine_name();
> }
>
> void __init arch_init_irq(void)
> {
> irqchip_init();
> }
> +
> +static int __init jz4740_machine_setup(void)
> +{
> + mips_machine_setup();
> +
> + return 0;
> +}
> +arch_initcall(jz4740_machine_setup);
> --
> 2.11.0
>
>

Why add another file in arch/mips/jz4740/? I think declaring a machine
and compatible string in dts would suffice. Please feel free to
correct me if I am wrong.

Regards,
PrasannaKumar

Subject: Re: [PATCH v5 11/15] MIPS: ingenic: Initial JZ4770 support

Hi Paul,

On 2 January 2018 at 20:38, Paul Cercueil <[email protected]> wrote:
> Provide just enough bits (clocks, clocksource, uart) to allow a kernel
> to boot on the JZ4770 SoC to a initramfs userspace.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> ---
> arch/mips/boot/dts/ingenic/jz4770.dtsi | 212 +++++++++++++++++++++++++++++++++
> arch/mips/jz4740/Kconfig | 6 +
> arch/mips/jz4740/time.c | 2 +-
> 3 files changed, 219 insertions(+), 1 deletion(-)
> create mode 100644 arch/mips/boot/dts/ingenic/jz4770.dtsi
>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
>
> diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
> new file mode 100644
> index 000000000000..7c2804f3f5f1
> --- /dev/null
> +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
> @@ -0,0 +1,212 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <dt-bindings/clock/jz4770-cgu.h>
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "ingenic,jz4770";
> +
> + cpuintc: interrupt-controller {
> + #address-cells = <0>;
> + #interrupt-cells = <1>;
> + interrupt-controller;
> + compatible = "mti,cpu-interrupt-controller";
> + };
> +
> + intc: interrupt-controller@10001000 {
> + compatible = "ingenic,jz4770-intc";
> + reg = <0x10001000 0x40>;
> +
> + interrupt-controller;
> + #interrupt-cells = <1>;
> +
> + interrupt-parent = <&cpuintc>;
> + interrupts = <2>;
> + };
> +
> + ext: ext {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + };
> +
> + osc32k: osc32k {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <32768>;
> + };
> +
> + cgu: jz4770-cgu@10000000 {
> + compatible = "ingenic,jz4770-cgu";
> + reg = <0x10000000 0x100>;
> +
> + clocks = <&ext>, <&osc32k>;
> + clock-names = "ext", "osc32k";
> +
> + #clock-cells = <1>;
> + };
> +
> + pinctrl: pin-controller@10010000 {
> + compatible = "ingenic,jz4770-pinctrl";
> + reg = <0x10010000 0x600>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + gpa: gpio@0 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <0>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 0 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <17>;
> + };
> +
> + gpb: gpio@1 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <1>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 32 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <16>;
> + };
> +
> + gpc: gpio@2 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <2>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 64 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <15>;
> + };
> +
> + gpd: gpio@3 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <3>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 96 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <14>;
> + };
> +
> + gpe: gpio@4 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <4>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 128 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <13>;
> + };
> +
> + gpf: gpio@5 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <5>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 160 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <12>;
> + };
> + };
> +
> + uart0: serial@10030000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10030000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART0>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <5>;
> +
> + status = "disabled";
> + };
> +
> + uart1: serial@10031000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10031000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART1>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <4>;
> +
> + status = "disabled";
> + };
> +
> + uart2: serial@10032000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10032000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART2>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <3>;
> +
> + status = "disabled";
> + };
> +
> + uart3: serial@10033000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10033000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART3>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <2>;
> +
> + status = "disabled";
> + };
> +
> + uhc: uhc@13430000 {
> + compatible = "generic-ohci";
> + reg = <0x13430000 0x1000>;
> +
> + clocks = <&cgu JZ4770_CLK_UHC>, <&cgu JZ4770_CLK_UHC_PHY>;
> + assigned-clocks = <&cgu JZ4770_CLK_UHC>;
> + assigned-clock-rates = <48000000>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <20>;
> +
> + status = "disabled";
> + };
> +};
> diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
> index 643af2012e14..29a9361a2b77 100644
> --- a/arch/mips/jz4740/Kconfig
> +++ b/arch/mips/jz4740/Kconfig
> @@ -18,6 +18,12 @@ config MACH_JZ4740
> bool
> select SYS_HAS_CPU_MIPS32_R1
>
> +config MACH_JZ4770
> + bool
> + select MIPS_CPU_SCACHE
> + select SYS_HAS_CPU_MIPS32_R2
> + select SYS_SUPPORTS_HIGHMEM
> +
> config MACH_JZ4780
> bool
> select MIPS_CPU_SCACHE
> diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
> index bb1ad5119da4..2ca9160f642a 100644
> --- a/arch/mips/jz4740/time.c
> +++ b/arch/mips/jz4740/time.c
> @@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
> #ifdef CONFIG_MACH_JZ4740
> .irq = JZ4740_IRQ_TCU0,
> #endif
> -#ifdef CONFIG_MACH_JZ4780
> +#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
> .irq = JZ4780_IRQ_TCU2,
> #endif
> };
> --
> 2.11.0
>
>

Looks good to me.
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>

2018-01-02 16:32:39

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v5 10/15] MIPS: ingenic: Add machine info for supported boards

Hi PrasannaKumar,

Le mar. 2 janv. 2018 ? 17:02, PrasannaKumar Muralidharan
<[email protected]> a ?crit :
> Hi Paul,
>
> On 2 January 2018 at 20:38, Paul Cercueil <[email protected]>
> wrote:
>> This makes sure that 'mips_machtype' will be initialized to the SoC
>> version used on the board.
>>
>> Signed-off-by: Paul Cercueil <[email protected]>
>> ---
>> arch/mips/Kconfig | 1 +
>> arch/mips/jz4740/Makefile | 2 +-
>> arch/mips/jz4740/boards.c | 12 ++++++++++++
>> arch/mips/jz4740/setup.c | 34 +++++++++++++++++++++++++++++-----
>> 4 files changed, 43 insertions(+), 6 deletions(-)
>> create mode 100644 arch/mips/jz4740/boards.c
>>
>> v2: No change
>> v3: No change
>> v4: No change
>> v5: Use SPDX license identifier
>>
>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> index 350a990fc719..83243e427e36 100644
>> --- a/arch/mips/Kconfig
>> +++ b/arch/mips/Kconfig
>> @@ -376,6 +376,7 @@ config MACH_INGENIC
>> select BUILTIN_DTB
>> select USE_OF
>> select LIBFDT
>> + select MIPS_MACHINE
>>
>> config LANTIQ
>> bool "Lantiq based platforms"
>> diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
>> index 88d6aa7d000b..fc2d3b3c4a80 100644
>> --- a/arch/mips/jz4740/Makefile
>> +++ b/arch/mips/jz4740/Makefile
>> @@ -6,7 +6,7 @@
>> # Object file lists.
>>
>> obj-y += prom.o time.o reset.o setup.o \
>> - platform.o timer.o
>> + platform.o timer.o boards.o
>>
>> CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
>>
>> diff --git a/arch/mips/jz4740/boards.c b/arch/mips/jz4740/boards.c
>> new file mode 100644
>> index 000000000000..13b0bddd8cb7
>> --- /dev/null
>> +++ b/arch/mips/jz4740/boards.c
>> @@ -0,0 +1,12 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Ingenic boards support
>> + * Copyright 2017, Paul Cercueil <[email protected]>
>> + */
>> +
>> +#include <asm/bootinfo.h>
>> +#include <asm/mips_machine.h>
>> +
>> +MIPS_MACHINE(MACH_INGENIC_JZ4740, "qi,lb60", "Qi Hardware Ben
>> Nanonote", NULL);
>> +MIPS_MACHINE(MACH_INGENIC_JZ4780, "img,ci20",
>> + "Imagination Technologies CI20", NULL);
>> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
>> index 6d0152321819..afd84ee966e8 100644
>> --- a/arch/mips/jz4740/setup.c
>> +++ b/arch/mips/jz4740/setup.c
>> @@ -22,6 +22,7 @@
>> #include <linux/of_fdt.h>
>>
>> #include <asm/bootinfo.h>
>> +#include <asm/mips_machine.h>
>> #include <asm/prom.h>
>>
>> #include <asm/mach-jz4740/base.h>
>> @@ -53,16 +54,34 @@ static void __init jz4740_detect_mem(void)
>> add_memory_region(0, size, BOOT_MEM_RAM);
>> }
>>
>> +static unsigned long __init get_board_mach_type(const void *fdt)
>> +{
>> + const struct mips_machine *mach;
>> +
>> + for (mach = (struct mips_machine *)&__mips_machines_start;
>> + mach < (struct mips_machine
>> *)&__mips_machines_end;
>> + mach++) {
>> + if (!fdt_node_check_compatible(fdt, 0,
>> mach->mach_id))
>> + return mach->mach_type;
>> + }
>> +
>> + return MACH_INGENIC_JZ4740;
>> +}
>> +
>> void __init plat_mem_setup(void)
>> {
>> int offset;
>>
>> + if (!early_init_dt_scan(__dtb_start))
>> + return;
>> +
>> jz4740_reset_init();
>> - __dt_setup_arch(__dtb_start);
>>
>> offset = fdt_path_offset(__dtb_start, "/memory");
>> if (offset < 0)
>> jz4740_detect_mem();
>> +
>> + mips_machtype = get_board_mach_type(__dtb_start);
>> }
>>
>> void __init device_tree_init(void)
>> @@ -75,13 +94,18 @@ void __init device_tree_init(void)
>>
>> const char *get_system_type(void)
>> {
>> - if (IS_ENABLED(CONFIG_MACH_JZ4780))
>> - return "JZ4780";
>> -
>> - return "JZ4740";
>> + return mips_get_machine_name();
>> }
>>
>> void __init arch_init_irq(void)
>> {
>> irqchip_init();
>> }
>> +
>> +static int __init jz4740_machine_setup(void)
>> +{
>> + mips_machine_setup();
>> +
>> + return 0;
>> +}
>> +arch_initcall(jz4740_machine_setup);
>> --
>> 2.11.0
>>
>>
>
> Why add another file in arch/mips/jz4740/? I think declaring a machine
> and compatible string in dts would suffice. Please feel free to
> correct me if I am wrong.
>
> Regards,
> PrasannaKumar

The point of this commit is, first, to have a textual description of
the board
that can then be retrieved in dmesg; then, to properly initialize the
mips_machtype early in the boot process. I think you are right and we
could
have both things just with "model" and "compatible" nodes in devicetree.

Regards,
-Paul

Subject: Re: [PATCH v5 13/15] MIPS: JZ4770: Workaround for corrupted DMA transfers

Hi Paul,

On 2 January 2018 at 20:38, Paul Cercueil <[email protected]> wrote:
> From: Maarten ter Huurne <[email protected]>
>
> We have seen MMC DMA transfers read corrupted data from SDRAM when
> a burst interval ends at physical address 0x10000000. To avoid this
> problem, we remove the final page of low memory from the memory map.
>
> Signed-off-by: Maarten ter Huurne <[email protected]>
> ---
> arch/mips/jz4740/setup.c | 24 ++++++++++++++++++++++++
> arch/mips/kernel/setup.c | 8 ++++++++
> 2 files changed, 32 insertions(+)
>
> v2: No change
> v3: No change
> v4: No change
> v5: No change
>
> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
> index afd84ee966e8..6948b133a15d 100644
> --- a/arch/mips/jz4740/setup.c
> +++ b/arch/mips/jz4740/setup.c
> @@ -23,6 +23,7 @@
>
> #include <asm/bootinfo.h>
> #include <asm/mips_machine.h>
> +#include <asm/page.h>
> #include <asm/prom.h>
>
> #include <asm/mach-jz4740/base.h>
> @@ -102,6 +103,29 @@ void __init arch_init_irq(void)
> irqchip_init();
> }
>
> +/*
> + * We have seen MMC DMA transfers read corrupted data from SDRAM when a burst
> + * interval ends at physical address 0x10000000. To avoid this problem, we
> + * remove the final page of low memory from the memory map.
> + */
> +void __init jz4770_reserve_unsafe_for_dma(void)
> +{
> + int i;
> +
> + for (i = 0; i < boot_mem_map.nr_map; i++) {
> + struct boot_mem_map_entry *entry = boot_mem_map.map + i;
> +
> + if (entry->type != BOOT_MEM_RAM)
> + continue;
> +
> + if (entry->addr + entry->size != 0x10000000)
> + continue;
> +
> + entry->size -= PAGE_SIZE;
> + break;
> + }
> +}
> +

Just a wild idea (probably bad too). Changing the memory node in the
device tree to skip this physical address would work I think. What is
your opinion about that?

> static int __init jz4740_machine_setup(void)
> {
> mips_machine_setup();
> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
> index 85bc601e9a0d..5a2c20145aee 100644
> --- a/arch/mips/kernel/setup.c
> +++ b/arch/mips/kernel/setup.c
> @@ -879,6 +879,14 @@ static void __init arch_mem_init(char **cmdline_p)
>
> parse_early_param();
>
> +#ifdef CONFIG_MACH_JZ4770
> + if (current_cpu_type() == CPU_JZRISC &&
> + mips_machtype == MACH_INGENIC_JZ4770) {
> + extern void __init jz4770_reserve_unsafe_for_dma(void);
> + jz4770_reserve_unsafe_for_dma();
> + }
> +#endif
> +
> if (usermem) {
> pr_info("User-defined physical RAM map:\n");
> print_memory_map();
> --
> 2.11.0
>
>

Thanks,
PrasannaKumar

2018-01-02 17:04:36

by Mathieu Malaterre

[permalink] [raw]
Subject: Re: [PATCH v5 15/15] MIPS: ingenic: Initial GCW Zero support

On Tue, Jan 2, 2018 at 4:08 PM, Paul Cercueil <[email protected]> wrote:
> The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
> handheld game console, successfully kickstarted in ~2012, running Linux.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> ---
> arch/mips/boot/dts/ingenic/Makefile | 1 +
> arch/mips/boot/dts/ingenic/gcw0.dts | 61 +++++++++++++++++++++++++++++++++++++
> arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
> arch/mips/jz4740/Kconfig | 4 +++
> arch/mips/jz4740/boards.c | 1 +
> 5 files changed, 94 insertions(+)
> create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
> create mode 100644 arch/mips/configs/gcw0_defconfig
>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
> Drop custom CROSS_COMPILE from defconfig

Thanks for removing CROSS_COMPILE.

Acked-by: Mathieu Malaterre <[email protected]>

2018-01-02 17:06:06

by Mathieu Malaterre

[permalink] [raw]
Subject: Re: [PATCH v5 07/15] MIPS: Setup boot_command_line before plat_mem_setup

On Tue, Jan 2, 2018 at 4:08 PM, Paul Cercueil <[email protected]> wrote:
> From: Paul Burton <[email protected]>
>
> Platforms using DT will typically call __dt_setup_arch from
> plat_mem_setup. This in turn calls early_init_dt_scan. When
> CONFIG_CMDLINE is set, this leads to its value being copied into
> boot_command_line by early_init_dt_scan_chosen. If this happens before
> the code setting up boot_command_line in arch_mem_init runs, that code
> will go on to append CONFIG_CMDLINE (via builtin_cmdline) to
> boot_command_line again, duplicating it. For some command line
> parameters (eg. earlycon) this can be a problem. Set up
> boot_command_line before early_init_dt_scan_chosen gets called such that
> it will not write CONFIG_CMDLINE in this scenario & the arguments aren't
> duplicated.
>
> Signed-off-by: Paul Burton <[email protected]>
> ---
> arch/mips/kernel/setup.c | 39 ++++++++++++++++++++-------------------
> 1 file changed, 20 insertions(+), 19 deletions(-)
>
> v2: New patch in this series
> v3: No change
> v4: No change
> v5: No change

I would have used @mips email. Anyway:

Acked-by: Mathieu Malaterre <[email protected]>

2018-01-05 16:34:04

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v5 05/15] dt-bindings: clock: Add jz4770-cgu.h header

On Tue, Jan 02, 2018 at 04:08:38PM +0100, Paul Cercueil wrote:
> This will be used from the devicetree bindings to specify the clocks
> that should be obtained from the jz4770-cgu driver.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> Acked-by: Stephen Boyd <[email protected]>
> ---
> include/dt-bindings/clock/jz4770-cgu.h | 58 ++++++++++++++++++++++++++++++++++
> 1 file changed, 58 insertions(+)
> create mode 100644 include/dt-bindings/clock/jz4770-cgu.h

Reviewed-by: Rob Herring <[email protected]>

2018-01-05 18:04:05

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v5 13/15] MIPS: JZ4770: Workaround for corrupted DMA transfers

Hi,
Hi,

>> [...]
>>
>> +/*
>> + * We have seen MMC DMA transfers read corrupted data from SDRAM
>> when a burst
>> + * interval ends at physical address 0x10000000. To avoid this
>> problem, we
>> + * remove the final page of low memory from the memory map.
>> + */
>> +void __init jz4770_reserve_unsafe_for_dma(void)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < boot_mem_map.nr_map; i++) {
>> + struct boot_mem_map_entry *entry = boot_mem_map.map
>> + i;
>> +
>> + if (entry->type != BOOT_MEM_RAM)
>> + continue;
>> +
>> + if (entry->addr + entry->size != 0x10000000)
>> + continue;
>> +
>> + entry->size -= PAGE_SIZE;
>> + break;
>> + }
>> +}
>> +
>
> Just a wild idea (probably bad too). Changing the memory node in the
> device tree to skip this physical address would work I think. What is
> your opinion about that?

I guess it would work as well, but I don't think this fix should be in
devicetree.

-Paul

2018-01-05 18:25:23

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 00/15] JZ4770 SoC support

Hi Ralf,

This is the V6 (and hopefully last) version of my JZ4770 patchset.

- In patches 07-08/15 I simply updated Paul Burton's email address
from @imgtec.com to @mips.com.
- Patch 10/15 changed, now I only init mips_machtype from devicetree
instead of using MIPS_MACHINE in platform code, as suggested by
Prasanna Kumar.
- Patch 15/15 has a minor addition, I added a "model" property in the
devicetree.

The rest (patches 01->06, 09, 11->14) are untouched.

Greetings,
Paul

2018-01-05 18:25:27

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 02/15] clk: ingenic: Fix recalc_rate for clocks with fixed divider

Previously, the clocks with a fixed divider would report their rate
as being the same as the one of their parent, independently of the
divider in use. This commit fixes this behaviour.

This went unnoticed as neither the jz4740 nor the jz4780 CGU code
have clocks with fixed dividers yet.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 2 ++
1 file changed, 2 insertions(+)

v2: No changes
v3: No changes
v4: No changes
v5: No changes
v6: No changes

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index ab393637f7b0..a2e73a6d60fd 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -328,6 +328,8 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
div *= clk_info->div.div;

rate /= div;
+ } else if (clk_info->type & CGU_CLK_FIXDIV) {
+ rate /= clk_info->fixdiv.div;
}

return rate;
--
2.11.0

2018-01-05 18:25:31

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 04/15] clk: ingenic: Add code to enable/disable PLLs

This commit permits the PLLs to be dynamically enabled and disabled when
their children clocks are enabled and disabled.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 89 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 74 insertions(+), 15 deletions(-)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 381c4a17a1fc..56a712c9075f 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -107,9 +107,6 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
if (bypass)
return parent_rate;

- if (!enable)
- return 0;
-
for (od = 0; od < pll_info->od_max; od++) {
if (pll_info->od_encoding[od] == od_enc)
break;
@@ -153,17 +150,25 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
return div_u64((u64)parent_rate * m, n * od);
}

-static long
-ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
- unsigned long *prate)
+static inline const struct ingenic_cgu_clk_info *to_clk_info(
+ struct ingenic_clk *ingenic_clk)
{
- struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;

clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);

+ return clk_info;
+}
+
+static long
+ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
+ unsigned long *prate)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+
return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
}

@@ -171,19 +176,14 @@ static int
ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long parent_rate)
{
- const unsigned timeout = 100;
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
- const struct ingenic_cgu_clk_info *clk_info;
- const struct ingenic_cgu_pll_info *pll_info;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long rate, flags;
- unsigned m, n, od, i;
+ unsigned int m, n, od;
u32 ctl;

- clk_info = &cgu->clock_info[ingenic_clk->idx];
- BUG_ON(clk_info->type != CGU_CLK_PLL);
- pll_info = &clk_info->pll;
-
rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
&m, &n, &od);
if (rate != req_rate)
@@ -202,6 +202,26 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;

+ writel(ctl, cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+
+ return 0;
+}
+
+static int ingenic_pll_enable(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ const unsigned int timeout = 100;
+ unsigned long flags;
+ unsigned int i;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+
ctl &= ~BIT(pll_info->bypass_bit);
ctl |= BIT(pll_info->enable_bit);

@@ -223,10 +243,48 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0;
}

+static void ingenic_pll_disable(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ unsigned long flags;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+
+ ctl &= ~BIT(pll_info->enable_bit);
+
+ writel(ctl, cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+}
+
+static int ingenic_pll_is_enabled(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ unsigned long flags;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+
+ return !!(ctl & BIT(pll_info->enable_bit));
+}
+
static const struct clk_ops ingenic_pll_ops = {
.recalc_rate = ingenic_pll_recalc_rate,
.round_rate = ingenic_pll_round_rate,
.set_rate = ingenic_pll_set_rate,
+
+ .enable = ingenic_pll_enable,
+ .disable = ingenic_pll_disable,
+ .is_enabled = ingenic_pll_is_enabled,
};

/*
@@ -601,6 +659,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
}
} else if (caps & CGU_CLK_PLL) {
clk_init.ops = &ingenic_pll_ops;
+ clk_init.flags |= CLK_SET_RATE_GATE;

caps &= ~CGU_CLK_PLL;

--
2.11.0

2018-01-05 18:25:34

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 09/15] MIPS: platform: add machtype IDs for more Ingenic SoCs

Add a machtype ID for the JZ4780 SoC, which was missing, and one for the
newly supported JZ4770 SoC.

Signed-off-by: Paul Cercueil <[email protected]>
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
---
arch/mips/include/asm/bootinfo.h | 2 ++
1 file changed, 2 insertions(+)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change

diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index e26a093bb17a..a301a8f4bc66 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -79,6 +79,8 @@ enum loongson_machine_type {
*/
#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */
#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */
+#define MACH_INGENIC_JZ4770 2 /* JZ4770 SOC */
+#define MACH_INGENIC_JZ4780 3 /* JZ4780 SOC */

extern char *system_type;
const char *get_system_type(void);
--
2.11.0

2018-01-05 18:25:37

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 13/15] MIPS: JZ4770: Workaround for corrupted DMA transfers

From: Maarten ter Huurne <[email protected]>

We have seen MMC DMA transfers read corrupted data from SDRAM when
a burst interval ends at physical address 0x10000000. To avoid this
problem, we remove the final page of low memory from the memory map.

Signed-off-by: Maarten ter Huurne <[email protected]>
---
arch/mips/jz4740/setup.c | 24 ++++++++++++++++++++++++
arch/mips/kernel/setup.c | 8 ++++++++
2 files changed, 32 insertions(+)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change

diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index cd89536fbba1..18c57c4bf47e 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -22,6 +22,7 @@
#include <linux/of_fdt.h>

#include <asm/bootinfo.h>
+#include <asm/page.h>
#include <asm/prom.h>

#include <asm/mach-jz4740/base.h>
@@ -103,3 +104,26 @@ void __init arch_init_irq(void)
{
irqchip_init();
}
+
+/*
+ * We have seen MMC DMA transfers read corrupted data from SDRAM when a burst
+ * interval ends at physical address 0x10000000. To avoid this problem, we
+ * remove the final page of low memory from the memory map.
+ */
+void __init jz4770_reserve_unsafe_for_dma(void)
+{
+ int i;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+
+ if (entry->type != BOOT_MEM_RAM)
+ continue;
+
+ if (entry->addr + entry->size != 0x10000000)
+ continue;
+
+ entry->size -= PAGE_SIZE;
+ break;
+ }
+}
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 85bc601e9a0d..5a2c20145aee 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -879,6 +879,14 @@ static void __init arch_mem_init(char **cmdline_p)

parse_early_param();

+#ifdef CONFIG_MACH_JZ4770
+ if (current_cpu_type() == CPU_JZRISC &&
+ mips_machtype == MACH_INGENIC_JZ4770) {
+ extern void __init jz4770_reserve_unsafe_for_dma(void);
+ jz4770_reserve_unsafe_for_dma();
+ }
+#endif
+
if (usermem) {
pr_info("User-defined physical RAM map:\n");
print_memory_map();
--
2.11.0

2018-01-05 18:25:40

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 11/15] MIPS: ingenic: Initial JZ4770 support

Provide just enough bits (clocks, clocksource, uart) to allow a kernel
to boot on the JZ4770 SoC to a initramfs userspace.

Signed-off-by: Paul Cercueil <[email protected]>
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
---
arch/mips/boot/dts/ingenic/jz4770.dtsi | 212 +++++++++++++++++++++++++++++++++
arch/mips/jz4740/Kconfig | 6 +
arch/mips/jz4740/time.c | 2 +-
3 files changed, 219 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/boot/dts/ingenic/jz4770.dtsi

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
v6: No change

diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
new file mode 100644
index 000000000000..7c2804f3f5f1
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/clock/jz4770-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4770";
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-controller@10001000 {
+ compatible = "ingenic,jz4770-intc";
+ reg = <0x10001000 0x40>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ osc32k: osc32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4770-cgu@10000000 {
+ compatible = "ingenic,jz4770-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&osc32k>;
+ clock-names = "ext", "osc32k";
+
+ #clock-cells = <1>;
+ };
+
+ pinctrl: pin-controller@10010000 {
+ compatible = "ingenic,jz4770-pinctrl";
+ reg = <0x10010000 0x600>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpa: gpio@0 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <0>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 0 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <17>;
+ };
+
+ gpb: gpio@1 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <1>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 32 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ };
+
+ gpc: gpio@2 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <2>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 64 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <15>;
+ };
+
+ gpd: gpio@3 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <3>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 96 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <14>;
+ };
+
+ gpe: gpio@4 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <4>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 128 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <13>;
+ };
+
+ gpf: gpio@5 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <5>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 160 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <12>;
+ };
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10030000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART0>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <5>;
+
+ status = "disabled";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10031000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART1>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <4>;
+
+ status = "disabled";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10032000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART2>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <3>;
+
+ status = "disabled";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10033000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART3>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <2>;
+
+ status = "disabled";
+ };
+
+ uhc: uhc@13430000 {
+ compatible = "generic-ohci";
+ reg = <0x13430000 0x1000>;
+
+ clocks = <&cgu JZ4770_CLK_UHC>, <&cgu JZ4770_CLK_UHC_PHY>;
+ assigned-clocks = <&cgu JZ4770_CLK_UHC>;
+ assigned-clock-rates = <48000000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <20>;
+
+ status = "disabled";
+ };
+};
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 643af2012e14..29a9361a2b77 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -18,6 +18,12 @@ config MACH_JZ4740
bool
select SYS_HAS_CPU_MIPS32_R1

+config MACH_JZ4770
+ bool
+ select MIPS_CPU_SCACHE
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_HIGHMEM
+
config MACH_JZ4780
bool
select MIPS_CPU_SCACHE
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index bb1ad5119da4..2ca9160f642a 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
#ifdef CONFIG_MACH_JZ4740
.irq = JZ4740_IRQ_TCU0,
#endif
-#ifdef CONFIG_MACH_JZ4780
+#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
.irq = JZ4780_IRQ_TCU2,
#endif
};
--
2.11.0

2018-01-05 18:25:41

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 15/15] MIPS: ingenic: Initial GCW Zero support

The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
handheld game console, successfully kickstarted in ~2012, running Linux.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Mathieu Malaterre <[email protected]>
---
arch/mips/boot/dts/ingenic/Makefile | 1 +
arch/mips/boot/dts/ingenic/gcw0.dts | 62 +++++++++++++++++++++++++++++++++++++
arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
arch/mips/jz4740/Kconfig | 4 +++
4 files changed, 94 insertions(+)
create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
create mode 100644 arch/mips/configs/gcw0_defconfig

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
Drop custom CROSS_COMPILE from defconfig
v6: Add "model" property in devicetree

diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
index 6a31759839b4..5b1361a89e02 100644
--- a/arch/mips/boot/dts/ingenic/Makefile
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb
+dtb-$(CONFIG_JZ4770_GCW0) += gcw0.dtb
dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb

obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts b/arch/mips/boot/dts/ingenic/gcw0.dts
new file mode 100644
index 000000000000..5cd76ac9cfba
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/gcw0.dts
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "jz4770.dtsi"
+
+/ {
+ compatible = "gcw,zero", "ingenic,jz4770";
+ model = "GCW Zero";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial2:57600n8";
+ };
+
+ board {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <>;
+
+ otg_phy: otg-phy {
+ compatible = "usb-nop-xceiv";
+ clocks = <&cgu JZ4770_CLK_OTG_PHY>;
+ clock-names = "main_clk";
+ };
+ };
+};
+
+&ext {
+ clock-frequency = <12000000>;
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&cgu {
+ /* Put high-speed peripherals under PLL1, such that we can change the
+ * PLL0 frequency on demand without having to suspend peripherals.
+ * We use a rate of 432 MHz, which is the least common multiple of
+ * 27 MHz (required by TV encoder) and 48 MHz (required by USB host).
+ */
+ assigned-clocks =
+ <&cgu JZ4770_CLK_PLL1>,
+ <&cgu JZ4770_CLK_UHC>;
+ assigned-clock-parents =
+ <0>,
+ <&cgu JZ4770_CLK_PLL1>;
+ assigned-clock-rates =
+ <432000000>;
+};
+
+&uhc {
+ /* The WiFi module is connected to the UHC. */
+ status = "okay";
+};
diff --git a/arch/mips/configs/gcw0_defconfig b/arch/mips/configs/gcw0_defconfig
new file mode 100644
index 000000000000..99ac1fa3b35f
--- /dev/null
+++ b/arch/mips/configs/gcw0_defconfig
@@ -0,0 +1,27 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4770_GCW0=y
+CONFIG_HIGHMEM=y
+# CONFIG_BOUNCE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_SECCOMP is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EMBEDDED=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_TMPFS=y
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 29a9361a2b77..4dd0c446ecec 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -8,6 +8,10 @@ config JZ4740_QI_LB60
bool "Qi Hardware Ben NanoNote"
select MACH_JZ4740

+config JZ4770_GCW0
+ bool "Game Consoles Worldwide GCW Zero"
+ select MACH_JZ4770
+
config JZ4780_CI20
bool "MIPS Creator CI20"
select MACH_JZ4780
--
2.11.0

2018-01-05 18:26:10

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 14/15] devicetree/bindings: Add GCW vendor prefix

Game Consoles Worldwide, mostly known under the acronym GCW, is the
creator of the GCW Zero open-source video game system.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)

v2: It's 'Game Consoles Worldwide', not 'Games Consoles Worldwide'
v3: No change
v4: No change
v5: No change
v6: No change

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0994bdd82cd3..f40f4da39937 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -123,6 +123,7 @@ focaltech FocalTech Systems Co.,Ltd
friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
fsl Freescale Semiconductor
fujitsu Fujitsu Ltd.
+gcw Game Consoles Worldwide
ge General Electric Company
geekbuying GeekBuying
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
--
2.11.0

2018-01-05 18:26:27

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 12/15] MIPS: JZ4770: Work around config2 misreporting associativity

From: Maarten ter Huurne <[email protected]>

According to config2, the associativity would be 5-ways, but the
documentation states 4-ways, which also matches the documented
L2 cache size of 256 kB.

Signed-off-by: Maarten ter Huurne <[email protected]>
---
arch/mips/mm/sc-mips.c | 9 +++++++++
1 file changed, 9 insertions(+)

v2: No change
v3: No change
v4: Rebased on top of Linux 4.15-rc5
v5: No change
v6: No change

diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 548acb7f8557..394673991bab 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -16,6 +16,7 @@
#include <asm/mmu_context.h>
#include <asm/r4kcache.h>
#include <asm/mips-cps.h>
+#include <asm/bootinfo.h>

/*
* MIPS32/MIPS64 L2 cache handling
@@ -220,6 +221,14 @@ static inline int __init mips_sc_probe(void)
else
return 0;

+ /*
+ * According to config2 it would be 5-ways, but that is contradicted
+ * by all documentation.
+ */
+ if (current_cpu_type() == CPU_JZRISC &&
+ mips_machtype == MACH_INGENIC_JZ4770)
+ c->scache.ways = 4;
+
c->scache.waysize = c->scache.sets * c->scache.linesz;
c->scache.waybit = __ffs(c->scache.waysize);

--
2.11.0

2018-01-05 18:25:33

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 10/15] MIPS: ingenic: Detect machtype from SoC compatible string

Previously, the mips_machtype variable was always initialized
to MACH_INGENIC_JZ4740 even if running on different SoCs.

Signed-off-by: Paul Cercueil <[email protected]>
---
arch/mips/jz4740/prom.c | 1 -
arch/mips/jz4740/setup.c | 26 ++++++++++++++++++++++----
2 files changed, 22 insertions(+), 5 deletions(-)

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
v6: Init mips_machtype from DT compatible string instead of using
MIPS_MACHINE

diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index a62dd8e6ecf9..eb9f2f97bedb 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -25,7 +25,6 @@

void __init prom_init(void)
{
- mips_machtype = MACH_INGENIC_JZ4740;
fw_init_cmdline();
}

diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 6d0152321819..cd89536fbba1 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -53,16 +53,30 @@ static void __init jz4740_detect_mem(void)
add_memory_region(0, size, BOOT_MEM_RAM);
}

+static unsigned long __init get_board_mach_type(const void *fdt)
+{
+ if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4780"))
+ return MACH_INGENIC_JZ4780;
+ if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4770"))
+ return MACH_INGENIC_JZ4770;
+
+ return MACH_INGENIC_JZ4740;
+}
+
void __init plat_mem_setup(void)
{
int offset;

+ if (!early_init_dt_scan(__dtb_start))
+ return;
+
jz4740_reset_init();
- __dt_setup_arch(__dtb_start);

offset = fdt_path_offset(__dtb_start, "/memory");
if (offset < 0)
jz4740_detect_mem();
+
+ mips_machtype = get_board_mach_type(__dtb_start);
}

void __init device_tree_init(void)
@@ -75,10 +89,14 @@ void __init device_tree_init(void)

const char *get_system_type(void)
{
- if (IS_ENABLED(CONFIG_MACH_JZ4780))
+ switch (mips_machtype) {
+ case MACH_INGENIC_JZ4780:
return "JZ4780";
-
- return "JZ4740";
+ case MACH_INGENIC_JZ4770:
+ return "JZ4770";
+ default:
+ return "JZ4740";
+ }
}

void __init arch_init_irq(void)
--
2.11.0

2018-01-05 18:27:02

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 08/15] MIPS: ingenic: Use common cmdline handling code

From: Paul Burton <[email protected]>

jz4740_init_cmdline appends all arguments from argv (in fw_arg1) to
arcs_cmdline, up to argc (in fw_arg0). The common code in
fw_init_cmdline will do the exact same thing when run on a system where
fw_arg0 isn't a pointer to kseg0 (it'll also set _fw_envp but we don't
use it). Remove the custom implementation & use the generic code.

Signed-off-by: Paul Burton <[email protected]>
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
---
arch/mips/jz4740/prom.c | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)

v2: No change
v3: No change
v4: No change
v5: No change
v6: Update Paul Burton's email address

diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index 47e857194ce6..a62dd8e6ecf9 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -20,33 +20,13 @@
#include <linux/serial_reg.h>

#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
#include <asm/mach-jz4740/base.h>

-static __init void jz4740_init_cmdline(int argc, char *argv[])
-{
- unsigned int count = COMMAND_LINE_SIZE - 1;
- int i;
- char *dst = &(arcs_cmdline[0]);
- char *src;
-
- for (i = 1; i < argc && count; ++i) {
- src = argv[i];
- while (*src && count) {
- *dst++ = *src++;
- --count;
- }
- *dst++ = ' ';
- }
- if (i > 1)
- --dst;
-
- *dst = 0;
-}
-
void __init prom_init(void)
{
- jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
mips_machtype = MACH_INGENIC_JZ4740;
+ fw_init_cmdline();
}

void __init prom_free_prom_memory(void)
--
2.11.0

2018-01-05 18:25:30

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 05/15] dt-bindings: clock: Add jz4770-cgu.h header

This will be used from the devicetree bindings to specify the clocks
that should be obtained from the jz4770-cgu driver.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
include/dt-bindings/clock/jz4770-cgu.h | 58 ++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 include/dt-bindings/clock/jz4770-cgu.h

v3: New patch in this series
v4: No change
v5: Use SPDX license identifier
v6: No change

diff --git a/include/dt-bindings/clock/jz4770-cgu.h b/include/dt-bindings/clock/jz4770-cgu.h
new file mode 100644
index 000000000000..d68a7695a1f8
--- /dev/null
+++ b/include/dt-bindings/clock/jz4770-cgu.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides clock numbers for the ingenic,jz4770-cgu DT binding.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+
+#define JZ4770_CLK_EXT 0
+#define JZ4770_CLK_OSC32K 1
+#define JZ4770_CLK_PLL0 2
+#define JZ4770_CLK_PLL1 3
+#define JZ4770_CLK_CCLK 4
+#define JZ4770_CLK_H0CLK 5
+#define JZ4770_CLK_H1CLK 6
+#define JZ4770_CLK_H2CLK 7
+#define JZ4770_CLK_C1CLK 8
+#define JZ4770_CLK_PCLK 9
+#define JZ4770_CLK_MMC0_MUX 10
+#define JZ4770_CLK_MMC0 11
+#define JZ4770_CLK_MMC1_MUX 12
+#define JZ4770_CLK_MMC1 13
+#define JZ4770_CLK_MMC2_MUX 14
+#define JZ4770_CLK_MMC2 15
+#define JZ4770_CLK_CIM 16
+#define JZ4770_CLK_UHC 17
+#define JZ4770_CLK_GPU 18
+#define JZ4770_CLK_BCH 19
+#define JZ4770_CLK_LPCLK_MUX 20
+#define JZ4770_CLK_GPS 21
+#define JZ4770_CLK_SSI_MUX 22
+#define JZ4770_CLK_PCM_MUX 23
+#define JZ4770_CLK_I2S 24
+#define JZ4770_CLK_OTG 25
+#define JZ4770_CLK_SSI0 26
+#define JZ4770_CLK_SSI1 27
+#define JZ4770_CLK_SSI2 28
+#define JZ4770_CLK_PCM0 29
+#define JZ4770_CLK_PCM1 30
+#define JZ4770_CLK_DMA 31
+#define JZ4770_CLK_I2C0 32
+#define JZ4770_CLK_I2C1 33
+#define JZ4770_CLK_I2C2 34
+#define JZ4770_CLK_UART0 35
+#define JZ4770_CLK_UART1 36
+#define JZ4770_CLK_UART2 37
+#define JZ4770_CLK_UART3 38
+#define JZ4770_CLK_IPU 39
+#define JZ4770_CLK_ADC 40
+#define JZ4770_CLK_AIC 41
+#define JZ4770_CLK_AUX 42
+#define JZ4770_CLK_VPU 43
+#define JZ4770_CLK_UHC_PHY 44
+#define JZ4770_CLK_OTG_PHY 45
+#define JZ4770_CLK_EXT512 46
+#define JZ4770_CLK_RTC 47
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4770_CGU_H__ */
--
2.11.0

2018-01-05 18:27:38

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 07/15] MIPS: Setup boot_command_line before plat_mem_setup

From: Paul Burton <[email protected]>

Platforms using DT will typically call __dt_setup_arch from
plat_mem_setup. This in turn calls early_init_dt_scan. When
CONFIG_CMDLINE is set, this leads to its value being copied into
boot_command_line by early_init_dt_scan_chosen. If this happens before
the code setting up boot_command_line in arch_mem_init runs, that code
will go on to append CONFIG_CMDLINE (via builtin_cmdline) to
boot_command_line again, duplicating it. For some command line
parameters (eg. earlycon) this can be a problem. Set up
boot_command_line before early_init_dt_scan_chosen gets called such that
it will not write CONFIG_CMDLINE in this scenario & the arguments aren't
duplicated.

Signed-off-by: Paul Burton <[email protected]>
Acked-by: Mathieu Malaterre <[email protected]>
---
arch/mips/kernel/setup.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)

v2: New patch in this series
v3: No change
v4: No change
v5: No change
v6: Update Paul Burton's email address

diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 702c678de116..85bc601e9a0d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -826,25 +826,6 @@ static void __init arch_mem_init(char **cmdline_p)
struct memblock_region *reg;
extern void plat_mem_setup(void);

- /* call board setup routine */
- plat_mem_setup();
-
- /*
- * Make sure all kernel memory is in the maps. The "UP" and
- * "DOWN" are opposite for initdata since if it crosses over
- * into another memory section you don't want that to be
- * freed when the initdata is freed.
- */
- arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
- PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
- BOOT_MEM_RAM);
- arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
- PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
- BOOT_MEM_INIT_RAM);
-
- pr_info("Determined physical RAM map:\n");
- print_memory_map();
-
#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
@@ -872,6 +853,26 @@ static void __init arch_mem_init(char **cmdline_p)
}
#endif
#endif
+
+ /* call board setup routine */
+ plat_mem_setup();
+
+ /*
+ * Make sure all kernel memory is in the maps. The "UP" and
+ * "DOWN" are opposite for initdata since if it crosses over
+ * into another memory section you don't want that to be
+ * freed when the initdata is freed.
+ */
+ arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
+ PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+ arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
+ PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
+ BOOT_MEM_INIT_RAM);
+
+ pr_info("Determined physical RAM map:\n");
+ print_memory_map();
+
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);

*cmdline_p = command_line;
--
2.11.0

2018-01-05 18:27:40

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 06/15] clk: Add Ingenic jz4770 CGU driver

Add support for the clocks provided by the CGU in the Ingenic JZ4770
SoC.

Signed-off-by: Paul Cercueil <[email protected]>
Signed-off-by: Maarten ter Huurne <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/Makefile | 1 +
drivers/clk/ingenic/jz4770-cgu.c | 483 +++++++++++++++++++++++++++++++++++++++
2 files changed, 484 insertions(+)
create mode 100644 drivers/clk/ingenic/jz4770-cgu.c

v2: Make structures static const
v3: <dt-bindings/clock/jz4770-cgu.h> is now added in a separate patch
v4: No change
v5: Use SPDX license identifier
v6: No change

diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index cd47b0664c2b..1456e4cdb562 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,3 +1,4 @@
obj-y += cgu.o
obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
+obj-$(CONFIG_MACH_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o
diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c
new file mode 100644
index 000000000000..c78d369b9403
--- /dev/null
+++ b/drivers/clk/ingenic/jz4770-cgu.c
@@ -0,0 +1,483 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ4770 SoC CGU driver
+ * Copyright 2018, Paul Cercueil <[email protected]>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/jz4770-cgu.h>
+#include "cgu.h"
+
+/*
+ * CPM registers offset address definition
+ */
+#define CGU_REG_CPCCR 0x00
+#define CGU_REG_LCR 0x04
+#define CGU_REG_CPPCR0 0x10
+#define CGU_REG_CLKGR0 0x20
+#define CGU_REG_OPCR 0x24
+#define CGU_REG_CLKGR1 0x28
+#define CGU_REG_CPPCR1 0x30
+#define CGU_REG_USBPCR1 0x48
+#define CGU_REG_USBCDR 0x50
+#define CGU_REG_I2SCDR 0x60
+#define CGU_REG_LPCDR 0x64
+#define CGU_REG_MSC0CDR 0x68
+#define CGU_REG_UHCCDR 0x6c
+#define CGU_REG_SSICDR 0x74
+#define CGU_REG_CIMCDR 0x7c
+#define CGU_REG_GPSCDR 0x80
+#define CGU_REG_PCMCDR 0x84
+#define CGU_REG_GPUCDR 0x88
+#define CGU_REG_MSC1CDR 0xA4
+#define CGU_REG_MSC2CDR 0xA8
+#define CGU_REG_BCHCDR 0xAC
+
+/* bits within the LCR register */
+#define LCR_LPM BIT(0) /* Low Power Mode */
+
+/* bits within the OPCR register */
+#define OPCR_SPENDH BIT(5) /* UHC PHY suspend */
+#define OPCR_SPENDN BIT(7) /* OTG PHY suspend */
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_UHC_POWER BIT(5) /* UHC PHY power down */
+
+static struct ingenic_cgu *cgu;
+
+static int jz4770_uhc_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
+ writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
+ return 0;
+}
+
+static void jz4770_uhc_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
+ writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
+}
+
+static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ return !(readl(reg_opcr) & OPCR_SPENDH) &&
+ (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
+}
+
+static const struct clk_ops jz4770_uhc_phy_ops = {
+ .enable = jz4770_uhc_phy_enable,
+ .disable = jz4770_uhc_phy_disable,
+ .is_enabled = jz4770_uhc_phy_is_enabled,
+};
+
+static int jz4770_otg_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ writel(readl(reg_opcr) | OPCR_SPENDN, reg_opcr);
+
+ /* Wait for the clock to be stable */
+ udelay(50);
+ return 0;
+}
+
+static void jz4770_otg_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDN, reg_opcr);
+}
+
+static int jz4770_otg_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ return !!(readl(reg_opcr) & OPCR_SPENDN);
+}
+
+static const struct clk_ops jz4770_otg_phy_ops = {
+ .enable = jz4770_otg_phy_enable,
+ .disable = jz4770_otg_phy_disable,
+ .is_enabled = jz4770_otg_phy_is_enabled,
+};
+
+static const s8 pll_od_encoding[8] = {
+ 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+};
+
+static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
+
+ /* External clocks */
+
+ [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
+ [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
+
+ /* PLLs */
+
+ [JZ4770_CLK_PLL0] = {
+ "pll0", CGU_CLK_PLL,
+ .parents = { JZ4770_CLK_EXT },
+ .pll = {
+ .reg = CGU_REG_CPPCR0,
+ .m_shift = 24,
+ .m_bits = 7,
+ .m_offset = 1,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 1,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 8,
+ .od_encoding = pll_od_encoding,
+ .bypass_bit = 9,
+ .enable_bit = 8,
+ .stable_bit = 10,
+ },
+ },
+
+ [JZ4770_CLK_PLL1] = {
+ /* TODO: PLL1 can depend on PLL0 */
+ "pll1", CGU_CLK_PLL,
+ .parents = { JZ4770_CLK_EXT },
+ .pll = {
+ .reg = CGU_REG_CPPCR1,
+ .m_shift = 24,
+ .m_bits = 7,
+ .m_offset = 1,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 1,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 8,
+ .od_encoding = pll_od_encoding,
+ .enable_bit = 7,
+ .stable_bit = 6,
+ .no_bypass_bit = true,
+ },
+ },
+
+ /* Main clocks */
+
+ [JZ4770_CLK_CCLK] = {
+ "cclk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_H0CLK] = {
+ "h0clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_H1CLK] = {
+ "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1 },
+ .gate = { CGU_REG_LCR, 30 },
+ },
+ [JZ4770_CLK_H2CLK] = {
+ "h2clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_C1CLK] = {
+ "c1clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_PCLK] = {
+ "pclk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
+ },
+
+ /* Those divided clocks can connect to PLL0 or PLL1 */
+
+ [JZ4770_CLK_MMC0_MUX] = {
+ "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC0CDR, 30, 1 },
+ .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC0CDR, 31 },
+ },
+ [JZ4770_CLK_MMC1_MUX] = {
+ "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC1CDR, 30, 1 },
+ .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC1CDR, 31 },
+ },
+ [JZ4770_CLK_MMC2_MUX] = {
+ "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC2CDR, 30, 1 },
+ .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC2CDR, 31 },
+ },
+ [JZ4770_CLK_CIM] = {
+ "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_CIMCDR, 31, 1 },
+ .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 26 },
+ },
+ [JZ4770_CLK_UHC] = {
+ "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_UHCCDR, 29, 1 },
+ .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 24 },
+ },
+ [JZ4770_CLK_GPU] = {
+ "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
+ .mux = { CGU_REG_GPUCDR, 31, 1 },
+ .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 9 },
+ },
+ [JZ4770_CLK_BCH] = {
+ "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_BCHCDR, 31, 1 },
+ .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 1 },
+ },
+ [JZ4770_CLK_LPCLK_MUX] = {
+ "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_LPCDR, 29, 1 },
+ .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 28 },
+ },
+ [JZ4770_CLK_GPS] = {
+ "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_GPSCDR, 31, 1 },
+ .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 22 },
+ },
+
+ /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
+
+ [JZ4770_CLK_SSI_MUX] = {
+ "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_SSICDR, 30, 2 },
+ .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
+ },
+ [JZ4770_CLK_PCM_MUX] = {
+ "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_PCMCDR, 30, 2 },
+ .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
+ },
+ [JZ4770_CLK_I2S] = {
+ "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_I2SCDR, 30, 2 },
+ .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 13 },
+ },
+ [JZ4770_CLK_OTG] = {
+ "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_USBCDR, 30, 2 },
+ .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 2 },
+ },
+
+ /* Gate-only clocks */
+
+ [JZ4770_CLK_SSI0] = {
+ "ssi0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 4 },
+ },
+ [JZ4770_CLK_SSI1] = {
+ "ssi1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 19 },
+ },
+ [JZ4770_CLK_SSI2] = {
+ "ssi2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 20 },
+ },
+ [JZ4770_CLK_PCM0] = {
+ "pcm0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PCM_MUX, },
+ .gate = { CGU_REG_CLKGR1, 8 },
+ },
+ [JZ4770_CLK_PCM1] = {
+ "pcm1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PCM_MUX, },
+ .gate = { CGU_REG_CLKGR1, 10 },
+ },
+ [JZ4770_CLK_DMA] = {
+ "dma", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H2CLK, },
+ .gate = { CGU_REG_CLKGR0, 21 },
+ },
+ [JZ4770_CLK_I2C0] = {
+ "i2c0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 5 },
+ },
+ [JZ4770_CLK_I2C1] = {
+ "i2c1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 6 },
+ },
+ [JZ4770_CLK_I2C2] = {
+ "i2c2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR1, 15 },
+ },
+ [JZ4770_CLK_UART0] = {
+ "uart0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 15 },
+ },
+ [JZ4770_CLK_UART1] = {
+ "uart1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 16 },
+ },
+ [JZ4770_CLK_UART2] = {
+ "uart2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 17 },
+ },
+ [JZ4770_CLK_UART3] = {
+ "uart3", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 18 },
+ },
+ [JZ4770_CLK_IPU] = {
+ "ipu", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H0CLK, },
+ .gate = { CGU_REG_CLKGR0, 29 },
+ },
+ [JZ4770_CLK_ADC] = {
+ "adc", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 14 },
+ },
+ [JZ4770_CLK_AIC] = {
+ "aic", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 8 },
+ },
+ [JZ4770_CLK_AUX] = {
+ "aux", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_C1CLK, },
+ .gate = { CGU_REG_CLKGR1, 14 },
+ },
+ [JZ4770_CLK_VPU] = {
+ "vpu", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR1, 7 },
+ },
+ [JZ4770_CLK_MMC0] = {
+ "mmc0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC0_MUX, },
+ .gate = { CGU_REG_CLKGR0, 3 },
+ },
+ [JZ4770_CLK_MMC1] = {
+ "mmc1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC1_MUX, },
+ .gate = { CGU_REG_CLKGR0, 11 },
+ },
+ [JZ4770_CLK_MMC2] = {
+ "mmc2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC2_MUX, },
+ .gate = { CGU_REG_CLKGR0, 12 },
+ },
+
+ /* Custom clocks */
+
+ [JZ4770_CLK_UHC_PHY] = {
+ "uhc_phy", CGU_CLK_CUSTOM,
+ .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
+ .custom = { &jz4770_uhc_phy_ops },
+ },
+ [JZ4770_CLK_OTG_PHY] = {
+ "usb_phy", CGU_CLK_CUSTOM,
+ .parents = { JZ4770_CLK_OTG, -1, -1, -1 },
+ .custom = { &jz4770_otg_phy_ops },
+ },
+
+ [JZ4770_CLK_EXT512] = {
+ "ext/512", CGU_CLK_FIXDIV,
+ .parents = { JZ4770_CLK_EXT },
+ .fixdiv = { 512 },
+ },
+
+ [JZ4770_CLK_RTC] = {
+ "rtc", CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
+ .mux = { CGU_REG_OPCR, 2, 1},
+ },
+};
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+static int jz4770_cgu_pm_suspend(void)
+{
+ u32 val;
+
+ val = readl(cgu->base + CGU_REG_LCR);
+ writel(val | LCR_LPM, cgu->base + CGU_REG_LCR);
+ return 0;
+}
+
+static void jz4770_cgu_pm_resume(void)
+{
+ u32 val;
+
+ val = readl(cgu->base + CGU_REG_LCR);
+ writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR);
+}
+
+static struct syscore_ops jz4770_cgu_pm_ops = {
+ .suspend = jz4770_cgu_pm_suspend,
+ .resume = jz4770_cgu_pm_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static void __init jz4770_cgu_init(struct device_node *np)
+{
+ int retval;
+
+ cgu = ingenic_cgu_new(jz4770_cgu_clocks,
+ ARRAY_SIZE(jz4770_cgu_clocks), np);
+ if (!cgu)
+ pr_err("%s: failed to initialise CGU\n", __func__);
+
+ retval = ingenic_cgu_register_clocks(cgu);
+ if (retval)
+ pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+ register_syscore_ops(&jz4770_cgu_pm_ops);
+#endif
+}
+
+/* We only probe via devicetree, no need for a platform driver */
+CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
--
2.11.0

2018-01-05 18:28:22

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 01/15] clk: ingenic: Use const pointer to clk_ops in struct

The CGU common code does not modify the pointed clk_ops structure, so it
should be marked as const.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.h | 2 +-
drivers/clk/ingenic/jz4780-cgu.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

v2: New patch in this series
v3: No change
v4: No change
v5: No change
v6: No change

diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index e78b586536ea..f1527cf75b3f 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -120,7 +120,7 @@ struct ingenic_cgu_gate_info {
* @clk_ops: custom clock operation callbacks
*/
struct ingenic_cgu_custom_info {
- struct clk_ops *clk_ops;
+ const struct clk_ops *clk_ops;
};

/**
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
index ac3585ed8228..6427be117ff1 100644
--- a/drivers/clk/ingenic/jz4780-cgu.c
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -203,7 +203,7 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0;
}

-static struct clk_ops jz4780_otg_phy_ops = {
+static const struct clk_ops jz4780_otg_phy_ops = {
.get_parent = jz4780_otg_phy_get_parent,
.set_parent = jz4780_otg_phy_set_parent,

--
2.11.0

2018-01-05 18:28:21

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v6 03/15] clk: ingenic: support PLLs with no bypass bit

The second PLL of the JZ4770 does not have a bypass bit.
This commit makes it possible to support it with the current common CGU
code.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 3 ++-
drivers/clk/ingenic/cgu.h | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index a2e73a6d60fd..381c4a17a1fc 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -100,7 +100,8 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0);
- bypass = !!(ctl & BIT(pll_info->bypass_bit));
+ bypass = !pll_info->no_bypass_bit &&
+ !!(ctl & BIT(pll_info->bypass_bit));
enable = !!(ctl & BIT(pll_info->enable_bit));

if (bypass)
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index f1527cf75b3f..9da34910bd80 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -48,6 +48,7 @@
* @bypass_bit: the index of the bypass bit in the PLL control register
* @enable_bit: the index of the enable bit in the PLL control register
* @stable_bit: the index of the stable bit in the PLL control register
+ * @no_bypass_bit: if set, the PLL has no bypass functionality
*/
struct ingenic_cgu_pll_info {
unsigned reg;
@@ -58,6 +59,7 @@ struct ingenic_cgu_pll_info {
u8 bypass_bit;
u8 enable_bit;
u8 stable_bit;
+ bool no_bypass_bit;
};

/**
--
2.11.0

2018-01-07 16:19:30

by Philippe Ombredanne

[permalink] [raw]
Subject: Re: [PATCH v6 15/15] MIPS: ingenic: Initial GCW Zero support

On Fri, Jan 5, 2018 at 7:25 PM, Paul Cercueil <[email protected]> wrote:
> The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
> handheld game console, successfully kickstarted in ~2012, running Linux.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> Acked-by: Mathieu Malaterre <[email protected]>
> ---
> arch/mips/boot/dts/ingenic/Makefile | 1 +
> arch/mips/boot/dts/ingenic/gcw0.dts | 62 +++++++++++++++++++++++++++++++++++++
> arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
> arch/mips/jz4740/Kconfig | 4 +++
> 4 files changed, 94 insertions(+)
> create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
> create mode 100644 arch/mips/configs/gcw0_defconfig
>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
> Drop custom CROSS_COMPILE from defconfig
> v6: Add "model" property in devicetree

For the use of SPDX tags for the whole patch set: thank you!

Acked-by: Philippe Ombredanne <[email protected]>
--
Cordially
Philippe Ombredanne

2018-01-10 21:38:26

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 06/15] clk: Add Ingenic jz4770 CGU driver

Hi Paul,

On Fri, Jan 05, 2018 at 07:25:04PM +0100, Paul Cercueil wrote:
> Add support for the clocks provided by the CGU in the Ingenic JZ4770
> SoC.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> Signed-off-by: Maarten ter Huurne <[email protected]>
> Acked-by: Stephen Boyd <[email protected]>
> ---
> drivers/clk/ingenic/Makefile | 1 +
> drivers/clk/ingenic/jz4770-cgu.c | 483 +++++++++++++++++++++++++++++++++++++++

Should this file and the jz4770-cgu.h header be added to a new
MAINTAINERS entry for this driver and/or for the platform as a whole?

Cheers
James

> 2 files changed, 484 insertions(+)
> create mode 100644 drivers/clk/ingenic/jz4770-cgu.c
>
> v2: Make structures static const
> v3: <dt-bindings/clock/jz4770-cgu.h> is now added in a separate patch
> v4: No change
> v5: Use SPDX license identifier
> v6: No change
>
> diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
> index cd47b0664c2b..1456e4cdb562 100644
> --- a/drivers/clk/ingenic/Makefile
> +++ b/drivers/clk/ingenic/Makefile
> @@ -1,3 +1,4 @@
> obj-y += cgu.o
> obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
> +obj-$(CONFIG_MACH_JZ4770) += jz4770-cgu.o
> obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o
> diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c
> new file mode 100644
> index 000000000000..c78d369b9403
> --- /dev/null
> +++ b/drivers/clk/ingenic/jz4770-cgu.c
> @@ -0,0 +1,483 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * JZ4770 SoC CGU driver
> + * Copyright 2018, Paul Cercueil <[email protected]>
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +#include <linux/syscore_ops.h>
> +#include <dt-bindings/clock/jz4770-cgu.h>
> +#include "cgu.h"
> +
> +/*
> + * CPM registers offset address definition
> + */
> +#define CGU_REG_CPCCR 0x00
> +#define CGU_REG_LCR 0x04
> +#define CGU_REG_CPPCR0 0x10
> +#define CGU_REG_CLKGR0 0x20
> +#define CGU_REG_OPCR 0x24
> +#define CGU_REG_CLKGR1 0x28
> +#define CGU_REG_CPPCR1 0x30
> +#define CGU_REG_USBPCR1 0x48
> +#define CGU_REG_USBCDR 0x50
> +#define CGU_REG_I2SCDR 0x60
> +#define CGU_REG_LPCDR 0x64
> +#define CGU_REG_MSC0CDR 0x68
> +#define CGU_REG_UHCCDR 0x6c
> +#define CGU_REG_SSICDR 0x74
> +#define CGU_REG_CIMCDR 0x7c
> +#define CGU_REG_GPSCDR 0x80
> +#define CGU_REG_PCMCDR 0x84
> +#define CGU_REG_GPUCDR 0x88
> +#define CGU_REG_MSC1CDR 0xA4
> +#define CGU_REG_MSC2CDR 0xA8
> +#define CGU_REG_BCHCDR 0xAC
> +
> +/* bits within the LCR register */
> +#define LCR_LPM BIT(0) /* Low Power Mode */
> +
> +/* bits within the OPCR register */
> +#define OPCR_SPENDH BIT(5) /* UHC PHY suspend */
> +#define OPCR_SPENDN BIT(7) /* OTG PHY suspend */
> +
> +/* bits within the USBPCR1 register */
> +#define USBPCR1_UHC_POWER BIT(5) /* UHC PHY power down */
> +
> +static struct ingenic_cgu *cgu;
> +
> +static int jz4770_uhc_phy_enable(struct clk_hw *hw)
> +{
> + void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
> + void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
> +
> + writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
> + writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
> + return 0;
> +}
> +
> +static void jz4770_uhc_phy_disable(struct clk_hw *hw)
> +{
> + void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
> + void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
> +
> + writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
> + writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
> +}
> +
> +static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
> +{
> + void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
> + void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
> +
> + return !(readl(reg_opcr) & OPCR_SPENDH) &&
> + (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
> +}
> +
> +static const struct clk_ops jz4770_uhc_phy_ops = {
> + .enable = jz4770_uhc_phy_enable,
> + .disable = jz4770_uhc_phy_disable,
> + .is_enabled = jz4770_uhc_phy_is_enabled,
> +};
> +
> +static int jz4770_otg_phy_enable(struct clk_hw *hw)
> +{
> + void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
> +
> + writel(readl(reg_opcr) | OPCR_SPENDN, reg_opcr);
> +
> + /* Wait for the clock to be stable */
> + udelay(50);
> + return 0;
> +}
> +
> +static void jz4770_otg_phy_disable(struct clk_hw *hw)
> +{
> + void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
> +
> + writel(readl(reg_opcr) & ~OPCR_SPENDN, reg_opcr);
> +}
> +
> +static int jz4770_otg_phy_is_enabled(struct clk_hw *hw)
> +{
> + void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
> +
> + return !!(readl(reg_opcr) & OPCR_SPENDN);
> +}
> +
> +static const struct clk_ops jz4770_otg_phy_ops = {
> + .enable = jz4770_otg_phy_enable,
> + .disable = jz4770_otg_phy_disable,
> + .is_enabled = jz4770_otg_phy_is_enabled,
> +};
> +
> +static const s8 pll_od_encoding[8] = {
> + 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
> +};
> +
> +static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
> +
> + /* External clocks */
> +
> + [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
> + [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
> +
> + /* PLLs */
> +
> + [JZ4770_CLK_PLL0] = {
> + "pll0", CGU_CLK_PLL,
> + .parents = { JZ4770_CLK_EXT },
> + .pll = {
> + .reg = CGU_REG_CPPCR0,
> + .m_shift = 24,
> + .m_bits = 7,
> + .m_offset = 1,
> + .n_shift = 18,
> + .n_bits = 5,
> + .n_offset = 1,
> + .od_shift = 16,
> + .od_bits = 2,
> + .od_max = 8,
> + .od_encoding = pll_od_encoding,
> + .bypass_bit = 9,
> + .enable_bit = 8,
> + .stable_bit = 10,
> + },
> + },
> +
> + [JZ4770_CLK_PLL1] = {
> + /* TODO: PLL1 can depend on PLL0 */
> + "pll1", CGU_CLK_PLL,
> + .parents = { JZ4770_CLK_EXT },
> + .pll = {
> + .reg = CGU_REG_CPPCR1,
> + .m_shift = 24,
> + .m_bits = 7,
> + .m_offset = 1,
> + .n_shift = 18,
> + .n_bits = 5,
> + .n_offset = 1,
> + .od_shift = 16,
> + .od_bits = 2,
> + .od_max = 8,
> + .od_encoding = pll_od_encoding,
> + .enable_bit = 7,
> + .stable_bit = 6,
> + .no_bypass_bit = true,
> + },
> + },
> +
> + /* Main clocks */
> +
> + [JZ4770_CLK_CCLK] = {
> + "cclk", CGU_CLK_DIV,
> + .parents = { JZ4770_CLK_PLL0, },
> + .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
> + },
> + [JZ4770_CLK_H0CLK] = {
> + "h0clk", CGU_CLK_DIV,
> + .parents = { JZ4770_CLK_PLL0, },
> + .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
> + },
> + [JZ4770_CLK_H1CLK] = {
> + "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_PLL0, },
> + .div = { CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1 },
> + .gate = { CGU_REG_LCR, 30 },
> + },
> + [JZ4770_CLK_H2CLK] = {
> + "h2clk", CGU_CLK_DIV,
> + .parents = { JZ4770_CLK_PLL0, },
> + .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 },
> + },
> + [JZ4770_CLK_C1CLK] = {
> + "c1clk", CGU_CLK_DIV,
> + .parents = { JZ4770_CLK_PLL0, },
> + .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
> + },
> + [JZ4770_CLK_PCLK] = {
> + "pclk", CGU_CLK_DIV,
> + .parents = { JZ4770_CLK_PLL0, },
> + .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
> + },
> +
> + /* Those divided clocks can connect to PLL0 or PLL1 */
> +
> + [JZ4770_CLK_MMC0_MUX] = {
> + "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_MSC0CDR, 30, 1 },
> + .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
> + .gate = { CGU_REG_MSC0CDR, 31 },
> + },
> + [JZ4770_CLK_MMC1_MUX] = {
> + "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_MSC1CDR, 30, 1 },
> + .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
> + .gate = { CGU_REG_MSC1CDR, 31 },
> + },
> + [JZ4770_CLK_MMC2_MUX] = {
> + "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_MSC2CDR, 30, 1 },
> + .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
> + .gate = { CGU_REG_MSC2CDR, 31 },
> + },
> + [JZ4770_CLK_CIM] = {
> + "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_CIMCDR, 31, 1 },
> + .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR0, 26 },
> + },
> + [JZ4770_CLK_UHC] = {
> + "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_UHCCDR, 29, 1 },
> + .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR0, 24 },
> + },
> + [JZ4770_CLK_GPU] = {
> + "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
> + .mux = { CGU_REG_GPUCDR, 31, 1 },
> + .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR1, 9 },
> + },
> + [JZ4770_CLK_BCH] = {
> + "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_BCHCDR, 31, 1 },
> + .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR0, 1 },
> + },
> + [JZ4770_CLK_LPCLK_MUX] = {
> + "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_LPCDR, 29, 1 },
> + .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR0, 28 },
> + },
> + [JZ4770_CLK_GPS] = {
> + "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
> + .mux = { CGU_REG_GPSCDR, 31, 1 },
> + .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR0, 22 },
> + },
> +
> + /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
> +
> + [JZ4770_CLK_SSI_MUX] = {
> + "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_EXT, -1,
> + JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
> + .mux = { CGU_REG_SSICDR, 30, 2 },
> + .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
> + },
> + [JZ4770_CLK_PCM_MUX] = {
> + "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_EXT, -1,
> + JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
> + .mux = { CGU_REG_PCMCDR, 30, 2 },
> + .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
> + },
> + [JZ4770_CLK_I2S] = {
> + "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_EXT, -1,
> + JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
> + .mux = { CGU_REG_I2SCDR, 30, 2 },
> + .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR1, 13 },
> + },
> + [JZ4770_CLK_OTG] = {
> + "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_EXT, -1,
> + JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
> + .mux = { CGU_REG_USBCDR, 30, 2 },
> + .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
> + .gate = { CGU_REG_CLKGR0, 2 },
> + },
> +
> + /* Gate-only clocks */
> +
> + [JZ4770_CLK_SSI0] = {
> + "ssi0", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_SSI_MUX, },
> + .gate = { CGU_REG_CLKGR0, 4 },
> + },
> + [JZ4770_CLK_SSI1] = {
> + "ssi1", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_SSI_MUX, },
> + .gate = { CGU_REG_CLKGR0, 19 },
> + },
> + [JZ4770_CLK_SSI2] = {
> + "ssi2", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_SSI_MUX, },
> + .gate = { CGU_REG_CLKGR0, 20 },
> + },
> + [JZ4770_CLK_PCM0] = {
> + "pcm0", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_PCM_MUX, },
> + .gate = { CGU_REG_CLKGR1, 8 },
> + },
> + [JZ4770_CLK_PCM1] = {
> + "pcm1", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_PCM_MUX, },
> + .gate = { CGU_REG_CLKGR1, 10 },
> + },
> + [JZ4770_CLK_DMA] = {
> + "dma", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_H2CLK, },
> + .gate = { CGU_REG_CLKGR0, 21 },
> + },
> + [JZ4770_CLK_I2C0] = {
> + "i2c0", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 5 },
> + },
> + [JZ4770_CLK_I2C1] = {
> + "i2c1", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 6 },
> + },
> + [JZ4770_CLK_I2C2] = {
> + "i2c2", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR1, 15 },
> + },
> + [JZ4770_CLK_UART0] = {
> + "uart0", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 15 },
> + },
> + [JZ4770_CLK_UART1] = {
> + "uart1", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 16 },
> + },
> + [JZ4770_CLK_UART2] = {
> + "uart2", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 17 },
> + },
> + [JZ4770_CLK_UART3] = {
> + "uart3", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 18 },
> + },
> + [JZ4770_CLK_IPU] = {
> + "ipu", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_H0CLK, },
> + .gate = { CGU_REG_CLKGR0, 29 },
> + },
> + [JZ4770_CLK_ADC] = {
> + "adc", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 14 },
> + },
> + [JZ4770_CLK_AIC] = {
> + "aic", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_EXT, },
> + .gate = { CGU_REG_CLKGR0, 8 },
> + },
> + [JZ4770_CLK_AUX] = {
> + "aux", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_C1CLK, },
> + .gate = { CGU_REG_CLKGR1, 14 },
> + },
> + [JZ4770_CLK_VPU] = {
> + "vpu", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_H1CLK, },
> + .gate = { CGU_REG_CLKGR1, 7 },
> + },
> + [JZ4770_CLK_MMC0] = {
> + "mmc0", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_MMC0_MUX, },
> + .gate = { CGU_REG_CLKGR0, 3 },
> + },
> + [JZ4770_CLK_MMC1] = {
> + "mmc1", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_MMC1_MUX, },
> + .gate = { CGU_REG_CLKGR0, 11 },
> + },
> + [JZ4770_CLK_MMC2] = {
> + "mmc2", CGU_CLK_GATE,
> + .parents = { JZ4770_CLK_MMC2_MUX, },
> + .gate = { CGU_REG_CLKGR0, 12 },
> + },
> +
> + /* Custom clocks */
> +
> + [JZ4770_CLK_UHC_PHY] = {
> + "uhc_phy", CGU_CLK_CUSTOM,
> + .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
> + .custom = { &jz4770_uhc_phy_ops },
> + },
> + [JZ4770_CLK_OTG_PHY] = {
> + "usb_phy", CGU_CLK_CUSTOM,
> + .parents = { JZ4770_CLK_OTG, -1, -1, -1 },
> + .custom = { &jz4770_otg_phy_ops },
> + },
> +
> + [JZ4770_CLK_EXT512] = {
> + "ext/512", CGU_CLK_FIXDIV,
> + .parents = { JZ4770_CLK_EXT },
> + .fixdiv = { 512 },
> + },
> +
> + [JZ4770_CLK_RTC] = {
> + "rtc", CGU_CLK_MUX,
> + .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
> + .mux = { CGU_REG_OPCR, 2, 1},
> + },
> +};
> +
> +#if IS_ENABLED(CONFIG_PM_SLEEP)
> +static int jz4770_cgu_pm_suspend(void)
> +{
> + u32 val;
> +
> + val = readl(cgu->base + CGU_REG_LCR);
> + writel(val | LCR_LPM, cgu->base + CGU_REG_LCR);
> + return 0;
> +}
> +
> +static void jz4770_cgu_pm_resume(void)
> +{
> + u32 val;
> +
> + val = readl(cgu->base + CGU_REG_LCR);
> + writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR);
> +}
> +
> +static struct syscore_ops jz4770_cgu_pm_ops = {
> + .suspend = jz4770_cgu_pm_suspend,
> + .resume = jz4770_cgu_pm_resume,
> +};
> +#endif /* CONFIG_PM_SLEEP */
> +
> +static void __init jz4770_cgu_init(struct device_node *np)
> +{
> + int retval;
> +
> + cgu = ingenic_cgu_new(jz4770_cgu_clocks,
> + ARRAY_SIZE(jz4770_cgu_clocks), np);
> + if (!cgu)
> + pr_err("%s: failed to initialise CGU\n", __func__);
> +
> + retval = ingenic_cgu_register_clocks(cgu);
> + if (retval)
> + pr_err("%s: failed to register CGU Clocks\n", __func__);
> +
> +#if IS_ENABLED(CONFIG_PM_SLEEP)
> + register_syscore_ops(&jz4770_cgu_pm_ops);
> +#endif
> +}
> +
> +/* We only probe via devicetree, no need for a platform driver */
> +CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
> --
> 2.11.0
>
>


Attachments:
(No filename) (15.14 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-10 22:17:14

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 08/15] MIPS: ingenic: Use common cmdline handling code

On Fri, Jan 05, 2018 at 07:25:06PM +0100, Paul Cercueil wrote:
> From: Paul Burton <[email protected]>
>
> jz4740_init_cmdline appends all arguments from argv (in fw_arg1) to
> arcs_cmdline, up to argc (in fw_arg0). The common code in
> fw_init_cmdline will do the exact same thing when run on a system where
> fw_arg0 isn't a pointer to kseg0 (it'll also set _fw_envp but we don't
> use it). Remove the custom implementation & use the generic code.
>
> Signed-off-by: Paul Burton <[email protected]>
> Reviewed-by: PrasannaKumar Muralidharan <[email protected]>

Reviewed-by: James Hogan <[email protected]>

Cheers
James

> ---
> arch/mips/jz4740/prom.c | 24 ++----------------------
> 1 file changed, 2 insertions(+), 22 deletions(-)
>
> v2: No change
> v3: No change
> v4: No change
> v5: No change
> v6: Update Paul Burton's email address
>
> diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
> index 47e857194ce6..a62dd8e6ecf9 100644
> --- a/arch/mips/jz4740/prom.c
> +++ b/arch/mips/jz4740/prom.c
> @@ -20,33 +20,13 @@
> #include <linux/serial_reg.h>
>
> #include <asm/bootinfo.h>
> +#include <asm/fw/fw.h>
> #include <asm/mach-jz4740/base.h>
>
> -static __init void jz4740_init_cmdline(int argc, char *argv[])
> -{
> - unsigned int count = COMMAND_LINE_SIZE - 1;
> - int i;
> - char *dst = &(arcs_cmdline[0]);
> - char *src;
> -
> - for (i = 1; i < argc && count; ++i) {
> - src = argv[i];
> - while (*src && count) {
> - *dst++ = *src++;
> - --count;
> - }
> - *dst++ = ' ';
> - }
> - if (i > 1)
> - --dst;
> -
> - *dst = 0;
> -}
> -
> void __init prom_init(void)
> {
> - jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
> mips_machtype = MACH_INGENIC_JZ4740;
> + fw_init_cmdline();
> }
>
> void __init prom_free_prom_memory(void)
> --
> 2.11.0
>
>


Attachments:
(No filename) (1.79 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-10 22:20:12

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 09/15] MIPS: platform: add machtype IDs for more Ingenic SoCs

On Fri, Jan 05, 2018 at 07:25:07PM +0100, Paul Cercueil wrote:
> Add a machtype ID for the JZ4780 SoC, which was missing, and one for the
> newly supported JZ4770 SoC.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> Reviewed-by: PrasannaKumar Muralidharan <[email protected]>

Reviewed-by: James Hogan <[email protected]>

Though perhaps its time for an enum.

Cheers
James

> ---
> arch/mips/include/asm/bootinfo.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> v2: No change
> v3: No change
> v4: No change
> v5: No change
> v6: No change
>
> diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
> index e26a093bb17a..a301a8f4bc66 100644
> --- a/arch/mips/include/asm/bootinfo.h
> +++ b/arch/mips/include/asm/bootinfo.h
> @@ -79,6 +79,8 @@ enum loongson_machine_type {
> */
> #define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */
> #define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */
> +#define MACH_INGENIC_JZ4770 2 /* JZ4770 SOC */
> +#define MACH_INGENIC_JZ4780 3 /* JZ4780 SOC */
>
> extern char *system_type;
> const char *get_system_type(void);
> --
> 2.11.0
>
>


Attachments:
(No filename) (1.11 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-10 22:28:40

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 10/15] MIPS: ingenic: Detect machtype from SoC compatible string

On Fri, Jan 05, 2018 at 07:25:08PM +0100, Paul Cercueil wrote:
> Previously, the mips_machtype variable was always initialized
> to MACH_INGENIC_JZ4740 even if running on different SoCs.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> ---
> arch/mips/jz4740/prom.c | 1 -
> arch/mips/jz4740/setup.c | 26 ++++++++++++++++++++++----
> 2 files changed, 22 insertions(+), 5 deletions(-)
>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
> v6: Init mips_machtype from DT compatible string instead of using
> MIPS_MACHINE
>
> diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
> index a62dd8e6ecf9..eb9f2f97bedb 100644
> --- a/arch/mips/jz4740/prom.c
> +++ b/arch/mips/jz4740/prom.c
> @@ -25,7 +25,6 @@
>
> void __init prom_init(void)
> {
> - mips_machtype = MACH_INGENIC_JZ4740;
> fw_init_cmdline();
> }
>
> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
> index 6d0152321819..cd89536fbba1 100644
> --- a/arch/mips/jz4740/setup.c
> +++ b/arch/mips/jz4740/setup.c
> @@ -53,16 +53,30 @@ static void __init jz4740_detect_mem(void)
> add_memory_region(0, size, BOOT_MEM_RAM);
> }
>
> +static unsigned long __init get_board_mach_type(const void *fdt)
> +{
> + if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4780"))
> + return MACH_INGENIC_JZ4780;
> + if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4770"))
> + return MACH_INGENIC_JZ4770;
> +
> + return MACH_INGENIC_JZ4740;
> +}
> +
> void __init plat_mem_setup(void)
> {
> int offset;
>
> + if (!early_init_dt_scan(__dtb_start))
> + return;
> +
> jz4740_reset_init();
> - __dt_setup_arch(__dtb_start);

Is it intentional that by removing this we no longer set the machine
name, so it'll default to "unknown"? The commit message doesn't mention
that change.

Cheers
James


>
> offset = fdt_path_offset(__dtb_start, "/memory");
> if (offset < 0)
> jz4740_detect_mem();
> +
> + mips_machtype = get_board_mach_type(__dtb_start);
> }
>
> void __init device_tree_init(void)
> @@ -75,10 +89,14 @@ void __init device_tree_init(void)
>
> const char *get_system_type(void)
> {
> - if (IS_ENABLED(CONFIG_MACH_JZ4780))
> + switch (mips_machtype) {
> + case MACH_INGENIC_JZ4780:
> return "JZ4780";
> -
> - return "JZ4740";
> + case MACH_INGENIC_JZ4770:
> + return "JZ4770";
> + default:
> + return "JZ4740";
> + }
> }
>
> void __init arch_init_irq(void)
> --
> 2.11.0
>
>


Attachments:
(No filename) (2.39 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-10 22:43:50

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 11/15] MIPS: ingenic: Initial JZ4770 support

On Fri, Jan 05, 2018 at 07:25:09PM +0100, Paul Cercueil wrote:
> Provide just enough bits (clocks, clocksource, uart) to allow a kernel
> to boot on the JZ4770 SoC to a initramfs userspace.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
> ---
> arch/mips/boot/dts/ingenic/jz4770.dtsi | 212 +++++++++++++++++++++++++++++++++
> arch/mips/jz4740/Kconfig | 6 +
> arch/mips/jz4740/time.c | 2 +-
> 3 files changed, 219 insertions(+), 1 deletion(-)
> create mode 100644 arch/mips/boot/dts/ingenic/jz4770.dtsi

We should probably have a MAINTAINERS entry including this file. Same
goes for the GC0 files added in the last patch.

Cheers
James

>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
> v6: No change
>
> diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
> new file mode 100644
> index 000000000000..7c2804f3f5f1
> --- /dev/null
> +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
> @@ -0,0 +1,212 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <dt-bindings/clock/jz4770-cgu.h>
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "ingenic,jz4770";
> +
> + cpuintc: interrupt-controller {
> + #address-cells = <0>;
> + #interrupt-cells = <1>;
> + interrupt-controller;
> + compatible = "mti,cpu-interrupt-controller";
> + };
> +
> + intc: interrupt-controller@10001000 {
> + compatible = "ingenic,jz4770-intc";
> + reg = <0x10001000 0x40>;
> +
> + interrupt-controller;
> + #interrupt-cells = <1>;
> +
> + interrupt-parent = <&cpuintc>;
> + interrupts = <2>;
> + };
> +
> + ext: ext {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + };
> +
> + osc32k: osc32k {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <32768>;
> + };
> +
> + cgu: jz4770-cgu@10000000 {
> + compatible = "ingenic,jz4770-cgu";
> + reg = <0x10000000 0x100>;
> +
> + clocks = <&ext>, <&osc32k>;
> + clock-names = "ext", "osc32k";
> +
> + #clock-cells = <1>;
> + };
> +
> + pinctrl: pin-controller@10010000 {
> + compatible = "ingenic,jz4770-pinctrl";
> + reg = <0x10010000 0x600>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + gpa: gpio@0 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <0>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 0 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <17>;
> + };
> +
> + gpb: gpio@1 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <1>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 32 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <16>;
> + };
> +
> + gpc: gpio@2 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <2>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 64 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <15>;
> + };
> +
> + gpd: gpio@3 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <3>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 96 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <14>;
> + };
> +
> + gpe: gpio@4 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <4>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 128 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <13>;
> + };
> +
> + gpf: gpio@5 {
> + compatible = "ingenic,jz4770-gpio";
> + reg = <5>;
> +
> + gpio-controller;
> + gpio-ranges = <&pinctrl 0 160 32>;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <12>;
> + };
> + };
> +
> + uart0: serial@10030000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10030000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART0>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <5>;
> +
> + status = "disabled";
> + };
> +
> + uart1: serial@10031000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10031000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART1>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <4>;
> +
> + status = "disabled";
> + };
> +
> + uart2: serial@10032000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10032000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART2>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <3>;
> +
> + status = "disabled";
> + };
> +
> + uart3: serial@10033000 {
> + compatible = "ingenic,jz4770-uart";
> + reg = <0x10033000 0x100>;
> +
> + clocks = <&ext>, <&cgu JZ4770_CLK_UART3>;
> + clock-names = "baud", "module";
> +
> + interrupt-parent = <&intc>;
> + interrupts = <2>;
> +
> + status = "disabled";
> + };
> +
> + uhc: uhc@13430000 {
> + compatible = "generic-ohci";
> + reg = <0x13430000 0x1000>;
> +
> + clocks = <&cgu JZ4770_CLK_UHC>, <&cgu JZ4770_CLK_UHC_PHY>;
> + assigned-clocks = <&cgu JZ4770_CLK_UHC>;
> + assigned-clock-rates = <48000000>;
> +
> + interrupt-parent = <&intc>;
> + interrupts = <20>;
> +
> + status = "disabled";
> + };
> +};
> diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
> index 643af2012e14..29a9361a2b77 100644
> --- a/arch/mips/jz4740/Kconfig
> +++ b/arch/mips/jz4740/Kconfig
> @@ -18,6 +18,12 @@ config MACH_JZ4740
> bool
> select SYS_HAS_CPU_MIPS32_R1
>
> +config MACH_JZ4770
> + bool
> + select MIPS_CPU_SCACHE
> + select SYS_HAS_CPU_MIPS32_R2
> + select SYS_SUPPORTS_HIGHMEM
> +
> config MACH_JZ4780
> bool
> select MIPS_CPU_SCACHE
> diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
> index bb1ad5119da4..2ca9160f642a 100644
> --- a/arch/mips/jz4740/time.c
> +++ b/arch/mips/jz4740/time.c
> @@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
> #ifdef CONFIG_MACH_JZ4740
> .irq = JZ4740_IRQ_TCU0,
> #endif
> -#ifdef CONFIG_MACH_JZ4780
> +#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
> .irq = JZ4780_IRQ_TCU2,
> #endif
> };
> --
> 2.11.0
>
>


Attachments:
(No filename) (6.43 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-10 22:53:58

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 12/15] MIPS: JZ4770: Work around config2 misreporting associativity

On Fri, Jan 05, 2018 at 07:25:10PM +0100, Paul Cercueil wrote:
> From: Maarten ter Huurne <[email protected]>
>
> According to config2, the associativity would be 5-ways, but the
> documentation states 4-ways, which also matches the documented
> L2 cache size of 256 kB.
>
> Signed-off-by: Maarten ter Huurne <[email protected]>

Hehe, nice

Reviewed-by: James Hogan <[email protected]>

Cheers
James

> ---
> arch/mips/mm/sc-mips.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> v2: No change
> v3: No change
> v4: Rebased on top of Linux 4.15-rc5
> v5: No change
> v6: No change
>
> diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
> index 548acb7f8557..394673991bab 100644
> --- a/arch/mips/mm/sc-mips.c
> +++ b/arch/mips/mm/sc-mips.c
> @@ -16,6 +16,7 @@
> #include <asm/mmu_context.h>
> #include <asm/r4kcache.h>
> #include <asm/mips-cps.h>
> +#include <asm/bootinfo.h>
>
> /*
> * MIPS32/MIPS64 L2 cache handling
> @@ -220,6 +221,14 @@ static inline int __init mips_sc_probe(void)
> else
> return 0;
>
> + /*
> + * According to config2 it would be 5-ways, but that is contradicted
> + * by all documentation.
> + */
> + if (current_cpu_type() == CPU_JZRISC &&
> + mips_machtype == MACH_INGENIC_JZ4770)
> + c->scache.ways = 4;
> +
> c->scache.waysize = c->scache.sets * c->scache.linesz;
> c->scache.waybit = __ffs(c->scache.waysize);
>
> --
> 2.11.0
>
>


Attachments:
(No filename) (1.39 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-10 22:59:42

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v6 15/15] MIPS: ingenic: Initial GCW Zero support

Hi Philippe,

Le dim. 7 janv. 2018 ? 17:18, Philippe Ombredanne
<[email protected]> a ?crit :
> On Fri, Jan 5, 2018 at 7:25 PM, Paul Cercueil <[email protected]>
> wrote:
>> The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
>> handheld game console, successfully kickstarted in ~2012, running
>> Linux.
>>
>> Signed-off-by: Paul Cercueil <[email protected]>
>> Acked-by: Mathieu Malaterre <[email protected]>
>> ---
>> arch/mips/boot/dts/ingenic/Makefile | 1 +
>> arch/mips/boot/dts/ingenic/gcw0.dts | 62
>> +++++++++++++++++++++++++++++++++++++
>> arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
>> arch/mips/jz4740/Kconfig | 4 +++
>> 4 files changed, 94 insertions(+)
>> create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
>> create mode 100644 arch/mips/configs/gcw0_defconfig
>>
>> v2: No change
>> v3: No change
>> v4: No change
>> v5: Use SPDX license identifier
>> Drop custom CROSS_COMPILE from defconfig
>> v6: Add "model" property in devicetree
>
> For the use of SPDX tags for the whole patch set: thank you!
>
> Acked-by: Philippe Ombredanne <[email protected]>

Is your Acked-by for the whole patchset? Or just this one patch?

-Paul

2018-01-10 23:21:28

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v6 13/15] MIPS: JZ4770: Workaround for corrupted DMA transfers

On Fri, Jan 05, 2018 at 07:25:11PM +0100, Paul Cercueil wrote:
> From: Maarten ter Huurne <[email protected]>
>
> We have seen MMC DMA transfers read corrupted data from SDRAM when
> a burst interval ends at physical address 0x10000000. To avoid this
> problem, we remove the final page of low memory from the memory map.
>
> Signed-off-by: Maarten ter Huurne <[email protected]>
> ---
> arch/mips/jz4740/setup.c | 24 ++++++++++++++++++++++++
> arch/mips/kernel/setup.c | 8 ++++++++
> 2 files changed, 32 insertions(+)
>
> v2: No change
> v3: No change
> v4: No change
> v5: No change
> v6: No change
>
> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
> index cd89536fbba1..18c57c4bf47e 100644
> --- a/arch/mips/jz4740/setup.c
> +++ b/arch/mips/jz4740/setup.c
> @@ -22,6 +22,7 @@
> #include <linux/of_fdt.h>
>
> #include <asm/bootinfo.h>
> +#include <asm/page.h>
> #include <asm/prom.h>
>
> #include <asm/mach-jz4740/base.h>
> @@ -103,3 +104,26 @@ void __init arch_init_irq(void)
> {
> irqchip_init();
> }
> +
> +/*
> + * We have seen MMC DMA transfers read corrupted data from SDRAM when a burst
> + * interval ends at physical address 0x10000000. To avoid this problem, we
> + * remove the final page of low memory from the memory map.
> + */
> +void __init jz4770_reserve_unsafe_for_dma(void)
> +{
> + int i;
> +
> + for (i = 0; i < boot_mem_map.nr_map; i++) {
> + struct boot_mem_map_entry *entry = boot_mem_map.map + i;
> +
> + if (entry->type != BOOT_MEM_RAM)
> + continue;
> +
> + if (entry->addr + entry->size != 0x10000000)
> + continue;
> +
> + entry->size -= PAGE_SIZE;
> + break;
> + }
> +}
> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
> index 85bc601e9a0d..5a2c20145aee 100644
> --- a/arch/mips/kernel/setup.c
> +++ b/arch/mips/kernel/setup.c
> @@ -879,6 +879,14 @@ static void __init arch_mem_init(char **cmdline_p)
>
> parse_early_param();
>
> +#ifdef CONFIG_MACH_JZ4770
> + if (current_cpu_type() == CPU_JZRISC &&
> + mips_machtype == MACH_INGENIC_JZ4770) {
> + extern void __init jz4770_reserve_unsafe_for_dma(void);
> + jz4770_reserve_unsafe_for_dma();
> + }
> +#endif

Hmm, a little bit ugly. I'm guessing the plat_mem_setup() callback is
too early since mem= parameters won't have been taken into account yet
from parse_early_param().

Is /memreserve/ in FDT of any value here or is it all too late due to
old DTs?

Cheers
James

> +
> if (usermem) {
> pr_info("User-defined physical RAM map:\n");
> print_memory_map();
> --
> 2.11.0
>
>


Attachments:
(No filename) (2.50 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-16 14:06:40

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v6 10/15] MIPS: ingenic: Detect machtype from SoC compatible string

Hi James,

Le mer. 10 janv. 2018 ? 23:27, James Hogan <[email protected]> a
?crit :
> On Fri, Jan 05, 2018 at 07:25:08PM +0100, Paul Cercueil wrote:
>> Previously, the mips_machtype variable was always initialized
>> to MACH_INGENIC_JZ4740 even if running on different SoCs.
>>
>> Signed-off-by: Paul Cercueil <[email protected]>
>> ---
>> arch/mips/jz4740/prom.c | 1 -
>> arch/mips/jz4740/setup.c | 26 ++++++++++++++++++++++----
>> 2 files changed, 22 insertions(+), 5 deletions(-)
>>
>> v2: No change
>> v3: No change
>> v4: No change
>> v5: Use SPDX license identifier
>> v6: Init mips_machtype from DT compatible string instead of using
>> MIPS_MACHINE
>>
>> diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
>> index a62dd8e6ecf9..eb9f2f97bedb 100644
>> --- a/arch/mips/jz4740/prom.c
>> +++ b/arch/mips/jz4740/prom.c
>> @@ -25,7 +25,6 @@
>>
>> void __init prom_init(void)
>> {
>> - mips_machtype = MACH_INGENIC_JZ4740;
>> fw_init_cmdline();
>> }
>>
>> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
>> index 6d0152321819..cd89536fbba1 100644
>> --- a/arch/mips/jz4740/setup.c
>> +++ b/arch/mips/jz4740/setup.c
>> @@ -53,16 +53,30 @@ static void __init jz4740_detect_mem(void)
>> add_memory_region(0, size, BOOT_MEM_RAM);
>> }
>>
>> +static unsigned long __init get_board_mach_type(const void *fdt)
>> +{
>> + if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4780"))
>> + return MACH_INGENIC_JZ4780;
>> + if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4770"))
>> + return MACH_INGENIC_JZ4770;
>> +
>> + return MACH_INGENIC_JZ4740;
>> +}
>> +
>> void __init plat_mem_setup(void)
>> {
>> int offset;
>>
>> + if (!early_init_dt_scan(__dtb_start))
>> + return;
>> +
>> jz4740_reset_init();
>> - __dt_setup_arch(__dtb_start);
>
> Is it intentional that by removing this we no longer set the machine
> name, so it'll default to "unknown"? The commit message doesn't
> mention
> that change.
>
> Cheers
> James

You're right, thank you for spotting that. I'll send a revised version
ASAP.

-Paul

2018-01-16 14:10:28

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v6 13/15] MIPS: JZ4770: Workaround for corrupted DMA transfers

Hi James,

Le jeu. 11 janv. 2018 ? 0:20, James Hogan <[email protected]> a
?crit :
> On Fri, Jan 05, 2018 at 07:25:11PM +0100, Paul Cercueil wrote:
>> [...]
>> +
>> +/*
>> + * We have seen MMC DMA transfers read corrupted data from SDRAM
>> when a burst
>> + * interval ends at physical address 0x10000000. To avoid this
>> problem, we
>> + * remove the final page of low memory from the memory map.
>> + */
>> +void __init jz4770_reserve_unsafe_for_dma(void)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < boot_mem_map.nr_map; i++) {
>> + struct boot_mem_map_entry *entry = boot_mem_map.map + i;
>> +
>> + if (entry->type != BOOT_MEM_RAM)
>> + continue;
>> +
>> + if (entry->addr + entry->size != 0x10000000)
>> + continue;
>> +
>> + entry->size -= PAGE_SIZE;
>> + break;
>> + }
>> +}
>> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
>> index 85bc601e9a0d..5a2c20145aee 100644
>> --- a/arch/mips/kernel/setup.c
>> +++ b/arch/mips/kernel/setup.c
>> @@ -879,6 +879,14 @@ static void __init arch_mem_init(char
>> **cmdline_p)
>>
>> parse_early_param();
>>
>> +#ifdef CONFIG_MACH_JZ4770
>> + if (current_cpu_type() == CPU_JZRISC &&
>> + mips_machtype == MACH_INGENIC_JZ4770) {
>> + extern void __init jz4770_reserve_unsafe_for_dma(void);
>> + jz4770_reserve_unsafe_for_dma();
>> + }
>> +#endif
>
> Hmm, a little bit ugly. I'm guessing the plat_mem_setup() callback is
> too early since mem= parameters won't have been taken into account yet
> from parse_early_param().
>
> Is /memreserve/ in FDT of any value here or is it all too late due to
> old DTs?
>
> Cheers
> James

When trying to test whether or not /memreserve/ fixes the corruption
bug we were
having, we ran into the problem that we can't reproduce it anymore.
Sigh.

So I'll skip this patch in the next patchset version, and handle this
later if
it reappears.

-Paul

2018-01-16 15:48:14

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 00/14] JZ4770 and GCW0 patchset

Hi Ralf,

Here is the V7 of my JZ4770 and GCW0 patch series.

What changed from V6:
- In patch 10/14 I reverted a change that prevented the system
name/model from being correctly initialized
- The patch dealing with the MMC DMA hardware issue has been dropped,
since we couldn't reproduce the corruption issue. I can always send a
separate patch if we find a way to reliably trigger the bug.
- All the rest is untouched.

Greetings,
-Paul

2018-01-16 15:48:17

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 02/14] clk: ingenic: Fix recalc_rate for clocks with fixed divider

Previously, the clocks with a fixed divider would report their rate
as being the same as the one of their parent, independently of the
divider in use. This commit fixes this behaviour.

This went unnoticed as neither the jz4740 nor the jz4780 CGU code
have clocks with fixed dividers yet.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 2 ++
1 file changed, 2 insertions(+)

v2: No changes
v3: No changes
v4: No changes
v5: No changes
v6: No changes
v7: No changes

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index ab393637f7b0..a2e73a6d60fd 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -328,6 +328,8 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
div *= clk_info->div.div;

rate /= div;
+ } else if (clk_info->type & CGU_CLK_FIXDIV) {
+ rate /= clk_info->fixdiv.div;
}

return rate;
--
2.11.0

2018-01-16 15:48:22

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 05/14] dt-bindings: clock: Add jz4770-cgu.h header

This will be used from the devicetree bindings to specify the clocks
that should be obtained from the jz4770-cgu driver.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
include/dt-bindings/clock/jz4770-cgu.h | 58 ++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 include/dt-bindings/clock/jz4770-cgu.h

v3: New patch in this series
v4: No change
v5: Use SPDX license identifier
v6: No change
v7: No change

diff --git a/include/dt-bindings/clock/jz4770-cgu.h b/include/dt-bindings/clock/jz4770-cgu.h
new file mode 100644
index 000000000000..d68a7695a1f8
--- /dev/null
+++ b/include/dt-bindings/clock/jz4770-cgu.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides clock numbers for the ingenic,jz4770-cgu DT binding.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+
+#define JZ4770_CLK_EXT 0
+#define JZ4770_CLK_OSC32K 1
+#define JZ4770_CLK_PLL0 2
+#define JZ4770_CLK_PLL1 3
+#define JZ4770_CLK_CCLK 4
+#define JZ4770_CLK_H0CLK 5
+#define JZ4770_CLK_H1CLK 6
+#define JZ4770_CLK_H2CLK 7
+#define JZ4770_CLK_C1CLK 8
+#define JZ4770_CLK_PCLK 9
+#define JZ4770_CLK_MMC0_MUX 10
+#define JZ4770_CLK_MMC0 11
+#define JZ4770_CLK_MMC1_MUX 12
+#define JZ4770_CLK_MMC1 13
+#define JZ4770_CLK_MMC2_MUX 14
+#define JZ4770_CLK_MMC2 15
+#define JZ4770_CLK_CIM 16
+#define JZ4770_CLK_UHC 17
+#define JZ4770_CLK_GPU 18
+#define JZ4770_CLK_BCH 19
+#define JZ4770_CLK_LPCLK_MUX 20
+#define JZ4770_CLK_GPS 21
+#define JZ4770_CLK_SSI_MUX 22
+#define JZ4770_CLK_PCM_MUX 23
+#define JZ4770_CLK_I2S 24
+#define JZ4770_CLK_OTG 25
+#define JZ4770_CLK_SSI0 26
+#define JZ4770_CLK_SSI1 27
+#define JZ4770_CLK_SSI2 28
+#define JZ4770_CLK_PCM0 29
+#define JZ4770_CLK_PCM1 30
+#define JZ4770_CLK_DMA 31
+#define JZ4770_CLK_I2C0 32
+#define JZ4770_CLK_I2C1 33
+#define JZ4770_CLK_I2C2 34
+#define JZ4770_CLK_UART0 35
+#define JZ4770_CLK_UART1 36
+#define JZ4770_CLK_UART2 37
+#define JZ4770_CLK_UART3 38
+#define JZ4770_CLK_IPU 39
+#define JZ4770_CLK_ADC 40
+#define JZ4770_CLK_AIC 41
+#define JZ4770_CLK_AUX 42
+#define JZ4770_CLK_VPU 43
+#define JZ4770_CLK_UHC_PHY 44
+#define JZ4770_CLK_OTG_PHY 45
+#define JZ4770_CLK_EXT512 46
+#define JZ4770_CLK_RTC 47
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4770_CGU_H__ */
--
2.11.0

2018-01-16 15:48:24

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 04/14] clk: ingenic: Add code to enable/disable PLLs

This commit permits the PLLs to be dynamically enabled and disabled when
their children clocks are enabled and disabled.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 89 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 74 insertions(+), 15 deletions(-)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change
v7: No change

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 381c4a17a1fc..56a712c9075f 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -107,9 +107,6 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
if (bypass)
return parent_rate;

- if (!enable)
- return 0;
-
for (od = 0; od < pll_info->od_max; od++) {
if (pll_info->od_encoding[od] == od_enc)
break;
@@ -153,17 +150,25 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
return div_u64((u64)parent_rate * m, n * od);
}

-static long
-ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
- unsigned long *prate)
+static inline const struct ingenic_cgu_clk_info *to_clk_info(
+ struct ingenic_clk *ingenic_clk)
{
- struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;

clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);

+ return clk_info;
+}
+
+static long
+ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
+ unsigned long *prate)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+
return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
}

@@ -171,19 +176,14 @@ static int
ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long parent_rate)
{
- const unsigned timeout = 100;
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
- const struct ingenic_cgu_clk_info *clk_info;
- const struct ingenic_cgu_pll_info *pll_info;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long rate, flags;
- unsigned m, n, od, i;
+ unsigned int m, n, od;
u32 ctl;

- clk_info = &cgu->clock_info[ingenic_clk->idx];
- BUG_ON(clk_info->type != CGU_CLK_PLL);
- pll_info = &clk_info->pll;
-
rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
&m, &n, &od);
if (rate != req_rate)
@@ -202,6 +202,26 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;

+ writel(ctl, cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+
+ return 0;
+}
+
+static int ingenic_pll_enable(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ const unsigned int timeout = 100;
+ unsigned long flags;
+ unsigned int i;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+
ctl &= ~BIT(pll_info->bypass_bit);
ctl |= BIT(pll_info->enable_bit);

@@ -223,10 +243,48 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0;
}

+static void ingenic_pll_disable(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ unsigned long flags;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+
+ ctl &= ~BIT(pll_info->enable_bit);
+
+ writel(ctl, cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+}
+
+static int ingenic_pll_is_enabled(struct clk_hw *hw)
+{
+ struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+ struct ingenic_cgu *cgu = ingenic_clk->cgu;
+ const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+ const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+ unsigned long flags;
+ u32 ctl;
+
+ spin_lock_irqsave(&cgu->lock, flags);
+ ctl = readl(cgu->base + pll_info->reg);
+ spin_unlock_irqrestore(&cgu->lock, flags);
+
+ return !!(ctl & BIT(pll_info->enable_bit));
+}
+
static const struct clk_ops ingenic_pll_ops = {
.recalc_rate = ingenic_pll_recalc_rate,
.round_rate = ingenic_pll_round_rate,
.set_rate = ingenic_pll_set_rate,
+
+ .enable = ingenic_pll_enable,
+ .disable = ingenic_pll_disable,
+ .is_enabled = ingenic_pll_is_enabled,
};

/*
@@ -601,6 +659,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
}
} else if (caps & CGU_CLK_PLL) {
clk_init.ops = &ingenic_pll_ops;
+ clk_init.flags |= CLK_SET_RATE_GATE;

caps &= ~CGU_CLK_PLL;

--
2.11.0

2018-01-16 15:48:27

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 10/14] MIPS: ingenic: Detect machtype from SoC compatible string

Previously, the mips_machtype variable was always initialized
to MACH_INGENIC_JZ4740 even if running on different SoCs.

Signed-off-by: Paul Cercueil <[email protected]>
---
arch/mips/jz4740/prom.c | 1 -
arch/mips/jz4740/setup.c | 22 +++++++++++++++++++---
2 files changed, 19 insertions(+), 4 deletions(-)

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
v6: Init mips_machtype from DT compatible string instead of using
MIPS_MACHINE
v7: Fix system name not initialized

diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index a62dd8e6ecf9..eb9f2f97bedb 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -25,7 +25,6 @@

void __init prom_init(void)
{
- mips_machtype = MACH_INGENIC_JZ4740;
fw_init_cmdline();
}

diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 6d0152321819..afb40f8bce96 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -53,6 +53,16 @@ static void __init jz4740_detect_mem(void)
add_memory_region(0, size, BOOT_MEM_RAM);
}

+static unsigned long __init get_board_mach_type(const void *fdt)
+{
+ if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4780"))
+ return MACH_INGENIC_JZ4780;
+ if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4770"))
+ return MACH_INGENIC_JZ4770;
+
+ return MACH_INGENIC_JZ4740;
+}
+
void __init plat_mem_setup(void)
{
int offset;
@@ -63,6 +73,8 @@ void __init plat_mem_setup(void)
offset = fdt_path_offset(__dtb_start, "/memory");
if (offset < 0)
jz4740_detect_mem();
+
+ mips_machtype = get_board_mach_type(__dtb_start);
}

void __init device_tree_init(void)
@@ -75,10 +87,14 @@ void __init device_tree_init(void)

const char *get_system_type(void)
{
- if (IS_ENABLED(CONFIG_MACH_JZ4780))
+ switch (mips_machtype) {
+ case MACH_INGENIC_JZ4780:
return "JZ4780";
-
- return "JZ4740";
+ case MACH_INGENIC_JZ4770:
+ return "JZ4770";
+ default:
+ return "JZ4740";
+ }
}

void __init arch_init_irq(void)
--
2.11.0

2018-01-16 15:48:39

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 14/14] MIPS: ingenic: Initial GCW Zero support

The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
handheld game console, successfully kickstarted in ~2012, running Linux.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Mathieu Malaterre <[email protected]>
Acked-by: Philippe Ombredanne <[email protected]>
---
arch/mips/boot/dts/ingenic/Makefile | 1 +
arch/mips/boot/dts/ingenic/gcw0.dts | 62 +++++++++++++++++++++++++++++++++++++
arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
arch/mips/jz4740/Kconfig | 4 +++
4 files changed, 94 insertions(+)
create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
create mode 100644 arch/mips/configs/gcw0_defconfig

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
Drop custom CROSS_COMPILE from defconfig
v6: Add "model" property in devicetree
v7: No change

diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
index 6a31759839b4..5b1361a89e02 100644
--- a/arch/mips/boot/dts/ingenic/Makefile
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb
+dtb-$(CONFIG_JZ4770_GCW0) += gcw0.dtb
dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb

obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts b/arch/mips/boot/dts/ingenic/gcw0.dts
new file mode 100644
index 000000000000..35f0291e8d38
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/gcw0.dts
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "jz4770.dtsi"
+
+/ {
+ compatible = "gcw,zero", "ingenic,jz4770";
+ model = "GCW Zero";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial2:57600n8";
+ };
+
+ board {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ otg_phy: otg-phy {
+ compatible = "usb-nop-xceiv";
+ clocks = <&cgu JZ4770_CLK_OTG_PHY>;
+ clock-names = "main_clk";
+ };
+ };
+};
+
+&ext {
+ clock-frequency = <12000000>;
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&cgu {
+ /* Put high-speed peripherals under PLL1, such that we can change the
+ * PLL0 frequency on demand without having to suspend peripherals.
+ * We use a rate of 432 MHz, which is the least common multiple of
+ * 27 MHz (required by TV encoder) and 48 MHz (required by USB host).
+ */
+ assigned-clocks =
+ <&cgu JZ4770_CLK_PLL1>,
+ <&cgu JZ4770_CLK_UHC>;
+ assigned-clock-parents =
+ <0>,
+ <&cgu JZ4770_CLK_PLL1>;
+ assigned-clock-rates =
+ <432000000>;
+};
+
+&uhc {
+ /* The WiFi module is connected to the UHC. */
+ status = "okay";
+};
diff --git a/arch/mips/configs/gcw0_defconfig b/arch/mips/configs/gcw0_defconfig
new file mode 100644
index 000000000000..99ac1fa3b35f
--- /dev/null
+++ b/arch/mips/configs/gcw0_defconfig
@@ -0,0 +1,27 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4770_GCW0=y
+CONFIG_HIGHMEM=y
+# CONFIG_BOUNCE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_SECCOMP is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EMBEDDED=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_TMPFS=y
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 29a9361a2b77..4dd0c446ecec 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -8,6 +8,10 @@ config JZ4740_QI_LB60
bool "Qi Hardware Ben NanoNote"
select MACH_JZ4740

+config JZ4770_GCW0
+ bool "Game Consoles Worldwide GCW Zero"
+ select MACH_JZ4770
+
config JZ4780_CI20
bool "MIPS Creator CI20"
select MACH_JZ4780
--
2.11.0

2018-01-16 15:48:55

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 13/14] devicetree/bindings: Add GCW vendor prefix

Game Consoles Worldwide, mostly known under the acronym GCW, is the
creator of the GCW Zero open-source video game system.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)

v2: It's 'Game Consoles Worldwide', not 'Games Consoles Worldwide'
v3: No change
v4: No change
v5: No change
v6: No change
v7: No change

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0994bdd82cd3..f40f4da39937 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -123,6 +123,7 @@ focaltech FocalTech Systems Co.,Ltd
friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
fsl Freescale Semiconductor
fujitsu Fujitsu Ltd.
+gcw Game Consoles Worldwide
ge General Electric Company
geekbuying GeekBuying
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
--
2.11.0

2018-01-16 15:49:11

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 12/14] MIPS: JZ4770: Work around config2 misreporting associativity

From: Maarten ter Huurne <[email protected]>

According to config2, the associativity would be 5-ways, but the
documentation states 4-ways, which also matches the documented
L2 cache size of 256 kB.

Signed-off-by: Maarten ter Huurne <[email protected]>
Reviewed-by: James Hogan <[email protected]>
---
arch/mips/mm/sc-mips.c | 9 +++++++++
1 file changed, 9 insertions(+)

v2: No change
v3: No change
v4: Rebased on top of Linux 4.15-rc5
v5: No change
v6: No change
v7: No change

diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 548acb7f8557..394673991bab 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -16,6 +16,7 @@
#include <asm/mmu_context.h>
#include <asm/r4kcache.h>
#include <asm/mips-cps.h>
+#include <asm/bootinfo.h>

/*
* MIPS32/MIPS64 L2 cache handling
@@ -220,6 +221,14 @@ static inline int __init mips_sc_probe(void)
else
return 0;

+ /*
+ * According to config2 it would be 5-ways, but that is contradicted
+ * by all documentation.
+ */
+ if (current_cpu_type() == CPU_JZRISC &&
+ mips_machtype == MACH_INGENIC_JZ4770)
+ c->scache.ways = 4;
+
c->scache.waysize = c->scache.sets * c->scache.linesz;
c->scache.waybit = __ffs(c->scache.waysize);

--
2.11.0

2018-01-16 15:49:26

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 11/14] MIPS: ingenic: Initial JZ4770 support

Provide just enough bits (clocks, clocksource, uart) to allow a kernel
to boot on the JZ4770 SoC to a initramfs userspace.

Signed-off-by: Paul Cercueil <[email protected]>
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
---
arch/mips/boot/dts/ingenic/jz4770.dtsi | 212 +++++++++++++++++++++++++++++++++
arch/mips/jz4740/Kconfig | 6 +
arch/mips/jz4740/time.c | 2 +-
3 files changed, 219 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/boot/dts/ingenic/jz4770.dtsi

v2: No change
v3: No change
v4: No change
v5: Use SPDX license identifier
v6: No change
v7: No change

diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
new file mode 100644
index 000000000000..7c2804f3f5f1
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/clock/jz4770-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4770";
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-controller@10001000 {
+ compatible = "ingenic,jz4770-intc";
+ reg = <0x10001000 0x40>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ osc32k: osc32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4770-cgu@10000000 {
+ compatible = "ingenic,jz4770-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&osc32k>;
+ clock-names = "ext", "osc32k";
+
+ #clock-cells = <1>;
+ };
+
+ pinctrl: pin-controller@10010000 {
+ compatible = "ingenic,jz4770-pinctrl";
+ reg = <0x10010000 0x600>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpa: gpio@0 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <0>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 0 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <17>;
+ };
+
+ gpb: gpio@1 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <1>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 32 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ };
+
+ gpc: gpio@2 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <2>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 64 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <15>;
+ };
+
+ gpd: gpio@3 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <3>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 96 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <14>;
+ };
+
+ gpe: gpio@4 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <4>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 128 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <13>;
+ };
+
+ gpf: gpio@5 {
+ compatible = "ingenic,jz4770-gpio";
+ reg = <5>;
+
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 160 32>;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <12>;
+ };
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10030000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART0>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <5>;
+
+ status = "disabled";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10031000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART1>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <4>;
+
+ status = "disabled";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10032000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART2>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <3>;
+
+ status = "disabled";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4770-uart";
+ reg = <0x10033000 0x100>;
+
+ clocks = <&ext>, <&cgu JZ4770_CLK_UART3>;
+ clock-names = "baud", "module";
+
+ interrupt-parent = <&intc>;
+ interrupts = <2>;
+
+ status = "disabled";
+ };
+
+ uhc: uhc@13430000 {
+ compatible = "generic-ohci";
+ reg = <0x13430000 0x1000>;
+
+ clocks = <&cgu JZ4770_CLK_UHC>, <&cgu JZ4770_CLK_UHC_PHY>;
+ assigned-clocks = <&cgu JZ4770_CLK_UHC>;
+ assigned-clock-rates = <48000000>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <20>;
+
+ status = "disabled";
+ };
+};
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 643af2012e14..29a9361a2b77 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -18,6 +18,12 @@ config MACH_JZ4740
bool
select SYS_HAS_CPU_MIPS32_R1

+config MACH_JZ4770
+ bool
+ select MIPS_CPU_SCACHE
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_HIGHMEM
+
config MACH_JZ4780
bool
select MIPS_CPU_SCACHE
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index bb1ad5119da4..2ca9160f642a 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
#ifdef CONFIG_MACH_JZ4740
.irq = JZ4740_IRQ_TCU0,
#endif
-#ifdef CONFIG_MACH_JZ4780
+#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
.irq = JZ4780_IRQ_TCU2,
#endif
};
--
2.11.0

2018-01-16 15:49:46

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 09/14] MIPS: platform: add machtype IDs for more Ingenic SoCs

Add a machtype ID for the JZ4780 SoC, which was missing, and one for the
newly supported JZ4770 SoC.

Signed-off-by: Paul Cercueil <[email protected]>
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
Reviewed-by: James Hogan <[email protected]>
---
arch/mips/include/asm/bootinfo.h | 2 ++
1 file changed, 2 insertions(+)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change
v7: No change

diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index e26a093bb17a..a301a8f4bc66 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -79,6 +79,8 @@ enum loongson_machine_type {
*/
#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */
#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */
+#define MACH_INGENIC_JZ4770 2 /* JZ4770 SOC */
+#define MACH_INGENIC_JZ4780 3 /* JZ4780 SOC */

extern char *system_type;
const char *get_system_type(void);
--
2.11.0

2018-01-16 15:50:07

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 08/14] MIPS: ingenic: Use common cmdline handling code

From: Paul Burton <[email protected]>

jz4740_init_cmdline appends all arguments from argv (in fw_arg1) to
arcs_cmdline, up to argc (in fw_arg0). The common code in
fw_init_cmdline will do the exact same thing when run on a system where
fw_arg0 isn't a pointer to kseg0 (it'll also set _fw_envp but we don't
use it). Remove the custom implementation & use the generic code.

Signed-off-by: Paul Burton <[email protected]>
Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
Reviewed-by: James Hogan <[email protected]>
---
arch/mips/jz4740/prom.c | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)

v2: No change
v3: No change
v4: No change
v5: No change
v6: Update Paul Burton's email address
v7: No change

diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index 47e857194ce6..a62dd8e6ecf9 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -20,33 +20,13 @@
#include <linux/serial_reg.h>

#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
#include <asm/mach-jz4740/base.h>

-static __init void jz4740_init_cmdline(int argc, char *argv[])
-{
- unsigned int count = COMMAND_LINE_SIZE - 1;
- int i;
- char *dst = &(arcs_cmdline[0]);
- char *src;
-
- for (i = 1; i < argc && count; ++i) {
- src = argv[i];
- while (*src && count) {
- *dst++ = *src++;
- --count;
- }
- *dst++ = ' ';
- }
- if (i > 1)
- --dst;
-
- *dst = 0;
-}
-
void __init prom_init(void)
{
- jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
mips_machtype = MACH_INGENIC_JZ4740;
+ fw_init_cmdline();
}

void __init prom_free_prom_memory(void)
--
2.11.0

2018-01-16 15:50:22

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 06/14] clk: Add Ingenic jz4770 CGU driver

Add support for the clocks provided by the CGU in the Ingenic JZ4770
SoC.

Signed-off-by: Paul Cercueil <[email protected]>
Signed-off-by: Maarten ter Huurne <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/Makefile | 1 +
drivers/clk/ingenic/jz4770-cgu.c | 483 +++++++++++++++++++++++++++++++++++++++
2 files changed, 484 insertions(+)
create mode 100644 drivers/clk/ingenic/jz4770-cgu.c

v2: Make structures static const
v3: <dt-bindings/clock/jz4770-cgu.h> is now added in a separate patch
v4: No change
v5: Use SPDX license identifier
v6: No change
v7: No change

diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index cd47b0664c2b..1456e4cdb562 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,3 +1,4 @@
obj-y += cgu.o
obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
+obj-$(CONFIG_MACH_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o
diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c
new file mode 100644
index 000000000000..c78d369b9403
--- /dev/null
+++ b/drivers/clk/ingenic/jz4770-cgu.c
@@ -0,0 +1,483 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ4770 SoC CGU driver
+ * Copyright 2018, Paul Cercueil <[email protected]>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/jz4770-cgu.h>
+#include "cgu.h"
+
+/*
+ * CPM registers offset address definition
+ */
+#define CGU_REG_CPCCR 0x00
+#define CGU_REG_LCR 0x04
+#define CGU_REG_CPPCR0 0x10
+#define CGU_REG_CLKGR0 0x20
+#define CGU_REG_OPCR 0x24
+#define CGU_REG_CLKGR1 0x28
+#define CGU_REG_CPPCR1 0x30
+#define CGU_REG_USBPCR1 0x48
+#define CGU_REG_USBCDR 0x50
+#define CGU_REG_I2SCDR 0x60
+#define CGU_REG_LPCDR 0x64
+#define CGU_REG_MSC0CDR 0x68
+#define CGU_REG_UHCCDR 0x6c
+#define CGU_REG_SSICDR 0x74
+#define CGU_REG_CIMCDR 0x7c
+#define CGU_REG_GPSCDR 0x80
+#define CGU_REG_PCMCDR 0x84
+#define CGU_REG_GPUCDR 0x88
+#define CGU_REG_MSC1CDR 0xA4
+#define CGU_REG_MSC2CDR 0xA8
+#define CGU_REG_BCHCDR 0xAC
+
+/* bits within the LCR register */
+#define LCR_LPM BIT(0) /* Low Power Mode */
+
+/* bits within the OPCR register */
+#define OPCR_SPENDH BIT(5) /* UHC PHY suspend */
+#define OPCR_SPENDN BIT(7) /* OTG PHY suspend */
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_UHC_POWER BIT(5) /* UHC PHY power down */
+
+static struct ingenic_cgu *cgu;
+
+static int jz4770_uhc_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
+ writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
+ return 0;
+}
+
+static void jz4770_uhc_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
+ writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
+}
+
+static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1;
+
+ return !(readl(reg_opcr) & OPCR_SPENDH) &&
+ (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
+}
+
+static const struct clk_ops jz4770_uhc_phy_ops = {
+ .enable = jz4770_uhc_phy_enable,
+ .disable = jz4770_uhc_phy_disable,
+ .is_enabled = jz4770_uhc_phy_is_enabled,
+};
+
+static int jz4770_otg_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ writel(readl(reg_opcr) | OPCR_SPENDN, reg_opcr);
+
+ /* Wait for the clock to be stable */
+ udelay(50);
+ return 0;
+}
+
+static void jz4770_otg_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDN, reg_opcr);
+}
+
+static int jz4770_otg_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+
+ return !!(readl(reg_opcr) & OPCR_SPENDN);
+}
+
+static const struct clk_ops jz4770_otg_phy_ops = {
+ .enable = jz4770_otg_phy_enable,
+ .disable = jz4770_otg_phy_disable,
+ .is_enabled = jz4770_otg_phy_is_enabled,
+};
+
+static const s8 pll_od_encoding[8] = {
+ 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+};
+
+static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
+
+ /* External clocks */
+
+ [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
+ [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
+
+ /* PLLs */
+
+ [JZ4770_CLK_PLL0] = {
+ "pll0", CGU_CLK_PLL,
+ .parents = { JZ4770_CLK_EXT },
+ .pll = {
+ .reg = CGU_REG_CPPCR0,
+ .m_shift = 24,
+ .m_bits = 7,
+ .m_offset = 1,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 1,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 8,
+ .od_encoding = pll_od_encoding,
+ .bypass_bit = 9,
+ .enable_bit = 8,
+ .stable_bit = 10,
+ },
+ },
+
+ [JZ4770_CLK_PLL1] = {
+ /* TODO: PLL1 can depend on PLL0 */
+ "pll1", CGU_CLK_PLL,
+ .parents = { JZ4770_CLK_EXT },
+ .pll = {
+ .reg = CGU_REG_CPPCR1,
+ .m_shift = 24,
+ .m_bits = 7,
+ .m_offset = 1,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 1,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 8,
+ .od_encoding = pll_od_encoding,
+ .enable_bit = 7,
+ .stable_bit = 6,
+ .no_bypass_bit = true,
+ },
+ },
+
+ /* Main clocks */
+
+ [JZ4770_CLK_CCLK] = {
+ "cclk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_H0CLK] = {
+ "h0clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_H1CLK] = {
+ "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1 },
+ .gate = { CGU_REG_LCR, 30 },
+ },
+ [JZ4770_CLK_H2CLK] = {
+ "h2clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_C1CLK] = {
+ "c1clk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
+ },
+ [JZ4770_CLK_PCLK] = {
+ "pclk", CGU_CLK_DIV,
+ .parents = { JZ4770_CLK_PLL0, },
+ .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
+ },
+
+ /* Those divided clocks can connect to PLL0 or PLL1 */
+
+ [JZ4770_CLK_MMC0_MUX] = {
+ "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC0CDR, 30, 1 },
+ .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC0CDR, 31 },
+ },
+ [JZ4770_CLK_MMC1_MUX] = {
+ "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC1CDR, 30, 1 },
+ .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC1CDR, 31 },
+ },
+ [JZ4770_CLK_MMC2_MUX] = {
+ "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_MSC2CDR, 30, 1 },
+ .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
+ .gate = { CGU_REG_MSC2CDR, 31 },
+ },
+ [JZ4770_CLK_CIM] = {
+ "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_CIMCDR, 31, 1 },
+ .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 26 },
+ },
+ [JZ4770_CLK_UHC] = {
+ "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_UHCCDR, 29, 1 },
+ .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 24 },
+ },
+ [JZ4770_CLK_GPU] = {
+ "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
+ .mux = { CGU_REG_GPUCDR, 31, 1 },
+ .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 9 },
+ },
+ [JZ4770_CLK_BCH] = {
+ "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_BCHCDR, 31, 1 },
+ .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 1 },
+ },
+ [JZ4770_CLK_LPCLK_MUX] = {
+ "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_LPCDR, 29, 1 },
+ .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 28 },
+ },
+ [JZ4770_CLK_GPS] = {
+ "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+ .mux = { CGU_REG_GPSCDR, 31, 1 },
+ .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 22 },
+ },
+
+ /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
+
+ [JZ4770_CLK_SSI_MUX] = {
+ "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_SSICDR, 30, 2 },
+ .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
+ },
+ [JZ4770_CLK_PCM_MUX] = {
+ "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_PCMCDR, 30, 2 },
+ .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
+ },
+ [JZ4770_CLK_I2S] = {
+ "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_I2SCDR, 30, 2 },
+ .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 13 },
+ },
+ [JZ4770_CLK_OTG] = {
+ "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT, -1,
+ JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+ .mux = { CGU_REG_USBCDR, 30, 2 },
+ .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 2 },
+ },
+
+ /* Gate-only clocks */
+
+ [JZ4770_CLK_SSI0] = {
+ "ssi0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 4 },
+ },
+ [JZ4770_CLK_SSI1] = {
+ "ssi1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 19 },
+ },
+ [JZ4770_CLK_SSI2] = {
+ "ssi2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_SSI_MUX, },
+ .gate = { CGU_REG_CLKGR0, 20 },
+ },
+ [JZ4770_CLK_PCM0] = {
+ "pcm0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PCM_MUX, },
+ .gate = { CGU_REG_CLKGR1, 8 },
+ },
+ [JZ4770_CLK_PCM1] = {
+ "pcm1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_PCM_MUX, },
+ .gate = { CGU_REG_CLKGR1, 10 },
+ },
+ [JZ4770_CLK_DMA] = {
+ "dma", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H2CLK, },
+ .gate = { CGU_REG_CLKGR0, 21 },
+ },
+ [JZ4770_CLK_I2C0] = {
+ "i2c0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 5 },
+ },
+ [JZ4770_CLK_I2C1] = {
+ "i2c1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 6 },
+ },
+ [JZ4770_CLK_I2C2] = {
+ "i2c2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR1, 15 },
+ },
+ [JZ4770_CLK_UART0] = {
+ "uart0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 15 },
+ },
+ [JZ4770_CLK_UART1] = {
+ "uart1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 16 },
+ },
+ [JZ4770_CLK_UART2] = {
+ "uart2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 17 },
+ },
+ [JZ4770_CLK_UART3] = {
+ "uart3", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 18 },
+ },
+ [JZ4770_CLK_IPU] = {
+ "ipu", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H0CLK, },
+ .gate = { CGU_REG_CLKGR0, 29 },
+ },
+ [JZ4770_CLK_ADC] = {
+ "adc", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 14 },
+ },
+ [JZ4770_CLK_AIC] = {
+ "aic", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR0, 8 },
+ },
+ [JZ4770_CLK_AUX] = {
+ "aux", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_C1CLK, },
+ .gate = { CGU_REG_CLKGR1, 14 },
+ },
+ [JZ4770_CLK_VPU] = {
+ "vpu", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR1, 7 },
+ },
+ [JZ4770_CLK_MMC0] = {
+ "mmc0", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC0_MUX, },
+ .gate = { CGU_REG_CLKGR0, 3 },
+ },
+ [JZ4770_CLK_MMC1] = {
+ "mmc1", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC1_MUX, },
+ .gate = { CGU_REG_CLKGR0, 11 },
+ },
+ [JZ4770_CLK_MMC2] = {
+ "mmc2", CGU_CLK_GATE,
+ .parents = { JZ4770_CLK_MMC2_MUX, },
+ .gate = { CGU_REG_CLKGR0, 12 },
+ },
+
+ /* Custom clocks */
+
+ [JZ4770_CLK_UHC_PHY] = {
+ "uhc_phy", CGU_CLK_CUSTOM,
+ .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
+ .custom = { &jz4770_uhc_phy_ops },
+ },
+ [JZ4770_CLK_OTG_PHY] = {
+ "usb_phy", CGU_CLK_CUSTOM,
+ .parents = { JZ4770_CLK_OTG, -1, -1, -1 },
+ .custom = { &jz4770_otg_phy_ops },
+ },
+
+ [JZ4770_CLK_EXT512] = {
+ "ext/512", CGU_CLK_FIXDIV,
+ .parents = { JZ4770_CLK_EXT },
+ .fixdiv = { 512 },
+ },
+
+ [JZ4770_CLK_RTC] = {
+ "rtc", CGU_CLK_MUX,
+ .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
+ .mux = { CGU_REG_OPCR, 2, 1},
+ },
+};
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+static int jz4770_cgu_pm_suspend(void)
+{
+ u32 val;
+
+ val = readl(cgu->base + CGU_REG_LCR);
+ writel(val | LCR_LPM, cgu->base + CGU_REG_LCR);
+ return 0;
+}
+
+static void jz4770_cgu_pm_resume(void)
+{
+ u32 val;
+
+ val = readl(cgu->base + CGU_REG_LCR);
+ writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR);
+}
+
+static struct syscore_ops jz4770_cgu_pm_ops = {
+ .suspend = jz4770_cgu_pm_suspend,
+ .resume = jz4770_cgu_pm_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static void __init jz4770_cgu_init(struct device_node *np)
+{
+ int retval;
+
+ cgu = ingenic_cgu_new(jz4770_cgu_clocks,
+ ARRAY_SIZE(jz4770_cgu_clocks), np);
+ if (!cgu)
+ pr_err("%s: failed to initialise CGU\n", __func__);
+
+ retval = ingenic_cgu_register_clocks(cgu);
+ if (retval)
+ pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+ register_syscore_ops(&jz4770_cgu_pm_ops);
+#endif
+}
+
+/* We only probe via devicetree, no need for a platform driver */
+CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
--
2.11.0

2018-01-16 15:50:21

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 07/14] MIPS: Setup boot_command_line before plat_mem_setup

From: Paul Burton <[email protected]>

Platforms using DT will typically call __dt_setup_arch from
plat_mem_setup. This in turn calls early_init_dt_scan. When
CONFIG_CMDLINE is set, this leads to its value being copied into
boot_command_line by early_init_dt_scan_chosen. If this happens before
the code setting up boot_command_line in arch_mem_init runs, that code
will go on to append CONFIG_CMDLINE (via builtin_cmdline) to
boot_command_line again, duplicating it. For some command line
parameters (eg. earlycon) this can be a problem. Set up
boot_command_line before early_init_dt_scan_chosen gets called such that
it will not write CONFIG_CMDLINE in this scenario & the arguments aren't
duplicated.

Signed-off-by: Paul Burton <[email protected]>
Acked-by: Mathieu Malaterre <[email protected]>
---
arch/mips/kernel/setup.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)

v2: New patch in this series
v3: No change
v4: No change
v5: No change
v6: Update Paul Burton's email address
v7: No change

diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 702c678de116..85bc601e9a0d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -826,25 +826,6 @@ static void __init arch_mem_init(char **cmdline_p)
struct memblock_region *reg;
extern void plat_mem_setup(void);

- /* call board setup routine */
- plat_mem_setup();
-
- /*
- * Make sure all kernel memory is in the maps. The "UP" and
- * "DOWN" are opposite for initdata since if it crosses over
- * into another memory section you don't want that to be
- * freed when the initdata is freed.
- */
- arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
- PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
- BOOT_MEM_RAM);
- arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
- PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
- BOOT_MEM_INIT_RAM);
-
- pr_info("Determined physical RAM map:\n");
- print_memory_map();
-
#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
@@ -872,6 +853,26 @@ static void __init arch_mem_init(char **cmdline_p)
}
#endif
#endif
+
+ /* call board setup routine */
+ plat_mem_setup();
+
+ /*
+ * Make sure all kernel memory is in the maps. The "UP" and
+ * "DOWN" are opposite for initdata since if it crosses over
+ * into another memory section you don't want that to be
+ * freed when the initdata is freed.
+ */
+ arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
+ PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+ arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
+ PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
+ BOOT_MEM_INIT_RAM);
+
+ pr_info("Determined physical RAM map:\n");
+ print_memory_map();
+
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);

*cmdline_p = command_line;
--
2.11.0

2018-01-16 15:50:53

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 03/14] clk: ingenic: support PLLs with no bypass bit

The second PLL of the JZ4770 does not have a bypass bit.
This commit makes it possible to support it with the current common CGU
code.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.c | 3 ++-
drivers/clk/ingenic/cgu.h | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)

v2: No change
v3: No change
v4: No change
v5: No change
v6: No change
v7: No change

diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index a2e73a6d60fd..381c4a17a1fc 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -100,7 +100,8 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0);
- bypass = !!(ctl & BIT(pll_info->bypass_bit));
+ bypass = !pll_info->no_bypass_bit &&
+ !!(ctl & BIT(pll_info->bypass_bit));
enable = !!(ctl & BIT(pll_info->enable_bit));

if (bypass)
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index f1527cf75b3f..9da34910bd80 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -48,6 +48,7 @@
* @bypass_bit: the index of the bypass bit in the PLL control register
* @enable_bit: the index of the enable bit in the PLL control register
* @stable_bit: the index of the stable bit in the PLL control register
+ * @no_bypass_bit: if set, the PLL has no bypass functionality
*/
struct ingenic_cgu_pll_info {
unsigned reg;
@@ -58,6 +59,7 @@ struct ingenic_cgu_pll_info {
u8 bypass_bit;
u8 enable_bit;
u8 stable_bit;
+ bool no_bypass_bit;
};

/**
--
2.11.0

2018-01-16 15:51:17

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v7 01/14] clk: ingenic: Use const pointer to clk_ops in struct

The CGU common code does not modify the pointed clk_ops structure, so it
should be marked as const.

Signed-off-by: Paul Cercueil <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
---
drivers/clk/ingenic/cgu.h | 2 +-
drivers/clk/ingenic/jz4780-cgu.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

v2: New patch in this series
v3: No change
v4: No change
v5: No change
v6: No change
v7: No change

diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index e78b586536ea..f1527cf75b3f 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -120,7 +120,7 @@ struct ingenic_cgu_gate_info {
* @clk_ops: custom clock operation callbacks
*/
struct ingenic_cgu_custom_info {
- struct clk_ops *clk_ops;
+ const struct clk_ops *clk_ops;
};

/**
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
index ac3585ed8228..6427be117ff1 100644
--- a/drivers/clk/ingenic/jz4780-cgu.c
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -203,7 +203,7 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0;
}

-static struct clk_ops jz4780_otg_phy_ops = {
+static const struct clk_ops jz4780_otg_phy_ops = {
.get_parent = jz4780_otg_phy_get_parent,
.set_parent = jz4780_otg_phy_set_parent,

--
2.11.0

2018-01-16 22:06:37

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v7 10/14] MIPS: ingenic: Detect machtype from SoC compatible string

On Tue, Jan 16, 2018 at 04:48:00PM +0100, Paul Cercueil wrote:
> Previously, the mips_machtype variable was always initialized
> to MACH_INGENIC_JZ4740 even if running on different SoCs.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> ---
> arch/mips/jz4740/prom.c | 1 -
> arch/mips/jz4740/setup.c | 22 +++++++++++++++++++---
> 2 files changed, 19 insertions(+), 4 deletions(-)
>
> v2: No change
> v3: No change
> v4: No change
> v5: Use SPDX license identifier
> v6: Init mips_machtype from DT compatible string instead of using
> MIPS_MACHINE
> v7: Fix system name not initialized
>
> diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
> index a62dd8e6ecf9..eb9f2f97bedb 100644
> --- a/arch/mips/jz4740/prom.c
> +++ b/arch/mips/jz4740/prom.c
> @@ -25,7 +25,6 @@
>
> void __init prom_init(void)
> {
> - mips_machtype = MACH_INGENIC_JZ4740;
> fw_init_cmdline();
> }
>
> diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
> index 6d0152321819..afb40f8bce96 100644
> --- a/arch/mips/jz4740/setup.c
> +++ b/arch/mips/jz4740/setup.c
> @@ -53,6 +53,16 @@ static void __init jz4740_detect_mem(void)
> add_memory_region(0, size, BOOT_MEM_RAM);
> }
>
> +static unsigned long __init get_board_mach_type(const void *fdt)
> +{
> + if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4780"))
> + return MACH_INGENIC_JZ4780;
> + if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4770"))
> + return MACH_INGENIC_JZ4770;

Based on the assumption that fdt will always be non-NULL since commit
ffb1843d059c ("MIPS: JZ4740: require & include DT"):

Reviewed-by: James Hogan <[email protected]>

Cheers
James

> +
> + return MACH_INGENIC_JZ4740;
> +}
> +
> void __init plat_mem_setup(void)
> {
> int offset;
> @@ -63,6 +73,8 @@ void __init plat_mem_setup(void)
> offset = fdt_path_offset(__dtb_start, "/memory");
> if (offset < 0)
> jz4740_detect_mem();
> +
> + mips_machtype = get_board_mach_type(__dtb_start);
> }
>
> void __init device_tree_init(void)
> @@ -75,10 +87,14 @@ void __init device_tree_init(void)
>
> const char *get_system_type(void)
> {
> - if (IS_ENABLED(CONFIG_MACH_JZ4780))
> + switch (mips_machtype) {
> + case MACH_INGENIC_JZ4780:
> return "JZ4780";
> -
> - return "JZ4740";
> + case MACH_INGENIC_JZ4770:
> + return "JZ4770";
> + default:
> + return "JZ4740";
> + }
> }
>
> void __init arch_init_irq(void)
> --
> 2.11.0
>


Attachments:
(No filename) (2.37 kB)
signature.asc (833.00 B)
Digital signature
Download all attachments

2018-01-17 21:30:29

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v7 11/14] MIPS: ingenic: Initial JZ4770 support

On Tue, Jan 16, 2018 at 04:48:01PM +0100, Paul Cercueil wrote:
> Provide just enough bits (clocks, clocksource, uart) to allow a kernel
> to boot on the JZ4770 SoC to a initramfs userspace.
>
> Signed-off-by: Paul Cercueil <[email protected]>
> Reviewed-by: PrasannaKumar Muralidharan <[email protected]>


> diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
> index bb1ad5119da4..2ca9160f642a 100644
> --- a/arch/mips/jz4740/time.c
> +++ b/arch/mips/jz4740/time.c
> @@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
> #ifdef CONFIG_MACH_JZ4740
> .irq = JZ4740_IRQ_TCU0,
> #endif
> -#ifdef CONFIG_MACH_JZ4780
> +#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
> .irq = JZ4780_IRQ_TCU2,
> #endif
> };
> --
> 2.11.0
>

MACH_INGENIC selects SYS_SUPPORTS_ZBOOT_UART16550, so I wonder whether
arch/mips/boot/compressed/uart-16550.c needs updating for JZ4770 like
commit ba9e72c2290f ("MIPS: Fix build with DEBUG_ZBOOT and MACH_JZ4780")
does for JZ4780.

Otherwise the non-DT bits look reasonable (I've not really looked
properly at the DT):
Reviewed-by: James Hogan <[email protected]>

Cheers
James


Attachments:
(No filename) (1.18 kB)
signature.asc (849.00 B)
Digital signature
Download all attachments

2018-01-18 17:15:58

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v7 11/14] MIPS: ingenic: Initial JZ4770 support

Hi James,

Le mer. 17 janv. 2018 ? 22:28, James Hogan <[email protected]> a
?crit :
> On Tue, Jan 16, 2018 at 04:48:01PM +0100, Paul Cercueil wrote:
>> Provide just enough bits (clocks, clocksource, uart) to allow a
>> kernel
>> to boot on the JZ4770 SoC to a initramfs userspace.
>>
>> Signed-off-by: Paul Cercueil <[email protected]>
>> Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
>
>
>> diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
>> index bb1ad5119da4..2ca9160f642a 100644
>> --- a/arch/mips/jz4740/time.c
>> +++ b/arch/mips/jz4740/time.c
>> @@ -113,7 +113,7 @@ static struct clock_event_device
>> jz4740_clockevent = {
>> #ifdef CONFIG_MACH_JZ4740
>> .irq = JZ4740_IRQ_TCU0,
>> #endif
>> -#ifdef CONFIG_MACH_JZ4780
>> +#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
>> .irq = JZ4780_IRQ_TCU2,
>> #endif
>> };
>> --
>> 2.11.0
>>
>
> MACH_INGENIC selects SYS_SUPPORTS_ZBOOT_UART16550, so I wonder whether
> arch/mips/boot/compressed/uart-16550.c needs updating for JZ4770 like
> commit ba9e72c2290f ("MIPS: Fix build with DEBUG_ZBOOT and
> MACH_JZ4780")
> does for JZ4780.
>
> Otherwise the non-DT bits look reasonable (I've not really looked
> properly at the DT):
> Reviewed-by: James Hogan <[email protected]>
>
> Cheers
> James

I will fix it in a separate patch, if you don't mind.

-Paul


2018-01-18 20:34:25

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v7 11/14] MIPS: ingenic: Initial JZ4770 support

On Thu, Jan 18, 2018 at 06:14:30PM +0100, Paul Cercueil wrote:
> Hi James,
>
> Le mer. 17 janv. 2018 à 22:28, James Hogan <[email protected]> a
> écrit :
> > On Tue, Jan 16, 2018 at 04:48:01PM +0100, Paul Cercueil wrote:
> >> Provide just enough bits (clocks, clocksource, uart) to allow a
> >> kernel
> >> to boot on the JZ4770 SoC to a initramfs userspace.
> >>
> >> Signed-off-by: Paul Cercueil <[email protected]>
> >> Reviewed-by: PrasannaKumar Muralidharan <[email protected]>
> >
> >
> >> diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
> >> index bb1ad5119da4..2ca9160f642a 100644
> >> --- a/arch/mips/jz4740/time.c
> >> +++ b/arch/mips/jz4740/time.c
> >> @@ -113,7 +113,7 @@ static struct clock_event_device
> >> jz4740_clockevent = {
> >> #ifdef CONFIG_MACH_JZ4740
> >> .irq = JZ4740_IRQ_TCU0,
> >> #endif
> >> -#ifdef CONFIG_MACH_JZ4780
> >> +#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
> >> .irq = JZ4780_IRQ_TCU2,
> >> #endif
> >> };
> >> --
> >> 2.11.0
> >>
> >
> > MACH_INGENIC selects SYS_SUPPORTS_ZBOOT_UART16550, so I wonder whether
> > arch/mips/boot/compressed/uart-16550.c needs updating for JZ4770 like
> > commit ba9e72c2290f ("MIPS: Fix build with DEBUG_ZBOOT and
> > MACH_JZ4780")
> > does for JZ4780.
> >
> > Otherwise the non-DT bits look reasonable (I've not really looked
> > properly at the DT):
> > Reviewed-by: James Hogan <[email protected]>
> >
> > Cheers
> > James
>
> I will fix it in a separate patch, if you don't mind.

Sure,

Cheers
James


Attachments:
(No filename) (1.58 kB)
signature.asc (849.00 B)
Digital signature
Download all attachments

2018-01-23 10:32:32

by Philippe Ombredanne

[permalink] [raw]
Subject: Re: [PATCH v6 15/15] MIPS: ingenic: Initial GCW Zero support

Paul:

On Wed, Jan 10, 2018 at 11:59 PM, Paul Cercueil <[email protected]> wrote:
> Hi Philippe,
>
> Le dim. 7 janv. 2018 à 17:18, Philippe Ombredanne <[email protected]> a
> écrit :
>>
>> On Fri, Jan 5, 2018 at 7:25 PM, Paul Cercueil <[email protected]>
>> wrote:
>>>
>>> The GCW Zero (http://www.gcw-zero.com) is a retro-gaming focused
>>> handheld game console, successfully kickstarted in ~2012, running Linux.
>>>
>>> Signed-off-by: Paul Cercueil <[email protected]>
>>> Acked-by: Mathieu Malaterre <[email protected]>
>>> ---
>>> arch/mips/boot/dts/ingenic/Makefile | 1 +
>>> arch/mips/boot/dts/ingenic/gcw0.dts | 62
>>> +++++++++++++++++++++++++++++++++++++
>>> arch/mips/configs/gcw0_defconfig | 27 ++++++++++++++++
>>> arch/mips/jz4740/Kconfig | 4 +++
>>> 4 files changed, 94 insertions(+)
>>> create mode 100644 arch/mips/boot/dts/ingenic/gcw0.dts
>>> create mode 100644 arch/mips/configs/gcw0_defconfig
>>>
>>> v2: No change
>>> v3: No change
>>> v4: No change
>>> v5: Use SPDX license identifier
>>> Drop custom CROSS_COMPILE from defconfig
>>> v6: Add "model" property in devicetree
>>
>>
>> For the use of SPDX tags for the whole patch set: thank you!
>>
>> Acked-by: Philippe Ombredanne <[email protected]>
>
>
> Is your Acked-by for the whole patchset? Or just this one patch?

Sorry for the late reply!
This is for the whole patchset for your use of SPDX tags.

--
Cordially
Philippe Ombredanne

2018-02-01 15:32:52

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v7 00/14] JZ4770 and GCW0 patchset

On Tue, Jan 16, 2018 at 04:47:50PM +0100, Paul Cercueil wrote:
> Hi Ralf,
>
> Here is the V7 of my JZ4770 and GCW0 patch series.
>
> What changed from V6:
> - In patch 10/14 I reverted a change that prevented the system
> name/model from being correctly initialized
> - The patch dealing with the MMC DMA hardware issue has been dropped,
> since we couldn't reproduce the corruption issue. I can always send a
> separate patch if we find a way to reliably trigger the bug.
> - All the rest is untouched.

I've applied to my 4.16 branch.

Thanks
James

>
> Greetings,
> -Paul
>
>


Attachments:
(No filename) (613.00 B)
signature.asc (849.00 B)
Digital signature
Download all attachments