* [PATCH 00/18] Update support for RK3188, Radxa Rock board @ 2015-03-02 20:21 Andrey Panov 2015-03-02 20:21 ` [PATCH 01/18] lib: Add gcd() function Andrey Panov ` (18 more replies) 0 siblings, 19 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Hello! This series will update support for Radxa Rock board, allowing it to boot from SD card with Barebox as first-stage loader. Based on next branch. -- Andrey _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/18] lib: Add gcd() function. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-03 7:45 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 02/18] CLK: Add support for composite clock from Linux kernel Andrey Panov ` (17 subsequent siblings) 18 siblings, 1 reply; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox It calculates greatest common divisor and is compiled in only if CONFIG_GCD is selected. Signed-off-by: Andrey Panov <rockford@yandex.ru> --- include/linux/gcd.h | 12 ++++++++++++ lib/Kconfig | 3 +++ lib/Makefile | 1 + lib/gcd.c | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 include/linux/gcd.h create mode 100644 lib/gcd.c diff --git a/include/linux/gcd.h b/include/linux/gcd.h new file mode 100644 index 0000000..6405b27 --- /dev/null +++ b/include/linux/gcd.h @@ -0,0 +1,12 @@ +#ifndef _GCD_H +#define _GCD_H + +#include <linux/compiler.h> + +#if !defined(swap) +#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) +#endif + +unsigned long gcd(unsigned long a, unsigned long b) __attribute_const__; + +#endif /* _GCD_H */ diff --git a/lib/Kconfig b/lib/Kconfig index 62695f1..4b9b472 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -55,6 +55,9 @@ config LIBMTD config STMP_DEVICE bool +config GCD + bool + source lib/gui/Kconfig source lib/bootstrap/Kconfig diff --git a/lib/Makefile b/lib/Makefile index b97e52d..6f70f01 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_STMP_DEVICE) += stmp-device.o obj-y += wchar.o obj-y += libfile.o obj-y += bitmap.o +obj-$(CONFIG_GCD) += gcd.o diff --git a/lib/gcd.c b/lib/gcd.c new file mode 100644 index 0000000..dde8c9e --- /dev/null +++ b/lib/gcd.c @@ -0,0 +1,19 @@ +#include <linux/kernel.h> +#include <linux/gcd.h> + +/* Greatest common divisor */ +unsigned long gcd(unsigned long a, unsigned long b) +{ + unsigned long r; + + if (a < b) + swap(a, b); + + if (!b) + return a; + while ((r = a % b) != 0) { + a = b; + b = r; + } + return b; +} -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 01/18] lib: Add gcd() function. 2015-03-02 20:21 ` [PATCH 01/18] lib: Add gcd() function Andrey Panov @ 2015-03-03 7:45 ` Sascha Hauer 0 siblings, 0 replies; 24+ messages in thread From: Sascha Hauer @ 2015-03-03 7:45 UTC (permalink / raw) To: Andrey Panov; +Cc: barebox On Mon, Mar 02, 2015 at 11:21:45PM +0300, Andrey Panov wrote: > It calculates greatest common divisor and is > compiled in only if CONFIG_GCD is selected. > > Signed-off-by: Andrey Panov <rockford@yandex.ru> > --- > include/linux/gcd.h | 12 ++++++++++++ > lib/Kconfig | 3 +++ > lib/Makefile | 1 + > lib/gcd.c | 19 +++++++++++++++++++ > 4 files changed, 35 insertions(+) > create mode 100644 include/linux/gcd.h > create mode 100644 lib/gcd.c > > diff --git a/include/linux/gcd.h b/include/linux/gcd.h > new file mode 100644 > index 0000000..6405b27 > --- /dev/null > +++ b/include/linux/gcd.h > @@ -0,0 +1,12 @@ > +#ifndef _GCD_H > +#define _GCD_H > + > +#include <linux/compiler.h> > + > +#if !defined(swap) > +#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) > +#endiif Please add this to a location where others can use it, maybe include/linux/kernel.h. > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -52,3 +52,4 @@ obj-$(CONFIG_STMP_DEVICE) += stmp-device.o > obj-y += wchar.o > obj-y += libfile.o > obj-y += bitmap.o > +obj-$(CONFIG_GCD) += gcd.o You can safely always compile it without adding an extra option. The linker will throw it away when it's unused. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 02/18] CLK: Add support for composite clock from Linux kernel. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov 2015-03-02 20:21 ` [PATCH 01/18] lib: Add gcd() function Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-03 7:48 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 03/18] CLK: Add fractional divider clock support " Andrey Panov ` (16 subsequent siblings) 18 siblings, 1 reply; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Arch Kconfig should select CLK_NEED_COMPOSITE to have this support compiled in. Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/Kconfig | 3 + drivers/clk/Makefile | 1 + drivers/clk/clk-composite.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk.h | 6 ++ 4 files changed, 156 insertions(+) create mode 100644 drivers/clk/clk-composite.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1cf0ccb..6db1f33 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -8,6 +8,9 @@ config COMMON_CLK select HAVE_CLK bool +config CLK_NEED_COMPOSITE + bool + config COMMON_CLK_OF_PROVIDER bool help diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index fa707dd..bdd93f5 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \ clk-mux.o clk-gate.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o +obj-$(CONFIG_CLK_NEED_COMPOSITE) += clk-composite.o obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_ARCH_MXS) += mxs/ diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c new file mode 100644 index 0000000..a4fc03d --- /dev/null +++ b/drivers/clk/clk-composite.c @@ -0,0 +1,146 @@ +/* + * Taken from linux/drivers/clk/ + * + * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <io.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/err.h> + +struct clk_composite { + struct clk clk; + + struct clk *mux_clk; + struct clk *rate_clk; + struct clk *gate_clk; +}; + +static int clk_composite_get_parent(struct clk *clk) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *mux_clk = composite->mux_clk; + + return mux_clk?mux_clk->ops->get_parent(mux_clk):0; +} + +static int clk_composite_set_parent(struct clk *clk, u8 index) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *mux_clk = composite->mux_clk; + + return mux_clk?mux_clk->ops->set_parent(mux_clk, index):0; +} + +static unsigned long clk_composite_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *rate_clk = composite->rate_clk; + + return rate_clk?rate_clk->ops->recalc_rate(rate_clk, parent_rate):0; +} + +static long clk_composite_round_rate(struct clk *clk, unsigned long rate, + unsigned long *prate) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *rate_clk = composite->rate_clk; + + return rate_clk?rate_clk->ops->round_rate(rate_clk, rate, prate):0; +} + +static int clk_composite_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *rate_clk = composite->rate_clk; + + return rate_clk?rate_clk->ops->set_rate(rate_clk, rate, parent_rate):0; +} + +static int clk_composite_is_enabled(struct clk *clk) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *gate_clk = composite->gate_clk; + + return gate_clk?gate_clk->ops->is_enabled(gate_clk):0; +} + +static int clk_composite_enable(struct clk *clk) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *gate_clk = composite->gate_clk; + + return gate_clk?gate_clk->ops->enable(gate_clk):0; +} + +static void clk_composite_disable(struct clk *clk) +{ + struct clk_composite *composite = container_of(clk, struct clk_composite, clk); + struct clk *gate_clk = composite->gate_clk; + + if(gate_clk) + gate_clk->ops->disable(gate_clk); +} + +static struct clk_ops clk_composite_ops = { + .get_parent = clk_composite_get_parent, + .set_parent = clk_composite_set_parent, + .recalc_rate = clk_composite_recalc_rate, + .round_rate = clk_composite_round_rate, + .set_rate = clk_composite_set_rate, + .is_enabled = clk_composite_is_enabled, + .enable = clk_composite_enable, + .disable = clk_composite_disable, +}; + +struct clk *clk_register_composite(const char *name, + const char **parent_names, int num_parents, + struct clk *mux_clk, + struct clk *rate_clk, + struct clk *gate_clk, + unsigned long flags) +{ + struct clk_composite *composite; + int ret; + + composite = kzalloc(sizeof(*composite), GFP_KERNEL); + if (!composite) { + pr_err("%s: could not allocate composite clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + composite->clk.name = name; + composite->clk.ops = &clk_composite_ops; + composite->clk.flags = flags; + composite->clk.parent_names = parent_names; + composite->clk.num_parents = num_parents; + composite->mux_clk = mux_clk; + composite->rate_clk = rate_clk; + composite->gate_clk = gate_clk; + + ret = clk_register(&composite->clk); + if (ret) + goto err; + + return &composite->clk; + +err: + kfree(composite); + return 0; +} diff --git a/include/linux/clk.h b/include/linux/clk.h index 49cb5a2..fe8ae5c 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -291,6 +291,12 @@ struct clk *clk_lookup(const char *name); void clk_dump(int verbose); +struct clk *clk_register_composite(const char *name, + const char **parent_names, int num_parents, + struct clk *mux_clk, + struct clk *rate_clk, + struct clk *gate_clk, + unsigned long flags); #endif struct device_node; -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/18] CLK: Add support for composite clock from Linux kernel. 2015-03-02 20:21 ` [PATCH 02/18] CLK: Add support for composite clock from Linux kernel Andrey Panov @ 2015-03-03 7:48 ` Sascha Hauer 0 siblings, 0 replies; 24+ messages in thread From: Sascha Hauer @ 2015-03-03 7:48 UTC (permalink / raw) To: Andrey Panov; +Cc: barebox On Mon, Mar 02, 2015 at 11:21:46PM +0300, Andrey Panov wrote: > Arch Kconfig should select CLK_NEED_COMPOSITE to have this support > compiled in. > > Signed-off-by: Andrey Panov <rockford@yandex.ru> > --- > drivers/clk/Kconfig | 3 + > drivers/clk/Makefile | 1 + > drivers/clk/clk-composite.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/clk.h | 6 ++ > 4 files changed, 156 insertions(+) > create mode 100644 drivers/clk/clk-composite.c > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig > index 1cf0ccb..6db1f33 100644 > --- a/drivers/clk/Kconfig > +++ b/drivers/clk/Kconfig > @@ -8,6 +8,9 @@ config COMMON_CLK > select HAVE_CLK > bool > > +config CLK_NEED_COMPOSITE > + bool > + > config COMMON_CLK_OF_PROVIDER > bool > help > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile > index fa707dd..bdd93f5 100644 > --- a/drivers/clk/Makefile > +++ b/drivers/clk/Makefile > @@ -1,6 +1,7 @@ > obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \ > clk-mux.o clk-gate.o > obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o > +obj-$(CONFIG_CLK_NEED_COMPOSITE) += clk-composite.o Same here, no need for a separate option. You can add this to the obj-$(CONFIG_COMMON_CLK) list above. > + > +static struct clk_ops clk_composite_ops = { > + .get_parent = clk_composite_get_parent, > + .set_parent = clk_composite_set_parent, > + .recalc_rate = clk_composite_recalc_rate, > + .round_rate = clk_composite_round_rate, Indention broken here. > +struct clk *clk_register_composite(const char *name, > + const char **parent_names, int num_parents, > + struct clk *mux_clk, > + struct clk *rate_clk, > + struct clk *gate_clk, > + unsigned long flags) > +{ > + struct clk_composite *composite; > + int ret; > + > + composite = kzalloc(sizeof(*composite), GFP_KERNEL); > + if (!composite) { > + pr_err("%s: could not allocate composite clk\n", __func__); > + return ERR_PTR(-ENOMEM); > + } Please use xzalloc here. You can skip the error check then. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 03/18] CLK: Add fractional divider clock support from Linux kernel. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov 2015-03-02 20:21 ` [PATCH 01/18] lib: Add gcd() function Andrey Panov 2015-03-02 20:21 ` [PATCH 02/18] CLK: Add support for composite clock from Linux kernel Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-03 7:51 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 04/18] CLK: clk-mux: Respect CLK_MUX_HIWORD_MASK flag Andrey Panov ` (15 subsequent siblings) 18 siblings, 1 reply; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Arch Kconfig should select CLK_NEED_FDIV to have this support compiled in. Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/Kconfig | 3 + drivers/clk/Makefile | 1 + drivers/clk/clk-fractional-divider.c | 156 +++++++++++++++++++++++++++++++++++ include/linux/clk.h | 9 ++ 4 files changed, 169 insertions(+) create mode 100644 drivers/clk/clk-fractional-divider.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6db1f33..e82b566 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -11,6 +11,9 @@ config COMMON_CLK config CLK_NEED_COMPOSITE bool +config CLK_NEED_FDIV + bool + config COMMON_CLK_OF_PROVIDER bool help diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index bdd93f5..47c7441 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \ clk-mux.o clk-gate.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_CLK_NEED_COMPOSITE) += clk-composite.o +obj-$(CONFIG_CLK_NEED_FDIV) += clk-fractional-divider.o obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_ARCH_MXS) += mxs/ diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c new file mode 100644 index 0000000..2f5d759 --- /dev/null +++ b/drivers/clk/clk-fractional-divider.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2014 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Adjustable fractional divider clock implementation. + * Output rate = (m / n) * parent_rate. + */ + +#include <common.h> +#include <io.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/gcd.h> +#include <linux/math64.h> +#include <linux/barebox-wrapper.h> + +#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, clk) + +struct clk_fractional_divider { + struct clk clk; + void __iomem *reg; + u8 mshift; + u32 mmask; + u8 nshift; + u32 nmask; + u8 flags; +}; + +static unsigned long clk_fd_recalc_rate(struct clk *hw, + unsigned long parent_rate) +{ + struct clk_fractional_divider *fd = to_clk_fd(hw); + u32 val, m, n; + u64 ret; + + val = readl(fd->reg); + + m = (val & fd->mmask) >> fd->mshift; + n = (val & fd->nmask) >> fd->nshift; + + ret = (u64)parent_rate * m; + do_div(ret, n); + + return ret; +} + +static long clk_fd_round_rate(struct clk *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned maxn = (fd->nmask >> fd->nshift) + 1; + unsigned div; + + if (!rate || rate >= *prate) + return *prate; + + div = gcd(*prate, rate); + + while ((*prate / div) > maxn) { + div <<= 1; + rate <<= 1; + } + + return rate; +} + +static int clk_fd_set_rate(struct clk *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned long div; + unsigned n, m; + u32 val; + + div = gcd(parent_rate, rate); + m = rate / div; + n = parent_rate / div; + + val = readl(fd->reg); + val &= ~(fd->mmask | fd->nmask); + val |= (m << fd->mshift) | (n << fd->nshift); + writel(val, fd->reg); + + return 0; +} + +const struct clk_ops clk_fractional_divider_ops = { + .recalc_rate = clk_fd_recalc_rate, + .round_rate = clk_fd_round_rate, + .set_rate = clk_fd_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); + +struct clk *clk_fractional_divider_alloc( + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags) +{ + struct clk_fractional_divider *fd; + + fd = kzalloc(sizeof(*fd), GFP_KERNEL); + if (!fd) { + pr_err("could not allocate fractional divider clk %s\n", name); + return ERR_PTR(-ENOMEM); + } + + fd->reg = reg; + fd->mshift = mshift; + fd->mmask = (BIT(mwidth) - 1) << mshift; + fd->nshift = nshift; + fd->nmask = (BIT(nwidth) - 1) << nshift; + fd->flags = clk_divider_flags; + fd->clk.name = name; + fd->clk.ops = &clk_fractional_divider_ops; + fd->clk.flags = flags; + fd->clk.parent_names = parent_name ? &parent_name : NULL; + fd->clk.num_parents = parent_name ? 1 : 0; + + return &fd->clk; +} + +void clk_fractional_divider_free(struct clk *clk_fd) +{ + struct clk_fractional_divider *fd = to_clk_fd(clk_fd); + + free(fd); +} + +struct clk *clk_fractional_divider( + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags) +{ + struct clk *fd; + int ret; + + fd = clk_fractional_divider_alloc(name, parent_name,flags, + reg, mshift, mwidth, nshift, nwidth, + clk_divider_flags); + + if (IS_ERR(fd)) + return fd; + + ret = clk_register(fd); + if (ret){ + clk_fractional_divider_free(fd); + return ERR_PTR(ret); + } + + return fd; +} +EXPORT_SYMBOL_GPL(clk_register_fractional_divider); diff --git a/include/linux/clk.h b/include/linux/clk.h index fe8ae5c..de2d4a5 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -260,6 +260,15 @@ struct clk *clk_divider_table(const char *name, struct clk *clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div, unsigned flags); +struct clk *clk_fractional_divider_alloc( + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags); +struct clk *clk_fractional_divider( + const char *name, const char *parent_name, unsigned long flags, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags); +void clk_fractional_divider_free(struct clk *clk_fd); struct clk *clk_mux_alloc(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, u8 num_parents, -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 03/18] CLK: Add fractional divider clock support from Linux kernel. 2015-03-02 20:21 ` [PATCH 03/18] CLK: Add fractional divider clock support " Andrey Panov @ 2015-03-03 7:51 ` Sascha Hauer 0 siblings, 0 replies; 24+ messages in thread From: Sascha Hauer @ 2015-03-03 7:51 UTC (permalink / raw) To: Andrey Panov; +Cc: barebox On Mon, Mar 02, 2015 at 11:21:47PM +0300, Andrey Panov wrote: > Arch Kconfig should select CLK_NEED_FDIV to have this support > compiled in. > > Signed-off-by: Andrey Panov <rockford@yandex.ru> > --- > drivers/clk/Kconfig | 3 + > drivers/clk/Makefile | 1 + > drivers/clk/clk-fractional-divider.c | 156 +++++++++++++++++++++++++++++++++++ > include/linux/clk.h | 9 ++ > 4 files changed, 169 insertions(+) > create mode 100644 drivers/clk/clk-fractional-divider.c > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig > index 6db1f33..e82b566 100644 > --- a/drivers/clk/Kconfig > +++ b/drivers/clk/Kconfig > @@ -11,6 +11,9 @@ config COMMON_CLK > config CLK_NEED_COMPOSITE > bool > > +config CLK_NEED_FDIV > + bool > + No separate option needed. > +struct clk *clk_fractional_divider_alloc( > + const char *name, const char *parent_name, unsigned long flags, > + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, > + u8 clk_divider_flags) > +{ > + struct clk_fractional_divider *fd; > + > + fd = kzalloc(sizeof(*fd), GFP_KERNEL); > + if (!fd) { > + pr_err("could not allocate fractional divider clk %s\n", name); > + return ERR_PTR(-ENOMEM); > + } xzalloc Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 04/18] CLK: clk-mux: Respect CLK_MUX_HIWORD_MASK flag. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (2 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 03/18] CLK: Add fractional divider clock support " Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 05/18] CLK: clk-divider: Respect CLK_DIVIDER_HIWORD_MASK flag Andrey Panov ` (14 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox It is required for Rockchip SoCs where clock settings registers have write-enable mask in high word. Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/clk-mux.c | 3 +++ include/linux/clk.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 4ce86f4..22e131f 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -45,6 +45,9 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx) val = readl(m->reg); val &= ~(((1 << m->width) - 1) << m->shift); val |= idx << m->shift; + + if (clk->flags & CLK_MUX_HIWORD_MASK) + val |= ((1 << m->width) - 1) << (m->shift + 16); writel(val, m->reg); return 0; diff --git a/include/linux/clk.h b/include/linux/clk.h index de2d4a5..89cb44e 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -248,6 +248,8 @@ struct clk_divider { int table_size; }; +#define CLK_MUX_HIWORD_MASK (1 << 2) + extern struct clk_ops clk_divider_ops; struct clk *clk_divider(const char *name, const char *parent, -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 05/18] CLK: clk-divider: Respect CLK_DIVIDER_HIWORD_MASK flag. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (3 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 04/18] CLK: clk-mux: Respect CLK_MUX_HIWORD_MASK flag Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 06/18] CLK: clk-divider: Introduce clk_divider_alloc() and *_free() routines Andrey Panov ` (13 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox It is required for Rockchip SoCs where clock settings registers have write-enable mask in high word. Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/clk-divider.c | 4 ++++ include/linux/clk.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 506a966..eb48334 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -197,6 +197,10 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate, val = readl(divider->reg); val &= ~(div_mask(divider) << divider->shift); val |= value << divider->shift; + + if (clk->flags & CLK_DIVIDER_HIWORD_MASK) + val |= div_mask(divider) << (divider->shift + 16); + writel(val, divider->reg); return 0; diff --git a/include/linux/clk.h b/include/linux/clk.h index 89cb44e..258bbe3 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -248,6 +248,8 @@ struct clk_divider { int table_size; }; +#define CLK_DIVIDER_HIWORD_MASK (1 << 3) + #define CLK_MUX_HIWORD_MASK (1 << 2) extern struct clk_ops clk_divider_ops; -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 06/18] CLK: clk-divider: Introduce clk_divider_alloc() and *_free() routines. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (4 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 05/18] CLK: clk-divider: Respect CLK_DIVIDER_HIWORD_MASK flag Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 07/18] CLK: clk-divider: Respect CLK_DIVIDER_POWER_OF_TWO flag Andrey Panov ` (12 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/clk-divider.c | 27 ++++++++++++++++++++++----- include/linux/clk.h | 3 +++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index eb48334..82b11ad 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -212,11 +212,10 @@ struct clk_ops clk_divider_ops = { .round_rate = clk_divider_round_rate, }; -struct clk *clk_divider(const char *name, const char *parent, +struct clk *clk_divider_alloc(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width, unsigned flags) { struct clk_divider *div = xzalloc(sizeof(*div)); - int ret; div->shift = shift; div->reg = reg; @@ -228,13 +227,31 @@ struct clk *clk_divider(const char *name, const char *parent, div->clk.parent_names = &div->parent; div->clk.num_parents = 1; - ret = clk_register(&div->clk); + return &div->clk; +} + +void clk_divider_free(struct clk *clk_divider) +{ + struct clk_divider *d = container_of(clk_divider, struct clk_divider, clk); + + free(d); +} + +struct clk *clk_divider(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, unsigned flags) +{ + struct clk *d; + int ret; + + d = clk_divider_alloc(name , parent, reg, shift, width, flags); + + ret = clk_register(d); if (ret) { - free(div); + clk_divider_free(d); return ERR_PTR(ret); } - return &div->clk; + return d; } struct clk *clk_divider_one_based(const char *name, const char *parent, diff --git a/include/linux/clk.h b/include/linux/clk.h index 258bbe3..65d3e99 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -254,6 +254,9 @@ struct clk_divider { extern struct clk_ops clk_divider_ops; +struct clk *clk_divider_alloc(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, unsigned flags); +void clk_divider_free(struct clk *clk_divider); struct clk *clk_divider(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width, unsigned flags); struct clk *clk_divider_one_based(const char *name, const char *parent, -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 07/18] CLK: clk-divider: Respect CLK_DIVIDER_POWER_OF_TWO flag. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (5 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 06/18] CLK: clk-divider: Introduce clk_divider_alloc() and *_free() routines Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 08/18] CLK: Check and do not allow to register clock twice Andrey Panov ` (11 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/clk-divider.c | 9 +++++++++ include/linux/clk.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 82b11ad..4da4c5a 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -19,6 +19,7 @@ #include <malloc.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/log2.h> #define div_mask(d) ((1 << ((d)->width)) - 1) @@ -26,6 +27,8 @@ static unsigned int _get_maxdiv(struct clk_divider *divider) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return div_mask(divider); + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << div_mask(divider); return div_mask(divider) + 1; } @@ -44,6 +47,8 @@ static unsigned int _get_div(struct clk_divider *divider, unsigned int val) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return val; + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << val; if (divider->table) return _get_table_div(divider->table, val); return val + 1; @@ -64,6 +69,8 @@ static unsigned int _get_val(struct clk_divider *divider, unsigned int div) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return div; + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return __ffs(div); if (divider->table) return _get_table_val(divider->table, div); return div - 1; @@ -102,6 +109,8 @@ static bool _is_valid_table_div(const struct clk_div_table *table, static bool _is_valid_div(struct clk_divider *divider, unsigned int div) { + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + return is_power_of_2(div); if (divider->table) return _is_valid_table_div(divider->table, div); return true; diff --git a/include/linux/clk.h b/include/linux/clk.h index 65d3e99..56890a0 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -248,6 +248,7 @@ struct clk_divider { int table_size; }; +#define CLK_DIVIDER_POWER_OF_TWO (1 << 1) #define CLK_DIVIDER_HIWORD_MASK (1 << 3) #define CLK_MUX_HIWORD_MASK (1 << 2) -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 08/18] CLK: Check and do not allow to register clock twice. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (6 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 07/18] CLK: clk-divider: Respect CLK_DIVIDER_POWER_OF_TWO flag Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-03 9:03 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 09/18] CLK: Add helper defines to barebox-wrapper.h for easier porting of drivers from Linux kernel Andrey Panov ` (10 subsequent siblings) 18 siblings, 1 reply; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/clk.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 584e2f3..5f78c9c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -212,8 +212,17 @@ struct clk *clk_get_parent(struct clk *clk) int clk_register(struct clk *clk) { + struct clk *c; + clk->parents = xzalloc(sizeof(struct clk *) * clk->num_parents); + list_for_each_entry(c, &clks, list) { + if (!strcmp(c->name, clk->name)){ + pr_err("%s clk %s is already registered, skipping!\n", __func__, clk->name); + return 0; + } + } + list_add_tail(&clk->list, &clks); return 0; -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 08/18] CLK: Check and do not allow to register clock twice. 2015-03-02 20:21 ` [PATCH 08/18] CLK: Check and do not allow to register clock twice Andrey Panov @ 2015-03-03 9:03 ` Sascha Hauer 0 siblings, 0 replies; 24+ messages in thread From: Sascha Hauer @ 2015-03-03 9:03 UTC (permalink / raw) To: Andrey Panov; +Cc: barebox On Mon, Mar 02, 2015 at 11:21:52PM +0300, Andrey Panov wrote: > Signed-off-by: Andrey Panov <rockford@yandex.ru> > --- > drivers/clk/clk.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c > index 584e2f3..5f78c9c 100644 > --- a/drivers/clk/clk.c > +++ b/drivers/clk/clk.c > @@ -212,8 +212,17 @@ struct clk *clk_get_parent(struct clk *clk) > > int clk_register(struct clk *clk) > { > + struct clk *c; > + > clk->parents = xzalloc(sizeof(struct clk *) * clk->num_parents); > > + list_for_each_entry(c, &clks, list) { > + if (!strcmp(c->name, clk->name)){ > + pr_err("%s clk %s is already registered, skipping!\n", __func__, clk->name); > + return 0; > + } > + } Why return 0 here? This should return -EBUSY. Also please move this check above the memory allocation. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 09/18] CLK: Add helper defines to barebox-wrapper.h for easier porting of drivers from Linux kernel. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (7 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 08/18] CLK: Check and do not allow to register clock twice Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 10/18] NET: arc_emac: Update for newer DTS, support for Rockchip .compatible Andrey Panov ` (9 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- include/linux/barebox-wrapper.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/barebox-wrapper.h b/include/linux/barebox-wrapper.h index d34d1d1..cbc8934 100644 --- a/include/linux/barebox-wrapper.h +++ b/include/linux/barebox-wrapper.h @@ -73,4 +73,10 @@ typedef int irqreturn_t; #define IRQ_NONE 0 #define IRQ_HANDLED 0 +/* To ease clk drivers porting from Linux kernel */ +#define __clk_get_name(clk) clk->name +#define __clk_lookup clk_lookup +#define __clk_get_rate clk_get_rate +#define __clk_get_parent clk_get_parent + #endif /* __INCLUDE_LINUX_BAREBOX_WRAPPER_H */ -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 10/18] NET: arc_emac: Update for newer DTS, support for Rockchip .compatible. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (8 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 09/18] CLK: Add helper defines to barebox-wrapper.h for easier porting of drivers from Linux kernel Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 11/18] MMC: dw_mmc: Add support for PIO mode and Rockchip variant of this hardware Andrey Panov ` (8 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/net/arc_emac.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/net/arc_emac.c b/drivers/net/arc_emac.c index 4bf456e..5a056d3 100644 --- a/drivers/net/arc_emac.c +++ b/drivers/net/arc_emac.c @@ -23,6 +23,7 @@ #include <io.h> #include <init.h> #include <linux/err.h> +#include <linux/clk.h> /* ARC EMAC register set combines entries for MAC and MDIO */ enum { @@ -99,6 +100,8 @@ struct arc_emac_priv { u8 *rxbuf; unsigned int txbd_curr; unsigned int last_rx_bd; + struct clk *clk; + struct clk *refclk; }; /** @@ -384,20 +387,18 @@ static int arc_emac_mdio_write(struct mii_bus *bus, int phy_addr, int reg_num, return arc_mdio_complete_wait(priv); } +#define DEFAULT_EMAC_CLOCK_FREQUENCY 50000000UL; + static int arc_emac_probe(struct device_d *dev) { struct eth_device *edev; struct arc_emac_priv *priv; - unsigned int clock_frequency; + unsigned long clock_frequency; struct mii_bus *miibus; u32 id; - /* Get CPU clock frequency from device tree */ - if (of_property_read_u32(dev->device_node, "clock-frequency", - &clock_frequency)) { - dev_err(dev, "failed to retrieve <clock-frequency> from device tree\n"); - return -EINVAL; - } + /* clock-frequency is dropped from DTS, so hardcode it here */ + clock_frequency = DEFAULT_EMAC_CLOCK_FREQUENCY; edev = xzalloc(sizeof(struct eth_device) + sizeof(struct arc_emac_priv)); @@ -410,6 +411,13 @@ static int arc_emac_probe(struct device_d *dev) return PTR_ERR(priv->regs); priv->bus = miibus; + priv->clk = clk_get(dev, "hclk"); + clk_enable(priv->clk); + + priv->refclk = clk_get(dev, "macref"); + clk_set_rate(priv->refclk,clock_frequency); + clk_enable(priv->refclk); + id = arc_reg_get(priv, R_ID); /* Check for EMAC revision 5 or 7, magic number */ if (!(id == 0x0005fd02 || id == 0x0007fd02)) { @@ -455,6 +463,8 @@ static __maybe_unused struct of_device_id arc_emac_dt_ids[] = { { .compatible = "snps,arc-emac", }, { + .compatible = "rockchip,rk3188-emac", + }, { /* sentinel */ } }; -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 11/18] MMC: dw_mmc: Add support for PIO mode and Rockchip variant of this hardware. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (9 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 10/18] NET: arc_emac: Update for newer DTS, support for Rockchip .compatible Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 12/18] ARM: Rockchip: Remove unused files from mach-rockchip Andrey Panov ` (7 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/mci/Kconfig | 8 ++- drivers/mci/dw_mmc.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 170 insertions(+), 8 deletions(-) diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index a5cf2fe..17bf0d3 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -36,12 +36,18 @@ comment "--- MCI host drivers ---" config MCI_DW bool "Synopsys DesignWare Memory Card Interface" - depends on HAS_DMA + depends on ARM help This selects support for the Synopsys DesignWare Mobile Storage IP block, this provides host support for SD and MMC interfaces, in both PIO and external DMA modes. +config MCI_DW_PIO + bool "Use PIO mode on Synopsys DesignWare MCI" + depends on MCI_DW + help + Use PIO mode (instead of IDMAC) in DW MMC driver. + config MCI_MXS bool "i.MX23/i.MX28" depends on ARCH_MXS diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c index f02ea62..0360a22 100644 --- a/drivers/mci/dw_mmc.c +++ b/drivers/mci/dw_mmc.c @@ -125,6 +125,8 @@ #define DWMCI_CTYPE_8BIT (1 << 16) /* Status Register */ +#define DWMCI_STATUS_FIFO_EMPTY (1 << 2) +#define DWMCI_STATUS_FIFO_FULL (1 << 3) #define DWMCI_STATUS_BUSY (1 << 9) /* FIFOTH Register */ @@ -153,6 +155,8 @@ struct dwmci_host { struct dwmci_idmac *idmac; unsigned long clkrate; int ciu_div; + u32 fifoth_val; + u32 pwren_value; }; struct dwmci_idmac { @@ -201,6 +205,8 @@ static int dwmci_prepare_data(struct dwmci_host *host, struct mci_data *data) { unsigned long ctrl; + +#ifndef CONFIG_MCI_DW_PIO unsigned int i = 0, flags, cnt, blk_cnt; unsigned long data_start, start_addr; struct dwmci_idmac *desc = host->idmac; @@ -256,7 +262,25 @@ static int dwmci_prepare_data(struct dwmci_host *host, dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize); dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks); +#else + /* PIO MODE */ + dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET); + dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_TXDR | DWMCI_INTMSK_RXDR); + + ctrl = dwmci_readl(host, DWMCI_INTMASK); + ctrl |= DWMCI_INTMSK_TXDR | DWMCI_INTMSK_RXDR; + dwmci_writel(host, DWMCI_INTMASK, ctrl); + + ctrl = dwmci_readl(host, DWMCI_CTRL); + ctrl &= ~(DWMCI_IDMAC_EN | DWMCI_DMA_EN); + dwmci_writel(host, DWMCI_CTRL, ctrl); + + dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val); + dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF); + dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize); + dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks); +#endif return 0; } @@ -272,12 +296,108 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host, return mode; } +#ifdef CONFIG_MCI_DW_PIO +static int dwmci_read_data_pio(struct dwmci_host *host, struct mci_data *data) +{ + u32 *pdata = (u32 *)data->dest; + u32 val, status, timeout; + u32 fcnt, bcnt, rcnt, rlen = 0; + + timeout = 100; + status = dwmci_readl(host, DWMCI_RINTSTS); + while (--timeout && !(status & DWMCI_INTMSK_RXDR)){ + status = dwmci_readl(host, DWMCI_RINTSTS); + } + + if(!timeout){ + dev_err(host->dev, "%s: RX ready wait timeout\n", __func__); + return 0; + } + + fcnt = data->blocksize; + bcnt = data->blocks; + + do { + for (rcnt = fcnt>>2; rcnt; rcnt--) { + timeout = 20000; + status = dwmci_readl(host, DWMCI_STATUS); + while (--timeout && (status & DWMCI_STATUS_FIFO_EMPTY)){ + udelay(200); + status = dwmci_readl(host, DWMCI_STATUS); + } + if(!timeout){ + dev_err(host->dev, "%s: FIFO underflow timeout\n", + __func__); + break; + } + + val = dwmci_readl(host, DWMCI_DATA); + + *pdata++ = val; + rlen+=4; + } + status = dwmci_readl(host, DWMCI_RINTSTS); + dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_RXDR); + } while (--bcnt && (status & DWMCI_INTMSK_RXDR)); + + return rlen; +} + +static int dwmci_write_data_pio(struct dwmci_host *host, struct mci_data *data) +{ + u32 *pdata = (u32 *)data->src; + u32 status, timeout; + u32 fcnt, bcnt, wcnt, wlen = 0; + + fcnt = host->fifo_size_bytes; + + bcnt = (data->blocks*data->blocksize)/fcnt; + + timeout = 100; + status = dwmci_readl(host, DWMCI_RINTSTS); + + while (--timeout && !(status & DWMCI_INTMSK_TXDR)){ + status = dwmci_readl(host, DWMCI_RINTSTS); + } + + if(!timeout){ + dev_err(host->dev, "%s: TX ready wait timeout\n", __func__); + return 0; + } + + do { + for (wcnt = fcnt>>2; wcnt; wcnt--) { + timeout = 20000; + status = dwmci_readl(host, DWMCI_STATUS); + while (--timeout && (status & DWMCI_STATUS_FIFO_FULL)){ + udelay(200); + status = dwmci_readl(host, DWMCI_STATUS); + } + if(!timeout){ + dev_err(host->dev, "%s: FIFO overflow timeout\n", + __func__); + break; + } + dwmci_writel(host, DWMCI_DATA, *pdata++); + wlen+=4; + } + status = dwmci_readl(host, DWMCI_RINTSTS); + dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_TXDR); + } while (--bcnt && (status & DWMCI_INTMSK_TXDR)); + + return wlen; +} +#endif + static int dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) { struct dwmci_host *host = to_dwmci_host(mci); int flags = 0; - uint32_t mask, ctrl; + uint32_t mask; +#ifndef CONFIG_MCI_DW_PIO + uint32_t ctrl; +#endif uint64_t start; int ret; unsigned int num_bytes = 0; @@ -346,8 +466,10 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) dwmci_writel(host, DWMCI_RINTSTS, mask); break; } - if (is_timeout(start, 100 * MSECOND)) + if (is_timeout(start, 100 * MSECOND)){ + dev_dbg(host->dev, "Send command timeout..\n"); return -ETIMEDOUT; + } } if (mask & DWMCI_INTMSK_RTO) { @@ -373,16 +495,34 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) start = get_time_ns(); do { mask = dwmci_readl(host, DWMCI_RINTSTS); +#ifdef CONFIG_MCI_DW_PIO + if (mask & (DWMCI_DATA_ERR)) { +#else if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { +#endif dev_dbg(host->dev, "DATA ERROR!\n"); return -EIO; } - if (is_timeout(start, SECOND)) +#ifndef CONFIG_MCI_DW_PIO + if (is_timeout(start, SECOND)){ +#else + if (is_timeout(start, SECOND*100)){ + /* In PIO end transfer can take more than a second, give it a chance */ +#endif + dev_dbg(host->dev, "Data timeout\n"); return -ETIMEDOUT; + } +#ifdef CONFIG_MCI_DW_PIO + if (mask & DWMCI_INTMSK_RXDR) + dwmci_read_data_pio(host, data); + if (mask & DWMCI_INTMSK_TXDR) + dwmci_write_data_pio(host, data); +#endif } while (!(mask & DWMCI_INTMSK_DTO)); dwmci_writel(host, DWMCI_RINTSTS, mask); +#ifndef CONFIG_MCI_DW_PIO ctrl = dwmci_readl(host, DWMCI_CTRL); ctrl &= ~(DWMCI_DMA_EN); dwmci_writel(host, DWMCI_CTRL, ctrl); @@ -393,6 +533,7 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) else dma_sync_single_for_cpu((unsigned long)data->dest, num_bytes, DMA_FROM_DEVICE); +#endif } udelay(100); @@ -481,9 +622,9 @@ static int dwmci_card_present(struct mci_host *mci) static int dwmci_init(struct mci_host *mci, struct device_d *dev) { struct dwmci_host *host = to_dwmci_host(mci); - uint32_t fifo_size, fifoth_val; + uint32_t fifo_size; - dwmci_writel(host, DWMCI_PWREN, 1); + dwmci_writel(host, DWMCI_PWREN, host->pwren_value); if (dwmci_wait_reset(host, DWMCI_RESET_ALL)) { dev_err(host->dev, "reset failed\n"); @@ -507,11 +648,19 @@ static int dwmci_init(struct mci_host *mci, struct device_d *dev) fifo_size = DWMCI_FIFOTH_FIFO_DEPTH(fifo_size); host->fifo_size_bytes = fifo_size * 4; - fifoth_val = DWMCI_FIFOTH_MSIZE(0x2) | + /* + * If fifo-depth property is set, use this value + */ + if (!of_property_read_u32(host->dev->device_node, "fifo-depth", &fifo_size)){ + host->fifo_size_bytes = fifo_size; + dev_dbg(host->dev, "Using fifo-depth=%u\n", host->fifo_size_bytes); + } + + host->fifoth_val = DWMCI_FIFOTH_MSIZE(0x2) | DWMCI_FIFOTH_RX_WMARK(fifo_size / 2 - 1) | DWMCI_FIFOTH_TX_WMARK(fifo_size / 2); - dwmci_writel(host, DWMCI_FIFOTH, fifoth_val); + dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val); dwmci_writel(host, DWMCI_CLKENA, 0); dwmci_writel(host, DWMCI_CLKSRC, 0); @@ -575,6 +724,11 @@ static int dw_mmc_probe(struct device_d *dev) host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; host->mci.host_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; + if (of_device_is_compatible(dev->device_node, "rockchip,rk2928-dw-mshc")) + host->pwren_value = 0; + else + host->pwren_value = 1; + dev->detect = dw_mmc_detect; host->clkrate = clk_get_rate(host->clk_ciu); @@ -594,6 +748,8 @@ static __maybe_unused struct of_device_id dw_mmc_compatible[] = { { .compatible = "altr,socfpga-dw-mshc", }, { + .compatible = "rockchip,rk2928-dw-mshc", + }, { /* sentinel */ } }; -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 12/18] ARM: Rockchip: Remove unused files from mach-rockchip. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (10 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 11/18] MMC: dw_mmc: Add support for PIO mode and Rockchip variant of this hardware Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 13/18] ARM: Rockchip: Update Kconfig Andrey Panov ` (6 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/include/mach/rockchip-pll.h | 26 ------ arch/arm/mach-rockchip/pll.c | 102 --------------------- 3 files changed, 129 deletions(-) delete mode 100644 arch/arm/mach-rockchip/include/mach/rockchip-pll.h delete mode 100644 arch/arm/mach-rockchip/pll.c diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 6f4ec16..820eb10 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -1,2 +1 @@ obj-y += core.o -obj-y += pll.o \ No newline at end of file diff --git a/arch/arm/mach-rockchip/include/mach/rockchip-pll.h b/arch/arm/mach-rockchip/include/mach/rockchip-pll.h deleted file mode 100644 index c2cd888..0000000 --- a/arch/arm/mach-rockchip/include/mach/rockchip-pll.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 __MACH_ROCKCHIP_PLL_H -#define __MACH_ROCKCHIP_PLL_H - -enum rk3188_plls { - RK3188_APLL = 0, /* ARM */ - RK3188_DPLL, /* DDR */ - RK3188_CPLL, /* Codec */ - RK3188_GPLL, /* General */ -}; - -int rk3188_pll_set_parameters(int pll, int nr, int nf, int no); - -#endif /* __MACH_ROCKCHIP_PLL_H */ diff --git a/arch/arm/mach-rockchip/pll.c b/arch/arm/mach-rockchip/pll.c deleted file mode 100644 index fce192c..0000000 --- a/arch/arm/mach-rockchip/pll.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> - * - * Based on Linux clk driver: - * Copyright (c) 2014 MundoReader S.L. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 <asm/io.h> -#include <common.h> -#include <mach/rockchip-regs.h> - -#define RK3188_CLK_BASE 0x20000000 -#define RK3188_PLL_LOCK_REG 0x200080ac - -#define PLL_MODE_MASK 0x3 -#define PLL_MODE_SLOW 0x0 -#define PLL_MODE_NORM 0x1 -#define PLL_MODE_DEEP 0x2 - -#define PLL_RESET_DELAY(nr) ((nr * 500) / 24 + 1) - -#define PLLCON0_OD_MASK 0xf -#define PLLCON0_OD_SHIFT 0 -#define PLLCON0_NR_MASK 0x3f -#define PLLCON0_NR_SHIFT 8 - -#define PLLCON1_NF_MASK 0x1fff -#define PLLCON1_NF_SHIFT 0 - -#define PLLCON2_BWADJ_MASK 0xfff -#define PLLCON2_BWADJ_SHIFT 0 - -#define PLLCON3_RESET (1 << 1) -#define PLLCON3_BYPASS (1 << 0) - -struct rockchip_pll_data { - int con_base; - int mode_offset; - int mode_shift; - int lock_shift; -}; - -struct rockchip_pll_data rk3188_plls[] = { - { 0x00, 0x40, 0x00, 0x06 }, - { 0x10, 0x40, 0x04, 0x05 }, - { 0x20, 0x40, 0x08, 0x07 }, - { 0x30, 0x40, 0x0c, 0x08 }, -}; - -#define HIWORD_UPDATE(val, mask, shift) \ - ((val) << (shift) | (mask) << ((shift) + 16)) - -int rk3188_pll_set_parameters(int pll, int nr, int nf, int no) -{ - struct rockchip_pll_data *d = &rk3188_plls[pll]; - int delay = 0; - - debug("rk3188 pll %d: set param %d %d %d\n", pll, nr, nf, no); - - /* pull pll in slow mode */ - writel(HIWORD_UPDATE(PLL_MODE_SLOW, PLL_MODE_MASK, d->mode_shift), - RK3188_CLK_BASE + d->mode_offset); - /* enter reset */ - writel(HIWORD_UPDATE(PLLCON3_RESET, PLLCON3_RESET, 0), - RK3188_CLK_BASE + d->con_base + 12); - - /* update pll values */ - writel(HIWORD_UPDATE(nr - 1, PLLCON0_NR_MASK, PLLCON0_NR_SHIFT) | - HIWORD_UPDATE(no - 1, PLLCON0_OD_MASK, PLLCON0_OD_SHIFT), - RK3188_CLK_BASE + d->con_base + 0); - writel(HIWORD_UPDATE(nf - 1, PLLCON1_NF_MASK, PLLCON1_NF_SHIFT), - RK3188_CLK_BASE + d->con_base + 4); - writel(HIWORD_UPDATE(nf >> 1, PLLCON2_BWADJ_MASK, PLLCON2_BWADJ_SHIFT), - RK3188_CLK_BASE + d->con_base + 8); - - /* leave reset and wait the reset_delay */ - writel(HIWORD_UPDATE(0, PLLCON3_RESET, 0), - RK3188_CLK_BASE + d->con_base + 12); - udelay(PLL_RESET_DELAY(nr)); - - /* wait for the pll to lock */ - while (delay++ < 24000000) { - if (readl(RK3188_PLL_LOCK_REG) & BIT(d->lock_shift)) - break; - } - - /* go back to normal mode */ - writel(HIWORD_UPDATE(PLL_MODE_NORM, PLL_MODE_MASK, d->mode_shift), - RK3188_CLK_BASE + d->mode_offset); - - return 0; -} -EXPORT_SYMBOL(rk3188_pll_set_parameters); -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 13/18] ARM: Rockchip: Update Kconfig 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (11 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 12/18] ARM: Rockchip: Remove unused files from mach-rockchip Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 14/18] ARM: Rockchip: Update clk driver from Linux kernel for use with newer DTS Andrey Panov ` (5 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- arch/arm/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 527a913..d174769 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -160,6 +160,10 @@ config ARCH_ROCKCHIP select PINCTRL_ROCKCHIP select HAVE_PBL_MULTI_IMAGES select HAS_DEBUG_LL + select ARCH_HAS_L2X0 + select GCD + select CLK_NEED_COMPOSITE + select CLK_NEED_FDIV config ARCH_SOCFPGA bool "Altera SOCFPGA cyclone5" -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 14/18] ARM: Rockchip: Update clk driver from Linux kernel for use with newer DTS. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (12 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 13/18] ARM: Rockchip: Update Kconfig Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:21 ` [PATCH 15/18] ARM: Rockchip: Use newer DTS for Radxa Rock board Andrey Panov ` (4 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- drivers/clk/rockchip/Makefile | 2 +- drivers/clk/rockchip/clk-cpu.c | 160 +++++++ drivers/clk/rockchip/clk-pll.c | 368 +++++++++++++++ drivers/clk/rockchip/clk-rk3188.c | 875 ++++++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk-rockchip.c | 86 ---- drivers/clk/rockchip/clk.c | 259 +++++++++++ drivers/clk/rockchip/clk.h | 431 ++++++++++++++++++ include/init.h | 1 + 8 files changed, 2095 insertions(+), 87 deletions(-) create mode 100644 drivers/clk/rockchip/clk-cpu.c create mode 100644 drivers/clk/rockchip/clk-pll.c create mode 100644 drivers/clk/rockchip/clk-rk3188.c delete mode 100644 drivers/clk/rockchip/clk-rockchip.c create mode 100644 drivers/clk/rockchip/clk.c create mode 100644 drivers/clk/rockchip/clk.h diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 1c5271f..865542a 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -1 +1 @@ -obj-y += clk-rockchip.o \ No newline at end of file +obj-y += clk-cpu.o clk-pll.o clk-rk3188.o clk.o diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c new file mode 100644 index 0000000..226b819 --- /dev/null +++ b/drivers/clk/rockchip/clk-cpu.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * based on clk/samsung/clk-cpu.c + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Thomas Abraham <thomas.ab@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * A CPU clock is defined as a clock supplied to a CPU or a group of CPUs. + * The CPU clock is typically derived from a hierarchy of clock + * blocks which includes mux and divider blocks. There are a number of other + * auxiliary clocks supplied to the CPU domain such as the debug blocks and AXI + * clock for CPU domain. The rates of these auxiliary clocks are related to the + * CPU clock rate and this relation is usually specified in the hardware manual + * of the SoC or supplied after the SoC characterization. + * + * The below implementation of the CPU clock allows the rate changes of the CPU + * clock and the corresponding rate changes of the auxillary clocks of the CPU + * domain. The platform clock driver provides a clock register configuration + * for each configurable rate which is then used to program the clock hardware + * registers to acheive a fast co-oridinated rate change for all the CPU domain + * clocks. + * + * On a rate change request for the CPU clock, the rate change is propagated + * upto the PLL supplying the clock to the CPU domain clock blocks. While the + * CPU domain PLL is reconfigured, the CPU domain clocks are driven using an + * alternate clock source. If required, the alternate clock source is divided + * down in order to keep the output clock rate within the previous OPP limits. + */ + +#include <common.h> +#include <of.h> +#include <malloc.h> +#include <io.h> +#include <xfuncs.h> +#include "clk.h" +#include <linux/barebox-wrapper.h> + +/** + * struct rockchip_cpuclk: information about clock supplied to a CPU core. + * @hw: handle between ccf and cpu clock. + * @alt_parent: alternate parent clock to use when switching the speed + * of the primary parent clock. + * @reg_base: base register for cpu-clock values. + * @rate_count: number of rates in the rate_table + * @rate_table: pll-rates and their associated dividers + * @reg_data: cpu-specific register settings + */ +struct rockchip_cpuclk { + struct clk hw; + + struct clk *alt_parent; + void __iomem *reg_base; + unsigned int rate_count; + struct rockchip_cpuclk_rate_table *rate_table; + const struct rockchip_cpuclk_reg_data *reg_data; +}; + +#define to_rockchip_cpuclk_hw(hw) container_of(hw, struct rockchip_cpuclk, hw) + +static unsigned long rockchip_cpuclk_recalc_rate(struct clk *hw, + unsigned long parent_rate) +{ + struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw); + const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; + u32 clksel0 = readl(cpuclk->reg_base + reg_data->core_reg); + + clksel0 >>= reg_data->div_core_shift; + clksel0 &= reg_data->div_core_mask; + return parent_rate / (clksel0 + 1); +} + +static const struct clk_ops rockchip_cpuclk_ops = { + .recalc_rate = rockchip_cpuclk_recalc_rate, +}; + +struct clk *rockchip_clk_register_cpuclk(const char *name, + const char **parent_names, u8 num_parents, + const struct rockchip_cpuclk_reg_data *reg_data, + const struct rockchip_cpuclk_rate_table *rates, + int nrates, void __iomem *reg_base) +{ + struct rockchip_cpuclk *cpuclk; + struct clk *clk; + int ret; + + if (num_parents != 2) { + pr_err("%s: needs two parent clocks\n", __func__); + return ERR_PTR(-EINVAL); + } + + cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL); + if (!cpuclk) + return ERR_PTR(-ENOMEM); + + cpuclk->hw.name = name; + cpuclk->hw.parent_names = &parent_names[0]; + cpuclk->hw.num_parents = 1; + cpuclk->hw.ops = &rockchip_cpuclk_ops; + + /* only allow rate changes when we have a rate table */ + cpuclk->hw.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0; + + cpuclk->reg_base = reg_base; + cpuclk->reg_data = reg_data; + + cpuclk->alt_parent = __clk_lookup(parent_names[1]); + if (!cpuclk->alt_parent) { + pr_err("%s: could not lookup alternate parent\n", + __func__); + ret = -EINVAL; + goto free_cpuclk; + } + + ret = clk_enable(cpuclk->alt_parent); + if (ret) { + pr_err("%s: could not enable alternate parent\n", + __func__); + goto free_cpuclk; + } + + clk = __clk_lookup(parent_names[0]); + if (!clk) { + pr_err("%s: could not lookup parent clock %s\n", + __func__, parent_names[0]); + ret = -EINVAL; + goto free_cpuclk; + } + + if (nrates > 0) { + cpuclk->rate_count = nrates; + cpuclk->rate_table = xmemdup(rates, + sizeof(*rates) * nrates + ); + if (!cpuclk->rate_table) { + pr_err("%s: could not allocate memory for cpuclk rates\n", + __func__); + ret = -ENOMEM; + goto free_cpuclk; + } + } + + ret = clk_register(&cpuclk->hw); + if (ret) { + pr_err("%s: could not register cpuclk %s\n", __func__, name); + goto free_rate_table; + } + + return &cpuclk->hw; + +free_rate_table: + kfree(cpuclk->rate_table); +free_cpuclk: + kfree(cpuclk); + return ERR_PTR(ret); +} diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c new file mode 100644 index 0000000..f0dc120 --- /dev/null +++ b/drivers/clk/rockchip/clk-pll.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * 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 <asm-generic/div64.h> +#include <common.h> +#include <io.h> +#include <linux/list.h> +#include <of.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/barebox-wrapper.h> +#include "clk.h" +#include <xfuncs.h> + +#define PLL_MODE_MASK 0x3 +#define PLL_MODE_SLOW 0x0 +#define PLL_MODE_NORM 0x1 +#define PLL_MODE_DEEP 0x2 + +struct rockchip_clk_pll { + struct clk hw; + + struct clk pll_mux; + const struct clk_ops *pll_mux_ops; + + void __iomem *reg_base; + int lock_offset; + unsigned int lock_shift; + enum rockchip_pll_type type; + u8 flags; + const struct rockchip_pll_rate_table *rate_table; + unsigned int rate_count; + char pll_name[20]; +}; + +#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) + +static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( + struct rockchip_clk_pll *pll, unsigned long rate) +{ + const struct rockchip_pll_rate_table *rate_table = pll->rate_table; + int i; + + for (i = 0; i < pll->rate_count; i++) { + if (rate == rate_table[i].rate) + return &rate_table[i]; + } + + return NULL; +} + +static long rockchip_pll_round_rate(struct clk *hw, + unsigned long drate, unsigned long *prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate_table = pll->rate_table; + int i; + + /* Assumming rate_table is in descending order */ + for (i = 0; i < pll->rate_count; i++) { + if (drate >= rate_table[i].rate) + return rate_table[i].rate; + } + + /* return minimum supported value */ + return rate_table[i - 1].rate; +} + +/* + * Wait for the pll to reach the locked state. + * The calling set_rate function is responsible for making sure the + * grf regmap is available. + */ +#define RK3188_PLL_LOCK_REG 0x200080ac + +static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) +{ + int delay = 24000000; + int val; + + /* wait for the pll to lock */ + while (delay > 0) { + val = readl(RK3188_PLL_LOCK_REG); + if (val & BIT(pll->lock_shift)) + return 0; + delay--; + } + + pr_err("%s: timeout waiting for pll to lock\n", __func__); + return -ETIMEDOUT; +} + +/** + * PLL used in RK3066, RK3188 and RK3288 + */ + +#define RK3066_PLL_RESET_DELAY(nr) ((nr * 500) / 24 + 1) + +#define RK3066_PLLCON(i) (i * 0x4) +#define RK3066_PLLCON0_OD_MASK 0xf +#define RK3066_PLLCON0_OD_SHIFT 0 +#define RK3066_PLLCON0_NR_MASK 0x3f +#define RK3066_PLLCON0_NR_SHIFT 8 +#define RK3066_PLLCON1_NF_MASK 0x1fff +#define RK3066_PLLCON1_NF_SHIFT 0 +#define RK3066_PLLCON2_BWADJ_MASK 0xfff +#define RK3066_PLLCON2_BWADJ_SHIFT 0 +#define RK3066_PLLCON3_RESET (1 << 5) +#define RK3066_PLLCON3_PWRDOWN (1 << 1) +#define RK3066_PLLCON3_BYPASS (1 << 0) + +static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk *hw, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + u64 nf, nr, no, rate64 = prate; + u32 pllcon; + + pllcon = readl(pll->reg_base + RK3066_PLLCON(3)); + if (pllcon & RK3066_PLLCON3_BYPASS) { + pr_debug("%s: pll %s is bypassed\n", __func__, + __clk_get_name(hw)); + return prate; + } + + pllcon = readl(pll->reg_base + RK3066_PLLCON(1)); + nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK; + + pllcon = readl(pll->reg_base + RK3066_PLLCON(0)); + nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK; + no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK; + + rate64 *= (nf + 1); + do_div(rate64, nr + 1); + do_div(rate64, no + 1); + + pr_debug("%s: %s rate=%lu\n", + __func__, hw->name, (unsigned long)rate64); + + return (unsigned long)rate64; +} + +static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); + struct clk *pll_mux = &pll->pll_mux; + const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; + int rate_change_remuxed = 0; + int cur_parent; + int ret; + + pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", + __func__, __clk_get_name(hw), old_rate, drate, prate); + + /* Get required rate settings from table */ + rate = rockchip_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw)); + return -EINVAL; + } + + pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", + __func__, rate->rate, rate->nr, rate->no, rate->nf); + + cur_parent = pll_mux_ops->get_parent(pll_mux); + if (cur_parent == PLL_MODE_NORM) { + pll_mux_ops->set_parent(pll_mux, PLL_MODE_SLOW); + rate_change_remuxed = 1; + } + + /* enter reset mode */ + writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), + pll->reg_base + RK3066_PLLCON(3)); + + /* update pll values */ + writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK, + RK3066_PLLCON0_NR_SHIFT) | + HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK, + RK3066_PLLCON0_OD_SHIFT), + pll->reg_base + RK3066_PLLCON(0)); + + writel(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, + RK3066_PLLCON1_NF_SHIFT), + pll->reg_base + RK3066_PLLCON(1)); + writel(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK, + RK3066_PLLCON2_BWADJ_SHIFT), + pll->reg_base + RK3066_PLLCON(2)); + + /* leave reset and wait the reset_delay */ + writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0), + pll->reg_base + RK3066_PLLCON(3)); + udelay(RK3066_PLL_RESET_DELAY(rate->nr)); + + /* wait for the pll to lock */ + ret = rockchip_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", + __func__, old_rate); + rockchip_rk3066_pll_set_rate(hw, old_rate, prate); + } + + if (rate_change_remuxed) + pll_mux_ops->set_parent(pll_mux, PLL_MODE_NORM); + + return ret; +} + +static int rockchip_rk3066_pll_enable(struct clk *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3066_PLLCON(3)); + + return 0; +} + +static void rockchip_rk3066_pll_disable(struct clk *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN, + RK3066_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3066_PLLCON(3)); +} + +static int rockchip_rk3066_pll_is_enabled(struct clk *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3)); + + return !(pllcon & RK3066_PLLCON3_PWRDOWN); +} + +static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { + .recalc_rate = rockchip_rk3066_pll_recalc_rate, + .enable = rockchip_rk3066_pll_enable, + .disable = rockchip_rk3066_pll_disable, + .is_enabled = rockchip_rk3066_pll_is_enabled, +}; + +static const struct clk_ops rockchip_rk3066_pll_clk_ops = { + .recalc_rate = rockchip_rk3066_pll_recalc_rate, + .round_rate = rockchip_pll_round_rate, + .set_rate = rockchip_rk3066_pll_set_rate, + .enable = rockchip_rk3066_pll_enable, + .disable = rockchip_rk3066_pll_disable, + .is_enabled = rockchip_rk3066_pll_is_enabled, +}; + +/* + * Common registering of pll clocks + */ + +struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, + const char *name, const char **parent_names, u8 num_parents, + void __iomem *base, int con_offset, int grf_lock_offset, + int lock_shift, int mode_offset, int mode_shift, + struct rockchip_pll_rate_table *rate_table, + u8 clk_pll_flags) +{ + const char **pll_parents; + struct rockchip_clk_pll *pll; + struct clk *pll_mux; + struct clk *mux_clk; + int ret; + + if (num_parents != 2) { + pr_err("%s: needs two parent clocks\n", __func__); + return ERR_PTR(-EINVAL); + } + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll_parents = kzalloc(sizeof(char *)*3, GFP_KERNEL); + if (!pll_parents) + return ERR_PTR(-ENOMEM); + + /* name the actual pll */ + snprintf(pll->pll_name, sizeof(pll->pll_name), "pll_%s", name); + pll->hw.name = pll->pll_name; + + pll->hw.parent_names = &parent_names[0]; + pll->hw.num_parents = 1; + + if (rate_table) { + int len; + + /* find count of rates in rate_table */ + for (len = 0; rate_table[len].rate != 0; ) + len++; + + pll->rate_count = len; + pll->rate_table = xmemdup(rate_table, + pll->rate_count * + sizeof(struct rockchip_pll_rate_table) + ); + WARN(!pll->rate_table, + "%s: could not allocate rate table for %s\n", + __func__, name); + } + + switch (pll_type) { + case pll_rk3066: + if (!pll->rate_table) + pll->hw.ops = &rockchip_rk3066_pll_clk_norate_ops; + else + pll->hw.ops = &rockchip_rk3066_pll_clk_ops; + break; + default: + pr_warn("%s: Unknown pll type for pll clk %s\n", + __func__, name); + } + + pll->type = pll_type; + pll->reg_base = base + con_offset; + pll->lock_offset = grf_lock_offset; + pll->lock_shift = lock_shift; + pll->flags = clk_pll_flags; + + ret = clk_register(&pll->hw); + if (ret) { + pr_err("%s: failed to register pll clock %s : %d\n", + __func__, name, ret); + mux_clk = &pll->hw; + goto err_exit; + } + + /* the actual muxing is xin24m, pll-output, xin32k */ + pll_parents[0] = parent_names[0]; + pll_parents[1] = pll->pll_name; + pll_parents[2] = parent_names[1]; + + pll_mux = clk_mux_alloc(name, base + mode_offset, mode_shift, PLL_MODE_MASK, pll_parents, 3, CLK_SET_RATE_PARENT); + pll->pll_mux_ops = pll_mux->ops; + mux_clk = pll_mux; + + if (pll_type == pll_rk3066) + pll_mux->flags |= CLK_MUX_HIWORD_MASK; + + ret = clk_register(pll_mux); + if (ret) + goto err_exit; + + return mux_clk; + +err_exit: + kfree(pll); + return mux_clk; +} diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c new file mode 100644 index 0000000..9f81649 --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * 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 <common.h> +#include <linux/clk.h> +#include <of.h> +#include <of_address.h> +#include <dt-bindings/clock/rk3188-cru-common.h> +#include "clk.h" +#include <linux/barebox-wrapper.h> +#include <init.h> + +#define RK3066_GRF_SOC_STATUS 0x15c +#define RK3188_GRF_SOC_STATUS 0xac + +#define CLK_SET_RATE_NO_REPARENT 0 +#define CLK_DIVIDER_READ_ONLY 0 + +enum rk3188_plls { + apll, cpll, dpll, gpll, +}; + +struct rockchip_pll_rate_table rk3188_pll_rates[] = { + RK3066_PLL_RATE(2208000000, 1, 92, 1), + RK3066_PLL_RATE(2184000000, 1, 91, 1), + RK3066_PLL_RATE(2160000000, 1, 90, 1), + RK3066_PLL_RATE(2136000000, 1, 89, 1), + RK3066_PLL_RATE(2112000000, 1, 88, 1), + RK3066_PLL_RATE(2088000000, 1, 87, 1), + RK3066_PLL_RATE(2064000000, 1, 86, 1), + RK3066_PLL_RATE(2040000000, 1, 85, 1), + RK3066_PLL_RATE(2016000000, 1, 84, 1), + RK3066_PLL_RATE(1992000000, 1, 83, 1), + RK3066_PLL_RATE(1968000000, 1, 82, 1), + RK3066_PLL_RATE(1944000000, 1, 81, 1), + RK3066_PLL_RATE(1920000000, 1, 80, 1), + RK3066_PLL_RATE(1896000000, 1, 79, 1), + RK3066_PLL_RATE(1872000000, 1, 78, 1), + RK3066_PLL_RATE(1848000000, 1, 77, 1), + RK3066_PLL_RATE(1824000000, 1, 76, 1), + RK3066_PLL_RATE(1800000000, 1, 75, 1), + RK3066_PLL_RATE(1776000000, 1, 74, 1), + RK3066_PLL_RATE(1752000000, 1, 73, 1), + RK3066_PLL_RATE(1728000000, 1, 72, 1), + RK3066_PLL_RATE(1704000000, 1, 71, 1), + RK3066_PLL_RATE(1680000000, 1, 70, 1), + RK3066_PLL_RATE(1656000000, 1, 69, 1), + RK3066_PLL_RATE(1632000000, 1, 68, 1), + RK3066_PLL_RATE(1608000000, 1, 67, 1), + RK3066_PLL_RATE(1560000000, 1, 65, 1), + RK3066_PLL_RATE(1512000000, 1, 63, 1), + RK3066_PLL_RATE(1488000000, 1, 62, 1), + RK3066_PLL_RATE(1464000000, 1, 61, 1), + RK3066_PLL_RATE(1440000000, 1, 60, 1), + RK3066_PLL_RATE(1416000000, 1, 59, 1), + RK3066_PLL_RATE(1392000000, 1, 58, 1), + RK3066_PLL_RATE(1368000000, 1, 57, 1), + RK3066_PLL_RATE(1344000000, 1, 56, 1), + RK3066_PLL_RATE(1320000000, 1, 55, 1), + RK3066_PLL_RATE(1296000000, 1, 54, 1), + RK3066_PLL_RATE(1272000000, 1, 53, 1), + RK3066_PLL_RATE(1248000000, 1, 52, 1), + RK3066_PLL_RATE(1224000000, 1, 51, 1), + RK3066_PLL_RATE(1200000000, 1, 50, 1), + RK3066_PLL_RATE(1188000000, 2, 99, 1), + RK3066_PLL_RATE(1176000000, 1, 49, 1), + RK3066_PLL_RATE(1128000000, 1, 47, 1), + RK3066_PLL_RATE(1104000000, 1, 46, 1), + RK3066_PLL_RATE(1008000000, 1, 84, 2), + RK3066_PLL_RATE( 912000000, 1, 76, 2), + RK3066_PLL_RATE( 891000000, 8, 594, 2), + RK3066_PLL_RATE( 888000000, 1, 74, 2), + RK3066_PLL_RATE( 816000000, 1, 68, 2), + RK3066_PLL_RATE( 798000000, 2, 133, 2), + RK3066_PLL_RATE( 792000000, 1, 66, 2), + RK3066_PLL_RATE( 768000000, 1, 64, 2), + RK3066_PLL_RATE( 742500000, 8, 495, 2), + RK3066_PLL_RATE( 696000000, 1, 58, 2), + RK3066_PLL_RATE( 600000000, 1, 50, 2), + RK3066_PLL_RATE( 594000000, 2, 198, 4), + RK3066_PLL_RATE( 552000000, 1, 46, 2), + RK3066_PLL_RATE( 504000000, 1, 84, 4), + RK3066_PLL_RATE( 456000000, 1, 76, 4), + RK3066_PLL_RATE( 408000000, 1, 68, 4), + RK3066_PLL_RATE( 384000000, 2, 128, 4), + RK3066_PLL_RATE( 360000000, 1, 60, 4), + RK3066_PLL_RATE( 312000000, 1, 52, 4), + RK3066_PLL_RATE( 300000000, 1, 50, 4), + RK3066_PLL_RATE( 297000000, 2, 198, 8), + RK3066_PLL_RATE( 252000000, 1, 84, 8), + RK3066_PLL_RATE( 216000000, 1, 72, 8), + RK3066_PLL_RATE( 148500000, 2, 99, 8), + RK3066_PLL_RATE( 126000000, 1, 84, 16), + RK3066_PLL_RATE( 48000000, 1, 64, 32), + { /* sentinel */ }, +}; + +#define RK3066_DIV_CORE_PERIPH_MASK 0x3 +#define RK3066_DIV_CORE_PERIPH_SHIFT 6 +#define RK3066_DIV_ACLK_CORE_MASK 0x7 +#define RK3066_DIV_ACLK_CORE_SHIFT 0 +#define RK3066_DIV_ACLK_HCLK_MASK 0x3 +#define RK3066_DIV_ACLK_HCLK_SHIFT 8 +#define RK3066_DIV_ACLK_PCLK_MASK 0x3 +#define RK3066_DIV_ACLK_PCLK_SHIFT 12 +#define RK3066_DIV_AHB2APB_MASK 0x3 +#define RK3066_DIV_AHB2APB_SHIFT 14 + +#define RK3066_CLKSEL0(_core_peri) \ + { \ + .reg = RK2928_CLKSEL_CON(0), \ + .val = HIWORD_UPDATE(_core_peri, RK3066_DIV_CORE_PERIPH_MASK, \ + RK3066_DIV_CORE_PERIPH_SHIFT) \ + } +#define RK3066_CLKSEL1(_aclk_core, _aclk_hclk, _aclk_pclk, _ahb2apb) \ + { \ + .reg = RK2928_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_aclk_core, RK3066_DIV_ACLK_CORE_MASK, \ + RK3066_DIV_ACLK_CORE_SHIFT) | \ + HIWORD_UPDATE(_aclk_hclk, RK3066_DIV_ACLK_HCLK_MASK, \ + RK3066_DIV_ACLK_HCLK_SHIFT) | \ + HIWORD_UPDATE(_aclk_pclk, RK3066_DIV_ACLK_PCLK_MASK, \ + RK3066_DIV_ACLK_PCLK_SHIFT) | \ + HIWORD_UPDATE(_ahb2apb, RK3066_DIV_AHB2APB_MASK, \ + RK3066_DIV_AHB2APB_SHIFT), \ + } + +#define RK3066_CPUCLK_RATE(_prate, _core_peri, _acore, _ahclk, _apclk, _h2p) \ + { \ + .prate = _prate, \ + .divs = { \ + RK3066_CLKSEL0(_core_peri), \ + RK3066_CLKSEL1(_acore, _ahclk, _apclk, _h2p), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rk3066_cpuclk_rates[] __initdata = { + RK3066_CPUCLK_RATE(1416000000, 2, 3, 1, 2, 1), + RK3066_CPUCLK_RATE(1200000000, 2, 3, 1, 2, 1), + RK3066_CPUCLK_RATE(1008000000, 2, 2, 1, 2, 1), + RK3066_CPUCLK_RATE( 816000000, 2, 2, 1, 2, 1), + RK3066_CPUCLK_RATE( 600000000, 1, 2, 1, 2, 1), + RK3066_CPUCLK_RATE( 504000000, 1, 1, 1, 2, 1), + RK3066_CPUCLK_RATE( 312000000, 0, 1, 1, 1, 0), +}; + +static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = { + .core_reg = RK2928_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_shift = 8, +}; + +#define RK3188_DIV_ACLK_CORE_MASK 0x7 +#define RK3188_DIV_ACLK_CORE_SHIFT 3 + +#define RK3188_CLKSEL1(_aclk_core) \ + { \ + .reg = RK2928_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_aclk_core, RK3188_DIV_ACLK_CORE_MASK,\ + RK3188_DIV_ACLK_CORE_SHIFT) \ + } +#define RK3188_CPUCLK_RATE(_prate, _core_peri, _aclk_core) \ + { \ + .prate = _prate, \ + .divs = { \ + RK3066_CLKSEL0(_core_peri), \ + RK3188_CLKSEL1(_aclk_core), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rk3188_cpuclk_rates[] __initdata = { + RK3188_CPUCLK_RATE(1608000000, 2, 3), + RK3188_CPUCLK_RATE(1416000000, 2, 3), + RK3188_CPUCLK_RATE(1200000000, 2, 3), + RK3188_CPUCLK_RATE(1008000000, 2, 3), + RK3188_CPUCLK_RATE( 816000000, 2, 3), + RK3188_CPUCLK_RATE( 600000000, 1, 3), + RK3188_CPUCLK_RATE( 504000000, 1, 3), + RK3188_CPUCLK_RATE( 312000000, 0, 1), +}; + +static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = { + .core_reg = RK2928_CLKSEL_CON(0), + .div_core_shift = 9, + .div_core_mask = 0x1f, + .mux_core_shift = 8, +}; + +PNAME(mux_pll_p) = { "xin24m", "xin32k" }; +PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; +PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" }; +PNAME(mux_pll_src_gpll_cpll_p) = { "gpll", "cpll" }; +PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; +PNAME(mux_aclk_cpu_p) = { "apll", "gpll" }; +PNAME(mux_sclk_cif0_p) = { "cif0_pre", "xin24m" }; +PNAME(mux_sclk_i2s0_p) = { "i2s0_pre", "i2s0_frac", "xin12m" }; +PNAME(mux_sclk_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; +PNAME(mux_sclk_uart0_p) = { "uart0_pre", "uart0_frac", "xin24m" }; +PNAME(mux_sclk_uart1_p) = { "uart1_pre", "uart1_frac", "xin24m" }; +PNAME(mux_sclk_uart2_p) = { "uart2_pre", "uart2_frac", "xin24m" }; +PNAME(mux_sclk_uart3_p) = { "uart3_pre", "uart3_frac", "xin24m" }; +PNAME(mux_sclk_hsadc_p) = { "hsadc_src", "hsadc_frac", "ext_hsadc" }; +PNAME(mux_mac_p) = { "gpll", "dpll" }; +PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" }; + +static struct rockchip_pll_clock rk3066_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), + RK2928_MODE_CON, 0, 5, 0, rk3188_pll_rates), + [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), + RK2928_MODE_CON, 4, 4, 0, NULL), + [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8), + RK2928_MODE_CON, 8, 6, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates), + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12), + RK2928_MODE_CON, 12, 7, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates), +}; + +static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), + RK2928_MODE_CON, 0, 6, 0, rk3188_pll_rates), + [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), + RK2928_MODE_CON, 4, 5, 0, NULL), + [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8), + RK2928_MODE_CON, 8, 7, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates), + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12), + RK2928_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) + +/* 2 ^ (val + 1) */ +static struct clk_div_table div_core_peri_t[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 4 }, + { .val = 2, .div = 8 }, + { .val = 3, .div = 16 }, + { /* sentinel */ }, +}; + +static struct rockchip_clk_branch common_clk_branches[] __initdata = { + /* + * Clock-Architecture Diagram 2 + */ + + GATE(0, "gpll_armclk", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS), + + /* these two are set by the cpuclk and should not be changed */ + COMPOSITE_NOMUX_DIVTBL(CORE_PERI, "core_peri", "armclk", 0, + RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, + div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS), + + COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 9, GFLAGS), + GATE(0, "hclk_vepu", "aclk_vepu", 0, + RK2928_CLKGATE_CON(3), 10, GFLAGS), + COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + GATE(0, "hclk_vdpu", "aclk_vdpu", 0, + RK2928_CLKGATE_CON(3), 12, GFLAGS), + + GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(1), 7, GFLAGS), + COMPOSITE(0, "ddrphy", mux_ddrphy_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(0), 2, GFLAGS), + + GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, + RK2928_CLKGATE_CON(0), 3, GFLAGS), + + GATE(0, "atclk_cpu", "pclk_cpu_pre", 0, + RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, + RK2928_CLKGATE_CON(0), 5, GFLAGS), + GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 4, GFLAGS), + + COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(31), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 0, GFLAGS), + COMPOSITE(0, "aclk_lcdc1_pre", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 4, GFLAGS), + + GATE(0, "aclk_peri", "aclk_peri_pre", 0, + RK2928_CLKGATE_CON(2), 1, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0, + RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(2), 2, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0, + RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(2), 3, GFLAGS), + + MUX(0, "cif_src", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(29), 0, 1, MFLAGS), + COMPOSITE_NOMUX(0, "cif0_pre", "cif_src", 0, + RK2928_CLKSEL_CON(29), 1, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 7, GFLAGS), + MUX(SCLK_CIF0, "sclk_cif0", mux_sclk_cif0_p, 0, + RK2928_CLKSEL_CON(29), 7, 1, MFLAGS), + + GATE(0, "pclkin_cif0", "ext_cif0", 0, + RK2928_CLKGATE_CON(3), 3, GFLAGS), + + /* + * the 480m are generated inside the usb block from these clocks, + * but they are also a source for the hsicphy clock. + */ + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(1), 5, GFLAGS), + GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(1), 6, GFLAGS), + + COMPOSITE(0, "mac_src", mux_mac_p, 0, + RK2928_CLKSEL_CON(21), 0, 1, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 5, GFLAGS), + MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(21), 4, 1, MFLAGS), + GATE(0, "sclk_mac_lbtest", "sclk_macref", + RK2928_CLKGATE_CON(2), 12, 0, GFLAGS), + + COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0, + RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(2), 6, GFLAGS), + COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0, + RK2928_CLKSEL_CON(23), 0, + RK2928_CLKGATE_CON(2), 7, GFLAGS), + MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0, + RK2928_CLKSEL_CON(22), 4, 2, MFLAGS), + + COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0, + RK2928_CLKSEL_CON(24), 8, 8, DFLAGS, + RK2928_CLKGATE_CON(2), 8, GFLAGS), + + COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, + RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 13, GFLAGS), + COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, + RK2928_CLKSEL_CON(9), 0, + RK2928_CLKGATE_CON(0), 14, GFLAGS), + MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, + RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), + + /* + * Clock-Architecture Diagram 4 + */ + + GATE(SCLK_SMC, "sclk_smc", "hclk_peri", + RK2928_CLKGATE_CON(2), 4, 0, GFLAGS), + + COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0, + RK2928_CLKSEL_CON(25), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 9, GFLAGS), + COMPOSITE_NOMUX(SCLK_SPI1, "sclk_spi1", "pclk_peri", 0, + RK2928_CLKSEL_CON(25), 8, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 10, GFLAGS), + + COMPOSITE_NOMUX(SCLK_SDMMC, "sclk_sdmmc", "hclk_peri", 0, + RK2928_CLKSEL_CON(11), 0, 6, DFLAGS, + RK2928_CLKGATE_CON(2), 11, GFLAGS), + COMPOSITE_NOMUX(SCLK_SDIO, "sclk_sdio", "hclk_peri", 0, + RK2928_CLKSEL_CON(12), 0, 6, DFLAGS, + RK2928_CLKGATE_CON(2), 13, GFLAGS), + COMPOSITE_NOMUX(SCLK_EMMC, "sclk_emmc", "hclk_peri", 0, + RK2928_CLKSEL_CON(12), 8, 6, DFLAGS, + RK2928_CLKGATE_CON(2), 14, GFLAGS), + + MUX(0, "uart_src", mux_pll_src_gpll_cpll_p, 0, + RK2928_CLKSEL_CON(12), 15, 1, MFLAGS), + COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0, + RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0, + RK2928_CLKSEL_CON(17), 0, + RK2928_CLKGATE_CON(1), 9, GFLAGS), + MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0, + RK2928_CLKSEL_CON(13), 8, 2, MFLAGS), + COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0, + RK2928_CLKSEL_CON(14), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 10, GFLAGS), + COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0, + RK2928_CLKSEL_CON(18), 0, + RK2928_CLKGATE_CON(1), 11, GFLAGS), + MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0, + RK2928_CLKSEL_CON(14), 8, 2, MFLAGS), + COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0, + RK2928_CLKSEL_CON(15), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 12, GFLAGS), + COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0, + RK2928_CLKSEL_CON(19), 0, + RK2928_CLKGATE_CON(1), 13, GFLAGS), + MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0, + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS), + COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0, + RK2928_CLKSEL_CON(16), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 14, GFLAGS), + COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0, + RK2928_CLKSEL_CON(20), 0, + RK2928_CLKGATE_CON(1), 15, GFLAGS), + MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS), + + GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS), + + GATE(SCLK_TIMER0, "timer0", "xin24m", 0, RK2928_CLKGATE_CON(1), 0, GFLAGS), + GATE(SCLK_TIMER1, "timer1", "xin24m", 0, RK2928_CLKGATE_CON(1), 1, GFLAGS), + + /* clk_core_pre gates */ + GATE(0, "core_dbg", "armclk", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS), + + /* aclk_cpu gates */ + GATE(ACLK_DMA1, "aclk_dma1", "aclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS), + GATE(0, "aclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS), + GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS), + + /* hclk_cpu gates */ + GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS), + GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), + GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS), + GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS), + /* hclk_ahb2apb is part of a clk branch */ + GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS), + GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS), + GATE(HCLK_LCDC1, "hclk_lcdc1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS), + GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS), + GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS), + GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS), + + /* hclk_peri gates */ + GATE(0, "hclk_peri_axi_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS), + GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 6, GFLAGS), + GATE(0, "hclk_emem_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 7, GFLAGS), + GATE(HCLK_EMAC, "hclk_emac", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS), + GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS), + GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 5, GFLAGS), + GATE(HCLK_OTG0, "hclk_usbotg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS), + GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 5, GFLAGS), + GATE(HCLK_PIDF, "hclk_pidfilter", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 6, GFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 12, GFLAGS), + + /* aclk_lcdc0_pre gates */ + GATE(0, "aclk_vio0", "aclk_lcdc0_pre", 0, RK2928_CLKGATE_CON(6), 13, GFLAGS), + GATE(ACLK_LCDC0, "aclk_lcdc0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 0, GFLAGS), + GATE(ACLK_CIF0, "aclk_cif0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 5, GFLAGS), + GATE(ACLK_IPP, "aclk_ipp", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 8, GFLAGS), + + /* aclk_lcdc1_pre gates */ + GATE(0, "aclk_vio1", "aclk_lcdc1_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), + GATE(ACLK_LCDC1, "aclk_lcdc1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 3, GFLAGS), + GATE(ACLK_RGA, "aclk_rga", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 11, GFLAGS), + + /* atclk_cpu gates */ + GATE(0, "atclk", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 3, GFLAGS), + GATE(0, "trace", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), + + /* pclk_cpu gates */ + GATE(PCLK_PWM01, "pclk_pwm01", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS), + GATE(PCLK_TIMER0, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS), + GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), + GATE(PCLK_EFUSE, "pclk_efuse", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS), + GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS), + GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), + GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), + GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), + GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), + GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 5, GFLAGS), + + /* aclk_peri */ + GATE(ACLK_DMA2, "aclk_dma2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), + GATE(ACLK_SMC, "aclk_smc", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 8, GFLAGS), + GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 4, GFLAGS), + GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), + GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS), + + /* pclk_peri gates */ + GATE(0, "pclk_peri_axi_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS), + GATE(PCLK_PWM23, "pclk_pwm23", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 11, GFLAGS), + GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), + GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 13, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), + GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), + GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), + GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS), +}; + +PNAME(mux_rk3066_lcdc0_p) = { "dclk_lcdc0_src", "xin27m" }; +PNAME(mux_rk3066_lcdc1_p) = { "dclk_lcdc1_src", "xin27m" }; +PNAME(mux_sclk_cif1_p) = { "cif1_pre", "xin24m" }; +PNAME(mux_sclk_i2s1_p) = { "i2s1_pre", "i2s1_frac", "xin12m" }; +PNAME(mux_sclk_i2s2_p) = { "i2s2_pre", "i2s2_frac", "xin12m" }; + +static struct clk_div_table div_aclk_cpu_t[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 4, .div = 8 }, + { /* sentinel */ }, +}; + +static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { + DIVTBL(0, "aclk_cpu_pre", "armclk", 0, + RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t), + DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0, + RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO + | CLK_DIVIDER_READ_ONLY), + DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0, + RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO + | CLK_DIVIDER_READ_ONLY), + COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0, + RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO + | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 9, GFLAGS), + + GATE(CORE_L2C, "core_l2c", "aclk_cpu", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(9), 4, GFLAGS), + + COMPOSITE(0, "aclk_peri_pre", mux_pll_src_gpll_cpll_p, 0, + RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + + COMPOSITE(0, "dclk_lcdc0_src", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 1, GFLAGS), + MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, 0, + RK2928_CLKSEL_CON(27), 4, 1, MFLAGS), + COMPOSITE(0, "dclk_lcdc1_src", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, 0, + RK2928_CLKSEL_CON(28), 4, 1, MFLAGS), + + COMPOSITE_NOMUX(0, "cif1_pre", "cif_src", 0, + RK2928_CLKSEL_CON(29), 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 8, GFLAGS), + MUX(SCLK_CIF1, "sclk_cif1", mux_sclk_cif1_p, 0, + RK2928_CLKSEL_CON(29), 15, 1, MFLAGS), + + GATE(0, "pclkin_cif1", "ext_cif1", 0, + RK2928_CLKGATE_CON(3), 4, GFLAGS), + + COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0, + RK2928_CLKGATE_CON(5), 15, GFLAGS), + + GATE(SCLK_TIMER2, "timer2", "xin24m", 0, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + + COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0, + RK2928_CLKSEL_CON(34), 0, 16, DFLAGS, + RK2928_CLKGATE_CON(2), 15, GFLAGS), + + MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0, + RK2928_CLKSEL_CON(2), 15, 1, MFLAGS), + COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, + RK2928_CLKSEL_CON(2), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 7, GFLAGS), + COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0, + RK2928_CLKSEL_CON(6), 0, + RK2928_CLKGATE_CON(0), 8, GFLAGS), + MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, + RK2928_CLKSEL_CON(2), 8, 2, MFLAGS), + COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0, + RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0, + RK2928_CLKSEL_CON(7), 0, + RK2928_CLKGATE_CON(0), 10, GFLAGS), + MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), + COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0, + RK2928_CLKSEL_CON(4), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 11, GFLAGS), + COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0, + RK2928_CLKSEL_CON(8), 0, + RK2928_CLKGATE_CON(0), 12, GFLAGS), + MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0, + RK2928_CLKSEL_CON(4), 8, 2, MFLAGS), + + GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), + GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), + GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), + GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), + + GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(5), 14, GFLAGS), + + GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), + + GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS), + GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), + GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS), + GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), + + GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 13, GFLAGS), +}; + +static struct clk_div_table div_rk3188_aclk_core_t[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 4, .div = 8 }, + { /* sentinel */ }, +}; + +PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1", + "gpll", "cpll" }; + +static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { + COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS), + + /* do not source aclk_cpu_pre from the apll, to keep complexity down */ + COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT, + RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS), + DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0, + RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), + DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0, + RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), + COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0, + RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(4), 9, GFLAGS), + + GATE(CORE_L2C, "core_l2c", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(9), 4, GFLAGS), + + COMPOSITE(0, "aclk_peri_pre", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + + COMPOSITE(DCLK_LCDC0, "dclk_lcdc0", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 1, GFLAGS), + COMPOSITE(DCLK_LCDC1, "dclk_lcdc1", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + + COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0, + RK2928_CLKSEL_CON(34), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 15, GFLAGS), + GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0, + RK2928_CLKGATE_CON(9), 7, GFLAGS), + + GATE(SCLK_TIMER2, "timer2", "xin24m", 0, RK2928_CLKGATE_CON(3), 4, GFLAGS), + GATE(SCLK_TIMER3, "timer3", "xin24m", 0, RK2928_CLKGATE_CON(1), 2, GFLAGS), + GATE(SCLK_TIMER4, "timer4", "xin24m", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), + GATE(SCLK_TIMER5, "timer5", "xin24m", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), + GATE(SCLK_TIMER6, "timer6", "xin24m", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), + + COMPOSITE_NODIV(0, "sclk_hsicphy_480m", mux_hsicphy_p, 0, + RK2928_CLKSEL_CON(30), 0, 2, DFLAGS, + RK2928_CLKGATE_CON(3), 6, GFLAGS), + DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0, + RK2928_CLKSEL_CON(11), 8, 6, DFLAGS), + + MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0, + RK2928_CLKSEL_CON(2), 15, 1, MFLAGS), + COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, + RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0, + RK2928_CLKSEL_CON(7), 0, + RK2928_CLKGATE_CON(0), 10, GFLAGS), + MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), + + GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), + GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS), + + GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(7), 3, GFLAGS), + GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), + + GATE(PCLK_TIMER3, "pclk_timer3", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), + + GATE(PCLK_UART0, "pclk_uart0", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), + + GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), +}; + +static const char *rk3188_critical_clocks[] __initconst = { + "aclk_cpu", + "aclk_peri", + "hclk_peri", +}; + + +static void __init rockchip_reparent_clk(char *clock, char *new_parent) +{ + struct clk *clk1, *clk2; + unsigned long rate; + int ret; + + clk1 = __clk_lookup(clock); + clk2 = __clk_lookup(new_parent); + if (!IS_ERR(clk1) && !IS_ERR(clk2)) { + rate = clk_get_rate(clk1); + + ret = clk_set_parent(clk1, clk2); + if (ret < 0) + pr_err("%s: could not reparent %s to %s, ret=%d\n", + __func__, clock, new_parent, ret); + + clk_set_rate(clk1, rate); + } else { + pr_err("%s: missing clocks to reparent %s to %s\n", + __func__, clock, new_parent); + } +} + +static void __init rockchip_clk_set_rate(char *clock, unsigned long rate) +{ + struct clk *clk; + + clk=__clk_lookup(clock); + if(clk && !IS_ERR(clk)){ + clk_set_rate(clk, rate); + return; + } + pr_err("%s: missing clock %s when setting initial rate to %lu\n", + __func__, clock, rate); +} + +static void __init rockchip_clk_set_defaults(void) +{ + struct rockchip_initial_rate { + char *name; + unsigned long rate; + }; + int i; + + struct rockchip_initial_rate rates[] = { + {"gpll", 891000000}, + {"cpll", 600000000}, + {"aclk_cpu", 300000000}, + {"hclk_cpu", 150000000}, + {"pclk_cpu", 75000000}, + {"hclk_ahb2apb", 75000000}, + {"aclk_peri_pre", 150000000}, + {"hclk_peri", 150000000}, + {"pclk_peri", 75000000}, + }; + + rockchip_reparent_clk("aclk_cpu_pre","gpll"); + rockchip_reparent_clk("mac_src","dpll"); + rockchip_reparent_clk("aclk_peri_pre","cpll"); + + for(i = 0; i < ARRAY_SIZE(rates); i++) + rockchip_clk_set_rate(rates[i].name, rates[i].rate); +} + +static void __init rk3188_common_clk_init(struct device_node *np) +{ + void __iomem *reg_base; + struct clk *clk; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + + /* XXX fixed-clock should be registered before all others */ + clk=clk_fixed("xin24m",24000000); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock xin24m: %ld\n", + __func__, PTR_ERR(clk)); + + /* xin12m is created by an cru-internal divider */ + clk = clk_fixed_factor("xin12m", "xin24m", 1, 2, 0); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock xin12m: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_fixed_factor("usb480m", "xin24m", 20, 1, 0); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock usb480m: %ld\n", + __func__, PTR_ERR(clk)); + + rockchip_clk_register_branches(common_clk_branches, + ARRAY_SIZE(common_clk_branches)); + rockchip_clk_protect_critical(rk3188_critical_clocks, + ARRAY_SIZE(rk3188_critical_clocks)); + + rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); +} + +static void __init rk3066a_clk_init(struct device_node *np) +{ + rk3188_common_clk_init(np); + rockchip_clk_register_plls(rk3066_pll_clks, + ARRAY_SIZE(rk3066_pll_clks), + RK3066_GRF_SOC_STATUS); + rockchip_clk_register_branches(rk3066a_clk_branches, + ARRAY_SIZE(rk3066a_clk_branches)); + rockchip_clk_register_armclk(ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3066_cpuclk_data, rk3066_cpuclk_rates, + ARRAY_SIZE(rk3066_cpuclk_rates)); +} +CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); + +static void __init rk3188a_clk_init(struct device_node *np) +{ + rk3188_common_clk_init(np); + rockchip_clk_register_plls(rk3188_pll_clks, + ARRAY_SIZE(rk3188_pll_clks), + RK3188_GRF_SOC_STATUS); + rockchip_clk_register_branches(rk3188_clk_branches, + ARRAY_SIZE(rk3188_clk_branches)); + rockchip_clk_register_armclk(ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3188_cpuclk_data, rk3188_cpuclk_rates, + ARRAY_SIZE(rk3188_cpuclk_rates)); + + rockchip_clk_set_defaults(); +} +CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); + +static void __init rk3188_clk_init(struct device_node *np) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rk3188_pll_clks); i++) { + struct rockchip_pll_clock *pll = &rk3188_pll_clks[i]; + struct rockchip_pll_rate_table *rate; + + if (!pll->rate_table) + continue; + + rate = pll->rate_table; + while (rate->rate > 0) { + rate->bwadj = 0; + rate++; + } + } + + rk3188a_clk_init(np); +} +CLK_OF_DECLARE(rk3188_cru, "rockchip,rk3188-cru", rk3188_clk_init); diff --git a/drivers/clk/rockchip/clk-rockchip.c b/drivers/clk/rockchip/clk-rockchip.c deleted file mode 100644 index 99f836c..0000000 --- a/drivers/clk/rockchip/clk-rockchip.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Clock gate driver for Rockchip SoCs - * - * Based on Linux driver: - * Copyright (c) 2013 MundoReader S.L. - * - * 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 <common.h> -#include <init.h> -#include <driver.h> -#include <linux/clk.h> -#include <linux/clkdev.h> -#include <of_address.h> -#include <malloc.h> - -static void __init rk2928_gate_clk_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - const char *clk_parent; - const char *clk_name; - void __iomem *reg; - void __iomem *reg_idx; - int flags; - int qty; - int reg_bit; - int clkflags = CLK_SET_RATE_PARENT; - int i; - - qty = of_property_count_strings(node, "clock-output-names"); - if (qty < 0) { - pr_err("%s: error in clock-output-names %d\n", __func__, qty); - return; - } - - if (qty == 0) { - pr_info("%s: nothing to do\n", __func__); - return; - } - - reg = of_iomap(node, 0); - - clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); - if (!clk_data) - return; - - clk_data->clks = kzalloc(qty * sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) { - kfree(clk_data); - return; - } - - flags = CLK_GATE_HIWORD_MASK | CLK_GATE_INVERTED; - - for (i = 0; i < qty; i++) { - of_property_read_string_index(node, "clock-output-names", - i, &clk_name); - - /* ignore empty slots */ - if (!strcmp("reserved", clk_name)) - continue; - - clk_parent = of_clk_get_parent_name(node, i); - - reg_idx = reg + 4 * (i / 16); - reg_bit = i % 16; - - clk_data->clks[i] = clk_gate(clk_name, clk_parent, reg_idx, - reg_bit, clkflags, flags); - WARN_ON(IS_ERR(clk_data->clks[i])); - } - - clk_data->clk_num = qty; - - of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -} -CLK_OF_DECLARE(rk2928_gate, "rockchip,rk2928-gate-clk", rk2928_gate_clk_init); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c new file mode 100644 index 0000000..2a23d92 --- /dev/null +++ b/drivers/clk/rockchip/clk.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * based on + * + * samsung/clk.c + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2013 Linaro Ltd. + * Author: Thomas Abraham <thomas.ab@samsung.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 <common.h> +#include <malloc.h> +#include <linux/clk.h> +#include "clk.h" +#include <init.h> + +/** + * Register a clock branch. + * Most clock branches have a form like + * + * src1 --|--\ + * |M |--[GATE]-[DIV]- + * src2 --|--/ + * + * sometimes without one of those components. + */ +static struct clk *rockchip_clk_register_branch(const char *name, + const char **parent_names, u8 num_parents, void __iomem *base, + int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, + u8 div_shift, u8 div_width, u8 div_flags, + struct clk_div_table *div_table, int gate_offset, + u8 gate_shift, u8 gate_flags, unsigned long flags + ) +{ + struct clk *clk; + struct clk *mux = NULL; + struct clk *gate = NULL; + struct clk *div = NULL; + + if (num_parents > 1) { + mux = clk_mux_alloc(name, base + muxdiv_offset, mux_shift, mux_width, parent_names, num_parents, mux_flags); + if (!mux) + return ERR_PTR(-ENOMEM); + } + + if (gate_offset >= 0) { + gate = clk_gate_alloc(name, *parent_names, base + gate_offset, gate_shift, flags, gate_flags); + if (!gate) + return ERR_PTR(-ENOMEM); + } + + if (div_width > 0) { + div = clk_divider_alloc(name, *parent_names, base + muxdiv_offset, div_shift, div_width, div_flags); + if (!div) + return ERR_PTR(-ENOMEM); + } + + clk = clk_register_composite(name, parent_names, num_parents, + mux, + div, + gate, + flags); + + return clk; +} + +static struct clk *rockchip_clk_register_frac_branch(const char *name, + const char **parent_names, u8 num_parents, void __iomem *base, + int muxdiv_offset, u8 div_flags, + int gate_offset, u8 gate_shift, u8 gate_flags, + unsigned long flags) +{ + struct clk *clk; + struct clk *gate = NULL; + struct clk *div = NULL; + + if (gate_offset >= 0) { + gate = clk_gate_alloc(name, *parent_names, base + gate_offset, gate_shift, flags, gate_flags); + if (!gate) + return ERR_PTR(-ENOMEM); + } + + if (muxdiv_offset < 0) + return ERR_PTR(-EINVAL); + + div = clk_fractional_divider_alloc(name, *parent_names, flags, + base + muxdiv_offset, 16, 16, 0, 16, div_flags); + if (!div) + return ERR_PTR(-ENOMEM); + + clk = clk_register_composite(name, parent_names, num_parents, + NULL, + div, + gate, + flags); + + return clk; +} + +static struct clk **clk_table; +static void __iomem *reg_base; +static struct clk_onecell_data clk_data; +static struct device_node *cru_node; + +void __init rockchip_clk_init(struct device_node *np, void __iomem *base, + unsigned long nr_clks) +{ + reg_base = base; + cru_node = np; + + clk_table = calloc(nr_clks, sizeof(struct clk *)); + if (!clk_table) + pr_err("%s: could not allocate clock lookup table\n", __func__); + + clk_data.clks = clk_table; + clk_data.clk_num = nr_clks; + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} + +void rockchip_clk_add_lookup(struct clk *clk, unsigned int id) +{ + if (clk_table && id) + clk_table[id] = clk; +} + +void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, + unsigned int nr_pll, int grf_lock_offset) +{ + struct clk *clk; + int idx; + + for (idx = 0; idx < nr_pll; idx++, list++) { + clk = rockchip_clk_register_pll(list->type, list->name, + list->parent_names, list->num_parents, + reg_base, list->con_offset, grf_lock_offset, + list->lock_shift, list->mode_offset, + list->mode_shift, list->rate_table, + list->pll_flags); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", __func__, + list->name); + continue; + } + + rockchip_clk_add_lookup(clk, list->id); + } +} + +void __init rockchip_clk_register_branches( + struct rockchip_clk_branch *list, + unsigned int nr_clk) +{ + struct clk *clk = NULL; + unsigned int idx; + unsigned long flags; + + for (idx = 0; idx < nr_clk; idx++, list++) { + flags = list->flags; + + /* catch simple muxes */ + switch (list->branch_type) { + case branch_mux: + /* XXX mux_flags and flags are ored, this is safe, since there is no value clash, but isn't that elegant */ + clk = clk_mux(list->name, reg_base + list->muxdiv_offset, list->mux_shift, list->mux_width, list->parent_names, list->num_parents, list->mux_flags | flags); + break; + case branch_divider: + if (list->div_table) + clk = clk_divider_table(list->name, list->parent_names[0], reg_base + list->muxdiv_offset, list->div_shift, list->div_width, list->div_table, list->div_flags); + else + clk = clk_divider(list->name, list->parent_names[0], reg_base + list->muxdiv_offset, list->div_shift, list->div_width, list->div_flags); + break; + case branch_fraction_divider: + clk = rockchip_clk_register_frac_branch(list->name, + list->parent_names, list->num_parents, + reg_base, list->muxdiv_offset, list->div_flags, + list->gate_offset, list->gate_shift, + list->gate_flags, flags); + break; + case branch_gate: + flags |= CLK_SET_RATE_PARENT; + + clk = clk_gate(list->name, list->parent_names[0], reg_base + list->gate_offset, list->gate_shift, flags, list->gate_flags); + break; + case branch_composite: + clk = rockchip_clk_register_branch(list->name, + list->parent_names, list->num_parents, + reg_base, list->muxdiv_offset, list->mux_shift, + list->mux_width, list->mux_flags, + list->div_shift, list->div_width, + list->div_flags, list->div_table, + list->gate_offset, list->gate_shift, + list->gate_flags, flags); + break; + case branch_mmc: + break; + } + + /* none of the cases above matched */ + if (!clk) { + pr_err("%s: unknown clock type %d\n", + __func__, list->branch_type); + continue; + } + + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s: %ld\n", + __func__, list->name, PTR_ERR(clk)); + continue; + } + + rockchip_clk_add_lookup(clk, list->id); + } +} + +void __init rockchip_clk_register_armclk(unsigned int lookup_id, + const char *name, const char **parent_names, + u8 num_parents, + const struct rockchip_cpuclk_reg_data *reg_data, + const struct rockchip_cpuclk_rate_table *rates, + int nrates) +{ + struct clk *clk; + + clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, + reg_data, rates, nrates, reg_base + ); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s: %ld\n", + __func__, name, PTR_ERR(clk)); + return; + } + + rockchip_clk_add_lookup(clk, lookup_id); +} + +void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks) +{ + int i; + + /* Protect the clocks that needs to stay on */ + for (i = 0; i < nclocks; i++) { + struct clk *clk = __clk_lookup(clocks[i]); + + if (clk) + clk_enable(clk); + } +} diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h new file mode 100644 index 0000000..6f6f428 --- /dev/null +++ b/drivers/clk/rockchip/clk.h @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * based on + * + * samsung/clk.h + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2013 Linaro Ltd. + * Author: Thomas Abraham <thomas.ab@samsung.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_ROCKCHIP_CLK_H +#define CLK_ROCKCHIP_CLK_H + +#include <io.h> +#include <linux/clk.h> + +/* XXX to keep changes from kernel smaller */ +#define CLK_IGNORE_UNUSED 0 +#define CLK_GATE_SET_TO_DISABLE CLK_GATE_INVERTED +#define CLK_GET_RATE_NOCACHE 0 + +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +/* register positions shared by RK2928, RK3066 and RK3188 */ +#define RK2928_PLL_CON(x) (x * 0x4) +#define RK2928_MODE_CON 0x40 +#define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44) +#define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0) +#define RK2928_GLB_SRST_FST 0x100 +#define RK2928_GLB_SRST_SND 0x104 +#define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110) +#define RK2928_MISC_CON 0x134 + +#define RK3288_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3288_MODE_CON 0x50 +#define RK3288_CLKSEL_CON(x) (x * 0x4 + 0x60) +#define RK3288_CLKGATE_CON(x) (x * 0x4 + 0x160) +#define RK3288_GLB_SRST_FST 0x1b0 +#define RK3288_GLB_SRST_SND 0x1b4 +#define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8) +#define RK3288_MISC_CON 0x1e8 +#define RK3288_SDMMC_CON0 0x200 +#define RK3288_SDMMC_CON1 0x204 +#define RK3288_SDIO0_CON0 0x208 +#define RK3288_SDIO0_CON1 0x20c +#define RK3288_SDIO1_CON0 0x210 +#define RK3288_SDIO1_CON1 0x214 +#define RK3288_EMMC_CON0 0x218 +#define RK3288_EMMC_CON1 0x21c + +enum rockchip_pll_type { + pll_rk3066, +}; + +#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ +{ \ + .rate = _rate##U, \ + .nr = _nr, \ + .nf = _nf, \ + .no = _no, \ + .bwadj = (_nf >> 1), \ +} + +#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \ +{ \ + .rate = _rate##U, \ + .nr = _nr, \ + .nf = _nf, \ + .no = _no, \ + .bwadj = _bw, \ +} + +struct rockchip_pll_rate_table { + unsigned long rate; + unsigned int nr; + unsigned int nf; + unsigned int no; + unsigned int bwadj; +}; + +/** + * struct rockchip_pll_clock: information about pll clock + * @id: platform specific id of the clock. + * @name: name of this pll clock. + * @parent_name: name of the parent clock. + * @flags: optional flags for basic clock. + * @con_offset: offset of the register for configuring the PLL. + * @mode_offset: offset of the register for configuring the PLL-mode. + * @mode_shift: offset inside the mode-register for the mode of this pll. + * @lock_shift: offset inside the lock register for the lock status. + * @type: Type of PLL to be registered. + * @pll_flags: hardware-specific flags + * @rate_table: Table of usable pll rates + * + * Flags: + * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the + * rate_table parameters and ajust them if necessary. + */ +struct rockchip_pll_clock { + unsigned int id; + const char *name; + const char **parent_names; + u8 num_parents; + unsigned long flags; + int con_offset; + int mode_offset; + int mode_shift; + int lock_shift; + enum rockchip_pll_type type; + u8 pll_flags; + struct rockchip_pll_rate_table *rate_table; +}; + +#define ROCKCHIP_PLL_SYNC_RATE BIT(0) + +#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ + _lshift, _pflags, _rtable) \ + { \ + .id = _id, \ + .type = _type, \ + .name = _name, \ + .parent_names = _pnames, \ + .num_parents = ARRAY_SIZE(_pnames), \ + .flags = CLK_GET_RATE_NOCACHE | _flags, \ + .con_offset = _con, \ + .mode_offset = _mode, \ + .mode_shift = _mshift, \ + .lock_shift = _lshift, \ + .pll_flags = _pflags, \ + .rate_table = _rtable, \ + } + +struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, + const char *name, const char **parent_names, u8 num_parents, + void __iomem *base, int con_offset, int grf_lock_offset, + int lock_shift, int reg_mode, int mode_shift, + struct rockchip_pll_rate_table *rate_table, + u8 clk_pll_flags); + +struct rockchip_cpuclk_clksel { + int reg; + u32 val; +}; + +#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 +struct rockchip_cpuclk_rate_table { + unsigned long prate; + struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; +}; + +/** + * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock + * @core_reg: register offset of the core settings register + * @div_core_shift: core divider offset used to divide the pll value + * @div_core_mask: core divider mask + * @mux_core_shift: offset of the core multiplexer + */ +struct rockchip_cpuclk_reg_data { + int core_reg; + u8 div_core_shift; + u32 div_core_mask; + int mux_core_reg; + u8 mux_core_shift; +}; + +struct clk *rockchip_clk_register_cpuclk(const char *name, + const char **parent_names, u8 num_parents, + const struct rockchip_cpuclk_reg_data *reg_data, + const struct rockchip_cpuclk_rate_table *rates, + int nrates, void __iomem *reg_base); + +struct clk *rockchip_clk_register_mmc(const char *name, + const char **parent_names, u8 num_parents, + void __iomem *reg, int shift); + +#define PNAME(x) static const char *x[] __initconst + +enum rockchip_clk_branch_type { + branch_composite, + branch_mux, + branch_divider, + branch_fraction_divider, + branch_gate, + branch_mmc, +}; + +struct rockchip_clk_branch { + unsigned int id; + enum rockchip_clk_branch_type branch_type; + const char *name; + const char **parent_names; + u8 num_parents; + unsigned long flags; + int muxdiv_offset; + u8 mux_shift; + u8 mux_width; + u8 mux_flags; + u8 div_shift; + u8 div_width; + u8 div_flags; + struct clk_div_table *div_table; + int gate_offset; + u8 gate_shift; + u8 gate_flags; +}; + +#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ + df, go, gs, gf) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = mo, \ + .mux_shift = ms, \ + .mux_width = mw, \ + .mux_flags = mf, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + } + +#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ + go, gs, gf) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = mo, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + } + +#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ + df, dt, go, gs, gf) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = mo, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .div_table = dt, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + } + +#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ + go, gs, gf) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = mo, \ + .mux_shift = ms, \ + .mux_width = mw, \ + .mux_flags = mf, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + } + +#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ + ds, dw, df) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = mo, \ + .mux_shift = ms, \ + .mux_width = mw, \ + .mux_flags = mf, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .gate_offset = -1, \ + } + +#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ + { \ + .id = _id, \ + .branch_type = branch_fraction_divider, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = mo, \ + .div_shift = 16, \ + .div_width = 16, \ + .div_flags = df, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + } + +#define MUX(_id, cname, pnames, f, o, s, w, mf) \ + { \ + .id = _id, \ + .branch_type = branch_mux, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = o, \ + .mux_shift = s, \ + .mux_width = w, \ + .mux_flags = mf, \ + .gate_offset = -1, \ + } + +#define DIV(_id, cname, pname, f, o, s, w, df) \ + { \ + .id = _id, \ + .branch_type = branch_divider, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = o, \ + .div_shift = s, \ + .div_width = w, \ + .div_flags = df, \ + .gate_offset = -1, \ + } + +#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ + { \ + .id = _id, \ + .branch_type = branch_divider, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = o, \ + .div_shift = s, \ + .div_width = w, \ + .div_flags = df, \ + .div_table = dt, \ + } + +#define GATE(_id, cname, pname, f, o, b, gf) \ + { \ + .id = _id, \ + .branch_type = branch_gate, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .gate_offset = o, \ + .gate_shift = b, \ + .gate_flags = gf, \ + } + +#define MMC(_id, cname, pname, offset, shift) \ + { \ + .id = _id, \ + .branch_type = branch_mmc, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .muxdiv_offset = offset, \ + .div_shift = shift, \ + } + +void rockchip_clk_init(struct device_node *np, void __iomem *base, + unsigned long nr_clks); +struct regmap *rockchip_clk_get_grf(void); +void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); +void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, + unsigned int nr_clk); +void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, + unsigned int nr_pll, int grf_lock_offset); +void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, + const char **parent_names, u8 num_parents, + const struct rockchip_cpuclk_reg_data *reg_data, + const struct rockchip_cpuclk_rate_table *rates, + int nrates); +void rockchip_clk_protect_critical(const char *clocks[], int nclocks); +void rockchip_register_restart_notifier(unsigned int reg); + +#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) + +#ifdef CONFIG_RESET_CONTROLLER +void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags); +#else +static inline void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags) +{ +} +#endif + +#endif diff --git a/include/init.h b/include/init.h index 976f643..40cea55 100644 --- a/include/init.h +++ b/include/init.h @@ -6,6 +6,7 @@ */ #define __init #define __initdata +#define __initconst /* For assembly routines */ #define __BARE_INIT .section ".text_bare_init.text","ax" -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 15/18] ARM: Rockchip: Use newer DTS for Radxa Rock board. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (13 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 14/18] ARM: Rockchip: Update clk driver from Linux kernel for use with newer DTS Andrey Panov @ 2015-03-02 20:21 ` Andrey Panov 2015-03-02 20:22 ` [PATCH 16/18] ARM: Rockchip: Update " Andrey Panov ` (3 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:21 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- arch/arm/dts/rk3188-clocks.dtsi | 289 ----------------------------------- arch/arm/dts/rk3188-radxarock.dts | 32 ++-- arch/arm/dts/rk3188.dtsi | 306 -------------------------------------- arch/arm/dts/rk3xxx.dtsi | 139 ----------------- 4 files changed, 20 insertions(+), 746 deletions(-) delete mode 100644 arch/arm/dts/rk3188-clocks.dtsi delete mode 100644 arch/arm/dts/rk3188.dtsi delete mode 100644 arch/arm/dts/rk3xxx.dtsi diff --git a/arch/arm/dts/rk3188-clocks.dtsi b/arch/arm/dts/rk3188-clocks.dtsi deleted file mode 100644 index b1b92dc..0000000 --- a/arch/arm/dts/rk3188-clocks.dtsi +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2013 MundoReader S.L. - * Author: Heiko Stuebner <heiko@sntech.de> - * - * 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. - */ - -/ { - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - /* - * This is a dummy clock, to be used as placeholder on - * other mux clocks when a specific parent clock is not - * yet implemented. It should be dropped when the driver - * is complete. - */ - dummy: dummy { - compatible = "fixed-clock"; - clock-frequency = <0>; - #clock-cells = <0>; - }; - - xin24m: xin24m { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - #clock-cells = <0>; - }; - - dummy48m: dummy48m { - compatible = "fixed-clock"; - clock-frequency = <48000000>; - #clock-cells = <0>; - }; - - dummy150m: dummy150m { - compatible = "fixed-clock"; - clock-frequency = <150000000>; - #clock-cells = <0>; - }; - - clk_gates0: gate-clk@200000d0 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000d0 0x4>; - clocks = <&dummy150m>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>; - - clock-output-names = - "gate_core_periph", "gate_cpu_gpll", - "gate_ddrphy", "gate_aclk_cpu", - "gate_hclk_cpu", "gate_pclk_cpu", - "gate_atclk_cpu", "gate_aclk_core", - "reserved", "gate_i2s0", - "gate_i2s0_frac", "reserved", - "reserved", "gate_spdif", - "gate_spdif_frac", "gate_testclk"; - - #clock-cells = <1>; - }; - - clk_gates1: gate-clk@200000d4 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000d4 0x4>; - clocks = <&xin24m>, <&xin24m>, - <&xin24m>, <&dummy>, - <&dummy>, <&xin24m>, - <&xin24m>, <&dummy>, - <&xin24m>, <&dummy>, - <&xin24m>, <&dummy>, - <&xin24m>, <&dummy>, - <&xin24m>, <&dummy>; - - clock-output-names = - "gate_timer0", "gate_timer1", - "gate_timer3", "gate_jtag", - "gate_aclk_lcdc1_src", "gate_otgphy0", - "gate_otgphy1", "gate_ddr_gpll", - "gate_uart0", "gate_frac_uart0", - "gate_uart1", "gate_frac_uart1", - "gate_uart2", "gate_frac_uart2", - "gate_uart3", "gate_frac_uart3"; - - #clock-cells = <1>; - }; - - clk_gates2: gate-clk@200000d8 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000d8 0x4>; - clocks = <&clk_gates2 1>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&clk_gates2 3>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy48m>, - <&dummy>, <&dummy48m>, - <&dummy>, <&dummy>; - - clock-output-names = - "gate_periph_src", "gate_aclk_periph", - "gate_hclk_periph", "gate_pclk_periph", - "gate_smc", "gate_mac", - "gate_hsadc", "gate_hsadc_frac", - "gate_saradc", "gate_spi0", - "gate_spi1", "gate_mmc0", - "gate_mac_lbtest", "gate_mmc1", - "gate_emmc", "reserved"; - - #clock-cells = <1>; - }; - - clk_gates3: gate-clk@200000dc { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000dc 0x4>; - clocks = <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&xin24m>, <&xin24m>, - <&dummy>, <&dummy>, - <&xin24m>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&xin24m>, <&dummy>; - - clock-output-names = - "gate_aclk_lcdc0_src", "gate_dclk_lcdc0", - "gate_dclk_lcdc1", "gate_pclkin_cif0", - "gate_timer2", "gate_timer4", - "gate_hsicphy", "gate_cif0_out", - "gate_timer5", "gate_aclk_vepu", - "gate_hclk_vepu", "gate_aclk_vdpu", - "gate_hclk_vdpu", "reserved", - "gate_timer6", "gate_aclk_gpu_src"; - - #clock-cells = <1>; - }; - - clk_gates4: gate-clk@200000e0 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000e0 0x4>; - clocks = <&clk_gates2 2>, <&clk_gates2 3>, - <&clk_gates2 1>, <&clk_gates2 1>, - <&clk_gates2 1>, <&clk_gates2 2>, - <&clk_gates2 2>, <&clk_gates2 2>, - <&clk_gates0 4>, <&clk_gates0 4>, - <&clk_gates0 3>, <&dummy>, - <&clk_gates0 3>, <&dummy>, - <&dummy>, <&dummy>; - - clock-output-names = - "gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix", - "gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix", - "gate_aclk_pei_niu", "gate_hclk_usb_peri", - "gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri", - "gate_hclk_cpubus", "gate_hclk_ahb2apb", - "gate_aclk_strc_sys", "reserved", - "gate_aclk_intmem", "reserved", - "gate_hclk_imem1", "gate_hclk_imem0"; - - #clock-cells = <1>; - }; - - clk_gates5: gate-clk@200000e4 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000e4 0x4>; - clocks = <&clk_gates0 3>, <&clk_gates2 1>, - <&clk_gates0 5>, <&clk_gates0 5>, - <&clk_gates0 5>, <&clk_gates0 5>, - <&clk_gates0 4>, <&clk_gates0 5>, - <&clk_gates2 1>, <&clk_gates2 2>, - <&clk_gates2 2>, <&clk_gates2 2>, - <&clk_gates2 2>, <&clk_gates4 5>; - - clock-output-names = - "gate_aclk_dmac1", "gate_aclk_dmac2", - "gate_pclk_efuse", "gate_pclk_tzpc", - "gate_pclk_grf", "gate_pclk_pmu", - "gate_hclk_rom", "gate_pclk_ddrupctl", - "gate_aclk_smc", "gate_hclk_nandc", - "gate_hclk_mmc0", "gate_hclk_mmc1", - "gate_hclk_emmc", "gate_hclk_otg0"; - - #clock-cells = <1>; - }; - - clk_gates6: gate-clk@200000e8 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000e8 0x4>; - clocks = <&clk_gates3 0>, <&clk_gates0 4>, - <&clk_gates0 4>, <&clk_gates1 4>, - <&clk_gates0 4>, <&clk_gates3 0>, - <&dummy>, <&dummy>, - <&clk_gates3 0>, <&clk_gates0 4>, - <&clk_gates0 4>, <&clk_gates1 4>, - <&clk_gates0 4>, <&clk_gates3 0>; - - clock-output-names = - "gate_aclk_lcdc0", "gate_hclk_lcdc0", - "gate_hclk_lcdc1", "gate_aclk_lcdc1", - "gate_hclk_cif0", "gate_aclk_cif0", - "reserved", "reserved", - "gate_aclk_ipp", "gate_hclk_ipp", - "gate_hclk_rga", "gate_aclk_rga", - "gate_hclk_vio_bus", "gate_aclk_vio0"; - - #clock-cells = <1>; - }; - - clk_gates7: gate-clk@200000ec { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000ec 0x4>; - clocks = <&clk_gates2 2>, <&clk_gates0 4>, - <&clk_gates0 4>, <&dummy>, - <&dummy>, <&clk_gates2 2>, - <&clk_gates2 2>, <&clk_gates0 5>, - <&dummy>, <&clk_gates0 5>, - <&clk_gates0 5>, <&clk_gates2 3>, - <&clk_gates2 3>, <&clk_gates2 3>, - <&clk_gates2 3>, <&clk_gates2 3>; - - clock-output-names = - "gate_hclk_emac", "gate_hclk_spdif", - "gate_hclk_i2s0_2ch", "gate_hclk_otg1", - "gate_hclk_hsic", "gate_hclk_hsadc", - "gate_hclk_pidf", "gate_pclk_timer0", - "reserved", "gate_pclk_timer2", - "gate_pclk_pwm01", "gate_pclk_pwm23", - "gate_pclk_spi0", "gate_pclk_spi1", - "gate_pclk_saradc", "gate_pclk_wdt"; - - #clock-cells = <1>; - }; - - clk_gates8: gate-clk@200000f0 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000f0 0x4>; - clocks = <&clk_gates0 5>, <&clk_gates0 5>, - <&clk_gates2 3>, <&clk_gates2 3>, - <&clk_gates0 5>, <&clk_gates0 5>, - <&clk_gates2 3>, <&clk_gates2 3>, - <&clk_gates2 3>, <&clk_gates0 5>, - <&clk_gates0 5>, <&clk_gates0 5>, - <&clk_gates2 3>, <&dummy>; - - clock-output-names = - "gate_pclk_uart0", "gate_pclk_uart1", - "gate_pclk_uart2", "gate_pclk_uart3", - "gate_pclk_i2c0", "gate_pclk_i2c1", - "gate_pclk_i2c2", "gate_pclk_i2c3", - "gate_pclk_i2c4", "gate_pclk_gpio0", - "gate_pclk_gpio1", "gate_pclk_gpio2", - "gate_pclk_gpio3", "gate_aclk_gps"; - - #clock-cells = <1>; - }; - - clk_gates9: gate-clk@200000f4 { - compatible = "rockchip,rk2928-gate-clk"; - reg = <0x200000f4 0x4>; - clocks = <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>, - <&dummy>, <&dummy>; - - clock-output-names = - "gate_clk_core_dbg", "gate_pclk_dbg", - "gate_clk_trace", "gate_atclk", - "gate_clk_l2c", "gate_aclk_vio1", - "gate_pclk_publ", "gate_aclk_gpu"; - - #clock-cells = <1>; - }; - }; - -}; diff --git a/arch/arm/dts/rk3188-radxarock.dts b/arch/arm/dts/rk3188-radxarock.dts index 2d49d69..47b2487 100644 --- a/arch/arm/dts/rk3188-radxarock.dts +++ b/arch/arm/dts/rk3188-radxarock.dts @@ -12,22 +12,30 @@ * GNU General Public License for more details. */ -/dts-v1/; -#include "rk3188.dtsi" +#include <arm/rk3188-radxarock.dts> / { - model = "Radxa Rock"; - compatible = "radxa,rock", "rockchip,rk3188"; + chosen { + linux,stdout-path = &uart2; - memory { - reg = <0x60000000 0x80000000>; - }; - - soc { - uart2: serial@20064000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_xfer>; + environment { + compatible = "barebox,environment"; + device-path = &mmc0, "partname:barebox-environment"; status = "okay"; }; }; }; + +&mmc0 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0x80000>; + }; + partition@1 { + label = "barebox-environment"; + reg = <0x80000 0x80000>; + }; +}; diff --git a/arch/arm/dts/rk3188.dtsi b/arch/arm/dts/rk3188.dtsi deleted file mode 100644 index 277a915..0000000 --- a/arch/arm/dts/rk3188.dtsi +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2013 MundoReader S.L. - * Author: Heiko Stuebner <heiko@sntech.de> - * - * 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 <dt-bindings/gpio/gpio.h> -#include <dt-bindings/pinctrl/rockchip.h> -#include "rk3xxx.dtsi" -#include "rk3188-clocks.dtsi" - -/* barebox additions */ -/ { - soc { - ethernet@10204000 { - compatible = "snps,arc-emac"; - reg = <0x10204000 0x100>; - interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; - clock-frequency = <50000000>; - max-speed = <100>; - phy = <&phy0>; - pinctrl-names = "default"; - pinctrl-0 = <&emac0_pins>; - - #address-cells = <1>; - #size-cells = <0>; - phy0: ethernet-phy@0 { - reg = <0>; - }; - }; - - pinctrl@20008000 { - emac0 { - emac0_pins: emac0-pins { - rockchip,pins = <RK_GPIO3 16 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 17 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 18 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 19 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 20 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 21 RK_FUNC_2 &pcfg_pull_none>, - <RK_GPIO3 22 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 23 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 24 RK_FUNC_2 &pcfg_pull_up>, - <RK_GPIO3 25 RK_FUNC_2 &pcfg_pull_up>; - }; - }; - }; - }; -}; - -/* original rk3188.dtsi from Linux 3.16 */ -/ { - compatible = "rockchip,rk3188"; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - enable-method = "rockchip,rk3066-smp"; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x0>; - }; - cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x1>; - }; - cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x2>; - }; - cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - next-level-cache = <&L2>; - reg = <0x3>; - }; - }; - - soc { - global-timer@1013c200 { - interrupts = <GIC_PPI 11 0xf04>; - }; - - local-timer@1013c600 { - interrupts = <GIC_PPI 13 0xf04>; - }; - - sram: sram@10080000 { - compatible = "mmio-sram"; - reg = <0x10080000 0x8000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x10080000 0x8000>; - - smp-sram@0 { - compatible = "rockchip,rk3066-smp-sram"; - reg = <0x0 0x50>; - }; - }; - - pinctrl@20008000 { - compatible = "rockchip,rk3188-pinctrl"; - rockchip,grf = <&grf>; - rockchip,pmu = <&pmu>; - - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio0: gpio0@0x2000a000 { - compatible = "rockchip,rk3188-gpio-bank0"; - reg = <0x2000a000 0x100>; - interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk_gates8 9>; - - gpio-controller; - #gpio-cells = <2>; - - interrupt-controller; - #interrupt-cells = <2>; - }; - - gpio1: gpio1@0x2003c000 { - compatible = "rockchip,gpio-bank"; - reg = <0x2003c000 0x100>; - interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk_gates8 10>; - - gpio-controller; - #gpio-cells = <2>; - - interrupt-controller; - #interrupt-cells = <2>; - }; - - gpio2: gpio2@2003e000 { - compatible = "rockchip,gpio-bank"; - reg = <0x2003e000 0x100>; - interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk_gates8 11>; - - gpio-controller; - #gpio-cells = <2>; - - interrupt-controller; - #interrupt-cells = <2>; - }; - - gpio3: gpio3@20080000 { - compatible = "rockchip,gpio-bank"; - reg = <0x20080000 0x100>; - interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk_gates8 12>; - - gpio-controller; - #gpio-cells = <2>; - - interrupt-controller; - #interrupt-cells = <2>; - }; - - pcfg_pull_up: pcfg_pull_up { - bias-pull-up; - }; - - pcfg_pull_down: pcfg_pull_down { - bias-pull-down; - }; - - pcfg_pull_none: pcfg_pull_none { - bias-disable; - }; - - uart0 { - uart0_xfer: uart0-xfer { - rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>, - <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>; - }; - - uart0_cts: uart0-cts { - rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>; - }; - - uart0_rts: uart0-rts { - rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>; - }; - }; - - uart1 { - uart1_xfer: uart1-xfer { - rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>, - <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>; - }; - - uart1_cts: uart1-cts { - rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>; - }; - - uart1_rts: uart1-rts { - rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>; - }; - }; - - uart2 { - uart2_xfer: uart2-xfer { - rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>, - <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>; - }; - /* no rts / cts for uart2 */ - }; - - uart3 { - uart3_xfer: uart3-xfer { - rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>, - <RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>; - }; - - uart3_cts: uart3-cts { - rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>; - }; - - uart3_rts: uart3-rts { - rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>; - }; - }; - - sd0 { - sd0_clk: sd0-clk { - rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd0_cmd: sd0-cmd { - rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd0_cd: sd0-cd { - rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd0_wp: sd0-wp { - rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd0_pwr: sd0-pwr { - rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd0_bus1: sd0-bus-width1 { - rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd0_bus4: sd0-bus-width4 { - rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>, - <RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>, - <RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>, - <RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>; - }; - }; - - sd1 { - sd1_clk: sd1-clk { - rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd1_cmd: sd1-cmd { - rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd1_cd: sd1-cd { - rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd1_wp: sd1-wp { - rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd1_bus1: sd1-bus-width1 { - rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>; - }; - - sd1_bus4: sd1-bus-width4 { - rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>, - <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>, - <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>, - <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>; - }; - }; - }; - }; -}; diff --git a/arch/arm/dts/rk3xxx.dtsi b/arch/arm/dts/rk3xxx.dtsi deleted file mode 100644 index 2adf1cc..0000000 --- a/arch/arm/dts/rk3xxx.dtsi +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2013 MundoReader S.L. - * Author: Heiko Stuebner <heiko@sntech.de> - * - * 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 <dt-bindings/interrupt-controller/irq.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> -#include "skeleton.dtsi" - -/ { - interrupt-parent = <&gic>; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - scu@1013c000 { - compatible = "arm,cortex-a9-scu"; - reg = <0x1013c000 0x100>; - }; - - pmu: pmu@20004000 { - compatible = "rockchip,rk3066-pmu", "syscon"; - reg = <0x20004000 0x100>; - }; - - grf: grf@20008000 { - compatible = "syscon"; - reg = <0x20008000 0x200>; - }; - - gic: interrupt-controller@1013d000 { - compatible = "arm,cortex-a9-gic"; - interrupt-controller; - #interrupt-cells = <3>; - reg = <0x1013d000 0x1000>, - <0x1013c100 0x0100>; - }; - - L2: l2-cache-controller@10138000 { - compatible = "arm,pl310-cache"; - reg = <0x10138000 0x1000>; - cache-unified; - cache-level = <2>; - }; - - global-timer@1013c200 { - compatible = "arm,cortex-a9-global-timer"; - reg = <0x1013c200 0x20>; - interrupts = <GIC_PPI 11 0x304>; - clocks = <&dummy150m>; - }; - - local-timer@1013c600 { - compatible = "arm,cortex-a9-twd-timer"; - reg = <0x1013c600 0x20>; - interrupts = <GIC_PPI 13 0x304>; - clocks = <&dummy150m>; - }; - - uart0: serial@10124000 { - compatible = "snps,dw-apb-uart"; - reg = <0x10124000 0x400>; - interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&clk_gates1 8>; - status = "disabled"; - }; - - uart1: serial@10126000 { - compatible = "snps,dw-apb-uart"; - reg = <0x10126000 0x400>; - interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&clk_gates1 10>; - status = "disabled"; - }; - - uart2: serial@20064000 { - compatible = "snps,dw-apb-uart"; - reg = <0x20064000 0x400>; - interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&clk_gates1 12>; - status = "disabled"; - }; - - uart3: serial@20068000 { - compatible = "snps,dw-apb-uart"; - reg = <0x20068000 0x400>; - interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&clk_gates1 14>; - status = "disabled"; - }; - - dwmmc@10214000 { - compatible = "rockchip,rk2928-dw-mshc"; - reg = <0x10214000 0x1000>; - interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - - clocks = <&clk_gates5 10>, <&clk_gates2 11>; - clock-names = "biu", "ciu"; - - status = "disabled"; - }; - - dwmmc@10218000 { - compatible = "rockchip,rk2928-dw-mshc"; - reg = <0x10218000 0x1000>; - interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - - clocks = <&clk_gates5 11>, <&clk_gates2 13>; - clock-names = "biu", "ciu"; - - status = "disabled"; - }; - }; -}; -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 16/18] ARM: Rockchip: Update Radxa Rock board. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (14 preceding siblings ...) 2015-03-02 20:21 ` [PATCH 15/18] ARM: Rockchip: Use newer DTS for Radxa Rock board Andrey Panov @ 2015-03-02 20:22 ` Andrey Panov 2015-03-02 20:22 ` [PATCH 17/18] ARM: Rockchip: Add Radxa Rock defconfig Andrey Panov ` (2 subsequent siblings) 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:22 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- arch/arm/boards/radxa-rock/board.c | 34 +++++--------------------- arch/arm/boards/radxa-rock/env/boot/mshc1 | 9 +++++++ arch/arm/boards/radxa-rock/env/boot/mshc1-old | 8 ++++++ arch/arm/boards/radxa-rock/env/init/bootsource | 7 ++++++ arch/arm/boards/radxa-rock/env/nv/hostname | 1 + 5 files changed, 31 insertions(+), 28 deletions(-) create mode 100644 arch/arm/boards/radxa-rock/env/boot/mshc1 create mode 100644 arch/arm/boards/radxa-rock/env/boot/mshc1-old create mode 100644 arch/arm/boards/radxa-rock/env/init/bootsource create mode 100644 arch/arm/boards/radxa-rock/env/nv/hostname diff --git a/arch/arm/boards/radxa-rock/board.c b/arch/arm/boards/radxa-rock/board.c index 3d9b5be..49ff26d 100644 --- a/arch/arm/boards/radxa-rock/board.c +++ b/arch/arm/boards/radxa-rock/board.c @@ -16,8 +16,9 @@ #include <io.h> #include <i2c/i2c.h> #include <i2c/i2c-gpio.h> -#include <mach/rockchip-pll.h> +#include <mach/rockchip-regs.h> #include <mfd/act8846.h> +#include <asm/armlinux.h> static struct i2c_board_info radxa_rock_i2c_devices[] = { { @@ -43,20 +44,6 @@ static void radxa_rock_pmic_init(void) act8846_set_bits(pmic, ACT8846_LDO9_CTRL, BIT(7), BIT(7)); } -static int setup_plls(void) -{ - if (!of_machine_is_compatible("radxa,rock")) - return 0; - - /* Codec PLL frequency: 594 MHz */ - rk3188_pll_set_parameters(RK3188_CPLL, 2, 198, 4); - /* General PLL frequency: 300 MHz */ - rk3188_pll_set_parameters(RK3188_GPLL, 1, 50, 4); - - return 0; -} -coredevice_initcall(setup_plls); - static int devices_init(void) { if (!of_machine_is_compatible("radxa,rock")) @@ -68,20 +55,11 @@ static int devices_init(void) radxa_rock_pmic_init(); - /* Set mac_pll divisor to 6 (50MHz output) */ - writel((5 << 8) | (0x1f << 24), 0x20000098); + armlinux_set_architecture(3066); - return 0; -} -device_initcall(devices_init); - -static int hostname_init(void) -{ - if (!of_machine_is_compatible("radxa,rock")) - return 0; - - barebox_set_hostname("radxa-rock"); + /* Map SRAM to address 0, kernel relies on this */ + writel((RK_SOC_CON0_REMAP << 16) | RK_SOC_CON0_REMAP, RK_GRF_BASE + RK_GRF_SOC_CON0); return 0; } -postcore_initcall(hostname_init); +device_initcall(devices_init); diff --git a/arch/arm/boards/radxa-rock/env/boot/mshc1 b/arch/arm/boards/radxa-rock/env/boot/mshc1 new file mode 100644 index 0000000..964b6cc --- /dev/null +++ b/arch/arm/boards/radxa-rock/env/boot/mshc1 @@ -0,0 +1,9 @@ +#!/bin/sh + +mount /dev/mshc1.0 + +oftree -f +oftree -l /mnt/mshc1.0/rk3188-radxarock.dtb + +global.bootm.image=/mnt/mshc1.0/zImage +global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootwait" diff --git a/arch/arm/boards/radxa-rock/env/boot/mshc1-old b/arch/arm/boards/radxa-rock/env/boot/mshc1-old new file mode 100644 index 0000000..1e1b577 --- /dev/null +++ b/arch/arm/boards/radxa-rock/env/boot/mshc1-old @@ -0,0 +1,8 @@ +#!/bin/sh + +mount /dev/mshc1.0 + +oftree -f + +global.bootm.image=/mnt/mshc1.0/zImage-old +global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootwait" diff --git a/arch/arm/boards/radxa-rock/env/init/bootsource b/arch/arm/boards/radxa-rock/env/init/bootsource new file mode 100644 index 0000000..4e8299b --- /dev/null +++ b/arch/arm/boards/radxa-rock/env/init/bootsource @@ -0,0 +1,7 @@ +#!/bin/sh + +if [ -n "$nv.boot.default" ]; then + exit +fi + +global.boot.default=mshc1 diff --git a/arch/arm/boards/radxa-rock/env/nv/hostname b/arch/arm/boards/radxa-rock/env/nv/hostname new file mode 100644 index 0000000..16523ac --- /dev/null +++ b/arch/arm/boards/radxa-rock/env/nv/hostname @@ -0,0 +1 @@ +radxa-rock -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 17/18] ARM: Rockchip: Add Radxa Rock defconfig 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (15 preceding siblings ...) 2015-03-02 20:22 ` [PATCH 16/18] ARM: Rockchip: Update " Andrey Panov @ 2015-03-02 20:22 ` Andrey Panov 2015-03-02 20:22 ` [PATCH 18/18] ARM: Rockchip: Add documentation Andrey Panov 2015-03-02 20:54 ` [PATCH 00/18] Update support for RK3188, Radxa Rock board Antony Pavlov 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:22 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- arch/arm/configs/radxa_rock_defconfig | 110 ++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 arch/arm/configs/radxa_rock_defconfig diff --git a/arch/arm/configs/radxa_rock_defconfig b/arch/arm/configs/radxa_rock_defconfig new file mode 100644 index 0000000..6e7da3e --- /dev/null +++ b/arch/arm/configs/radxa_rock_defconfig @@ -0,0 +1,110 @@ +CONFIG_ARCH_ROCKCHIP=y +CONFIG_MACH_RADXA_ROCK=y +CONFIG_AEABI=y +CONFIG_ARM_BOARD_APPEND_ATAG=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_ARM_UNWIND=y +CONFIG_MALLOC_SIZE=0x4000000 +CONFIG_EXPERIMENTAL=y +CONFIG_MALLOC_TLSF=y +CONFIG_KALLSYMS=y +CONFIG_RELOCATABLE=y +CONFIG_PROMPT="radxa-rock:" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_DEFAULT_COMPRESSION_LZO=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/radxa-rock/env" +CONFIG_BAREBOXENV_TARGET=y +CONFIG_BAREBOXCRC32_TARGET=y +CONFIG_POLLER=y +CONFIG_CMD_DMESG=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_ARM_MMUINFO=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y +CONFIG_CMD_BOOTM_AIMAGE=y +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_GO=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_RESET=y +CONFIG_CMD_SAVES=y +CONFIG_CMD_UIMAGE=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_DEFAULTENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_LN=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA224SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_LET=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_READF=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_HOST=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_PING=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_MM=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DETECT=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_LED=y +CONFIG_CMD_SPI=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_DISPLAY_TIMINGS=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIME=y +CONFIG_NET=y +CONFIG_NET_NFS=y +CONFIG_NET_NETCONSOLE=y +CONFIG_OFDEVICE=y +CONFIG_OF_BAREBOX_DRIVERS=y +CONFIG_DRIVER_SERIAL_NS16550=y +CONFIG_DRIVER_NET_ARC_EMAC=y +CONFIG_SMSC_PHY=y +CONFIG_I2C=y +CONFIG_I2C_GPIO=y +CONFIG_MCI=y +CONFIG_MCI_STARTUP=y +CONFIG_MCI_MMC_BOOT_PARTITIONS=y +CONFIG_MCI_DW=y +CONFIG_MCI_DW_PIO=y +CONFIG_MFD_ACT8846=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_OF=y +CONFIG_GENERIC_PHY=y +CONFIG_FS_CRAMFS=y +CONFIG_FS_EXT4=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_FS_FAT=y +CONFIG_FS_BPKFS=y +CONFIG_FS_UIMAGEFS=y +CONFIG_LZO_DECOMPRESS=y -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 18/18] ARM: Rockchip: Add documentation. 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (16 preceding siblings ...) 2015-03-02 20:22 ` [PATCH 17/18] ARM: Rockchip: Add Radxa Rock defconfig Andrey Panov @ 2015-03-02 20:22 ` Andrey Panov 2015-03-02 20:54 ` [PATCH 00/18] Update support for RK3188, Radxa Rock board Antony Pavlov 18 siblings, 0 replies; 24+ messages in thread From: Andrey Panov @ 2015-03-02 20:22 UTC (permalink / raw) To: barebox Signed-off-by: Andrey Panov <rockford@yandex.ru> --- Documentation/boards/rockchip.rst | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/boards/rockchip.rst diff --git a/Documentation/boards/rockchip.rst b/Documentation/boards/rockchip.rst new file mode 100644 index 0000000..e064255 --- /dev/null +++ b/Documentation/boards/rockchip.rst @@ -0,0 +1,48 @@ +Rockchip RK3188 +=============== + +Radxa Rock +---------- + +Radxa Rock is a small SBC based on Rockchip RK3188 SoC. +See http://radxa.com/Rock for additional information. + +Building +^^^^^^^^ + +.. code-block:: sh + + make ARCH=arm radxa_rock_defconfig + make ARCH=arm + +Creating bootable SD card +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This will require a DRAM setup blob and additional utilities, see above. + +Card layout (block == 0x200 bytes). + +============ ========================================== +Block Number Name +============ ========================================== +0x0000 DOS partition table +0x0040 RK bootinfo (BootROM check sector) +0x0044 DRAM setup routine +0x005C Bootloader (barebox) +0x0400 Barebox environment +0x0800 Free space start +============ ========================================== + +Instructions. + +* Make 2 partitions on SD for boot and root filesystems. +* Checkout and compile https://github.com/apxii/rkboottools +* Get some RK3188 bootloader from https://github.com/neo-technologies/rockchip-bootloader +* Run "rk-splitboot RK3188Loader(L)_V2.13.bin" command. (for example). + You will get FlashData file with others. It's a DRAM setup blob. +* Otherwise it can be borrowed from RK U-boot sources from + https://github.com/linux-rockchip/u-boot-rockchip/blob/u-boot-rk3188/tools/rk_tools/3188_LPDDR2_300MHz_DDR3_300MHz_20130830.bin +* Run "rk-makebootable FlashData barebox-radxa-rock.bin rrboot.bin" +* Insert SD card and run "dd if=rrboot.bin of=</dev/sdcard> bs=$((0x200)) seek=$((0x40))" +* SD card is ready + -- 2.1.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 00/18] Update support for RK3188, Radxa Rock board 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov ` (17 preceding siblings ...) 2015-03-02 20:22 ` [PATCH 18/18] ARM: Rockchip: Add documentation Andrey Panov @ 2015-03-02 20:54 ` Antony Pavlov 18 siblings, 0 replies; 24+ messages in thread From: Antony Pavlov @ 2015-03-02 20:54 UTC (permalink / raw) To: Andrey Panov; +Cc: barebox On Mon, 2 Mar 2015 23:21:44 +0300 Andrey Panov <rockford@yandex.ru> wrote: > Hello! > > This series will update support for Radxa Rock board, allowing it > to boot from SD card with Barebox as first-stage loader. > > Based on next branch. Please use checkpatch.pl on your series. Also please do not use a period '.' at the end of the first line of a commit message. > -- > Andrey > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox -- -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2015-03-03 9:03 UTC | newest] Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-03-02 20:21 [PATCH 00/18] Update support for RK3188, Radxa Rock board Andrey Panov 2015-03-02 20:21 ` [PATCH 01/18] lib: Add gcd() function Andrey Panov 2015-03-03 7:45 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 02/18] CLK: Add support for composite clock from Linux kernel Andrey Panov 2015-03-03 7:48 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 03/18] CLK: Add fractional divider clock support " Andrey Panov 2015-03-03 7:51 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 04/18] CLK: clk-mux: Respect CLK_MUX_HIWORD_MASK flag Andrey Panov 2015-03-02 20:21 ` [PATCH 05/18] CLK: clk-divider: Respect CLK_DIVIDER_HIWORD_MASK flag Andrey Panov 2015-03-02 20:21 ` [PATCH 06/18] CLK: clk-divider: Introduce clk_divider_alloc() and *_free() routines Andrey Panov 2015-03-02 20:21 ` [PATCH 07/18] CLK: clk-divider: Respect CLK_DIVIDER_POWER_OF_TWO flag Andrey Panov 2015-03-02 20:21 ` [PATCH 08/18] CLK: Check and do not allow to register clock twice Andrey Panov 2015-03-03 9:03 ` Sascha Hauer 2015-03-02 20:21 ` [PATCH 09/18] CLK: Add helper defines to barebox-wrapper.h for easier porting of drivers from Linux kernel Andrey Panov 2015-03-02 20:21 ` [PATCH 10/18] NET: arc_emac: Update for newer DTS, support for Rockchip .compatible Andrey Panov 2015-03-02 20:21 ` [PATCH 11/18] MMC: dw_mmc: Add support for PIO mode and Rockchip variant of this hardware Andrey Panov 2015-03-02 20:21 ` [PATCH 12/18] ARM: Rockchip: Remove unused files from mach-rockchip Andrey Panov 2015-03-02 20:21 ` [PATCH 13/18] ARM: Rockchip: Update Kconfig Andrey Panov 2015-03-02 20:21 ` [PATCH 14/18] ARM: Rockchip: Update clk driver from Linux kernel for use with newer DTS Andrey Panov 2015-03-02 20:21 ` [PATCH 15/18] ARM: Rockchip: Use newer DTS for Radxa Rock board Andrey Panov 2015-03-02 20:22 ` [PATCH 16/18] ARM: Rockchip: Update " Andrey Panov 2015-03-02 20:22 ` [PATCH 17/18] ARM: Rockchip: Add Radxa Rock defconfig Andrey Panov 2015-03-02 20:22 ` [PATCH 18/18] ARM: Rockchip: Add documentation Andrey Panov 2015-03-02 20:54 ` [PATCH 00/18] Update support for RK3188, Radxa Rock board Antony Pavlov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox