From: Masahiro Yamada <yamada.masahiro@socionext.com> To: linux-clk@vger.kernel.org Cc: Masahiro Yamada <yamada.masahiro@socionext.com>, Michael Turquette <mturquette@baylibre.com>, Stephen Boyd <sboyd@codeaurora.org>, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs Date: Mon, 28 Dec 2015 19:20:58 +0900 [thread overview] Message-ID: <1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com> (raw) This is the initial commit for the UniPhier clock drivers, including support for PH1-sLD3, PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5, and ProXstream2/PH1-LD6b. To improve the code maintainability, the driver consists of common functions (clk-uniphier-core.c) and clock data arrays needed to support each SoC. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> --- Changes in v2: - split emmc_hw_reset - make SD clock rate-controllable - add CLK_SET_RATE_PARENT flag to mux, gate, fixed-factor clocks MAINTAINERS | 1 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/uniphier/Kconfig | 35 ++++ drivers/clk/uniphier/Makefile | 10 + drivers/clk/uniphier/clk-ph1-ld4.c | 117 ++++++++++++ drivers/clk/uniphier/clk-ph1-pro4.c | 117 ++++++++++++ drivers/clk/uniphier/clk-ph1-pro5.c | 107 +++++++++++ drivers/clk/uniphier/clk-ph1-sld3.c | 117 ++++++++++++ drivers/clk/uniphier/clk-ph1-sld8.c | 107 +++++++++++ drivers/clk/uniphier/clk-proxstream2.c | 88 +++++++++ drivers/clk/uniphier/clk-uniphier-core.c | 151 +++++++++++++++ drivers/clk/uniphier/clk-uniphier-mio.c | 315 +++++++++++++++++++++++++++++++ drivers/clk/uniphier/clk-uniphier-peri.c | 175 +++++++++++++++++ drivers/clk/uniphier/clk-uniphier.h | 68 +++++++ 15 files changed, 1410 insertions(+) create mode 100644 drivers/clk/uniphier/Kconfig create mode 100644 drivers/clk/uniphier/Makefile create mode 100644 drivers/clk/uniphier/clk-ph1-ld4.c create mode 100644 drivers/clk/uniphier/clk-ph1-pro4.c create mode 100644 drivers/clk/uniphier/clk-ph1-pro5.c create mode 100644 drivers/clk/uniphier/clk-ph1-sld3.c create mode 100644 drivers/clk/uniphier/clk-ph1-sld8.c create mode 100644 drivers/clk/uniphier/clk-proxstream2.c create mode 100644 drivers/clk/uniphier/clk-uniphier-core.c create mode 100644 drivers/clk/uniphier/clk-uniphier-mio.c create mode 100644 drivers/clk/uniphier/clk-uniphier-peri.c create mode 100644 drivers/clk/uniphier/clk-uniphier.h diff --git a/MAINTAINERS b/MAINTAINERS index fc08493..6c10e9b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1644,6 +1644,7 @@ F: arch/arm/mach-uniphier/ F: arch/arm/mm/cache-uniphier.c F: arch/arm64/boot/dts/socionext/ F: drivers/bus/uniphier-system-bus.c +F: drivers/clk/uniphier/ F: drivers/i2c/busses/i2c-uniphier* F: drivers/pinctrl/uniphier/ F: drivers/tty/serial/8250/8250_uniphier.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c3e3a02..7580323 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -191,6 +191,7 @@ config COMMON_CLK_CDCE706 source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/qcom/Kconfig" +source "drivers/clk/uniphier/Kconfig" endmenu diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 820714c..ab9d1bd 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_ARCH_OMAP2PLUS) += ti/ +obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig new file mode 100644 index 0000000..7606f27 --- /dev/null +++ b/drivers/clk/uniphier/Kconfig @@ -0,0 +1,35 @@ +menuconfig CLK_UNIPHIER + bool "Clock drivers for UniPhier SoCs" + depends on ARCH_UNIPHIER + depends on OF + default y + help + Supports clock drivers for UniPhier SoCs. + +if CLK_UNIPHIER + +config CLK_UNIPHIER_PH1_SLD3 + bool "Clock driver for UniPhier PH1-sLD3 SoC" + default y + +config CLK_UNIPHIER_PH1_LD4 + bool "Clock driver for UniPhier PH1-LD4 SoC" + default y + +config CLK_UNIPHIER_PH1_PRO4 + bool "Clock driver for UniPhier PH1-Pro4 SoC" + default y + +config CLK_UNIPHIER_PH1_SLD8 + bool "Clock driver for UniPhier PH1-sLD8 SoC" + default y + +config CLK_UNIPHIER_PH1_PRO5 + bool "Clock driver for UniPhier PH1-Pro5 SoC" + default y + +config CLK_UNIPHIER_PROXSTREAM2 + bool "Clock driver for UniPhier ProXstream2/PH1-LD6b SoC" + default y + +endif diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile new file mode 100644 index 0000000..3be1a17 --- /dev/null +++ b/drivers/clk/uniphier/Makefile @@ -0,0 +1,10 @@ +obj-y += clk-uniphier-core.o +obj-y += clk-uniphier-peri.o +obj-y += clk-uniphier-mio.o + +obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD3) += clk-ph1-sld3.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_LD4) += clk-ph1-ld4.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO4) += clk-ph1-pro4.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD8) += clk-ph1-sld8.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO5) += clk-ph1-pro5.o +obj-$(CONFIG_CLK_UNIPHIER_PROXSTREAM2) += clk-proxstream2.o diff --git a/drivers/clk/uniphier/clk-ph1-ld4.c b/drivers/clk/uniphier/clk-ph1-ld4.c new file mode 100644 index 0000000..48d342f --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-ld4.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_ld4_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 65, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288000, + .div = 24576, + }, + }, + { + .name = "a2pll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 24, + .div = 1, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "a2pll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "i2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_ld4_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_ld4_clk_idata); +} +CLK_OF_DECLARE(ph1_ld4_clk, "socionext,ph1-ld4-sysctrl", ph1_ld4_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-pro4.c b/drivers/clk/uniphier/clk-ph1-pro4.c new file mode 100644 index 0000000..052813a --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-pro4.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_pro4_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 64, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288, + .div = 25, + }, + }, + { + .name = "a2pll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = "upll", + .mult = 256, + .div = 125, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "a2pll", + .mult = 1, + .div = 8, + }, + }, + { + .name = "fi2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_pro4_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro4_clk_idata); +} +CLK_OF_DECLARE(ph1_pro4_clk, "socionext,ph1-pro4-sysctrl", ph1_pro4_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-pro5.c b/drivers/clk/uniphier/clk-ph1-pro5.c new file mode 100644 index 0000000..9f782d9 --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-pro5.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_pro5_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 120, + .div = 1, + }, + }, + { + .name = "dapll1", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 128, + .div = 125, + }, + }, + { + .name = "dapll2", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = "upll", + .mult = 144, + .div = 5, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "dapll2", + .mult = 1, + .div = 8, + }, + }, + { + .name = "fi2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_pro5_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro5_clk_idata); +} +CLK_OF_DECLARE(ph1_pro5_clk, "socionext,ph1-pro5-sysctrl", ph1_pro5_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-sld3.c b/drivers/clk/uniphier/clk-ph1-sld3.c new file mode 100644 index 0000000..7249a81 --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-sld3.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_sld3_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 65, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288000, + .div = 24576, + }, + }, + { + .name = "a2pll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 24, + .div = 1, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "a2pll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "i2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_sld3_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_sld3_clk_idata); +} +CLK_OF_DECLARE(ph1_sld3_clk, "socionext,ph1-sld3-sysctrl", ph1_sld3_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-sld8.c b/drivers/clk/uniphier/clk-ph1-sld8.c new file mode 100644 index 0000000..bfebd38 --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-sld8.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_sld8_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 64, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288, + .div = 25, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 20, + }, + }, + { + .name = "i2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_sld8_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_sld8_clk_idata); +} +CLK_OF_DECLARE(ph1_sld8_clk, "socionext,ph1-sld8-sysctrl", ph1_sld8_clk_init); diff --git a/drivers/clk/uniphier/clk-proxstream2.c b/drivers/clk/uniphier/clk-proxstream2.c new file mode 100644 index 0000000..b3ffedc --- /dev/null +++ b/drivers/clk/uniphier/clk-proxstream2.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data proxstream2_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 96, + .div = 1, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 27, + }, + }, + { + .name = "fi2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { /* sentinel */ } +}; + +static void __init proxstream2_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, proxstream2_clk_idata); +} +CLK_OF_DECLARE(proxstream2_clk, "socionext,proxstream2-sysctrl", + proxstream2_clk_init); diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c new file mode 100644 index 0000000..8680101 --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#define pr_fmt(fmt) "uniphier-clk: " fmt + +#include <linux/clk-provider.h> +#include <linux/log2.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> + +#include "clk-uniphier.h" + +static void __init uniphier_clk_update_parent_name(struct device_node *np, + const char **parent_name) +{ + const char *new_name; + int index; + + if (!parent_name || !*parent_name) + return; + + if (strncmp(*parent_name, UNIPHIER_CLK_EXT, strlen(UNIPHIER_CLK_EXT))) + return; + + index = of_property_match_string(np, "clock-names", + *parent_name + strlen(UNIPHIER_CLK_EXT)); + new_name = of_clk_get_parent_name(np, index); + if (new_name) + *parent_name = new_name; +} + +static struct clk * __init uniphier_clk_register(struct device_node *np, + void __iomem *regbase, + struct uniphier_clk_init_data *idata) +{ + int i; + + switch (idata->type) { + case UNIPHIER_CLK_TYPE_FIXED_FACTOR: + uniphier_clk_update_parent_name(np, + &idata->data.factor.parent_name); + return clk_register_fixed_factor(NULL, idata->name, + idata->data.factor.parent_name, + CLK_SET_RATE_PARENT, + idata->data.factor.mult, + idata->data.factor.div); + case UNIPHIER_CLK_TYPE_FIXED_RATE: + return clk_register_fixed_rate(NULL, idata->name, NULL, + CLK_IS_ROOT, + idata->data.rate.fixed_rate); + case UNIPHIER_CLK_TYPE_GATE: + uniphier_clk_update_parent_name(np, + &idata->data.gate.parent_name); + return clk_register_gate(NULL, idata->name, + idata->data.gate.parent_name, + idata->data.gate.parent_name ? + CLK_SET_RATE_PARENT : CLK_IS_ROOT, + regbase + idata->data.gate.reg, + idata->data.gate.bit_idx, 0, NULL); + case UNIPHIER_CLK_TYPE_MUX: + for (i = 0; i < idata->data.mux.num_parents; i++) + uniphier_clk_update_parent_name(np, + &idata->data.mux.parent_names[i]); + return clk_register_mux(NULL, idata->name, + idata->data.mux.parent_names, + idata->data.mux.num_parents, + CLK_SET_RATE_PARENT, + regbase + idata->data.mux.reg, + idata->data.mux.shift, + ilog2(idata->data.mux.num_parents), + 0, NULL); + default: + WARN(1, "unsupported clock type\n"); + return ERR_PTR(-EINVAL); + } +} + +int __init uniphier_clk_init(struct device_node *np, + struct uniphier_clk_init_data *idata) +{ + struct clk_onecell_data *clk_data; + struct uniphier_clk_init_data *p; + void __iomem *regbase; + int max_index = 0; + int ret; + + regbase = of_iomap(np, 0); + if (!regbase) + return -ENOMEM; + + for (p = idata; p->name; p++) + max_index = max(max_index, p->output_index); + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->clk_num = max_index + 1; + clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *), + GFP_KERNEL); + if (!clk_data->clks) { + ret = -ENOMEM; + goto free_clk_data; + } + + for (p = idata; p->name; p++) { + pr_debug("register %s (%s[%d])\n", p->name, np->name, + p->output_index); + p->clk = uniphier_clk_register(np, regbase, p); + if (IS_ERR(p->clk)) { + pr_err("failed to register %s\n", p->name); + ret = PTR_ERR(p->clk); + goto unregister; + } + + if (p->output_index >= 0) + clk_data->clks[p->output_index] = p->clk; + } + + ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); + if (ret) + goto unregister; + + return ret; +unregister: + for (p--; p >= idata; p--) { + pr_debug("unregister %s (%s[%d])\n", p->name, np->name, + p->output_index); + clk_unregister(p->clk); + p->clk = NULL; + } + kfree(clk_data->clks); +free_clk_data: + kfree(clk_data); + + pr_err("%s: init failed with error %d\n", np->full_name, ret); + + return ret; +} diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c new file mode 100644 index 0000000..ad6491b --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +#define UNIPHIER_MIO_CLK_SD_FIXED \ + { \ + .name = "sd-44m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 44444444, \ + }, \ + }, \ + { \ + .name = "sd-33m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 33333333, \ + }, \ + }, \ + { \ + .name = "sd-50m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 50000000, \ + }, \ + }, \ + { \ + .name = "sd-67m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 66666666, \ + }, \ + }, \ + { \ + .name = "sd-100m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 100000000, \ + }, \ + }, \ + { \ + .name = "sd-40m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 40000000, \ + }, \ + }, \ + { \ + .name = "sd-25m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 25000000, \ + }, \ + }, \ + { \ + .name = "sd-22m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 22222222, \ + }, \ + } + + +#define UNIPHIER_MIO_CLK_SD(ch, index) \ + { \ + .name = "sd" #ch "-clksel0", \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .output_index = -1, \ + .data.mux = { \ + .parent_names = { \ + "sd-44m", \ + "sd-33m", \ + "sd-50m", \ + "sd-67m", \ + }, \ + .num_parents = 4, \ + .reg = 0x30 + 0x200 * ch, \ + .shift = 16, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-clksel1", \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .output_index = -1, \ + .data.mux = { \ + .parent_names = { \ + "sd-100m", \ + "sd-40m", \ + "sd-25m", \ + "sd-22m", \ + }, \ + .num_parents = 4, \ + .reg = 0x30 + 0x200 * ch, \ + .shift = 8, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-clkmode", \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .output_index = -1, \ + .data.mux = { \ + .parent_names = { \ + "sd" #ch "-clksel0", \ + "sd" #ch "-clksel1", \ + }, \ + .num_parents = 2, \ + .reg = 0x30 + 0x200 * ch, \ + .shift = 12, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "sd" #ch "-clkmode", \ + .reg = 0x20 + 0x200 * ch, \ + .bit_idx = 8, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-bridge-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "sd" #ch "-clken", \ + .reg = 0x110 + 0x200 * ch, \ + .bit_idx = 26, \ + }, \ + }, \ + { \ + .name = "sd" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "sd" #ch "-bridge-reset", \ + .reg = 0x110 + 0x200 * ch, \ + .bit_idx = 0, \ + }, \ + } + +#define UNIPHIER_MIO_CLK_SD_HW_RESET(ch, index) \ + { \ + .name = "sd" #ch "-hw-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = NULL, \ + .reg = 0x80 + 0x200 * ch, \ + .bit_idx = 0, \ + }, \ + } + +#define UNIPHIER_MIO_CLK_EHCI(ch, index) \ + { \ + .name = "ehci" #ch "-phy-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "ehci", \ + .reg = 0x20 + 0x200 * ch, \ + .bit_idx = 29, \ + }, \ + }, \ + { \ + .name = "ehci" #ch "-link-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "ehci" #ch "-phy-clken", \ + .reg = 0x20 + 0x200 * ch, \ + .bit_idx = 28, \ + }, \ + }, \ + { \ + .name = "ehci" #ch "-bridge-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "ehci" #ch "-link-clken", \ + .reg = 0x110 + 0x200 * ch, \ + .bit_idx = 24, \ + }, \ + }, \ + { \ + .name = "ehci" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "ehci" #ch "-bridge-reset", \ + .reg = 0x114 + 0x200 * ch, \ + .bit_idx = 0, \ + }, \ + } + +#define UNIPHIER_MIO_CLK_DMAC(index) \ + { \ + .name = "miodmac-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "stdmac", \ + .reg = 0x20, \ + .bit_idx = 25, \ + }, \ + }, \ + { \ + .name = "miodmac", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "miodmac-clken", \ + .reg = 0x110, \ + .bit_idx = 17, \ + }, \ + } + +static struct uniphier_clk_init_data ph1_sld3_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD_HW_RESET(0, 3), + UNIPHIER_MIO_CLK_EHCI(0, 4), + UNIPHIER_MIO_CLK_EHCI(1, 5), + UNIPHIER_MIO_CLK_EHCI(2, 6), + UNIPHIER_MIO_CLK_EHCI(3, 7), + UNIPHIER_MIO_CLK_DMAC(8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_ld4_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3), + UNIPHIER_MIO_CLK_EHCI(0, 4), + UNIPHIER_MIO_CLK_EHCI(1, 5), + UNIPHIER_MIO_CLK_EHCI(2, 6), + UNIPHIER_MIO_CLK_DMAC(8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro4_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD(2, 2), + UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3), + UNIPHIER_MIO_CLK_EHCI(0, 4), + UNIPHIER_MIO_CLK_EHCI(1, 5), + UNIPHIER_MIO_CLK_DMAC(8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro5_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3), + { /* sentinel */ } +}; + +static void __init ph1_sld3_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_sld3_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_sld3_mio_clk, "socionext,ph1-sld3-mioctrl", + ph1_sld3_mio_clk_init); + +static void __init ph1_ld4_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_ld4_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_ld4_mio_clk, "socionext,ph1-ld4-mioctrl", + ph1_ld4_mio_clk_init); +CLK_OF_DECLARE(ph1_sld8_mio_clk, "socionext,ph1-sld8-mioctrl", + ph1_ld4_mio_clk_init); + +static void __init ph1_pro4_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro4_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_pro4_mio_clk, "socionext,ph1-pro4-mioctrl", + ph1_pro4_mio_clk_init); + +static void __init ph1_pro5_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro5_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_pro5_mio_clk, "socionext,ph1-pro5-mioctrl", + ph1_pro5_mio_clk_init); +CLK_OF_DECLARE(proxstream2_mio_clk, "socionext,proxstream2-mioctrl", + ph1_pro5_mio_clk_init); diff --git a/drivers/clk/uniphier/clk-uniphier-peri.c b/drivers/clk/uniphier/clk-uniphier-peri.c new file mode 100644 index 0000000..adaae8e --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier-peri.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +#define UNIPHIER_PERI_CLK_UART(ch, index) \ + { \ + .name = "uart" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "uart", \ + .reg = 0x24, \ + .bit_idx = 19 + ch, \ + }, \ + }, \ + { \ + .name = "uart" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "uart" #ch "-clken", \ + .reg = 0x114, \ + .bit_idx = 19 + ch, \ + }, \ + } + +#define UNIPHIER_PERI_CLK_I2C_COMMON \ + { \ + .name = "i2c-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "i2c", \ + .reg = 0x20, \ + .bit_idx = 1, \ + }, \ + }, \ + { \ + .name = "i2c-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "i2c-clken", \ + .reg = 0x110, \ + .bit_idx = 1, \ + }, \ + } + + +#define UNIPHIER_PERI_CLK_I2C(ch, index) \ + { \ + .name = "i2c" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "i2c-reset", \ + .reg = 0x24, \ + .bit_idx = 5 + ch, \ + }, \ + }, \ + { \ + .name = "i2c" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "i2c" #ch "-clken", \ + .reg = 0x114, \ + .bit_idx = 5 + ch, \ + }, \ + } + +#define UNIPHIER_PERI_CLK_FI2C(ch, index) \ + { \ + .name = "fi2c" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "fi2c", \ + .reg = 0x24, \ + .bit_idx = 24 + ch, \ + }, \ + }, \ + { \ + .name = "fi2c" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = index, \ + .data.gate = { \ + .parent_name = "fi2c" #ch "-clken", \ + .reg = 0x114, \ + .bit_idx = 24 + ch, \ + }, \ + } + +static struct uniphier_clk_init_data ph1_ld4_peri_clk_idata[] __initdata = { + UNIPHIER_PERI_CLK_UART(0, 0), + UNIPHIER_PERI_CLK_UART(1, 1), + UNIPHIER_PERI_CLK_UART(2, 2), + UNIPHIER_PERI_CLK_UART(3, 3), + UNIPHIER_PERI_CLK_I2C_COMMON, + UNIPHIER_PERI_CLK_I2C(0, 4), + UNIPHIER_PERI_CLK_I2C(1, 5), + UNIPHIER_PERI_CLK_I2C(2, 6), + UNIPHIER_PERI_CLK_I2C(3, 7), + UNIPHIER_PERI_CLK_I2C(4, 8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro4_peri_clk_idata[] __initdata = { + UNIPHIER_PERI_CLK_UART(0, 0), + UNIPHIER_PERI_CLK_UART(1, 1), + UNIPHIER_PERI_CLK_UART(2, 2), + UNIPHIER_PERI_CLK_UART(3, 3), + UNIPHIER_PERI_CLK_FI2C(0, 4), + UNIPHIER_PERI_CLK_FI2C(1, 5), + UNIPHIER_PERI_CLK_FI2C(2, 6), + UNIPHIER_PERI_CLK_FI2C(3, 7), + /* no I2C ch4 */ + UNIPHIER_PERI_CLK_FI2C(5, 9), + UNIPHIER_PERI_CLK_FI2C(6, 10), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro5_peri_clk_idata[] __initdata = { + UNIPHIER_PERI_CLK_UART(0, 0), + UNIPHIER_PERI_CLK_UART(1, 1), + UNIPHIER_PERI_CLK_UART(2, 2), + UNIPHIER_PERI_CLK_UART(3, 3), + UNIPHIER_PERI_CLK_FI2C(0, 4), + UNIPHIER_PERI_CLK_FI2C(1, 5), + UNIPHIER_PERI_CLK_FI2C(2, 6), + UNIPHIER_PERI_CLK_FI2C(3, 7), + UNIPHIER_PERI_CLK_FI2C(4, 8), + UNIPHIER_PERI_CLK_FI2C(5, 9), + UNIPHIER_PERI_CLK_FI2C(6, 10), + { /* sentinel */ } +}; + +static void __init ph1_ld4_peri_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_ld4_peri_clk_idata); +} +CLK_OF_DECLARE(ph1_ld4_peri_clk, "socionext,ph1-ld4-perictrl", + ph1_ld4_peri_clk_init); +CLK_OF_DECLARE(ph1_sld8_peri_clk, "socionext,ph1-sld8-perictrl", + ph1_ld4_peri_clk_init); + +static void __init ph1_pro4_peri_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro4_peri_clk_idata); +} +CLK_OF_DECLARE(ph1_pro4_peri_clk, "socionext,ph1-pro4-perictrl", + ph1_pro4_peri_clk_init); + +static void __init ph1_pro5_peri_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro5_peri_clk_idata); +} +CLK_OF_DECLARE(ph1_pro5_peri_clk, "socionext,ph1-pro5-perictrl", + ph1_pro5_peri_clk_init); +CLK_OF_DECLARE(proxstream2_peri_clk, "socionext,proxstream2-perictrl", + ph1_pro5_peri_clk_init); diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h new file mode 100644 index 0000000..05277b6 --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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 __CLK_UNIPHIER_H__ +#define __CLK_UNIPHIER_H__ + +#include <linux/kernel.h> + +#define UNIPHIER_CLK_EXT "[EXT]" + +enum uniphier_clk_type { + UNIPHIER_CLK_TYPE_FIXED_FACTOR, + UNIPHIER_CLK_TYPE_FIXED_RATE, + UNIPHIER_CLK_TYPE_GATE, + UNIPHIER_CLK_TYPE_MUX, +}; + +struct uniphier_clk_fixed_factor_data { + const char *parent_name; + unsigned int mult; + unsigned int div; +}; + +struct uniphier_clk_fixed_rate_data { + unsigned long fixed_rate; +}; + +struct uniphier_clk_gate_data { + const char *parent_name; + unsigned int reg; + u8 bit_idx; +}; + +struct uniphier_clk_mux_data { + const char *parent_names[4]; + u8 num_parents; + unsigned int reg; + u8 shift; +}; + +struct uniphier_clk_init_data { + const char *name; + enum uniphier_clk_type type; + int output_index; + union { + struct uniphier_clk_fixed_factor_data factor; + struct uniphier_clk_fixed_rate_data rate; + struct uniphier_clk_gate_data gate; + struct uniphier_clk_mux_data mux; + } data; + struct clk *clk; +}; + +int uniphier_clk_init(struct device_node *np, + struct uniphier_clk_init_data *idata); + +#endif /* __CLK_UNIPHIER_H__ */ -- 1.9.1
WARNING: multiple messages have this Message-ID (diff)
From: yamada.masahiro@socionext.com (Masahiro Yamada) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs Date: Mon, 28 Dec 2015 19:20:58 +0900 [thread overview] Message-ID: <1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com> (raw) This is the initial commit for the UniPhier clock drivers, including support for PH1-sLD3, PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5, and ProXstream2/PH1-LD6b. To improve the code maintainability, the driver consists of common functions (clk-uniphier-core.c) and clock data arrays needed to support each SoC. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> --- Changes in v2: - split emmc_hw_reset - make SD clock rate-controllable - add CLK_SET_RATE_PARENT flag to mux, gate, fixed-factor clocks MAINTAINERS | 1 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/uniphier/Kconfig | 35 ++++ drivers/clk/uniphier/Makefile | 10 + drivers/clk/uniphier/clk-ph1-ld4.c | 117 ++++++++++++ drivers/clk/uniphier/clk-ph1-pro4.c | 117 ++++++++++++ drivers/clk/uniphier/clk-ph1-pro5.c | 107 +++++++++++ drivers/clk/uniphier/clk-ph1-sld3.c | 117 ++++++++++++ drivers/clk/uniphier/clk-ph1-sld8.c | 107 +++++++++++ drivers/clk/uniphier/clk-proxstream2.c | 88 +++++++++ drivers/clk/uniphier/clk-uniphier-core.c | 151 +++++++++++++++ drivers/clk/uniphier/clk-uniphier-mio.c | 315 +++++++++++++++++++++++++++++++ drivers/clk/uniphier/clk-uniphier-peri.c | 175 +++++++++++++++++ drivers/clk/uniphier/clk-uniphier.h | 68 +++++++ 15 files changed, 1410 insertions(+) create mode 100644 drivers/clk/uniphier/Kconfig create mode 100644 drivers/clk/uniphier/Makefile create mode 100644 drivers/clk/uniphier/clk-ph1-ld4.c create mode 100644 drivers/clk/uniphier/clk-ph1-pro4.c create mode 100644 drivers/clk/uniphier/clk-ph1-pro5.c create mode 100644 drivers/clk/uniphier/clk-ph1-sld3.c create mode 100644 drivers/clk/uniphier/clk-ph1-sld8.c create mode 100644 drivers/clk/uniphier/clk-proxstream2.c create mode 100644 drivers/clk/uniphier/clk-uniphier-core.c create mode 100644 drivers/clk/uniphier/clk-uniphier-mio.c create mode 100644 drivers/clk/uniphier/clk-uniphier-peri.c create mode 100644 drivers/clk/uniphier/clk-uniphier.h diff --git a/MAINTAINERS b/MAINTAINERS index fc08493..6c10e9b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1644,6 +1644,7 @@ F: arch/arm/mach-uniphier/ F: arch/arm/mm/cache-uniphier.c F: arch/arm64/boot/dts/socionext/ F: drivers/bus/uniphier-system-bus.c +F: drivers/clk/uniphier/ F: drivers/i2c/busses/i2c-uniphier* F: drivers/pinctrl/uniphier/ F: drivers/tty/serial/8250/8250_uniphier.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c3e3a02..7580323 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -191,6 +191,7 @@ config COMMON_CLK_CDCE706 source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/qcom/Kconfig" +source "drivers/clk/uniphier/Kconfig" endmenu diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 820714c..ab9d1bd 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_ARCH_OMAP2PLUS) += ti/ +obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig new file mode 100644 index 0000000..7606f27 --- /dev/null +++ b/drivers/clk/uniphier/Kconfig @@ -0,0 +1,35 @@ +menuconfig CLK_UNIPHIER + bool "Clock drivers for UniPhier SoCs" + depends on ARCH_UNIPHIER + depends on OF + default y + help + Supports clock drivers for UniPhier SoCs. + +if CLK_UNIPHIER + +config CLK_UNIPHIER_PH1_SLD3 + bool "Clock driver for UniPhier PH1-sLD3 SoC" + default y + +config CLK_UNIPHIER_PH1_LD4 + bool "Clock driver for UniPhier PH1-LD4 SoC" + default y + +config CLK_UNIPHIER_PH1_PRO4 + bool "Clock driver for UniPhier PH1-Pro4 SoC" + default y + +config CLK_UNIPHIER_PH1_SLD8 + bool "Clock driver for UniPhier PH1-sLD8 SoC" + default y + +config CLK_UNIPHIER_PH1_PRO5 + bool "Clock driver for UniPhier PH1-Pro5 SoC" + default y + +config CLK_UNIPHIER_PROXSTREAM2 + bool "Clock driver for UniPhier ProXstream2/PH1-LD6b SoC" + default y + +endif diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile new file mode 100644 index 0000000..3be1a17 --- /dev/null +++ b/drivers/clk/uniphier/Makefile @@ -0,0 +1,10 @@ +obj-y += clk-uniphier-core.o +obj-y += clk-uniphier-peri.o +obj-y += clk-uniphier-mio.o + +obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD3) += clk-ph1-sld3.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_LD4) += clk-ph1-ld4.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO4) += clk-ph1-pro4.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_SLD8) += clk-ph1-sld8.o +obj-$(CONFIG_CLK_UNIPHIER_PH1_PRO5) += clk-ph1-pro5.o +obj-$(CONFIG_CLK_UNIPHIER_PROXSTREAM2) += clk-proxstream2.o diff --git a/drivers/clk/uniphier/clk-ph1-ld4.c b/drivers/clk/uniphier/clk-ph1-ld4.c new file mode 100644 index 0000000..48d342f --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-ld4.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_ld4_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 65, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288000, + .div = 24576, + }, + }, + { + .name = "a2pll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 24, + .div = 1, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "a2pll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "i2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_ld4_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_ld4_clk_idata); +} +CLK_OF_DECLARE(ph1_ld4_clk, "socionext,ph1-ld4-sysctrl", ph1_ld4_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-pro4.c b/drivers/clk/uniphier/clk-ph1-pro4.c new file mode 100644 index 0000000..052813a --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-pro4.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_pro4_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 64, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288, + .div = 25, + }, + }, + { + .name = "a2pll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = "upll", + .mult = 256, + .div = 125, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "a2pll", + .mult = 1, + .div = 8, + }, + }, + { + .name = "fi2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_pro4_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro4_clk_idata); +} +CLK_OF_DECLARE(ph1_pro4_clk, "socionext,ph1-pro4-sysctrl", ph1_pro4_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-pro5.c b/drivers/clk/uniphier/clk-ph1-pro5.c new file mode 100644 index 0000000..9f782d9 --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-pro5.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_pro5_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 120, + .div = 1, + }, + }, + { + .name = "dapll1", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 128, + .div = 125, + }, + }, + { + .name = "dapll2", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = "upll", + .mult = 144, + .div = 5, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "dapll2", + .mult = 1, + .div = 8, + }, + }, + { + .name = "fi2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_pro5_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro5_clk_idata); +} +CLK_OF_DECLARE(ph1_pro5_clk, "socionext,ph1-pro5-sysctrl", ph1_pro5_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-sld3.c b/drivers/clk/uniphier/clk-ph1-sld3.c new file mode 100644 index 0000000..7249a81 --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-sld3.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_sld3_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 65, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288000, + .div = 24576, + }, + }, + { + .name = "a2pll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 24, + .div = 1, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "a2pll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "i2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_sld3_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_sld3_clk_idata); +} +CLK_OF_DECLARE(ph1_sld3_clk, "socionext,ph1-sld3-sysctrl", ph1_sld3_clk_init); diff --git a/drivers/clk/uniphier/clk-ph1-sld8.c b/drivers/clk/uniphier/clk-ph1-sld8.c new file mode 100644 index 0000000..bfebd38 --- /dev/null +++ b/drivers/clk/uniphier/clk-ph1-sld8.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data ph1_sld8_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 64, + .div = 1, + }, + }, + { + .name = "upll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 288, + .div = 25, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 20, + }, + }, + { + .name = "i2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 16, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 32, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { + .name = "ehci", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 18, + .data.factor = { + .parent_name = "upll", + .mult = 1, + .div = 12, + }, + }, + { /* sentinel */ } +}; + +static void __init ph1_sld8_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_sld8_clk_idata); +} +CLK_OF_DECLARE(ph1_sld8_clk, "socionext,ph1-sld8-sysctrl", ph1_sld8_clk_init); diff --git a/drivers/clk/uniphier/clk-proxstream2.c b/drivers/clk/uniphier/clk-proxstream2.c new file mode 100644 index 0000000..b3ffedc --- /dev/null +++ b/drivers/clk/uniphier/clk-proxstream2.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +static struct uniphier_clk_init_data proxstream2_clk_idata[] __initdata = { + { + .name = "spll", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = -1, + .data.factor = { + .parent_name = UNIPHIER_CLK_EXT "ref", + .mult = 96, + .div = 1, + }, + }, + { + .name = "uart", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 3, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 27, + }, + }, + { + .name = "fi2c", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 4, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "arm-scu", + .type = UNIPHIER_CLK_TYPE_FIXED_FACTOR, + .output_index = 7, + .data.factor = { + .parent_name = "spll", + .mult = 1, + .div = 48, + }, + }, + { + .name = "stdmac-clken", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = -1, + .data.gate = { + .parent_name = NULL, + .reg = 0x2104, + .bit_idx = 10, + }, + }, + { + .name = "stdmac", + .type = UNIPHIER_CLK_TYPE_GATE, + .output_index = 10, + .data.gate = { + .parent_name = "stdmac-clken", + .reg = 0x2000, + .bit_idx = 10, + }, + }, + { /* sentinel */ } +}; + +static void __init proxstream2_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, proxstream2_clk_idata); +} +CLK_OF_DECLARE(proxstream2_clk, "socionext,proxstream2-sysctrl", + proxstream2_clk_init); diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c new file mode 100644 index 0000000..8680101 --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#define pr_fmt(fmt) "uniphier-clk: " fmt + +#include <linux/clk-provider.h> +#include <linux/log2.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> + +#include "clk-uniphier.h" + +static void __init uniphier_clk_update_parent_name(struct device_node *np, + const char **parent_name) +{ + const char *new_name; + int index; + + if (!parent_name || !*parent_name) + return; + + if (strncmp(*parent_name, UNIPHIER_CLK_EXT, strlen(UNIPHIER_CLK_EXT))) + return; + + index = of_property_match_string(np, "clock-names", + *parent_name + strlen(UNIPHIER_CLK_EXT)); + new_name = of_clk_get_parent_name(np, index); + if (new_name) + *parent_name = new_name; +} + +static struct clk * __init uniphier_clk_register(struct device_node *np, + void __iomem *regbase, + struct uniphier_clk_init_data *idata) +{ + int i; + + switch (idata->type) { + case UNIPHIER_CLK_TYPE_FIXED_FACTOR: + uniphier_clk_update_parent_name(np, + &idata->data.factor.parent_name); + return clk_register_fixed_factor(NULL, idata->name, + idata->data.factor.parent_name, + CLK_SET_RATE_PARENT, + idata->data.factor.mult, + idata->data.factor.div); + case UNIPHIER_CLK_TYPE_FIXED_RATE: + return clk_register_fixed_rate(NULL, idata->name, NULL, + CLK_IS_ROOT, + idata->data.rate.fixed_rate); + case UNIPHIER_CLK_TYPE_GATE: + uniphier_clk_update_parent_name(np, + &idata->data.gate.parent_name); + return clk_register_gate(NULL, idata->name, + idata->data.gate.parent_name, + idata->data.gate.parent_name ? + CLK_SET_RATE_PARENT : CLK_IS_ROOT, + regbase + idata->data.gate.reg, + idata->data.gate.bit_idx, 0, NULL); + case UNIPHIER_CLK_TYPE_MUX: + for (i = 0; i < idata->data.mux.num_parents; i++) + uniphier_clk_update_parent_name(np, + &idata->data.mux.parent_names[i]); + return clk_register_mux(NULL, idata->name, + idata->data.mux.parent_names, + idata->data.mux.num_parents, + CLK_SET_RATE_PARENT, + regbase + idata->data.mux.reg, + idata->data.mux.shift, + ilog2(idata->data.mux.num_parents), + 0, NULL); + default: + WARN(1, "unsupported clock type\n"); + return ERR_PTR(-EINVAL); + } +} + +int __init uniphier_clk_init(struct device_node *np, + struct uniphier_clk_init_data *idata) +{ + struct clk_onecell_data *clk_data; + struct uniphier_clk_init_data *p; + void __iomem *regbase; + int max_index = 0; + int ret; + + regbase = of_iomap(np, 0); + if (!regbase) + return -ENOMEM; + + for (p = idata; p->name; p++) + max_index = max(max_index, p->output_index); + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->clk_num = max_index + 1; + clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *), + GFP_KERNEL); + if (!clk_data->clks) { + ret = -ENOMEM; + goto free_clk_data; + } + + for (p = idata; p->name; p++) { + pr_debug("register %s (%s[%d])\n", p->name, np->name, + p->output_index); + p->clk = uniphier_clk_register(np, regbase, p); + if (IS_ERR(p->clk)) { + pr_err("failed to register %s\n", p->name); + ret = PTR_ERR(p->clk); + goto unregister; + } + + if (p->output_index >= 0) + clk_data->clks[p->output_index] = p->clk; + } + + ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); + if (ret) + goto unregister; + + return ret; +unregister: + for (p--; p >= idata; p--) { + pr_debug("unregister %s (%s[%d])\n", p->name, np->name, + p->output_index); + clk_unregister(p->clk); + p->clk = NULL; + } + kfree(clk_data->clks); +free_clk_data: + kfree(clk_data); + + pr_err("%s: init failed with error %d\n", np->full_name, ret); + + return ret; +} diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c new file mode 100644 index 0000000..ad6491b --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +#define UNIPHIER_MIO_CLK_SD_FIXED \ + { \ + .name = "sd-44m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 44444444, \ + }, \ + }, \ + { \ + .name = "sd-33m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 33333333, \ + }, \ + }, \ + { \ + .name = "sd-50m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 50000000, \ + }, \ + }, \ + { \ + .name = "sd-67m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 66666666, \ + }, \ + }, \ + { \ + .name = "sd-100m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 100000000, \ + }, \ + }, \ + { \ + .name = "sd-40m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 40000000, \ + }, \ + }, \ + { \ + .name = "sd-25m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 25000000, \ + }, \ + }, \ + { \ + .name = "sd-22m", \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .output_index = -1, \ + .data.rate = { \ + .fixed_rate = 22222222, \ + }, \ + } + + +#define UNIPHIER_MIO_CLK_SD(ch, index) \ + { \ + .name = "sd" #ch "-clksel0", \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .output_index = -1, \ + .data.mux = { \ + .parent_names = { \ + "sd-44m", \ + "sd-33m", \ + "sd-50m", \ + "sd-67m", \ + }, \ + .num_parents = 4, \ + .reg = 0x30 + 0x200 * ch, \ + .shift = 16, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-clksel1", \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .output_index = -1, \ + .data.mux = { \ + .parent_names = { \ + "sd-100m", \ + "sd-40m", \ + "sd-25m", \ + "sd-22m", \ + }, \ + .num_parents = 4, \ + .reg = 0x30 + 0x200 * ch, \ + .shift = 8, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-clkmode", \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .output_index = -1, \ + .data.mux = { \ + .parent_names = { \ + "sd" #ch "-clksel0", \ + "sd" #ch "-clksel1", \ + }, \ + .num_parents = 2, \ + .reg = 0x30 + 0x200 * ch, \ + .shift = 12, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "sd" #ch "-clkmode", \ + .reg = 0x20 + 0x200 * ch, \ + .bit_idx = 8, \ + }, \ + }, \ + { \ + .name = "sd" #ch "-bridge-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "sd" #ch "-clken", \ + .reg = 0x110 + 0x200 * ch, \ + .bit_idx = 26, \ + }, \ + }, \ + { \ + .name = "sd" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "sd" #ch "-bridge-reset", \ + .reg = 0x110 + 0x200 * ch, \ + .bit_idx = 0, \ + }, \ + } + +#define UNIPHIER_MIO_CLK_SD_HW_RESET(ch, index) \ + { \ + .name = "sd" #ch "-hw-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = NULL, \ + .reg = 0x80 + 0x200 * ch, \ + .bit_idx = 0, \ + }, \ + } + +#define UNIPHIER_MIO_CLK_EHCI(ch, index) \ + { \ + .name = "ehci" #ch "-phy-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "ehci", \ + .reg = 0x20 + 0x200 * ch, \ + .bit_idx = 29, \ + }, \ + }, \ + { \ + .name = "ehci" #ch "-link-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "ehci" #ch "-phy-clken", \ + .reg = 0x20 + 0x200 * ch, \ + .bit_idx = 28, \ + }, \ + }, \ + { \ + .name = "ehci" #ch "-bridge-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "ehci" #ch "-link-clken", \ + .reg = 0x110 + 0x200 * ch, \ + .bit_idx = 24, \ + }, \ + }, \ + { \ + .name = "ehci" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "ehci" #ch "-bridge-reset", \ + .reg = 0x114 + 0x200 * ch, \ + .bit_idx = 0, \ + }, \ + } + +#define UNIPHIER_MIO_CLK_DMAC(index) \ + { \ + .name = "miodmac-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "stdmac", \ + .reg = 0x20, \ + .bit_idx = 25, \ + }, \ + }, \ + { \ + .name = "miodmac", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "miodmac-clken", \ + .reg = 0x110, \ + .bit_idx = 17, \ + }, \ + } + +static struct uniphier_clk_init_data ph1_sld3_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD_HW_RESET(0, 3), + UNIPHIER_MIO_CLK_EHCI(0, 4), + UNIPHIER_MIO_CLK_EHCI(1, 5), + UNIPHIER_MIO_CLK_EHCI(2, 6), + UNIPHIER_MIO_CLK_EHCI(3, 7), + UNIPHIER_MIO_CLK_DMAC(8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_ld4_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3), + UNIPHIER_MIO_CLK_EHCI(0, 4), + UNIPHIER_MIO_CLK_EHCI(1, 5), + UNIPHIER_MIO_CLK_EHCI(2, 6), + UNIPHIER_MIO_CLK_DMAC(8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro4_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD(2, 2), + UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3), + UNIPHIER_MIO_CLK_EHCI(0, 4), + UNIPHIER_MIO_CLK_EHCI(1, 5), + UNIPHIER_MIO_CLK_DMAC(8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro5_mio_clk_idata[] __initdata = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD_HW_RESET(1, 3), + { /* sentinel */ } +}; + +static void __init ph1_sld3_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_sld3_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_sld3_mio_clk, "socionext,ph1-sld3-mioctrl", + ph1_sld3_mio_clk_init); + +static void __init ph1_ld4_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_ld4_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_ld4_mio_clk, "socionext,ph1-ld4-mioctrl", + ph1_ld4_mio_clk_init); +CLK_OF_DECLARE(ph1_sld8_mio_clk, "socionext,ph1-sld8-mioctrl", + ph1_ld4_mio_clk_init); + +static void __init ph1_pro4_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro4_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_pro4_mio_clk, "socionext,ph1-pro4-mioctrl", + ph1_pro4_mio_clk_init); + +static void __init ph1_pro5_mio_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro5_mio_clk_idata); +} +CLK_OF_DECLARE(ph1_pro5_mio_clk, "socionext,ph1-pro5-mioctrl", + ph1_pro5_mio_clk_init); +CLK_OF_DECLARE(proxstream2_mio_clk, "socionext,proxstream2-mioctrl", + ph1_pro5_mio_clk_init); diff --git a/drivers/clk/uniphier/clk-uniphier-peri.c b/drivers/clk/uniphier/clk-uniphier-peri.c new file mode 100644 index 0000000..adaae8e --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier-peri.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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. + */ + +#include <linux/clk-provider.h> + +#include "clk-uniphier.h" + +#define UNIPHIER_PERI_CLK_UART(ch, index) \ + { \ + .name = "uart" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "uart", \ + .reg = 0x24, \ + .bit_idx = 19 + ch, \ + }, \ + }, \ + { \ + .name = "uart" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "uart" #ch "-clken", \ + .reg = 0x114, \ + .bit_idx = 19 + ch, \ + }, \ + } + +#define UNIPHIER_PERI_CLK_I2C_COMMON \ + { \ + .name = "i2c-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "i2c", \ + .reg = 0x20, \ + .bit_idx = 1, \ + }, \ + }, \ + { \ + .name = "i2c-reset", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "i2c-clken", \ + .reg = 0x110, \ + .bit_idx = 1, \ + }, \ + } + + +#define UNIPHIER_PERI_CLK_I2C(ch, index) \ + { \ + .name = "i2c" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = "i2c-reset", \ + .reg = 0x24, \ + .bit_idx = 5 + ch, \ + }, \ + }, \ + { \ + .name = "i2c" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = (index), \ + .data.gate = { \ + .parent_name = "i2c" #ch "-clken", \ + .reg = 0x114, \ + .bit_idx = 5 + ch, \ + }, \ + } + +#define UNIPHIER_PERI_CLK_FI2C(ch, index) \ + { \ + .name = "fi2c" #ch "-clken", \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = -1, \ + .data.gate = { \ + .parent_name = UNIPHIER_CLK_EXT "fi2c", \ + .reg = 0x24, \ + .bit_idx = 24 + ch, \ + }, \ + }, \ + { \ + .name = "fi2c" #ch, \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .output_index = index, \ + .data.gate = { \ + .parent_name = "fi2c" #ch "-clken", \ + .reg = 0x114, \ + .bit_idx = 24 + ch, \ + }, \ + } + +static struct uniphier_clk_init_data ph1_ld4_peri_clk_idata[] __initdata = { + UNIPHIER_PERI_CLK_UART(0, 0), + UNIPHIER_PERI_CLK_UART(1, 1), + UNIPHIER_PERI_CLK_UART(2, 2), + UNIPHIER_PERI_CLK_UART(3, 3), + UNIPHIER_PERI_CLK_I2C_COMMON, + UNIPHIER_PERI_CLK_I2C(0, 4), + UNIPHIER_PERI_CLK_I2C(1, 5), + UNIPHIER_PERI_CLK_I2C(2, 6), + UNIPHIER_PERI_CLK_I2C(3, 7), + UNIPHIER_PERI_CLK_I2C(4, 8), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro4_peri_clk_idata[] __initdata = { + UNIPHIER_PERI_CLK_UART(0, 0), + UNIPHIER_PERI_CLK_UART(1, 1), + UNIPHIER_PERI_CLK_UART(2, 2), + UNIPHIER_PERI_CLK_UART(3, 3), + UNIPHIER_PERI_CLK_FI2C(0, 4), + UNIPHIER_PERI_CLK_FI2C(1, 5), + UNIPHIER_PERI_CLK_FI2C(2, 6), + UNIPHIER_PERI_CLK_FI2C(3, 7), + /* no I2C ch4 */ + UNIPHIER_PERI_CLK_FI2C(5, 9), + UNIPHIER_PERI_CLK_FI2C(6, 10), + { /* sentinel */ } +}; + +static struct uniphier_clk_init_data ph1_pro5_peri_clk_idata[] __initdata = { + UNIPHIER_PERI_CLK_UART(0, 0), + UNIPHIER_PERI_CLK_UART(1, 1), + UNIPHIER_PERI_CLK_UART(2, 2), + UNIPHIER_PERI_CLK_UART(3, 3), + UNIPHIER_PERI_CLK_FI2C(0, 4), + UNIPHIER_PERI_CLK_FI2C(1, 5), + UNIPHIER_PERI_CLK_FI2C(2, 6), + UNIPHIER_PERI_CLK_FI2C(3, 7), + UNIPHIER_PERI_CLK_FI2C(4, 8), + UNIPHIER_PERI_CLK_FI2C(5, 9), + UNIPHIER_PERI_CLK_FI2C(6, 10), + { /* sentinel */ } +}; + +static void __init ph1_ld4_peri_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_ld4_peri_clk_idata); +} +CLK_OF_DECLARE(ph1_ld4_peri_clk, "socionext,ph1-ld4-perictrl", + ph1_ld4_peri_clk_init); +CLK_OF_DECLARE(ph1_sld8_peri_clk, "socionext,ph1-sld8-perictrl", + ph1_ld4_peri_clk_init); + +static void __init ph1_pro4_peri_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro4_peri_clk_idata); +} +CLK_OF_DECLARE(ph1_pro4_peri_clk, "socionext,ph1-pro4-perictrl", + ph1_pro4_peri_clk_init); + +static void __init ph1_pro5_peri_clk_init(struct device_node *np) +{ + uniphier_clk_init(np, ph1_pro5_peri_clk_idata); +} +CLK_OF_DECLARE(ph1_pro5_peri_clk, "socionext,ph1-pro5-perictrl", + ph1_pro5_peri_clk_init); +CLK_OF_DECLARE(proxstream2_peri_clk, "socionext,proxstream2-perictrl", + ph1_pro5_peri_clk_init); diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h new file mode 100644 index 0000000..05277b6 --- /dev/null +++ b/drivers/clk/uniphier/clk-uniphier.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * 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 __CLK_UNIPHIER_H__ +#define __CLK_UNIPHIER_H__ + +#include <linux/kernel.h> + +#define UNIPHIER_CLK_EXT "[EXT]" + +enum uniphier_clk_type { + UNIPHIER_CLK_TYPE_FIXED_FACTOR, + UNIPHIER_CLK_TYPE_FIXED_RATE, + UNIPHIER_CLK_TYPE_GATE, + UNIPHIER_CLK_TYPE_MUX, +}; + +struct uniphier_clk_fixed_factor_data { + const char *parent_name; + unsigned int mult; + unsigned int div; +}; + +struct uniphier_clk_fixed_rate_data { + unsigned long fixed_rate; +}; + +struct uniphier_clk_gate_data { + const char *parent_name; + unsigned int reg; + u8 bit_idx; +}; + +struct uniphier_clk_mux_data { + const char *parent_names[4]; + u8 num_parents; + unsigned int reg; + u8 shift; +}; + +struct uniphier_clk_init_data { + const char *name; + enum uniphier_clk_type type; + int output_index; + union { + struct uniphier_clk_fixed_factor_data factor; + struct uniphier_clk_fixed_rate_data rate; + struct uniphier_clk_gate_data gate; + struct uniphier_clk_mux_data mux; + } data; + struct clk *clk; +}; + +int uniphier_clk_init(struct device_node *np, + struct uniphier_clk_init_data *idata); + +#endif /* __CLK_UNIPHIER_H__ */ -- 1.9.1
next reply other threads:[~2015-12-28 10:21 UTC|newest] Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-12-28 10:20 Masahiro Yamada [this message] 2015-12-28 10:20 ` [PATCH v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs Masahiro Yamada 2015-12-31 1:35 ` Michael Turquette 2015-12-31 1:35 ` [PATCH v2, RESEND] " Michael Turquette 2015-12-31 1:35 ` [PATCH v2,RESEND] " Michael Turquette 2016-01-02 1:26 ` Masahiro Yamada 2016-01-02 1:26 ` [PATCH v2, RESEND] " Masahiro Yamada 2016-01-04 8:36 ` [PATCH v2,RESEND] " Michael Turquette 2016-01-04 8:36 ` [PATCH v2, RESEND] " Michael Turquette 2016-05-02 15:56 ` Masahiro Yamada 2016-05-02 15:56 ` Masahiro Yamada
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com \ --to=yamada.masahiro@socionext.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-clk@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mturquette@baylibre.com \ --cc=sboyd@codeaurora.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.