diff mbox

[v2,RESEND] clk: uniphier: add clock drivers for UniPhier SoCs

Message ID 1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com (mailing list archive)
State New, archived
Headers show

Commit Message

Masahiro Yamada Dec. 28, 2015, 10:20 a.m. UTC
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

Comments

Michael Turquette Dec. 31, 2015, 1:35 a.m. UTC | #1
Hello Yamada-san,

Quoting Masahiro Yamada (2015-12-28 02:20:58)
> 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

Might want to make the above line:

	depends on ARCH_UNIPHIER || COMPILE_TEST

> +       depends on OF
> +       default y
> +       help
> +         Supports clock drivers for UniPhier SoCs.

Why menuconfig? Can we make this a non-visible config option selected by
the UniPhier platform?

> +
> +if CLK_UNIPHIER

Please drop the if statement here and have the below options 'depends'
on CLK_UNIPHIER.

> +
> +config CLK_UNIPHIER_PH1_SLD3
> +       bool "Clock driver for UniPhier PH1-sLD3 SoC"
> +       default y

Can you make these drivers into loadable modules? If so you might
consider tristate.

> +
> +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);

Can you avoid using CLK_OF_DECLARE and instead make this into a
platform_driver? For examples please see drivers/clk/qcom*.c

> 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);

Ditto.

> 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);

Ditto.

> 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);

Ditto.

> 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);

Ditto.

> 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);

Ditto.

> 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;

Where can I find the DT binding description and DTS for this clock
controller? I'm confused why the parent name function is necessary and
I'd like to see the data.

Regards,
Mike
Masahiro Yamada Jan. 2, 2016, 1:26 a.m. UTC | #2
Hi Michael,


2015-12-31 10:35 GMT+09:00 Michael Turquette <mturquette@baylibre.com>:
> Hello Yamada-san,
>
> Quoting Masahiro Yamada (2015-12-28 02:20:58)
>> 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
>
> Might want to make the above line:
>
>         depends on ARCH_UNIPHIER || COMPILE_TEST
>
>> +       depends on OF
>> +       default y
>> +       help
>> +         Supports clock drivers for UniPhier SoCs.
>
> Why menuconfig? Can we make this a non-visible config option selected by
> the UniPhier platform?

Yes, I can do that if you like.

Do you prefer to making it flat, like all clocks are shown in the
"Common Clock Framework" menu?

Or, is it better to categorize SoC clocks with "menu" for each SoC family?



>> +
>> +if CLK_UNIPHIER
>
> Please drop the if statement here and have the below options 'depends'
> on CLK_UNIPHIER.

Why is it bad?

I think surrounding all the options with "if CLK_UNIPHIER" ... "endif"
is easier than adding "depends on CLK_UNIPHIER" to each of them.



>> +
>> +config CLK_UNIPHIER_PH1_SLD3
>> +       bool "Clock driver for UniPhier PH1-sLD3 SoC"
>> +       default y
>
> Can you make these drivers into loadable modules? If so you might
> consider tristate.

For some, I can.
For some, I can't (because they must provide an input clock for the timer.)


>> +
>> +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);
>
> Can you avoid using CLK_OF_DECLARE and instead make this into a
> platform_driver? For examples please see drivers/clk/qcom*.c


For clk-uniphier-peri.c and clk-uniphier-mio.c, yes.
They provide clocks for peripheral devices like USB, MMC, etc., so I
can delay them.


For clk-ph1-*.c, I am afraid I can't.
They provide an input clock for the timer (ARM global timer).
I think they should be initialized very early.


Is platform_driver better than CLK_OF_DECLARE() where it is possible?

I just chose CLK_OF_DECLARE() for consistency
and it seems the majority.



>> +
>> +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;
>
> Where can I find the DT binding description and DTS for this clock
> controller? I'm confused why the parent name function is necessary and
> I'd like to see the data.


clk_register() needs the name strings of parent clocks,
not pointers to parent clocks.
(It looks a bit odd to me, although it allows us to register clocks in
any order.
In stead, we have to think about orphan-walking.)
So, we need to exactly know the names of parent clocks.

Let's assume the clock system that consists of some hardware blocks.


  root_clk: root_clk {
        compatible = "foo-clk";
        reg = <0x10000000 0x1000>;
        #clock-cells = <1>;
  };

  bar_clk {
        compatible = "bar-clk";
        reg = <0x20000000 0x1000>;
        #clock-cells = <1>;
        clock-names = "input"
        clocks = <&root_clk 0>;
   };

  baz_clk {
        compatible = "baz-clk";
        reg = <0x30000000 0x1000>;
        #clock-cells = <1>;
        clock-names = "input"
        clocks = <&root_clk 1>;
   };



The "bar_clk" is a clock provider for other peripherals,
and also a consumer of "root_clk".

The "bar_clk" wants to know the name of index 0 of root_clk
because it is needed when calling clk_register().


Let's say the names of clocks provided root_clk are, "for-bar123", "for-baz456".

The "bar_clk" needs the string "for-bar123", but it does not know.
(Likewise, the "baz_clk" needs the string "for-baz456", but it does not know.)

Of course, I can hard-code "for-bar123" in the driver of "bar_clk",
but I think it is annoying to keep the name synced between the
provider and the consumer.

So, I implemented uniphier_clk_update_parent_name()
to convert the clock-names into the parent clock name.
In this case, this function takes "input" and converts it into "for-bar123".


Is there any good idea to solve this problem?
Michael Turquette Jan. 4, 2016, 8:36 a.m. UTC | #3
Quoting Masahiro Yamada (2016-01-01 17:26:05)
> Hi Michael,
> 
> 
> 2015-12-31 10:35 GMT+09:00 Michael Turquette <mturquette@baylibre.com>:
> > Hello Yamada-san,
> >
> > Quoting Masahiro Yamada (2015-12-28 02:20:58)
> >> 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
> >
> > Might want to make the above line:
> >
> >         depends on ARCH_UNIPHIER || COMPILE_TEST
> >
> >> +       depends on OF
> >> +       default y
> >> +       help
> >> +         Supports clock drivers for UniPhier SoCs.
> >
> > Why menuconfig? Can we make this a non-visible config option selected by
> > the UniPhier platform?
> 
> Yes, I can do that if you like.

Thanks, and the other questions I asked in my previous reply are
relevant here: can you make these into platform_drivers and compile them
as loadable modules? That would be ideal.

> 
> Do you prefer to making it flat, like all clocks are shown in the
> "Common Clock Framework" menu?
> 
> Or, is it better to categorize SoC clocks with "menu" for each SoC family?

The precedent is to do it flat. I'm fine with a menu though. Your
choice.

> 
> 
> 
> >> +
> >> +if CLK_UNIPHIER
> >
> > Please drop the if statement here and have the below options 'depends'
> > on CLK_UNIPHIER.
> 
> Why is it bad?
> 
> I think surrounding all the options with "if CLK_UNIPHIER" ... "endif"
> is easier than adding "depends on CLK_UNIPHIER" to each of them.

I find it more readable to clearly define the dependencies for each
config option.

> 
> 
> 
> >> +
> >> +config CLK_UNIPHIER_PH1_SLD3
> >> +       bool "Clock driver for UniPhier PH1-sLD3 SoC"
> >> +       default y
> >
> > Can you make these drivers into loadable modules? If so you might
> > consider tristate.
> 
> For some, I can.
> For some, I can't (because they must provide an input clock for the timer.)
> 
> 
> >> +
> >> +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);
> >
> > Can you avoid using CLK_OF_DECLARE and instead make this into a
> > platform_driver? For examples please see drivers/clk/qcom*.c
> 
> 
> For clk-uniphier-peri.c and clk-uniphier-mio.c, yes.
> They provide clocks for peripheral devices like USB, MMC, etc., so I
> can delay them.
> 
> 
> For clk-ph1-*.c, I am afraid I can't.
> They provide an input clock for the timer (ARM global timer).
> I think they should be initialized very early.
> 
> 
> Is platform_driver better than CLK_OF_DECLARE() where it is possible?

Yes.

> 
> I just chose CLK_OF_DECLARE() for consistency
> and it seems the majority.

I'm trying to change that.

> 
> 
> 
> >> +
> >> +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;
> >
> > Where can I find the DT binding description and DTS for this clock
> > controller?

Any update on the above question? I wasn't able to find the DT binding
description anywhere.

> I'm confused why the parent name function is necessary and
> > I'd like to see the data.
> 
> 
> clk_register() needs the name strings of parent clocks,
> not pointers to parent clocks.
> (It looks a bit odd to me, although it allows us to register clocks in
> any order.
> In stead, we have to think about orphan-walking.)

Actually, I'd like to allow a clk_register() that takes pointers to
struct clk_core for the parent. This is useful for registering clocks
whose parents are inside the same clock provider/generator/driver.

We might still need the clock parent names for registering parents across
the clock provider/generator/driver boundary. Or maybe not ... Since we
can use the phandle to fetch a struct clk_core for a clock that has
already been registered. But these are ideas for the future.

> So, we need to exactly know the names of parent clocks.
> 
> Let's assume the clock system that consists of some hardware blocks.
> 
> 
>   root_clk: root_clk {
>         compatible = "foo-clk";
>         reg = <0x10000000 0x1000>;
>         #clock-cells = <1>;
>   };
> 
>   bar_clk {
>         compatible = "bar-clk";
>         reg = <0x20000000 0x1000>;
>         #clock-cells = <1>;
>         clock-names = "input"
>         clocks = <&root_clk 0>;
>    };
> 
>   baz_clk {
>         compatible = "baz-clk";
>         reg = <0x30000000 0x1000>;
>         #clock-cells = <1>;
>         clock-names = "input"
>         clocks = <&root_clk 1>;
>    };
> 
> 
> 
> The "bar_clk" is a clock provider for other peripherals,
> and also a consumer of "root_clk".
> 
> The "bar_clk" wants to know the name of index 0 of root_clk
> because it is needed when calling clk_register().
> 
> 
> Let's say the names of clocks provided root_clk are, "for-bar123", "for-baz456".
> 
> The "bar_clk" needs the string "for-bar123", but it does not know.
> (Likewise, the "baz_clk" needs the string "for-baz456", but it does not know.)
> 
> Of course, I can hard-code "for-bar123" in the driver of "bar_clk",
> but I think it is annoying to keep the name synced between the
> provider and the consumer.

For on-chip clock providers and consumers it is usually safe to
hard-code the names since the clock configuration of the IC/SoC is
well-defined. For making board-level connections it is less safe.

Still, many clk drivers do indeed hard-code the string names for their
parent clocks.

> 
> So, I implemented uniphier_clk_update_parent_name()
> to convert the clock-names into the parent clock name.
> In this case, this function takes "input" and converts it into "for-bar123".
> 
> 
> Is there any good idea to solve this problem?

Well, using the clock-output-names DT property in conjunction with
of_clk_get_parent_name() solves this for you in a common way. However I
would like to get rid of clock-output-names in the future. In general
I'm working slowy to reduce the reliance on clock string names, but it
is a long-term side project.

How bad is it for you to hard-code the string names in your driver? Are
the foo, bar and baz clock providers all on the same chip?

Regards,
Mike

> 
> 
> -- 
> Best Regards
> Masahiro Yamada
Masahiro Yamada May 2, 2016, 3:56 p.m. UTC | #4
Hi Michael,

I am back after long pause.

2016-01-04 17:36 GMT+09:00 Michael Turquette <mturquette@baylibre.com>:
> Quoting Masahiro Yamada (2016-01-01 17:26:05)
>> Hi Michael,
>>
>>
>> 2015-12-31 10:35 GMT+09:00 Michael Turquette <mturquette@baylibre.com>:
>> > Hello Yamada-san,
>> >
>> > Quoting Masahiro Yamada (2015-12-28 02:20:58)
>> >> 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
>> >
>> > Might want to make the above line:
>> >
>> >         depends on ARCH_UNIPHIER || COMPILE_TEST
>> >
>> >> +       depends on OF
>> >> +       default y
>> >> +       help
>> >> +         Supports clock drivers for UniPhier SoCs.
>> >
>> > Why menuconfig? Can we make this a non-visible config option selected by
>> > the UniPhier platform?
>>
>> Yes, I can do that if you like.
>
> Thanks, and the other questions I asked in my previous reply are
> relevant here: can you make these into platform_drivers and compile them
> as loadable modules? That would be ideal.


I noticed a conflict between two of your requests.

If I have CLK_UNIPHIER selected by ARCH_UNIPHIER,
it is impossible to add "depends on COMPILE_TEST".


I see some drivers that have "depends on ARCH_<SOC> || COMPILE_TEST"
as follows:


config COMMON_CLK_HI6220
        bool "Hi6220 Clock Driver"
        depends on ARCH_HISI || COMPILE_TEST

config COMMON_CLK_QCOM
        tristate "Support for Qualcomm's clock controllers"
        depends on OF
        depends on ARCH_QCOM || COMPILE_TEST


I think the style above works fine with COMPILE_TEST.


But, if we make it a non-visible config option selected by ARCH,
how can COMPILE_TEST select it?


config COMMON_CLK_HI6220
        bool
        prompt "Hi6220 Clock Driver" if COMPILE_TEST

should work, but looks a bit tricky.   Hmm...






>> >
>> > Where can I find the DT binding description and DTS for this clock
>> > controller?
>
> Any update on the above question? I wasn't able to find the DT binding
> description anywhere.


OK, will add a binding document in the next version.



>>
>> So, I implemented uniphier_clk_update_parent_name()
>> to convert the clock-names into the parent clock name.
>> In this case, this function takes "input" and converts it into "for-bar123".
>>
>>
>> Is there any good idea to solve this problem?
>
> Well, using the clock-output-names DT property in conjunction with
> of_clk_get_parent_name() solves this for you in a common way. However I
> would like to get rid of clock-output-names in the future. In general
> I'm working slowy to reduce the reliance on clock string names, but it
> is a long-term side project.


I do not intend to add clock-output-names in my device trees.

of_clk_get_parent_name() tries best to take the parent name via
of_clk_get_from_provider() if clock-output-names is missing.
I wanted to use this feature.



> How bad is it for you to hard-code the string names in your driver? Are
> the foo, bar and baz clock providers all on the same chip?

No problem, but not 100% happy.

If we allow to hardcode the parent name strings,
"clock-names" and "clocks" properties are useless in clock-cascading.

Like IRQ controllers can be cascaded by "interrupts" chain,
I want to describe the hierarchy of clock-providers
without hard-coding the detail of parent.
diff mbox

Patch

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__ */