Merge branches 'clk-bcm63xx', 'clk-silabs', 'clk-lochnagar' and 'clk-rockchip' into clk-next
- Support gated clk controller on MIPS based BCM63XX SoCs - Small frequency support for SiLabs Si544 chips - Support SiLabs Si5341 and Si5340 chips * clk-bcm63xx: clk: add BCM63XX gated clock controller driver devicetree: document the BCM63XX gated clock bindings * clk-silabs: clk: Add Si5341/Si5340 driver dt-bindings: clock: Add silabs,si5341 clk: clk-si544: Implement small frequency change support * clk-lochnagar: clk: lochnagar: Update DT binding doc to include the primary SPDIF MCLK clk: lochnagar: Use new parent_data approach to register clock parents * clk-rockchip: clk: rockchip: export HDMIPHY clock on rk3228 clk: rockchip: add watchdog pclk on rk3328 clk: rockchip: add clock id for hdmi_phy special clock on rk3228 clk: rockchip: add clock id for watchdog pclk on rk3328 clk: rockchip: convert pclk_wdt boilerplat to new SGRF_GATE macro clk: rockchip: add a type from SGRF-controlled gate clocks clk: rockchip: Remove 48 MHz PLL rate from rk3288 clk: rockchip: add 1.464GHz cpu-clock rate to rk3228 clk: rockchip: Slightly more accurate math in rockchip_mmc_get_phase() clk: rockchip: Don't yell about bad mmc phases when getting clk: rockchip: Use clk_hw_get_rate() in MMC phase calculation
This commit is contained in:
commit
b1511f7a48
21 changed files with 1998 additions and 176 deletions
|
@ -0,0 +1,22 @@
|
|||
Gated Clock Controller Bindings for MIPS based BCM63XX SoCs
|
||||
|
||||
Required properties:
|
||||
- compatible: must be one of:
|
||||
"brcm,bcm3368-clocks"
|
||||
"brcm,bcm6328-clocks"
|
||||
"brcm,bcm6358-clocks"
|
||||
"brcm,bcm6362-clocks"
|
||||
"brcm,bcm6368-clocks"
|
||||
"brcm,bcm63268-clocks"
|
||||
|
||||
- reg: Address and length of the register set
|
||||
- #clock-cells: must be <1>
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
clkctl: clock-controller@10000004 {
|
||||
compatible = "brcm,bcm6328-clocks";
|
||||
reg = <0x10000004 0x4>;
|
||||
#clock-cells = <1>;
|
||||
};
|
|
@ -40,6 +40,7 @@ Optional properties:
|
|||
input audio clocks from host system.
|
||||
- ln-psia1-mclk, ln-psia2-mclk : Optional input audio clocks from
|
||||
external connector.
|
||||
- ln-spdif-mclk : Optional input audio clock from SPDIF.
|
||||
- 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.
|
||||
|
|
162
Documentation/devicetree/bindings/clock/silabs,si5341.txt
Normal file
162
Documentation/devicetree/bindings/clock/silabs,si5341.txt
Normal file
|
@ -0,0 +1,162 @@
|
|||
Binding for Silicon Labs Si5341 and Si5340 programmable i2c clock generator.
|
||||
|
||||
Reference
|
||||
[1] Si5341 Data Sheet
|
||||
https://www.silabs.com/documents/public/data-sheets/Si5341-40-D-DataSheet.pdf
|
||||
[2] Si5341 Reference Manual
|
||||
https://www.silabs.com/documents/public/reference-manuals/Si5341-40-D-RM.pdf
|
||||
|
||||
The Si5341 and Si5340 are programmable i2c clock generators with up to 10 output
|
||||
clocks. The chip contains a PLL that sources 5 (or 4) multisynth clocks, which
|
||||
in turn can be directed to any of the 10 (or 4) outputs through a divider.
|
||||
The internal structure of the clock generators can be found in [2].
|
||||
|
||||
The driver can be used in "as is" mode, reading the current settings from the
|
||||
chip at boot, in case you have a (pre-)programmed device. If the PLL is not
|
||||
configured when the driver probes, it assumes the driver must fully initialize
|
||||
it.
|
||||
|
||||
The device type, speed grade and revision are determined runtime by probing.
|
||||
|
||||
The driver currently only supports XTAL input mode, and does not support any
|
||||
fancy input configurations. They can still be programmed into the chip and
|
||||
the driver will leave them "as is".
|
||||
|
||||
==I2C device node==
|
||||
|
||||
Required properties:
|
||||
- compatible: shall be one of the following:
|
||||
"silabs,si5340" - Si5340 A/B/C/D
|
||||
"silabs,si5341" - Si5341 A/B/C/D
|
||||
- reg: i2c device address, usually 0x74
|
||||
- #clock-cells: from common clock binding; shall be set to 2.
|
||||
The first value is "0" for outputs, "1" for synthesizers.
|
||||
The second value is the output or synthesizer index.
|
||||
- clocks: from common clock binding; list of parent clock handles,
|
||||
corresponding to inputs. Use a fixed clock for the "xtal" input.
|
||||
At least one must be present.
|
||||
- clock-names: One of: "xtal", "in0", "in1", "in2"
|
||||
- vdd-supply: Regulator node for VDD
|
||||
|
||||
Optional properties:
|
||||
- vdda-supply: Regulator node for VDDA
|
||||
- vdds-supply: Regulator node for VDDS
|
||||
- silabs,pll-m-num, silabs,pll-m-den: Numerator and denominator for PLL
|
||||
feedback divider. Must be such that the PLL output is in the valid range. For
|
||||
example, to create 14GHz from a 48MHz xtal, use m-num=14000 and m-den=48. Only
|
||||
the fraction matters, using 3500 and 12 will deliver the exact same result.
|
||||
If these are not specified, and the PLL is not yet programmed when the driver
|
||||
probes, the PLL will be set to 14GHz.
|
||||
- silabs,reprogram: When present, the driver will always assume the device must
|
||||
be initialized, and always performs the soft-reset routine. Since this will
|
||||
temporarily stop all output clocks, don't do this if the chip is generating
|
||||
the CPU clock for example.
|
||||
- interrupts: Interrupt for INTRb pin.
|
||||
- #address-cells: shall be set to 1.
|
||||
- #size-cells: shall be set to 0.
|
||||
|
||||
|
||||
== Child nodes: Outputs ==
|
||||
|
||||
The child nodes list the output clocks.
|
||||
|
||||
Each of the clock outputs can be overwritten individually by using a child node.
|
||||
If a child node for a clock output is not set, the configuration remains
|
||||
unchanged.
|
||||
|
||||
Required child node properties:
|
||||
- reg: number of clock output.
|
||||
|
||||
Optional child node properties:
|
||||
- vdd-supply: Regulator node for VDD for this output. The driver selects default
|
||||
values for common-mode and amplitude based on the voltage.
|
||||
- silabs,format: Output format, one of:
|
||||
1 = differential (defaults to LVDS levels)
|
||||
2 = low-power (defaults to HCSL levels)
|
||||
4 = LVCMOS
|
||||
- silabs,common-mode: Manually override output common mode, see [2] for values
|
||||
- silabs,amplitude: Manually override output amplitude, see [2] for values
|
||||
- silabs,synth-master: boolean. If present, this output is allowed to change the
|
||||
multisynth frequency dynamically.
|
||||
- silabs,silabs,disable-high: boolean. If set, the clock output is driven HIGH
|
||||
when disabled, otherwise it's driven LOW.
|
||||
|
||||
==Example==
|
||||
|
||||
/* 48MHz reference crystal */
|
||||
ref48: ref48M {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
||||
i2c-master-node {
|
||||
/* Programmable clock (for logic) */
|
||||
si5341: clock-generator@74 {
|
||||
reg = <0x74>;
|
||||
compatible = "silabs,si5341";
|
||||
#clock-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&ref48>;
|
||||
clock-names = "xtal";
|
||||
|
||||
silabs,pll-m-num = <14000>; /* PLL at 14.0 GHz */
|
||||
silabs,pll-m-den = <48>;
|
||||
silabs,reprogram; /* Chips are not programmed, always reset */
|
||||
|
||||
out@0 {
|
||||
reg = <0>;
|
||||
silabs,format = <1>; /* LVDS 3v3 */
|
||||
silabs,common-mode = <3>;
|
||||
silabs,amplitude = <3>;
|
||||
silabs,synth-master;
|
||||
};
|
||||
|
||||
/*
|
||||
* Output 6 configuration:
|
||||
* LVDS 1v8
|
||||
*/
|
||||
out@6 {
|
||||
reg = <6>;
|
||||
silabs,format = <1>; /* LVDS 1v8 */
|
||||
silabs,common-mode = <13>;
|
||||
silabs,amplitude = <3>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Output 8 configuration:
|
||||
* HCSL 3v3
|
||||
*/
|
||||
out@8 {
|
||||
reg = <8>;
|
||||
silabs,format = <2>;
|
||||
silabs,common-mode = <11>;
|
||||
silabs,amplitude = <3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
some-video-node {
|
||||
/* Standard clock bindings */
|
||||
clock-names = "pixel";
|
||||
clocks = <&si5341 0 7>; /* Output 7 */
|
||||
|
||||
/* Set output 7 to use syntesizer 3 as its parent */
|
||||
assigned-clocks = <&si5341 0 7>, <&si5341 1 3>;
|
||||
assigned-clock-parents = <&si5341 1 3>;
|
||||
/* Set output 7 to 148.5 MHz using a synth frequency of 594 MHz */
|
||||
assigned-clock-rates = <148500000>, <594000000>;
|
||||
};
|
||||
|
||||
some-audio-node {
|
||||
clock-names = "i2s-clk";
|
||||
clocks = <&si5341 0 0>;
|
||||
/*
|
||||
* since output 0 is a synth-master, the synth will be automatically set
|
||||
* to an appropriate frequency when the audio driver requests another
|
||||
* frequency. We give control over synth 2 to this output here.
|
||||
*/
|
||||
assigned-clocks = <&si5341 0 0>;
|
||||
assigned-clock-parents = <&si5341 1 2>;
|
||||
};
|
|
@ -91,6 +91,17 @@ config COMMON_CLK_SCPI
|
|||
This driver uses SCPI Message Protocol to interact with the
|
||||
firmware providing all the clock controls.
|
||||
|
||||
config COMMON_CLK_SI5341
|
||||
tristate "Clock driver for SiLabs 5341 and 5340 A/B/C/D devices"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports Silicon Labs Si5341 and Si5340 programmable clock
|
||||
generators. Not all features of these chips are currently supported
|
||||
by the driver, in particular it only supports XTAL input. The chip can
|
||||
be pre-programmed to support other configurations and features not yet
|
||||
implemented in the driver.
|
||||
|
||||
config COMMON_CLK_SI5351
|
||||
tristate "Clock driver for SiLabs 5351A/B/C"
|
||||
depends on I2C
|
||||
|
|
|
@ -49,6 +49,7 @@ obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o
|
|||
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI5341) += clk-si5341.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI544) += clk-si544.o
|
||||
|
|
|
@ -16,6 +16,14 @@ config CLK_BCM_63XX
|
|||
Enable common clock framework support for Broadcom BCM63xx DSL SoCs
|
||||
based on the ARM architecture
|
||||
|
||||
config CLK_BCM_63XX_GATE
|
||||
bool "Broadcom BCM63xx gated clock support"
|
||||
depends on BMIPS_GENERIC || COMPILE_TEST
|
||||
default BMIPS_GENERIC
|
||||
help
|
||||
Enable common clock framework support for Broadcom BCM63xx DSL SoCs
|
||||
based on the MIPS architecture
|
||||
|
||||
config CLK_BCM_KONA
|
||||
bool "Broadcom Kona CCU clock support"
|
||||
depends on ARCH_BCM_MOBILE || COMPILE_TEST
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o
|
||||
obj-$(CONFIG_CLK_BCM_63XX_GATE) += clk-bcm63xx-gate.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
|
||||
|
|
238
drivers/clk/bcm/clk-bcm63xx-gate.c
Normal file
238
drivers/clk/bcm/clk-bcm63xx-gate.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct clk_bcm63xx_table_entry {
|
||||
const char * const name;
|
||||
u8 bit;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct clk_bcm63xx_hw {
|
||||
void __iomem *regs;
|
||||
spinlock_t lock;
|
||||
|
||||
struct clk_hw_onecell_data data;
|
||||
};
|
||||
|
||||
static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
|
||||
{ .name = "mac", .bit = 3, },
|
||||
{ .name = "tc", .bit = 5, },
|
||||
{ .name = "us_top", .bit = 6, },
|
||||
{ .name = "ds_top", .bit = 7, },
|
||||
{ .name = "acm", .bit = 8, },
|
||||
{ .name = "spi", .bit = 9, },
|
||||
{ .name = "usbs", .bit = 10, },
|
||||
{ .name = "bmu", .bit = 11, },
|
||||
{ .name = "pcm", .bit = 12, },
|
||||
{ .name = "ntp", .bit = 13, },
|
||||
{ .name = "acp_b", .bit = 14, },
|
||||
{ .name = "acp_a", .bit = 15, },
|
||||
{ .name = "emusb", .bit = 17, },
|
||||
{ .name = "enet0", .bit = 18, },
|
||||
{ .name = "enet1", .bit = 19, },
|
||||
{ .name = "usbsu", .bit = 20, },
|
||||
{ .name = "ephy", .bit = 21, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
|
||||
{ .name = "phy_mips", .bit = 0, },
|
||||
{ .name = "adsl_qproc", .bit = 1, },
|
||||
{ .name = "adsl_afe", .bit = 2, },
|
||||
{ .name = "adsl", .bit = 3, },
|
||||
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, },
|
||||
{ .name = "sar", .bit = 5, },
|
||||
{ .name = "pcm", .bit = 6, },
|
||||
{ .name = "usbd", .bit = 7, },
|
||||
{ .name = "usbh", .bit = 8, },
|
||||
{ .name = "hsspi", .bit = 9, },
|
||||
{ .name = "pcie", .bit = 10, },
|
||||
{ .name = "robosw", .bit = 11, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
|
||||
{ .name = "enet", .bit = 4, },
|
||||
{ .name = "adslphy", .bit = 5, },
|
||||
{ .name = "pcm", .bit = 8, },
|
||||
{ .name = "spi", .bit = 9, },
|
||||
{ .name = "usbs", .bit = 10, },
|
||||
{ .name = "sar", .bit = 11, },
|
||||
{ .name = "emusb", .bit = 17, },
|
||||
{ .name = "enet0", .bit = 18, },
|
||||
{ .name = "enet1", .bit = 19, },
|
||||
{ .name = "usbsu", .bit = 20, },
|
||||
{ .name = "ephy", .bit = 21, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
|
||||
{ .name = "adsl_qproc", .bit = 1, },
|
||||
{ .name = "adsl_afe", .bit = 2, },
|
||||
{ .name = "adsl", .bit = 3, },
|
||||
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, },
|
||||
{ .name = "wlan_ocp", .bit = 5, },
|
||||
{ .name = "swpkt_usb", .bit = 7, },
|
||||
{ .name = "swpkt_sar", .bit = 8, },
|
||||
{ .name = "sar", .bit = 9, },
|
||||
{ .name = "robosw", .bit = 10, },
|
||||
{ .name = "pcm", .bit = 11, },
|
||||
{ .name = "usbd", .bit = 12, },
|
||||
{ .name = "usbh", .bit = 13, },
|
||||
{ .name = "ipsec", .bit = 14, },
|
||||
{ .name = "spi", .bit = 15, },
|
||||
{ .name = "hsspi", .bit = 16, },
|
||||
{ .name = "pcie", .bit = 17, },
|
||||
{ .name = "fap", .bit = 18, },
|
||||
{ .name = "phymips", .bit = 19, },
|
||||
{ .name = "nand", .bit = 20, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
|
||||
{ .name = "vdsl_qproc", .bit = 2, },
|
||||
{ .name = "vdsl_afe", .bit = 3, },
|
||||
{ .name = "vdsl_bonding", .bit = 4, },
|
||||
{ .name = "vdsl", .bit = 5, },
|
||||
{ .name = "phymips", .bit = 6, },
|
||||
{ .name = "swpkt_usb", .bit = 7, },
|
||||
{ .name = "swpkt_sar", .bit = 8, },
|
||||
{ .name = "spi", .bit = 9, },
|
||||
{ .name = "usbd", .bit = 10, },
|
||||
{ .name = "sar", .bit = 11, },
|
||||
{ .name = "robosw", .bit = 12, },
|
||||
{ .name = "utopia", .bit = 13, },
|
||||
{ .name = "pcm", .bit = 14, },
|
||||
{ .name = "usbh", .bit = 15, },
|
||||
{ .name = "disable_gless", .bit = 16, },
|
||||
{ .name = "nand", .bit = 17, },
|
||||
{ .name = "ipsec", .bit = 18, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
|
||||
{ .name = "disable_gless", .bit = 0, },
|
||||
{ .name = "vdsl_qproc", .bit = 1, },
|
||||
{ .name = "vdsl_afe", .bit = 2, },
|
||||
{ .name = "vdsl", .bit = 3, },
|
||||
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, },
|
||||
{ .name = "wlan_ocp", .bit = 5, },
|
||||
{ .name = "dect", .bit = 6, },
|
||||
{ .name = "fap0", .bit = 7, },
|
||||
{ .name = "fap1", .bit = 8, },
|
||||
{ .name = "sar", .bit = 9, },
|
||||
{ .name = "robosw", .bit = 10, },
|
||||
{ .name = "pcm", .bit = 11, },
|
||||
{ .name = "usbd", .bit = 12, },
|
||||
{ .name = "usbh", .bit = 13, },
|
||||
{ .name = "ipsec", .bit = 14, },
|
||||
{ .name = "spi", .bit = 15, },
|
||||
{ .name = "hsspi", .bit = 16, },
|
||||
{ .name = "pcie", .bit = 17, },
|
||||
{ .name = "phymips", .bit = 18, },
|
||||
{ .name = "gmac", .bit = 19, },
|
||||
{ .name = "nand", .bit = 20, },
|
||||
{ .name = "tbus", .bit = 27, },
|
||||
{ .name = "robosw250", .bit = 31, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int clk_bcm63xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct clk_bcm63xx_table_entry *entry, *table;
|
||||
struct clk_bcm63xx_hw *hw;
|
||||
struct resource *r;
|
||||
u8 maxbit = 0;
|
||||
int i, ret;
|
||||
|
||||
table = of_device_get_match_data(&pdev->dev);
|
||||
if (!table)
|
||||
return -EINVAL;
|
||||
|
||||
for (entry = table; entry->name; entry++)
|
||||
maxbit = max_t(u8, maxbit, entry->bit);
|
||||
|
||||
hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
|
||||
GFP_KERNEL);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
spin_lock_init(&hw->lock);
|
||||
|
||||
hw->data.num = maxbit;
|
||||
for (i = 0; i < maxbit; i++)
|
||||
hw->data.hws[i] = ERR_PTR(-ENODEV);
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hw->regs = devm_ioremap_resource(&pdev->dev, r);
|
||||
if (IS_ERR(hw->regs))
|
||||
return PTR_ERR(hw->regs);
|
||||
|
||||
for (entry = table; entry->name; entry++) {
|
||||
struct clk_hw *clk;
|
||||
|
||||
clk = clk_hw_register_gate(&pdev->dev, entry->name, NULL,
|
||||
entry->flags, hw->regs, entry->bit,
|
||||
CLK_GATE_BIG_ENDIAN, &hw->lock);
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
hw->data.hws[entry->bit] = clk;
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
|
||||
&hw->data);
|
||||
if (!ret)
|
||||
return 0;
|
||||
out_err:
|
||||
for (i = 0; i < hw->data.num; i++) {
|
||||
if (!IS_ERR(hw->data.hws[i]))
|
||||
clk_hw_unregister_gate(hw->data.hws[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clk_bcm63xx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_bcm63xx_hw *hw = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
of_clk_del_provider(pdev->dev.of_node);
|
||||
|
||||
for (i = 0; i < hw->data.num; i++) {
|
||||
if (!IS_ERR(hw->data.hws[i]))
|
||||
clk_hw_unregister_gate(hw->data.hws[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id clk_bcm63xx_dt_ids[] = {
|
||||
{ .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
|
||||
{ .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
|
||||
{ .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
|
||||
{ .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },
|
||||
{ .compatible = "brcm,bcm6368-clocks", .data = &bcm6368_clocks, },
|
||||
{ .compatible = "brcm,bcm63268-clocks", .data = &bcm63268_clocks, },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver clk_bcm63xx = {
|
||||
.probe = clk_bcm63xx_probe,
|
||||
.remove = clk_bcm63xx_remove,
|
||||
.driver = {
|
||||
.name = "bcm63xx-clock",
|
||||
.of_match_table = clk_bcm63xx_dt_ids,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(clk_bcm63xx);
|
|
@ -16,7 +16,6 @@
|
|||
#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>
|
||||
|
||||
|
@ -40,48 +39,46 @@ struct lochnagar_clk {
|
|||
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",
|
||||
#define LN_PARENT(NAME) { .name = NAME, .fw_name = NAME }
|
||||
|
||||
static const struct clk_parent_data lochnagar1_clk_parents[] = {
|
||||
LN_PARENT("ln-none"),
|
||||
LN_PARENT("ln-spdif-mclk"),
|
||||
LN_PARENT("ln-psia1-mclk"),
|
||||
LN_PARENT("ln-psia2-mclk"),
|
||||
LN_PARENT("ln-cdc-clkout"),
|
||||
LN_PARENT("ln-dsp-clkout"),
|
||||
LN_PARENT("ln-pmic-32k"),
|
||||
LN_PARENT("ln-gf-mclk1"),
|
||||
LN_PARENT("ln-gf-mclk3"),
|
||||
LN_PARENT("ln-gf-mclk2"),
|
||||
LN_PARENT("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",
|
||||
static const struct clk_parent_data lochnagar2_clk_parents[] = {
|
||||
LN_PARENT("ln-none"),
|
||||
LN_PARENT("ln-cdc-clkout"),
|
||||
LN_PARENT("ln-dsp-clkout"),
|
||||
LN_PARENT("ln-pmic-32k"),
|
||||
LN_PARENT("ln-spdif-mclk"),
|
||||
LN_PARENT("ln-clk-12m"),
|
||||
LN_PARENT("ln-clk-11m"),
|
||||
LN_PARENT("ln-clk-24m"),
|
||||
LN_PARENT("ln-clk-22m"),
|
||||
LN_PARENT("ln-clk-8m"),
|
||||
LN_PARENT("ln-usb-clk-24m"),
|
||||
LN_PARENT("ln-gf-mclk1"),
|
||||
LN_PARENT("ln-gf-mclk3"),
|
||||
LN_PARENT("ln-gf-mclk2"),
|
||||
LN_PARENT("ln-psia1-mclk"),
|
||||
LN_PARENT("ln-psia2-mclk"),
|
||||
LN_PARENT("ln-spdif-clkout"),
|
||||
LN_PARENT("ln-adat-mclk"),
|
||||
LN_PARENT("ln-usb-clk-12m"),
|
||||
};
|
||||
|
||||
#define LN1_CLK(ID, NAME, REG) \
|
||||
|
@ -122,6 +119,24 @@ static const struct lochnagar_clk lochnagar2_clks[LOCHNAGAR_NUM_CLOCKS] = {
|
|||
LN2_CLK(SOUNDCARD_MCLK, "ln-soundcard-mclk"),
|
||||
};
|
||||
|
||||
struct lochnagar_config {
|
||||
const struct clk_parent_data *parents;
|
||||
int nparents;
|
||||
const struct lochnagar_clk *clks;
|
||||
};
|
||||
|
||||
static const struct lochnagar_config lochnagar1_conf = {
|
||||
.parents = lochnagar1_clk_parents,
|
||||
.nparents = ARRAY_SIZE(lochnagar1_clk_parents),
|
||||
.clks = lochnagar1_clks,
|
||||
};
|
||||
|
||||
static const struct lochnagar_config lochnagar2_conf = {
|
||||
.parents = lochnagar2_clk_parents,
|
||||
.nparents = ARRAY_SIZE(lochnagar2_clk_parents),
|
||||
.clks = lochnagar2_clks,
|
||||
};
|
||||
|
||||
static inline struct lochnagar_clk *lochnagar_hw_to_lclk(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct lochnagar_clk, hw);
|
||||
|
@ -183,7 +198,7 @@ static u8 lochnagar_clk_get_parent(struct clk_hw *hw)
|
|||
if (ret < 0) {
|
||||
dev_dbg(priv->dev, "Failed to read parent of %s: %d\n",
|
||||
lclk->name, ret);
|
||||
return priv->nparents;
|
||||
return hw->init->num_parents;
|
||||
}
|
||||
|
||||
val &= lclk->src_mask;
|
||||
|
@ -198,46 +213,6 @@ static const struct clk_ops lochnagar_clk_ops = {
|
|||
.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)
|
||||
{
|
||||
|
@ -252,16 +227,42 @@ lochnagar_of_clk_hw_get(struct of_phandle_args *clkspec, void *data)
|
|||
return &priv->lclks[idx].hw;
|
||||
}
|
||||
|
||||
static int lochnagar_init_clks(struct lochnagar_clk_priv *priv)
|
||||
static const struct of_device_id lochnagar_of_match[] = {
|
||||
{ .compatible = "cirrus,lochnagar1-clk", .data = &lochnagar1_conf },
|
||||
{ .compatible = "cirrus,lochnagar2-clk", .data = &lochnagar2_conf },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lochnagar_of_match);
|
||||
|
||||
static int lochnagar_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_init_data clk_init = {
|
||||
.ops = &lochnagar_clk_ops,
|
||||
.parent_names = priv->parents,
|
||||
.num_parents = priv->nparents,
|
||||
};
|
||||
struct device *dev = &pdev->dev;
|
||||
struct lochnagar_clk_priv *priv;
|
||||
const struct of_device_id *of_id;
|
||||
struct lochnagar_clk *lclk;
|
||||
struct lochnagar_config *conf;
|
||||
int ret, i;
|
||||
|
||||
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);
|
||||
conf = (struct lochnagar_config *)of_id->data;
|
||||
|
||||
memcpy(priv->lclks, conf->clks, sizeof(priv->lclks));
|
||||
|
||||
clk_init.parent_data = conf->parents;
|
||||
clk_init.num_parents = conf->nparents;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->lclks); i++) {
|
||||
lclk = &priv->lclks[i];
|
||||
|
||||
|
@ -273,55 +274,21 @@ static int lochnagar_init_clks(struct lochnagar_clk_priv *priv)
|
|||
lclk->priv = priv;
|
||||
lclk->hw.init = &clk_init;
|
||||
|
||||
ret = devm_clk_hw_register(priv->dev, &lclk->hw);
|
||||
ret = devm_clk_hw_register(dev, &lclk->hw);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to register %s: %d\n",
|
||||
dev_err(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);
|
||||
ret = devm_of_clk_add_hw_provider(dev, lochnagar_of_clk_hw_get, priv);
|
||||
if (ret < 0)
|
||||
dev_err(priv->dev, "Failed to register provider: %d\n", ret);
|
||||
dev_err(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",
|
||||
|
|
1346
drivers/clk/clk-si5341.c
Normal file
1346
drivers/clk/clk-si5341.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -50,6 +51,11 @@
|
|||
/* Lowest frequency synthesizeable using only the HS divider */
|
||||
#define MIN_HSDIV_FREQ (FVCO_MIN / HS_DIV_MAX)
|
||||
|
||||
/* Range and interpretation of the adjustment value */
|
||||
#define DELTA_M_MAX 8161512
|
||||
#define DELTA_M_FRAC_NUM 19
|
||||
#define DELTA_M_FRAC_DEN 20000
|
||||
|
||||
enum si544_speed_grade {
|
||||
si544a,
|
||||
si544b,
|
||||
|
@ -71,12 +77,14 @@ struct clk_si544 {
|
|||
* @hs_div: 1st divider, 5..2046, must be even when >33
|
||||
* @ls_div_bits: 2nd divider, as 2^x, range 0..5
|
||||
* If ls_div_bits is non-zero, hs_div must be even
|
||||
* @delta_m: Frequency shift for small -950..+950 ppm changes, 24 bit
|
||||
*/
|
||||
struct clk_si544_muldiv {
|
||||
u32 fb_div_frac;
|
||||
u16 fb_div_int;
|
||||
u16 hs_div;
|
||||
u8 ls_div_bits;
|
||||
s32 delta_m;
|
||||
};
|
||||
|
||||
/* Enables or disables the output driver */
|
||||
|
@ -134,9 +142,30 @@ static int si544_get_muldiv(struct clk_si544 *data,
|
|||
settings->fb_div_int = reg[4] | (reg[5] & 0x07) << 8;
|
||||
settings->fb_div_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
|
||||
reg[3] << 24;
|
||||
|
||||
err = regmap_bulk_read(data->regmap, SI544_REG_ADPLL_DELTA_M0, reg, 3);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Interpret as 24-bit signed number */
|
||||
settings->delta_m = reg[0] << 8 | reg[1] << 16 | reg[2] << 24;
|
||||
settings->delta_m >>= 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si544_set_delta_m(struct clk_si544 *data, s32 delta_m)
|
||||
{
|
||||
u8 reg[3];
|
||||
|
||||
reg[0] = delta_m;
|
||||
reg[1] = delta_m >> 8;
|
||||
reg[2] = delta_m >> 16;
|
||||
|
||||
return regmap_bulk_write(data->regmap, SI544_REG_ADPLL_DELTA_M0,
|
||||
reg, 3);
|
||||
}
|
||||
|
||||
static int si544_set_muldiv(struct clk_si544 *data,
|
||||
struct clk_si544_muldiv *settings)
|
||||
{
|
||||
|
@ -238,11 +267,15 @@ static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
|
|||
do_div(vco, FXO);
|
||||
settings->fb_div_frac = vco;
|
||||
|
||||
/* Reset the frequency adjustment */
|
||||
settings->delta_m = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate resulting frequency given the register settings */
|
||||
static unsigned long si544_calc_rate(struct clk_si544_muldiv *settings)
|
||||
static unsigned long si544_calc_center_rate(
|
||||
const struct clk_si544_muldiv *settings)
|
||||
{
|
||||
u32 d = settings->hs_div * BIT(settings->ls_div_bits);
|
||||
u64 vco;
|
||||
|
@ -261,6 +294,25 @@ static unsigned long si544_calc_rate(struct clk_si544_muldiv *settings)
|
|||
return vco;
|
||||
}
|
||||
|
||||
static unsigned long si544_calc_rate(const struct clk_si544_muldiv *settings)
|
||||
{
|
||||
unsigned long rate = si544_calc_center_rate(settings);
|
||||
s64 delta = (s64)rate * (DELTA_M_FRAC_NUM * settings->delta_m);
|
||||
|
||||
/*
|
||||
* The clock adjustment is much smaller than 1 Hz, round to the
|
||||
* nearest multiple. Apparently div64_s64 rounds towards zero, hence
|
||||
* check the sign and adjust into the proper direction.
|
||||
*/
|
||||
if (settings->delta_m < 0)
|
||||
delta -= ((s64)DELTA_M_MAX * DELTA_M_FRAC_DEN) / 2;
|
||||
else
|
||||
delta += ((s64)DELTA_M_MAX * DELTA_M_FRAC_DEN) / 2;
|
||||
delta = div64_s64(delta, ((s64)DELTA_M_MAX * DELTA_M_FRAC_DEN));
|
||||
|
||||
return rate + delta;
|
||||
}
|
||||
|
||||
static unsigned long si544_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
@ -279,33 +331,60 @@ static long si544_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
unsigned long *parent_rate)
|
||||
{
|
||||
struct clk_si544 *data = to_clk_si544(hw);
|
||||
struct clk_si544_muldiv settings;
|
||||
int err;
|
||||
|
||||
if (!is_valid_frequency(data, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = si544_calc_muldiv(&settings, rate);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return si544_calc_rate(&settings);
|
||||
/* The accuracy is less than 1 Hz, so any rate is possible */
|
||||
return rate;
|
||||
}
|
||||
|
||||
/* Calculates the maximum "small" change, 950 * rate / 1000000 */
|
||||
static unsigned long si544_max_delta(unsigned long rate)
|
||||
{
|
||||
u64 num = rate;
|
||||
|
||||
num *= DELTA_M_FRAC_NUM;
|
||||
do_div(num, DELTA_M_FRAC_DEN);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static s32 si544_calc_delta(s32 delta, s32 max_delta)
|
||||
{
|
||||
s64 n = (s64)delta * DELTA_M_MAX;
|
||||
|
||||
return div_s64(n, max_delta);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update output frequency for "big" frequency changes
|
||||
*/
|
||||
static int si544_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_si544 *data = to_clk_si544(hw);
|
||||
struct clk_si544_muldiv settings;
|
||||
unsigned long center;
|
||||
long max_delta;
|
||||
long delta;
|
||||
unsigned int old_oe_state;
|
||||
int err;
|
||||
|
||||
if (!is_valid_frequency(data, rate))
|
||||
return -EINVAL;
|
||||
|
||||
/* Try using the frequency adjustment feature for a <= 950ppm change */
|
||||
err = si544_get_muldiv(data, &settings);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
center = si544_calc_center_rate(&settings);
|
||||
max_delta = si544_max_delta(center);
|
||||
delta = rate - center;
|
||||
|
||||
if (abs(delta) <= max_delta)
|
||||
return si544_set_delta_m(data,
|
||||
si544_calc_delta(delta, max_delta));
|
||||
|
||||
/* Too big for the delta adjustment, need to reprogram */
|
||||
err = si544_calc_muldiv(&settings, rate);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -321,6 +400,9 @@ static int si544_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = si544_set_delta_m(data, settings.delta_m);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = si544_set_muldiv(data, &settings);
|
||||
if (err < 0)
|
||||
|
|
|
@ -55,29 +55,27 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
|
|||
static int rockchip_mmc_get_phase(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
|
||||
unsigned long rate = clk_get_rate(hw->clk);
|
||||
unsigned long rate = clk_hw_get_rate(hw);
|
||||
u32 raw_value;
|
||||
u16 degrees;
|
||||
u32 delay_num = 0;
|
||||
|
||||
/* See the comment for rockchip_mmc_set_phase below */
|
||||
if (!rate) {
|
||||
pr_err("%s: invalid clk rate\n", __func__);
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
|
||||
|
||||
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
|
||||
|
||||
if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
|
||||
/* degrees/delaynum * 10000 */
|
||||
/* degrees/delaynum * 1000000 */
|
||||
unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
|
||||
36 * (rate / 1000000);
|
||||
36 * (rate / 10000);
|
||||
|
||||
delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
|
||||
delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
|
||||
degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
|
||||
degrees += DIV_ROUND_CLOSEST(delay_num * factor, 1000000);
|
||||
}
|
||||
|
||||
return degrees % 360;
|
||||
|
@ -86,7 +84,7 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
|
|||
static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
|
||||
{
|
||||
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
|
||||
unsigned long rate = clk_get_rate(hw->clk);
|
||||
unsigned long rate = clk_hw_get_rate(hw);
|
||||
u8 nineties, remainder;
|
||||
u8 delay_num;
|
||||
u32 raw_value;
|
||||
|
|
|
@ -803,6 +803,9 @@ static struct rockchip_clk_branch px30_clk_branches[] __initdata = {
|
|||
GATE(ACLK_GIC, "aclk_gic", "aclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 12, GFLAGS),
|
||||
GATE(ACLK_DCF, "aclk_dcf", "aclk_bus_pre", 0, PX30_CLKGATE_CON(13), 15, GFLAGS),
|
||||
|
||||
/* aclk_dmac is controlled by sgrf_soc_con1[11]. */
|
||||
SGRF_GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre"),
|
||||
|
||||
GATE(0, "hclk_bus_niu", "hclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 9, GFLAGS),
|
||||
GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 14, GFLAGS),
|
||||
GATE(HCLK_PDM, "hclk_pdm", "hclk_bus_pre", 0, PX30_CLKGATE_CON(14), 1, GFLAGS),
|
||||
|
@ -966,7 +969,6 @@ static void __init px30_clk_init(struct device_node *np)
|
|||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
|
@ -981,14 +983,6 @@ static void __init px30_clk_init(struct device_node *np)
|
|||
return;
|
||||
}
|
||||
|
||||
/* aclk_dmac is controlled by sgrf_soc_con1[11]. */
|
||||
clk = clk_register_fixed_factor(NULL, "aclk_dmac", "aclk_bus_pre", 0, 1, 1);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock aclk_dmac: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
else
|
||||
rockchip_clk_add_lookup(ctx, clk, ACLK_DMAC);
|
||||
|
||||
rockchip_clk_register_plls(ctx, px30_pll_clks,
|
||||
ARRAY_SIZE(px30_pll_clks),
|
||||
PX30_GRF_SOC_STATUS0);
|
||||
|
|
|
@ -110,6 +110,7 @@ static struct rockchip_cpuclk_rate_table rk3228_cpuclk_rates[] __initdata = {
|
|||
RK3228_CPUCLK_RATE(1608000000, 1, 7),
|
||||
RK3228_CPUCLK_RATE(1512000000, 1, 7),
|
||||
RK3228_CPUCLK_RATE(1488000000, 1, 5),
|
||||
RK3228_CPUCLK_RATE(1464000000, 1, 5),
|
||||
RK3228_CPUCLK_RATE(1416000000, 1, 5),
|
||||
RK3228_CPUCLK_RATE(1392000000, 1, 5),
|
||||
RK3228_CPUCLK_RATE(1296000000, 1, 5),
|
||||
|
@ -255,7 +256,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
|
|||
RK2928_CLKGATE_CON(4), 0, GFLAGS),
|
||||
|
||||
/* PD_MISC */
|
||||
MUX(0, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
|
||||
MUX(SCLK_HDMI_PHY, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_MISC_CON, 13, 1, MFLAGS),
|
||||
MUX(0, "usb480m_phy", mux_usb480m_phy_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_MISC_CON, 14, 1, MFLAGS),
|
||||
|
|
|
@ -122,7 +122,6 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
|
|||
RK3066_PLL_RATE( 160000000, 1, 80, 12),
|
||||
RK3066_PLL_RATE( 157500000, 1, 105, 16),
|
||||
RK3066_PLL_RATE( 126000000, 1, 84, 16),
|
||||
RK3066_PLL_RATE( 48000000, 1, 64, 32),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
@ -776,6 +775,9 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 11, GFLAGS),
|
||||
GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS),
|
||||
|
||||
/* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
|
||||
SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_pd_alive"),
|
||||
|
||||
/* pclk_pd_pmu gates */
|
||||
GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 0, GFLAGS),
|
||||
GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 1, GFLAGS),
|
||||
|
@ -924,7 +926,6 @@ static struct syscore_ops rk3288_clk_syscore_ops = {
|
|||
static void __init rk3288_clk_init(struct device_node *np)
|
||||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
struct clk *clk;
|
||||
|
||||
rk3288_cru_base = of_iomap(np, 0);
|
||||
if (!rk3288_cru_base) {
|
||||
|
@ -939,14 +940,6 @@ static void __init rk3288_clk_init(struct device_node *np)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
|
||||
clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock pclk_wdt: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
else
|
||||
rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
|
||||
|
||||
rockchip_clk_register_plls(ctx, rk3288_pll_clks,
|
||||
ARRAY_SIZE(rk3288_pll_clks),
|
||||
RK3288_GRF_SOC_STATUS1);
|
||||
|
|
|
@ -800,6 +800,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
|||
GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 0, RK3328_CLKGATE_CON(17), 15, GFLAGS),
|
||||
GATE(0, "pclk_pmu", "pclk_bus", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(28), 3, GFLAGS),
|
||||
|
||||
/* Watchdog pclk is controlled from the secure GRF */
|
||||
SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_bus"),
|
||||
|
||||
GATE(PCLK_USB3PHY_OTG, "pclk_usb3phy_otg", "pclk_phy_pre", 0, RK3328_CLKGATE_CON(28), 1, GFLAGS),
|
||||
GATE(PCLK_USB3PHY_PIPE, "pclk_usb3phy_pipe", "pclk_phy_pre", 0, RK3328_CLKGATE_CON(28), 2, GFLAGS),
|
||||
GATE(PCLK_USB3_GRF, "pclk_usb3_grf", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(17), 2, GFLAGS),
|
||||
|
|
|
@ -820,6 +820,9 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 2, GFLAGS),
|
||||
GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 1, GFLAGS),
|
||||
|
||||
/* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
|
||||
SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_pd_alive"),
|
||||
|
||||
/*
|
||||
* pclk_vio gates
|
||||
* pclk_vio comes from the exactly same source as hclk_vio
|
||||
|
@ -871,7 +874,6 @@ static void __init rk3368_clk_init(struct device_node *np)
|
|||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
|
@ -886,14 +888,6 @@ static void __init rk3368_clk_init(struct device_node *np)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
|
||||
clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock pclk_wdt: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
else
|
||||
rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
|
||||
|
||||
rockchip_clk_register_plls(ctx, rk3368_pll_clks,
|
||||
ARRAY_SIZE(rk3368_pll_clks),
|
||||
RK3368_GRF_SOC_STATUS0);
|
||||
|
|
|
@ -1304,6 +1304,9 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
|
|||
GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS),
|
||||
GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS),
|
||||
|
||||
/* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
|
||||
SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_alive"),
|
||||
|
||||
GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS),
|
||||
GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS),
|
||||
|
||||
|
@ -1531,7 +1534,6 @@ static void __init rk3399_clk_init(struct device_node *np)
|
|||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
|
@ -1546,14 +1548,6 @@ static void __init rk3399_clk_init(struct device_node *np)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
|
||||
clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_alive", 0, 1, 1);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock pclk_wdt: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
else
|
||||
rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
|
||||
|
||||
rockchip_clk_register_plls(ctx, rk3399_pll_clks,
|
||||
ARRAY_SIZE(rk3399_pll_clks), -1);
|
||||
|
||||
|
|
|
@ -820,6 +820,10 @@ struct rockchip_clk_branch {
|
|||
.gate_offset = -1, \
|
||||
}
|
||||
|
||||
/* SGRF clocks are only accessible from secure mode, so not controllable */
|
||||
#define SGRF_GATE(_id, cname, pname) \
|
||||
FACTOR(_id, cname, pname, 0, 1, 1)
|
||||
|
||||
struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
|
||||
void __iomem *base, unsigned long nr_clks);
|
||||
void rockchip_clk_of_add_provider(struct device_node *np,
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#define SCLK_WIFI 141
|
||||
#define SCLK_OTGPHY0 142
|
||||
#define SCLK_OTGPHY1 143
|
||||
#define SCLK_HDMI_PHY 144
|
||||
|
||||
/* dclk gates */
|
||||
#define DCLK_VOP 190
|
||||
|
|
|
@ -173,6 +173,7 @@
|
|||
#define PCLK_DCF 233
|
||||
#define PCLK_SARADC 234
|
||||
#define PCLK_ACODECPHY 235
|
||||
#define PCLK_WDT 236
|
||||
|
||||
/* hclk gates */
|
||||
#define HCLK_PERI 308
|
||||
|
|
Loading…
Reference in a new issue