提交 b2d8bc21 编写于 作者: M Michael Turquette

Merge remote-tracking branch 'clk/clk-next' into clk-next

......@@ -230,30 +230,7 @@ clk_register(...)
See the basic clock types in drivers/clk/clk-*.c for examples.
Part 5 - static initialization of clock data
For platforms with many clocks (often numbering into the hundreds) it
may be desirable to statically initialize some clock data. This
presents a problem since the definition of struct clk should be hidden
from everyone except for the clock core in drivers/clk/clk.c.
To get around this problem struct clk's definition is exposed in
include/linux/clk-private.h along with some macros for more easily
initializing instances of the basic clock types. These clocks must
still be initialized with the common clock framework via a call to
__clk_init.
clk-private.h must NEVER be included by code which implements struct
clk_ops callbacks, nor must it be included by any logic which pokes
around inside of struct clk at run-time. To do so is a layering
violation.
To better enforce this policy, always follow this simple rule: any
statically initialized clock data MUST be defined in a separate file
from the logic that implements its ops. Basically separate the logic
from the data and all is well.
Part 6 - Disabling clock gating of unused clocks
Part 5 - Disabling clock gating of unused clocks
Sometimes during development it can be useful to be able to bypass the
default disabling of unused clocks. For example, if drivers aren't enabling
......@@ -264,7 +241,7 @@ are sorted out.
To bypass this disabling, include "clk_ignore_unused" in the bootargs to the
kernel.
Part 7 - Locking
Part 6 - Locking
The common clock framework uses two global locks, the prepare lock and the
enable lock.
......
Mediatek apmixedsys controller
==============================
The Mediatek apmixedsys controller provides the PLLs to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt8135-apmixedsys"
- "mediatek,mt8173-apmixedsys"
- #clock-cells: Must be 1
The apmixedsys controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
apmixedsys: clock-controller@10209000 {
compatible = "mediatek,mt8173-apmixedsys";
reg = <0 0x10209000 0 0x1000>;
#clock-cells = <1>;
};
Mediatek infracfg controller
============================
The Mediatek infracfg controller provides various clocks and reset
outputs to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt8135-infracfg", "syscon"
- "mediatek,mt8173-infracfg", "syscon"
- #clock-cells: Must be 1
- #reset-cells: Must be 1
The infracfg controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Also it uses the common reset controller binding from
Documentation/devicetree/bindings/reset/reset.txt.
The available reset outputs are defined in
dt-bindings/reset-controller/mt*-resets.h
Example:
infracfg: power-controller@10001000 {
compatible = "mediatek,mt8173-infracfg", "syscon";
reg = <0 0x10001000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
Mediatek pericfg controller
===========================
The Mediatek pericfg controller provides various clocks and reset
outputs to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt8135-pericfg", "syscon"
- "mediatek,mt8173-pericfg", "syscon"
- #clock-cells: Must be 1
- #reset-cells: Must be 1
The pericfg controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Also it uses the common reset controller binding from
Documentation/devicetree/bindings/reset/reset.txt.
The available reset outputs are defined in
dt-bindings/reset-controller/mt*-resets.h
Example:
pericfg: power-controller@10003000 {
compatible = "mediatek,mt8173-pericfg", "syscon";
reg = <0 0x10003000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
Mediatek topckgen controller
============================
The Mediatek topckgen controller provides various clocks to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt8135-topckgen"
- "mediatek,mt8173-topckgen"
- #clock-cells: Must be 1
The topckgen controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
topckgen: power-controller@10000000 {
compatible = "mediatek,mt8173-topckgen";
reg = <0 0x10000000 0 0x1000>;
#clock-cells = <1>;
};
* Amlogic Meson8b Clock and Reset Unit
The Amlogic Meson8b clock controller generates and supplies clock to various
controllers within the SoC.
Required Properties:
- compatible: should be "amlogic,meson8b-clkc"
- reg: it must be composed by two tuples:
0) physical base address of the xtal register and length of memory
mapped region.
1) physical base address of the clock controller and length of memory
mapped region.
- #clock-cells: should be 1.
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
used in device tree sources.
Example: Clock controller node:
clkc: clock-controller@c1104000 {
#clock-cells = <1>;
compatible = "amlogic,meson8b-clkc";
reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
};
Example: UART controller node that consumes the clock generated by the clock
controller:
uart_AO: serial@c81004c0 {
compatible = "amlogic,meson-uart";
reg = <0xc81004c0 0x14>;
interrupts = <0 90 1>;
clocks = <&clkc CLKID_CLK81>;
status = "disabled";
};
......@@ -138,9 +138,10 @@ Some platforms may require initial configuration of default parent clocks
and clock frequencies. Such a configuration can be specified in a device tree
node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
properties. The assigned-clock-parents property should contain a list of parent
clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
property the list of assigned clock frequency values - corresponding to clocks
listed in the assigned-clocks property.
clocks in the form of a phandle and clock specifier pair and the
assigned-clock-rates property should contain a list of frequencies in Hz. Both
these properties should correspond to the clocks listed in the assigned-clocks
property.
To skip setting parent or rate of a clock its corresponding entry should be
set to 0, or can be omitted if it is not followed by any non-zero entry.
......
* Clock and reset bindings for CSR atlas7
Required properties:
- compatible: Should be "sirf,atlas7-car"
- reg: Address and length of the register set
- #clock-cells: Should be <1>
- #reset-cells: Should be <1>
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell.
The ID list atlas7_clks defined in drivers/clk/sirf/clk-atlas7.c
The reset consumer should specify the desired reset by having the reset
ID in its "reset" phandle cell.
The ID list atlas7_reset_unit defined in drivers/clk/sirf/clk-atlas7.c
Examples: Clock and reset controller node:
car: clock-controller@18620000 {
compatible = "sirf,atlas7-car";
reg = <0x18620000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
Examples: Consumers using clock or reset:
timer@10dc0000 {
compatible = "sirf,macro-tick";
reg = <0x10dc0000 0x1000>;
clocks = <&car 54>;
interrupts = <0 0 0>,
<0 1 0>,
<0 2 0>,
<0 49 0>,
<0 50 0>,
<0 51 0>;
};
uart1: uart@18020000 {
cell-index = <1>;
compatible = "sirf,macro-uart";
reg = <0x18020000 0x1000>;
clocks = <&clks 95>;
interrupts = <0 18 0>;
fifosize = <32>;
};
vpp@13110000 {
compatible = "sirf,prima2-vpp";
reg = <0x13110000 0x10000>;
interrupts = <0 31 0>;
clocks = <&car 85>;
resets = <&car 29>;
};
......@@ -52,7 +52,7 @@ usia_u0_sclk: usia_u0_sclk {
Example of consumer:
uart@e1020000 {
serial@e1020000 {
compatible = "renesas,em-uart";
reg = <0xe1020000 0x38>;
interrupts = <0 8 0>;
......
* Marvell PXA1928 Clock Controllers
The PXA1928 clock subsystem generates and supplies clock to various
controllers within the PXA1928 SoC. The PXA1928 contains 3 clock controller
blocks called APMU, MPMU, and APBC roughly corresponding to internal buses.
Required Properties:
- compatible: should be one of the following.
- "marvell,pxa1928-apmu" - APMU controller compatible
- "marvell,pxa1928-mpmu" - MPMU controller compatible
- "marvell,pxa1928-apbc" - APBC controller compatible
- reg: physical base address of the clock controller and length of memory mapped
region.
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Each clock is assigned an identifier and client nodes use the clock controller
phandle and this identifier to specify the clock which they consume.
All these identifiers can be found in <dt-bindings/clock/marvell,pxa1928.h>.
......@@ -19,6 +19,7 @@ ID Clock Peripheral
9 pex1 PCIe Cntrl 1
15 sata0 SATA Host 0
17 sdio SDHCI Host
23 crypto CESA (crypto engine)
25 tdm Time Division Mplx
28 ddr DDR Cntrl
30 sata1 SATA Host 0
......
Binding for TO CDCE925 programmable I2C clock synthesizers.
Reference
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] http://www.ti.com/product/cdce925
The driver provides clock sources for each output Y1 through Y5.
Required properties:
- compatible: Shall be "ti,cdce925"
- reg: I2C device address.
- clocks: Points to a fixed parent clock that provides the input frequency.
- #clock-cells: From common clock bindings: Shall be 1.
Optional properties:
- xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
board, or to compensate for external influences.
For both PLL1 and PLL2 an optional child node can be used to specify spread
spectrum clocking parameters for a board.
- spread-spectrum: SSC mode as defined in the data sheet.
- spread-spectrum-center: Use "centered" mode instead of "max" mode. When
present, the clock runs at the requested frequency on average. Otherwise
the requested frequency is the maximum value of the SCC range.
Example:
clockgen: cdce925pw@64 {
compatible = "cdce925";
reg = <0x64>;
clocks = <&xtal_27Mhz>;
#clock-cells = <1>;
xtal-load-pf = <5>;
/* PLL options to get SSC 1% centered */
PLL2 {
spread-spectrum = <4>;
spread-spectrum-center;
};
};
......@@ -38,6 +38,21 @@
};
};
clocks {
xinw {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "xinw";
};
xin {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
clock-output-names = "xin";
};
};
noc {
compatible = "simple-bus";
#address-cells = <1>;
......
......@@ -78,6 +78,23 @@ config COMMON_CLK_SI570
This driver supports Silicon Labs 570/571/598/599 programmable
clock generators.
config COMMON_CLK_CDCE925
tristate "Clock driver for TI CDCE925 devices"
depends on I2C
depends on OF
select REGMAP_I2C
help
---help---
This driver supports the TI CDCE925 programmable clock synthesizer.
The chip contains two PLLs with spread-spectrum clocking support and
five output dividers. The driver only supports the following setup,
and uses a fixed setting for the output muxes.
Y1 is derived from the input clock
Y2 and Y3 derive from PLL1
Y4 and Y5 derive from PLL2
Given a target output frequency, the driver will set the PLL and
divider to best approximate the desired output.
config COMMON_CLK_S2MPS11
tristate "Clock driver for S2MPS1X/S5M8767 MFD"
depends on MFD_SEC_CORE
......@@ -150,11 +167,12 @@ config COMMON_CLK_CDCE706
---help---
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/qcom/Kconfig"
endmenu
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/samsung/Kconfig"
......@@ -38,6 +38,7 @@ obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_U300) += clk-u300.o
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
......@@ -47,14 +48,14 @@ obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
obj-$(CONFIG_ARCH_HIP04) += hisilicon/
obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
endif
obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
......
......@@ -614,7 +614,7 @@ void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
const char *name = np->name;
int i;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > 2)
return;
......
......@@ -224,7 +224,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
const char *name = np->name;
struct clk_master_characteristics *characteristics;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
return;
......
......@@ -237,7 +237,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
const char *name;
struct device_node *progclknp;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
return;
......
......@@ -373,7 +373,7 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
const char *name = np->name;
int i;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > 2)
return;
......@@ -451,7 +451,7 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
const char *name = np->name;
int i;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents != 2)
return;
......
......@@ -150,7 +150,7 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
const char *parent_names[SMD_SOURCE_MAX];
const char *name = np->name;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
return;
......
......@@ -378,7 +378,7 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
const char *parent_names[USB_SOURCE_MAX];
const char *name = np->name;
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
return;
......
......@@ -153,7 +153,7 @@ static int pmc_irq_domain_xlate(struct irq_domain *d,
return 0;
}
static struct irq_domain_ops pmc_irq_ops = {
static const struct irq_domain_ops pmc_irq_ops = {
.map = pmc_irq_map,
.xlate = pmc_irq_domain_xlate,
};
......
......@@ -21,8 +21,6 @@
#define selector_clear_exists(sel) ((sel)->width = 0)
#define trigger_clear_exists(trig) FLAG_CLEAR(trig, TRIG, EXISTS)
LIST_HEAD(ccu_list); /* The list of set up CCUs */
/* Validity checking */
static bool ccu_data_offsets_valid(struct ccu_data *ccu)
......@@ -773,7 +771,6 @@ static void kona_ccu_teardown(struct ccu_data *ccu)
of_clk_del_provider(ccu->node); /* safe if never added */
ccu_clks_teardown(ccu);
list_del(&ccu->links);
of_node_put(ccu->node);
ccu->node = NULL;
iounmap(ccu->base);
......@@ -847,7 +844,6 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
goto out_err;
}
ccu->node = of_node_get(node);
list_add_tail(&ccu->links, &ccu_list);
/*
* Set up each defined kona clock and save the result in
......
......@@ -1240,7 +1240,7 @@ static bool __kona_clk_init(struct kona_clk *bcm_clk)
default:
BUG();
}
return -EINVAL;
return false;
}
/* Set a CCU and all its clocks into their desired initial state */
......
......@@ -480,7 +480,6 @@ struct ccu_data {
spinlock_t lock; /* serialization lock */
bool write_enabled; /* write access is currently enabled */
struct ccu_policy policy;
struct list_head links; /* for ccu_list */
struct device_node *node;
struct clk_onecell_data clk_data;
const char *name;
......@@ -492,7 +491,6 @@ struct ccu_data {
#define KONA_CCU_COMMON(_prefix, _name, _ccuname) \
.name = #_name "_ccu", \
.lock = __SPIN_LOCK_UNLOCKED(_name ## _ccu_data.lock), \
.links = LIST_HEAD_INIT(_name ## _ccu_data.links), \
.clk_data = { \
.clk_num = _prefix ## _ ## _ccuname ## _CCU_CLOCK_COUNT, \
}
......
......@@ -25,14 +25,7 @@
#include <asm/div64.h>
#include "berlin2-div.h"
struct berlin2_pll_map {
const u8 vcodiv[16];
u8 mult;
u8 fbdiv_shift;
u8 rfdiv_shift;
u8 divsel_shift;
};
#include "berlin2-pll.h"
struct berlin2_pll {
struct clk_hw hw;
......
......@@ -274,7 +274,7 @@ static void __init asm9260_acc_init(struct device_node *np)
u32 accuracy = 0;
base = of_io_request_and_map(np, 0, np->name);
if (!base)
if (IS_ERR(base))
panic("%s: unable to map resource", np->name);
/* register pll */
......
......@@ -556,7 +556,7 @@ static int axmclk_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
num_clks = ARRAY_SIZE(axmclk_clocks);
pr_info("axmclk: supporting %u clocks\n", num_clks);
pr_info("axmclk: supporting %zu clocks\n", num_clks);
priv = devm_kzalloc(dev, sizeof(*priv) + sizeof(*priv->clks) * num_clks,
GFP_KERNEL);
if (!priv)
......
......@@ -94,7 +94,7 @@ static const char * const cdce706_source_name[] = {
"clk_in0", "clk_in1",
};
static const char *cdce706_clkin_name[] = {
static const char * const cdce706_clkin_name[] = {
"clk_in",
};
......@@ -102,7 +102,7 @@ static const char * const cdce706_pll_name[] = {
"pll1", "pll2", "pll3",
};
static const char *cdce706_divider_parent_name[] = {
static const char * const cdce706_divider_parent_name[] = {
"clk_in", "pll1", "pll2", "pll2", "pll3",
};
......@@ -666,6 +666,7 @@ static int cdce706_probe(struct i2c_client *client,
static int cdce706_remove(struct i2c_client *client)
{
of_clk_del_provider(client->dev.of_node);
return 0;
}
......
/*
* Driver for TI Dual PLL CDCE925 clock synthesizer
*
* This driver always connects the Y1 to the input clock, Y2/Y3 to PLL1
* and Y4/Y5 to PLL2. PLL frequency is set on a first-come-first-serve
* basis. Clients can directly request any frequency that the chip can
* deliver using the standard clk framework. In addition, the device can
* be configured and activated via the devicetree.
*
* Copyright (C) 2014, Topic Embedded Products
* Licenced under GPL
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/gcd.h>
/* The chip has 2 PLLs which can be routed through dividers to 5 outputs.
* Model this as 2 PLL clocks which are parents to the outputs.
*/
#define NUMBER_OF_PLLS 2
#define NUMBER_OF_OUTPUTS 5
#define CDCE925_REG_GLOBAL1 0x01
#define CDCE925_REG_Y1SPIPDIVH 0x02
#define CDCE925_REG_PDIVL 0x03
#define CDCE925_REG_XCSEL 0x05
/* PLL parameters start at 0x10, steps of 0x10 */
#define CDCE925_OFFSET_PLL 0x10
/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */
#define CDCE925_PLL_MUX_OUTPUTS 0x14
#define CDCE925_PLL_MULDIV 0x18
#define CDCE925_PLL_FREQUENCY_MIN 80000000ul
#define CDCE925_PLL_FREQUENCY_MAX 230000000ul
struct clk_cdce925_chip;
struct clk_cdce925_output {
struct clk_hw hw;
struct clk_cdce925_chip *chip;
u8 index;
u16 pdiv; /* 1..127 for Y2-Y5; 1..1023 for Y1 */
};
#define to_clk_cdce925_output(_hw) \
container_of(_hw, struct clk_cdce925_output, hw)
struct clk_cdce925_pll {
struct clk_hw hw;
struct clk_cdce925_chip *chip;
u8 index;
u16 m; /* 1..511 */
u16 n; /* 1..4095 */
};
#define to_clk_cdce925_pll(_hw) container_of(_hw, struct clk_cdce925_pll, hw)
struct clk_cdce925_chip {
struct regmap *regmap;
struct i2c_client *i2c_client;
struct clk_cdce925_pll pll[NUMBER_OF_PLLS];
struct clk_cdce925_output clk[NUMBER_OF_OUTPUTS];
struct clk *dt_clk[NUMBER_OF_OUTPUTS];
struct clk_onecell_data onecell;
};
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static unsigned long cdce925_pll_calculate_rate(unsigned long parent_rate,
u16 n, u16 m)
{
if ((!m || !n) || (m == n))
return parent_rate; /* In bypass mode runs at same frequency */
return mult_frac(parent_rate, (unsigned long)n, (unsigned long)m);
}
static unsigned long cdce925_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
/* Output frequency of PLL is Fout = (Fin/Pdiv)*(N/M) */
struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
return cdce925_pll_calculate_rate(parent_rate, data->n, data->m);
}
static void cdce925_pll_find_rate(unsigned long rate,
unsigned long parent_rate, u16 *n, u16 *m)
{
unsigned long un;
unsigned long um;
unsigned long g;
if (rate <= parent_rate) {
/* Can always deliver parent_rate in bypass mode */
rate = parent_rate;
*n = 0;
*m = 0;
} else {
/* In PLL mode, need to apply min/max range */
if (rate < CDCE925_PLL_FREQUENCY_MIN)
rate = CDCE925_PLL_FREQUENCY_MIN;
else if (rate > CDCE925_PLL_FREQUENCY_MAX)
rate = CDCE925_PLL_FREQUENCY_MAX;
g = gcd(rate, parent_rate);
um = parent_rate / g;
un = rate / g;
/* When outside hw range, reduce to fit (rounding errors) */
while ((un > 4095) || (um > 511)) {
un >>= 1;
um >>= 1;
}
if (un == 0)
un = 1;
if (um == 0)
um = 1;
*n = un;
*m = um;
}
}
static long cdce925_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
u16 n, m;
cdce925_pll_find_rate(rate, *parent_rate, &n, &m);
return (long)cdce925_pll_calculate_rate(*parent_rate, n, m);
}
static int cdce925_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
if (!rate || (rate == parent_rate)) {
data->m = 0; /* Bypass mode */
data->n = 0;
return 0;
}
if ((rate < CDCE925_PLL_FREQUENCY_MIN) ||
(rate > CDCE925_PLL_FREQUENCY_MAX)) {
pr_debug("%s: rate %lu outside PLL range.\n", __func__, rate);
return -EINVAL;
}
if (rate < parent_rate) {
pr_debug("%s: rate %lu less than parent rate %lu.\n", __func__,
rate, parent_rate);
return -EINVAL;
}
cdce925_pll_find_rate(rate, parent_rate, &data->n, &data->m);
return 0;
}
/* calculate p = max(0, 4 - int(log2 (n/m))) */
static u8 cdce925_pll_calc_p(u16 n, u16 m)
{
u8 p;
u16 r = n / m;
if (r >= 16)
return 0;
p = 4;
while (r > 1) {
r >>= 1;
--p;
}
return p;
}
/* Returns VCO range bits for VCO1_0_RANGE */
static u8 cdce925_pll_calc_range_bits(struct clk_hw *hw, u16 n, u16 m)
{
struct clk *parent = clk_get_parent(hw->clk);
unsigned long rate = clk_get_rate(parent);
rate = mult_frac(rate, (unsigned long)n, (unsigned long)m);
if (rate >= 175000000)
return 0x3;
if (rate >= 150000000)
return 0x02;
if (rate >= 125000000)
return 0x01;
return 0x00;
}
/* I2C clock, hence everything must happen in (un)prepare because this
* may sleep */
static int cdce925_pll_prepare(struct clk_hw *hw)
{
struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
u16 n = data->n;
u16 m = data->m;
u16 r;
u8 q;
u8 p;
u16 nn;
u8 pll[4]; /* Bits are spread out over 4 byte registers */
u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
unsigned i;
if ((!m || !n) || (m == n)) {
/* Set PLL mux to bypass mode, leave the rest as is */
regmap_update_bits(data->chip->regmap,
reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
} else {
/* According to data sheet: */
/* p = max(0, 4 - int(log2 (n/m))) */
p = cdce925_pll_calc_p(n, m);
/* nn = n * 2^p */
nn = n * BIT(p);
/* q = int(nn/m) */
q = nn / m;
if ((q < 16) || (1 > 64)) {
pr_debug("%s invalid q=%d\n", __func__, q);
return -EINVAL;
}
r = nn - (m*q);
if (r > 511) {
pr_debug("%s invalid r=%d\n", __func__, r);
return -EINVAL;
}
pr_debug("%s n=%d m=%d p=%d q=%d r=%d\n", __func__,
n, m, p, q, r);
/* encode into register bits */
pll[0] = n >> 4;
pll[1] = ((n & 0x0F) << 4) | ((r >> 5) & 0x0F);
pll[2] = ((r & 0x1F) << 3) | ((q >> 3) & 0x07);
pll[3] = ((q & 0x07) << 5) | (p << 2) |
cdce925_pll_calc_range_bits(hw, n, m);
/* Write to registers */
for (i = 0; i < ARRAY_SIZE(pll); ++i)
regmap_write(data->chip->regmap,
reg_ofs + CDCE925_PLL_MULDIV + i, pll[i]);
/* Enable PLL */
regmap_update_bits(data->chip->regmap,
reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x00);
}
return 0;
}
static void cdce925_pll_unprepare(struct clk_hw *hw)
{
struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
regmap_update_bits(data->chip->regmap,
reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
}
static const struct clk_ops cdce925_pll_ops = {
.prepare = cdce925_pll_prepare,
.unprepare = cdce925_pll_unprepare,
.recalc_rate = cdce925_pll_recalc_rate,
.round_rate = cdce925_pll_round_rate,
.set_rate = cdce925_pll_set_rate,
};
static void cdce925_clk_set_pdiv(struct clk_cdce925_output *data, u16 pdiv)
{
switch (data->index) {
case 0:
regmap_update_bits(data->chip->regmap,
CDCE925_REG_Y1SPIPDIVH,
0x03, (pdiv >> 8) & 0x03);
regmap_write(data->chip->regmap, 0x03, pdiv & 0xFF);
break;
case 1:
regmap_update_bits(data->chip->regmap, 0x16, 0x7F, pdiv);
break;
case 2:
regmap_update_bits(data->chip->regmap, 0x17, 0x7F, pdiv);
break;
case 3:
regmap_update_bits(data->chip->regmap, 0x26, 0x7F, pdiv);
break;
case 4:
regmap_update_bits(data->chip->regmap, 0x27, 0x7F, pdiv);
break;
}
}
static void cdce925_clk_activate(struct clk_cdce925_output *data)
{
switch (data->index) {
case 0:
regmap_update_bits(data->chip->regmap,
CDCE925_REG_Y1SPIPDIVH, 0x0c, 0x0c);
break;
case 1:
case 2:
regmap_update_bits(data->chip->regmap, 0x14, 0x03, 0x03);
break;
case 3:
case 4:
regmap_update_bits(data->chip->regmap, 0x24, 0x03, 0x03);
break;
}
}
static int cdce925_clk_prepare(struct clk_hw *hw)
{
struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
cdce925_clk_set_pdiv(data, data->pdiv);
cdce925_clk_activate(data);
return 0;
}
static void cdce925_clk_unprepare(struct clk_hw *hw)
{
struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
/* Disable clock by setting divider to "0" */
cdce925_clk_set_pdiv(data, 0);
}
static unsigned long cdce925_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
if (data->pdiv)
return parent_rate / data->pdiv;
return 0;
}
static u16 cdce925_calc_divider(unsigned long rate,
unsigned long parent_rate)
{
unsigned long divider;
if (!rate)
return 0;
if (rate >= parent_rate)
return 1;
divider = DIV_ROUND_CLOSEST(parent_rate, rate);
if (divider > 0x7F)
divider = 0x7F;
return (u16)divider;
}
static unsigned long cdce925_clk_best_parent_rate(
struct clk_hw *hw, unsigned long rate)
{
struct clk *pll = clk_get_parent(hw->clk);
struct clk *root = clk_get_parent(pll);
unsigned long root_rate = clk_get_rate(root);
unsigned long best_rate_error = rate;
u16 pdiv_min;
u16 pdiv_max;
u16 pdiv_best;
u16 pdiv_now;
if (root_rate % rate == 0)
return root_rate; /* Don't need the PLL, use bypass */
pdiv_min = (u16)max(1ul, DIV_ROUND_UP(CDCE925_PLL_FREQUENCY_MIN, rate));
pdiv_max = (u16)min(127ul, CDCE925_PLL_FREQUENCY_MAX / rate);
if (pdiv_min > pdiv_max)
return 0; /* No can do? */
pdiv_best = pdiv_min;
for (pdiv_now = pdiv_min; pdiv_now < pdiv_max; ++pdiv_now) {
unsigned long target_rate = rate * pdiv_now;
long pll_rate = clk_round_rate(pll, target_rate);
unsigned long actual_rate;
unsigned long rate_error;
if (pll_rate <= 0)
continue;
actual_rate = pll_rate / pdiv_now;
rate_error = abs((long)actual_rate - (long)rate);
if (rate_error < best_rate_error) {
pdiv_best = pdiv_now;
best_rate_error = rate_error;
}
/* TODO: Consider PLL frequency based on smaller n/m values
* and pick the better one if the error is equal */
}
return rate * pdiv_best;
}
static long cdce925_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned long l_parent_rate = *parent_rate;
u16 divider = cdce925_calc_divider(rate, l_parent_rate);
if (l_parent_rate / divider != rate) {
l_parent_rate = cdce925_clk_best_parent_rate(hw, rate);
divider = cdce925_calc_divider(rate, l_parent_rate);
*parent_rate = l_parent_rate;
}
if (divider)
return (long)(l_parent_rate / divider);
return 0;
}
static int cdce925_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
data->pdiv = cdce925_calc_divider(rate, parent_rate);
return 0;
}
static const struct clk_ops cdce925_clk_ops = {
.prepare = cdce925_clk_prepare,
.unprepare = cdce925_clk_unprepare,
.recalc_rate = cdce925_clk_recalc_rate,
.round_rate = cdce925_clk_round_rate,
.set_rate = cdce925_clk_set_rate,
};
static u16 cdce925_y1_calc_divider(unsigned long rate,
unsigned long parent_rate)
{
unsigned long divider;
if (!rate)
return 0;
if (rate >= parent_rate)
return 1;
divider = DIV_ROUND_CLOSEST(parent_rate, rate);
if (divider > 0x3FF) /* Y1 has 10-bit divider */
divider = 0x3FF;
return (u16)divider;
}
static long cdce925_clk_y1_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned long l_parent_rate = *parent_rate;
u16 divider = cdce925_y1_calc_divider(rate, l_parent_rate);
if (divider)
return (long)(l_parent_rate / divider);
return 0;
}
static int cdce925_clk_y1_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
data->pdiv = cdce925_y1_calc_divider(rate, parent_rate);
return 0;
}
static const struct clk_ops cdce925_clk_y1_ops = {
.prepare = cdce925_clk_prepare,
.unprepare = cdce925_clk_unprepare,
.recalc_rate = cdce925_clk_recalc_rate,
.round_rate = cdce925_clk_y1_round_rate,
.set_rate = cdce925_clk_y1_set_rate,
};
static struct regmap_config cdce925_regmap_config = {
.name = "configuration0",
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.max_register = 0x2F,
};
#define CDCE925_I2C_COMMAND_BLOCK_TRANSFER 0x00
#define CDCE925_I2C_COMMAND_BYTE_TRANSFER 0x80
static int cdce925_regmap_i2c_write(
void *context, const void *data, size_t count)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
int ret;
u8 reg_data[2];
if (count != 2)
return -ENOTSUPP;
/* First byte is command code */
reg_data[0] = CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)data)[0];
reg_data[1] = ((u8 *)data)[1];
dev_dbg(&i2c->dev, "%s(%zu) %#x %#x\n", __func__, count,
reg_data[0], reg_data[1]);
ret = i2c_master_send(i2c, reg_data, count);
if (likely(ret == count))
return 0;
else if (ret < 0)
return ret;
else
return -EIO;
}
static int cdce925_regmap_i2c_read(void *context,
const void *reg, size_t reg_size, void *val, size_t val_size)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
struct i2c_msg xfer[2];
int ret;
u8 reg_data[2];
if (reg_size != 1)
return -ENOTSUPP;
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].buf = reg_data;
if (val_size == 1) {
reg_data[0] =
CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)reg)[0];
xfer[0].len = 1;
} else {
reg_data[0] =
CDCE925_I2C_COMMAND_BLOCK_TRANSFER | ((u8 *)reg)[0];
reg_data[1] = val_size;
xfer[0].len = 2;
}
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = val_size;
xfer[1].buf = val;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (likely(ret == 2)) {
dev_dbg(&i2c->dev, "%s(%zu, %zu) %#x %#x\n", __func__,
reg_size, val_size, reg_data[0], *((u8 *)val));
return 0;
} else if (ret < 0)
return ret;
else
return -EIO;
}
/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
* just weird, so just use the single byte mode exclusively. */
static struct regmap_bus regmap_cdce925_bus = {
.write = cdce925_regmap_i2c_write,
.read = cdce925_regmap_i2c_read,
};
static int cdce925_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct clk_cdce925_chip *data;
struct device_node *node = client->dev.of_node;
const char *parent_name;
const char *pll_clk_name[NUMBER_OF_PLLS] = {NULL,};
struct clk_init_data init;
struct clk *clk;
u32 value;
int i;
int err;
struct device_node *np_output;
char child_name[6];
dev_dbg(&client->dev, "%s\n", __func__);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->i2c_client = client;
data->regmap = devm_regmap_init(&client->dev, &regmap_cdce925_bus,
&client->dev, &cdce925_regmap_config);
if (IS_ERR(data->regmap)) {
dev_err(&client->dev, "failed to allocate register map\n");
return PTR_ERR(data->regmap);
}
i2c_set_clientdata(client, data);
parent_name = of_clk_get_parent_name(node, 0);
if (!parent_name) {
dev_err(&client->dev, "missing parent clock\n");
return -ENODEV;
}
dev_dbg(&client->dev, "parent is: %s\n", parent_name);
if (of_property_read_u32(node, "xtal-load-pf", &value) == 0)
regmap_write(data->regmap,
CDCE925_REG_XCSEL, (value << 3) & 0xF8);
/* PWDN bit */
regmap_update_bits(data->regmap, CDCE925_REG_GLOBAL1, BIT(4), 0);
/* Set input source for Y1 to be the XTAL */
regmap_update_bits(data->regmap, 0x02, BIT(7), 0);
init.ops = &cdce925_pll_ops;
init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = parent_name ? 1 : 0;
/* Register PLL clocks */
for (i = 0; i < NUMBER_OF_PLLS; ++i) {
pll_clk_name[i] = kasprintf(GFP_KERNEL, "%s.pll%d",
client->dev.of_node->name, i);
init.name = pll_clk_name[i];
data->pll[i].chip = data;
data->pll[i].hw.init = &init;
data->pll[i].index = i;
clk = devm_clk_register(&client->dev, &data->pll[i].hw);
if (IS_ERR(clk)) {
dev_err(&client->dev, "Failed register PLL %d\n", i);
err = PTR_ERR(clk);
goto error;
}
sprintf(child_name, "PLL%d", i+1);
np_output = of_get_child_by_name(node, child_name);
if (!np_output)
continue;
if (!of_property_read_u32(np_output,
"clock-frequency", &value)) {
err = clk_set_rate(clk, value);
if (err)
dev_err(&client->dev,
"unable to set PLL frequency %ud\n",
value);
}
if (!of_property_read_u32(np_output,
"spread-spectrum", &value)) {
u8 flag = of_property_read_bool(np_output,
"spread-spectrum-center") ? 0x80 : 0x00;
regmap_update_bits(data->regmap,
0x16 + (i*CDCE925_OFFSET_PLL),
0x80, flag);
regmap_update_bits(data->regmap,
0x12 + (i*CDCE925_OFFSET_PLL),
0x07, value & 0x07);
}
}
/* Register output clock Y1 */
init.ops = &cdce925_clk_y1_ops;
init.flags = 0;
init.num_parents = 1;
init.parent_names = &parent_name; /* Mux Y1 to input */
init.name = kasprintf(GFP_KERNEL, "%s.Y1", client->dev.of_node->name);
data->clk[0].chip = data;
data->clk[0].hw.init = &init;
data->clk[0].index = 0;
data->clk[0].pdiv = 1;
clk = devm_clk_register(&client->dev, &data->clk[0].hw);
kfree(init.name); /* clock framework made a copy of the name */
if (IS_ERR(clk)) {
dev_err(&client->dev, "clock registration Y1 failed\n");
err = PTR_ERR(clk);
goto error;
}
data->dt_clk[0] = clk;
/* Register output clocks Y2 .. Y5*/
init.ops = &cdce925_clk_ops;
init.flags = CLK_SET_RATE_PARENT;
init.num_parents = 1;
for (i = 1; i < NUMBER_OF_OUTPUTS; ++i) {
init.name = kasprintf(GFP_KERNEL, "%s.Y%d",
client->dev.of_node->name, i+1);
data->clk[i].chip = data;
data->clk[i].hw.init = &init;
data->clk[i].index = i;
data->clk[i].pdiv = 1;
switch (i) {
case 1:
case 2:
/* Mux Y2/3 to PLL1 */
init.parent_names = &pll_clk_name[0];
break;
case 3:
case 4:
/* Mux Y4/5 to PLL2 */
init.parent_names = &pll_clk_name[1];
break;
}
clk = devm_clk_register(&client->dev, &data->clk[i].hw);
kfree(init.name); /* clock framework made a copy of the name */
if (IS_ERR(clk)) {
dev_err(&client->dev, "clock registration failed\n");
err = PTR_ERR(clk);
goto error;
}
data->dt_clk[i] = clk;
}
/* Register the output clocks */
data->onecell.clk_num = NUMBER_OF_OUTPUTS;
data->onecell.clks = data->dt_clk;
err = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
&data->onecell);
if (err)
dev_err(&client->dev, "unable to add OF clock provider\n");
err = 0;
error:
for (i = 0; i < NUMBER_OF_PLLS; ++i)
/* clock framework made a copy of the name */
kfree(pll_clk_name[i]);
return err;
}
static const struct i2c_device_id cdce925_id[] = {
{ "cdce925", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cdce925_id);
static const struct of_device_id clk_cdce925_of_match[] = {
{ .compatible = "ti,cdce925" },
{ },
};
MODULE_DEVICE_TABLE(of, clk_cdce925_of_match);
static struct i2c_driver cdce925_driver = {
.driver = {
.name = "cdce925",
.of_match_table = of_match_ptr(clk_cdce925_of_match),
},
.probe = cdce925_probe,
.id_table = cdce925_id,
};
module_i2c_driver(cdce925_driver);
MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
MODULE_DESCRIPTION("cdce925 driver");
MODULE_LICENSE("GPL");
......@@ -188,7 +188,7 @@ static void clk_composite_disable(struct clk_hw *hw)
}
struct clk *clk_register_composite(struct device *dev, const char *name,
const char **parent_names, int num_parents,
const char * const *parent_names, int num_parents,
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
......@@ -200,10 +200,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
struct clk_ops *clk_composite_ops;
composite = kzalloc(sizeof(*composite), GFP_KERNEL);
if (!composite) {
pr_err("%s: could not allocate composite clk\n", __func__);
if (!composite)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.flags = flags | CLK_IS_BASIC;
......
......@@ -106,8 +106,9 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
rc = clk_set_rate(clk, rate);
if (rc < 0)
pr_err("clk: couldn't set %s clock rate: %d\n",
__clk_get_name(clk), rc);
pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
__clk_get_name(clk), rate, rc,
clk_get_rate(clk));
clk_put(clk);
}
index++;
......@@ -124,7 +125,7 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
* and sets any specified clock parents and rates. The @clk_supplier argument
* should be set to true if @node may be also a clock supplier of any clock
* listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
* If @clk_supplier is false the function exits returnning 0 as soon as it
* If @clk_supplier is false the function exits returning 0 as soon as it
* determines the @node is also a supplier of any of the clocks.
*/
int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
......
......@@ -430,11 +430,9 @@ static struct clk *_register_divider(struct device *dev, const char *name,
}
/* allocate the divider */
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
if (!div) {
pr_err("%s: could not allocate divider clk\n", __func__);
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_divider_ops;
......
......@@ -55,10 +55,16 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
/*
* We must report success but we can do so unconditionally because
* clk_factor_round_rate returns values that ensure this call is a
* nop.
*/
return 0;
}
struct clk_ops clk_fixed_factor_ops = {
const struct clk_ops clk_fixed_factor_ops = {
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
.recalc_rate = clk_factor_recalc_rate,
......@@ -74,10 +80,8 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
struct clk *clk;
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
if (!fix) {
pr_err("%s: could not allocate fixed factor clk\n", __func__);
if (!fix)
return ERR_PTR(-ENOMEM);
}
/* struct clk_fixed_factor assignments */
fix->mult = mult;
......
......@@ -65,11 +65,9 @@ struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
struct clk_init_data init;
/* allocate fixed-rate clock */
fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
if (!fixed) {
pr_err("%s: could not allocate fixed clk\n", __func__);
fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
if (!fixed)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_fixed_rate_ops;
......
......@@ -109,10 +109,8 @@ struct clk *clk_register_fractional_divider(struct device *dev,
struct clk *clk;
fd = kzalloc(sizeof(*fd), GFP_KERNEL);
if (!fd) {
dev_err(dev, "could not allocate fractional divider clk\n");
if (!fd)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_fractional_divider_ops;
......
......@@ -135,11 +135,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
}
/* allocate the gate */
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
if (!gate) {
pr_err("%s: could not allocate gated clk\n", __func__);
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_gate_ops;
......
......@@ -189,7 +189,7 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
/**
* of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
*/
void __init of_gpio_gate_clk_setup(struct device_node *node)
static void __init of_gpio_gate_clk_setup(struct device_node *node)
{
struct clk_gpio_gate_delayed_register_data *data;
......@@ -203,6 +203,5 @@ void __init of_gpio_gate_clk_setup(struct device_node *node)
of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
}
EXPORT_SYMBOL_GPL(of_gpio_gate_clk_setup);
CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
#endif
......@@ -80,9 +80,9 @@ static struct clk *__init clk_register_pll(struct device *dev,
return clk;
}
static const char const *cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
static const char const *ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
static const char const *dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
void __init ls1x_clk_init(void)
{
......
......@@ -31,6 +31,8 @@
#include <linux/of.h>
#include <linux/export.h>
#include "clk-max-gen.h"
struct max_gen_clk {
struct regmap *regmap;
u32 mask;
......
......@@ -15,7 +15,7 @@
#include <linux/of_address.h>
#include <linux/clkdev.h>
void __init moxart_of_pll_clk_init(struct device_node *node)
static void __init moxart_of_pll_clk_init(struct device_node *node)
{
static void __iomem *base;
struct clk *clk, *ref_clk;
......@@ -53,7 +53,7 @@ void __init moxart_of_pll_clk_init(struct device_node *node)
CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
moxart_of_pll_clk_init);
void __init moxart_of_apb_clk_init(struct device_node *node)
static void __init moxart_of_apb_clk_init(struct device_node *node)
{
static void __iomem *base;
struct clk *clk, *pll_clk;
......
......@@ -114,7 +114,8 @@ const struct clk_ops clk_mux_ro_ops = {
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
const char * const *parent_names, u8 num_parents,
unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{
......@@ -166,7 +167,8 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
EXPORT_SYMBOL_GPL(clk_register_mux_table);
struct clk *clk_register_mux(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
const char * const *parent_names, u8 num_parents,
unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock)
{
......
......@@ -552,7 +552,8 @@ static const struct clk_ops si5351_pll_ops = {
* MSx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c
* MSx_P3[19:0] = c
*
* MS[6,7] are integer (P1) divide only, P2 = 0, P3 = 0
* MS[6,7] are integer (P1) divide only, P1 = divide value,
* P2 and P3 are not applicable
*
* for 150MHz < fOUT <= 160MHz:
*
......@@ -606,9 +607,6 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
if (!hwdata->params.valid)
si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
if (hwdata->params.p3 == 0)
return parent_rate;
/*
* multisync0-5: fOUT = (128 * P3 * fIN) / (P1*P3 + P2 + 512*P3)
* multisync6-7: fOUT = fIN / P1
......@@ -616,6 +614,8 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
rate = parent_rate;
if (hwdata->num > 5) {
m = hwdata->params.p1;
} else if (hwdata->params.p3 == 0) {
return parent_rate;
} else if ((si5351_reg_read(hwdata->drvdata, reg + 2) &
SI5351_OUTPUT_CLK_DIVBY4) == SI5351_OUTPUT_CLK_DIVBY4) {
m = 4;
......@@ -679,6 +679,16 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
c = 1;
*parent_rate = a * rate;
} else if (hwdata->num >= 6) {
/* determine the closest integer divider */
a = DIV_ROUND_CLOSEST(*parent_rate, rate);
if (a < SI5351_MULTISYNTH_A_MIN)
a = SI5351_MULTISYNTH_A_MIN;
if (a > SI5351_MULTISYNTH67_A_MAX)
a = SI5351_MULTISYNTH67_A_MAX;
b = 0;
c = 1;
} else {
unsigned long rfrac, denom;
......@@ -692,9 +702,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
a = *parent_rate / rate;
if (a < SI5351_MULTISYNTH_A_MIN)
a = SI5351_MULTISYNTH_A_MIN;
if (hwdata->num >= 6 && a > SI5351_MULTISYNTH67_A_MAX)
a = SI5351_MULTISYNTH67_A_MAX;
else if (a > SI5351_MULTISYNTH_A_MAX)
if (a > SI5351_MULTISYNTH_A_MAX)
a = SI5351_MULTISYNTH_A_MAX;
/* find best approximation for b/c = fVCO mod fOUT */
......@@ -723,6 +731,10 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
hwdata->params.p3 = 1;
hwdata->params.p2 = 0;
hwdata->params.p1 = 0;
} else if (hwdata->num >= 6) {
hwdata->params.p3 = 0;
hwdata->params.p2 = 0;
hwdata->params.p1 = a;
} else {
hwdata->params.p3 = c;
hwdata->params.p2 = (128 * b) % c;
......
......@@ -12,6 +12,7 @@
#include <linux/clk-provider.h>
#include <linux/spinlock.h>
#include <linux/of.h>
#include <linux/platform_data/clk-u300.h>
/* APP side SYSCON registers */
/* CLK Control Register 16bit (R/W) */
......
......@@ -42,12 +42,12 @@
static DEFINE_SPINLOCK(clk_lock);
static inline u32 xgene_clk_read(void *csr)
static inline u32 xgene_clk_read(void __iomem *csr)
{
return readl_relaxed(csr);
}
static inline void xgene_clk_write(u32 data, void *csr)
static inline void xgene_clk_write(u32 data, void __iomem *csr)
{
return writel_relaxed(data, csr);
}
......@@ -119,7 +119,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
return fvco / nout;
}
const struct clk_ops xgene_clk_pll_ops = {
static const struct clk_ops xgene_clk_pll_ops = {
.is_enabled = xgene_clk_pll_is_enabled,
.recalc_rate = xgene_clk_pll_recalc_rate,
};
......@@ -167,7 +167,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty
{
const char *clk_name = np->full_name;
struct clk *clk;
void *reg;
void __iomem *reg;
reg = of_iomap(np, 0);
if (reg == NULL) {
......@@ -222,20 +222,22 @@ static int xgene_clk_enable(struct clk_hw *hw)
struct xgene_clk *pclk = to_xgene_clk(hw);
unsigned long flags = 0;
u32 data;
phys_addr_t reg;
if (pclk->lock)
spin_lock_irqsave(pclk->lock, flags);
if (pclk->param.csr_reg != NULL) {
pr_debug("%s clock enabled\n", pclk->name);
reg = __pa(pclk->param.csr_reg);
/* First enable the clock */
data = xgene_clk_read(pclk->param.csr_reg +
pclk->param.reg_clk_offset);
data |= pclk->param.reg_clk_mask;
xgene_clk_write(data, pclk->param.csr_reg +
pclk->param.reg_clk_offset);
pr_debug("%s clock PADDR base 0x%016LX clk offset 0x%08X mask 0x%08X value 0x%08X\n",
pclk->name, __pa(pclk->param.csr_reg),
pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
pclk->name, &reg,
pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
data);
......@@ -245,8 +247,8 @@ static int xgene_clk_enable(struct clk_hw *hw)
data &= ~pclk->param.reg_csr_mask;
xgene_clk_write(data, pclk->param.csr_reg +
pclk->param.reg_csr_offset);
pr_debug("%s CSR RESET PADDR base 0x%016LX csr offset 0x%08X mask 0x%08X value 0x%08X\n",
pclk->name, __pa(pclk->param.csr_reg),
pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
pclk->name, &reg,
pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
data);
}
......@@ -386,7 +388,7 @@ static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
return parent_rate / divider;
}
const struct clk_ops xgene_clk_ops = {
static const struct clk_ops xgene_clk_ops = {
.enable = xgene_clk_enable,
.disable = xgene_clk_disable,
.is_enabled = xgene_clk_is_enabled,
......@@ -456,7 +458,7 @@ static void __init xgene_devclk_init(struct device_node *np)
parameters.csr_reg = NULL;
parameters.divider_reg = NULL;
for (i = 0; i < 2; i++) {
void *map_res;
void __iomem *map_res;
rc = of_address_to_resource(np, i, &res);
if (rc != 0) {
if (i == 0) {
......
此差异已折叠。
config COMMON_CLK_HI6220
bool "Hi6220 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
default ARCH_HISI
help
Build the Hisilicon Hi6220 clock driver based on the common clock framework.
......@@ -2,8 +2,9 @@
# Hisilicon Clock specific Makefile
#
obj-y += clk.o clkgate-separated.o
obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o
obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
......@@ -38,44 +38,44 @@
#include "clk.h"
/* clock parent list */
static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", };
static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", };
static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", };
static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", };
static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", };
static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", };
static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", };
static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", };
static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", };
static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", };
static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
static const char *const timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
static const char *const timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
static const char *const timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
static const char *const timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
static const char *const timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
static const char *const timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
static const char *const timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
static const char *const timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
static const char *const timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
static const char *const timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
static const char *const uart0_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *const uart1_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *const uart2_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *const uart3_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *const uart4_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *const spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
static const char *const spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
static const char *const spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
/* share axi parent */
static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", };
static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", };
static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", };
static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", };
static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4",
static const char *const saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
static const char *const pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
static const char *const pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
static const char *const sd_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
static const char *const g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const venc_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
"armpll3", "armpll5", };
static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4",
static const char *const edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
"armpll3", "armpll5", };
static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", };
static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *const rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
static const char *const mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *const mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
/* fixed rate clocks */
......
/*
* Hisilicon Hi6220 clock driver
*
* Copyright (c) 2015 Hisilicon Limited.
*
* Author: Bintian Wang <bintian.wang@huawei.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.
*/
#include <linux/kernel.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <dt-bindings/clock/hi6220-clock.h>
#include "clk.h"
/* clocks in AO (always on) controller */
static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
{ HI6220_REF32K, "ref32k", NULL, CLK_IS_ROOT, 32764, },
{ HI6220_CLK_TCXO, "clk_tcxo", NULL, CLK_IS_ROOT, 19200000, },
{ HI6220_MMC1_PAD, "mmc1_pad", NULL, CLK_IS_ROOT, 100000000, },
{ HI6220_MMC2_PAD, "mmc2_pad", NULL, CLK_IS_ROOT, 100000000, },
{ HI6220_MMC0_PAD, "mmc0_pad", NULL, CLK_IS_ROOT, 200000000, },
{ HI6220_PLL_BBP, "bbppll0", NULL, CLK_IS_ROOT, 245760000, },
{ HI6220_PLL_GPU, "gpupll", NULL, CLK_IS_ROOT, 1000000000,},
{ HI6220_PLL1_DDR, "ddrpll1", NULL, CLK_IS_ROOT, 1066000000,},
{ HI6220_PLL_SYS, "syspll", NULL, CLK_IS_ROOT, 1200000000,},
{ HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
{ HI6220_DDR_SRC, "ddr_sel_src", NULL, CLK_IS_ROOT, 1200000000,},
{ HI6220_PLL_MEDIA, "media_pll", NULL, CLK_IS_ROOT, 1440000000,},
{ HI6220_PLL_DDR, "ddrpll0", NULL, CLK_IS_ROOT, 1600000000,},
};
static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
{ HI6220_300M, "clk_300m", "syspll", 1, 4, 0, },
{ HI6220_150M, "clk_150m", "clk_300m", 1, 2, 0, },
{ HI6220_PICOPHY_SRC, "picophy_src", "clk_150m", 1, 4, 0, },
{ HI6220_MMC0_SRC_SEL, "mmc0srcsel", "mmc0_sel", 1, 8, 0, },
{ HI6220_MMC1_SRC_SEL, "mmc1srcsel", "mmc1_sel", 1, 8, 0, },
{ HI6220_MMC2_SRC_SEL, "mmc2srcsel", "mmc2_sel", 1, 8, 0, },
{ HI6220_VPU_CODEC, "vpucodec", "codec_jpeg_aclk", 1, 2, 0, },
{ HI6220_MMC0_SMP, "mmc0_sample", "mmc0_sel", 1, 8, 0, },
{ HI6220_MMC1_SMP, "mmc1_sample", "mmc1_sel", 1, 8, 0, },
{ HI6220_MMC2_SMP, "mmc2_sample", "mmc2_sel", 1, 8, 0, },
};
static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
{ HI6220_WDT0_PCLK, "wdt0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
{ HI6220_WDT1_PCLK, "wdt1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
{ HI6220_WDT2_PCLK, "wdt2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
{ HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
{ HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
{ HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
{ HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
{ HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
{ HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
{ HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
{ HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
{ HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
{ HI6220_UART0_PCLK, "uart0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
};
static void __init hi6220_clk_ao_init(struct device_node *np)
{
struct hisi_clock_data *clk_data_ao;
clk_data_ao = hisi_clk_init(np, HI6220_AO_NR_CLKS);
if (!clk_data_ao)
return;
hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data_ao);
hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data_ao);
hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data_ao);
}
CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
/* clocks in sysctrl */
static const char *mmc0_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
static const char *mmc0_mux1_p[] __initdata = { "mmc0_mux0", "pll_media_gate", };
static const char *mmc0_src_p[] __initdata = { "mmc0srcsel", "mmc0_div", };
static const char *mmc1_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
static const char *mmc1_mux1_p[] __initdata = { "mmc1_mux0", "pll_media_gate", };
static const char *mmc1_src_p[] __initdata = { "mmc1srcsel", "mmc1_div", };
static const char *mmc2_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
static const char *mmc2_mux1_p[] __initdata = { "mmc2_mux0", "pll_media_gate", };
static const char *mmc2_src_p[] __initdata = { "mmc2srcsel", "mmc2_div", };
static const char *mmc0_sample_in[] __initdata = { "mmc0_sample", "mmc0_pad", };
static const char *mmc1_sample_in[] __initdata = { "mmc1_sample", "mmc1_pad", };
static const char *mmc2_sample_in[] __initdata = { "mmc2_sample", "mmc2_pad", };
static const char *uart1_src[] __initdata = { "clk_tcxo", "clk_150m", };
static const char *uart2_src[] __initdata = { "clk_tcxo", "clk_150m", };
static const char *uart3_src[] __initdata = { "clk_tcxo", "clk_150m", };
static const char *uart4_src[] __initdata = { "clk_tcxo", "clk_150m", };
static const char *hifi_src[] __initdata = { "syspll", "pll_media_gate", };
static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
{ HI6220_MMC0_CLK, "mmc0_clk", "mmc0_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, },
{ HI6220_MMC0_CIUCLK, "mmc0_ciuclk", "mmc0_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, },
{ HI6220_MMC1_CLK, "mmc1_clk", "mmc1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, },
{ HI6220_MMC1_CIUCLK, "mmc1_ciuclk", "mmc1_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, },
{ HI6220_MMC2_CLK, "mmc2_clk", "mmc2_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2, 0, },
{ HI6220_MMC2_CIUCLK, "mmc2_ciuclk", "mmc2_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2, 0, },
{ HI6220_USBOTG_HCLK, "usbotg_hclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4, 0, },
{ HI6220_CLK_PICOPHY, "clk_picophy", "cs_dapb", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5, 0, },
{ HI6220_HIFI, "hifi_clk", "hifi_div", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0, 0, },
{ HI6220_DACODEC_PCLK, "dacodec_pclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5, 0, },
{ HI6220_EDMAC_ACLK, "edmac_aclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2, 0, },
{ HI6220_CS_ATB, "cs_atb", "cs_atb_div", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0, 0, },
{ HI6220_I2C0_CLK, "i2c0_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1, 0, },
{ HI6220_I2C1_CLK, "i2c1_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2, 0, },
{ HI6220_I2C2_CLK, "i2c2_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3, 0, },
{ HI6220_I2C3_CLK, "i2c3_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4, 0, },
{ HI6220_UART1_PCLK, "uart1_pclk", "uart1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5, 0, },
{ HI6220_UART2_PCLK, "uart2_pclk", "uart2_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6, 0, },
{ HI6220_UART3_PCLK, "uart3_pclk", "uart3_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7, 0, },
{ HI6220_UART4_PCLK, "uart4_pclk", "uart4_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8, 0, },
{ HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9, 0, },
{ HI6220_TSENSOR_CLK, "tsensor_clk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 12, 0, },
{ HI6220_MMU_CLK, "mmu_clk", "ddrc_axi1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
{ HI6220_HIFI_SEL, "hifi_sel", "hifi_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0, 0, },
{ HI6220_MMC0_SYSPLL, "mmc0_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1, 0, },
{ HI6220_MMC1_SYSPLL, "mmc1_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2, 0, },
{ HI6220_MMC2_SYSPLL, "mmc2_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3, 0, },
{ HI6220_MMC0_SEL, "mmc0_sel", "mmc0_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6, 0, },
{ HI6220_MMC1_SEL, "mmc1_sel", "mmc1_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7, 0, },
{ 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, },
};
static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
{ HI6220_MMC0_SRC, "mmc0_src", mmc0_src_p, ARRAY_SIZE(mmc0_src_p), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, },
{ HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, },
{ HI6220_MMC1_SRC, "mmc1_src", mmc1_src_p, ARRAY_SIZE(mmc1_src_p), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, },
{ HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, },
{ HI6220_MMC2_SRC, "mmc2_src", mmc2_src_p, ARRAY_SIZE(mmc2_src_p), CLK_SET_RATE_PARENT, 0x4, 4, 1, 0, },
{ HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4, 4, 1, 0, },
{ HI6220_HIFI_SRC, "hifi_src", hifi_src, ARRAY_SIZE(hifi_src), CLK_SET_RATE_PARENT, 0x400, 0, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_UART1_SRC, "uart1_src", uart1_src, ARRAY_SIZE(uart1_src), CLK_SET_RATE_PARENT, 0x400, 1, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_UART2_SRC, "uart2_src", uart2_src, ARRAY_SIZE(uart2_src), CLK_SET_RATE_PARENT, 0x400, 2, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_UART3_SRC, "uart3_src", uart3_src, ARRAY_SIZE(uart3_src), CLK_SET_RATE_PARENT, 0x400, 3, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_UART4_SRC, "uart4_src", uart4_src, ARRAY_SIZE(uart4_src), CLK_SET_RATE_PARENT, 0x400, 4, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_MMC0_MUX0, "mmc0_mux0", mmc0_mux0_p, ARRAY_SIZE(mmc0_mux0_p), CLK_SET_RATE_PARENT, 0x400, 5, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_MMC1_MUX0, "mmc1_mux0", mmc1_mux0_p, ARRAY_SIZE(mmc1_mux0_p), CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_MMC2_MUX0, "mmc2_mux0", mmc2_mux0_p, ARRAY_SIZE(mmc2_mux0_p), CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_MMC0_MUX1, "mmc0_mux1", mmc0_mux1_p, ARRAY_SIZE(mmc0_mux1_p), CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_MMC1_MUX1, "mmc1_mux1", mmc1_mux1_p, ARRAY_SIZE(mmc1_mux1_p), CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
{ HI6220_MMC2_MUX1, "mmc2_mux1", mmc2_mux1_p, ARRAY_SIZE(mmc2_mux1_p), CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
};
static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
{ HI6220_CLK_BUS, "clk_bus", "clk_300m", CLK_SET_RATE_PARENT, 0x490, 0, 4, 7, },
{ HI6220_MMC0_DIV, "mmc0_div", "mmc0_syspll", CLK_SET_RATE_PARENT, 0x494, 0, 6, 7, },
{ HI6220_MMC1_DIV, "mmc1_div", "mmc1_syspll", CLK_SET_RATE_PARENT, 0x498, 0, 6, 7, },
{ HI6220_MMC2_DIV, "mmc2_div", "mmc2_syspll", CLK_SET_RATE_PARENT, 0x49c, 0, 6, 7, },
{ HI6220_HIFI_DIV, "hifi_div", "hifi_sel", CLK_SET_RATE_PARENT, 0x4a0, 0, 4, 7, },
{ HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel", CLK_SET_RATE_PARENT, 0x4a0, 8, 6, 15,},
{ HI6220_CS_DAPB, "cs_dapb", "picophy_src", CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
{ HI6220_CS_ATB_DIV, "cs_atb_div", "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0, 4, 7, },
};
static void __init hi6220_clk_sys_init(struct device_node *np)
{
struct hisi_clock_data *clk_data;
clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
if (!clk_data)
return;
hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
hisi_clk_register_mux(hi6220_mux_clks_sys,
ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
hi6220_clk_register_divider(hi6220_div_clks_sys,
ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
}
CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-sysctrl", hi6220_clk_sys_init);
/* clocks in media controller */
static const char *clk_1000_1200_src[] __initdata = { "pll_gpu_gate", "media_syspll_src", };
static const char *clk_1440_1200_src[] __initdata = { "media_syspll_src", "media_pll_src", };
static const char *clk_1000_1440_src[] __initdata = { "pll_gpu_gate", "media_pll_src", };
static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
{ HI6220_DSI_PCLK, "dsi_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0, 0, },
{ HI6220_G3D_PCLK, "g3d_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1, 0, },
{ HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3, 0, },
{ HI6220_ISP_SCLK, "isp_sclk", "isp_sclk_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5, 0, },
{ HI6220_ADE_CORE, "ade_core", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6, 0, },
{ HI6220_MED_MMU, "media_mmu", "mmu_clk", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8, 0, },
{ HI6220_CFG_CSI4PHY, "cfg_csi4phy", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9, 0, },
{ HI6220_CFG_CSI2PHY, "cfg_csi2phy", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
{ HI6220_ISP_SCLK_GATE, "isp_sclk_gate", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
{ HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
{ HI6220_ADE_CORE_GATE, "ade_core_gate", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
{ HI6220_CODEC_VPU_GATE, "codec_vpu_gate", "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
{ HI6220_MED_SYSPLL, "media_syspll_src", "media_syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
};
static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
{ HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
{ HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
{ HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
};
static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
{ HI6220_CODEC_JPEG, "codec_jpeg_aclk", "media_pll_src", CLK_SET_RATE_PARENT, 0xcbc, 0, 4, 23, },
{ HI6220_ISP_SCLK_SRC, "isp_sclk_src", "isp_sclk_gate", CLK_SET_RATE_PARENT, 0xcbc, 8, 4, 15, },
{ HI6220_ISP_SCLK1, "isp_sclk1", "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
{ HI6220_ADE_CORE_SRC, "ade_core_src", "ade_core_gate", CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
{ HI6220_ADE_PIX_SRC, "ade_pix_src", "clk_1440_1200", CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
{ HI6220_G3D_CLK, "g3d_clk", "clk_1000_1200", CLK_SET_RATE_PARENT, 0xcc4, 8, 4, 15, },
{ HI6220_CODEC_VPU_SRC, "codec_vpu_src", "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
};
static void __init hi6220_clk_media_init(struct device_node *np)
{
struct hisi_clock_data *clk_data;
clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
if (!clk_data)
return;
hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
hisi_clk_register_mux(hi6220_mux_clks_media,
ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
hi6220_clk_register_divider(hi6220_div_clks_media,
ARRAY_SIZE(hi6220_div_clks_media), clk_data);
}
CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-mediactrl", hi6220_clk_media_init);
/* clocks in pmctrl */
static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
{ HI6220_PLL_GPU_GATE, "pll_gpu_gate", "gpupll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8, 0, 0, },
{ HI6220_PLL1_DDR_GATE, "pll1_ddr_gate", "ddrpll1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0, 0, },
{ HI6220_PLL_DDR_GATE, "pll_ddr_gate", "ddrpll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0, 0, },
{ HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0, 0, },
{ HI6220_PLL0_BBP_GATE, "pll0_bbp_gate", "bbppll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0, 0, },
};
static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
{ HI6220_DDRC_SRC, "ddrc_src", "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
{ HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src", CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
};
static void __init hi6220_clk_power_init(struct device_node *np)
{
struct hisi_clock_data *clk_data;
clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
if (!clk_data)
return;
hisi_clk_register_gate(hi6220_gate_clks_power,
ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
hi6220_clk_register_divider(hi6220_div_clks_power,
ARRAY_SIZE(hi6220_div_clks_power), clk_data);
}
CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-pmctrl", hi6220_clk_power_init);
......@@ -46,15 +46,15 @@ static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
{ HIX5HD2_FIXED_83M, "83m", NULL, CLK_IS_ROOT, 83333333, },
};
static const char *sfc_mux_p[] __initdata = {
static const char *const sfc_mux_p[] __initconst = {
"24m", "150m", "200m", "100m", "75m", };
static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
static const char *sdio_mux_p[] __initdata = {
static const char *const sdio_mux_p[] __initconst = {
"75m", "100m", "50m", "15m", };
static u32 sdio_mux_table[] = {0, 1, 2, 3};
static const char *fephy_mux_p[] __initdata = { "25m", "125m"};
static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
static u32 fephy_mux_table[] = {0, 1};
......@@ -252,8 +252,9 @@ static struct clk_ops clk_complex_ops = {
.disable = clk_complex_disable,
};
void __init hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks,
int nums, struct hisi_clock_data *data)
static void __init
hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
struct hisi_clock_data *data)
{
void __iomem *base = data->base;
int i;
......
......@@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
data->clk_data.clks[clks[i].id] = clk;
}
}
void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
int nums, struct hisi_clock_data *data)
{
struct clk *clk;
void __iomem *base = data->base;
int i;
for (i = 0; i < nums; i++) {
clk = hi6220_register_clkdiv(NULL, clks[i].name,
clks[i].parent_name,
clks[i].flags,
base + clks[i].offset,
clks[i].shift,
clks[i].width,
clks[i].mask_bit,
&hisi_clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].alias)
clk_register_clkdev(clk, clks[i].alias, NULL);
data->clk_data.clks[clks[i].id] = clk;
}
}
此差异已折叠。
此差异已折叠。
obj-y += clk-mtk.o clk-pll.o clk-gate.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-y += clk-mt8135.o
obj-y += clk-mt8173.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
#
# Makefile for Meson specific clk
#
obj-y += clkc.o clk-pll.o clk-cpu.o
obj-y += meson8b-clkc.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -12,3 +12,5 @@ obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
obj-y += clk-of-pxa1928.o
......@@ -115,7 +115,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw)
spin_unlock_irqrestore(apbc->lock, flags);
}
struct clk_ops clk_apbc_ops = {
static struct clk_ops clk_apbc_ops = {
.prepare = clk_apbc_prepare,
.unprepare = clk_apbc_unprepare,
};
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册