mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
We have two changes to the core framework this time around. The first being a
large change that introduces runtime PM support to the clk framework. Now we properly call runtime PM operations on the device providing a clk when the clk is in use. This helps on SoCs where the clks provided by a device need something to be powered on before using the clks, like power domains or regulators. It also helps power those things down when clks aren't in use. The other core change is a devm API addition for clk providers so we can get rid of a bunch of clk driver remove functions that are just doing of_clk_del_provider(). Outside of the core, we have the usual addition of clk drivers and smattering of non-critical fixes to existing drivers. The biggest diff is support for Mediatek MT2712 and MT7622 SoCs, but those patches really just add a bunch of data. By the way, we're trying something new here where we build the tree up with topic branches. We plan to work this into our workflow so that we don't step on each other's toes, and so the fixes branch can be merged on an as-needed basis. Core: - Runtime PM support for clk providers - devm API for of_clk_add_hw_provider() New Drivers: - Mediatek MT2712 and MT7622 - Renesas R-Car V3M SoC Updates: - Runtime PM support for Samsung exynos5433/exynos4412 providers - Removal of clkdev aliases on Samsung SoCs - Convert clk-gpio to use gpio descriptors - Various driver cleanups to match kernel coding style - Amlogic Video Processing Unit VPU and VAPB clks - Sigma-delta modulation for Allwinner audio PLLs - Allwinner A83t Display clks - Support for the second display unit clock on Renesas RZ/G1E - Suspend/resume support for Renesas R-Car Gen3 CPG/MSSR - New clock ids for Rockchip rk3188 and rk3368 SoCs - Various 'const' markings on clk_ops structures - RPM clk support on Qualcomm MSM8996/MSM8660 SoCs -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJaD3qRAAoJEK0CiJfG5JUlOLgQAKWekgG/IYgcPzPWDYfg8Hwr sVVUK7+q7TVfbHsbYVikJuUaxutKZ0onnrYmOalTTyyxqL2E1/rYScnxdYHfcwX8 cyfHebRHsbh/Xg45ktwjzBkO49nwuppkpXd/V80GSBUZ+lsIVl5DUrrFAZdRUEdr CEsAsF9tEWIl+0gqXYNuiKBV7QAYv5BUPrbJQf0PwL6jX0OAhLv+ukfN8BdmYsOb rdoqhdgmyHkTuIMqsC/H2yP59aAKBse7wxIYebDiTdbPWfTkC9q927fTs4A02F6L sHfLvCpfuB4rOjXy6LSd1gMGWIcjotZai+idHBqtNLLVz6exF1QpUCp+pZjEULbA /Sx9lk8A3cYoa8pTu1NrrZbZX17iHkFswqMF3T20nhUN9+Ti597ZEbRcWDcoEZtw v2NznOTJ7Mm2SrNHOvDklstggNIGcwiAEePGMo7rJNEQZChpDjQj/gJWKzn0UwL4 zfk+0EzoejPdvZ5FJUfmlr8Tqk53uw+y7/0xQ6gf8lDviTrzzoeXtJUyumGBiuGx RxFywf8n02oLYRJm5hu+0NkC+/bX0Lxg/kwiR6FLBFbBFgkWyp7FGcxhlm6ZiBfe 0KkPciWslNavn5KhljIkZDbXymbvhhSr9uBEFsyeJueA5q7sSghWloL8Ag1cac3W e6swD1ngXtM/t5gjOLhR =hC7z -----END PGP SIGNATURE----- Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux Pull clk updates from Stephen Boyd: "We have two changes to the core framework this time around. The first being a large change that introduces runtime PM support to the clk framework. Now we properly call runtime PM operations on the device providing a clk when the clk is in use. This helps on SoCs where the clks provided by a device need something to be powered on before using the clks, like power domains or regulators. It also helps power those things down when clks aren't in use. The other core change is a devm API addition for clk providers so we can get rid of a bunch of clk driver remove functions that are just doing of_clk_del_provider(). Outside of the core, we have the usual addition of clk drivers and smattering of non-critical fixes to existing drivers. The biggest diff is support for Mediatek MT2712 and MT7622 SoCs, but those patches really just add a bunch of data. By the way, we're trying something new here where we build the tree up with topic branches. We plan to work this into our workflow so that we don't step on each other's toes, and so the fixes branch can be merged on an as-needed basis. Summary: Core: - runtime PM support for clk providers - devm API for of_clk_add_hw_provider() New Drivers: - Mediatek MT2712 and MT7622 - Renesas R-Car V3M SoC Updates: - runtime PM support for Samsung exynos5433/exynos4412 providers - removal of clkdev aliases on Samsung SoCs - convert clk-gpio to use gpio descriptors - various driver cleanups to match kernel coding style - Amlogic Video Processing Unit VPU and VAPB clks - sigma-delta modulation for Allwinner audio PLLs - Allwinner A83t Display clks - support for the second display unit clock on Renesas RZ/G1E - suspend/resume support for Renesas R-Car Gen3 CPG/MSSR - new clock ids for Rockchip rk3188 and rk3368 SoCs - various 'const' markings on clk_ops structures - RPM clk support on Qualcomm MSM8996/MSM8660 SoCs" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (137 commits) clk: stm32h7: fix test of clock config clk: pxa: fix building on older compilers clk: sunxi-ng: a83t: Fix i2c buses bits clk: ti: dra7-atl-clock: fix child-node lookups clk: qcom: common: fix legacy board-clock registration clk: uniphier: fix DAPLL2 clock rate of Pro5 clk: uniphier: fix parent of miodmac clock data clk: hi3798cv200: correct parent mux clock for 'clk_sdio0_ciu' clk: hisilicon: Delete an error message for a failed memory allocation in hisi_register_clkgate_sep() clk: hi3660: fix incorrect uart3 clock freqency clk: kona-setup: Delete error messages for failed memory allocations ARC: clk: fix spelling mistake: "configurarion" -> "configuration" clk: cdce925: remove redundant check for non-null parent_name clk: versatile: Improve sizeof() usage clk: versatile: Delete error messages for failed memory allocations clk: ux500: Improve sizeof() usage clk: ux500: Delete error messages for failed memory allocations clk: spear: Delete error messages for failed memory allocations clk: ti: Delete error messages for failed memory allocations clk: mmp: Adjust checks for NULL pointers ...
This commit is contained in:
commit
fc35c1966e
185 changed files with 7230 additions and 979 deletions
|
|
@ -14,14 +14,20 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <soc/at91/atmel-sfr.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define UTMI_FIXED_MUL 40
|
||||
/*
|
||||
* The purpose of this clock is to generate a 480 MHz signal. A different
|
||||
* rate can't be configured.
|
||||
*/
|
||||
#define UTMI_RATE 480000000
|
||||
|
||||
struct clk_utmi {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
struct regmap *regmap_pmc;
|
||||
struct regmap *regmap_sfr;
|
||||
};
|
||||
|
||||
#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
|
||||
|
|
@ -37,13 +43,54 @@ static inline bool clk_utmi_ready(struct regmap *regmap)
|
|||
|
||||
static int clk_utmi_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw *hw_parent;
|
||||
struct clk_utmi *utmi = to_clk_utmi(hw);
|
||||
unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
|
||||
AT91_PMC_BIASEN;
|
||||
unsigned int utmi_ref_clk_freq;
|
||||
unsigned long parent_rate;
|
||||
|
||||
regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr);
|
||||
/*
|
||||
* If mainck rate is different from 12 MHz, we have to configure the
|
||||
* FREQ field of the SFR_UTMICKTRIM register to generate properly
|
||||
* the utmi clock.
|
||||
*/
|
||||
hw_parent = clk_hw_get_parent(hw);
|
||||
parent_rate = clk_hw_get_rate(hw_parent);
|
||||
|
||||
while (!clk_utmi_ready(utmi->regmap))
|
||||
switch (parent_rate) {
|
||||
case 12000000:
|
||||
utmi_ref_clk_freq = 0;
|
||||
break;
|
||||
case 16000000:
|
||||
utmi_ref_clk_freq = 1;
|
||||
break;
|
||||
case 24000000:
|
||||
utmi_ref_clk_freq = 2;
|
||||
break;
|
||||
/*
|
||||
* Not supported on SAMA5D2 but it's not an issue since MAINCK
|
||||
* maximum value is 24 MHz.
|
||||
*/
|
||||
case 48000000:
|
||||
utmi_ref_clk_freq = 3;
|
||||
break;
|
||||
default:
|
||||
pr_err("UTMICK: unsupported mainck rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (utmi->regmap_sfr) {
|
||||
regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
|
||||
AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
|
||||
} else if (utmi_ref_clk_freq) {
|
||||
pr_err("UTMICK: sfr node required\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
|
||||
|
||||
while (!clk_utmi_ready(utmi->regmap_pmc))
|
||||
cpu_relax();
|
||||
|
||||
return 0;
|
||||
|
|
@ -53,21 +100,22 @@ static int clk_utmi_is_prepared(struct clk_hw *hw)
|
|||
{
|
||||
struct clk_utmi *utmi = to_clk_utmi(hw);
|
||||
|
||||
return clk_utmi_ready(utmi->regmap);
|
||||
return clk_utmi_ready(utmi->regmap_pmc);
|
||||
}
|
||||
|
||||
static void clk_utmi_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_utmi *utmi = to_clk_utmi(hw);
|
||||
|
||||
regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0);
|
||||
regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
|
||||
AT91_PMC_UPLLEN, 0);
|
||||
}
|
||||
|
||||
static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
/* UTMI clk is a fixed clk multiplier */
|
||||
return parent_rate * UTMI_FIXED_MUL;
|
||||
/* UTMI clk rate is fixed. */
|
||||
return UTMI_RATE;
|
||||
}
|
||||
|
||||
static const struct clk_ops utmi_ops = {
|
||||
|
|
@ -78,7 +126,7 @@ static const struct clk_ops utmi_ops = {
|
|||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
at91_clk_register_utmi(struct regmap *regmap,
|
||||
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
|
||||
const char *name, const char *parent_name)
|
||||
{
|
||||
struct clk_utmi *utmi;
|
||||
|
|
@ -97,7 +145,8 @@ at91_clk_register_utmi(struct regmap *regmap,
|
|||
init.flags = CLK_SET_RATE_GATE;
|
||||
|
||||
utmi->hw.init = &init;
|
||||
utmi->regmap = regmap;
|
||||
utmi->regmap_pmc = regmap_pmc;
|
||||
utmi->regmap_sfr = regmap_sfr;
|
||||
|
||||
hw = &utmi->hw;
|
||||
ret = clk_hw_register(NULL, &utmi->hw);
|
||||
|
|
@ -114,17 +163,35 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
|
|||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
struct regmap *regmap_pmc, *regmap_sfr;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap_pmc))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, name, parent_name);
|
||||
/*
|
||||
* If the device supports different mainck rates, this value has to be
|
||||
* set in the UTMI Clock Trimming register.
|
||||
* - 9x5: mainck supports several rates but it is indicated that a
|
||||
* 12 MHz is needed in case of USB.
|
||||
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
|
||||
* the FREQ field of the UTMI Clock Trimming register is mandatory.
|
||||
* - sama5d4: mainck is at 12 MHz.
|
||||
*
|
||||
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
|
||||
*/
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
|
||||
if (IS_ERR(regmap_sfr)) {
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
regmap_sfr = NULL;
|
||||
}
|
||||
|
||||
hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -579,18 +579,13 @@ static u32 *parent_process(const char *clocks[],
|
|||
*/
|
||||
parent_names = kmalloc_array(parent_count, sizeof(*parent_names),
|
||||
GFP_KERNEL);
|
||||
if (!parent_names) {
|
||||
pr_err("%s: error allocating %u parent names\n", __func__,
|
||||
parent_count);
|
||||
if (!parent_names)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* There is at least one parent, so allocate a selector array */
|
||||
parent_sel = kmalloc_array(parent_count, sizeof(*parent_sel),
|
||||
GFP_KERNEL);
|
||||
if (!parent_sel) {
|
||||
pr_err("%s: error allocating %u parent selectors\n", __func__,
|
||||
parent_count);
|
||||
kfree(parent_names);
|
||||
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ static int cdce925_probe(struct i2c_client *client,
|
|||
init.ops = &cdce925_pll_ops;
|
||||
init.flags = 0;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
init.num_parents = 1;
|
||||
|
||||
/* Register PLL clocks */
|
||||
for (i = 0; i < data->chip_info->num_plls; ++i) {
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
@ -95,14 +93,12 @@ const struct clk_ops clk_gpio_mux_ops = {
|
|||
EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
|
||||
|
||||
static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags,
|
||||
const struct clk_ops *clk_gpio_ops)
|
||||
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
|
||||
unsigned long flags, const struct clk_ops *clk_gpio_ops)
|
||||
{
|
||||
struct clk_gpio *clk_gpio;
|
||||
struct clk_hw *hw;
|
||||
struct clk_init_data init = {};
|
||||
unsigned long gpio_flags;
|
||||
int err;
|
||||
|
||||
if (dev)
|
||||
|
|
@ -113,32 +109,13 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
|
|||
if (!clk_gpio)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (active_low)
|
||||
gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
|
||||
else
|
||||
gpio_flags = GPIOF_OUT_INIT_LOW;
|
||||
|
||||
if (dev)
|
||||
err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
|
||||
else
|
||||
err = gpio_request_one(gpio, gpio_flags, name);
|
||||
if (err) {
|
||||
if (err != -EPROBE_DEFER)
|
||||
pr_err("%s: %s: Error requesting clock control gpio %u\n",
|
||||
__func__, name, gpio);
|
||||
if (!dev)
|
||||
kfree(clk_gpio);
|
||||
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = clk_gpio_ops;
|
||||
init.flags = flags | CLK_IS_BASIC;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
|
||||
clk_gpio->gpiod = gpio_to_desc(gpio);
|
||||
clk_gpio->gpiod = gpiod;
|
||||
clk_gpio->hw.init = &init;
|
||||
|
||||
hw = &clk_gpio->hw;
|
||||
|
|
@ -151,7 +128,6 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
|
|||
return hw;
|
||||
|
||||
if (!dev) {
|
||||
gpiod_put(clk_gpio->gpiod);
|
||||
kfree(clk_gpio);
|
||||
}
|
||||
|
||||
|
|
@ -164,29 +140,27 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
|
|||
* @dev: device that is registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of this clock's parent
|
||||
* @gpio: gpio number to gate this clock
|
||||
* @active_low: true if gpio should be set to 0 to enable clock
|
||||
* @gpiod: gpio descriptor to gate this clock
|
||||
* @flags: clock flags
|
||||
*/
|
||||
struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned gpio, bool active_low,
|
||||
const char *parent_name, struct gpio_desc *gpiod,
|
||||
unsigned long flags)
|
||||
{
|
||||
return clk_register_gpio(dev, name,
|
||||
(parent_name ? &parent_name : NULL),
|
||||
(parent_name ? 1 : 0), gpio, active_low, flags,
|
||||
(parent_name ? 1 : 0), gpiod, flags,
|
||||
&clk_gpio_gate_ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
|
||||
|
||||
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned gpio, bool active_low,
|
||||
const char *parent_name, struct gpio_desc *gpiod,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low,
|
||||
flags);
|
||||
hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
|
|
@ -199,13 +173,12 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
|
|||
* @name: name of this clock
|
||||
* @parent_names: names of this clock's parents
|
||||
* @num_parents: number of parents listed in @parent_names
|
||||
* @gpio: gpio number to gate this clock
|
||||
* @active_low: true if gpio should be set to 0 to enable clock
|
||||
* @gpiod: gpio descriptor to gate this clock
|
||||
* @flags: clock flags
|
||||
*/
|
||||
struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags)
|
||||
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (num_parents != 2) {
|
||||
pr_err("mux-clock %s must have 2 parents\n", name);
|
||||
|
|
@ -213,18 +186,18 @@ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
|
|||
}
|
||||
|
||||
return clk_register_gpio(dev, name, parent_names, num_parents,
|
||||
gpio, active_low, flags, &clk_gpio_mux_ops);
|
||||
gpiod, flags, &clk_gpio_mux_ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux);
|
||||
|
||||
struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents, unsigned gpio,
|
||||
bool active_low, unsigned long flags)
|
||||
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents,
|
||||
gpio, active_low, flags);
|
||||
gpiod, flags);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
|
|
@ -236,10 +209,10 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
|
|||
struct device_node *node = pdev->dev.of_node;
|
||||
const char **parent_names, *gpio_name;
|
||||
unsigned int num_parents;
|
||||
int gpio;
|
||||
enum of_gpio_flags of_flags;
|
||||
struct gpio_desc *gpiod;
|
||||
struct clk *clk;
|
||||
bool active_low, is_mux;
|
||||
bool is_mux;
|
||||
int ret;
|
||||
|
||||
num_parents = of_clk_get_parent_count(node);
|
||||
if (num_parents) {
|
||||
|
|
@ -255,28 +228,27 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
|
|||
|
||||
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
|
||||
|
||||
gpio_name = is_mux ? "select-gpios" : "enable-gpios";
|
||||
gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags);
|
||||
if (gpio < 0) {
|
||||
if (gpio == -EPROBE_DEFER)
|
||||
gpio_name = is_mux ? "select" : "enable";
|
||||
gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpiod)) {
|
||||
ret = PTR_ERR(gpiod);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
pr_debug("%s: %s: GPIOs not yet available, retry later\n",
|
||||
node->name, __func__);
|
||||
else
|
||||
pr_err("%s: %s: Can't get '%s' DT property\n",
|
||||
pr_err("%s: %s: Can't get '%s' named GPIO property\n",
|
||||
node->name, __func__,
|
||||
gpio_name);
|
||||
return gpio;
|
||||
return ret;
|
||||
}
|
||||
|
||||
active_low = of_flags & OF_GPIO_ACTIVE_LOW;
|
||||
|
||||
if (is_mux)
|
||||
clk = clk_register_gpio_mux(&pdev->dev, node->name,
|
||||
parent_names, num_parents, gpio, active_low, 0);
|
||||
parent_names, num_parents, gpiod, 0);
|
||||
else
|
||||
clk = clk_register_gpio_gate(&pdev->dev, node->name,
|
||||
parent_names ? parent_names[0] : NULL, gpio,
|
||||
active_low, 0);
|
||||
parent_names ? parent_names[0] : NULL, gpiod,
|
||||
0);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ static inline void hsdk_pll_set_cfg(struct hsdk_pll_clk *clk,
|
|||
val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT;
|
||||
val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT;
|
||||
|
||||
dev_dbg(clk->dev, "write configurarion: %#x\n", val);
|
||||
dev_dbg(clk->dev, "write configuration: %#x\n", val);
|
||||
|
||||
hsdk_pll_write(clk, CGU_PLL_CTRL, val);
|
||||
}
|
||||
|
|
@ -169,7 +169,7 @@ static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw,
|
|||
|
||||
val = hsdk_pll_read(clk, CGU_PLL_CTRL);
|
||||
|
||||
dev_dbg(clk->dev, "current configurarion: %#x\n", val);
|
||||
dev_dbg(clk->dev, "current configuration: %#x\n", val);
|
||||
|
||||
/* Check if PLL is disabled */
|
||||
if (val & CGU_PLL_CTRL_PD)
|
||||
|
|
|
|||
|
|
@ -134,11 +134,9 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
|||
}
|
||||
|
||||
/* allocate the mux */
|
||||
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
|
||||
if (!mux) {
|
||||
pr_err("%s: could not allocate mux clk\n", __func__);
|
||||
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
if (clk_mux_flags & CLK_MUX_READ_ONLY)
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg,
|
|||
mux_ops = div_ops = gate_ops = NULL;
|
||||
mux_hw = div_hw = gate_hw = NULL;
|
||||
|
||||
if (gcfg->mux && gcfg->mux) {
|
||||
if (gcfg->mux && cfg->mux) {
|
||||
mux = _get_cmux(base + cfg->mux->offset,
|
||||
cfg->mux->shift,
|
||||
cfg->mux->width,
|
||||
|
|
@ -410,7 +410,7 @@ static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg,
|
|||
}
|
||||
}
|
||||
|
||||
if (gcfg->gate && gcfg->gate) {
|
||||
if (gcfg->gate && cfg->gate) {
|
||||
gate = _get_cgate(base + cfg->gate->offset,
|
||||
cfg->gate->bit_idx,
|
||||
gcfg->gate->flags, lock);
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ static const struct clk_ops twl6040_pdmclk_ops = {
|
|||
.recalc_rate = twl6040_pdmclk_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_init_data twl6040_pdmclk_init = {
|
||||
static const struct clk_init_data twl6040_pdmclk_init = {
|
||||
.name = "pdmclk",
|
||||
.ops = &twl6040_pdmclk_ops,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
|
|
|
|||
|
|
@ -229,15 +229,15 @@
|
|||
#define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK (0x01E0)
|
||||
#define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK (0x001E)
|
||||
#define U300_SYSCON_S0CCR_CLOCK_ENABLE (0x0001)
|
||||
#define U300_SYSCON_S0CCR_SEL_MCLK (0x8<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6<<1)
|
||||
#define U300_SYSCON_S0CCR_SEL_MCLK (0x8 << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0 << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2 << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4 << 1)
|
||||
#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6 << 1)
|
||||
/* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */
|
||||
#define U300_SYSCON_S1CCR (0x124)
|
||||
#define U300_SYSCON_S1CCR_FIELD_MASK (0x43FF)
|
||||
|
|
@ -247,16 +247,16 @@
|
|||
#define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK (0x01E0)
|
||||
#define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK (0x001E)
|
||||
#define U300_SYSCON_S1CCR_CLOCK_ENABLE (0x0001)
|
||||
#define U300_SYSCON_S1CCR_SEL_MCLK (0x8<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4<<1)
|
||||
#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6<<1)
|
||||
/* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */
|
||||
#define U300_SYSCON_S1CCR_SEL_MCLK (0x8 << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0 << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2 << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4 << 1)
|
||||
#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6 << 1)
|
||||
/* SYS_2_CLK_CONTROL third clock control 16 bit (R/W) */
|
||||
#define U300_SYSCON_S2CCR (0x128)
|
||||
#define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF)
|
||||
#define U300_SYSCON_S2CCR_CLK_STEAL (0x8000)
|
||||
|
|
@ -266,15 +266,15 @@
|
|||
#define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK (0x01E0)
|
||||
#define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK (0x001E)
|
||||
#define U300_SYSCON_S2CCR_CLOCK_ENABLE (0x0001)
|
||||
#define U300_SYSCON_S2CCR_SEL_MCLK (0x8<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6<<1)
|
||||
#define U300_SYSCON_S2CCR_SEL_MCLK (0x8 << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0 << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2 << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4 << 1)
|
||||
#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6 << 1)
|
||||
/* SC_PLL_IRQ_CONTROL 16bit (R/W) */
|
||||
#define U300_SYSCON_PICR (0x0130)
|
||||
#define U300_SYSCON_PICR_MASK (0x00FF)
|
||||
|
|
@ -378,7 +378,7 @@
|
|||
* +- ISP Image Signal Processor (U335 only)
|
||||
* +- CDS (U335 only)
|
||||
* +- DMA Direct Memory Access Controller
|
||||
* +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
|
||||
* +- AAIF APP/ACC Interface (Mobile Scalable Link, MSL)
|
||||
* +- APEX
|
||||
* +- VIDEO_ENC AVE2/3 Video Encoder
|
||||
* +- XGAM Graphics Accelerator Controller
|
||||
|
|
@ -568,14 +568,14 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
|
|||
struct clk_syscon *sclk = to_syscon(hw);
|
||||
u16 perf = syscon_get_perf();
|
||||
|
||||
switch(sclk->clk_val) {
|
||||
switch (sclk->clk_val) {
|
||||
case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN:
|
||||
case U300_SYSCON_SBCER_I2C0_CLK_EN:
|
||||
case U300_SYSCON_SBCER_I2C1_CLK_EN:
|
||||
case U300_SYSCON_SBCER_MMC_CLK_EN:
|
||||
case U300_SYSCON_SBCER_SPI_CLK_EN:
|
||||
/* The FAST clocks have one progression */
|
||||
switch(perf) {
|
||||
switch (perf) {
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
|
||||
return 13000000;
|
||||
|
|
@ -586,7 +586,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
|
|||
case U300_SYSCON_SBCER_NANDIF_CLK_EN:
|
||||
case U300_SYSCON_SBCER_XGAM_CLK_EN:
|
||||
/* AMBA interconnect peripherals */
|
||||
switch(perf) {
|
||||
switch (perf) {
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
|
||||
return 6500000;
|
||||
|
|
@ -598,7 +598,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
|
|||
case U300_SYSCON_SBCER_SEMI_CLK_EN:
|
||||
case U300_SYSCON_SBCER_EMIF_CLK_EN:
|
||||
/* EMIF speeds */
|
||||
switch(perf) {
|
||||
switch (perf) {
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
|
||||
return 13000000;
|
||||
|
|
@ -609,7 +609,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
|
|||
}
|
||||
case U300_SYSCON_SBCER_CPU_CLK_EN:
|
||||
/* And the fast CPU clock */
|
||||
switch(perf) {
|
||||
switch (perf) {
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
|
||||
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
|
||||
return 13000000;
|
||||
|
|
@ -702,12 +702,10 @@ syscon_clk_register(struct device *dev, const char *name,
|
|||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL);
|
||||
if (!sclk) {
|
||||
pr_err("could not allocate syscon clock %s\n",
|
||||
name);
|
||||
sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
|
||||
if (!sclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &syscon_clk_ops;
|
||||
init.flags = flags;
|
||||
|
|
@ -1123,12 +1121,10 @@ mclk_clk_register(struct device *dev, const char *name,
|
|||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL);
|
||||
if (!mclk) {
|
||||
pr_err("could not allocate MMC/SD clock %s\n",
|
||||
name);
|
||||
mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
|
||||
if (!mclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = "mclk";
|
||||
init.ops = &mclk_ops;
|
||||
init.flags = 0;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static const struct clk_ops wm831x_xtal_ops = {
|
|||
.recalc_rate = wm831x_xtal_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_init_data wm831x_xtal_init = {
|
||||
static const struct clk_init_data wm831x_xtal_init = {
|
||||
.name = "xtal",
|
||||
.ops = &wm831x_xtal_ops,
|
||||
};
|
||||
|
|
@ -225,7 +225,7 @@ static const struct clk_ops wm831x_fll_ops = {
|
|||
.get_parent = wm831x_fll_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_init_data wm831x_fll_init = {
|
||||
static const struct clk_init_data wm831x_fll_init = {
|
||||
.name = "fll",
|
||||
.ops = &wm831x_fll_ops,
|
||||
.parent_names = wm831x_fll_parents,
|
||||
|
|
@ -338,7 +338,7 @@ static const struct clk_ops wm831x_clkout_ops = {
|
|||
.set_parent = wm831x_clkout_set_parent,
|
||||
};
|
||||
|
||||
static struct clk_init_data wm831x_clkout_init = {
|
||||
static const struct clk_init_data wm831x_clkout_init = {
|
||||
.name = "clkout",
|
||||
.ops = &wm831x_clkout_ops,
|
||||
.parent_names = wm831x_clkout_parents,
|
||||
|
|
|
|||
|
|
@ -146,10 +146,8 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
|
|||
|
||||
/* allocate the APM clock structure */
|
||||
apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
|
||||
if (!apmclk) {
|
||||
pr_err("%s: could not allocate APM clk\n", __func__);
|
||||
if (!apmclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &xgene_clk_pll_ops;
|
||||
|
|
@ -191,7 +189,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty
|
|||
int version = xgene_pllclk_version(np);
|
||||
|
||||
reg = of_iomap(np, 0);
|
||||
if (reg == NULL) {
|
||||
if (!reg) {
|
||||
pr_err("Unable to map CSR register for %pOF\n", np);
|
||||
return;
|
||||
}
|
||||
|
|
@ -467,7 +465,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
|
|||
if (pclk->lock)
|
||||
spin_lock_irqsave(pclk->lock, flags);
|
||||
|
||||
if (pclk->param.csr_reg != NULL) {
|
||||
if (pclk->param.csr_reg) {
|
||||
pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
|
||||
/* First enable the clock */
|
||||
data = xgene_clk_read(pclk->param.csr_reg +
|
||||
|
|
@ -507,7 +505,7 @@ static void xgene_clk_disable(struct clk_hw *hw)
|
|||
if (pclk->lock)
|
||||
spin_lock_irqsave(pclk->lock, flags);
|
||||
|
||||
if (pclk->param.csr_reg != NULL) {
|
||||
if (pclk->param.csr_reg) {
|
||||
pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
|
||||
/* First put the CSR in reset */
|
||||
data = xgene_clk_read(pclk->param.csr_reg +
|
||||
|
|
@ -533,7 +531,7 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
|
|||
struct xgene_clk *pclk = to_xgene_clk(hw);
|
||||
u32 data = 0;
|
||||
|
||||
if (pclk->param.csr_reg != NULL) {
|
||||
if (pclk->param.csr_reg) {
|
||||
pr_debug("%s clock checking\n", clk_hw_get_name(hw));
|
||||
data = xgene_clk_read(pclk->param.csr_reg +
|
||||
pclk->param.reg_clk_offset);
|
||||
|
|
@ -542,7 +540,7 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
|
|||
"disabled");
|
||||
}
|
||||
|
||||
if (pclk->param.csr_reg == NULL)
|
||||
if (!pclk->param.csr_reg)
|
||||
return 1;
|
||||
return data & pclk->param.reg_clk_mask ? 1 : 0;
|
||||
}
|
||||
|
|
@ -650,10 +648,8 @@ static struct clk *xgene_register_clk(struct device *dev,
|
|||
|
||||
/* allocate the APM clock structure */
|
||||
apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
|
||||
if (!apmclk) {
|
||||
pr_err("%s: could not allocate APM clk\n", __func__);
|
||||
if (!apmclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &xgene_clk_ops;
|
||||
|
|
@ -709,7 +705,7 @@ static void __init xgene_devclk_init(struct device_node *np)
|
|||
break;
|
||||
}
|
||||
map_res = of_iomap(np, i);
|
||||
if (map_res == NULL) {
|
||||
if (!map_res) {
|
||||
pr_err("Unable to map resource %d for %pOF\n", i, np);
|
||||
goto err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ struct clk_core {
|
|||
const struct clk_ops *ops;
|
||||
struct clk_hw *hw;
|
||||
struct module *owner;
|
||||
struct device *dev;
|
||||
struct clk_core *parent;
|
||||
const char **parent_names;
|
||||
struct clk_core **parents;
|
||||
|
|
@ -87,6 +89,26 @@ struct clk {
|
|||
struct hlist_node clks_node;
|
||||
};
|
||||
|
||||
/*** runtime pm ***/
|
||||
static int clk_pm_runtime_get(struct clk_core *core)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!core->dev)
|
||||
return 0;
|
||||
|
||||
ret = pm_runtime_get_sync(core->dev);
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static void clk_pm_runtime_put(struct clk_core *core)
|
||||
{
|
||||
if (!core->dev)
|
||||
return;
|
||||
|
||||
pm_runtime_put_sync(core->dev);
|
||||
}
|
||||
|
||||
/*** locking ***/
|
||||
static void clk_prepare_lock(void)
|
||||
{
|
||||
|
|
@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags)
|
|||
|
||||
static bool clk_core_is_prepared(struct clk_core *core)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
/*
|
||||
* .is_prepared is optional for clocks that can prepare
|
||||
* fall back to software usage counter if it is missing
|
||||
|
|
@ -157,11 +181,18 @@ static bool clk_core_is_prepared(struct clk_core *core)
|
|||
if (!core->ops->is_prepared)
|
||||
return core->prepare_count;
|
||||
|
||||
return core->ops->is_prepared(core->hw);
|
||||
if (!clk_pm_runtime_get(core)) {
|
||||
ret = core->ops->is_prepared(core->hw);
|
||||
clk_pm_runtime_put(core);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool clk_core_is_enabled(struct clk_core *core)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
/*
|
||||
* .is_enabled is only mandatory for clocks that gate
|
||||
* fall back to software usage counter if .is_enabled is missing
|
||||
|
|
@ -169,7 +200,29 @@ static bool clk_core_is_enabled(struct clk_core *core)
|
|||
if (!core->ops->is_enabled)
|
||||
return core->enable_count;
|
||||
|
||||
return core->ops->is_enabled(core->hw);
|
||||
/*
|
||||
* Check if clock controller's device is runtime active before
|
||||
* calling .is_enabled callback. If not, assume that clock is
|
||||
* disabled, because we might be called from atomic context, from
|
||||
* which pm_runtime_get() is not allowed.
|
||||
* This function is called mainly from clk_disable_unused_subtree,
|
||||
* which ensures proper runtime pm activation of controller before
|
||||
* taking enable spinlock, but the below check is needed if one tries
|
||||
* to call it from other places.
|
||||
*/
|
||||
if (core->dev) {
|
||||
pm_runtime_get_noresume(core->dev);
|
||||
if (!pm_runtime_active(core->dev)) {
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = core->ops->is_enabled(core->hw);
|
||||
done:
|
||||
clk_pm_runtime_put(core);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*** helper functions ***/
|
||||
|
|
@ -489,6 +542,8 @@ static void clk_core_unprepare(struct clk_core *core)
|
|||
if (core->ops->unprepare)
|
||||
core->ops->unprepare(core->hw);
|
||||
|
||||
clk_pm_runtime_put(core);
|
||||
|
||||
trace_clk_unprepare_complete(core);
|
||||
clk_core_unprepare(core->parent);
|
||||
}
|
||||
|
|
@ -530,10 +585,14 @@ static int clk_core_prepare(struct clk_core *core)
|
|||
return 0;
|
||||
|
||||
if (core->prepare_count == 0) {
|
||||
ret = clk_core_prepare(core->parent);
|
||||
ret = clk_pm_runtime_get(core);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_core_prepare(core->parent);
|
||||
if (ret)
|
||||
goto runtime_put;
|
||||
|
||||
trace_clk_prepare(core);
|
||||
|
||||
if (core->ops->prepare)
|
||||
|
|
@ -541,15 +600,18 @@ static int clk_core_prepare(struct clk_core *core)
|
|||
|
||||
trace_clk_prepare_complete(core);
|
||||
|
||||
if (ret) {
|
||||
clk_core_unprepare(core->parent);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto unprepare;
|
||||
}
|
||||
|
||||
core->prepare_count++;
|
||||
|
||||
return 0;
|
||||
unprepare:
|
||||
clk_core_unprepare(core->parent);
|
||||
runtime_put:
|
||||
clk_pm_runtime_put(core);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clk_core_prepare_lock(struct clk_core *core)
|
||||
|
|
@ -745,6 +807,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
|
|||
if (core->flags & CLK_IGNORE_UNUSED)
|
||||
return;
|
||||
|
||||
if (clk_pm_runtime_get(core))
|
||||
return;
|
||||
|
||||
if (clk_core_is_prepared(core)) {
|
||||
trace_clk_unprepare(core);
|
||||
if (core->ops->unprepare_unused)
|
||||
|
|
@ -753,6 +818,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
|
|||
core->ops->unprepare(core->hw);
|
||||
trace_clk_unprepare_complete(core);
|
||||
}
|
||||
|
||||
clk_pm_runtime_put(core);
|
||||
}
|
||||
|
||||
static void clk_disable_unused_subtree(struct clk_core *core)
|
||||
|
|
@ -768,6 +835,9 @@ static void clk_disable_unused_subtree(struct clk_core *core)
|
|||
if (core->flags & CLK_OPS_PARENT_ENABLE)
|
||||
clk_core_prepare_enable(core->parent);
|
||||
|
||||
if (clk_pm_runtime_get(core))
|
||||
goto unprepare_out;
|
||||
|
||||
flags = clk_enable_lock();
|
||||
|
||||
if (core->enable_count)
|
||||
|
|
@ -792,6 +862,8 @@ static void clk_disable_unused_subtree(struct clk_core *core)
|
|||
|
||||
unlock_out:
|
||||
clk_enable_unlock(flags);
|
||||
clk_pm_runtime_put(core);
|
||||
unprepare_out:
|
||||
if (core->flags & CLK_OPS_PARENT_ENABLE)
|
||||
clk_core_disable_unprepare(core->parent);
|
||||
}
|
||||
|
|
@ -1038,9 +1110,13 @@ EXPORT_SYMBOL_GPL(clk_get_accuracy);
|
|||
static unsigned long clk_recalc(struct clk_core *core,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
if (core->ops->recalc_rate)
|
||||
return core->ops->recalc_rate(core->hw, parent_rate);
|
||||
return parent_rate;
|
||||
unsigned long rate = parent_rate;
|
||||
|
||||
if (core->ops->recalc_rate && !clk_pm_runtime_get(core)) {
|
||||
rate = core->ops->recalc_rate(core->hw, parent_rate);
|
||||
clk_pm_runtime_put(core);
|
||||
}
|
||||
return rate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1565,6 +1641,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
|
|||
{
|
||||
struct clk_core *top, *fail_clk;
|
||||
unsigned long rate = req_rate;
|
||||
int ret = 0;
|
||||
|
||||
if (!core)
|
||||
return 0;
|
||||
|
|
@ -1581,21 +1658,28 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
|
|||
if (!top)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_pm_runtime_get(core);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* notify that we are about to change rates */
|
||||
fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
|
||||
if (fail_clk) {
|
||||
pr_debug("%s: failed to set %s rate\n", __func__,
|
||||
fail_clk->name);
|
||||
clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* change the rates */
|
||||
clk_change_rate(top);
|
||||
|
||||
core->req_rate = req_rate;
|
||||
err:
|
||||
clk_pm_runtime_put(core);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1826,12 +1910,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
|||
p_rate = parent->rate;
|
||||
}
|
||||
|
||||
ret = clk_pm_runtime_get(core);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* propagate PRE_RATE_CHANGE notifications */
|
||||
ret = __clk_speculate_rates(core, p_rate);
|
||||
|
||||
/* abort if a driver objects */
|
||||
if (ret & NOTIFY_STOP_MASK)
|
||||
goto out;
|
||||
goto runtime_put;
|
||||
|
||||
/* do the re-parent */
|
||||
ret = __clk_set_parent(core, parent, p_index);
|
||||
|
|
@ -1844,6 +1932,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
|
|||
__clk_recalc_accuracies(core);
|
||||
}
|
||||
|
||||
runtime_put:
|
||||
clk_pm_runtime_put(core);
|
||||
out:
|
||||
clk_prepare_unlock();
|
||||
|
||||
|
|
@ -2350,7 +2440,7 @@ static inline void clk_debug_unregister(struct clk_core *core)
|
|||
*/
|
||||
static int __clk_core_init(struct clk_core *core)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int i, ret;
|
||||
struct clk_core *orphan;
|
||||
struct hlist_node *tmp2;
|
||||
unsigned long rate;
|
||||
|
|
@ -2360,6 +2450,10 @@ static int __clk_core_init(struct clk_core *core)
|
|||
|
||||
clk_prepare_lock();
|
||||
|
||||
ret = clk_pm_runtime_get(core);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/* check to see if a clock with this name is already registered */
|
||||
if (clk_core_lookup(core->name)) {
|
||||
pr_debug("%s: clk %s already initialized\n",
|
||||
|
|
@ -2512,6 +2606,8 @@ static int __clk_core_init(struct clk_core *core)
|
|||
|
||||
kref_init(&core->ref);
|
||||
out:
|
||||
clk_pm_runtime_put(core);
|
||||
unlock:
|
||||
clk_prepare_unlock();
|
||||
|
||||
if (!ret)
|
||||
|
|
@ -2583,6 +2679,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
|
|||
goto fail_name;
|
||||
}
|
||||
core->ops = hw->init->ops;
|
||||
if (dev && pm_runtime_enabled(dev))
|
||||
core->dev = dev;
|
||||
if (dev && dev->driver)
|
||||
core->owner = dev->driver->owner;
|
||||
core->hw = hw;
|
||||
|
|
@ -3177,6 +3275,37 @@ int of_clk_add_hw_provider(struct device_node *np,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
|
||||
|
||||
static void devm_of_clk_release_provider(struct device *dev, void *res)
|
||||
{
|
||||
of_clk_del_provider(*(struct device_node **)res);
|
||||
}
|
||||
|
||||
int devm_of_clk_add_hw_provider(struct device *dev,
|
||||
struct clk_hw *(*get)(struct of_phandle_args *clkspec,
|
||||
void *data),
|
||||
void *data)
|
||||
{
|
||||
struct device_node **ptr, *np;
|
||||
int ret;
|
||||
|
||||
ptr = devres_alloc(devm_of_clk_release_provider, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
np = dev->of_node;
|
||||
ret = of_clk_add_hw_provider(np, get, data);
|
||||
if (!ret) {
|
||||
*ptr = np;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_of_clk_add_hw_provider);
|
||||
|
||||
/**
|
||||
* of_clk_del_provider() - Remove a previously registered clock provider
|
||||
* @np: Device node pointer associated with clock provider
|
||||
|
|
@ -3198,6 +3327,27 @@ void of_clk_del_provider(struct device_node *np)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_clk_del_provider);
|
||||
|
||||
static int devm_clk_provider_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct device_node **np = res;
|
||||
|
||||
if (WARN_ON(!np || !*np))
|
||||
return 0;
|
||||
|
||||
return *np == data;
|
||||
}
|
||||
|
||||
void devm_of_clk_del_provider(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devres_release(dev, devm_of_clk_release_provider,
|
||||
devm_clk_provider_match, dev->of_node);
|
||||
|
||||
WARN_ON(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(devm_of_clk_del_provider);
|
||||
|
||||
static struct clk_hw *
|
||||
__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
|
||||
struct of_phandle_args *clkspec)
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
return mmc_clk_set_timing(hw, rate);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_mmc_ops = {
|
||||
static const struct clk_ops clk_mmc_ops = {
|
||||
.prepare = mmc_clk_prepare,
|
||||
.determine_rate = mmc_clk_determine_rate,
|
||||
.set_rate = mmc_clk_set_rate,
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = {
|
|||
|
||||
/* crgctrl */
|
||||
static const struct hisi_fixed_factor_clock hi3660_crg_fixed_factor_clks[] = {
|
||||
{ HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 8, 0, },
|
||||
{ HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 16, 0, },
|
||||
{ HI3660_CLK_FACTOR_MMC, "clk_factor_mmc", "clkin_sys", 1, 6, 0, },
|
||||
{ HI3660_CLK_GATE_I2C0, "clk_gate_i2c0", "clk_i2c0_iomcu", 1, 4, 0, },
|
||||
{ HI3660_CLK_GATE_I2C1, "clk_gate_i2c1", "clk_i2c1_iomcu", 1, 4, 0, },
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
|
|||
{ HI6220_BBPPLL_SEL, "bbppll_sel", "pll0_bbp_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9, 0, },
|
||||
{ HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
|
||||
{ HI6220_MMC2_SEL, "mmc2_sel", "mmc2_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
|
||||
{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
|
||||
{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x270, 12, 0, },
|
||||
};
|
||||
|
||||
static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ static void clk_ether_unprepare(struct clk_hw *hw)
|
|||
writel_relaxed(val, clk->ctrl_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_ether_ops = {
|
||||
static const struct clk_ops clk_ether_ops = {
|
||||
.prepare = clk_ether_prepare,
|
||||
.unprepare = clk_ether_unprepare,
|
||||
};
|
||||
|
|
@ -247,7 +247,7 @@ static void clk_complex_disable(struct clk_hw *hw)
|
|||
writel_relaxed(val, clk->phy_reg);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_complex_ops = {
|
||||
static const struct clk_ops clk_complex_ops = {
|
||||
.enable = clk_complex_enable,
|
||||
.disable = clk_complex_disable,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ static int clkgate_separated_is_enabled(struct clk_hw *hw)
|
|||
return reg ? 1 : 0;
|
||||
}
|
||||
|
||||
static struct clk_ops clkgate_separated_ops = {
|
||||
static const struct clk_ops clkgate_separated_ops = {
|
||||
.enable = clkgate_separated_enable,
|
||||
.disable = clkgate_separated_disable,
|
||||
.is_enabled = clkgate_separated_is_enabled,
|
||||
|
|
@ -105,10 +105,8 @@ struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name,
|
|||
struct clk_init_data init;
|
||||
|
||||
sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
|
||||
if (!sclk) {
|
||||
pr_err("%s: fail to allocate separated gated clk\n", __func__);
|
||||
if (!sclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clkgate_separated_ops;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
#define HI3798CV200_FIXED_12M 81
|
||||
#define HI3798CV200_FIXED_48M 82
|
||||
#define HI3798CV200_FIXED_60M 83
|
||||
#define HI3798CV200_FIXED_166P5M 84
|
||||
#define HI3798CV200_SDIO0_MUX 85
|
||||
|
||||
#define HI3798CV200_CRG_NR_CLKS 128
|
||||
|
||||
|
|
@ -63,6 +65,7 @@ static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
|
|||
{ HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
|
||||
{ HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
|
||||
{ HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
|
||||
{ HI3798CV200_FIXED_166P5M, "166p5m", NULL, 0, 165000000, },
|
||||
{ HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
|
||||
{ HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
|
||||
};
|
||||
|
|
@ -75,12 +78,19 @@ static const char *const comphy1_mux_p[] = {
|
|||
"100m", "25m"};
|
||||
static u32 comphy1_mux_table[] = {2, 3};
|
||||
|
||||
static const char *const sdio_mux_p[] = {
|
||||
"100m", "50m", "150m", "166p5m" };
|
||||
static u32 sdio_mux_table[] = {0, 1, 2, 3};
|
||||
|
||||
static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
|
||||
{ HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
|
||||
{ HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
|
||||
comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
|
||||
{ HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p,
|
||||
ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT,
|
||||
0x9c, 8, 2, 0, sdio_mux_table, },
|
||||
};
|
||||
|
||||
static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
|
||||
|
|
@ -104,7 +114,7 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
|
|||
/* SDIO */
|
||||
{ HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
|
||||
CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
|
||||
{ HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux",
|
||||
{ HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
|
||||
CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
|
||||
/* EMMC */
|
||||
{ HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_busy_divider_ops = {
|
||||
static const struct clk_ops clk_busy_divider_ops = {
|
||||
.recalc_rate = clk_busy_divider_recalc_rate,
|
||||
.round_rate = clk_busy_divider_round_rate,
|
||||
.set_rate = clk_busy_divider_set_rate,
|
||||
|
|
@ -147,7 +147,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_busy_mux_ops = {
|
||||
static const struct clk_ops clk_busy_mux_ops = {
|
||||
.get_parent = clk_busy_mux_get_parent,
|
||||
.set_parent = clk_busy_mux_set_parent,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static void clk_gate2_disable_unused(struct clk_hw *hw)
|
|||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_gate2_ops = {
|
||||
static const struct clk_ops clk_gate2_ops = {
|
||||
.enable = clk_gate2_enable,
|
||||
.disable = clk_gate2_disable,
|
||||
.disable_unused = clk_gate2_disable_unused,
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
|||
clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
|
||||
clk[IMX6QDL_CLK_GPU3D_CORE] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26);
|
||||
clk[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0);
|
||||
clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "video_27m", base + 0x70, 4);
|
||||
clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "mipi_core_cfg", base + 0x70, 4);
|
||||
clk[IMX6QDL_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6);
|
||||
clk[IMX6QDL_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8);
|
||||
clk[IMX6QDL_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10);
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
|||
clks[IMX6ULL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
|
||||
}
|
||||
clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
|
||||
clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
|
||||
clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT);
|
||||
clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
|
||||
|
||||
clks[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
|
||||
|
|
|
|||
|
|
@ -54,11 +54,6 @@ static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk",
|
|||
"pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
|
||||
"pll_usb_main_clk", };
|
||||
|
||||
static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk",
|
||||
"pll_enet_125m_clk", "pll_sys_pfd2_135m_clk",
|
||||
"pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
|
||||
"pll_usb_main_clk", };
|
||||
|
||||
static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
|
||||
"pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk",
|
||||
"pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", };
|
||||
|
|
@ -510,7 +505,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
|
||||
clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel));
|
||||
clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
|
||||
clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel));
|
||||
clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
|
||||
clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
|
||||
clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
|
||||
|
|
@ -582,7 +576,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
|
||||
clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
|
||||
clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
|
||||
clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28);
|
||||
clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28);
|
||||
clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28);
|
||||
clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28);
|
||||
|
|
@ -721,7 +714,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
|
||||
clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
|
||||
clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
|
||||
clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3);
|
||||
clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
|
||||
clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
|
||||
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
|
||||
|
|
@ -793,11 +785,10 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
|
||||
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
|
||||
clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
|
||||
clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0);
|
||||
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
|
||||
clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
|
||||
clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
|
||||
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0);
|
||||
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0);
|
||||
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
|
||||
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
|
|||
return ull;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_pllv1_ops = {
|
||||
static const struct clk_ops clk_pllv1_ops = {
|
||||
.recalc_rate = clk_pllv1_recalc_rate,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ static void clk_pllv2_unprepare(struct clk_hw *hw)
|
|||
__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_pllv2_ops = {
|
||||
static const struct clk_ops clk_pllv2_ops = {
|
||||
.prepare = clk_pllv2_prepare,
|
||||
.unprepare = clk_pllv2_unprepare,
|
||||
.recalc_rate = clk_pllv2_recalc_rate,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,56 @@ config COMMON_CLK_MT2701_BDPSYS
|
|||
---help---
|
||||
This driver supports Mediatek MT2701 bdpsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712
|
||||
bool "Clock driver for Mediatek MT2712"
|
||||
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK && ARM64
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 basic clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_BDPSYS
|
||||
bool "Clock driver for Mediatek MT2712 bdpsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 bdpsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_IMGSYS
|
||||
bool "Clock driver for Mediatek MT2712 imgsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_JPGDECSYS
|
||||
bool "Clock driver for Mediatek MT2712 jpgdecsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 jpgdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_MFGCFG
|
||||
bool "Clock driver for Mediatek MT2712 mfgcfg"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 mfgcfg clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_MMSYS
|
||||
bool "Clock driver for Mediatek MT2712 mmsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 mmsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_VDECSYS
|
||||
bool "Clock driver for Mediatek MT2712 vdecsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 vdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_VENCSYS
|
||||
bool "Clock driver for Mediatek MT2712 vencsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 vencsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797
|
||||
bool "Clock driver for Mediatek MT6797"
|
||||
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
|
||||
|
|
@ -82,6 +132,36 @@ config COMMON_CLK_MT6797_VENCSYS
|
|||
---help---
|
||||
This driver supports Mediatek MT6797 vencsys clocks.
|
||||
|
||||
config COMMON_CLK_MT7622
|
||||
bool "Clock driver for MediaTek MT7622"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK
|
||||
---help---
|
||||
This driver supports MediaTek MT7622 basic clocks and clocks
|
||||
required for various periperals found on MediaTek.
|
||||
|
||||
config COMMON_CLK_MT7622_ETHSYS
|
||||
bool "Clock driver for MediaTek MT7622 ETHSYS"
|
||||
depends on COMMON_CLK_MT7622
|
||||
---help---
|
||||
This driver add support for clocks for Ethernet and SGMII
|
||||
required on MediaTek MT7622 SoC.
|
||||
|
||||
config COMMON_CLK_MT7622_HIFSYS
|
||||
bool "Clock driver for MediaTek MT7622 HIFSYS"
|
||||
depends on COMMON_CLK_MT7622
|
||||
---help---
|
||||
This driver supports MediaTek MT7622 HIFSYS clocks providing
|
||||
to PCI-E and USB.
|
||||
|
||||
config COMMON_CLK_MT7622_AUDSYS
|
||||
bool "Clock driver for MediaTek MT7622 AUDSYS"
|
||||
depends on COMMON_CLK_MT7622
|
||||
---help---
|
||||
This driver supports MediaTek MT7622 AUDSYS clocks providing
|
||||
to audio consumers such as I2S and TDM.
|
||||
|
||||
config COMMON_CLK_MT8135
|
||||
bool "Clock driver for Mediatek MT8135"
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -13,5 +13,17 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
|
|||
obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
|
||||
|
|
|
|||
|
|
@ -750,7 +750,7 @@ static const struct mtk_fixed_factor infra_fixed_divs[] = {
|
|||
|
||||
static struct clk_onecell_data *infra_clk_data;
|
||||
|
||||
static void mtk_infrasys_init_early(struct device_node *node)
|
||||
static void __init mtk_infrasys_init_early(struct device_node *node)
|
||||
{
|
||||
int r, i;
|
||||
|
||||
|
|
|
|||
102
drivers/clk/mediatek/clk-mt2712-bdp.c
Normal file
102
drivers/clk/mediatek/clk-mt2712-bdp.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs bdp_cg_regs = {
|
||||
.set_ofs = 0x100,
|
||||
.clr_ofs = 0x100,
|
||||
.sta_ofs = 0x100,
|
||||
};
|
||||
|
||||
#define GATE_BDP(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &bdp_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate bdp_clks[] = {
|
||||
GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0),
|
||||
GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1),
|
||||
GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2),
|
||||
GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3),
|
||||
GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4),
|
||||
GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5),
|
||||
GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9),
|
||||
GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10),
|
||||
GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11),
|
||||
GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12),
|
||||
GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13),
|
||||
GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14),
|
||||
GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15),
|
||||
GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16),
|
||||
GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17),
|
||||
GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18),
|
||||
GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19),
|
||||
GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20),
|
||||
GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21),
|
||||
GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22),
|
||||
GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23),
|
||||
GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24),
|
||||
GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25),
|
||||
GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26),
|
||||
GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27),
|
||||
GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28),
|
||||
GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29),
|
||||
GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30),
|
||||
};
|
||||
|
||||
static int clk_mt2712_bdp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_bdp[] = {
|
||||
{ .compatible = "mediatek,mt2712-bdpsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_bdp_drv = {
|
||||
.probe = clk_mt2712_bdp_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-bdp",
|
||||
.of_match_table = of_match_clk_mt2712_bdp,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_bdp_drv);
|
||||
80
drivers/clk/mediatek/clk-mt2712-img.c
Normal file
80
drivers/clk/mediatek/clk-mt2712-img.c
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs img_cg_regs = {
|
||||
.set_ofs = 0x0,
|
||||
.clr_ofs = 0x0,
|
||||
.sta_ofs = 0x0,
|
||||
};
|
||||
|
||||
#define GATE_IMG(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &img_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate img_clks[] = {
|
||||
GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0),
|
||||
GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3),
|
||||
GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8),
|
||||
GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9),
|
||||
GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10),
|
||||
GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11),
|
||||
};
|
||||
|
||||
static int clk_mt2712_img_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_img[] = {
|
||||
{ .compatible = "mediatek,mt2712-imgsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_img_drv = {
|
||||
.probe = clk_mt2712_img_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-img",
|
||||
.of_match_table = of_match_clk_mt2712_img,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_img_drv);
|
||||
76
drivers/clk/mediatek/clk-mt2712-jpgdec.c
Normal file
76
drivers/clk/mediatek/clk-mt2712-jpgdec.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs jpgdec_cg_regs = {
|
||||
.set_ofs = 0x4,
|
||||
.clr_ofs = 0x8,
|
||||
.sta_ofs = 0x0,
|
||||
};
|
||||
|
||||
#define GATE_JPGDEC(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &jpgdec_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate jpgdec_clks[] = {
|
||||
GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0),
|
||||
GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4),
|
||||
};
|
||||
|
||||
static int clk_mt2712_jpgdec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_jpgdec[] = {
|
||||
{ .compatible = "mediatek,mt2712-jpgdecsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_jpgdec_drv = {
|
||||
.probe = clk_mt2712_jpgdec_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-jpgdec",
|
||||
.of_match_table = of_match_clk_mt2712_jpgdec,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_jpgdec_drv);
|
||||
75
drivers/clk/mediatek/clk-mt2712-mfg.c
Normal file
75
drivers/clk/mediatek/clk-mt2712-mfg.c
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs mfg_cg_regs = {
|
||||
.set_ofs = 0x4,
|
||||
.clr_ofs = 0x8,
|
||||
.sta_ofs = 0x0,
|
||||
};
|
||||
|
||||
#define GATE_MFG(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &mfg_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate mfg_clks[] = {
|
||||
GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0),
|
||||
};
|
||||
|
||||
static int clk_mt2712_mfg_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_mfg[] = {
|
||||
{ .compatible = "mediatek,mt2712-mfgcfg", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_mfg_drv = {
|
||||
.probe = clk_mt2712_mfg_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-mfg",
|
||||
.of_match_table = of_match_clk_mt2712_mfg,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_mfg_drv);
|
||||
170
drivers/clk/mediatek/clk-mt2712-mm.c
Normal file
170
drivers/clk/mediatek/clk-mt2712-mm.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs mm0_cg_regs = {
|
||||
.set_ofs = 0x104,
|
||||
.clr_ofs = 0x108,
|
||||
.sta_ofs = 0x100,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs mm1_cg_regs = {
|
||||
.set_ofs = 0x114,
|
||||
.clr_ofs = 0x118,
|
||||
.sta_ofs = 0x110,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs mm2_cg_regs = {
|
||||
.set_ofs = 0x224,
|
||||
.clr_ofs = 0x228,
|
||||
.sta_ofs = 0x220,
|
||||
};
|
||||
|
||||
#define GATE_MM0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &mm0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_MM1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &mm1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_MM2(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &mm2_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate mm_clks[] = {
|
||||
/* MM0 */
|
||||
GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
|
||||
GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
|
||||
GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2),
|
||||
GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3),
|
||||
GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4),
|
||||
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5),
|
||||
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6),
|
||||
GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7),
|
||||
GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8),
|
||||
GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9),
|
||||
GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10),
|
||||
GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
|
||||
GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
|
||||
GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
|
||||
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
|
||||
GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15),
|
||||
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16),
|
||||
GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17),
|
||||
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18),
|
||||
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
|
||||
GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20),
|
||||
GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
|
||||
GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
|
||||
GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23),
|
||||
GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24),
|
||||
GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
|
||||
GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
|
||||
GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27),
|
||||
GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28),
|
||||
GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31),
|
||||
/* MM1 */
|
||||
GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0),
|
||||
GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1),
|
||||
GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2),
|
||||
GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3),
|
||||
GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4),
|
||||
GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5),
|
||||
GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6),
|
||||
GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7),
|
||||
GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8),
|
||||
GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9),
|
||||
GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10),
|
||||
GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11),
|
||||
GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16),
|
||||
GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17),
|
||||
GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18),
|
||||
GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21),
|
||||
GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22),
|
||||
GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23),
|
||||
GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24),
|
||||
GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25),
|
||||
GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26),
|
||||
GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27),
|
||||
GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28),
|
||||
GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29),
|
||||
GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30),
|
||||
GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31),
|
||||
/* MM2 */
|
||||
GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0),
|
||||
GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1),
|
||||
GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2),
|
||||
GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3),
|
||||
GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4),
|
||||
GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5),
|
||||
GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6),
|
||||
};
|
||||
|
||||
static int clk_mt2712_mm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_mm[] = {
|
||||
{ .compatible = "mediatek,mt2712-mmsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_mm_drv = {
|
||||
.probe = clk_mt2712_mm_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-mm",
|
||||
.of_match_table = of_match_clk_mt2712_mm,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_mm_drv);
|
||||
94
drivers/clk/mediatek/clk-mt2712-vdec.c
Normal file
94
drivers/clk/mediatek/clk-mt2712-vdec.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs vdec0_cg_regs = {
|
||||
.set_ofs = 0x0,
|
||||
.clr_ofs = 0x4,
|
||||
.sta_ofs = 0x0,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs vdec1_cg_regs = {
|
||||
.set_ofs = 0x8,
|
||||
.clr_ofs = 0xc,
|
||||
.sta_ofs = 0x8,
|
||||
};
|
||||
|
||||
#define GATE_VDEC0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &vdec0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
#define GATE_VDEC1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &vdec1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate vdec_clks[] = {
|
||||
/* VDEC0 */
|
||||
GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
|
||||
/* VDEC1 */
|
||||
GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0),
|
||||
GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1),
|
||||
};
|
||||
|
||||
static int clk_mt2712_vdec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_vdec[] = {
|
||||
{ .compatible = "mediatek,mt2712-vdecsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_vdec_drv = {
|
||||
.probe = clk_mt2712_vdec_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-vdec",
|
||||
.of_match_table = of_match_clk_mt2712_vdec,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_vdec_drv);
|
||||
77
drivers/clk/mediatek/clk-mt2712-venc.c
Normal file
77
drivers/clk/mediatek/clk-mt2712-venc.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Weiyi Lu <weiyi.lu@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2712-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs venc_cg_regs = {
|
||||
.set_ofs = 0x4,
|
||||
.clr_ofs = 0x8,
|
||||
.sta_ofs = 0x0,
|
||||
};
|
||||
|
||||
#define GATE_VENC(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &venc_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate venc_clks[] = {
|
||||
GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0),
|
||||
GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4),
|
||||
GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12),
|
||||
};
|
||||
|
||||
static int clk_mt2712_venc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
if (r != 0)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2712_venc[] = {
|
||||
{ .compatible = "mediatek,mt2712-vencsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver clk_mt2712_venc_drv = {
|
||||
.probe = clk_mt2712_venc_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2712-venc",
|
||||
.of_match_table = of_match_clk_mt2712_venc,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2712_venc_drv);
|
||||
1435
drivers/clk/mediatek/clk-mt2712.c
Normal file
1435
drivers/clk/mediatek/clk-mt2712.c
Normal file
File diff suppressed because it is too large
Load diff
195
drivers/clk/mediatek/clk-mt7622-aud.c
Normal file
195
drivers/clk/mediatek/clk-mt7622-aud.c
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Chen Zhong <chen.zhong@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7622-clk.h>
|
||||
|
||||
#define GATE_AUDIO0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &audio0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_AUDIO1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &audio1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_AUDIO2(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &audio2_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_AUDIO3(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &audio3_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate_regs audio0_cg_regs = {
|
||||
.set_ofs = 0x0,
|
||||
.clr_ofs = 0x0,
|
||||
.sta_ofs = 0x0,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs audio1_cg_regs = {
|
||||
.set_ofs = 0x10,
|
||||
.clr_ofs = 0x10,
|
||||
.sta_ofs = 0x10,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs audio2_cg_regs = {
|
||||
.set_ofs = 0x14,
|
||||
.clr_ofs = 0x14,
|
||||
.sta_ofs = 0x14,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs audio3_cg_regs = {
|
||||
.set_ofs = 0x634,
|
||||
.clr_ofs = 0x634,
|
||||
.sta_ofs = 0x634,
|
||||
};
|
||||
|
||||
static const struct mtk_gate audio_clks[] = {
|
||||
/* AUDIO0 */
|
||||
GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2),
|
||||
GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20),
|
||||
GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21),
|
||||
GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23),
|
||||
/* AUDIO1 */
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8),
|
||||
GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9),
|
||||
GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12),
|
||||
GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13),
|
||||
GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14),
|
||||
GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15),
|
||||
GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20),
|
||||
GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21),
|
||||
GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22),
|
||||
/* AUDIO2 */
|
||||
GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0),
|
||||
GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1),
|
||||
GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2),
|
||||
GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3),
|
||||
GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4),
|
||||
GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5),
|
||||
GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6),
|
||||
GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7),
|
||||
GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8),
|
||||
GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9),
|
||||
GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10),
|
||||
GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11),
|
||||
GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12),
|
||||
GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13),
|
||||
GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14),
|
||||
GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15),
|
||||
GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16),
|
||||
GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17),
|
||||
/* AUDIO3 */
|
||||
GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2),
|
||||
GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3),
|
||||
GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6),
|
||||
GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7),
|
||||
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10),
|
||||
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11),
|
||||
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12),
|
||||
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13),
|
||||
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14),
|
||||
};
|
||||
|
||||
static int clk_mt7622_audiosys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7622_aud[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt7622-audsys",
|
||||
.data = clk_mt7622_audiosys_init,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static int clk_mt7622_aud_probe(struct platform_device *pdev)
|
||||
{
|
||||
int (*clk_init)(struct platform_device *);
|
||||
int r;
|
||||
|
||||
clk_init = of_device_get_match_data(&pdev->dev);
|
||||
if (!clk_init)
|
||||
return -EINVAL;
|
||||
|
||||
r = clk_init(pdev);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt7622_aud_drv = {
|
||||
.probe = clk_mt7622_aud_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7622-aud",
|
||||
.of_match_table = of_match_clk_mt7622_aud,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt7622_aud_drv);
|
||||
156
drivers/clk/mediatek/clk-mt7622-eth.c
Normal file
156
drivers/clk/mediatek/clk-mt7622-eth.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Chen Zhong <chen.zhong@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7622-clk.h>
|
||||
|
||||
#define GATE_ETH(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = ð_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate_regs eth_cg_regs = {
|
||||
.set_ofs = 0x30,
|
||||
.clr_ofs = 0x30,
|
||||
.sta_ofs = 0x30,
|
||||
};
|
||||
|
||||
static const struct mtk_gate eth_clks[] = {
|
||||
GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5),
|
||||
GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6),
|
||||
GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7),
|
||||
GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8),
|
||||
GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs sgmii_cg_regs = {
|
||||
.set_ofs = 0xE4,
|
||||
.clr_ofs = 0xE4,
|
||||
.sta_ofs = 0xE4,
|
||||
};
|
||||
|
||||
#define GATE_SGMII(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &sgmii_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate sgmii_clks[] = {
|
||||
GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en",
|
||||
"ssusb_tx250m", 2),
|
||||
GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en",
|
||||
"ssusb_eq_rx250m", 3),
|
||||
GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref",
|
||||
"ssusb_cdr_ref", 4),
|
||||
GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb",
|
||||
"ssusb_cdr_fb", 5),
|
||||
};
|
||||
|
||||
static int clk_mt7622_ethsys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
mtk_register_reset_controller(node, 1, 0x34);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int clk_mt7622_sgmiisys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7622_eth[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt7622-ethsys",
|
||||
.data = clk_mt7622_ethsys_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt7622-sgmiisys",
|
||||
.data = clk_mt7622_sgmiisys_init,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static int clk_mt7622_eth_probe(struct platform_device *pdev)
|
||||
{
|
||||
int (*clk_init)(struct platform_device *);
|
||||
int r;
|
||||
|
||||
clk_init = of_device_get_match_data(&pdev->dev);
|
||||
if (!clk_init)
|
||||
return -EINVAL;
|
||||
|
||||
r = clk_init(pdev);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt7622_eth_drv = {
|
||||
.probe = clk_mt7622_eth_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7622-eth",
|
||||
.of_match_table = of_match_clk_mt7622_eth,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt7622_eth_drv);
|
||||
169
drivers/clk/mediatek/clk-mt7622-hif.c
Normal file
169
drivers/clk/mediatek/clk-mt7622-hif.c
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Chen Zhong <chen.zhong@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7622-clk.h>
|
||||
|
||||
#define GATE_PCIE(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &pcie_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
#define GATE_SSUSB(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &ssusb_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate_regs pcie_cg_regs = {
|
||||
.set_ofs = 0x30,
|
||||
.clr_ofs = 0x30,
|
||||
.sta_ofs = 0x30,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs ssusb_cg_regs = {
|
||||
.set_ofs = 0x30,
|
||||
.clr_ofs = 0x30,
|
||||
.sta_ofs = 0x30,
|
||||
};
|
||||
|
||||
static const struct mtk_gate ssusb_clks[] = {
|
||||
GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p",
|
||||
"to_u2_phy_1p", 0),
|
||||
GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1),
|
||||
GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5),
|
||||
GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6),
|
||||
GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7),
|
||||
GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8),
|
||||
};
|
||||
|
||||
static const struct mtk_gate pcie_clks[] = {
|
||||
GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12),
|
||||
GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13),
|
||||
GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14),
|
||||
GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15),
|
||||
GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16),
|
||||
GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17),
|
||||
GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18),
|
||||
GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19),
|
||||
GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20),
|
||||
GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21),
|
||||
GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22),
|
||||
GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23),
|
||||
GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26),
|
||||
GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27),
|
||||
GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28),
|
||||
GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29),
|
||||
GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30),
|
||||
};
|
||||
|
||||
static int clk_mt7622_ssusbsys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
mtk_register_reset_controller(node, 1, 0x34);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int clk_mt7622_pciesys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
mtk_register_reset_controller(node, 1, 0x34);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7622_hif[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt7622-pciesys",
|
||||
.data = clk_mt7622_pciesys_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt7622-ssusbsys",
|
||||
.data = clk_mt7622_ssusbsys_init,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static int clk_mt7622_hif_probe(struct platform_device *pdev)
|
||||
{
|
||||
int (*clk_init)(struct platform_device *);
|
||||
int r;
|
||||
|
||||
clk_init = of_device_get_match_data(&pdev->dev);
|
||||
if (!clk_init)
|
||||
return -EINVAL;
|
||||
|
||||
r = clk_init(pdev);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt7622_hif_drv = {
|
||||
.probe = clk_mt7622_hif_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7622-hif",
|
||||
.of_match_table = of_match_clk_mt7622_hif,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt7622_hif_drv);
|
||||
780
drivers/clk/mediatek/clk-mt7622.c
Normal file
780
drivers/clk/mediatek/clk-mt7622.c
Normal file
|
|
@ -0,0 +1,780 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Chen Zhong <chen.zhong@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
#include "clk-cpumux.h"
|
||||
|
||||
#include <dt-bindings/clock/mt7622-clk.h>
|
||||
#include <linux/clk.h> /* for consumer */
|
||||
|
||||
#define MT7622_PLL_FMAX (2500UL * MHZ)
|
||||
#define CON0_MT7622_RST_BAR BIT(27)
|
||||
|
||||
#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
|
||||
_pcw_shift, _div_table, _parent_name) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.reg = _reg, \
|
||||
.pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, \
|
||||
.flags = _flags, \
|
||||
.rst_bar_mask = CON0_MT7622_RST_BAR, \
|
||||
.fmax = MT7622_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, \
|
||||
.pd_reg = _pd_reg, \
|
||||
.pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, \
|
||||
.pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, \
|
||||
.div_table = _div_table, \
|
||||
.parent_name = _parent_name, \
|
||||
}
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
|
||||
_pcw_shift) \
|
||||
PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
|
||||
NULL, "clkxtal")
|
||||
|
||||
#define GATE_APMIXED(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &apmixed_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
#define GATE_INFRA(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_TOP0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &top0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_TOP1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &top1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_PERI0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &peri0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_PERI1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &peri1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(mt7622_clk_lock);
|
||||
|
||||
static const char * const infra_mux1_parents[] = {
|
||||
"clkxtal",
|
||||
"armpll",
|
||||
"main_core_en",
|
||||
"armpll"
|
||||
};
|
||||
|
||||
static const char * const axi_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll1_d2",
|
||||
"syspll_d5",
|
||||
"syspll1_d4",
|
||||
"univpll_d5",
|
||||
"univpll2_d2",
|
||||
"univpll_d7"
|
||||
};
|
||||
|
||||
static const char * const mem_parents[] = {
|
||||
"clkxtal",
|
||||
"dmpll_ck"
|
||||
};
|
||||
|
||||
static const char * const ddrphycfg_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll1_d8"
|
||||
};
|
||||
|
||||
static const char * const eth_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll1_d2",
|
||||
"univpll1_d2",
|
||||
"syspll1_d4",
|
||||
"univpll_d5",
|
||||
"clk_null",
|
||||
"univpll_d7"
|
||||
};
|
||||
|
||||
static const char * const pwm_parents[] = {
|
||||
"clkxtal",
|
||||
"univpll2_d4"
|
||||
};
|
||||
|
||||
static const char * const f10m_ref_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll4_d16"
|
||||
};
|
||||
|
||||
static const char * const nfi_infra_parents[] = {
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"clkxtal",
|
||||
"univpll2_d8",
|
||||
"syspll1_d8",
|
||||
"univpll1_d8",
|
||||
"syspll4_d2",
|
||||
"univpll2_d4",
|
||||
"univpll3_d2",
|
||||
"syspll1_d4"
|
||||
};
|
||||
|
||||
static const char * const flash_parents[] = {
|
||||
"clkxtal",
|
||||
"univpll_d80_d4",
|
||||
"syspll2_d8",
|
||||
"syspll3_d4",
|
||||
"univpll3_d4",
|
||||
"univpll1_d8",
|
||||
"syspll2_d4",
|
||||
"univpll2_d4"
|
||||
};
|
||||
|
||||
static const char * const uart_parents[] = {
|
||||
"clkxtal",
|
||||
"univpll2_d8"
|
||||
};
|
||||
|
||||
static const char * const spi0_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll3_d2",
|
||||
"clkxtal",
|
||||
"syspll2_d4",
|
||||
"syspll4_d2",
|
||||
"univpll2_d4",
|
||||
"univpll1_d8",
|
||||
"clkxtal"
|
||||
};
|
||||
|
||||
static const char * const spi1_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll3_d2",
|
||||
"clkxtal",
|
||||
"syspll4_d4",
|
||||
"syspll4_d2",
|
||||
"univpll2_d4",
|
||||
"univpll1_d8",
|
||||
"clkxtal"
|
||||
};
|
||||
|
||||
static const char * const msdc30_0_parents[] = {
|
||||
"clkxtal",
|
||||
"univpll2_d16",
|
||||
"univ48m"
|
||||
};
|
||||
|
||||
static const char * const a1sys_hp_parents[] = {
|
||||
"clkxtal",
|
||||
"aud1pll_ck",
|
||||
"aud2pll_ck",
|
||||
"clkxtal"
|
||||
};
|
||||
|
||||
static const char * const intdir_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll_d2",
|
||||
"univpll_d2",
|
||||
"sgmiipll_ck"
|
||||
};
|
||||
|
||||
static const char * const aud_intbus_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll1_d4",
|
||||
"syspll4_d2",
|
||||
"syspll3_d2"
|
||||
};
|
||||
|
||||
static const char * const pmicspi_parents[] = {
|
||||
"clkxtal",
|
||||
"clk_null",
|
||||
"clk_null",
|
||||
"clk_null",
|
||||
"clk_null",
|
||||
"univpll2_d16"
|
||||
};
|
||||
|
||||
static const char * const atb_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll1_d2",
|
||||
"syspll_d5"
|
||||
};
|
||||
|
||||
static const char * const audio_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll3_d4",
|
||||
"syspll4_d4",
|
||||
"univpll1_d16"
|
||||
};
|
||||
|
||||
static const char * const usb20_parents[] = {
|
||||
"clkxtal",
|
||||
"univpll3_d4",
|
||||
"syspll1_d8",
|
||||
"clkxtal"
|
||||
};
|
||||
|
||||
static const char * const aud1_parents[] = {
|
||||
"clkxtal",
|
||||
"aud1pll_ck"
|
||||
};
|
||||
|
||||
static const char * const aud2_parents[] = {
|
||||
"clkxtal",
|
||||
"aud2pll_ck"
|
||||
};
|
||||
|
||||
static const char * const asm_l_parents[] = {
|
||||
"clkxtal",
|
||||
"syspll_d5",
|
||||
"univpll2_d2",
|
||||
"univpll2_d4"
|
||||
};
|
||||
|
||||
static const char * const apll1_ck_parents[] = {
|
||||
"aud1_sel",
|
||||
"aud2_sel"
|
||||
};
|
||||
|
||||
static const char * const peribus_ck_parents[] = {
|
||||
"syspll1_d8",
|
||||
"syspll1_d4"
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs apmixed_cg_regs = {
|
||||
.set_ofs = 0x8,
|
||||
.clr_ofs = 0x8,
|
||||
.sta_ofs = 0x8,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra_cg_regs = {
|
||||
.set_ofs = 0x40,
|
||||
.clr_ofs = 0x44,
|
||||
.sta_ofs = 0x48,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs top0_cg_regs = {
|
||||
.set_ofs = 0x120,
|
||||
.clr_ofs = 0x120,
|
||||
.sta_ofs = 0x120,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs top1_cg_regs = {
|
||||
.set_ofs = 0x128,
|
||||
.clr_ofs = 0x128,
|
||||
.sta_ofs = 0x128,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs peri0_cg_regs = {
|
||||
.set_ofs = 0x8,
|
||||
.clr_ofs = 0x10,
|
||||
.sta_ofs = 0x18,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs peri1_cg_regs = {
|
||||
.set_ofs = 0xC,
|
||||
.clr_ofs = 0x14,
|
||||
.sta_ofs = 0x1C,
|
||||
};
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001,
|
||||
PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0),
|
||||
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001,
|
||||
HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0),
|
||||
PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001,
|
||||
HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14),
|
||||
PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001,
|
||||
0, 21, 0x0300, 1, 0, 0x0304, 0),
|
||||
PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001,
|
||||
0, 21, 0x0314, 1, 0, 0x0318, 0),
|
||||
PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001,
|
||||
0, 31, 0x0324, 1, 0, 0x0328, 0),
|
||||
PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001,
|
||||
0, 31, 0x0334, 1, 0, 0x0338, 0),
|
||||
PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001,
|
||||
0, 21, 0x0344, 1, 0, 0x0348, 0),
|
||||
PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001,
|
||||
0, 21, 0x0358, 1, 0, 0x035C, 0),
|
||||
};
|
||||
|
||||
static const struct mtk_gate apmixed_clks[] = {
|
||||
GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5),
|
||||
};
|
||||
|
||||
static const struct mtk_gate infra_clks[] = {
|
||||
GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0),
|
||||
GATE_INFRA(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 2),
|
||||
GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5),
|
||||
GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16),
|
||||
GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18),
|
||||
GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_clk top_fixed_clks[] = {
|
||||
FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal",
|
||||
31250000),
|
||||
FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal",
|
||||
31250000),
|
||||
FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal",
|
||||
125000000),
|
||||
FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal",
|
||||
125000000),
|
||||
FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal",
|
||||
250000000),
|
||||
FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal",
|
||||
250000000),
|
||||
FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal",
|
||||
33333333),
|
||||
FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal",
|
||||
50000000),
|
||||
FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal",
|
||||
50000000),
|
||||
FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal",
|
||||
50000000),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_factor top_divs[] = {
|
||||
FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4),
|
||||
FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500),
|
||||
FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125),
|
||||
FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500),
|
||||
FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1),
|
||||
FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024),
|
||||
FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1),
|
||||
FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24),
|
||||
FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
|
||||
FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10),
|
||||
FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112),
|
||||
FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320),
|
||||
FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25),
|
||||
FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1),
|
||||
FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2),
|
||||
FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1),
|
||||
FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1),
|
||||
FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2),
|
||||
FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4),
|
||||
FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1),
|
||||
FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1),
|
||||
FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_gate top_clks[] = {
|
||||
/* TOP0 */
|
||||
GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0),
|
||||
GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1),
|
||||
GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div",
|
||||
2),
|
||||
GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div",
|
||||
3),
|
||||
GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div",
|
||||
4),
|
||||
GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div",
|
||||
5),
|
||||
|
||||
/* TOP1 */
|
||||
GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0),
|
||||
GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16),
|
||||
};
|
||||
|
||||
static const struct mtk_clk_divider top_adj_divs[] = {
|
||||
DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel",
|
||||
0x120, 24, 3),
|
||||
DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel",
|
||||
0x120, 28, 3),
|
||||
DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel",
|
||||
0x124, 0, 7),
|
||||
DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel",
|
||||
0x124, 8, 7),
|
||||
DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck",
|
||||
0x124, 16, 7),
|
||||
DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel",
|
||||
0x124, 24, 7),
|
||||
DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel",
|
||||
0x128, 8, 7),
|
||||
DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel",
|
||||
0x128, 24, 7),
|
||||
};
|
||||
|
||||
static const struct mtk_gate peri_clks[] = {
|
||||
/* PERI0 */
|
||||
GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1),
|
||||
GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2),
|
||||
GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3),
|
||||
GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4),
|
||||
GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5),
|
||||
GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6),
|
||||
GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7),
|
||||
GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8),
|
||||
GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9),
|
||||
GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14),
|
||||
GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17),
|
||||
GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18),
|
||||
GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19),
|
||||
GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20),
|
||||
GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21),
|
||||
GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22),
|
||||
GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23),
|
||||
GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24),
|
||||
GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25),
|
||||
GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26),
|
||||
GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27),
|
||||
GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28),
|
||||
GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29),
|
||||
GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30),
|
||||
GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31),
|
||||
|
||||
/* PERI1 */
|
||||
GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1),
|
||||
GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2),
|
||||
};
|
||||
|
||||
static struct mtk_composite infra_muxes[] __initdata = {
|
||||
MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents,
|
||||
0x000, 2, 2),
|
||||
};
|
||||
|
||||
static struct mtk_composite top_muxes[] = {
|
||||
/* CLK_CFG_0 */
|
||||
MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
|
||||
0x040, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
|
||||
0x040, 8, 1, 15),
|
||||
MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
|
||||
0x040, 16, 1, 23),
|
||||
MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents,
|
||||
0x040, 24, 3, 31),
|
||||
|
||||
/* CLK_CFG_1 */
|
||||
MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
|
||||
0x050, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents,
|
||||
0x050, 8, 1, 15),
|
||||
MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents,
|
||||
0x050, 16, 4, 23),
|
||||
MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
|
||||
0x050, 24, 3, 31),
|
||||
|
||||
/* CLK_CFG_2 */
|
||||
MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
|
||||
0x060, 0, 1, 7),
|
||||
MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents,
|
||||
0x060, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents,
|
||||
0x060, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents,
|
||||
0x060, 24, 3, 31),
|
||||
|
||||
/* CLK_CFG_3 */
|
||||
MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents,
|
||||
0x070, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents,
|
||||
0x070, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents,
|
||||
0x070, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents,
|
||||
0x070, 24, 2, 31),
|
||||
|
||||
/* CLK_CFG_4 */
|
||||
MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
|
||||
0x080, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
|
||||
0x080, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
|
||||
0x080, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents,
|
||||
0x080, 24, 2, 31),
|
||||
|
||||
/* CLK_CFG_5 */
|
||||
MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents,
|
||||
0x090, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents,
|
||||
0x090, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
|
||||
0x090, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents,
|
||||
0x090, 24, 2, 31),
|
||||
|
||||
/* CLK_CFG_6 */
|
||||
MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents,
|
||||
0x0A0, 0, 1, 7),
|
||||
MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents,
|
||||
0x0A0, 8, 1, 15),
|
||||
MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents,
|
||||
0x0A0, 16, 1, 23),
|
||||
MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents,
|
||||
0x0A0, 24, 1, 31),
|
||||
|
||||
/* CLK_CFG_7 */
|
||||
MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents,
|
||||
0x0B0, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents,
|
||||
0x0B0, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents,
|
||||
0x0B0, 16, 2, 23),
|
||||
|
||||
/* CLK_AUDDIV_0 */
|
||||
MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents,
|
||||
0x120, 6, 1),
|
||||
MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents,
|
||||
0x120, 7, 1),
|
||||
MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents,
|
||||
0x120, 8, 1),
|
||||
MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents,
|
||||
0x120, 9, 1),
|
||||
MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents,
|
||||
0x120, 10, 1),
|
||||
MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents,
|
||||
0x120, 11, 1),
|
||||
};
|
||||
|
||||
static struct mtk_composite peri_muxes[] = {
|
||||
/* PERI_GLOBALCON_CKSEL */
|
||||
MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1),
|
||||
};
|
||||
|
||||
static int mtk_topckgen_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
void __iomem *base;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
|
||||
|
||||
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
|
||||
clk_data);
|
||||
|
||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs),
|
||||
clk_data);
|
||||
|
||||
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
|
||||
base, &mt7622_clk_lock, clk_data);
|
||||
|
||||
mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
|
||||
base, &mt7622_clk_lock, clk_data);
|
||||
|
||||
mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
|
||||
clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]);
|
||||
|
||||
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
static int __init mtk_infrasys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
clk_data);
|
||||
|
||||
mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get,
|
||||
clk_data);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mtk_register_reset_controller(node, 1, 0x30);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_apmixedsys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls),
|
||||
clk_data);
|
||||
|
||||
mtk_clk_register_gates(node, apmixed_clks,
|
||||
ARRAY_SIZE(apmixed_clks), clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]);
|
||||
clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]);
|
||||
|
||||
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
static int mtk_pericfg_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
void __iomem *base;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
|
||||
clk_data);
|
||||
|
||||
mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base,
|
||||
&mt7622_clk_lock, clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]);
|
||||
|
||||
mtk_register_reset_controller(node, 2, 0x0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt7622[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt7622-apmixedsys",
|
||||
.data = mtk_apmixedsys_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt7622-infracfg",
|
||||
.data = mtk_infrasys_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt7622-topckgen",
|
||||
.data = mtk_topckgen_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt7622-pericfg",
|
||||
.data = mtk_pericfg_init,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static int clk_mt7622_probe(struct platform_device *pdev)
|
||||
{
|
||||
int (*clk_init)(struct platform_device *);
|
||||
int r;
|
||||
|
||||
clk_init = of_device_get_match_data(&pdev->dev);
|
||||
if (!clk_init)
|
||||
return -EINVAL;
|
||||
|
||||
r = clk_init(pdev);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt7622_drv = {
|
||||
.probe = clk_mt7622_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt7622",
|
||||
.of_match_table = of_match_clk_mt7622,
|
||||
},
|
||||
};
|
||||
|
||||
static int clk_mt7622_init(void)
|
||||
{
|
||||
return platform_driver_register(&clk_mt7622_drv);
|
||||
}
|
||||
|
||||
arch_initcall(clk_mt7622_init);
|
||||
|
|
@ -207,6 +207,8 @@ struct mtk_pll_data {
|
|||
uint32_t en_mask;
|
||||
uint32_t pd_reg;
|
||||
uint32_t tuner_reg;
|
||||
uint32_t tuner_en_reg;
|
||||
uint8_t tuner_en_bit;
|
||||
int pd_shift;
|
||||
unsigned int flags;
|
||||
const struct clk_ops *ops;
|
||||
|
|
@ -216,6 +218,7 @@ struct mtk_pll_data {
|
|||
uint32_t pcw_reg;
|
||||
int pcw_shift;
|
||||
const struct mtk_pll_div_table *div_table;
|
||||
const char *parent_name;
|
||||
};
|
||||
|
||||
void mtk_clk_register_plls(struct device_node *node,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct mtk_clk_pll {
|
|||
void __iomem *pd_addr;
|
||||
void __iomem *pwr_addr;
|
||||
void __iomem *tuner_addr;
|
||||
void __iomem *tuner_en_addr;
|
||||
void __iomem *pcw_addr;
|
||||
const struct mtk_pll_data *data;
|
||||
};
|
||||
|
|
@ -227,7 +228,10 @@ static int mtk_pll_prepare(struct clk_hw *hw)
|
|||
r |= pll->data->en_mask;
|
||||
writel(r, pll->base_addr + REG_CON0);
|
||||
|
||||
if (pll->tuner_addr) {
|
||||
if (pll->tuner_en_addr) {
|
||||
r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
|
||||
writel(r, pll->tuner_en_addr);
|
||||
} else if (pll->tuner_addr) {
|
||||
r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
|
||||
writel(r, pll->tuner_addr);
|
||||
}
|
||||
|
|
@ -254,7 +258,10 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
|
|||
writel(r, pll->base_addr + REG_CON0);
|
||||
}
|
||||
|
||||
if (pll->tuner_addr) {
|
||||
if (pll->tuner_en_addr) {
|
||||
r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
|
||||
writel(r, pll->tuner_en_addr);
|
||||
} else if (pll->tuner_addr) {
|
||||
r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
|
||||
writel(r, pll->tuner_addr);
|
||||
}
|
||||
|
|
@ -297,13 +304,18 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
|
|||
pll->pcw_addr = base + data->pcw_reg;
|
||||
if (data->tuner_reg)
|
||||
pll->tuner_addr = base + data->tuner_reg;
|
||||
if (data->tuner_en_reg)
|
||||
pll->tuner_en_addr = base + data->tuner_en_reg;
|
||||
pll->hw.init = &init;
|
||||
pll->data = data;
|
||||
|
||||
init.name = data->name;
|
||||
init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
|
||||
init.ops = &mtk_pll_ops;
|
||||
init.parent_names = &parent_name;
|
||||
if (data->parent_name)
|
||||
init.parent_names = &data->parent_name;
|
||||
else
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clk = clk_register(NULL, &pll->hw);
|
||||
|
|
|
|||
|
|
@ -1131,6 +1131,253 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = {
|
|||
},
|
||||
};
|
||||
|
||||
/* VPU Clock */
|
||||
|
||||
static u32 mux_table_vpu[] = {0, 1, 2, 3};
|
||||
static const char * const gxbb_vpu_parent_names[] = {
|
||||
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_vpu_0_sel = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.table = mux_table_vpu,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_0_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bits 9:10 selects from 4 possible parents:
|
||||
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
|
||||
*/
|
||||
.parent_names = gxbb_vpu_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_vpu_0_div = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vpu_0_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_vpu_0 = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vpu_0",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vpu_0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_vpu_1_sel = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.table = mux_table_vpu,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_1_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bits 25:26 selects from 4 possible parents:
|
||||
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
|
||||
*/
|
||||
.parent_names = gxbb_vpu_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_vpu_1_div = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu_1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vpu_1_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_vpu_1 = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vpu_1",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vpu_1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_vpu = {
|
||||
.reg = (void *)HHI_VPU_CLK_CNTL,
|
||||
.mask = 1,
|
||||
.shift = 31,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vpu",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bit 31 selects from 2 possible parents:
|
||||
* vpu_0 or vpu_1
|
||||
*/
|
||||
.parent_names = (const char *[]){ "vpu_0", "vpu_1" },
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
/* VAPB Clock */
|
||||
|
||||
static u32 mux_table_vapb[] = {0, 1, 2, 3};
|
||||
static const char * const gxbb_vapb_parent_names[] = {
|
||||
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_vapb_0_sel = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
.lock = &clk_lock,
|
||||
.table = mux_table_vapb,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_0_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bits 9:10 selects from 4 possible parents:
|
||||
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
|
||||
*/
|
||||
.parent_names = gxbb_vapb_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_vapb_0_div = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vapb_0_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_vapb_0 = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vapb_0",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vapb_0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_vapb_1_sel = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 25,
|
||||
.lock = &clk_lock,
|
||||
.table = mux_table_vapb,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_1_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bits 25:26 selects from 4 possible parents:
|
||||
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
|
||||
*/
|
||||
.parent_names = gxbb_vapb_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_vapb_1_div = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "vapb_1_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_vapb_1 = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vapb_1",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vapb_1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_vapb_sel = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.mask = 1,
|
||||
.shift = 31,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vapb_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bit 31 selects from 2 possible parents:
|
||||
* vapb_0 or vapb_1
|
||||
*/
|
||||
.parent_names = (const char *[]){ "vapb_0", "vapb_1" },
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_vapb = {
|
||||
.reg = (void *)HHI_VAPBCLK_CNTL,
|
||||
.bit_idx = 30,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vapb",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "vapb_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
/* Everything Else (EE) domain gates */
|
||||
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
|
||||
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
|
||||
|
|
@ -1349,6 +1596,21 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
|
|||
[CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw,
|
||||
[CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw,
|
||||
[CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw,
|
||||
[CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw,
|
||||
[CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw,
|
||||
[CLKID_VPU_0] = &gxbb_vpu_0.hw,
|
||||
[CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw,
|
||||
[CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw,
|
||||
[CLKID_VPU_1] = &gxbb_vpu_1.hw,
|
||||
[CLKID_VPU] = &gxbb_vpu.hw,
|
||||
[CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw,
|
||||
[CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw,
|
||||
[CLKID_VAPB_0] = &gxbb_vapb_0.hw,
|
||||
[CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw,
|
||||
[CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw,
|
||||
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
|
||||
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
|
||||
[CLKID_VAPB] = &gxbb_vapb.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
|
|
@ -1481,6 +1743,21 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
|
|||
[CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw,
|
||||
[CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw,
|
||||
[CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw,
|
||||
[CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw,
|
||||
[CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw,
|
||||
[CLKID_VPU_0] = &gxbb_vpu_0.hw,
|
||||
[CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw,
|
||||
[CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw,
|
||||
[CLKID_VPU_1] = &gxbb_vpu_1.hw,
|
||||
[CLKID_VPU] = &gxbb_vpu.hw,
|
||||
[CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw,
|
||||
[CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw,
|
||||
[CLKID_VAPB_0] = &gxbb_vapb_0.hw,
|
||||
[CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw,
|
||||
[CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw,
|
||||
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
|
||||
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
|
||||
[CLKID_VAPB] = &gxbb_vapb.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
|
|
@ -1600,6 +1877,11 @@ static struct clk_gate *const gxbb_clk_gates[] = {
|
|||
&gxbb_sd_emmc_a_clk0,
|
||||
&gxbb_sd_emmc_b_clk0,
|
||||
&gxbb_sd_emmc_c_clk0,
|
||||
&gxbb_vpu_0,
|
||||
&gxbb_vpu_1,
|
||||
&gxbb_vapb_0,
|
||||
&gxbb_vapb_1,
|
||||
&gxbb_vapb,
|
||||
};
|
||||
|
||||
static struct clk_mux *const gxbb_clk_muxes[] = {
|
||||
|
|
@ -1615,6 +1897,12 @@ static struct clk_mux *const gxbb_clk_muxes[] = {
|
|||
&gxbb_sd_emmc_a_clk0_sel,
|
||||
&gxbb_sd_emmc_b_clk0_sel,
|
||||
&gxbb_sd_emmc_c_clk0_sel,
|
||||
&gxbb_vpu_0_sel,
|
||||
&gxbb_vpu_1_sel,
|
||||
&gxbb_vpu,
|
||||
&gxbb_vapb_0_sel,
|
||||
&gxbb_vapb_1_sel,
|
||||
&gxbb_vapb_sel,
|
||||
};
|
||||
|
||||
static struct clk_divider *const gxbb_clk_dividers[] = {
|
||||
|
|
@ -1627,6 +1915,10 @@ static struct clk_divider *const gxbb_clk_dividers[] = {
|
|||
&gxbb_sd_emmc_a_clk0_div,
|
||||
&gxbb_sd_emmc_b_clk0_div,
|
||||
&gxbb_sd_emmc_c_clk0_div,
|
||||
&gxbb_vpu_0_div,
|
||||
&gxbb_vpu_1_div,
|
||||
&gxbb_vapb_0_div,
|
||||
&gxbb_vapb_1_div,
|
||||
};
|
||||
|
||||
static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
|
||||
|
|
|
|||
|
|
@ -190,8 +190,12 @@
|
|||
#define CLKID_SD_EMMC_B_CLK0_DIV 121
|
||||
#define CLKID_SD_EMMC_C_CLK0_SEL 123
|
||||
#define CLKID_SD_EMMC_C_CLK0_DIV 124
|
||||
#define CLKID_VPU_0_DIV 127
|
||||
#define CLKID_VPU_1_DIV 130
|
||||
#define CLKID_VAPB_0_DIV 134
|
||||
#define CLKID_VAPB_1_DIV 137
|
||||
|
||||
#define NR_CLKS 126
|
||||
#define NR_CLKS 141
|
||||
|
||||
/* include the CLKIDs that have been made part of the DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw)
|
|||
spin_unlock_irqrestore(apbc->lock, flags);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_apbc_ops = {
|
||||
static const struct clk_ops clk_apbc_ops = {
|
||||
.prepare = clk_apbc_prepare,
|
||||
.unprepare = clk_apbc_unprepare,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ static void clk_apmu_disable(struct clk_hw *hw)
|
|||
spin_unlock_irqrestore(apmu->lock, flags);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_apmu_ops = {
|
||||
static const struct clk_ops clk_apmu_ops = {
|
||||
.enable = clk_apmu_enable,
|
||||
.disable = clk_apmu_disable,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ static void clk_factor_init(struct clk_hw *hw)
|
|||
spin_unlock_irqrestore(factor->lock, flags);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_factor_ops = {
|
||||
static const struct clk_ops clk_factor_ops = {
|
||||
.recalc_rate = clk_factor_recalc_rate,
|
||||
.round_rate = clk_factor_round_rate,
|
||||
.set_rate = clk_factor_set_rate,
|
||||
|
|
@ -172,10 +172,8 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
|
|||
}
|
||||
|
||||
factor = kzalloc(sizeof(*factor), GFP_KERNEL);
|
||||
if (!factor) {
|
||||
pr_err("%s: could not allocate factor clk\n", __func__);
|
||||
if (!factor)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* struct clk_aux assignments */
|
||||
factor->base = base;
|
||||
|
|
|
|||
|
|
@ -103,10 +103,8 @@ struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
|
|||
|
||||
/* allocate the gate */
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate) {
|
||||
pr_err("%s:%s could not allocate gate clk\n", __func__, name);
|
||||
if (!gate)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &mmp_clk_gate_ops;
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
|
|||
parent_rate = clk_hw_get_rate(parent);
|
||||
mix_rate = parent_rate / item->divisor;
|
||||
gap = abs(mix_rate - req->rate);
|
||||
if (parent_best == NULL || gap < gap_best) {
|
||||
if (!parent_best || gap < gap_best) {
|
||||
parent_best = parent;
|
||||
parent_rate_best = parent_rate;
|
||||
mix_rate_best = mix_rate;
|
||||
|
|
@ -247,7 +247,7 @@ static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
|
|||
div = _get_div(mix, j);
|
||||
mix_rate = parent_rate / div;
|
||||
gap = abs(mix_rate - req->rate);
|
||||
if (parent_best == NULL || gap < gap_best) {
|
||||
if (!parent_best || gap < gap_best) {
|
||||
parent_best = parent;
|
||||
parent_rate_best = parent_rate;
|
||||
mix_rate_best = mix_rate;
|
||||
|
|
@ -451,11 +451,8 @@ struct clk *mmp_clk_register_mix(struct device *dev,
|
|||
size_t table_bytes;
|
||||
|
||||
mix = kzalloc(sizeof(*mix), GFP_KERNEL);
|
||||
if (!mix) {
|
||||
pr_err("%s:%s: could not allocate mmp mix clk\n",
|
||||
__func__, name);
|
||||
if (!mix)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.flags = flags | CLK_GET_RATE_NOCACHE;
|
||||
|
|
@ -467,12 +464,9 @@ struct clk *mmp_clk_register_mix(struct device *dev,
|
|||
if (config->table) {
|
||||
table_bytes = sizeof(*config->table) * config->table_size;
|
||||
mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL);
|
||||
if (!mix->table) {
|
||||
pr_err("%s:%s: could not allocate mmp mix table\n",
|
||||
__func__, name);
|
||||
kfree(mix);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
if (!mix->table)
|
||||
goto free_mix;
|
||||
|
||||
mix->table_size = config->table_size;
|
||||
}
|
||||
|
||||
|
|
@ -481,11 +475,8 @@ struct clk *mmp_clk_register_mix(struct device *dev,
|
|||
mix->mux_table = kmemdup(config->mux_table, table_bytes,
|
||||
GFP_KERNEL);
|
||||
if (!mix->mux_table) {
|
||||
pr_err("%s:%s: could not allocate mmp mix mux-table\n",
|
||||
__func__, name);
|
||||
kfree(mix->table);
|
||||
kfree(mix);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
goto free_mix;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -509,4 +500,8 @@ struct clk *mmp_clk_register_mix(struct device *dev,
|
|||
}
|
||||
|
||||
return clk;
|
||||
|
||||
free_mix:
|
||||
kfree(mix);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,19 +83,19 @@ void __init mmp2_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys,
|
|||
void __iomem *apbc_base;
|
||||
|
||||
mpmu_base = ioremap(mpmu_phys, SZ_4K);
|
||||
if (mpmu_base == NULL) {
|
||||
if (!mpmu_base) {
|
||||
pr_err("error to ioremap MPMU base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apmu_base = ioremap(apmu_phys, SZ_4K);
|
||||
if (apmu_base == NULL) {
|
||||
if (!apmu_base) {
|
||||
pr_err("error to ioremap APMU base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apbc_base = ioremap(apbc_phys, SZ_4K);
|
||||
if (apbc_base == NULL) {
|
||||
if (!apbc_base) {
|
||||
pr_err("error to ioremap APBC base\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,19 +75,19 @@ void __init pxa168_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys,
|
|||
void __iomem *apbc_base;
|
||||
|
||||
mpmu_base = ioremap(mpmu_phys, SZ_4K);
|
||||
if (mpmu_base == NULL) {
|
||||
if (!mpmu_base) {
|
||||
pr_err("error to ioremap MPMU base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apmu_base = ioremap(apmu_phys, SZ_4K);
|
||||
if (apmu_base == NULL) {
|
||||
if (!apmu_base) {
|
||||
pr_err("error to ioremap APMU base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apbc_base = ioremap(apbc_phys, SZ_4K);
|
||||
if (apbc_base == NULL) {
|
||||
if (!apbc_base) {
|
||||
pr_err("error to ioremap APBC base\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,25 +74,25 @@ void __init pxa910_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys,
|
|||
void __iomem *apbc_base;
|
||||
|
||||
mpmu_base = ioremap(mpmu_phys, SZ_4K);
|
||||
if (mpmu_base == NULL) {
|
||||
if (!mpmu_base) {
|
||||
pr_err("error to ioremap MPMU base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apmu_base = ioremap(apmu_phys, SZ_4K);
|
||||
if (apmu_base == NULL) {
|
||||
if (!apmu_base) {
|
||||
pr_err("error to ioremap APMU base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apbcp_base = ioremap(apbcp_phys, SZ_4K);
|
||||
if (apbcp_base == NULL) {
|
||||
if (!apbcp_base) {
|
||||
pr_err("error to ioremap APBC extension base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
apbc_base = ioremap(apbc_phys, SZ_4K);
|
||||
if (apbc_base == NULL) {
|
||||
if (!apbc_base) {
|
||||
pr_err("error to ioremap APBC base\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_div_ops = {
|
||||
static const struct clk_ops clk_div_ops = {
|
||||
.recalc_rate = clk_div_recalc_rate,
|
||||
.round_rate = clk_div_round_rate,
|
||||
.set_rate = clk_div_set_rate,
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
return mxs_clk_wait(frac->reg, frac->busy);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_frac_ops = {
|
||||
static const struct clk_ops clk_frac_ops = {
|
||||
.recalc_rate = clk_frac_recalc_rate,
|
||||
.round_rate = clk_frac_round_rate,
|
||||
.set_rate = clk_frac_set_rate,
|
||||
|
|
|
|||
|
|
@ -147,9 +147,7 @@ void pxa2xx_core_turbo_switch(bool on)
|
|||
" b 3f\n"
|
||||
"2: b 1b\n"
|
||||
"3: nop\n"
|
||||
: "=&r" (unused)
|
||||
: "r" (clkcfg)
|
||||
: );
|
||||
: "=&r" (unused) : "r" (clkcfg));
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ extern const struct clk_ops clk_dyn_rcg_ops;
|
|||
* @hid_width: number of bits in half integer divider
|
||||
* @parent_map: map from software's parent index to hardware's src_sel field
|
||||
* @freq_tbl: frequency table
|
||||
* @current_freq: last cached frequency when using branches with shared RCGs
|
||||
* @clkr: regmap clock handle
|
||||
*
|
||||
*/
|
||||
|
|
@ -166,7 +165,6 @@ struct clk_rcg2 {
|
|||
u8 hid_width;
|
||||
const struct parent_map *parent_map;
|
||||
const struct freq_tbl *freq_tbl;
|
||||
unsigned long current_freq;
|
||||
struct clk_regmap clkr;
|
||||
};
|
||||
|
||||
|
|
@ -174,7 +172,6 @@ struct clk_rcg2 {
|
|||
|
||||
extern const struct clk_ops clk_rcg2_ops;
|
||||
extern const struct clk_ops clk_rcg2_floor_ops;
|
||||
extern const struct clk_ops clk_rcg2_shared_ops;
|
||||
extern const struct clk_ops clk_edp_pixel_ops;
|
||||
extern const struct clk_ops clk_byte_ops;
|
||||
extern const struct clk_ops clk_byte2_ops;
|
||||
|
|
|
|||
|
|
@ -358,85 +358,6 @@ const struct clk_ops clk_rcg2_floor_ops = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
|
||||
|
||||
static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
const char *name = clk_hw_get_name(hw);
|
||||
int ret, count;
|
||||
|
||||
/* force enable RCG */
|
||||
ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
|
||||
CMD_ROOT_EN, CMD_ROOT_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* wait for RCG to turn ON */
|
||||
for (count = 500; count > 0; count--) {
|
||||
ret = clk_rcg2_is_enabled(hw);
|
||||
if (ret)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (!count)
|
||||
pr_err("%s: RCG did not turn on\n", name);
|
||||
|
||||
/* set clock rate */
|
||||
ret = __clk_rcg2_set_rate(hw, rate, CEIL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* clear force enable RCG */
|
||||
return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
|
||||
CMD_ROOT_EN, 0);
|
||||
}
|
||||
|
||||
static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
||||
/* cache the rate */
|
||||
rcg->current_freq = rate;
|
||||
|
||||
if (!__clk_is_enabled(hw->clk))
|
||||
return 0;
|
||||
|
||||
return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
||||
return rcg->current_freq = clk_rcg2_recalc_rate(hw, parent_rate);
|
||||
}
|
||||
|
||||
static int clk_rcg2_shared_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
||||
return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
|
||||
}
|
||||
|
||||
static void clk_rcg2_shared_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
||||
/* switch to XO, which is the lowest entry in the freq table */
|
||||
clk_rcg2_shared_set_rate(hw, rcg->freq_tbl[0].freq, 0);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_rcg2_shared_ops = {
|
||||
.enable = clk_rcg2_shared_enable,
|
||||
.disable = clk_rcg2_shared_disable,
|
||||
.get_parent = clk_rcg2_get_parent,
|
||||
.recalc_rate = clk_rcg2_shared_recalc_rate,
|
||||
.determine_rate = clk_rcg2_determine_rate,
|
||||
.set_rate = clk_rcg2_shared_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops);
|
||||
|
||||
struct frac_entry {
|
||||
int num;
|
||||
int den;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,18 @@
|
|||
}, \
|
||||
}
|
||||
|
||||
#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \
|
||||
static struct clk_rpm _platform##_##_name = { \
|
||||
.rpm_clk_id = (r_id), \
|
||||
.rate = (r), \
|
||||
.hw.init = &(struct clk_init_data){ \
|
||||
.ops = &clk_rpm_fixed_ops, \
|
||||
.name = #_name, \
|
||||
.parent_names = (const char *[]){ "pxo" }, \
|
||||
.num_parents = 1, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \
|
||||
static struct clk_rpm _platform##_##_active; \
|
||||
static struct clk_rpm _platform##_##_name = { \
|
||||
|
|
@ -143,6 +155,13 @@ static int clk_rpm_handoff(struct clk_rpm *r)
|
|||
int ret;
|
||||
u32 value = INT_MAX;
|
||||
|
||||
/*
|
||||
* The vendor tree simply reads the status for this
|
||||
* RPM clock.
|
||||
*/
|
||||
if (r->rpm_clk_id == QCOM_RPM_PLL_4)
|
||||
return 0;
|
||||
|
||||
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
|
||||
r->rpm_clk_id, &value, 1);
|
||||
if (ret)
|
||||
|
|
@ -269,6 +288,32 @@ out:
|
|||
mutex_unlock(&rpm_clk_lock);
|
||||
}
|
||||
|
||||
static int clk_rpm_fixed_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rpm *r = to_clk_rpm(hw);
|
||||
u32 value = 1;
|
||||
int ret;
|
||||
|
||||
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
|
||||
r->rpm_clk_id, &value, 1);
|
||||
if (!ret)
|
||||
r->enabled = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_rpm_fixed_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rpm *r = to_clk_rpm(hw);
|
||||
u32 value = 0;
|
||||
int ret;
|
||||
|
||||
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
|
||||
r->rpm_clk_id, &value, 1);
|
||||
if (!ret)
|
||||
r->enabled = false;
|
||||
}
|
||||
|
||||
static int clk_rpm_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
|
|
@ -333,6 +378,13 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
|
|||
return r->rate;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_rpm_fixed_ops = {
|
||||
.prepare = clk_rpm_fixed_prepare,
|
||||
.unprepare = clk_rpm_fixed_unprepare,
|
||||
.round_rate = clk_rpm_round_rate,
|
||||
.recalc_rate = clk_rpm_recalc_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops clk_rpm_ops = {
|
||||
.prepare = clk_rpm_prepare,
|
||||
.unprepare = clk_rpm_unprepare,
|
||||
|
|
@ -348,6 +400,45 @@ static const struct clk_ops clk_rpm_branch_ops = {
|
|||
.recalc_rate = clk_rpm_recalc_rate,
|
||||
};
|
||||
|
||||
/* MSM8660/APQ8060 */
|
||||
DEFINE_CLK_RPM(msm8660, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, smi_clk, smi_a_clk, QCOM_RPM_SMI_CLK);
|
||||
DEFINE_CLK_RPM(msm8660, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
|
||||
DEFINE_CLK_RPM_FIXED(msm8660, pll4_clk, pll4_a_clk, QCOM_RPM_PLL_4, 540672000);
|
||||
|
||||
static struct clk_rpm *msm8660_clks[] = {
|
||||
[RPM_APPS_FABRIC_CLK] = &msm8660_afab_clk,
|
||||
[RPM_APPS_FABRIC_A_CLK] = &msm8660_afab_a_clk,
|
||||
[RPM_SYS_FABRIC_CLK] = &msm8660_sfab_clk,
|
||||
[RPM_SYS_FABRIC_A_CLK] = &msm8660_sfab_a_clk,
|
||||
[RPM_MM_FABRIC_CLK] = &msm8660_mmfab_clk,
|
||||
[RPM_MM_FABRIC_A_CLK] = &msm8660_mmfab_a_clk,
|
||||
[RPM_DAYTONA_FABRIC_CLK] = &msm8660_daytona_clk,
|
||||
[RPM_DAYTONA_FABRIC_A_CLK] = &msm8660_daytona_a_clk,
|
||||
[RPM_SFPB_CLK] = &msm8660_sfpb_clk,
|
||||
[RPM_SFPB_A_CLK] = &msm8660_sfpb_a_clk,
|
||||
[RPM_CFPB_CLK] = &msm8660_cfpb_clk,
|
||||
[RPM_CFPB_A_CLK] = &msm8660_cfpb_a_clk,
|
||||
[RPM_MMFPB_CLK] = &msm8660_mmfpb_clk,
|
||||
[RPM_MMFPB_A_CLK] = &msm8660_mmfpb_a_clk,
|
||||
[RPM_SMI_CLK] = &msm8660_smi_clk,
|
||||
[RPM_SMI_A_CLK] = &msm8660_smi_a_clk,
|
||||
[RPM_EBI1_CLK] = &msm8660_ebi1_clk,
|
||||
[RPM_EBI1_A_CLK] = &msm8660_ebi1_a_clk,
|
||||
[RPM_PLL4_CLK] = &msm8660_pll4_clk,
|
||||
};
|
||||
|
||||
static const struct rpm_clk_desc rpm_clk_msm8660 = {
|
||||
.clks = msm8660_clks,
|
||||
.num_clks = ARRAY_SIZE(msm8660_clks),
|
||||
};
|
||||
|
||||
/* apq8064 */
|
||||
DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
|
||||
DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
|
||||
|
|
@ -386,6 +477,8 @@ static const struct rpm_clk_desc rpm_clk_apq8064 = {
|
|||
};
|
||||
|
||||
static const struct of_device_id rpm_clk_match_table[] = {
|
||||
{ .compatible = "qcom,rpmcc-msm8660", .data = &rpm_clk_msm8660 },
|
||||
{ .compatible = "qcom,rpmcc-apq8060", .data = &rpm_clk_msm8660 },
|
||||
{ .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },
|
||||
{ }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -530,9 +530,91 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = {
|
|||
.clks = msm8974_clks,
|
||||
.num_clks = ARRAY_SIZE(msm8974_clks),
|
||||
};
|
||||
|
||||
/* msm8996 */
|
||||
DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
|
||||
DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
|
||||
DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
|
||||
DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
|
||||
DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk,
|
||||
QCOM_SMD_RPM_MMAXI_CLK, 0);
|
||||
DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
|
||||
DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
|
||||
DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk,
|
||||
QCOM_SMD_RPM_AGGR_CLK, 1, 1000);
|
||||
DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk,
|
||||
QCOM_SMD_RPM_AGGR_CLK, 2, 1000);
|
||||
DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk,
|
||||
QCOM_SMD_RPM_MISC_CLK, 1);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4);
|
||||
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5);
|
||||
|
||||
static struct clk_smd_rpm *msm8996_clks[] = {
|
||||
[RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk,
|
||||
[RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk,
|
||||
[RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk,
|
||||
[RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk,
|
||||
[RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk,
|
||||
[RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk,
|
||||
[RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk,
|
||||
[RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk,
|
||||
[RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk,
|
||||
[RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk,
|
||||
[RPM_SMD_IPA_CLK] = &msm8996_ipa_clk,
|
||||
[RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk,
|
||||
[RPM_SMD_CE1_CLK] = &msm8996_ce1_clk,
|
||||
[RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk,
|
||||
[RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk,
|
||||
[RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk,
|
||||
[RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk,
|
||||
[RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk,
|
||||
[RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk,
|
||||
[RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk,
|
||||
[RPM_SMD_BB_CLK1] = &msm8996_bb_clk1,
|
||||
[RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a,
|
||||
[RPM_SMD_BB_CLK2] = &msm8996_bb_clk2,
|
||||
[RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a,
|
||||
[RPM_SMD_RF_CLK1] = &msm8996_rf_clk1,
|
||||
[RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a,
|
||||
[RPM_SMD_RF_CLK2] = &msm8996_rf_clk2,
|
||||
[RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a,
|
||||
[RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk,
|
||||
[RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk,
|
||||
[RPM_SMD_DIV_CLK1] = &msm8996_div_clk1,
|
||||
[RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a,
|
||||
[RPM_SMD_DIV_CLK2] = &msm8996_div_clk2,
|
||||
[RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a,
|
||||
[RPM_SMD_DIV_CLK3] = &msm8996_div_clk3,
|
||||
[RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a,
|
||||
[RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin,
|
||||
[RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin,
|
||||
[RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin,
|
||||
[RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin,
|
||||
[RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin,
|
||||
[RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin,
|
||||
[RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin,
|
||||
[RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin,
|
||||
};
|
||||
|
||||
static const struct rpm_smd_clk_desc rpm_clk_msm8996 = {
|
||||
.clks = msm8996_clks,
|
||||
.num_clks = ARRAY_SIZE(msm8996_clks),
|
||||
};
|
||||
|
||||
static const struct of_device_id rpm_smd_clk_match_table[] = {
|
||||
{ .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
|
||||
{ .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 },
|
||||
{ .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
|
||||
|
|
|
|||
|
|
@ -111,16 +111,6 @@ qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode);
|
||||
|
||||
static void qcom_cc_del_clk_provider(void *data)
|
||||
{
|
||||
of_clk_del_provider(data);
|
||||
}
|
||||
|
||||
static void qcom_cc_reset_unregister(void *data)
|
||||
{
|
||||
reset_controller_unregister(data);
|
||||
}
|
||||
|
||||
static void qcom_cc_gdsc_unregister(void *data)
|
||||
{
|
||||
gdsc_unregister(data);
|
||||
|
|
@ -143,8 +133,10 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path,
|
|||
int ret;
|
||||
|
||||
clocks_node = of_find_node_by_path("/clocks");
|
||||
if (clocks_node)
|
||||
node = of_find_node_by_name(clocks_node, path);
|
||||
if (clocks_node) {
|
||||
node = of_get_child_by_name(clocks_node, path);
|
||||
of_node_put(clocks_node);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
|
||||
|
|
@ -248,13 +240,7 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(dev->of_node, qcom_cc_clk_hw_get, cc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, qcom_cc_del_clk_provider,
|
||||
pdev->dev.of_node);
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -266,13 +252,7 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
|||
reset->regmap = regmap;
|
||||
reset->reset_map = desc->resets;
|
||||
|
||||
ret = reset_controller_register(&reset->rcdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, qcom_cc_reset_unregister,
|
||||
&reset->rcdev);
|
||||
|
||||
ret = devm_reset_controller_register(dev, &reset->rcdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ config CLK_RENESAS
|
|||
select CLK_R8A7794 if ARCH_R8A7794
|
||||
select CLK_R8A7795 if ARCH_R8A7795
|
||||
select CLK_R8A7796 if ARCH_R8A7796
|
||||
select CLK_R8A77970 if ARCH_R8A77970
|
||||
select CLK_R8A77995 if ARCH_R8A77995
|
||||
select CLK_SH73A0 if ARCH_SH73A0
|
||||
|
||||
|
|
@ -95,6 +96,10 @@ config CLK_R8A7796
|
|||
bool "R-Car M3-W clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_GEN3_CPG
|
||||
|
||||
config CLK_R8A77970
|
||||
bool "R-Car V3M clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_GEN3_CPG
|
||||
|
||||
config CLK_R8A77995
|
||||
bool "R-Car D3 clock support" if COMPILE_TEST
|
||||
select CLK_RCAR_GEN3_CPG
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o
|
|||
obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o
|
||||
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk-div6.h"
|
||||
|
|
@ -32,6 +34,7 @@
|
|||
* @src_shift: Shift to access the register bits to select the parent clock
|
||||
* @src_width: Number of register bits to select the parent clock (may be 0)
|
||||
* @parents: Array to map from valid parent clocks indices to hardware indices
|
||||
* @nb: Notifier block to save/restore clock state for system resume
|
||||
*/
|
||||
struct div6_clock {
|
||||
struct clk_hw hw;
|
||||
|
|
@ -40,6 +43,7 @@ struct div6_clock {
|
|||
u32 src_shift;
|
||||
u32 src_width;
|
||||
u8 *parents;
|
||||
struct notifier_block nb;
|
||||
};
|
||||
|
||||
#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)
|
||||
|
|
@ -176,6 +180,29 @@ static const struct clk_ops cpg_div6_clock_ops = {
|
|||
.set_rate = cpg_div6_clock_set_rate,
|
||||
};
|
||||
|
||||
static int cpg_div6_clock_notifier_call(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct div6_clock *clock = container_of(nb, struct div6_clock, nb);
|
||||
|
||||
switch (action) {
|
||||
case PM_EVENT_RESUME:
|
||||
/*
|
||||
* TODO: This does not yet support DIV6 clocks with multiple
|
||||
* parents, as the parent selection bits are not restored.
|
||||
* Fortunately so far such DIV6 clocks are found only on
|
||||
* R/SH-Mobile SoCs, while the resume functionality is only
|
||||
* needed on R-Car Gen3.
|
||||
*/
|
||||
if (__clk_get_enable_count(clock->hw.clk))
|
||||
cpg_div6_clock_enable(&clock->hw);
|
||||
else
|
||||
cpg_div6_clock_disable(&clock->hw);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpg_div6_register - Register a DIV6 clock
|
||||
|
|
@ -183,11 +210,13 @@ static const struct clk_ops cpg_div6_clock_ops = {
|
|||
* @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8)
|
||||
* @parent_names: Array containing the names of the parent clocks
|
||||
* @reg: Mapped register used to control the DIV6 clock
|
||||
* @notifiers: Optional notifier chain to save/restore state for system resume
|
||||
*/
|
||||
struct clk * __init cpg_div6_register(const char *name,
|
||||
unsigned int num_parents,
|
||||
const char **parent_names,
|
||||
void __iomem *reg)
|
||||
void __iomem *reg,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
unsigned int valid_parents;
|
||||
struct clk_init_data init;
|
||||
|
|
@ -258,6 +287,11 @@ struct clk * __init cpg_div6_register(const char *name,
|
|||
if (IS_ERR(clk))
|
||||
goto free_parents;
|
||||
|
||||
if (notifiers) {
|
||||
clock->nb.notifier_call = cpg_div6_clock_notifier_call;
|
||||
raw_notifier_chain_register(notifiers, &clock->nb);
|
||||
}
|
||||
|
||||
return clk;
|
||||
|
||||
free_parents:
|
||||
|
|
@ -301,7 +335,7 @@ static void __init cpg_div6_clock_init(struct device_node *np)
|
|||
for (i = 0; i < num_parents; i++)
|
||||
parent_names[i] = of_clk_get_parent_name(np, i);
|
||||
|
||||
clk = cpg_div6_register(clk_name, num_parents, parent_names, reg);
|
||||
clk = cpg_div6_register(clk_name, num_parents, parent_names, reg, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register %s DIV6 clock (%ld)\n",
|
||||
__func__, np->name, PTR_ERR(clk));
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#define __RENESAS_CLK_DIV6_H__
|
||||
|
||||
struct clk *cpg_div6_register(const char *name, unsigned int num_parents,
|
||||
const char **parent_names, void __iomem *reg);
|
||||
const char **parent_names, void __iomem *reg,
|
||||
struct raw_notifier_head *notifiers);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -156,10 +156,8 @@ static struct clk * __init cpg_mstp_clock_register(const char *name,
|
|||
struct clk *clk;
|
||||
|
||||
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
|
||||
if (!clock) {
|
||||
pr_err("%s: failed to allocate MSTP clock.\n", __func__);
|
||||
if (!clock)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_mstp_clock_ops;
|
||||
|
|
@ -196,7 +194,6 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
|
|||
if (group == NULL || clks == NULL) {
|
||||
kfree(group);
|
||||
kfree(clks);
|
||||
pr_err("%s: failed to allocate group\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -423,7 +423,6 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
|
|||
/* We're leaking memory on purpose, there's no point in cleaning
|
||||
* up as the system won't boot anyway.
|
||||
*/
|
||||
pr_err("%s: failed to allocate cpg\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* rz Core CPG Clocks
|
||||
* RZ/A1 Core CPG Clocks
|
||||
*
|
||||
* Copyright (C) 2013 Ideas On Board SPRL
|
||||
* Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
|
|||
DEF_MOD("scif2", 719, R8A7745_CLK_P),
|
||||
DEF_MOD("scif1", 720, R8A7745_CLK_P),
|
||||
DEF_MOD("scif0", 721, R8A7745_CLK_P),
|
||||
DEF_MOD("du1", 723, R8A7745_CLK_ZX),
|
||||
DEF_MOD("du0", 724, R8A7745_CLK_ZX),
|
||||
DEF_MOD("ipmmu-sgx", 800, R8A7745_CLK_ZX),
|
||||
DEF_MOD("vin1", 810, R8A7745_CLK_ZG),
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
|
|||
DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("rwdt", 402, R8A7795_CLK_R),
|
||||
DEF_MOD("intc-ex", 407, R8A7795_CLK_CP),
|
||||
DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("intc-ap", 408, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("drif7", 508, R8A7795_CLK_S3D2),
|
||||
|
|
@ -348,6 +348,7 @@ static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
|
|||
{ MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */
|
||||
{ MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */
|
||||
{ MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */
|
||||
{ MOD_CLK_ID(408), R8A7795_CLK_S3D1 }, /* INTC-AP */
|
||||
{ MOD_CLK_ID(501), R8A7795_CLK_S3D1 }, /* AUDMAC1 */
|
||||
{ MOD_CLK_ID(502), R8A7795_CLK_S3D1 }, /* AUDMAC0 */
|
||||
{ MOD_CLK_ID(523), R8A7795_CLK_S3D4 }, /* PWM */
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
|
|||
DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1),
|
||||
DEF_MOD("rwdt", 402, R8A7796_CLK_R),
|
||||
DEF_MOD("intc-ex", 407, R8A7796_CLK_CP),
|
||||
DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1),
|
||||
DEF_MOD("intc-ap", 408, R8A7796_CLK_S0D3),
|
||||
DEF_MOD("audmac1", 501, R8A7796_CLK_S0D3),
|
||||
DEF_MOD("audmac0", 502, R8A7796_CLK_S0D3),
|
||||
DEF_MOD("drif7", 508, R8A7796_CLK_S3D2),
|
||||
|
|
|
|||
199
drivers/clk/renesas/r8a77970-cpg-mssr.c
Normal file
199
drivers/clk/renesas/r8a77970-cpg-mssr.c
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* r8a77970 Clock Pulse Generator / Module Standby and Software Reset
|
||||
*
|
||||
* Copyright (C) 2017 Cogent Embedded Inc.
|
||||
*
|
||||
* Based on r8a7795-cpg-mssr.c
|
||||
*
|
||||
* Copyright (C) 2015 Glider bvba
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/soc/renesas/rcar-rst.h>
|
||||
|
||||
#include <dt-bindings/clock/r8a77970-cpg-mssr.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
#include "rcar-gen3-cpg.h"
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R8A77970_CLK_OSC,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_EXTAL,
|
||||
CLK_EXTALR,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_MAIN,
|
||||
CLK_PLL0,
|
||||
CLK_PLL1,
|
||||
CLK_PLL3,
|
||||
CLK_PLL1_DIV2,
|
||||
CLK_PLL1_DIV4,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE
|
||||
};
|
||||
|
||||
static const struct cpg_core_clk r8a77970_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
|
||||
DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
|
||||
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
|
||||
DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
|
||||
|
||||
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
|
||||
DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
|
||||
DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
|
||||
DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED("zx", R8A77970_CLK_ZX, CLK_PLL1_DIV2, 3, 1),
|
||||
DEF_FIXED("s1d1", R8A77970_CLK_S1D1, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED("s1d2", R8A77970_CLK_S1D2, CLK_PLL1_DIV2, 8, 1),
|
||||
DEF_FIXED("s1d4", R8A77970_CLK_S1D4, CLK_PLL1_DIV2, 16, 1),
|
||||
DEF_FIXED("s2d1", R8A77970_CLK_S2D1, CLK_PLL1_DIV2, 6, 1),
|
||||
DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1),
|
||||
DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1),
|
||||
|
||||
DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
||||
DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
|
||||
DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014),
|
||||
DEF_DIV6P1("csi0", R8A77970_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
|
||||
|
||||
DEF_FIXED("osc", R8A77970_CLK_OSC, CLK_PLL1_DIV2, 12*1024, 1),
|
||||
DEF_FIXED("r", R8A77970_CLK_R, CLK_EXTALR, 1, 1),
|
||||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = {
|
||||
DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("scif4", 203, R8A77970_CLK_S2D4),
|
||||
DEF_MOD("scif3", 204, R8A77970_CLK_S2D4),
|
||||
DEF_MOD("scif1", 206, R8A77970_CLK_S2D4),
|
||||
DEF_MOD("scif0", 207, R8A77970_CLK_S2D4),
|
||||
DEF_MOD("msiof3", 208, R8A77970_CLK_MSO),
|
||||
DEF_MOD("msiof2", 209, R8A77970_CLK_MSO),
|
||||
DEF_MOD("msiof1", 210, R8A77970_CLK_MSO),
|
||||
DEF_MOD("msiof0", 211, R8A77970_CLK_MSO),
|
||||
DEF_MOD("mfis", 213, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("rwdt", 402, R8A77970_CLK_R),
|
||||
DEF_MOD("intc-ex", 407, R8A77970_CLK_CP),
|
||||
DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("hscif0", 520, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("thermal", 522, R8A77970_CLK_CP),
|
||||
DEF_MOD("pwm", 523, R8A77970_CLK_S2D4),
|
||||
DEF_MOD("fcpvd0", 603, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("vspd0", 623, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("csi40", 716, R8A77970_CLK_CSI0),
|
||||
DEF_MOD("du0", 724, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("vin3", 808, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("vin2", 809, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("vin1", 810, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("vin0", 811, R8A77970_CLK_S2D1),
|
||||
DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("gpio5", 907, R8A77970_CLK_CP),
|
||||
DEF_MOD("gpio4", 908, R8A77970_CLK_CP),
|
||||
DEF_MOD("gpio3", 909, R8A77970_CLK_CP),
|
||||
DEF_MOD("gpio2", 910, R8A77970_CLK_CP),
|
||||
DEF_MOD("gpio1", 911, R8A77970_CLK_CP),
|
||||
DEF_MOD("gpio0", 912, R8A77970_CLK_CP),
|
||||
DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("i2c1", 930, R8A77970_CLK_S2D2),
|
||||
DEF_MOD("i2c0", 931, R8A77970_CLK_S2D2),
|
||||
};
|
||||
|
||||
static const unsigned int r8a77970_crit_mod_clks[] __initconst = {
|
||||
MOD_CLK_ID(408), /* INTC-AP (GIC) */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* CPG Clock Data
|
||||
*/
|
||||
|
||||
/*
|
||||
* MD EXTAL PLL0 PLL1 PLL3
|
||||
* 14 13 19 (MHz)
|
||||
*-------------------------------------------------
|
||||
* 0 0 0 16.66 x 1 x192 x192 x96
|
||||
* 0 0 1 16.66 x 1 x192 x192 x80
|
||||
* 0 1 0 20 x 1 x160 x160 x80
|
||||
* 0 1 1 20 x 1 x160 x160 x66
|
||||
* 1 0 0 27 / 2 x236 x236 x118
|
||||
* 1 0 1 27 / 2 x236 x236 x98
|
||||
* 1 1 0 33.33 / 2 x192 x192 x96
|
||||
* 1 1 1 33.33 / 2 x192 x192 x80
|
||||
*/
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
|
||||
(((md) & BIT(13)) >> 12) | \
|
||||
(((md) & BIT(19)) >> 19))
|
||||
|
||||
static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = {
|
||||
/* EXTAL div PLL1 mult/div PLL3 mult/div */
|
||||
{ 1, 192, 1, 96, 1, },
|
||||
{ 1, 192, 1, 80, 1, },
|
||||
{ 1, 160, 1, 80, 1, },
|
||||
{ 1, 160, 1, 66, 1, },
|
||||
{ 2, 236, 1, 118, 1, },
|
||||
{ 2, 236, 1, 98, 1, },
|
||||
{ 2, 192, 1, 96, 1, },
|
||||
{ 2, 192, 1, 80, 1, },
|
||||
};
|
||||
|
||||
static int __init r8a77970_cpg_mssr_init(struct device *dev)
|
||||
{
|
||||
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
|
||||
u32 cpg_mode;
|
||||
int error;
|
||||
|
||||
error = rcar_rst_read_mode_pins(&cpg_mode);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
|
||||
|
||||
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
|
||||
}
|
||||
|
||||
const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = {
|
||||
/* Core Clocks */
|
||||
.core_clks = r8a77970_core_clks,
|
||||
.num_core_clks = ARRAY_SIZE(r8a77970_core_clks),
|
||||
.last_dt_core_clk = LAST_DT_CORE_CLK,
|
||||
.num_total_core_clks = MOD_CLK_BASE,
|
||||
|
||||
/* Module Clocks */
|
||||
.mod_clks = r8a77970_mod_clks,
|
||||
.num_mod_clks = ARRAY_SIZE(r8a77970_mod_clks),
|
||||
.num_hw_mod_clks = 12 * 32,
|
||||
|
||||
/* Critical Module Clocks */
|
||||
.crit_mod_clks = r8a77970_crit_mod_clks,
|
||||
.num_crit_mod_clks = ARRAY_SIZE(r8a77970_crit_mod_clks),
|
||||
|
||||
/* Callbacks */
|
||||
.init = r8a77970_cpg_mssr_init,
|
||||
.cpg_clk_register = rcar_gen3_cpg_clk_register,
|
||||
};
|
||||
|
|
@ -127,7 +127,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
|
|||
DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1),
|
||||
DEF_MOD("rwdt", 402, R8A77995_CLK_R),
|
||||
DEF_MOD("intc-ex", 407, R8A77995_CLK_CP),
|
||||
DEF_MOD("intc-ap", 408, R8A77995_CLK_S3D1),
|
||||
DEF_MOD("intc-ap", 408, R8A77995_CLK_S1D2),
|
||||
DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1),
|
||||
DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C),
|
||||
DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C),
|
||||
|
|
|
|||
|
|
@ -262,10 +262,9 @@ static unsigned int cpg_pll0_div __initdata;
|
|||
static u32 cpg_mode __initdata;
|
||||
|
||||
struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct clk **clks,
|
||||
void __iomem *base)
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
const struct clk_div_table *table = NULL;
|
||||
const struct clk *parent;
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ struct rcar_gen2_cpg_pll_config {
|
|||
};
|
||||
|
||||
struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base);
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers);
|
||||
int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
|
||||
unsigned int pll0_div, u32 mode);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
|
|
@ -29,6 +30,36 @@
|
|||
#define CPG_PLL2CR 0x002c
|
||||
#define CPG_PLL4CR 0x01f4
|
||||
|
||||
struct cpg_simple_notifier {
|
||||
struct notifier_block nb;
|
||||
void __iomem *reg;
|
||||
u32 saved;
|
||||
};
|
||||
|
||||
static int cpg_simple_notifier_call(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct cpg_simple_notifier *csn =
|
||||
container_of(nb, struct cpg_simple_notifier, nb);
|
||||
|
||||
switch (action) {
|
||||
case PM_EVENT_SUSPEND:
|
||||
csn->saved = readl(csn->reg);
|
||||
return NOTIFY_OK;
|
||||
|
||||
case PM_EVENT_RESUME:
|
||||
writel(csn->saved, csn->reg);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
|
||||
struct cpg_simple_notifier *csn)
|
||||
{
|
||||
csn->nb.notifier_call = cpg_simple_notifier_call;
|
||||
raw_notifier_chain_register(notifiers, &csn->nb);
|
||||
}
|
||||
|
||||
/*
|
||||
* SDn Clock
|
||||
|
|
@ -55,8 +86,8 @@ struct sd_div_table {
|
|||
|
||||
struct sd_clock {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
const struct sd_div_table *div_table;
|
||||
struct cpg_simple_notifier csn;
|
||||
unsigned int div_num;
|
||||
unsigned int div_min;
|
||||
unsigned int div_max;
|
||||
|
|
@ -97,12 +128,12 @@ static const struct sd_div_table cpg_sd_div_table[] = {
|
|||
static int cpg_sd_clock_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
u32 val = readl(clock->reg);
|
||||
u32 val = readl(clock->csn.reg);
|
||||
|
||||
val &= ~(CPG_SD_STP_MASK);
|
||||
val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK;
|
||||
|
||||
writel(val, clock->reg);
|
||||
writel(val, clock->csn.reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -111,14 +142,14 @@ static void cpg_sd_clock_disable(struct clk_hw *hw)
|
|||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
writel(readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
|
||||
writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg);
|
||||
}
|
||||
|
||||
static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_clock *clock = to_sd_clock(hw);
|
||||
|
||||
return !(readl(clock->reg) & CPG_SD_STP_MASK);
|
||||
return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
|
||||
}
|
||||
|
||||
static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
|
||||
|
|
@ -170,10 +201,10 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
|
||||
clock->cur_div_idx = i;
|
||||
|
||||
val = readl(clock->reg);
|
||||
val = readl(clock->csn.reg);
|
||||
val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
|
||||
val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
|
||||
writel(val, clock->reg);
|
||||
writel(val, clock->csn.reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -188,8 +219,8 @@ static const struct clk_ops cpg_sd_clock_ops = {
|
|||
};
|
||||
|
||||
static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
|
||||
void __iomem *base,
|
||||
const char *parent_name)
|
||||
void __iomem *base, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct sd_clock *clock;
|
||||
|
|
@ -207,12 +238,12 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
|
|||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clock->reg = base + core->offset;
|
||||
clock->csn.reg = base + core->offset;
|
||||
clock->hw.init = &init;
|
||||
clock->div_table = cpg_sd_div_table;
|
||||
clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
|
||||
|
||||
sd_fc = readl(clock->reg) & CPG_SD_FC_MASK;
|
||||
sd_fc = readl(clock->csn.reg) & CPG_SD_FC_MASK;
|
||||
for (i = 0; i < clock->div_num; i++)
|
||||
if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
|
||||
break;
|
||||
|
|
@ -233,8 +264,13 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
|
|||
|
||||
clk = clk_register(NULL, &clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(clock);
|
||||
goto free_clock;
|
||||
|
||||
cpg_simple_notifier_register(notifiers, &clock->csn);
|
||||
return clk;
|
||||
|
||||
free_clock:
|
||||
kfree(clock);
|
||||
return clk;
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +301,8 @@ static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
|
|||
|
||||
struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base)
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
const struct clk *parent;
|
||||
unsigned int mult = 1;
|
||||
|
|
@ -331,22 +368,32 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_SD:
|
||||
return cpg_sd_clk_register(core, base, __clk_get_name(parent));
|
||||
return cpg_sd_clk_register(core, base, __clk_get_name(parent),
|
||||
notifiers);
|
||||
|
||||
case CLK_TYPE_GEN3_R:
|
||||
if (cpg_quirks & RCKCR_CKSEL) {
|
||||
struct cpg_simple_notifier *csn;
|
||||
|
||||
csn = kzalloc(sizeof(*csn), GFP_KERNEL);
|
||||
if (!csn)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
csn->reg = base + CPG_RCKCR;
|
||||
|
||||
/*
|
||||
* RINT is default.
|
||||
* Only if EXTALR is populated, we switch to it.
|
||||
*/
|
||||
value = readl(base + CPG_RCKCR) & 0x3f;
|
||||
value = readl(csn->reg) & 0x3f;
|
||||
|
||||
if (clk_get_rate(clks[cpg_clk_extalr])) {
|
||||
parent = clks[cpg_clk_extalr];
|
||||
value |= BIT(15);
|
||||
}
|
||||
|
||||
writel(value, base + CPG_RCKCR);
|
||||
writel(value, csn->reg);
|
||||
cpg_simple_notifier_register(notifiers, csn);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ struct rcar_gen3_cpg_pll_config {
|
|||
|
||||
struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base);
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers);
|
||||
int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
|
||||
unsigned int clk_extalr, u32 mode);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
|
@ -106,6 +107,9 @@ static const u16 srcr[] = {
|
|||
* @num_core_clks: Number of Core Clocks in clks[]
|
||||
* @num_mod_clks: Number of Module Clocks in clks[]
|
||||
* @last_dt_core_clk: ID of the last Core Clock exported to DT
|
||||
* @notifiers: Notifier chain to save/restore clock state for system resume
|
||||
* @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
|
||||
* @smstpcr_saved[].val: Saved values of SMSTPCR[]
|
||||
*/
|
||||
struct cpg_mssr_priv {
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
|
|
@ -119,6 +123,12 @@ struct cpg_mssr_priv {
|
|||
unsigned int num_core_clks;
|
||||
unsigned int num_mod_clks;
|
||||
unsigned int last_dt_core_clk;
|
||||
|
||||
struct raw_notifier_head notifiers;
|
||||
struct {
|
||||
u32 mask;
|
||||
u32 val;
|
||||
} smstpcr_saved[ARRAY_SIZE(smstpcr)];
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -293,7 +303,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
|||
|
||||
if (core->type == CLK_TYPE_DIV6P1) {
|
||||
clk = cpg_div6_register(core->name, 1, &parent_name,
|
||||
priv->base + core->offset);
|
||||
priv->base + core->offset,
|
||||
&priv->notifiers);
|
||||
} else {
|
||||
clk = clk_register_fixed_factor(NULL, core->name,
|
||||
parent_name, 0,
|
||||
|
|
@ -304,7 +315,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
|||
default:
|
||||
if (info->cpg_clk_register)
|
||||
clk = info->cpg_clk_register(dev, core, info,
|
||||
priv->clks, priv->base);
|
||||
priv->clks, priv->base,
|
||||
&priv->notifiers);
|
||||
else
|
||||
dev_err(dev, "%s has unsupported core clock type %u\n",
|
||||
core->name, core->type);
|
||||
|
|
@ -382,6 +394,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
|
|||
|
||||
dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk);
|
||||
priv->clks[id] = clk;
|
||||
priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32);
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
|
@ -680,6 +693,12 @@ static const struct of_device_id cpg_mssr_match[] = {
|
|||
.data = &r8a7796_cpg_mssr_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CLK_R8A77970
|
||||
{
|
||||
.compatible = "renesas,r8a77970-cpg-mssr",
|
||||
.data = &r8a77970_cpg_mssr_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CLK_R8A77995
|
||||
{
|
||||
.compatible = "renesas,r8a77995-cpg-mssr",
|
||||
|
|
@ -694,6 +713,85 @@ static void cpg_mssr_del_clk_provider(void *data)
|
|||
of_clk_del_provider(data);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
|
||||
static int cpg_mssr_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned int reg;
|
||||
|
||||
/* This is the best we can do to check for the presence of PSCI */
|
||||
if (!psci_ops.cpu_suspend)
|
||||
return 0;
|
||||
|
||||
/* Save module registers with bits under our control */
|
||||
for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
|
||||
if (priv->smstpcr_saved[reg].mask)
|
||||
priv->smstpcr_saved[reg].val =
|
||||
readl(priv->base + SMSTPCR(reg));
|
||||
}
|
||||
|
||||
/* Save core clocks */
|
||||
raw_notifier_call_chain(&priv->notifiers, PM_EVENT_SUSPEND, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_mssr_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned int reg, i;
|
||||
u32 mask, oldval, newval;
|
||||
|
||||
/* This is the best we can do to check for the presence of PSCI */
|
||||
if (!psci_ops.cpu_suspend)
|
||||
return 0;
|
||||
|
||||
/* Restore core clocks */
|
||||
raw_notifier_call_chain(&priv->notifiers, PM_EVENT_RESUME, NULL);
|
||||
|
||||
/* Restore module clocks */
|
||||
for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
|
||||
mask = priv->smstpcr_saved[reg].mask;
|
||||
if (!mask)
|
||||
continue;
|
||||
|
||||
oldval = readl(priv->base + SMSTPCR(reg));
|
||||
newval = oldval & ~mask;
|
||||
newval |= priv->smstpcr_saved[reg].val & mask;
|
||||
if (newval == oldval)
|
||||
continue;
|
||||
|
||||
writel(newval, priv->base + SMSTPCR(reg));
|
||||
|
||||
/* Wait until enabled clocks are really enabled */
|
||||
mask &= ~priv->smstpcr_saved[reg].val;
|
||||
if (!mask)
|
||||
continue;
|
||||
|
||||
for (i = 1000; i > 0; --i) {
|
||||
oldval = readl(priv->base + MSTPSR(reg));
|
||||
if (!(oldval & mask))
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
if (!i)
|
||||
dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n",
|
||||
priv->base + SMSTPCR(reg), oldval & mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops cpg_mssr_pm = {
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cpg_mssr_suspend_noirq,
|
||||
cpg_mssr_resume_noirq)
|
||||
};
|
||||
#define DEV_PM_OPS &cpg_mssr_pm
|
||||
#else
|
||||
#define DEV_PM_OPS NULL
|
||||
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
|
||||
|
||||
static int __init cpg_mssr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
|
@ -729,10 +827,12 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
|
|||
if (!clks)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
priv->clks = clks;
|
||||
priv->num_core_clks = info->num_total_core_clks;
|
||||
priv->num_mod_clks = info->num_hw_mod_clks;
|
||||
priv->last_dt_core_clk = info->last_dt_core_clk;
|
||||
RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);
|
||||
|
||||
for (i = 0; i < nclks; i++)
|
||||
clks[i] = ERR_PTR(-ENOENT);
|
||||
|
|
@ -769,6 +869,7 @@ static struct platform_driver cpg_mssr_driver = {
|
|||
.driver = {
|
||||
.name = "renesas-cpg-mssr",
|
||||
.of_match_table = cpg_mssr_match,
|
||||
.pm = DEV_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ struct cpg_mssr_info {
|
|||
struct clk *(*cpg_clk_register)(struct device *dev,
|
||||
const struct cpg_core_clk *core,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base);
|
||||
struct clk **clks, void __iomem *base,
|
||||
struct raw_notifier_head *notifiers);
|
||||
};
|
||||
|
||||
extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
|
||||
|
|
@ -138,6 +139,7 @@ extern const struct cpg_mssr_info r8a7792_cpg_mssr_info;
|
|||
extern const struct cpg_mssr_info r8a7794_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a77970_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -322,8 +322,6 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
|
|||
sizeof(*rates) * nrates,
|
||||
GFP_KERNEL);
|
||||
if (!cpuclk->rate_table) {
|
||||
pr_err("%s: could not allocate memory for cpuclk rates\n",
|
||||
__func__);
|
||||
ret = -ENOMEM;
|
||||
goto unregister_notifier;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,15 +290,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|||
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,
|
||||
COMPOSITE(ACLK_VEPU, "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,
|
||||
GATE(HCLK_VEPU, "hclk_vepu", "aclk_vepu", 0,
|
||||
RK2928_CLKGATE_CON(3), 10, GFLAGS),
|
||||
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0,
|
||||
COMPOSITE(ACLK_VDPU, "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,
|
||||
GATE(HCLK_VDPU, "hclk_vdpu", "aclk_vdpu", 0,
|
||||
RK2928_CLKGATE_CON(3), 12, GFLAGS),
|
||||
|
||||
GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
|
||||
|
|
@ -644,13 +644,13 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
|
|||
|
||||
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(HCLK_CIF1, "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(ACLK_CIF1, "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),
|
||||
|
|
|
|||
|
|
@ -711,7 +711,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS),
|
||||
GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS),
|
||||
GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS),
|
||||
GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS),
|
||||
GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS),
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o
|
||||
obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o
|
||||
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
|
||||
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
|
||||
|
|
|
|||
|
|
@ -457,8 +457,6 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
|||
|
||||
cpuclk->cfg = kmemdup(cfg, sizeof(*cfg) * num_cfgs, GFP_KERNEL);
|
||||
if (!cpuclk->cfg) {
|
||||
pr_err("%s: could not allocate memory for cpuclk data\n",
|
||||
__func__);
|
||||
ret = -ENOMEM;
|
||||
goto unregister_clk_nb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/syscore_ops.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <dt-bindings/clock/exynos-audss-clk.h>
|
||||
|
||||
|
|
@ -36,14 +37,13 @@ static struct clk *epll;
|
|||
#define ASS_CLK_DIV 0x4
|
||||
#define ASS_CLK_GATE 0x8
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static unsigned long reg_save[][2] = {
|
||||
{ ASS_CLK_SRC, 0 },
|
||||
{ ASS_CLK_DIV, 0 },
|
||||
{ ASS_CLK_GATE, 0 },
|
||||
};
|
||||
|
||||
static int exynos_audss_clk_suspend(struct device *dev)
|
||||
static int __maybe_unused exynos_audss_clk_suspend(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ static int exynos_audss_clk_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_audss_clk_resume(struct device *dev)
|
||||
static int __maybe_unused exynos_audss_clk_resume(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -62,7 +62,6 @@ static int exynos_audss_clk_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
struct exynos_audss_clk_drvdata {
|
||||
unsigned int has_adma_clk:1;
|
||||
|
|
@ -135,6 +134,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
const struct exynos_audss_clk_drvdata *variant;
|
||||
struct clk_hw **clk_table;
|
||||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
int i, ret = 0;
|
||||
|
||||
variant = of_device_get_match_data(&pdev->dev);
|
||||
|
|
@ -142,15 +142,15 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
reg_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(reg_base)) {
|
||||
dev_err(&pdev->dev, "failed to map audss registers\n");
|
||||
dev_err(dev, "failed to map audss registers\n");
|
||||
return PTR_ERR(reg_base);
|
||||
}
|
||||
|
||||
epll = ERR_PTR(-ENODEV);
|
||||
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
clk_data = devm_kzalloc(dev,
|
||||
sizeof(*clk_data) +
|
||||
sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS,
|
||||
GFP_KERNEL);
|
||||
|
|
@ -160,8 +160,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
clk_data->num = variant->num_clks;
|
||||
clk_table = clk_data->hws;
|
||||
|
||||
pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
|
||||
pll_in = devm_clk_get(&pdev->dev, "pll_in");
|
||||
pll_ref = devm_clk_get(dev, "pll_ref");
|
||||
pll_in = devm_clk_get(dev, "pll_in");
|
||||
if (!IS_ERR(pll_ref))
|
||||
mout_audss_p[0] = __clk_get_name(pll_ref);
|
||||
if (!IS_ERR(pll_in)) {
|
||||
|
|
@ -172,88 +172,103 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
|
||||
ret = clk_prepare_enable(epll);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
dev_err(dev,
|
||||
"failed to prepare the epll clock\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss",
|
||||
|
||||
/*
|
||||
* Enable runtime PM here to allow the clock core using runtime PM
|
||||
* for the registered clocks. Additionally, we increase the runtime
|
||||
* PM usage count before registering the clocks, to prevent the
|
||||
* clock core from runtime suspending the device.
|
||||
*/
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(dev, "mout_audss",
|
||||
mout_audss_p, ARRAY_SIZE(mout_audss_p),
|
||||
CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
|
||||
|
||||
cdclk = devm_clk_get(&pdev->dev, "cdclk");
|
||||
sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio");
|
||||
cdclk = devm_clk_get(dev, "cdclk");
|
||||
sclk_audio = devm_clk_get(dev, "sclk_audio");
|
||||
if (!IS_ERR(cdclk))
|
||||
mout_i2s_p[1] = __clk_get_name(cdclk);
|
||||
if (!IS_ERR(sclk_audio))
|
||||
mout_i2s_p[2] = __clk_get_name(sclk_audio);
|
||||
clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(NULL, "mout_i2s",
|
||||
clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(dev, "mout_i2s",
|
||||
mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp",
|
||||
clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(dev, "dout_srp",
|
||||
"mout_audss", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL,
|
||||
clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(dev,
|
||||
"dout_aud_bus", "dout_srp", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s",
|
||||
clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(dev, "dout_i2s",
|
||||
"mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0,
|
||||
&lock);
|
||||
|
||||
clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(NULL, "srp_clk",
|
||||
clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(dev, "srp_clk",
|
||||
"dout_srp", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 0, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(NULL, "i2s_bus",
|
||||
clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(dev, "i2s_bus",
|
||||
"dout_aud_bus", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 2, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(NULL, "sclk_i2s",
|
||||
clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(dev, "sclk_i2s",
|
||||
"dout_i2s", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 3, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(NULL, "pcm_bus",
|
||||
clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(dev, "pcm_bus",
|
||||
"sclk_pcm", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 4, 0, &lock);
|
||||
|
||||
sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in");
|
||||
sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in");
|
||||
if (!IS_ERR(sclk_pcm_in))
|
||||
sclk_pcm_p = __clk_get_name(sclk_pcm_in);
|
||||
clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm",
|
||||
clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(dev, "sclk_pcm",
|
||||
sclk_pcm_p, CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 5, 0, &lock);
|
||||
|
||||
if (variant->has_adma_clk) {
|
||||
clk_table[EXYNOS_ADMA] = clk_hw_register_gate(NULL, "adma",
|
||||
clk_table[EXYNOS_ADMA] = clk_hw_register_gate(dev, "adma",
|
||||
"dout_srp", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 9, 0, &lock);
|
||||
}
|
||||
|
||||
for (i = 0; i < clk_data->num; i++) {
|
||||
if (IS_ERR(clk_table[i])) {
|
||||
dev_err(&pdev->dev, "failed to register clock %d\n", i);
|
||||
dev_err(dev, "failed to register clock %d\n", i);
|
||||
ret = PTR_ERR(clk_table[i]);
|
||||
goto unregister;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
|
||||
ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
clk_data);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add clock provider\n");
|
||||
dev_err(dev, "failed to add clock provider\n");
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
unregister:
|
||||
exynos_audss_clk_teardown();
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
if (!IS_ERR(epll))
|
||||
clk_disable_unprepare(epll);
|
||||
|
|
@ -266,6 +281,7 @@ static int exynos_audss_clk_remove(struct platform_device *pdev)
|
|||
of_clk_del_provider(pdev->dev.of_node);
|
||||
|
||||
exynos_audss_clk_teardown();
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
if (!IS_ERR(epll))
|
||||
clk_disable_unprepare(epll);
|
||||
|
|
@ -274,8 +290,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
static const struct dev_pm_ops exynos_audss_clk_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_audss_clk_suspend,
|
||||
exynos_audss_clk_resume)
|
||||
SET_RUNTIME_PM_OPS(exynos_audss_clk_suspend, exynos_audss_clk_resume,
|
||||
NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver exynos_audss_clk_driver = {
|
||||
|
|
|
|||
|
|
@ -144,8 +144,6 @@ static void __init exynos4_clkout_init(struct device_node *node)
|
|||
}
|
||||
CLK_OF_DECLARE_DRIVER(exynos4210_clkout, "samsung,exynos4210-pmu",
|
||||
exynos4_clkout_init);
|
||||
CLK_OF_DECLARE_DRIVER(exynos4212_clkout, "samsung,exynos4212-pmu",
|
||||
exynos4_clkout_init);
|
||||
CLK_OF_DECLARE_DRIVER(exynos4412_clkout, "samsung,exynos4412-pmu",
|
||||
exynos4_clkout_init);
|
||||
CLK_OF_DECLARE_DRIVER(exynos3250_clkout, "samsung,exynos3250-pmu",
|
||||
|
|
|
|||
|
|
@ -550,9 +550,8 @@ static const struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __
|
|||
|
||||
/* list of mux clocks supported in all exynos4 soc's */
|
||||
static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = {
|
||||
MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0,
|
||||
"mout_apll"),
|
||||
MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
|
||||
MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
|
||||
MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
|
||||
MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
|
||||
|
|
@ -737,7 +736,7 @@ static const struct samsung_div_clock exynos4_div_clks[] __initconst = {
|
|||
DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
|
||||
DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
|
||||
DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
|
||||
DIV(CLK_ARM_CLK, "div_core2", "div_core", DIV_CPU0, 28, 3),
|
||||
DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
|
||||
DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
|
||||
DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
|
||||
DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
|
||||
|
|
@ -837,6 +836,12 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = {
|
|||
DIV(0, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
|
||||
DIV(0, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
|
||||
DIV(0, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
|
||||
DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
|
||||
DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
|
||||
DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
|
||||
};
|
||||
|
||||
static struct samsung_div_clock exynos4x12_isp_div_clks[] = {
|
||||
DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3,
|
||||
CLK_GET_RATE_NOCACHE, 0),
|
||||
DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3,
|
||||
|
|
@ -846,18 +851,10 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = {
|
|||
4, 3, CLK_GET_RATE_NOCACHE, 0),
|
||||
DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
|
||||
8, 3, CLK_GET_RATE_NOCACHE, 0),
|
||||
DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
|
||||
DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
|
||||
DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
|
||||
};
|
||||
|
||||
/* list of gate clocks supported in all exynos4 soc's */
|
||||
static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = {
|
||||
/*
|
||||
* After all Exynos4 based platforms are migrated to use device tree,
|
||||
* the device name and clock alias names specified below for some
|
||||
* of the clocks can be removed.
|
||||
*/
|
||||
GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0),
|
||||
GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0),
|
||||
GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0),
|
||||
|
|
@ -1147,6 +1144,13 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
|
|||
0, 0),
|
||||
GATE(CLK_I2S0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3,
|
||||
0, 0),
|
||||
GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
|
||||
GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
|
||||
GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
|
||||
0),
|
||||
};
|
||||
|
||||
static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = {
|
||||
GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0,
|
||||
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||
GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1,
|
||||
|
|
@ -1199,24 +1203,6 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
|
|||
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||
GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
|
||||
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||
GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
|
||||
GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
|
||||
GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
|
||||
0),
|
||||
};
|
||||
|
||||
static const struct samsung_clock_alias exynos4_aliases[] __initconst = {
|
||||
ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
|
||||
ALIAS(CLK_ARM_CLK, NULL, "armclk"),
|
||||
ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
|
||||
};
|
||||
|
||||
static const struct samsung_clock_alias exynos4210_aliases[] __initconst = {
|
||||
ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
|
||||
};
|
||||
|
||||
static const struct samsung_clock_alias exynos4x12_aliases[] __initconst = {
|
||||
ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1355,14 +1341,14 @@ static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst =
|
|||
};
|
||||
|
||||
static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = {
|
||||
[apll] = PLL_A(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll",
|
||||
APLL_LOCK, APLL_CON0, "fout_apll", NULL),
|
||||
[mpll] = PLL_A(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
|
||||
E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL),
|
||||
[epll] = PLL_A(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
|
||||
EPLL_LOCK, EPLL_CON0, "fout_epll", NULL),
|
||||
[vpll] = PLL_A(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
|
||||
VPLL_LOCK, VPLL_CON0, "fout_vpll", NULL),
|
||||
[apll] = PLL(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll",
|
||||
APLL_LOCK, APLL_CON0, NULL),
|
||||
[mpll] = PLL(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
|
||||
E4210_MPLL_LOCK, E4210_MPLL_CON0, NULL),
|
||||
[epll] = PLL(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
|
||||
EPLL_LOCK, EPLL_CON0, NULL),
|
||||
[vpll] = PLL(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
|
||||
VPLL_LOCK, VPLL_CON0, NULL),
|
||||
};
|
||||
|
||||
static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
|
||||
|
|
@ -1416,24 +1402,6 @@ static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = {
|
|||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct exynos_cpuclk_cfg_data e4212_armclk_d[] __initconst = {
|
||||
{ 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), },
|
||||
{ 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), },
|
||||
{ 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), },
|
||||
{ 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), },
|
||||
{ 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4210_CPU_DIV1(2, 4), },
|
||||
{ 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4210_CPU_DIV1(2, 4), },
|
||||
{ 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
|
||||
{ 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4210_CPU_DIV1(2, 3), },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
#define E4412_CPU_DIV1(cores, hpm, copy) \
|
||||
(((cores) << 8) | ((hpm) << 4) | ((copy) << 0))
|
||||
|
||||
|
|
@ -1527,8 +1495,6 @@ static void __init exynos4_clk_init(struct device_node *np,
|
|||
ARRAY_SIZE(exynos4210_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4210_gate_clks,
|
||||
ARRAY_SIZE(exynos4210_gate_clks));
|
||||
samsung_clk_register_alias(ctx, exynos4210_aliases,
|
||||
ARRAY_SIZE(exynos4210_aliases));
|
||||
samsung_clk_register_fixed_factor(ctx,
|
||||
exynos4210_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4210_fixed_factor_clks));
|
||||
|
|
@ -1537,32 +1503,31 @@ static void __init exynos4_clk_init(struct device_node *np,
|
|||
e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d),
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
|
||||
} else {
|
||||
struct resource res;
|
||||
|
||||
samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
|
||||
ARRAY_SIZE(exynos4x12_mux_clks));
|
||||
samsung_clk_register_div(ctx, exynos4x12_div_clks,
|
||||
ARRAY_SIZE(exynos4x12_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
|
||||
ARRAY_SIZE(exynos4x12_gate_clks));
|
||||
samsung_clk_register_alias(ctx, exynos4x12_aliases,
|
||||
ARRAY_SIZE(exynos4x12_aliases));
|
||||
samsung_clk_register_fixed_factor(ctx,
|
||||
exynos4x12_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos4x12_fixed_factor_clks));
|
||||
if (of_machine_is_compatible("samsung,exynos4412")) {
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
mout_core_p4x12[0], mout_core_p4x12[1], 0x14200,
|
||||
e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d),
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
|
||||
} else {
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
mout_core_p4x12[0], mout_core_p4x12[1], 0x14200,
|
||||
e4212_armclk_d, ARRAY_SIZE(e4212_armclk_d),
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
|
||||
}
|
||||
}
|
||||
|
||||
samsung_clk_register_alias(ctx, exynos4_aliases,
|
||||
ARRAY_SIZE(exynos4_aliases));
|
||||
of_address_to_resource(np, 0, &res);
|
||||
if (resource_size(&res) > 0x18000) {
|
||||
samsung_clk_register_div(ctx, exynos4x12_isp_div_clks,
|
||||
ARRAY_SIZE(exynos4x12_isp_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks,
|
||||
ARRAY_SIZE(exynos4x12_isp_gate_clks));
|
||||
}
|
||||
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
mout_core_p4x12[0], mout_core_p4x12[1], 0x14200,
|
||||
e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d),
|
||||
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
|
||||
}
|
||||
|
||||
if (soc == EXYNOS4X12)
|
||||
exynos4x12_core_down_clock();
|
||||
|
|
|
|||
179
drivers/clk/samsung/clk-exynos4412-isp.c
Normal file
179
drivers/clk/samsung/clk-exynos4412-isp.c
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
|
||||
* Author: Marek Szyprowski <m.szyprowski@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 Exynos4412 ISP module.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/exynos4.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
/* Exynos4x12 specific registers, which belong to ISP power domain */
|
||||
#define E4X12_DIV_ISP0 0x0300
|
||||
#define E4X12_DIV_ISP1 0x0304
|
||||
#define E4X12_GATE_ISP0 0x0800
|
||||
#define E4X12_GATE_ISP1 0x0804
|
||||
|
||||
/*
|
||||
* Support for CMU save/restore across system suspends
|
||||
*/
|
||||
static struct samsung_clk_reg_dump *exynos4x12_save_isp;
|
||||
|
||||
static const unsigned long exynos4x12_clk_isp_save[] __initconst = {
|
||||
E4X12_DIV_ISP0,
|
||||
E4X12_DIV_ISP1,
|
||||
E4X12_GATE_ISP0,
|
||||
E4X12_GATE_ISP1,
|
||||
};
|
||||
|
||||
PNAME(mout_user_aclk400_mcuisp_p4x12) = { "fin_pll", "div_aclk400_mcuisp", };
|
||||
|
||||
static struct samsung_div_clock exynos4x12_isp_div_clks[] = {
|
||||
DIV(CLK_ISP_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3),
|
||||
DIV(CLK_ISP_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3),
|
||||
DIV(CLK_ISP_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp",
|
||||
E4X12_DIV_ISP1, 4, 3),
|
||||
DIV(CLK_ISP_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0",
|
||||
E4X12_DIV_ISP1, 8, 3),
|
||||
DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
|
||||
};
|
||||
|
||||
static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = {
|
||||
GATE(CLK_ISP_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, 0, 0),
|
||||
GATE(CLK_ISP_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, 0, 0),
|
||||
GATE(CLK_ISP_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2, 0, 0),
|
||||
GATE(CLK_ISP_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, 0, 0),
|
||||
GATE(CLK_ISP_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, 0, 0),
|
||||
GATE(CLK_ISP_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, 0, 0),
|
||||
GATE(CLK_ISP_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, 0, 0),
|
||||
GATE(CLK_ISP_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, 0, 0),
|
||||
GATE(CLK_ISP_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, 0, 0),
|
||||
GATE(CLK_ISP_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, 0, 0),
|
||||
GATE(CLK_ISP_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28, 0, 0),
|
||||
GATE(CLK_ISP_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30, 0, 0),
|
||||
GATE(CLK_ISP_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
|
||||
0, 0),
|
||||
GATE(CLK_ISP_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
|
||||
0, 0),
|
||||
};
|
||||
|
||||
static int __maybe_unused exynos4x12_isp_clk_suspend(struct device *dev)
|
||||
{
|
||||
struct samsung_clk_provider *ctx = dev_get_drvdata(dev);
|
||||
|
||||
samsung_clk_save(ctx->reg_base, exynos4x12_save_isp,
|
||||
ARRAY_SIZE(exynos4x12_clk_isp_save));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused exynos4x12_isp_clk_resume(struct device *dev)
|
||||
{
|
||||
struct samsung_clk_provider *ctx = dev_get_drvdata(dev);
|
||||
|
||||
samsung_clk_restore(ctx->reg_base, exynos4x12_save_isp,
|
||||
ARRAY_SIZE(exynos4x12_clk_isp_save));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct resource *res;
|
||||
void __iomem *reg_base;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
reg_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(reg_base)) {
|
||||
dev_err(dev, "failed to map registers\n");
|
||||
return PTR_ERR(reg_base);
|
||||
}
|
||||
|
||||
exynos4x12_save_isp = samsung_clk_alloc_reg_dump(exynos4x12_clk_isp_save,
|
||||
ARRAY_SIZE(exynos4x12_clk_isp_save));
|
||||
if (!exynos4x12_save_isp)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx = samsung_clk_init(np, reg_base, CLK_NR_ISP_CLKS);
|
||||
ctx->dev = dev;
|
||||
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
samsung_clk_register_div(ctx, exynos4x12_isp_div_clks,
|
||||
ARRAY_SIZE(exynos4x12_isp_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks,
|
||||
ARRAY_SIZE(exynos4x12_isp_gate_clks));
|
||||
|
||||
samsung_clk_of_add_provider(np, ctx);
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id exynos4x12_isp_clk_of_match[] = {
|
||||
{ .compatible = "samsung,exynos4412-isp-clock", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct dev_pm_ops exynos4x12_isp_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(exynos4x12_isp_clk_suspend,
|
||||
exynos4x12_isp_clk_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver exynos4x12_isp_clk_driver __refdata = {
|
||||
.driver = {
|
||||
.name = "exynos4x12-isp-clk",
|
||||
.of_match_table = exynos4x12_isp_clk_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &exynos4x12_isp_pm_ops,
|
||||
},
|
||||
.probe = exynos4x12_isp_clk_probe,
|
||||
};
|
||||
|
||||
static int __init exynos4x12_isp_clk_init(void)
|
||||
{
|
||||
return platform_driver_register(&exynos4x12_isp_clk_driver);
|
||||
}
|
||||
core_initcall(exynos4x12_isp_clk_init);
|
||||
|
|
@ -293,14 +293,14 @@ static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = {
|
|||
/*
|
||||
* CMU_CPU
|
||||
*/
|
||||
MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT, 0, "mout_apll"),
|
||||
MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
|
||||
MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT, 0),
|
||||
MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
|
||||
|
||||
/*
|
||||
* CMU_CORE
|
||||
*/
|
||||
MUX_A(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"),
|
||||
MUX(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1),
|
||||
|
||||
/*
|
||||
* CMU_TOP
|
||||
|
|
@ -391,7 +391,7 @@ static const struct samsung_div_clock exynos5250_div_clks[] __initconst = {
|
|||
*/
|
||||
DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
|
||||
DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
|
||||
DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
|
||||
DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
|
||||
|
||||
/*
|
||||
* CMU_TOP
|
||||
|
|
@ -743,10 +743,10 @@ static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = {
|
|||
};
|
||||
|
||||
static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
|
||||
[apll] = PLL_A(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
|
||||
APLL_LOCK, APLL_CON0, "fout_apll", NULL),
|
||||
[mpll] = PLL_A(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
|
||||
MPLL_LOCK, MPLL_CON0, "fout_mpll", NULL),
|
||||
[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
|
||||
APLL_CON0, NULL),
|
||||
[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
|
||||
MPLL_CON0, NULL),
|
||||
[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
|
||||
BPLL_CON0, NULL),
|
||||
[gpll] = PLL(pll_35xx, CLK_FOUT_GPLL, "fout_gpll", "fin_pll", GPLL_LOCK,
|
||||
|
|
|
|||
|
|
@ -600,8 +600,7 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
|
|||
TOP_SPARE2, 4, 1),
|
||||
|
||||
MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2),
|
||||
MUX_A(0, "mout_aclk400_mscl", mout_group1_p,
|
||||
SRC_TOP0, 4, 2, "aclk400_mscl"),
|
||||
MUX(0, "mout_aclk400_mscl", mout_group1_p, SRC_TOP0, 4, 2),
|
||||
MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2),
|
||||
MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2),
|
||||
|
||||
|
|
@ -998,7 +997,7 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
|
|||
GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
|
||||
GATE_BUS_TOP, 16, 0, 0),
|
||||
GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl",
|
||||
GATE_BUS_TOP, 17, 0, 0),
|
||||
GATE_BUS_TOP, 17, CLK_IS_CRITICAL, 0),
|
||||
GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1",
|
||||
GATE_BUS_TOP, 18, CLK_IS_CRITICAL, 0),
|
||||
GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24",
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@
|
|||
* Common Clock Framework support for Exynos5433 SoC.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <dt-bindings/clock/exynos5433.h>
|
||||
|
||||
|
|
@ -1991,6 +1995,14 @@ static const unsigned long fsys_clk_regs[] __initconst = {
|
|||
ENABLE_IP_FSYS1,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump fsys_suspend_regs[] = {
|
||||
{ MUX_SEL_FSYS0, 0 },
|
||||
{ MUX_SEL_FSYS1, 0 },
|
||||
{ MUX_SEL_FSYS2, 0 },
|
||||
{ MUX_SEL_FSYS3, 0 },
|
||||
{ MUX_SEL_FSYS4, 0 },
|
||||
};
|
||||
|
||||
static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = {
|
||||
/* PHY clocks from USBDRD30_PHY */
|
||||
FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY,
|
||||
|
|
@ -2296,16 +2308,11 @@ static const struct samsung_cmu_info fsys_cmu_info __initconst = {
|
|||
.nr_clk_ids = FSYS_NR_CLK,
|
||||
.clk_regs = fsys_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs),
|
||||
.suspend_regs = fsys_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(fsys_suspend_regs),
|
||||
.clk_name = "aclk_fsys_200",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_fsys_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &fsys_cmu_info);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys",
|
||||
exynos5433_cmu_fsys_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_G2D
|
||||
*/
|
||||
|
|
@ -2335,6 +2342,10 @@ static const unsigned long g2d_clk_regs[] __initconst = {
|
|||
DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump g2d_suspend_regs[] = {
|
||||
{ MUX_SEL_G2D0, 0 },
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(mout_aclk_g2d_266_user_p) = { "oscclk", "aclk_g2d_266", };
|
||||
PNAME(mout_aclk_g2d_400_user_p) = { "oscclk", "aclk_g2d_400", };
|
||||
|
|
@ -2420,16 +2431,11 @@ static const struct samsung_cmu_info g2d_cmu_info __initconst = {
|
|||
.nr_clk_ids = G2D_NR_CLK,
|
||||
.clk_regs = g2d_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs),
|
||||
.suspend_regs = g2d_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(g2d_suspend_regs),
|
||||
.clk_name = "aclk_g2d_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_g2d_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &g2d_cmu_info);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d",
|
||||
exynos5433_cmu_g2d_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_DISP
|
||||
*/
|
||||
|
|
@ -2494,6 +2500,18 @@ static const unsigned long disp_clk_regs[] __initconst = {
|
|||
CLKOUT_CMU_DISP_DIV_STAT,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump disp_suspend_regs[] = {
|
||||
/* PLL has to be enabled for suspend */
|
||||
{ DISP_PLL_CON0, 0x85f40502 },
|
||||
/* ignore status of external PHY muxes during suspend to avoid hangs */
|
||||
{ MUX_IGNORE_DISP2, 0x00111111 },
|
||||
{ MUX_SEL_DISP0, 0 },
|
||||
{ MUX_SEL_DISP1, 0 },
|
||||
{ MUX_SEL_DISP2, 0 },
|
||||
{ MUX_SEL_DISP3, 0 },
|
||||
{ MUX_SEL_DISP4, 0 },
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(mout_disp_pll_p) = { "oscclk", "fout_disp_pll", };
|
||||
PNAME(mout_sclk_dsim1_user_p) = { "oscclk", "sclk_dsim1_disp", };
|
||||
|
|
@ -2841,16 +2859,11 @@ static const struct samsung_cmu_info disp_cmu_info __initconst = {
|
|||
.nr_clk_ids = DISP_NR_CLK,
|
||||
.clk_regs = disp_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(disp_clk_regs),
|
||||
.suspend_regs = disp_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(disp_suspend_regs),
|
||||
.clk_name = "aclk_disp_333",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_disp_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &disp_cmu_info);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp",
|
||||
exynos5433_cmu_disp_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_AUD
|
||||
*/
|
||||
|
|
@ -2885,6 +2898,11 @@ static const unsigned long aud_clk_regs[] __initconst = {
|
|||
ENABLE_IP_AUD1,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump aud_suspend_regs[] = {
|
||||
{ MUX_SEL_AUD0, 0 },
|
||||
{ MUX_SEL_AUD1, 0 },
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", };
|
||||
PNAME(mout_sclk_aud_pcm_p) = { "mout_aud_pll_user", "ioclk_audiocdclk0",};
|
||||
|
|
@ -3011,16 +3029,11 @@ static const struct samsung_cmu_info aud_cmu_info __initconst = {
|
|||
.nr_clk_ids = AUD_NR_CLK,
|
||||
.clk_regs = aud_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(aud_clk_regs),
|
||||
.suspend_regs = aud_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(aud_suspend_regs),
|
||||
.clk_name = "fout_aud_pll",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_aud_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &aud_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud",
|
||||
exynos5433_cmu_aud_init);
|
||||
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_BUS{0|1|2}
|
||||
*/
|
||||
|
|
@ -3222,6 +3235,10 @@ static const unsigned long g3d_clk_regs[] __initconst = {
|
|||
CLK_STOPCTRL,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump g3d_suspend_regs[] = {
|
||||
{ MUX_SEL_G3D, 0 },
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", };
|
||||
PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", };
|
||||
|
|
@ -3295,15 +3312,11 @@ static const struct samsung_cmu_info g3d_cmu_info __initconst = {
|
|||
.nr_clk_ids = G3D_NR_CLK,
|
||||
.clk_regs = g3d_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs),
|
||||
.suspend_regs = g3d_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(g3d_suspend_regs),
|
||||
.clk_name = "aclk_g3d_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_g3d_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &g3d_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d",
|
||||
exynos5433_cmu_g3d_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_GSCL
|
||||
*/
|
||||
|
|
@ -3342,6 +3355,12 @@ static const unsigned long gscl_clk_regs[] __initconst = {
|
|||
ENABLE_IP_GSCL_SECURE_SMMU_GSCL2,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump gscl_suspend_regs[] = {
|
||||
{ MUX_SEL_GSCL, 0 },
|
||||
{ ENABLE_ACLK_GSCL, 0xfff },
|
||||
{ ENABLE_PCLK_GSCL, 0xff },
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(aclk_gscl_111_user_p) = { "oscclk", "aclk_gscl_111", };
|
||||
PNAME(aclk_gscl_333_user_p) = { "oscclk", "aclk_gscl_333", };
|
||||
|
|
@ -3436,15 +3455,11 @@ static const struct samsung_cmu_info gscl_cmu_info __initconst = {
|
|||
.nr_clk_ids = GSCL_NR_CLK,
|
||||
.clk_regs = gscl_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs),
|
||||
.suspend_regs = gscl_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(gscl_suspend_regs),
|
||||
.clk_name = "aclk_gscl_111",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_gscl_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &gscl_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl",
|
||||
exynos5433_cmu_gscl_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_APOLLO
|
||||
*/
|
||||
|
|
@ -3970,6 +3985,11 @@ static const unsigned long mscl_clk_regs[] __initconst = {
|
|||
ENABLE_IP_MSCL_SECURE_SMMU_JPEG,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump mscl_suspend_regs[] = {
|
||||
{ MUX_SEL_MSCL0, 0 },
|
||||
{ MUX_SEL_MSCL1, 0 },
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(mout_sclk_jpeg_user_p) = { "oscclk", "sclk_jpeg_mscl", };
|
||||
PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", };
|
||||
|
|
@ -4082,15 +4102,11 @@ static const struct samsung_cmu_info mscl_cmu_info __initconst = {
|
|||
.nr_clk_ids = MSCL_NR_CLK,
|
||||
.clk_regs = mscl_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(mscl_clk_regs),
|
||||
.suspend_regs = mscl_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(mscl_suspend_regs),
|
||||
.clk_name = "aclk_mscl_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_mscl_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &mscl_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl",
|
||||
exynos5433_cmu_mscl_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_MFC
|
||||
*/
|
||||
|
|
@ -4120,6 +4136,10 @@ static const unsigned long mfc_clk_regs[] __initconst = {
|
|||
ENABLE_IP_MFC_SECURE_SMMU_MFC,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump mfc_suspend_regs[] = {
|
||||
{ MUX_SEL_MFC, 0 },
|
||||
};
|
||||
|
||||
PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", };
|
||||
|
||||
static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
|
||||
|
|
@ -4190,15 +4210,11 @@ static const struct samsung_cmu_info mfc_cmu_info __initconst = {
|
|||
.nr_clk_ids = MFC_NR_CLK,
|
||||
.clk_regs = mfc_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs),
|
||||
.suspend_regs = mfc_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(mfc_suspend_regs),
|
||||
.clk_name = "aclk_mfc_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_mfc_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &mfc_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc",
|
||||
exynos5433_cmu_mfc_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_HEVC
|
||||
*/
|
||||
|
|
@ -4228,6 +4244,10 @@ static const unsigned long hevc_clk_regs[] __initconst = {
|
|||
ENABLE_IP_HEVC_SECURE_SMMU_HEVC,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump hevc_suspend_regs[] = {
|
||||
{ MUX_SEL_HEVC, 0 },
|
||||
};
|
||||
|
||||
PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", };
|
||||
|
||||
static const struct samsung_mux_clock hevc_mux_clks[] __initconst = {
|
||||
|
|
@ -4300,15 +4320,11 @@ static const struct samsung_cmu_info hevc_cmu_info __initconst = {
|
|||
.nr_clk_ids = HEVC_NR_CLK,
|
||||
.clk_regs = hevc_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(hevc_clk_regs),
|
||||
.suspend_regs = hevc_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(hevc_suspend_regs),
|
||||
.clk_name = "aclk_hevc_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_hevc_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &hevc_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc",
|
||||
exynos5433_cmu_hevc_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_ISP
|
||||
*/
|
||||
|
|
@ -4342,6 +4358,10 @@ static const unsigned long isp_clk_regs[] __initconst = {
|
|||
ENABLE_IP_ISP3,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump isp_suspend_regs[] = {
|
||||
{ MUX_SEL_ISP, 0 },
|
||||
};
|
||||
|
||||
PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", };
|
||||
PNAME(mout_aclk_isp_400_user_p) = { "oscclk", "aclk_isp_400", };
|
||||
|
||||
|
|
@ -4553,15 +4573,11 @@ static const struct samsung_cmu_info isp_cmu_info __initconst = {
|
|||
.nr_clk_ids = ISP_NR_CLK,
|
||||
.clk_regs = isp_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(isp_clk_regs),
|
||||
.suspend_regs = isp_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(isp_suspend_regs),
|
||||
.clk_name = "aclk_isp_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_isp_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &isp_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp",
|
||||
exynos5433_cmu_isp_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_CAM0
|
||||
*/
|
||||
|
|
@ -4625,6 +4641,15 @@ static const unsigned long cam0_clk_regs[] __initconst = {
|
|||
ENABLE_IP_CAM02,
|
||||
ENABLE_IP_CAM03,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump cam0_suspend_regs[] = {
|
||||
{ MUX_SEL_CAM00, 0 },
|
||||
{ MUX_SEL_CAM01, 0 },
|
||||
{ MUX_SEL_CAM02, 0 },
|
||||
{ MUX_SEL_CAM03, 0 },
|
||||
{ MUX_SEL_CAM04, 0 },
|
||||
};
|
||||
|
||||
PNAME(mout_aclk_cam0_333_user_p) = { "oscclk", "aclk_cam0_333", };
|
||||
PNAME(mout_aclk_cam0_400_user_p) = { "oscclk", "aclk_cam0_400", };
|
||||
PNAME(mout_aclk_cam0_552_user_p) = { "oscclk", "aclk_cam0_552", };
|
||||
|
|
@ -5030,15 +5055,11 @@ static const struct samsung_cmu_info cam0_cmu_info __initconst = {
|
|||
.nr_clk_ids = CAM0_NR_CLK,
|
||||
.clk_regs = cam0_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(cam0_clk_regs),
|
||||
.suspend_regs = cam0_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(cam0_suspend_regs),
|
||||
.clk_name = "aclk_cam0_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_cam0_init(struct device_node *np)
|
||||
{
|
||||
samsung_cmu_register_one(np, &cam0_cmu_info);
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0",
|
||||
exynos5433_cmu_cam0_init);
|
||||
|
||||
/*
|
||||
* Register offset definitions for CMU_CAM1
|
||||
*/
|
||||
|
|
@ -5085,6 +5106,12 @@ static const unsigned long cam1_clk_regs[] __initconst = {
|
|||
ENABLE_IP_CAM12,
|
||||
};
|
||||
|
||||
static const struct samsung_clk_reg_dump cam1_suspend_regs[] = {
|
||||
{ MUX_SEL_CAM10, 0 },
|
||||
{ MUX_SEL_CAM11, 0 },
|
||||
{ MUX_SEL_CAM12, 0 },
|
||||
};
|
||||
|
||||
PNAME(mout_sclk_isp_uart_user_p) = { "oscclk", "sclk_isp_uart_cam1", };
|
||||
PNAME(mout_sclk_isp_spi1_user_p) = { "oscclk", "sclk_isp_spi1_cam1", };
|
||||
PNAME(mout_sclk_isp_spi0_user_p) = { "oscclk", "sclk_isp_spi0_cam1", };
|
||||
|
|
@ -5403,11 +5430,223 @@ static const struct samsung_cmu_info cam1_cmu_info __initconst = {
|
|||
.nr_clk_ids = CAM1_NR_CLK,
|
||||
.clk_regs = cam1_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(cam1_clk_regs),
|
||||
.suspend_regs = cam1_suspend_regs,
|
||||
.nr_suspend_regs = ARRAY_SIZE(cam1_suspend_regs),
|
||||
.clk_name = "aclk_cam1_400",
|
||||
};
|
||||
|
||||
static void __init exynos5433_cmu_cam1_init(struct device_node *np)
|
||||
|
||||
struct exynos5433_cmu_data {
|
||||
struct samsung_clk_reg_dump *clk_save;
|
||||
unsigned int nr_clk_save;
|
||||
const struct samsung_clk_reg_dump *clk_suspend;
|
||||
unsigned int nr_clk_suspend;
|
||||
|
||||
struct clk *clk;
|
||||
struct clk **pclks;
|
||||
int nr_pclks;
|
||||
|
||||
/* must be the last entry */
|
||||
struct samsung_clk_provider ctx;
|
||||
};
|
||||
|
||||
static int __maybe_unused exynos5433_cmu_suspend(struct device *dev)
|
||||
{
|
||||
samsung_cmu_register_one(np, &cam1_cmu_info);
|
||||
struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
samsung_clk_save(data->ctx.reg_base, data->clk_save,
|
||||
data->nr_clk_save);
|
||||
|
||||
for (i = 0; i < data->nr_pclks; i++)
|
||||
clk_prepare_enable(data->pclks[i]);
|
||||
|
||||
/* for suspend some registers have to be set to certain values */
|
||||
samsung_clk_restore(data->ctx.reg_base, data->clk_suspend,
|
||||
data->nr_clk_suspend);
|
||||
|
||||
for (i = 0; i < data->nr_pclks; i++)
|
||||
clk_disable_unprepare(data->pclks[i]);
|
||||
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1",
|
||||
exynos5433_cmu_cam1_init);
|
||||
|
||||
static int __maybe_unused exynos5433_cmu_resume(struct device *dev)
|
||||
{
|
||||
struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
clk_prepare_enable(data->clk);
|
||||
|
||||
for (i = 0; i < data->nr_pclks; i++)
|
||||
clk_prepare_enable(data->pclks[i]);
|
||||
|
||||
samsung_clk_restore(data->ctx.reg_base, data->clk_save,
|
||||
data->nr_clk_save);
|
||||
|
||||
for (i = 0; i < data->nr_pclks; i++)
|
||||
clk_disable_unprepare(data->pclks[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init exynos5433_cmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct samsung_cmu_info *info;
|
||||
struct exynos5433_cmu_data *data;
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
void __iomem *reg_base;
|
||||
int i;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data) +
|
||||
sizeof(*data->ctx.clk_data.hws) * info->nr_clk_ids,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
ctx = &data->ctx;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
reg_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(reg_base)) {
|
||||
dev_err(dev, "failed to map registers\n");
|
||||
return PTR_ERR(reg_base);
|
||||
}
|
||||
|
||||
for (i = 0; i < info->nr_clk_ids; ++i)
|
||||
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
ctx->clk_data.num = info->nr_clk_ids;
|
||||
ctx->reg_base = reg_base;
|
||||
ctx->dev = dev;
|
||||
spin_lock_init(&ctx->lock);
|
||||
|
||||
data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs,
|
||||
info->nr_clk_regs);
|
||||
data->nr_clk_save = info->nr_clk_regs;
|
||||
data->clk_suspend = info->suspend_regs;
|
||||
data->nr_clk_suspend = info->nr_suspend_regs;
|
||||
data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks",
|
||||
"#clock-cells");
|
||||
if (data->nr_pclks > 0) {
|
||||
data->pclks = devm_kcalloc(dev, sizeof(struct clk *),
|
||||
data->nr_pclks, GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < data->nr_pclks; i++) {
|
||||
struct clk *clk = of_clk_get(dev->of_node, i);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
data->pclks[i] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->clk_name)
|
||||
data->clk = clk_get(dev, info->clk_name);
|
||||
clk_prepare_enable(data->clk);
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
/*
|
||||
* Enable runtime PM here to allow the clock core using runtime PM
|
||||
* for the registered clocks. Additionally, we increase the runtime
|
||||
* PM usage count before registering the clocks, to prevent the
|
||||
* clock core from runtime suspending the device.
|
||||
*/
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
if (info->pll_clks)
|
||||
samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks,
|
||||
reg_base);
|
||||
if (info->mux_clks)
|
||||
samsung_clk_register_mux(ctx, info->mux_clks,
|
||||
info->nr_mux_clks);
|
||||
if (info->div_clks)
|
||||
samsung_clk_register_div(ctx, info->div_clks,
|
||||
info->nr_div_clks);
|
||||
if (info->gate_clks)
|
||||
samsung_clk_register_gate(ctx, info->gate_clks,
|
||||
info->nr_gate_clks);
|
||||
if (info->fixed_clks)
|
||||
samsung_clk_register_fixed_rate(ctx, info->fixed_clks,
|
||||
info->nr_fixed_clks);
|
||||
if (info->fixed_factor_clks)
|
||||
samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks,
|
||||
info->nr_fixed_factor_clks);
|
||||
|
||||
samsung_clk_of_add_provider(dev->of_node, ctx);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id exynos5433_cmu_of_match[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5433-cmu-aud",
|
||||
.data = &aud_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-cam0",
|
||||
.data = &cam0_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-cam1",
|
||||
.data = &cam1_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-disp",
|
||||
.data = &disp_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-g2d",
|
||||
.data = &g2d_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-g3d",
|
||||
.data = &g3d_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-fsys",
|
||||
.data = &fsys_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-gscl",
|
||||
.data = &gscl_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-mfc",
|
||||
.data = &mfc_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-hevc",
|
||||
.data = &hevc_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-isp",
|
||||
.data = &isp_cmu_info,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-cmu-mscl",
|
||||
.data = &mscl_cmu_info,
|
||||
}, {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dev_pm_ops exynos5433_cmu_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume,
|
||||
NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver exynos5433_cmu_driver __refdata = {
|
||||
.driver = {
|
||||
.name = "exynos5433-cmu",
|
||||
.of_match_table = exynos5433_cmu_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &exynos5433_cmu_pm_ops,
|
||||
},
|
||||
.probe = exynos5433_cmu_probe,
|
||||
};
|
||||
|
||||
static int __init exynos5433_cmu_init(void)
|
||||
{
|
||||
return platform_driver_register(&exynos5433_cmu_driver);
|
||||
}
|
||||
core_initcall(exynos5433_cmu_init);
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __
|
|||
/* mux clocks */
|
||||
static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
|
||||
MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
|
||||
MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p,
|
||||
CPU_CLK_STATUS, 0, 1, "armclk"),
|
||||
MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1),
|
||||
};
|
||||
|
||||
/* divider clocks */
|
||||
|
|
@ -117,6 +116,13 @@ static const struct samsung_pll_clock exynos5440_plls[] __initconst = {
|
|||
PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL),
|
||||
};
|
||||
|
||||
/*
|
||||
* Clock aliases for legacy clkdev look-up.
|
||||
*/
|
||||
static const struct samsung_clock_alias exynos5440_aliases[] __initconst = {
|
||||
ALIAS(CLK_ARM_CLK, NULL, "armclk"),
|
||||
};
|
||||
|
||||
/* register exynos5440 clocks */
|
||||
static void __init exynos5440_clk_init(struct device_node *np)
|
||||
{
|
||||
|
|
@ -147,6 +153,8 @@ static void __init exynos5440_clk_init(struct device_node *np)
|
|||
ARRAY_SIZE(exynos5440_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos5440_gate_clks,
|
||||
ARRAY_SIZE(exynos5440_gate_clks));
|
||||
samsung_clk_register_alias(ctx, exynos5440_aliases,
|
||||
ARRAY_SIZE(exynos5440_aliases));
|
||||
|
||||
samsung_clk_of_add_provider(np, ctx);
|
||||
|
||||
|
|
|
|||
|
|
@ -1388,7 +1388,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
pll->lock_reg = base + pll_clk->lock_offset;
|
||||
pll->con_reg = base + pll_clk->con_offset;
|
||||
|
||||
ret = clk_hw_register(NULL, &pll->hw);
|
||||
ret = clk_hw_register(ctx->dev, &pll->hw);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register pll clock %s : %d\n",
|
||||
__func__, pll_clk->name, ret);
|
||||
|
|
@ -1397,15 +1397,6 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
|
||||
|
||||
if (!pll_clk->alias)
|
||||
return;
|
||||
|
||||
ret = clk_hw_register_clkdev(&pll->hw, pll_clk->alias,
|
||||
pll_clk->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup for %s : %d",
|
||||
__func__, pll_clk->name, ret);
|
||||
}
|
||||
|
||||
void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
|
|||
MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
|
||||
MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
|
||||
MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
|
||||
MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"),
|
||||
MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"),
|
||||
MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1),
|
||||
MUX(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1),
|
||||
MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2),
|
||||
};
|
||||
|
||||
|
|
@ -189,6 +189,10 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
|
|||
};
|
||||
|
||||
struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
|
||||
ALIAS(MSYSCLK, NULL, "msysclk"),
|
||||
ALIAS(ARMCLK, NULL, "armclk"),
|
||||
ALIAS(MPLL, NULL, "mpll"),
|
||||
ALIAS(EPLL, NULL, "epll"),
|
||||
ALIAS(HCLK, NULL, "hclk"),
|
||||
ALIAS(HCLK_SSMC, NULL, "nand"),
|
||||
ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
|
||||
|
|
@ -221,9 +225,9 @@ struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
|
|||
/* S3C2416 specific clocks */
|
||||
|
||||
static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
|
||||
[mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref",
|
||||
[mpll] = PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref",
|
||||
LOCKCON0, MPLLCON, NULL),
|
||||
[epll] = PLL(pll_6553, 0, "epll", "epllref",
|
||||
[epll] = PLL(pll_6553, EPLL, "epll", "epllref",
|
||||
LOCKCON1, EPLLCON, NULL),
|
||||
};
|
||||
|
||||
|
|
@ -275,9 +279,9 @@ struct samsung_clock_alias s3c2416_aliases[] __initdata = {
|
|||
/* S3C2443 specific clocks */
|
||||
|
||||
static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
|
||||
[mpll] = PLL(pll_3000, 0, "mpll", "mpllref",
|
||||
[mpll] = PLL(pll_3000, MPLL, "mpll", "mpllref",
|
||||
LOCKCON0, MPLLCON, NULL),
|
||||
[epll] = PLL(pll_2126, 0, "epll", "epllref",
|
||||
[epll] = PLL(pll_2126, EPLL, "epll", "epllref",
|
||||
LOCKCON1, EPLLCON, NULL),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
|
|||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk_hw = clk_hw_register_fixed_rate(NULL, list->name,
|
||||
clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name,
|
||||
list->parent_name, list->flags, list->fixed_rate);
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
|
|
@ -163,7 +163,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
|
|||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk_hw = clk_hw_register_fixed_factor(NULL, list->name,
|
||||
clk_hw = clk_hw_register_fixed_factor(ctx->dev, list->name,
|
||||
list->parent_name, list->flags, list->mult, list->div);
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
|
|
@ -181,10 +181,10 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
|
|||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk_hw = clk_hw_register_mux(NULL, list->name,
|
||||
clk_hw = clk_hw_register_mux(ctx->dev, list->name,
|
||||
list->parent_names, list->num_parents, list->flags,
|
||||
ctx->reg_base + list->offset,
|
||||
list->shift, list->width, list->mux_flags, &ctx->lock);
|
||||
|
|
@ -195,15 +195,6 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
|
|||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,17 +204,17 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
|
|||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
if (list->table)
|
||||
clk_hw = clk_hw_register_divider_table(NULL,
|
||||
clk_hw = clk_hw_register_divider_table(ctx->dev,
|
||||
list->name, list->parent_name, list->flags,
|
||||
ctx->reg_base + list->offset,
|
||||
list->shift, list->width, list->div_flags,
|
||||
list->table, &ctx->lock);
|
||||
else
|
||||
clk_hw = clk_hw_register_divider(NULL, list->name,
|
||||
clk_hw = clk_hw_register_divider(ctx->dev, list->name,
|
||||
list->parent_name, list->flags,
|
||||
ctx->reg_base + list->offset, list->shift,
|
||||
list->width, list->div_flags, &ctx->lock);
|
||||
|
|
@ -234,15 +225,6 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
|
|||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,10 +234,10 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
|
|||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name,
|
||||
clk_hw = clk_hw_register_gate(ctx->dev, list->name, list->parent_name,
|
||||
list->flags, ctx->reg_base + list->offset,
|
||||
list->bit_idx, list->gate_flags, &ctx->lock);
|
||||
if (IS_ERR(clk_hw)) {
|
||||
|
|
@ -264,15 +246,6 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
struct samsung_clk_provider {
|
||||
void __iomem *reg_base;
|
||||
struct device *dev;
|
||||
spinlock_t lock;
|
||||
/* clk_data must be the last entry due to variable lenght 'hws' array */
|
||||
struct clk_hw_onecell_data clk_data;
|
||||
|
|
@ -106,7 +107,6 @@ struct samsung_fixed_factor_clock {
|
|||
/**
|
||||
* 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.
|
||||
|
|
@ -115,11 +115,9 @@ struct samsung_fixed_factor_clock {
|
|||
* @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 *const *parent_names;
|
||||
u8 num_parents;
|
||||
|
|
@ -128,13 +126,11 @@ struct samsung_mux_clock {
|
|||
u8 shift;
|
||||
u8 width;
|
||||
u8 mux_flags;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \
|
||||
#define __MUX(_id, cname, pnames, o, s, w, f, mf) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.dev_name = dname, \
|
||||
.name = cname, \
|
||||
.parent_names = pnames, \
|
||||
.num_parents = ARRAY_SIZE(pnames), \
|
||||
|
|
@ -143,36 +139,26 @@ struct samsung_mux_clock {
|
|||
.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)
|
||||
__MUX(_id, cname, pnames, o, s, w, 0, 0)
|
||||
|
||||
#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)
|
||||
__MUX(_id, cname, pnames, o, s, w, f, mf)
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
|
@ -180,14 +166,12 @@ struct samsung_div_clock {
|
|||
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) \
|
||||
#define __DIV(_id, cname, pname, o, s, w, f, df, t) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.dev_name = dname, \
|
||||
.name = cname, \
|
||||
.parent_name = pname, \
|
||||
.flags = f, \
|
||||
|
|
@ -195,70 +179,51 @@ struct samsung_div_clock {
|
|||
.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)
|
||||
__DIV(_id, cname, pname, o, s, w, 0, 0, NULL)
|
||||
|
||||
#define DIV_F(_id, cname, pname, o, s, w, f, df) \
|
||||
__DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
|
||||
__DIV(_id, cname, pname, o, s, w, f, df, NULL)
|
||||
|
||||
#define DIV_T(_id, cname, pname, o, s, w, t) \
|
||||
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
|
||||
__DIV(_id, cname, pname, o, s, w, 0, 0, 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) \
|
||||
#define __GATE(_id, cname, pname, o, b, f, gf) \
|
||||
{ \
|
||||
.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)
|
||||
__GATE(_id, cname, pname, o, b, f, gf)
|
||||
|
||||
#define PNAME(x) static const char * const x[] __initconst
|
||||
|
||||
|
|
@ -275,18 +240,15 @@ struct samsung_clk_reg_dump {
|
|||
/**
|
||||
* 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;
|
||||
|
|
@ -294,31 +256,23 @@ struct samsung_pll_clock {
|
|||
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) \
|
||||
#define __PLL(_typ, _id, _name, _pname, _flags, _lock, _con, _rtable) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.type = _typ, \
|
||||
.dev_name = _dname, \
|
||||
.name = _name, \
|
||||
.parent_name = _pname, \
|
||||
.flags = CLK_GET_RATE_NOCACHE, \
|
||||
.flags = _flags, \
|
||||
.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)
|
||||
__PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock, \
|
||||
_con, _rtable)
|
||||
|
||||
struct samsung_clock_reg_cache {
|
||||
struct list_head node;
|
||||
|
|
@ -352,6 +306,12 @@ struct samsung_cmu_info {
|
|||
/* list and number of clocks registers */
|
||||
const unsigned long *clk_regs;
|
||||
unsigned int nr_clk_regs;
|
||||
|
||||
/* list and number of clocks registers to set before suspend */
|
||||
const struct samsung_clk_reg_dump *suspend_regs;
|
||||
unsigned int nr_suspend_regs;
|
||||
/* name of the parent clock needed for CMU register access */
|
||||
const char *clk_name;
|
||||
};
|
||||
|
||||
extern struct samsung_clk_provider *__init samsung_clk_init(
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static struct clk_dmn clk_mmc45 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_nand_init = {
|
||||
static const struct clk_init_data clk_nand_init = {
|
||||
.name = "nand",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ static const char * const pll_clk_parents[] = {
|
|||
"xin",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_cpupll_init = {
|
||||
static const struct clk_init_data clk_cpupll_init = {
|
||||
.name = "cpupll_vco",
|
||||
.ops = &ab_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -406,7 +406,7 @@ static struct clk_pll clk_cpupll = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mempll_init = {
|
||||
static const struct clk_init_data clk_mempll_init = {
|
||||
.name = "mempll_vco",
|
||||
.ops = &ab_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -420,7 +420,7 @@ static struct clk_pll clk_mempll = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_sys0pll_init = {
|
||||
static const struct clk_init_data clk_sys0pll_init = {
|
||||
.name = "sys0pll_vco",
|
||||
.ops = &ab_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -434,7 +434,7 @@ static struct clk_pll clk_sys0pll = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_sys1pll_init = {
|
||||
static const struct clk_init_data clk_sys1pll_init = {
|
||||
.name = "sys1pll_vco",
|
||||
.ops = &ab_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -448,7 +448,7 @@ static struct clk_pll clk_sys1pll = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_sys2pll_init = {
|
||||
static const struct clk_init_data clk_sys2pll_init = {
|
||||
.name = "sys2pll_vco",
|
||||
.ops = &ab_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -462,7 +462,7 @@ static struct clk_pll clk_sys2pll = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_sys3pll_init = {
|
||||
static const struct clk_init_data clk_sys3pll_init = {
|
||||
.name = "sys3pll_vco",
|
||||
.ops = &ab_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -596,7 +596,7 @@ static const char * const audiodto_clk_parents[] = {
|
|||
"sys3pll_clk1",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_audiodto_init = {
|
||||
static const struct clk_init_data clk_audiodto_init = {
|
||||
.name = "audio_dto",
|
||||
.ops = &dto_ops,
|
||||
.parent_names = audiodto_clk_parents,
|
||||
|
|
@ -617,7 +617,7 @@ static const char * const disp0dto_clk_parents[] = {
|
|||
"sys3pll_clk1",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_disp0dto_init = {
|
||||
static const struct clk_init_data clk_disp0dto_init = {
|
||||
.name = "disp0_dto",
|
||||
.ops = &dto_ops,
|
||||
.parent_names = disp0dto_clk_parents,
|
||||
|
|
@ -638,7 +638,7 @@ static const char * const disp1dto_clk_parents[] = {
|
|||
"sys3pll_clk1",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_disp1dto_init = {
|
||||
static const struct clk_init_data clk_disp1dto_init = {
|
||||
.name = "disp1_dto",
|
||||
.ops = &dto_ops,
|
||||
.parent_names = disp1dto_clk_parents,
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw,
|
|||
return clk_hw_get_rate(parent_clk);
|
||||
}
|
||||
|
||||
static struct clk_ops std_pll_ops = {
|
||||
static const struct clk_ops std_pll_ops = {
|
||||
.recalc_rate = pll_clk_recalc_rate,
|
||||
.round_rate = pll_clk_round_rate,
|
||||
.set_rate = pll_clk_set_rate,
|
||||
|
|
@ -194,21 +194,21 @@ static const char * const pll_clk_parents[] = {
|
|||
"osc",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_pll1_init = {
|
||||
static const struct clk_init_data clk_pll1_init = {
|
||||
.name = "pll1",
|
||||
.ops = &std_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
.num_parents = ARRAY_SIZE(pll_clk_parents),
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_pll2_init = {
|
||||
static const struct clk_init_data clk_pll2_init = {
|
||||
.name = "pll2",
|
||||
.ops = &std_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
.num_parents = ARRAY_SIZE(pll_clk_parents),
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_pll3_init = {
|
||||
static const struct clk_init_data clk_pll3_init = {
|
||||
.name = "pll3",
|
||||
.ops = &std_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -265,13 +265,13 @@ static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long pa
|
|||
return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ;
|
||||
}
|
||||
|
||||
static struct clk_ops usb_pll_ops = {
|
||||
static const struct clk_ops usb_pll_ops = {
|
||||
.enable = usb_pll_clk_enable,
|
||||
.disable = usb_pll_clk_disable,
|
||||
.recalc_rate = usb_pll_clk_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_usb_pll_init = {
|
||||
static const struct clk_init_data clk_usb_pll_init = {
|
||||
.name = "usb_pll",
|
||||
.ops = &usb_pll_ops,
|
||||
.parent_names = pll_clk_parents,
|
||||
|
|
@ -437,7 +437,7 @@ static int cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
return ret2 ? ret2 : ret1;
|
||||
}
|
||||
|
||||
static struct clk_ops msi_ops = {
|
||||
static const struct clk_ops msi_ops = {
|
||||
.set_rate = dmn_clk_set_rate,
|
||||
.round_rate = dmn_clk_round_rate,
|
||||
.recalc_rate = dmn_clk_recalc_rate,
|
||||
|
|
@ -445,7 +445,7 @@ static struct clk_ops msi_ops = {
|
|||
.get_parent = dmn_clk_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mem_init = {
|
||||
static const struct clk_init_data clk_mem_init = {
|
||||
.name = "mem",
|
||||
.ops = &msi_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -459,7 +459,7 @@ static struct clk_dmn clk_mem = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_sys_init = {
|
||||
static const struct clk_init_data clk_sys_init = {
|
||||
.name = "sys",
|
||||
.ops = &msi_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -474,7 +474,7 @@ static struct clk_dmn clk_sys = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_io_init = {
|
||||
static const struct clk_init_data clk_io_init = {
|
||||
.name = "io",
|
||||
.ops = &msi_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -488,7 +488,7 @@ static struct clk_dmn clk_io = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_ops cpu_ops = {
|
||||
static const struct clk_ops cpu_ops = {
|
||||
.set_parent = dmn_clk_set_parent,
|
||||
.get_parent = dmn_clk_get_parent,
|
||||
.set_rate = cpu_clk_set_rate,
|
||||
|
|
@ -496,7 +496,7 @@ static struct clk_ops cpu_ops = {
|
|||
.recalc_rate = cpu_clk_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_cpu_init = {
|
||||
static const struct clk_init_data clk_cpu_init = {
|
||||
.name = "cpu",
|
||||
.ops = &cpu_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -511,7 +511,7 @@ static struct clk_dmn clk_cpu = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_ops dmn_ops = {
|
||||
static const struct clk_ops dmn_ops = {
|
||||
.is_enabled = std_clk_is_enabled,
|
||||
.enable = std_clk_enable,
|
||||
.disable = std_clk_disable,
|
||||
|
|
@ -524,7 +524,7 @@ static struct clk_ops dmn_ops = {
|
|||
|
||||
/* dsp, gfx, mm, lcd and vpp domain */
|
||||
|
||||
static struct clk_init_data clk_dsp_init = {
|
||||
static const struct clk_init_data clk_dsp_init = {
|
||||
.name = "dsp",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -539,7 +539,7 @@ static struct clk_dmn clk_dsp = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_gfx_init = {
|
||||
static const struct clk_init_data clk_gfx_init = {
|
||||
.name = "gfx",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -554,7 +554,7 @@ static struct clk_dmn clk_gfx = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mm_init = {
|
||||
static const struct clk_init_data clk_mm_init = {
|
||||
.name = "mm",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -574,7 +574,7 @@ static struct clk_dmn clk_mm = {
|
|||
*/
|
||||
#define clk_gfx2d clk_mm
|
||||
|
||||
static struct clk_init_data clk_lcd_init = {
|
||||
static const struct clk_init_data clk_lcd_init = {
|
||||
.name = "lcd",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -589,7 +589,7 @@ static struct clk_dmn clk_lcd = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_vpp_init = {
|
||||
static const struct clk_init_data clk_vpp_init = {
|
||||
.name = "vpp",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -604,21 +604,21 @@ static struct clk_dmn clk_vpp = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mmc01_init = {
|
||||
static const struct clk_init_data clk_mmc01_init = {
|
||||
.name = "mmc01",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
.num_parents = ARRAY_SIZE(dmn_clk_parents),
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mmc23_init = {
|
||||
static const struct clk_init_data clk_mmc23_init = {
|
||||
.name = "mmc23",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
.num_parents = ARRAY_SIZE(dmn_clk_parents),
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mmc45_init = {
|
||||
static const struct clk_init_data clk_mmc45_init = {
|
||||
.name = "mmc45",
|
||||
.ops = &dmn_ops,
|
||||
.parent_names = dmn_clk_parents,
|
||||
|
|
@ -679,13 +679,13 @@ static const char * const std_clk_io_parents[] = {
|
|||
"io",
|
||||
};
|
||||
|
||||
static struct clk_ops ios_ops = {
|
||||
static const struct clk_ops ios_ops = {
|
||||
.is_enabled = std_clk_is_enabled,
|
||||
.enable = std_clk_enable,
|
||||
.disable = std_clk_disable,
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_cphif_init = {
|
||||
static const struct clk_init_data clk_cphif_init = {
|
||||
.name = "cphif",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -699,7 +699,7 @@ static struct clk_std clk_cphif = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_dmac0_init = {
|
||||
static const struct clk_init_data clk_dmac0_init = {
|
||||
.name = "dmac0",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -713,7 +713,7 @@ static struct clk_std clk_dmac0 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_dmac1_init = {
|
||||
static const struct clk_init_data clk_dmac1_init = {
|
||||
.name = "dmac1",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -727,7 +727,7 @@ static struct clk_std clk_dmac1 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_audio_init = {
|
||||
static const struct clk_init_data clk_audio_init = {
|
||||
.name = "audio",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -741,7 +741,7 @@ static struct clk_std clk_audio = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_uart0_init = {
|
||||
static const struct clk_init_data clk_uart0_init = {
|
||||
.name = "uart0",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -755,7 +755,7 @@ static struct clk_std clk_uart0 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_uart1_init = {
|
||||
static const struct clk_init_data clk_uart1_init = {
|
||||
.name = "uart1",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -769,7 +769,7 @@ static struct clk_std clk_uart1 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_uart2_init = {
|
||||
static const struct clk_init_data clk_uart2_init = {
|
||||
.name = "uart2",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -783,7 +783,7 @@ static struct clk_std clk_uart2 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_usp0_init = {
|
||||
static const struct clk_init_data clk_usp0_init = {
|
||||
.name = "usp0",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -797,7 +797,7 @@ static struct clk_std clk_usp0 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_usp1_init = {
|
||||
static const struct clk_init_data clk_usp1_init = {
|
||||
.name = "usp1",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -811,7 +811,7 @@ static struct clk_std clk_usp1 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_usp2_init = {
|
||||
static const struct clk_init_data clk_usp2_init = {
|
||||
.name = "usp2",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -825,7 +825,7 @@ static struct clk_std clk_usp2 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_vip_init = {
|
||||
static const struct clk_init_data clk_vip_init = {
|
||||
.name = "vip",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -839,7 +839,7 @@ static struct clk_std clk_vip = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_spi0_init = {
|
||||
static const struct clk_init_data clk_spi0_init = {
|
||||
.name = "spi0",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -853,7 +853,7 @@ static struct clk_std clk_spi0 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_spi1_init = {
|
||||
static const struct clk_init_data clk_spi1_init = {
|
||||
.name = "spi1",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -867,7 +867,7 @@ static struct clk_std clk_spi1 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_tsc_init = {
|
||||
static const struct clk_init_data clk_tsc_init = {
|
||||
.name = "tsc",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -881,7 +881,7 @@ static struct clk_std clk_tsc = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_i2c0_init = {
|
||||
static const struct clk_init_data clk_i2c0_init = {
|
||||
.name = "i2c0",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -895,7 +895,7 @@ static struct clk_std clk_i2c0 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_i2c1_init = {
|
||||
static const struct clk_init_data clk_i2c1_init = {
|
||||
.name = "i2c1",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -909,7 +909,7 @@ static struct clk_std clk_i2c1 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_pwmc_init = {
|
||||
static const struct clk_init_data clk_pwmc_init = {
|
||||
.name = "pwmc",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -923,7 +923,7 @@ static struct clk_std clk_pwmc = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_efuse_init = {
|
||||
static const struct clk_init_data clk_efuse_init = {
|
||||
.name = "efuse",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -937,7 +937,7 @@ static struct clk_std clk_efuse = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_pulse_init = {
|
||||
static const struct clk_init_data clk_pulse_init = {
|
||||
.name = "pulse",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -955,7 +955,7 @@ static const char * const std_clk_dsp_parents[] = {
|
|||
"dsp",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_gps_init = {
|
||||
static const struct clk_init_data clk_gps_init = {
|
||||
.name = "gps",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_dsp_parents,
|
||||
|
|
@ -969,7 +969,7 @@ static struct clk_std clk_gps = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_mf_init = {
|
||||
static const struct clk_init_data clk_mf_init = {
|
||||
.name = "mf",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
@ -987,7 +987,7 @@ static const char * const std_clk_sys_parents[] = {
|
|||
"sys",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_security_init = {
|
||||
static const struct clk_init_data clk_security_init = {
|
||||
.name = "security",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_sys_parents,
|
||||
|
|
@ -1005,7 +1005,7 @@ static const char * const std_clk_usb_parents[] = {
|
|||
"usb_pll",
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_usb0_init = {
|
||||
static const struct clk_init_data clk_usb0_init = {
|
||||
.name = "usb0",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_usb_parents,
|
||||
|
|
@ -1019,7 +1019,7 @@ static struct clk_std clk_usb0 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_usb1_init = {
|
||||
static const struct clk_init_data clk_usb1_init = {
|
||||
.name = "usb1",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_usb_parents,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static struct clk_dmn clk_mmc45 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_init_data clk_nand_init = {
|
||||
static const struct clk_init_data clk_nand_init = {
|
||||
.name = "nand",
|
||||
.ops = &ios_ops,
|
||||
.parent_names = std_clk_io_parents,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#define to_clk_aux(_hw) container_of(_hw, struct clk_aux, hw)
|
||||
|
||||
static struct aux_clk_masks default_aux_masks = {
|
||||
static const struct aux_clk_masks default_aux_masks = {
|
||||
.eq_sel_mask = AUX_EQ_SEL_MASK,
|
||||
.eq_sel_shift = AUX_EQ_SEL_SHIFT,
|
||||
.eq1_mask = AUX_EQ1_SEL,
|
||||
|
|
@ -128,7 +128,7 @@ static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_aux_ops = {
|
||||
static const struct clk_ops clk_aux_ops = {
|
||||
.recalc_rate = clk_aux_recalc_rate,
|
||||
.round_rate = clk_aux_round_rate,
|
||||
.set_rate = clk_aux_set_rate,
|
||||
|
|
@ -136,7 +136,7 @@ static struct clk_ops clk_aux_ops = {
|
|||
|
||||
struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
|
||||
const char *parent_name, unsigned long flags, void __iomem *reg,
|
||||
struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl,
|
||||
const struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl,
|
||||
u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk)
|
||||
{
|
||||
struct clk_aux *aux;
|
||||
|
|
@ -149,10 +149,8 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
|
|||
}
|
||||
|
||||
aux = kzalloc(sizeof(*aux), GFP_KERNEL);
|
||||
if (!aux) {
|
||||
pr_err("could not allocate aux clk\n");
|
||||
if (!aux)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* struct clk_aux assignments */
|
||||
if (!masks)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue