Re: [PATCH v3 2/5] clk: sunxi-ng: add support for PRCM CCUs

From: Icenowy Zheng
Date: Wed Mar 29 2017 - 11:31:52 EST


On Wed, 29 Mar 2017 18:42:43 +0800
Icenowy Zheng <icenowy@xxxxxxx> wrote:

> From: Icenowy Zheng <icenowy@xxxxxxxx>
>
> SoCs after A31 has a clock controller module in the PRCM part.
>
> Support the clock controller module on H3/5 and A64 now.
>
> Signed-off-by: Icenowy Zheng <icenowy@xxxxxxxx>
> ---
> Changes in v3:
> - Change osc32000 mux to iosc, as its frequency varies between SoCs.
> (And none of them is really 32000Hz)
> Changes in v2:
> - Replace all sun6i to sun8i, as this driver currently doesn't really
> support sun6i(A31).
> - Add osc32000 mux for ar100 clk. (Note: the frequency is proven to
> be wrong during the development of PATCH v3).
> - Rename some clocks.
> - Add gate of TWD (Trusted Watchdog). There's no reset for TWD.
> - Removed reset of PIO, which doesn't exist really.
>
> drivers/clk/sunxi-ng/Kconfig | 6 +
> drivers/clk/sunxi-ng/Makefile | 1 +
> drivers/clk/sunxi-ng/ccu-sun8i-r.c | 211
> ++++++++++++++++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun8i-r.h | 27 ++++
> include/dt-bindings/clock/sun8i-r-ccu.h | 59 +++++++++
> include/dt-bindings/reset/sun8i-r-ccu.h | 53 ++++++++ 6 files
> changed, 357 insertions(+) create mode 100644
> drivers/clk/sunxi-ng/ccu-sun8i-r.c create mode 100644
> drivers/clk/sunxi-ng/ccu-sun8i-r.h create mode 100644
> include/dt-bindings/clock/sun8i-r-ccu.h create mode 100644
> include/dt-bindings/reset/sun8i-r-ccu.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig
> b/drivers/clk/sunxi-ng/Kconfig index 8af8f4be8e3b..fbd3f8cd5c22 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -151,4 +151,10 @@ config SUN9I_A80_CCU
> default MACH_SUN9I
> depends on MACH_SUN9I || COMPILE_TEST
>
> +config SUN8I_R_CCU
> + bool "Support for Allwinner SoCs' PRCM CCUs"
> + select SUNXI_CCU_DIV
> + select SUNXI_CCU_GATE
> + default MACH_SUN8I || (ARCH_SUNXI && ARM64)
> +
> endif
> diff --git a/drivers/clk/sunxi-ng/Makefile
> b/drivers/clk/sunxi-ng/Makefile index 6feaac0c5600..0ec02fe14c50
> 100644 --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU) +=
> ccu-sun8i-a23.o obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
> obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o
> obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o
> +obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o
> obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o
> obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o
> obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c
> b/drivers/clk/sunxi-ng/ccu-sun8i-r.c new file mode 100644
> index 000000000000..ddbb34018086
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
> @@ -0,0 +1,211 @@
> +/*
> + * Copyright (c) 2016 Icenowy Zheng <icenowy@xxxxxxxx>
> + *
> + * This software is licensed under the terms of the GNU General
> Public
> + * License version 2, as published by the Free Software Foundation,
> and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_div.h"
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +#include "ccu_nm.h"
> +
> +#include "ccu-sun8i-r.h"
> +
> +static const char * const ar100_parents[] = { "osc32k", "osc24M",
> + "pll-periph0", "iosc" };
> +
> +static struct ccu_div ar100_clk = {
> + .div = _SUNXI_CCU_DIV_FLAGS(4, 2,
> CLK_DIVIDER_POWER_OF_TWO), +
> + .mux = {
> + .shift = 16,
> + .width = 2,
> +
> + .variable_prediv = {
> + .index = 2,
> + .shift = 8,
> + .width = 5,
> + },
> + },
> +
> + .common = {
> + .reg = 0x00,
> + .features = CCU_FEATURE_VARIABLE_PREDIV,
> + .hw.init = CLK_HW_INIT_PARENTS("ar100",
> + ar100_parents,
> + &ccu_div_ops,
> + 0),
> + },
> +};
> +
> +static CLK_FIXED_FACTOR(ahb0_clk, "ahb0", "ar100", 1, 1, 0);
> +
> +static struct ccu_div apb0_clk = {
> + .div = _SUNXI_CCU_DIV_FLAGS(0, 2,
> CLK_DIVIDER_POWER_OF_TWO), +
> + .common = {
> + .reg = 0x0c,
> + .hw.init = CLK_HW_INIT("apb0",
> + "ahb0",
> + &ccu_div_ops,
> + 0),
> + },
> +};
> +
> +static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0",
> + 0x28, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb0_ir_clk, "apb0-ir", "apb0",
> + 0x28, BIT(1), 0);
> +static
> SUNXI_CCU_GATE(apb0_timer_clk, "apb0-timer", "apb0",
> + 0x28, BIT(2), 0);
> +static SUNXI_CCU_GATE(apb0_rsb_clk, "apb0-rsb", "apb0",
> + 0x28, BIT(3), 0);
> +static
> SUNXI_CCU_GATE(apb0_uart_clk, "apb0-uart", "apb0",
> + 0x28, BIT(4), 0);
> +static SUNXI_CCU_GATE(apb0_i2c_clk, "apb0-i2c", "apb0",
> + 0x28, BIT(6), 0);
> +static SUNXI_CCU_GATE(apb0_twd_clk, "apb0-twd", "apb0",
> + 0x28, BIT(7), 0);
> +
> +static const char * const r_mod0_default_parents[] = { "osc32K",
> "osc24M" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
> + r_mod0_default_parents, 0x54,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static struct ccu_common *sun8i_h3_r_ccu_clks[] = {
> + &ar100_clk.common,
> + &apb0_clk.common,
> + &apb0_pio_clk.common,
> + &apb0_ir_clk.common,
> + &apb0_timer_clk.common,
> + &apb0_uart_clk.common,
> + &apb0_i2c_clk.common,
I'm sorry but I missed something here:

+ &apb0_twd_clk.common,

> + &ir_clk.common,
> +};
> +
> +static struct ccu_common *sun50i_a64_r_ccu_clks[] = {
> + &ar100_clk.common,
> + &apb0_clk.common,
> + &apb0_pio_clk.common,
> + &apb0_ir_clk.common,
> + &apb0_timer_clk.common,
> + &apb0_rsb_clk.common,
> + &apb0_uart_clk.common,
> + &apb0_i2c_clk.common,
+ &apb0_twd_clk.common,
> + &ir_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun8i_h3_r_hw_clks = {
> + .hws = {
> + [CLK_AR100] = &ar100_clk.common.hw,
> + [CLK_AHB0] = &ahb0_clk.hw,
> + [CLK_APB0] = &apb0_clk.common.hw,
> + [CLK_APB0_PIO] =
> &apb0_pio_clk.common.hw,
> + [CLK_APB0_IR] =
> &apb0_ir_clk.common.hw,
> + [CLK_APB0_TIMER] = &apb0_timer_clk.common.hw,
> + [CLK_APB0_UART] =
> &apb0_uart_clk.common.hw,
> + [CLK_APB0_I2C] =
> &apb0_i2c_clk.common.hw,
> + [CLK_APB0_TWD] =
> &apb0_twd_clk.common.hw,
> + [CLK_IR] = &ir_clk.common.hw,
> + },
> + .num = CLK_NUMBER,
> +};
> +
> +static struct clk_hw_onecell_data sun50i_a64_r_hw_clks = {
> + .hws = {
> + [CLK_AR100] = &ar100_clk.common.hw,
> + [CLK_AHB0] = &ahb0_clk.hw,
> + [CLK_APB0] = &apb0_clk.common.hw,
> + [CLK_APB0_PIO] =
> &apb0_pio_clk.common.hw,
> + [CLK_APB0_IR] =
> &apb0_ir_clk.common.hw,
> + [CLK_APB0_TIMER] = &apb0_timer_clk.common.hw,
> + [CLK_APB0_RSB] =
> &apb0_rsb_clk.common.hw,
> + [CLK_APB0_UART] =
> &apb0_uart_clk.common.hw,
> + [CLK_APB0_I2C] =
> &apb0_i2c_clk.common.hw,
> + [CLK_APB0_TWD] =
> &apb0_twd_clk.common.hw,
> + [CLK_IR] = &ir_clk.common.hw,
> + },
> + .num = CLK_NUMBER,
> +};
> +
> +static struct ccu_reset_map sun8i_h3_r_ccu_resets[] = {
> + [RST_APB0_IR] = { 0xb0, BIT(1) },
> + [RST_APB0_TIMER] = { 0xb0, BIT(2) },
> + [RST_APB0_UART] = { 0xb0, BIT(4) },
> + [RST_APB0_I2C] = { 0xb0, BIT(6) },
> +};
> +
> +static struct ccu_reset_map sun50i_a64_r_ccu_resets[] = {
> + [RST_APB0_IR] = { 0xb0, BIT(1) },
> + [RST_APB0_TIMER] = { 0xb0, BIT(2) },
> + [RST_APB0_RSB] = { 0xb0, BIT(3) },
> + [RST_APB0_UART] = { 0xb0, BIT(4) },
> + [RST_APB0_I2C] = { 0xb0, BIT(6) },
> +};
> +
> +static const struct sunxi_ccu_desc sun8i_h3_r_ccu_desc = {
> + .ccu_clks = sun8i_h3_r_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun8i_h3_r_ccu_clks),
> +
> + .hw_clks = &sun8i_h3_r_hw_clks,
> +
> + .resets = sun8i_h3_r_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun8i_h3_r_ccu_resets),
> +};
> +
> +static const struct sunxi_ccu_desc sun50i_a64_r_ccu_desc = {
> + .ccu_clks = sun50i_a64_r_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun50i_a64_r_ccu_clks),
> +
> + .hw_clks = &sun50i_a64_r_hw_clks,
> +
> + .resets = sun50i_a64_r_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun50i_a64_r_ccu_resets),
> +};
> +
> +static void __init sunxi_r_ccu_init(struct device_node *node,
> + const struct sunxi_ccu_desc
> *desc) +{
> + void __iomem *reg;
> +
> + reg = of_io_request_and_map(node, 0,
> of_node_full_name(node));
> + if (IS_ERR(reg)) {
> + pr_err("%s: Could not map the clock registers\n",
> + of_node_full_name(node));
> + return;
> + }
> +
> + sunxi_ccu_probe(node, reg, desc);
> +}
> +
> +static void __init sun8i_h3_r_ccu_setup(struct device_node *node)
> +{
> + sunxi_r_ccu_init(node, &sun8i_h3_r_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun8i_h3_r_ccu, "allwinner,sun8i-h3-r-ccu",
> + sun8i_h3_r_ccu_setup);
> +
> +static void __init sun50i_a64_r_ccu_setup(struct device_node *node)
> +{
> + sunxi_r_ccu_init(node, &sun50i_a64_r_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun50i_a64_r_ccu, "allwinner,sun50i-a64-r-ccu",
> + sun50i_a64_r_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.h
> b/drivers/clk/sunxi-ng/ccu-sun8i-r.h new file mode 100644
> index 000000000000..eaa431fd1d8f
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.h
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright 2016 Icenowy <icenowy@xxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License as published
> by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_SUN8I_R_H
> +#define _CCU_SUN8I_R_H_
> +
> +#include <dt-bindings/clock/sun8i-r-ccu.h>
> +#include <dt-bindings/reset/sun8i-r-ccu.h>
> +
> +/* AHB/APB bus clocks are not exported */
> +#define CLK_AHB0 1
> +#define CLK_APB0 2
> +
> +#define CLK_NUMBER (CLK_APB0_TWD + 1)
> +
> +#endif /* _CCU_SUN8I_R_H */
> diff --git a/include/dt-bindings/clock/sun8i-r-ccu.h
> b/include/dt-bindings/clock/sun8i-r-ccu.h new file mode 100644
> index 000000000000..779d20aa0d05
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-r-ccu.h
> @@ -0,0 +1,59 @@
> +/*
> + * Copyright (c) 2016 Icenowy Zheng <icenowy@xxxxxxxx>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2
> of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the
> Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN8I_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN8I_R_CCU_H_
> +
> +#define CLK_AR100 0
> +
> +#define CLK_APB0_PIO 3
> +#define CLK_APB0_IR 4
> +#define CLK_APB0_TIMER 5
> +#define CLK_APB0_RSB 6
> +#define CLK_APB0_UART 7
> +/* 8 is reserved for CLK_APB0_W1 on A31 */
> +#define CLK_APB0_I2C 9
> +#define CLK_APB0_TWD 10
> +
> +#define CLK_IR 11
> +
> +#endif /* _DT_BINDINGS_CLK_SUN8I_R_CCU_H_ */
> diff --git a/include/dt-bindings/reset/sun8i-r-ccu.h
> b/include/dt-bindings/reset/sun8i-r-ccu.h new file mode 100644
> index 000000000000..4ba64f3d6fc9
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun8i-r-ccu.h
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (C) 2016 Icenowy Zheng <icenowy@xxxxxxxx>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2
> of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the
> Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN8I_R_CCU_H_
> +#define _DT_BINDINGS_RST_SUN8I_R_CCU_H_
> +
> +#define RST_APB0_IR 0
> +#define RST_APB0_TIMER 1
> +#define RST_APB0_RSB 2
> +#define RST_APB0_UART 3
> +/* 4 is reserved for RST_APB0_W1 on A31 */
> +#define RST_APB0_I2C 5
> +
> +#endif /* _DT_BINDINGS_RST_SUN8I_R_CCU_H_ */