mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
Merge branches 'clk-hisi', 'clk-lochnagar', 'clk-allwinner', 'clk-rockchip' and 'clk-qoriq' into clk-next
- Mark UFS clk as critical on Hi-Silicon hi3660 SoCs - Support for Cirrus Logic Lochnagar clks * clk-hisi: clk: hi3660: Mark clk_gate_ufs_subsys as critical * clk-lochnagar: clk: lochnagar: Add support for the Cirrus Logic Lochnagar clk: lochnagar: Add initial binding documentation * clk-allwinner: clk: sunxi-ng: sun5i: Export the MBUS clock clk: sunxi-ng: a83t: Add pll-video0 as parent of csi-mclk clk: sunxi-ng: h6: Allow video & vpu clocks to change parent rate clk: sunxi-ng: h6: Preset hdmi-cec clock parent clk: sunxi: Add Kconfig options clk: sunxi-ng: f1c100s: fix USB PHY gate bit offset clk: sunxi-ng: Allow DE clock to set parent rate * clk-rockchip: clk: rockchip: undo several noc and special clocks as critical on rk3288 clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type clk: rockchip: Turn on "aclk_dmac1" for suspend on rk3288 clk: rockchip: Limit use of USB PHY clock to USB on rk3288 clk: rockchip: Fix video codec clocks on rk3288 clk: rockchip: Make rkpwm a critical clock on rk3288 clk: rockchip: fix wrong clock definitions for rk3328 * clk-qoriq: clk: qoriq: increase array size of cmux_to_group dt-bindings: qoriq-clock: Add ls1028a chip compatible string clk: qoriq: Add ls1028a clock configuration clk: qoriq: add more PLL divider clocks support dt-bindings: qoriq-clock: add more PLL divider clocks support
This commit is contained in:
commit
5816b74581
93
Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
Normal file
93
Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
Normal file
@ -0,0 +1,93 @@
|
||||
Cirrus Logic Lochnagar Audio Development Board
|
||||
|
||||
Lochnagar is an evaluation and development board for Cirrus Logic
|
||||
Smart CODEC and Amp devices. It allows the connection of most Cirrus
|
||||
Logic devices on mini-cards, as well as allowing connection of
|
||||
various application processor systems to provide a full evaluation
|
||||
platform. Audio system topology, clocking and power can all be
|
||||
controlled through the Lochnagar, allowing the device under test
|
||||
to be used in a variety of possible use cases.
|
||||
|
||||
This binding document describes the binding for the clock portion of
|
||||
the driver.
|
||||
|
||||
Also see these documents for generic binding information:
|
||||
[1] Clock : ../clock/clock-bindings.txt
|
||||
|
||||
And these for relevant defines:
|
||||
[2] include/dt-bindings/clock/lochnagar.h
|
||||
|
||||
This binding must be part of the Lochnagar MFD binding:
|
||||
[3] ../mfd/cirrus,lochnagar.txt
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of the following strings:
|
||||
"cirrus,lochnagar1-clk"
|
||||
"cirrus,lochnagar2-clk"
|
||||
|
||||
- #clock-cells : Must be 1. The first cell indicates the clock
|
||||
number, see [2] for available clocks and [1].
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clocks : Must contain an entry for each clock in clock-names.
|
||||
- clock-names : May contain entries for each of the following
|
||||
clocks:
|
||||
- ln-cdc-clkout : Output clock from CODEC card.
|
||||
- ln-dsp-clkout : Output clock from DSP card.
|
||||
- ln-gf-mclk1,ln-gf-mclk2,ln-gf-mclk3,ln-gf-mclk4 : Optional
|
||||
input audio clocks from host system.
|
||||
- ln-psia1-mclk, ln-psia2-mclk : Optional input audio clocks from
|
||||
external connector.
|
||||
- ln-spdif-clkout : Optional input audio clock from SPDIF.
|
||||
- ln-adat-mclk : Optional input audio clock from ADAT.
|
||||
- ln-pmic-32k : On board fixed clock.
|
||||
- ln-clk-12m : On board fixed clock.
|
||||
- ln-clk-11m : On board fixed clock.
|
||||
- ln-clk-24m : On board fixed clock.
|
||||
- ln-clk-22m : On board fixed clock.
|
||||
- ln-clk-8m : On board fixed clock.
|
||||
- ln-usb-clk-24m : On board fixed clock.
|
||||
- ln-usb-clk-12m : On board fixed clock.
|
||||
|
||||
- assigned-clocks : A list of Lochnagar clocks to be reparented, see
|
||||
[2] for available clocks.
|
||||
- assigned-clock-parents : Parents to be assigned to the clocks
|
||||
listed in "assigned-clocks".
|
||||
|
||||
Optional nodes:
|
||||
|
||||
- fixed-clock nodes may be registered for the following on board clocks:
|
||||
- ln-pmic-32k : 32768 Hz
|
||||
- ln-clk-12m : 12288000 Hz
|
||||
- ln-clk-11m : 11298600 Hz
|
||||
- ln-clk-24m : 24576000 Hz
|
||||
- ln-clk-22m : 22579200 Hz
|
||||
- ln-clk-8m : 8192000 Hz
|
||||
- ln-usb-clk-24m : 24576000 Hz
|
||||
- ln-usb-clk-12m : 12288000 Hz
|
||||
|
||||
Example:
|
||||
|
||||
lochnagar {
|
||||
lochnagar-clk {
|
||||
compatible = "cirrus,lochnagar2-clk";
|
||||
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&clk-audio>, <&clk_pmic>;
|
||||
clock-names = "ln-gf-mclk2", "ln-pmic-32k";
|
||||
|
||||
assigned-clocks = <&lochnagar-clk LOCHNAGAR_CDC_MCLK1>,
|
||||
<&lochnagar-clk LOCHNAGAR_CDC_MCLK2>;
|
||||
assigned-clock-parents = <&clk-audio>,
|
||||
<&clk-pmic>;
|
||||
};
|
||||
|
||||
clk-pmic: clk-pmic {
|
||||
compatible = "fixed-clock";
|
||||
clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
};
|
@ -39,6 +39,7 @@ Required properties:
|
||||
* "fsl,b4860-clockgen"
|
||||
* "fsl,ls1012a-clockgen"
|
||||
* "fsl,ls1021a-clockgen"
|
||||
* "fsl,ls1028a-clockgen"
|
||||
* "fsl,ls1043a-clockgen"
|
||||
* "fsl,ls1046a-clockgen"
|
||||
* "fsl,ls1088a-clockgen"
|
||||
@ -83,8 +84,8 @@ second cell is the clock index for the specified type.
|
||||
1 cmux index (n in CLKCnCSR)
|
||||
2 hwaccel index (n in CLKCGnHWACSR)
|
||||
3 fman 0 for fm1, 1 for fm2
|
||||
4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4
|
||||
4=pll/5, 5=pll/6, 6=pll/7, 7=pll/8
|
||||
4 platform pll n=pll/(n+1). For example, when n=1,
|
||||
that means output_freq=PLL_freq/2.
|
||||
5 coreclk must be 0
|
||||
|
||||
3. Example
|
||||
|
@ -219,6 +219,13 @@ config COMMON_CLK_XGENE
|
||||
---help---
|
||||
Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
|
||||
|
||||
config COMMON_CLK_LOCHNAGAR
|
||||
tristate "Cirrus Logic Lochnagar clock driver"
|
||||
depends on MFD_LOCHNAGAR
|
||||
help
|
||||
This driver supports the clocking features of the Cirrus Logic
|
||||
Lochnagar audio development board.
|
||||
|
||||
config COMMON_CLK_NXP
|
||||
def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
|
||||
select REGMAP_MMIO if ARCH_LPC32XX
|
||||
@ -310,6 +317,7 @@ source "drivers/clk/qcom/Kconfig"
|
||||
source "drivers/clk/renesas/Kconfig"
|
||||
source "drivers/clk/samsung/Kconfig"
|
||||
source "drivers/clk/sprd/Kconfig"
|
||||
source "drivers/clk/sunxi/Kconfig"
|
||||
source "drivers/clk/sunxi-ng/Kconfig"
|
||||
source "drivers/clk/tegra/Kconfig"
|
||||
source "drivers/clk/ti/Kconfig"
|
||||
|
@ -32,6 +32,7 @@ obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
|
||||
obj-$(CONFIG_COMMON_CLK_ASPEED) += clk-aspeed.o
|
||||
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
|
||||
obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o
|
||||
obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o
|
||||
|
336
drivers/clk/clk-lochnagar.c
Normal file
336
drivers/clk/clk-lochnagar.c
Normal file
@ -0,0 +1,336 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Lochnagar clock control
|
||||
*
|
||||
* Copyright (c) 2017-2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <linux/mfd/lochnagar.h>
|
||||
#include <linux/mfd/lochnagar1_regs.h>
|
||||
#include <linux/mfd/lochnagar2_regs.h>
|
||||
|
||||
#include <dt-bindings/clk/lochnagar.h>
|
||||
|
||||
#define LOCHNAGAR_NUM_CLOCKS (LOCHNAGAR_SPDIF_CLKOUT + 1)
|
||||
|
||||
struct lochnagar_clk {
|
||||
const char * const name;
|
||||
struct clk_hw hw;
|
||||
|
||||
struct lochnagar_clk_priv *priv;
|
||||
|
||||
u16 cfg_reg;
|
||||
u16 ena_mask;
|
||||
|
||||
u16 src_reg;
|
||||
u16 src_mask;
|
||||
};
|
||||
|
||||
struct lochnagar_clk_priv {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
enum lochnagar_type type;
|
||||
|
||||
const char **parents;
|
||||
unsigned int nparents;
|
||||
|
||||
struct lochnagar_clk lclks[LOCHNAGAR_NUM_CLOCKS];
|
||||
};
|
||||
|
||||
static const char * const lochnagar1_clk_parents[] = {
|
||||
"ln-none",
|
||||
"ln-spdif-mclk",
|
||||
"ln-psia1-mclk",
|
||||
"ln-psia2-mclk",
|
||||
"ln-cdc-clkout",
|
||||
"ln-dsp-clkout",
|
||||
"ln-pmic-32k",
|
||||
"ln-gf-mclk1",
|
||||
"ln-gf-mclk3",
|
||||
"ln-gf-mclk2",
|
||||
"ln-gf-mclk4",
|
||||
};
|
||||
|
||||
static const char * const lochnagar2_clk_parents[] = {
|
||||
"ln-none",
|
||||
"ln-cdc-clkout",
|
||||
"ln-dsp-clkout",
|
||||
"ln-pmic-32k",
|
||||
"ln-spdif-mclk",
|
||||
"ln-clk-12m",
|
||||
"ln-clk-11m",
|
||||
"ln-clk-24m",
|
||||
"ln-clk-22m",
|
||||
"ln-clk-8m",
|
||||
"ln-usb-clk-24m",
|
||||
"ln-gf-mclk1",
|
||||
"ln-gf-mclk3",
|
||||
"ln-gf-mclk2",
|
||||
"ln-psia1-mclk",
|
||||
"ln-psia2-mclk",
|
||||
"ln-spdif-clkout",
|
||||
"ln-adat-mclk",
|
||||
"ln-usb-clk-12m",
|
||||
};
|
||||
|
||||
#define LN1_CLK(ID, NAME, REG) \
|
||||
[LOCHNAGAR_##ID] = { \
|
||||
.name = NAME, \
|
||||
.cfg_reg = LOCHNAGAR1_##REG, \
|
||||
.ena_mask = LOCHNAGAR1_##ID##_ENA_MASK, \
|
||||
.src_reg = LOCHNAGAR1_##ID##_SEL, \
|
||||
.src_mask = LOCHNAGAR1_SRC_MASK, \
|
||||
}
|
||||
|
||||
#define LN2_CLK(ID, NAME) \
|
||||
[LOCHNAGAR_##ID] = { \
|
||||
.name = NAME, \
|
||||
.cfg_reg = LOCHNAGAR2_##ID##_CTRL, \
|
||||
.src_reg = LOCHNAGAR2_##ID##_CTRL, \
|
||||
.ena_mask = LOCHNAGAR2_CLK_ENA_MASK, \
|
||||
.src_mask = LOCHNAGAR2_CLK_SRC_MASK, \
|
||||
}
|
||||
|
||||
static const struct lochnagar_clk lochnagar1_clks[LOCHNAGAR_NUM_CLOCKS] = {
|
||||
LN1_CLK(CDC_MCLK1, "ln-cdc-mclk1", CDC_AIF_CTRL2),
|
||||
LN1_CLK(CDC_MCLK2, "ln-cdc-mclk2", CDC_AIF_CTRL2),
|
||||
LN1_CLK(DSP_CLKIN, "ln-dsp-clkin", DSP_AIF),
|
||||
LN1_CLK(GF_CLKOUT1, "ln-gf-clkout1", GF_AIF1),
|
||||
};
|
||||
|
||||
static const struct lochnagar_clk lochnagar2_clks[LOCHNAGAR_NUM_CLOCKS] = {
|
||||
LN2_CLK(CDC_MCLK1, "ln-cdc-mclk1"),
|
||||
LN2_CLK(CDC_MCLK2, "ln-cdc-mclk2"),
|
||||
LN2_CLK(DSP_CLKIN, "ln-dsp-clkin"),
|
||||
LN2_CLK(GF_CLKOUT1, "ln-gf-clkout1"),
|
||||
LN2_CLK(GF_CLKOUT2, "ln-gf-clkout2"),
|
||||
LN2_CLK(PSIA1_MCLK, "ln-psia1-mclk"),
|
||||
LN2_CLK(PSIA2_MCLK, "ln-psia2-mclk"),
|
||||
LN2_CLK(SPDIF_MCLK, "ln-spdif-mclk"),
|
||||
LN2_CLK(ADAT_MCLK, "ln-adat-mclk"),
|
||||
LN2_CLK(SOUNDCARD_MCLK, "ln-soundcard-mclk"),
|
||||
};
|
||||
|
||||
static inline struct lochnagar_clk *lochnagar_hw_to_lclk(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct lochnagar_clk, hw);
|
||||
}
|
||||
|
||||
static int lochnagar_clk_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
|
||||
struct lochnagar_clk_priv *priv = lclk->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, lclk->cfg_reg,
|
||||
lclk->ena_mask, lclk->ena_mask);
|
||||
if (ret < 0)
|
||||
dev_dbg(priv->dev, "Failed to prepare %s: %d\n",
|
||||
lclk->name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lochnagar_clk_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
|
||||
struct lochnagar_clk_priv *priv = lclk->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, lclk->cfg_reg, lclk->ena_mask, 0);
|
||||
if (ret < 0)
|
||||
dev_dbg(priv->dev, "Failed to unprepare %s: %d\n",
|
||||
lclk->name, ret);
|
||||
}
|
||||
|
||||
static int lochnagar_clk_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
|
||||
struct lochnagar_clk_priv *priv = lclk->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, lclk->src_reg, lclk->src_mask, index);
|
||||
if (ret < 0)
|
||||
dev_dbg(priv->dev, "Failed to reparent %s: %d\n",
|
||||
lclk->name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 lochnagar_clk_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
|
||||
struct lochnagar_clk_priv *priv = lclk->priv;
|
||||
struct regmap *regmap = priv->regmap;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, lclk->src_reg, &val);
|
||||
if (ret < 0) {
|
||||
dev_dbg(priv->dev, "Failed to read parent of %s: %d\n",
|
||||
lclk->name, ret);
|
||||
return priv->nparents;
|
||||
}
|
||||
|
||||
val &= lclk->src_mask;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static const struct clk_ops lochnagar_clk_ops = {
|
||||
.prepare = lochnagar_clk_prepare,
|
||||
.unprepare = lochnagar_clk_unprepare,
|
||||
.set_parent = lochnagar_clk_set_parent,
|
||||
.get_parent = lochnagar_clk_get_parent,
|
||||
};
|
||||
|
||||
static int lochnagar_init_parents(struct lochnagar_clk_priv *priv)
|
||||
{
|
||||
struct device_node *np = priv->dev->of_node;
|
||||
int i, j;
|
||||
|
||||
switch (priv->type) {
|
||||
case LOCHNAGAR1:
|
||||
memcpy(priv->lclks, lochnagar1_clks, sizeof(lochnagar1_clks));
|
||||
|
||||
priv->nparents = ARRAY_SIZE(lochnagar1_clk_parents);
|
||||
priv->parents = devm_kmemdup(priv->dev, lochnagar1_clk_parents,
|
||||
sizeof(lochnagar1_clk_parents),
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
case LOCHNAGAR2:
|
||||
memcpy(priv->lclks, lochnagar2_clks, sizeof(lochnagar2_clks));
|
||||
|
||||
priv->nparents = ARRAY_SIZE(lochnagar2_clk_parents);
|
||||
priv->parents = devm_kmemdup(priv->dev, lochnagar2_clk_parents,
|
||||
sizeof(lochnagar2_clk_parents),
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
default:
|
||||
dev_err(priv->dev, "Unknown Lochnagar type: %d\n", priv->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!priv->parents)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < priv->nparents; i++) {
|
||||
j = of_property_match_string(np, "clock-names",
|
||||
priv->parents[i]);
|
||||
if (j >= 0)
|
||||
priv->parents[i] = of_clk_get_parent_name(np, j);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_hw *
|
||||
lochnagar_of_clk_hw_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
struct lochnagar_clk_priv *priv = data;
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx >= ARRAY_SIZE(priv->lclks)) {
|
||||
dev_err(priv->dev, "Invalid index %u\n", idx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return &priv->lclks[idx].hw;
|
||||
}
|
||||
|
||||
static int lochnagar_init_clks(struct lochnagar_clk_priv *priv)
|
||||
{
|
||||
struct clk_init_data clk_init = {
|
||||
.ops = &lochnagar_clk_ops,
|
||||
.parent_names = priv->parents,
|
||||
.num_parents = priv->nparents,
|
||||
};
|
||||
struct lochnagar_clk *lclk;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->lclks); i++) {
|
||||
lclk = &priv->lclks[i];
|
||||
|
||||
if (!lclk->name)
|
||||
continue;
|
||||
|
||||
clk_init.name = lclk->name;
|
||||
|
||||
lclk->priv = priv;
|
||||
lclk->hw.init = &clk_init;
|
||||
|
||||
ret = devm_clk_hw_register(priv->dev, &lclk->hw);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to register %s: %d\n",
|
||||
lclk->name, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(priv->dev, lochnagar_of_clk_hw_get,
|
||||
priv);
|
||||
if (ret < 0)
|
||||
dev_err(priv->dev, "Failed to register provider: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id lochnagar_of_match[] = {
|
||||
{ .compatible = "cirrus,lochnagar1-clk", .data = (void *)LOCHNAGAR1 },
|
||||
{ .compatible = "cirrus,lochnagar2-clk", .data = (void *)LOCHNAGAR2 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lochnagar_of_match);
|
||||
|
||||
static int lochnagar_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct lochnagar_clk_priv *priv;
|
||||
const struct of_device_id *of_id;
|
||||
int ret;
|
||||
|
||||
of_id = of_match_device(lochnagar_of_match, dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = dev;
|
||||
priv->regmap = dev_get_regmap(dev->parent, NULL);
|
||||
priv->type = (enum lochnagar_type)of_id->data;
|
||||
|
||||
ret = lochnagar_init_parents(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lochnagar_init_clks(priv);
|
||||
}
|
||||
|
||||
static struct platform_driver lochnagar_clk_driver = {
|
||||
.driver = {
|
||||
.name = "lochnagar-clk",
|
||||
.of_match_table = lochnagar_of_match,
|
||||
},
|
||||
.probe = lochnagar_clk_probe,
|
||||
};
|
||||
module_platform_driver(lochnagar_clk_driver);
|
||||
|
||||
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
|
||||
MODULE_DESCRIPTION("Clock driver for Cirrus Logic Lochnagar Board");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -34,6 +34,7 @@
|
||||
#define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */
|
||||
#define CGB_PLL1 4
|
||||
#define CGB_PLL2 5
|
||||
#define MAX_PLL_DIV 16
|
||||
|
||||
struct clockgen_pll_div {
|
||||
struct clk *clk;
|
||||
@ -41,7 +42,7 @@ struct clockgen_pll_div {
|
||||
};
|
||||
|
||||
struct clockgen_pll {
|
||||
struct clockgen_pll_div div[8];
|
||||
struct clockgen_pll_div div[MAX_PLL_DIV];
|
||||
};
|
||||
|
||||
#define CLKSEL_VALID 1
|
||||
@ -79,7 +80,7 @@ struct clockgen_chipinfo {
|
||||
const struct clockgen_muxinfo *cmux_groups[2];
|
||||
const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
|
||||
void (*init_periph)(struct clockgen *cg);
|
||||
int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
|
||||
int cmux_to_group[NUM_CMUX + 1]; /* array should be -1 terminated */
|
||||
u32 pll_mask; /* 1 << n bit set if PLL n is valid */
|
||||
u32 flags; /* CG_xxx */
|
||||
};
|
||||
@ -245,6 +246,58 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct clockgen_muxinfo ls1028a_hwa1 = {
|
||||
{
|
||||
{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
|
||||
{},
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct clockgen_muxinfo ls1028a_hwa2 = {
|
||||
{
|
||||
{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
|
||||
{},
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct clockgen_muxinfo ls1028a_hwa3 = {
|
||||
{
|
||||
{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
|
||||
{},
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct clockgen_muxinfo ls1028a_hwa4 = {
|
||||
{
|
||||
{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
|
||||
{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
|
||||
{},
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
|
||||
{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct clockgen_muxinfo ls1043a_hwa1 = {
|
||||
{
|
||||
{},
|
||||
@ -507,6 +560,21 @@ static const struct clockgen_chipinfo chipinfo[] = {
|
||||
},
|
||||
.pll_mask = 0x03,
|
||||
},
|
||||
{
|
||||
.compat = "fsl,ls1028a-clockgen",
|
||||
.cmux_groups = {
|
||||
&clockgen2_cmux_cga12
|
||||
},
|
||||
.hwaccel = {
|
||||
&ls1028a_hwa1, &ls1028a_hwa2,
|
||||
&ls1028a_hwa3, &ls1028a_hwa4
|
||||
},
|
||||
.cmux_to_group = {
|
||||
0, 0, 0, 0, -1
|
||||
},
|
||||
.pll_mask = 0x07,
|
||||
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
|
||||
},
|
||||
{
|
||||
.compat = "fsl,ls1043a-clockgen",
|
||||
.init_periph = t2080_init_periph,
|
||||
@ -601,7 +669,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
|
||||
&p4080_cmux_grp1, &p4080_cmux_grp2
|
||||
},
|
||||
.cmux_to_group = {
|
||||
0, 0, 0, 0, 1, 1, 1, 1
|
||||
0, 0, 0, 0, 1, 1, 1, 1, -1
|
||||
},
|
||||
.pll_mask = 0x1f,
|
||||
},
|
||||
@ -1128,7 +1196,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* For platform PLL, there are 8 divider clocks.
|
||||
* For platform PLL, there are MAX_PLL_DIV divider clocks.
|
||||
* For core PLL, there are 4 divider clocks at most.
|
||||
*/
|
||||
if (idx != PLATFORM_PLL && i >= 4)
|
||||
@ -1423,6 +1491,7 @@ CLK_OF_DECLARE(qoriq_clockgen_b4420, "fsl,b4420-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_b4860, "fsl,b4860-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_ls1028a, "fsl,ls1028a-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
|
||||
CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init);
|
||||
|
@ -163,8 +163,12 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_sep_clks[] = {
|
||||
"clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 17, 0, },
|
||||
{ HI3660_CLK_GATE_ISP_SNCLK2, "clk_gate_isp_snclk2",
|
||||
"clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 18, 0, },
|
||||
/*
|
||||
* clk_gate_ufs_subsys is a system bus clock, mark it as critical
|
||||
* clock and keep it on for system suspend and resume.
|
||||
*/
|
||||
{ HI3660_CLK_GATE_UFS_SUBSYS, "clk_gate_ufs_subsys", "clk_div_sysbus",
|
||||
CLK_SET_RATE_PARENT, 0x50, 21, 0, },
|
||||
CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0x50, 21, 0, },
|
||||
{ HI3660_PCLK_GATE_DSI0, "pclk_gate_dsi0", "clk_div_cfgbus",
|
||||
CLK_SET_RATE_PARENT, 0x50, 28, 0, },
|
||||
{ HI3660_PCLK_GATE_DSI1, "pclk_gate_dsi1", "clk_div_cfgbus",
|
||||
|
@ -200,8 +200,8 @@ PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu" };
|
||||
PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" };
|
||||
PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" };
|
||||
PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" };
|
||||
PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usbphy480m_src" };
|
||||
PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "usbphy480m_src", "npll" };
|
||||
PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "unstable:usbphy480m_src" };
|
||||
PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "unstable:usbphy480m_src", "npll" };
|
||||
|
||||
PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" };
|
||||
PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
|
||||
@ -219,7 +219,7 @@ PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" };
|
||||
PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" };
|
||||
PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" };
|
||||
|
||||
PNAME(mux_aclk_vcodec_pre_p) = { "aclk_vepu", "aclk_vdpu" };
|
||||
PNAME(mux_aclk_vcodec_pre_p) = { "aclk_vdpu", "aclk_vepu" };
|
||||
PNAME(mux_usbphy480m_p) = { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
|
||||
"sclk_otgphy0_480m" };
|
||||
PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" };
|
||||
@ -313,13 +313,13 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK3288_CLKGATE_CON(12), 6, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "atclk", "armclk", CLK_IGNORE_UNUSED,
|
||||
COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
|
||||
RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK3288_CLKGATE_CON(12), 7, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK3288_CLKGATE_CON(12), 8, GFLAGS),
|
||||
GATE(0, "pclk_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED,
|
||||
GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
|
||||
RK3288_CLKGATE_CON(12), 9, GFLAGS),
|
||||
GATE(0, "cs_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED,
|
||||
RK3288_CLKGATE_CON(12), 10, GFLAGS),
|
||||
@ -420,7 +420,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
|
||||
RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3288_CLKGATE_CON(3), 11, GFLAGS),
|
||||
MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, 0,
|
||||
MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS),
|
||||
GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
|
||||
RK3288_CLKGATE_CON(9), 0, GFLAGS),
|
||||
@ -647,7 +647,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
|
||||
RK3288_CLKSEL_CON(22), 7, IFLAGS),
|
||||
|
||||
GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
|
||||
GATE(0, "jtag", "ext_jtag", 0,
|
||||
RK3288_CLKGATE_CON(4), 14, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(SCLK_USBPHY480M_SRC, "usbphy480m_src", mux_usbphy480m_p, 0,
|
||||
@ -656,7 +656,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
|
||||
RK3288_CLKSEL_CON(29), 0, 2, MFLAGS,
|
||||
RK3288_CLKGATE_CON(3), 6, GFLAGS),
|
||||
GATE(0, "hsicphy12m_xin12m", "xin12m", CLK_IGNORE_UNUSED,
|
||||
GATE(0, "hsicphy12m_xin12m", "xin12m", 0,
|
||||
RK3288_CLKGATE_CON(13), 9, GFLAGS),
|
||||
DIV(0, "hsicphy12m_usbphy", "sclk_hsicphy480m", 0,
|
||||
RK3288_CLKSEL_CON(11), 8, 6, DFLAGS),
|
||||
@ -697,7 +697,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
|
||||
GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
|
||||
GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS),
|
||||
GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS),
|
||||
|
||||
/* ddrctrl [DDR Controller PHY clock] gates */
|
||||
GATE(0, "nclk_ddrupctl0", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 4, GFLAGS),
|
||||
@ -837,12 +837,9 @@ static const char *const rk3288_critical_clocks[] __initconst = {
|
||||
"pclk_alive_niu",
|
||||
"pclk_pd_pmu",
|
||||
"pclk_pmu_niu",
|
||||
"pclk_core_niu",
|
||||
"pclk_ddrupctl0",
|
||||
"pclk_publ0",
|
||||
"pclk_ddrupctl1",
|
||||
"pclk_publ1",
|
||||
"pmu_hclk_otg0",
|
||||
/* pwm-regulators on some boards, so handoff-critical later */
|
||||
"pclk_rkpwm",
|
||||
};
|
||||
|
||||
static void __iomem *rk3288_cru_base;
|
||||
@ -859,6 +856,9 @@ static const int rk3288_saved_cru_reg_ids[] = {
|
||||
RK3288_CLKSEL_CON(10),
|
||||
RK3288_CLKSEL_CON(33),
|
||||
RK3288_CLKSEL_CON(37),
|
||||
|
||||
/* We turn aclk_dmac1 on for suspend; this will restore it */
|
||||
RK3288_CLKGATE_CON(10),
|
||||
};
|
||||
|
||||
static u32 rk3288_saved_cru_regs[ARRAY_SIZE(rk3288_saved_cru_reg_ids)];
|
||||
@ -874,6 +874,14 @@ static int rk3288_clk_suspend(void)
|
||||
readl_relaxed(rk3288_cru_base + reg_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Going into deep sleep (specifically setting PMU_CLR_DMA in
|
||||
* RK3288_PMU_PWRMODE_CON1) appears to fail unless
|
||||
* "aclk_dmac1" is on.
|
||||
*/
|
||||
writel_relaxed(1 << (12 + 16),
|
||||
rk3288_cru_base + RK3288_CLKGATE_CON(10));
|
||||
|
||||
/*
|
||||
* Switch PLLs other than DPLL (for SDRAM) to slow mode to
|
||||
* avoid crashes on resume. The Mask ROM on the system will
|
||||
|
@ -458,7 +458,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
RK3328_CLKSEL_CON(35), 15, 1, MFLAGS, 8, 7, DFLAGS,
|
||||
RK3328_CLKGATE_CON(2), 12, GFLAGS),
|
||||
COMPOSITE(SCLK_CRYPTO, "clk_crypto", mux_2plls_p, 0,
|
||||
RK3328_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK3328_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3328_CLKGATE_CON(2), 4, GFLAGS),
|
||||
COMPOSITE_NOMUX(SCLK_TSADC, "clk_tsadc", "clk_24m", 0,
|
||||
RK3328_CLKSEL_CON(22), 0, 10, DFLAGS,
|
||||
@ -550,15 +550,15 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
GATE(0, "hclk_rkvenc_niu", "hclk_rkvenc", 0,
|
||||
RK3328_CLKGATE_CON(25), 1, GFLAGS),
|
||||
GATE(ACLK_H265, "aclk_h265", "aclk_rkvenc", 0,
|
||||
RK3328_CLKGATE_CON(25), 0, GFLAGS),
|
||||
RK3328_CLKGATE_CON(25), 2, GFLAGS),
|
||||
GATE(PCLK_H265, "pclk_h265", "hclk_rkvenc", 0,
|
||||
RK3328_CLKGATE_CON(25), 1, GFLAGS),
|
||||
RK3328_CLKGATE_CON(25), 3, GFLAGS),
|
||||
GATE(ACLK_H264, "aclk_h264", "aclk_rkvenc", 0,
|
||||
RK3328_CLKGATE_CON(25), 0, GFLAGS),
|
||||
RK3328_CLKGATE_CON(25), 4, GFLAGS),
|
||||
GATE(HCLK_H264, "hclk_h264", "hclk_rkvenc", 0,
|
||||
RK3328_CLKGATE_CON(25), 1, GFLAGS),
|
||||
RK3328_CLKGATE_CON(25), 5, GFLAGS),
|
||||
GATE(ACLK_AXISRAM, "aclk_axisram", "aclk_rkvenc", CLK_IGNORE_UNUSED,
|
||||
RK3328_CLKGATE_CON(25), 0, GFLAGS),
|
||||
RK3328_CLKGATE_CON(25), 6, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_VENC_CORE, "sclk_venc_core", mux_4plls_p, 0,
|
||||
RK3328_CLKSEL_CON(51), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
@ -663,7 +663,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
|
||||
/* PD_GMAC */
|
||||
COMPOSITE(ACLK_GMAC, "aclk_gmac", mux_2plls_hdmiphy_p, 0,
|
||||
RK3328_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3328_CLKSEL_CON(25), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3328_CLKGATE_CON(3), 2, GFLAGS),
|
||||
COMPOSITE_NOMUX(PCLK_GMAC, "pclk_gmac", "aclk_gmac", 0,
|
||||
RK3328_CLKSEL_CON(25), 8, 3, DFLAGS,
|
||||
@ -733,7 +733,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
|
||||
/* PD_PERI */
|
||||
GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(19), 11, GFLAGS),
|
||||
GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri", 0, RK3328_CLKGATE_CON(19), 4, GFLAGS),
|
||||
GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri", 0, RK3328_CLKGATE_CON(19), 14, GFLAGS),
|
||||
|
||||
GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 0, GFLAGS),
|
||||
GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 1, GFLAGS),
|
||||
@ -913,7 +913,7 @@ static void __init rk3328_clk_init(struct device_node *np)
|
||||
&rk3328_cpuclk_data, rk3328_cpuclk_rates,
|
||||
ARRAY_SIZE(rk3328_cpuclk_rates));
|
||||
|
||||
rockchip_register_softrst(np, 11, reg_base + RK3328_SOFTRST_CON(0),
|
||||
rockchip_register_softrst(np, 12, reg_base + RK3328_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(ctx, RK3328_GLB_SRST_FST, NULL);
|
||||
|
@ -46,7 +46,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *base,
|
||||
int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
|
||||
u8 div_shift, u8 div_width, u8 div_flags,
|
||||
int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
|
||||
struct clk_div_table *div_table, int gate_offset,
|
||||
u8 gate_shift, u8 gate_flags, unsigned long flags,
|
||||
spinlock_t *lock)
|
||||
@ -95,7 +95,10 @@ static struct clk *rockchip_clk_register_branch(const char *name,
|
||||
}
|
||||
|
||||
div->flags = div_flags;
|
||||
div->reg = base + muxdiv_offset;
|
||||
if (div_offset)
|
||||
div->reg = base + div_offset;
|
||||
else
|
||||
div->reg = base + muxdiv_offset;
|
||||
div->shift = div_shift;
|
||||
div->width = div_width;
|
||||
div->lock = lock;
|
||||
@ -516,7 +519,7 @@ void __init rockchip_clk_register_branches(
|
||||
ctx->reg_base, list->muxdiv_offset,
|
||||
list->mux_shift,
|
||||
list->mux_width, list->mux_flags,
|
||||
list->div_shift, list->div_width,
|
||||
list->div_offset, list->div_shift, list->div_width,
|
||||
list->div_flags, list->div_table,
|
||||
list->gate_offset, list->gate_shift,
|
||||
list->gate_flags, flags, &ctx->lock);
|
||||
|
@ -407,6 +407,7 @@ struct rockchip_clk_branch {
|
||||
u8 mux_shift;
|
||||
u8 mux_width;
|
||||
u8 mux_flags;
|
||||
int div_offset;
|
||||
u8 div_shift;
|
||||
u8 div_width;
|
||||
u8 div_flags;
|
||||
@ -438,6 +439,28 @@ struct rockchip_clk_branch {
|
||||
.gate_flags = gf, \
|
||||
}
|
||||
|
||||
#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw, \
|
||||
mf, do, ds, dw, df, go, gs, gf) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.branch_type = branch_composite, \
|
||||
.name = cname, \
|
||||
.parent_names = pnames, \
|
||||
.num_parents = ARRAY_SIZE(pnames), \
|
||||
.flags = f, \
|
||||
.muxdiv_offset = mo, \
|
||||
.mux_shift = ms, \
|
||||
.mux_width = mw, \
|
||||
.mux_flags = mf, \
|
||||
.div_offset = do, \
|
||||
.div_shift = ds, \
|
||||
.div_width = dw, \
|
||||
.div_flags = df, \
|
||||
.gate_offset = go, \
|
||||
.gate_shift = gs, \
|
||||
.gate_flags = gf, \
|
||||
}
|
||||
|
||||
#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
|
||||
go, gs, gf) \
|
||||
{ \
|
||||
|
@ -531,7 +531,8 @@ static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram",
|
||||
|
||||
static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
|
||||
0x104, 0, 4, 24, 3, BIT(31), 0);
|
||||
0x104, 0, 4, 24, 3, BIT(31),
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
|
||||
static const u8 tcon0_table[] = { 0, 2, };
|
||||
|
@ -266,7 +266,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
|
||||
0, 4, /* M */
|
||||
24, 1, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
|
||||
0x60c, BIT(0), 0);
|
||||
@ -311,7 +311,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
|
||||
0, 3, /* M */
|
||||
24, 1, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
|
||||
0x69c, BIT(0), 0);
|
||||
@ -656,6 +656,8 @@ static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
|
||||
static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
|
||||
{ .index = 1, .div = 36621 },
|
||||
};
|
||||
|
||||
#define SUN50I_H6_HDMI_CEC_CLK_REG 0xb10
|
||||
static struct ccu_mux hdmi_cec_clk = {
|
||||
.enable = BIT(31),
|
||||
|
||||
@ -689,7 +691,7 @@ static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0",
|
||||
tcon_lcd0_parents, 0xb60,
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb3",
|
||||
0xb7c, BIT(0), 0);
|
||||
@ -704,7 +706,7 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
|
||||
0xb9c, BIT(0), 0);
|
||||
@ -1200,6 +1202,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
|
||||
val &= ~(GENMASK(21, 16) | BIT(0));
|
||||
writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG);
|
||||
|
||||
/*
|
||||
* First clock parent (osc32K) is unusable for CEC. But since there
|
||||
* is no good way to force parent switch (both run with same frequency),
|
||||
* just set second clock parent here.
|
||||
*/
|
||||
val = readl(reg + SUN50I_H6_HDMI_CEC_CLK_REG);
|
||||
val |= BIT(24);
|
||||
writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
|
||||
|
||||
return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
|
||||
}
|
||||
|
||||
|
@ -60,10 +60,6 @@
|
||||
|
||||
/* The rest of the module clocks are exported */
|
||||
|
||||
#define CLK_MBUS 99
|
||||
|
||||
/* And finally the IEP clock */
|
||||
|
||||
#define CLK_NUMBER (CLK_IEP + 1)
|
||||
|
||||
#endif /* _CCU_SUN5I_H_ */
|
||||
|
@ -513,8 +513,9 @@ static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x130, BIT(16), 0);
|
||||
|
||||
static SUNXI_CCU_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x130, BIT(31), 0);
|
||||
|
||||
static const char * const csi_mclk_parents[] = { "pll-de", "osc24M" };
|
||||
static const u8 csi_mclk_table[] = { 3, 5 };
|
||||
static const char * const csi_mclk_parents[] = { "pll-video0", "pll-de",
|
||||
"osc24M" };
|
||||
static const u8 csi_mclk_table[] = { 0, 3, 5 };
|
||||
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk",
|
||||
csi_mclk_parents, csi_mclk_table,
|
||||
0x134,
|
||||
|
@ -325,7 +325,8 @@ static SUNXI_CCU_GATE(dram_ohci_clk, "dram-ohci", "dram",
|
||||
|
||||
static const char * const de_parents[] = { "pll-video", "pll-periph0" };
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
|
||||
0x104, 0, 4, 24, 2, BIT(31), 0);
|
||||
0x104, 0, 4, 24, 2, BIT(31),
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static const char * const tcon_parents[] = { "pll-video" };
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
|
||||
|
@ -240,7 +240,7 @@ static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_spdif_parents,
|
||||
/* The BSP header file has a CIR_CFG, but no mod clock uses this definition */
|
||||
|
||||
static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
|
||||
0x0cc, BIT(8), 0);
|
||||
0x0cc, BIT(1), 0);
|
||||
|
||||
static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr",
|
||||
0x100, BIT(0), 0);
|
||||
|
43
drivers/clk/sunxi/Kconfig
Normal file
43
drivers/clk/sunxi/Kconfig
Normal file
@ -0,0 +1,43 @@
|
||||
menuconfig CLK_SUNXI
|
||||
bool "Legacy clock support for Allwinner SoCs"
|
||||
depends on ARCH_SUNXI || COMPILE_TEST
|
||||
default y
|
||||
|
||||
if CLK_SUNXI
|
||||
|
||||
config CLK_SUNXI_CLOCKS
|
||||
bool "Legacy clock drivers"
|
||||
default y
|
||||
help
|
||||
Legacy clock drivers being used on older (A10, A13, A20,
|
||||
A23, A31, A80) SoCs. These drivers are kept around for
|
||||
Device Tree backward compatibility issues, in case one would
|
||||
still use a Device Tree with one clock provider by
|
||||
node. Newer Device Trees and newer SoCs use the drivers
|
||||
controlled by CONFIG_SUNXI_CCU.
|
||||
|
||||
config CLK_SUNXI_PRCM_SUN6I
|
||||
bool "Legacy A31 PRCM driver"
|
||||
select MFD_SUN6I_PRCM
|
||||
default y
|
||||
help
|
||||
Legacy clock driver for the A31 PRCM clocks. Those are
|
||||
usually needed for the PMIC communication, mostly.
|
||||
|
||||
config CLK_SUNXI_PRCM_SUN8I
|
||||
bool "Legacy sun8i PRCM driver"
|
||||
select MFD_SUN6I_PRCM
|
||||
default y
|
||||
help
|
||||
Legacy clock driver for the sun8i family PRCM clocks.
|
||||
Those are usually needed for the PMIC communication,
|
||||
mostly.
|
||||
|
||||
config CLK_SUNXI_PRCM_SUN9I
|
||||
bool "Legacy A80 PRCM driver"
|
||||
default y
|
||||
help
|
||||
Legacy clock driver for the A80 PRCM clocks. Those are
|
||||
usually needed for the PMIC communication, mostly.
|
||||
|
||||
endif
|
@ -3,27 +3,32 @@
|
||||
# Makefile for sunxi specific clk
|
||||
#
|
||||
|
||||
obj-y += clk-sunxi.o clk-factors.o
|
||||
obj-y += clk-a10-codec.o
|
||||
obj-y += clk-a10-hosc.o
|
||||
obj-y += clk-a10-mod1.o
|
||||
obj-y += clk-a10-pll2.o
|
||||
obj-y += clk-a10-ve.o
|
||||
obj-y += clk-a20-gmac.o
|
||||
obj-y += clk-mod0.o
|
||||
obj-y += clk-simple-gates.o
|
||||
obj-y += clk-sun4i-display.o
|
||||
obj-y += clk-sun4i-pll3.o
|
||||
obj-y += clk-sun4i-tcon-ch1.o
|
||||
obj-y += clk-sun8i-bus-gates.o
|
||||
obj-y += clk-sun8i-mbus.o
|
||||
obj-y += clk-sun9i-core.o
|
||||
obj-y += clk-sun9i-mmc.o
|
||||
obj-y += clk-usb.o
|
||||
obj-$(CONFIG_CLK_SUNXI) += clk-factors.o
|
||||
|
||||
obj-$(CONFIG_MACH_SUN9I) += clk-sun8i-apb0.o
|
||||
obj-$(CONFIG_MACH_SUN9I) += clk-sun9i-cpus.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sunxi.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-codec.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-hosc.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-mod1.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-pll2.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-ve.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a20-gmac.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-mod0.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-simple-gates.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun4i-display.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun4i-pll3.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun4i-tcon-ch1.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun8i-bus-gates.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun8i-mbus.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun9i-core.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun9i-mmc.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-usb.o
|
||||
|
||||
obj-$(CONFIG_MFD_SUN6I_PRCM) += \
|
||||
clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
|
||||
clk-sun8i-apb0.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun8i-apb0.o
|
||||
obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun9i-cpus.o
|
||||
|
||||
obj-$(CONFIG_CLK_SUNXI_PRCM_SUN6I) += clk-sun6i-apb0.o
|
||||
obj-$(CONFIG_CLK_SUNXI_PRCM_SUN6I) += clk-sun6i-apb0-gates.o
|
||||
obj-$(CONFIG_CLK_SUNXI_PRCM_SUN6I) += clk-sun6i-ar100.o
|
||||
|
||||
obj-$(CONFIG_CLK_SUNXI_PRCM_SUN8I) += clk-sun8i-apb0.o
|
||||
obj-$(CONFIG_CLK_SUNXI_PRCM_SUN8I) += clk-sun6i-apb0-gates.o
|
||||
|
@ -100,7 +100,7 @@
|
||||
#define CLK_AVS 96
|
||||
#define CLK_HDMI 97
|
||||
#define CLK_GPU 98
|
||||
|
||||
#define CLK_MBUS 99
|
||||
#define CLK_IEP 100
|
||||
|
||||
#endif /* _DT_BINDINGS_CLK_SUN5I_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user