819c1de344
Add a CLK_SET_RATE_NO_REPARENT clock flag, which will prevent muxes being reparented during clk_set_rate. To avoid breaking existing platforms, all callers of clk_register_mux() are adjusted to pass the new flag. Platform maintainers are encouraged to remove the flag if they wish to allow mux reparenting on set_rate. Signed-off-by: James Hogan <james.hogan@imgtec.com> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Cc: Mike Turquette <mturquette@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Sascha Hauer <kernel@pengutronix.de> Cc: Stephen Warren <swarren@wwwdotorg.org> Cc: Viresh Kumar <viresh.linux@gmail.com> Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: Haojian Zhuang <haojian.zhuang@linaro.org> Cc: Chao Xie <xiechao.mail@gmail.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: "Emilio López" <emilio@elopez.com.ar> Cc: Gregory CLEMENT <gregory.clement@free-electrons.com> Cc: Maxime Ripard <maxime.ripard@free-electrons.com> Cc: Prashant Gaikwad <pgaikwad@nvidia.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Peter De Schrijver <pdeschrijver@nvidia.com> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Andrew Chew <achew@nvidia.com> Cc: Doug Anderson <dianders@chromium.org> Cc: Heiko Stuebner <heiko@sntech.de> Cc: Paul Walmsley <pwalmsley@nvidia.com> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com> Cc: Thomas Abraham <thomas.abraham@linaro.org> Cc: Tomasz Figa <t.figa@samsung.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: spear-devel@list.st.com Cc: linux-tegra@vger.kernel.org Tested-by: Haojian Zhuang <haojian.zhuang@gmail.com> Acked-by: Stephen Warren <swarren@nvidia.com> [tegra] Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> [sunxi] Acked-by: Sören Brinkmann <soren.brinkmann@xilinx.com> [Zynq] Signed-off-by: Mike Turquette <mturquette@linaro.org>
344 lines
10 KiB
C
344 lines
10 KiB
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 version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* Common Clock Framework support for all Samsung platforms
|
|
*/
|
|
|
|
#ifndef __SAMSUNG_CLK_H
|
|
#define __SAMSUNG_CLK_H
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/clkdev.h>
|
|
#include <linux/io.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include "clk-pll.h"
|
|
|
|
/**
|
|
* struct samsung_clock_alias: information about mux clock
|
|
* @id: platform specific id of the clock.
|
|
* @dev_name: name of the device to which this clock belongs.
|
|
* @alias: optional clock alias name to be assigned to this clock.
|
|
*/
|
|
struct samsung_clock_alias {
|
|
unsigned int id;
|
|
const char *dev_name;
|
|
const char *alias;
|
|
};
|
|
|
|
#define ALIAS(_id, dname, a) \
|
|
{ \
|
|
.id = _id, \
|
|
.dev_name = dname, \
|
|
.alias = a, \
|
|
}
|
|
|
|
#define MHZ (1000 * 1000)
|
|
|
|
/**
|
|
* struct samsung_fixed_rate_clock: information about fixed-rate clock
|
|
* @id: platform specific id of the clock.
|
|
* @name: name of this fixed-rate clock.
|
|
* @parent_name: optional parent clock name.
|
|
* @flags: optional fixed-rate clock flags.
|
|
* @fixed-rate: fixed clock rate of this clock.
|
|
*/
|
|
struct samsung_fixed_rate_clock {
|
|
unsigned int id;
|
|
char *name;
|
|
const char *parent_name;
|
|
unsigned long flags;
|
|
unsigned long fixed_rate;
|
|
};
|
|
|
|
#define FRATE(_id, cname, pname, f, frate) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = cname, \
|
|
.parent_name = pname, \
|
|
.flags = f, \
|
|
.fixed_rate = frate, \
|
|
}
|
|
|
|
/*
|
|
* struct samsung_fixed_factor_clock: information about fixed-factor clock
|
|
* @id: platform specific id of the clock.
|
|
* @name: name of this fixed-factor clock.
|
|
* @parent_name: parent clock name.
|
|
* @mult: fixed multiplication factor.
|
|
* @div: fixed division factor.
|
|
* @flags: optional fixed-factor clock flags.
|
|
*/
|
|
struct samsung_fixed_factor_clock {
|
|
unsigned int id;
|
|
char *name;
|
|
const char *parent_name;
|
|
unsigned long mult;
|
|
unsigned long div;
|
|
unsigned long flags;
|
|
};
|
|
|
|
#define FFACTOR(_id, cname, pname, m, d, f) \
|
|
{ \
|
|
.id = _id, \
|
|
.name = cname, \
|
|
.parent_name = pname, \
|
|
.mult = m, \
|
|
.div = d, \
|
|
.flags = f, \
|
|
}
|
|
|
|
/**
|
|
* struct samsung_mux_clock: information about mux clock
|
|
* @id: platform specific id of the clock.
|
|
* @dev_name: name of the device to which this clock belongs.
|
|
* @name: name of this mux clock.
|
|
* @parent_names: array of pointer to parent clock names.
|
|
* @num_parents: number of parents listed in @parent_names.
|
|
* @flags: optional flags for basic clock.
|
|
* @offset: offset of the register for configuring the mux.
|
|
* @shift: starting bit location of the mux control bit-field in @reg.
|
|
* @width: width of the mux control bit-field in @reg.
|
|
* @mux_flags: flags for mux-type clock.
|
|
* @alias: optional clock alias name to be assigned to this clock.
|
|
*/
|
|
struct samsung_mux_clock {
|
|
unsigned int id;
|
|
const char *dev_name;
|
|
const char *name;
|
|
const char **parent_names;
|
|
u8 num_parents;
|
|
unsigned long flags;
|
|
unsigned long offset;
|
|
u8 shift;
|
|
u8 width;
|
|
u8 mux_flags;
|
|
const char *alias;
|
|
};
|
|
|
|
#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \
|
|
{ \
|
|
.id = _id, \
|
|
.dev_name = dname, \
|
|
.name = cname, \
|
|
.parent_names = pnames, \
|
|
.num_parents = ARRAY_SIZE(pnames), \
|
|
.flags = (f) | CLK_SET_RATE_NO_REPARENT, \
|
|
.offset = o, \
|
|
.shift = s, \
|
|
.width = w, \
|
|
.mux_flags = mf, \
|
|
.alias = a, \
|
|
}
|
|
|
|
#define MUX(_id, cname, pnames, o, s, w) \
|
|
__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
|
|
|
|
#define MUX_A(_id, cname, pnames, o, s, w, a) \
|
|
__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
|
|
|
|
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
|
|
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
|
|
|
|
#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a) \
|
|
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a)
|
|
|
|
/**
|
|
* @id: platform specific id of the clock.
|
|
* struct samsung_div_clock: information about div clock
|
|
* @dev_name: name of the device to which this clock belongs.
|
|
* @name: name of this div clock.
|
|
* @parent_name: name of the parent clock.
|
|
* @flags: optional flags for basic clock.
|
|
* @offset: offset of the register for configuring the div.
|
|
* @shift: starting bit location of the div control bit-field in @reg.
|
|
* @div_flags: flags for div-type clock.
|
|
* @alias: optional clock alias name to be assigned to this clock.
|
|
*/
|
|
struct samsung_div_clock {
|
|
unsigned int id;
|
|
const char *dev_name;
|
|
const char *name;
|
|
const char *parent_name;
|
|
unsigned long flags;
|
|
unsigned long offset;
|
|
u8 shift;
|
|
u8 width;
|
|
u8 div_flags;
|
|
const char *alias;
|
|
struct clk_div_table *table;
|
|
};
|
|
|
|
#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t) \
|
|
{ \
|
|
.id = _id, \
|
|
.dev_name = dname, \
|
|
.name = cname, \
|
|
.parent_name = pname, \
|
|
.flags = f, \
|
|
.offset = o, \
|
|
.shift = s, \
|
|
.width = w, \
|
|
.div_flags = df, \
|
|
.alias = a, \
|
|
.table = t, \
|
|
}
|
|
|
|
#define DIV(_id, cname, pname, o, s, w) \
|
|
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
|
|
|
|
#define DIV_A(_id, cname, pname, o, s, w, a) \
|
|
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
|
|
|
|
#define DIV_F(_id, cname, pname, o, s, w, f, df) \
|
|
__DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
|
|
|
|
#define DIV_T(_id, cname, pname, o, s, w, t) \
|
|
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
|
|
|
|
/**
|
|
* struct samsung_gate_clock: information about gate clock
|
|
* @id: platform specific id of the clock.
|
|
* @dev_name: name of the device to which this clock belongs.
|
|
* @name: name of this gate clock.
|
|
* @parent_name: name of the parent clock.
|
|
* @flags: optional flags for basic clock.
|
|
* @offset: offset of the register for configuring the gate.
|
|
* @bit_idx: bit index of the gate control bit-field in @reg.
|
|
* @gate_flags: flags for gate-type clock.
|
|
* @alias: optional clock alias name to be assigned to this clock.
|
|
*/
|
|
struct samsung_gate_clock {
|
|
unsigned int id;
|
|
const char *dev_name;
|
|
const char *name;
|
|
const char *parent_name;
|
|
unsigned long flags;
|
|
unsigned long offset;
|
|
u8 bit_idx;
|
|
u8 gate_flags;
|
|
const char *alias;
|
|
};
|
|
|
|
#define __GATE(_id, dname, cname, pname, o, b, f, gf, a) \
|
|
{ \
|
|
.id = _id, \
|
|
.dev_name = dname, \
|
|
.name = cname, \
|
|
.parent_name = pname, \
|
|
.flags = f, \
|
|
.offset = o, \
|
|
.bit_idx = b, \
|
|
.gate_flags = gf, \
|
|
.alias = a, \
|
|
}
|
|
|
|
#define GATE(_id, cname, pname, o, b, f, gf) \
|
|
__GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
|
|
|
|
#define GATE_A(_id, cname, pname, o, b, f, gf, a) \
|
|
__GATE(_id, NULL, cname, pname, o, b, f, gf, a)
|
|
|
|
#define GATE_D(_id, dname, cname, pname, o, b, f, gf) \
|
|
__GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
|
|
|
|
#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \
|
|
__GATE(_id, dname, cname, pname, o, b, f, gf, a)
|
|
|
|
#define PNAME(x) static const char *x[] __initdata
|
|
|
|
/**
|
|
* struct samsung_clk_reg_dump: register dump of clock controller registers.
|
|
* @offset: clock register offset from the controller base address.
|
|
* @value: the value to be register at offset.
|
|
*/
|
|
struct samsung_clk_reg_dump {
|
|
u32 offset;
|
|
u32 value;
|
|
};
|
|
|
|
/**
|
|
* struct samsung_pll_clock: information about pll clock
|
|
* @id: platform specific id of the clock.
|
|
* @dev_name: name of the device to which this clock belongs.
|
|
* @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.
|
|
* @lock_offset: offset of the register for locking the PLL.
|
|
* @type: Type of PLL to be registered.
|
|
* @alias: optional clock alias name to be assigned to this clock.
|
|
*/
|
|
struct samsung_pll_clock {
|
|
unsigned int id;
|
|
const char *dev_name;
|
|
const char *name;
|
|
const char *parent_name;
|
|
unsigned long flags;
|
|
int con_offset;
|
|
int lock_offset;
|
|
enum samsung_pll_type type;
|
|
const struct samsung_pll_rate_table *rate_table;
|
|
const char *alias;
|
|
};
|
|
|
|
#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \
|
|
_rtable, _alias) \
|
|
{ \
|
|
.id = _id, \
|
|
.type = _typ, \
|
|
.dev_name = _dname, \
|
|
.name = _name, \
|
|
.parent_name = _pname, \
|
|
.flags = CLK_GET_RATE_NOCACHE, \
|
|
.con_offset = _con, \
|
|
.lock_offset = _lock, \
|
|
.rate_table = _rtable, \
|
|
.alias = _alias, \
|
|
}
|
|
|
|
#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \
|
|
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
|
|
_lock, _con, _rtable, _name)
|
|
|
|
#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
|
|
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
|
|
_lock, _con, _rtable, _alias)
|
|
|
|
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
|
|
unsigned long nr_clks, unsigned long *rdump,
|
|
unsigned long nr_rdump, unsigned long *soc_rdump,
|
|
unsigned long nr_soc_rdump);
|
|
extern void __init samsung_clk_of_register_fixed_ext(
|
|
struct samsung_fixed_rate_clock *fixed_rate_clk,
|
|
unsigned int nr_fixed_rate_clk,
|
|
struct of_device_id *clk_matches);
|
|
|
|
extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id);
|
|
|
|
extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
|
|
unsigned int nr_clk);
|
|
extern void __init samsung_clk_register_fixed_rate(
|
|
struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
|
|
extern void __init samsung_clk_register_fixed_factor(
|
|
struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
|
|
extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
|
|
unsigned int nr_clk);
|
|
extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
|
|
unsigned int nr_clk);
|
|
extern void __init samsung_clk_register_gate(
|
|
struct samsung_gate_clock *clk_list, unsigned int nr_clk);
|
|
extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
|
|
unsigned int nr_clk, void __iomem *base);
|
|
|
|
extern unsigned long _get_rate(const char *clk_name);
|
|
|
|
#endif /* __SAMSUNG_CLK_H */
|