mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 18:20:52 +07:00
Merge remote-tracking branch 'clk/clk-next' into clk-next
This commit is contained in:
commit
b2d8bc21ce
@ -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.
|
||||
|
@ -0,0 +1,23 @@
|
||||
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>;
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
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>;
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
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>;
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
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>;
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
* 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.
|
||||
|
55
Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
Normal file
55
Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
Normal file
@ -0,0 +1,55 @@
|
||||
* 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>;
|
||||
|
21
Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
Normal file
21
Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
Normal file
@ -0,0 +1,21 @@
|
||||
* 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
|
||||
|
42
Documentation/devicetree/bindings/clock/ti,cdce925.txt
Normal file
42
Documentation/devicetree/bindings/clock/ti,cdce925.txt
Normal file
@ -0,0 +1,42 @@
|
||||
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 @@ cpu@1 {
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
749
drivers/clk/clk-cdce925.c
Normal file
749
drivers/clk/clk-cdce925.c
Normal file
@ -0,0 +1,749 @@
|
||||
/*
|
||||
* 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, ®map_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, ®,
|
||||
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, ®,
|
||||
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) {
|
||||
|
1683
drivers/clk/clk.c
1683
drivers/clk/clk.c
File diff suppressed because it is too large
Load Diff
6
drivers/clk/hisilicon/Kconfig
Normal file
6
drivers/clk/hisilicon/Kconfig
Normal file
@ -0,0 +1,6 @@
|
||||
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 */
|
||||
|
284
drivers/clk/hisilicon/clk-hi6220.c
Normal file
284
drivers/clk/hisilicon/clk-hi6220.c
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ struct hisi_fixed_factor_clock {
|
||||
struct hisi_mux_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char **parent_names;
|
||||
const char *const *parent_names;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
@ -79,6 +79,18 @@ struct hisi_divider_clock {
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
struct hi6220_divider_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u32 mask_bit;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
struct hisi_gate_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
@ -94,18 +106,23 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
|
||||
const char *, unsigned long,
|
||||
void __iomem *, u8,
|
||||
u8, spinlock_t *);
|
||||
struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags, void __iomem *reg,
|
||||
u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
|
||||
|
||||
struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
|
||||
void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
|
||||
struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
|
||||
void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
|
||||
int, struct hisi_clock_data *);
|
||||
void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
|
||||
void hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
|
||||
int, struct hisi_clock_data *);
|
||||
void __init hisi_clk_register_mux(struct hisi_mux_clock *, int,
|
||||
void hisi_clk_register_mux(struct hisi_mux_clock *, int,
|
||||
struct hisi_clock_data *);
|
||||
void __init hisi_clk_register_divider(struct hisi_divider_clock *,
|
||||
void hisi_clk_register_divider(struct hisi_divider_clock *,
|
||||
int, struct hisi_clock_data *);
|
||||
void __init hisi_clk_register_gate(struct hisi_gate_clock *,
|
||||
void hisi_clk_register_gate(struct hisi_gate_clock *,
|
||||
int, struct hisi_clock_data *);
|
||||
void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
|
||||
void hisi_clk_register_gate_sep(struct hisi_gate_clock *,
|
||||
int, struct hisi_clock_data *);
|
||||
void hi6220_clk_register_divider(struct hi6220_divider_clock *,
|
||||
int, struct hisi_clock_data *);
|
||||
#endif /* __HISI_CLK_H */
|
||||
|
156
drivers/clk/hisilicon/clkdivider-hi6220.c
Normal file
156
drivers/clk/hisilicon/clkdivider-hi6220.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Hisilicon hi6220 SoC divider 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/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define div_mask(width) ((1 << (width)) - 1)
|
||||
|
||||
/**
|
||||
* struct hi6220_clk_divider - divider clock for hi6220
|
||||
*
|
||||
* @hw: handle between common and hardware-specific interfaces
|
||||
* @reg: register containing divider
|
||||
* @shift: shift to the divider bit field
|
||||
* @width: width of the divider bit field
|
||||
* @mask: mask for setting divider rate
|
||||
* @table: the div table that the divider supports
|
||||
* @lock: register lock
|
||||
*/
|
||||
struct hi6220_clk_divider {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u32 mask;
|
||||
const struct clk_div_table *table;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
#define to_hi6220_clk_divider(_hw) \
|
||||
container_of(_hw, struct hi6220_clk_divider, hw)
|
||||
|
||||
static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
unsigned int val;
|
||||
struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
|
||||
|
||||
val = readl_relaxed(dclk->reg) >> dclk->shift;
|
||||
val &= div_mask(dclk->width);
|
||||
|
||||
return divider_recalc_rate(hw, parent_rate, val, dclk->table,
|
||||
CLK_DIVIDER_ROUND_CLOSEST);
|
||||
}
|
||||
|
||||
static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
|
||||
|
||||
return divider_round_rate(hw, rate, prate, dclk->table,
|
||||
dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
|
||||
}
|
||||
|
||||
static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
int value;
|
||||
unsigned long flags = 0;
|
||||
u32 data;
|
||||
struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
|
||||
|
||||
value = divider_get_val(rate, parent_rate, dclk->table,
|
||||
dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
|
||||
|
||||
if (dclk->lock)
|
||||
spin_lock_irqsave(dclk->lock, flags);
|
||||
|
||||
data = readl_relaxed(dclk->reg);
|
||||
data &= ~(div_mask(dclk->width) << dclk->shift);
|
||||
data |= value << dclk->shift;
|
||||
data |= dclk->mask;
|
||||
|
||||
writel_relaxed(data, dclk->reg);
|
||||
|
||||
if (dclk->lock)
|
||||
spin_unlock_irqrestore(dclk->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops hi6220_clkdiv_ops = {
|
||||
.recalc_rate = hi6220_clkdiv_recalc_rate,
|
||||
.round_rate = hi6220_clkdiv_round_rate,
|
||||
.set_rate = hi6220_clkdiv_set_rate,
|
||||
};
|
||||
|
||||
struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags, void __iomem *reg,
|
||||
u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
|
||||
{
|
||||
struct hi6220_clk_divider *div;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
struct clk_div_table *table;
|
||||
u32 max_div, min_div;
|
||||
int i;
|
||||
|
||||
/* allocate the divider */
|
||||
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
||||
if (!div)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Init the divider table */
|
||||
max_div = div_mask(width) + 1;
|
||||
min_div = 1;
|
||||
|
||||
table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
|
||||
if (!table) {
|
||||
kfree(div);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
for (i = 0; i < max_div; i++) {
|
||||
table[i].div = min_div + i;
|
||||
table[i].val = table[i].div - 1;
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &hi6220_clkdiv_ops;
|
||||
init.flags = flags;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
|
||||
/* struct hi6220_clk_divider assignments */
|
||||
div->reg = reg;
|
||||
div->shift = shift;
|
||||
div->width = width;
|
||||
div->mask = mask_bit ? BIT(mask_bit) : 0;
|
||||
div->lock = lock;
|
||||
div->hw.init = &init;
|
||||
div->table = table;
|
||||
|
||||
/* register the clock */
|
||||
clk = clk_register(dev, &div->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(table);
|
||||
kfree(div);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
4
drivers/clk/mediatek/Makefile
Normal file
4
drivers/clk/mediatek/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
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
|
137
drivers/clk/mediatek/clk-gate.c
Normal file
137
drivers/clk/mediatek/clk-gate.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_clk_gate(hw);
|
||||
u32 val;
|
||||
|
||||
regmap_read(cg->regmap, cg->sta_ofs, &val);
|
||||
|
||||
val &= BIT(cg->bit);
|
||||
|
||||
return val == 0;
|
||||
}
|
||||
|
||||
static int mtk_cg_bit_is_set(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_clk_gate(hw);
|
||||
u32 val;
|
||||
|
||||
regmap_read(cg->regmap, cg->sta_ofs, &val);
|
||||
|
||||
val &= BIT(cg->bit);
|
||||
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_set_bit(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_clk_gate(hw);
|
||||
|
||||
regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static void mtk_cg_clr_bit(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_clk_gate(hw);
|
||||
|
||||
regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static int mtk_cg_enable(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_clr_bit(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_disable(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_set_bit(hw);
|
||||
}
|
||||
|
||||
static int mtk_cg_enable_inv(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_set_bit(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_disable_inv(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_clr_bit(hw);
|
||||
}
|
||||
|
||||
const struct clk_ops mtk_clk_gate_ops_setclr = {
|
||||
.is_enabled = mtk_cg_bit_is_cleared,
|
||||
.enable = mtk_cg_enable,
|
||||
.disable = mtk_cg_disable,
|
||||
};
|
||||
|
||||
const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
|
||||
.is_enabled = mtk_cg_bit_is_set,
|
||||
.enable = mtk_cg_enable_inv,
|
||||
.disable = mtk_cg_disable_inv,
|
||||
};
|
||||
|
||||
struct clk *mtk_clk_register_gate(
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
struct regmap *regmap,
|
||||
int set_ofs,
|
||||
int clr_ofs,
|
||||
int sta_ofs,
|
||||
u8 bit,
|
||||
const struct clk_ops *ops)
|
||||
{
|
||||
struct mtk_clk_gate *cg;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init = {};
|
||||
|
||||
cg = kzalloc(sizeof(*cg), GFP_KERNEL);
|
||||
if (!cg)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
init.ops = ops;
|
||||
|
||||
cg->regmap = regmap;
|
||||
cg->set_ofs = set_ofs;
|
||||
cg->clr_ofs = clr_ofs;
|
||||
cg->sta_ofs = sta_ofs;
|
||||
cg->bit = bit;
|
||||
|
||||
cg->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &cg->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(cg);
|
||||
|
||||
return clk;
|
||||
}
|
49
drivers/clk/mediatek/clk-gate.h
Normal file
49
drivers/clk/mediatek/clk-gate.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DRV_CLK_GATE_H
|
||||
#define __DRV_CLK_GATE_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
struct mtk_clk_gate {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
int set_ofs;
|
||||
int clr_ofs;
|
||||
int sta_ofs;
|
||||
u8 bit;
|
||||
};
|
||||
|
||||
static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct mtk_clk_gate, hw);
|
||||
}
|
||||
|
||||
extern const struct clk_ops mtk_clk_gate_ops_setclr;
|
||||
extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
|
||||
|
||||
struct clk *mtk_clk_register_gate(
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
struct regmap *regmap,
|
||||
int set_ofs,
|
||||
int clr_ofs,
|
||||
int sta_ofs,
|
||||
u8 bit,
|
||||
const struct clk_ops *ops);
|
||||
|
||||
#endif /* __DRV_CLK_GATE_H */
|
644
drivers/clk/mediatek/clk-mt8135.c
Normal file
644
drivers/clk/mediatek/clk-mt8135.c
Normal file
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <dt-bindings/clock/mt8135-clk.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
static DEFINE_SPINLOCK(mt8135_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
|
||||
FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
|
||||
FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
|
||||
FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
|
||||
FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_factor top_divs[] __initconst = {
|
||||
FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
|
||||
FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
|
||||
FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
|
||||
|
||||
FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
|
||||
FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
|
||||
FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
|
||||
FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
|
||||
|
||||
FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
|
||||
FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
|
||||
FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
|
||||
FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
|
||||
FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
|
||||
|
||||
FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
|
||||
FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
|
||||
FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
|
||||
FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
|
||||
FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
|
||||
|
||||
FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
|
||||
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
|
||||
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
|
||||
|
||||
FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
|
||||
FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
|
||||
FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
|
||||
FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
|
||||
FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
|
||||
|
||||
FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
|
||||
FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
|
||||
FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
|
||||
|
||||
FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
|
||||
FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
|
||||
FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
|
||||
|
||||
FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
|
||||
|
||||
FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
|
||||
};
|
||||
|
||||
static const char * const axi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d3",
|
||||
"syspll_d4",
|
||||
"syspll_d6",
|
||||
"univpll_d5",
|
||||
"univpll2_d2",
|
||||
"syspll_d3p5"
|
||||
};
|
||||
|
||||
static const char * const smi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"clkph_mck",
|
||||
"syspll_d2p5",
|
||||
"syspll_d3",
|
||||
"syspll_d8",
|
||||
"univpll_d5",
|
||||
"univpll1_d2",
|
||||
"univpll1_d6",
|
||||
"mmpll_d3",
|
||||
"mmpll_d4",
|
||||
"mmpll_d5",
|
||||
"mmpll_d6",
|
||||
"mmpll_d7",
|
||||
"vdecpll",
|
||||
"lvdspll"
|
||||
};
|
||||
|
||||
static const char * const mfg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll1_d4",
|
||||
"syspll_d2",
|
||||
"syspll_d2p5",
|
||||
"syspll_d3",
|
||||
"univpll_d5",
|
||||
"univpll1_d2",
|
||||
"mmpll_d2",
|
||||
"mmpll_d3",
|
||||
"mmpll_d4",
|
||||
"mmpll_d5",
|
||||
"mmpll_d6",
|
||||
"mmpll_d7"
|
||||
};
|
||||
|
||||
static const char * const irda_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d8",
|
||||
"univpll1_d6"
|
||||
};
|
||||
|
||||
static const char * const cam_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d3",
|
||||
"syspll_d3p5",
|
||||
"syspll_d4",
|
||||
"univpll_d5",
|
||||
"univpll2_d2",
|
||||
"univpll_d7",
|
||||
"univpll1_d4"
|
||||
};
|
||||
|
||||
static const char * const aud_intbus_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d6",
|
||||
"univpll_d10"
|
||||
};
|
||||
|
||||
static const char * const jpg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d5",
|
||||
"syspll_d4",
|
||||
"syspll_d3",
|
||||
"univpll_d7",
|
||||
"univpll2_d2",
|
||||
"univpll_d5"
|
||||
};
|
||||
|
||||
static const char * const disp_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d3p5",
|
||||
"syspll_d3",
|
||||
"univpll2_d2",
|
||||
"univpll_d5",
|
||||
"univpll1_d2",
|
||||
"lvdspll",
|
||||
"vdecpll"
|
||||
};
|
||||
|
||||
static const char * const msdc30_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d6",
|
||||
"syspll_d5",
|
||||
"univpll1_d4",
|
||||
"univpll2_d4",
|
||||
"msdcpll"
|
||||
};
|
||||
|
||||
static const char * const usb20_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d6",
|
||||
"univpll1_d10"
|
||||
};
|
||||
|
||||
static const char * const venc_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d3",
|
||||
"syspll_d8",
|
||||
"univpll_d5",
|
||||
"univpll1_d6",
|
||||
"mmpll_d4",
|
||||
"mmpll_d5",
|
||||
"mmpll_d6"
|
||||
};
|
||||
|
||||
static const char * const spi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d6",
|
||||
"syspll_d8",
|
||||
"syspll_d10",
|
||||
"univpll1_d6",
|
||||
"univpll1_d8"
|
||||
};
|
||||
|
||||
static const char * const uart_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d8"
|
||||
};
|
||||
|
||||
static const char * const mem_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"clkph_mck"
|
||||
};
|
||||
|
||||
static const char * const camtg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll_d26",
|
||||
"univpll1_d6",
|
||||
"syspll_d16",
|
||||
"syspll_d8"
|
||||
};
|
||||
|
||||
static const char * const audio_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d24"
|
||||
};
|
||||
|
||||
static const char * const fix_parents[] __initconst = {
|
||||
"rtc32k",
|
||||
"clk26m",
|
||||
"univpll_d5",
|
||||
"univpll_d7",
|
||||
"univpll1_d2",
|
||||
"univpll1_d4",
|
||||
"univpll1_d6",
|
||||
"univpll1_d8"
|
||||
};
|
||||
|
||||
static const char * const vdec_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"vdecpll",
|
||||
"clkph_mck",
|
||||
"syspll_d2p5",
|
||||
"syspll_d3",
|
||||
"syspll_d3p5",
|
||||
"syspll_d4",
|
||||
"syspll_d5",
|
||||
"syspll_d6",
|
||||
"syspll_d8",
|
||||
"univpll1_d2",
|
||||
"univpll2_d2",
|
||||
"univpll_d7",
|
||||
"univpll_d10",
|
||||
"univpll2_d4",
|
||||
"lvdspll"
|
||||
};
|
||||
|
||||
static const char * const ddrphycfg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"axi_sel",
|
||||
"syspll_d12"
|
||||
};
|
||||
|
||||
static const char * const dpilvds_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"lvdspll",
|
||||
"lvdspll_d2",
|
||||
"lvdspll_d4",
|
||||
"lvdspll_d8"
|
||||
};
|
||||
|
||||
static const char * const pmicspi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d6",
|
||||
"syspll_d8",
|
||||
"syspll_d10",
|
||||
"univpll1_d10",
|
||||
"mempll_mck_d4",
|
||||
"univpll_d26",
|
||||
"syspll_d24"
|
||||
};
|
||||
|
||||
static const char * const smi_mfg_as_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"smi_sel",
|
||||
"mfg_sel",
|
||||
"mem_sel"
|
||||
};
|
||||
|
||||
static const char * const gcpu_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll_d4",
|
||||
"univpll_d7",
|
||||
"syspll_d5",
|
||||
"syspll_d6"
|
||||
};
|
||||
|
||||
static const char * const dpi1_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"tvhdmi_h_ck",
|
||||
"tvhdmi_d2",
|
||||
"tvhdmi_d4"
|
||||
};
|
||||
|
||||
static const char * const cci_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"mainpll_537p3m",
|
||||
"univpll_d3",
|
||||
"syspll_d2p5",
|
||||
"syspll_d3",
|
||||
"syspll_d5"
|
||||
};
|
||||
|
||||
static const char * const apll_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"apll_ck",
|
||||
"apll_d4",
|
||||
"apll_d8",
|
||||
"apll_d16",
|
||||
"apll_d24"
|
||||
};
|
||||
|
||||
static const char * const hdmipll_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"hdmitx_clkdig_cts",
|
||||
"hdmitx_clkdig_d2",
|
||||
"hdmitx_clkdig_d3"
|
||||
};
|
||||
|
||||
static const struct mtk_composite top_muxes[] __initconst = {
|
||||
/* CLK_CFG_0 */
|
||||
MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
|
||||
0x0140, 0, 3, INVALID_MUX_GATE_BIT),
|
||||
MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
|
||||
MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
|
||||
MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
|
||||
/* CLK_CFG_1 */
|
||||
MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
|
||||
0x0144, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
|
||||
/* CLK_CFG_2 */
|
||||
MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
|
||||
/* CLK_CFG_3 */
|
||||
MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
|
||||
/* CLK_CFG_4 */
|
||||
MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
|
||||
/* CLK_CFG_6 */
|
||||
MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
|
||||
/* CLK_CFG_7 */
|
||||
MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
|
||||
MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
|
||||
0x015c, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
|
||||
/* CLK_CFG_8 */
|
||||
MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
|
||||
0x0164, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
|
||||
/* CLK_CFG_9 */
|
||||
MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra_cg_regs = {
|
||||
.set_ofs = 0x0040,
|
||||
.clr_ofs = 0x0044,
|
||||
.sta_ofs = 0x0048,
|
||||
};
|
||||
|
||||
#define GATE_ICG(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] __initconst = {
|
||||
GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
|
||||
GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
|
||||
GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
|
||||
GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
|
||||
GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
|
||||
GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
|
||||
GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
|
||||
GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
|
||||
GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
|
||||
GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
|
||||
GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
|
||||
GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
|
||||
GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs peri0_cg_regs = {
|
||||
.set_ofs = 0x0008,
|
||||
.clr_ofs = 0x0010,
|
||||
.sta_ofs = 0x0018,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs peri1_cg_regs = {
|
||||
.set_ofs = 0x000c,
|
||||
.clr_ofs = 0x0014,
|
||||
.sta_ofs = 0x001c,
|
||||
};
|
||||
|
||||
#define GATE_PERI0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &peri0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_PERI1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &peri1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate peri_gates[] __initconst = {
|
||||
/* PERI0 */
|
||||
GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
|
||||
GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
|
||||
GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
|
||||
GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
|
||||
GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
|
||||
GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
|
||||
GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
|
||||
GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
|
||||
GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
|
||||
GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
|
||||
GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
|
||||
GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
|
||||
GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
|
||||
GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
|
||||
GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
|
||||
GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
|
||||
GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
|
||||
GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
|
||||
GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
|
||||
GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
|
||||
GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
|
||||
GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
|
||||
GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
|
||||
GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
|
||||
GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
|
||||
GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
|
||||
GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
|
||||
GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
|
||||
GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
|
||||
/* PERI1 */
|
||||
GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
|
||||
GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
|
||||
GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
|
||||
GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
|
||||
GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
|
||||
GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
|
||||
GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
|
||||
GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
|
||||
GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
|
||||
};
|
||||
|
||||
static const char * const uart_ck_sel_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"uart_sel",
|
||||
};
|
||||
|
||||
static const struct mtk_composite peri_clks[] __initconst = {
|
||||
MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
|
||||
MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
|
||||
MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
|
||||
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
|
||||
};
|
||||
|
||||
static void __init mtk_topckgen_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
void __iomem *base;
|
||||
int r;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
|
||||
|
||||
mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
|
||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
|
||||
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
|
||||
&mt8135_clk_lock, clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
|
||||
|
||||
static void __init mtk_infrasys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
mtk_register_reset_controller(node, 2, 0x30);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
|
||||
|
||||
static void __init mtk_pericfg_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
|
||||
clk_data);
|
||||
mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
|
||||
&mt8135_clk_lock, clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
mtk_register_reset_controller(node, 2, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
|
||||
|
||||
#define MT8135_PLL_FMAX (2000 * MHZ)
|
||||
#define CON0_MT8135_RST_BAR BIT(27)
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.reg = _reg, \
|
||||
.pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, \
|
||||
.flags = _flags, \
|
||||
.rst_bar_mask = CON0_MT8135_RST_BAR, \
|
||||
.fmax = MT8135_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, \
|
||||
.pd_reg = _pd_reg, \
|
||||
.pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, \
|
||||
.pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, \
|
||||
}
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
|
||||
PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
|
||||
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
|
||||
PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
|
||||
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
|
||||
PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
|
||||
PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
|
||||
PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
|
||||
PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
|
||||
PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
|
||||
};
|
||||
|
||||
static void __init mtk_apmixedsys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
|
||||
if (!clk_data)
|
||||
return;
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
|
||||
mtk_apmixedsys_init);
|
830
drivers/clk/mediatek/clk-mt8173.c
Normal file
830
drivers/clk/mediatek/clk-mt8173.c
Normal file
@ -0,0 +1,830 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt8173-clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(mt8173_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
|
||||
FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
|
||||
FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
|
||||
FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
|
||||
FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_factor top_divs[] __initconst = {
|
||||
FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
|
||||
FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
|
||||
|
||||
FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
|
||||
FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
|
||||
FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
|
||||
|
||||
FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
|
||||
FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
|
||||
|
||||
FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
|
||||
FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
|
||||
FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
|
||||
FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
|
||||
|
||||
FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
|
||||
FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
|
||||
FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
|
||||
FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
|
||||
|
||||
FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
|
||||
FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
|
||||
FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
|
||||
|
||||
FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
|
||||
FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
|
||||
FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
|
||||
FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
|
||||
FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
|
||||
|
||||
FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
|
||||
FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
|
||||
FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
|
||||
|
||||
FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
|
||||
FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
|
||||
|
||||
FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
|
||||
FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
|
||||
FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
|
||||
FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
|
||||
FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
|
||||
FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
|
||||
|
||||
FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
|
||||
FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
|
||||
|
||||
FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
|
||||
FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
|
||||
FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
|
||||
FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
|
||||
FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
|
||||
|
||||
FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
|
||||
|
||||
FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
|
||||
FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
|
||||
|
||||
FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
|
||||
FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
|
||||
FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
|
||||
};
|
||||
|
||||
static const char * const axi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"syspll_d5",
|
||||
"syspll1_d4",
|
||||
"univpll_d5",
|
||||
"univpll2_d2",
|
||||
"dmpll_d2",
|
||||
"dmpll_d4"
|
||||
};
|
||||
|
||||
static const char * const mem_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"dmpll_ck"
|
||||
};
|
||||
|
||||
static const char * const ddrphycfg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d8"
|
||||
};
|
||||
|
||||
static const char * const mm_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"vencpll_d2",
|
||||
"main_h364m",
|
||||
"syspll1_d2",
|
||||
"syspll_d5",
|
||||
"syspll1_d4",
|
||||
"univpll1_d2",
|
||||
"univpll2_d2",
|
||||
"dmpll_d2"
|
||||
};
|
||||
|
||||
static const char * const pwm_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d4",
|
||||
"univpll3_d2",
|
||||
"univpll1_d4"
|
||||
};
|
||||
|
||||
static const char * const vdec_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"vcodecpll_ck",
|
||||
"tvdpll_445p5m",
|
||||
"univpll_d3",
|
||||
"vencpll_d2",
|
||||
"syspll_d3",
|
||||
"univpll1_d2",
|
||||
"mmpll_d2",
|
||||
"dmpll_d2",
|
||||
"dmpll_d4"
|
||||
};
|
||||
|
||||
static const char * const venc_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"vcodecpll_ck",
|
||||
"tvdpll_445p5m",
|
||||
"univpll_d3",
|
||||
"vencpll_d2",
|
||||
"syspll_d3",
|
||||
"univpll1_d2",
|
||||
"univpll2_d2",
|
||||
"dmpll_d2",
|
||||
"dmpll_d4"
|
||||
};
|
||||
|
||||
static const char * const mfg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"mmpll_ck",
|
||||
"dmpll_ck",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
"syspll_d3",
|
||||
"syspll1_d2",
|
||||
"syspll_d5",
|
||||
"univpll_d3",
|
||||
"univpll1_d2",
|
||||
"univpll_d5",
|
||||
"univpll2_d2"
|
||||
};
|
||||
|
||||
static const char * const camtg_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll_d26",
|
||||
"univpll2_d2",
|
||||
"syspll3_d2",
|
||||
"syspll3_d4",
|
||||
"univpll1_d4"
|
||||
};
|
||||
|
||||
static const char * const uart_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d8"
|
||||
};
|
||||
|
||||
static const char * const spi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll3_d2",
|
||||
"syspll1_d4",
|
||||
"syspll4_d2",
|
||||
"univpll3_d2",
|
||||
"univpll2_d4",
|
||||
"univpll1_d8"
|
||||
};
|
||||
|
||||
static const char * const usb20_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll1_d8",
|
||||
"univpll3_d4"
|
||||
};
|
||||
|
||||
static const char * const usb30_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll3_d2",
|
||||
"usb_syspll_125m",
|
||||
"univpll2_d4"
|
||||
};
|
||||
|
||||
static const char * const msdc50_0_h_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"syspll2_d2",
|
||||
"syspll4_d2",
|
||||
"univpll_d5",
|
||||
"univpll1_d4"
|
||||
};
|
||||
|
||||
static const char * const msdc50_0_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"msdcpll_ck",
|
||||
"msdcpll_d2",
|
||||
"univpll1_d4",
|
||||
"syspll2_d2",
|
||||
"syspll_d7",
|
||||
"msdcpll_d4",
|
||||
"vencpll_d4",
|
||||
"tvdpll_ck",
|
||||
"univpll_d2",
|
||||
"univpll1_d2",
|
||||
"mmpll_ck",
|
||||
"msdcpll2_ck",
|
||||
"msdcpll2_d2",
|
||||
"msdcpll2_d4"
|
||||
};
|
||||
|
||||
static const char * const msdc30_1_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d2",
|
||||
"msdcpll_d4",
|
||||
"univpll1_d4",
|
||||
"syspll2_d2",
|
||||
"syspll_d7",
|
||||
"univpll_d7",
|
||||
"vencpll_d4"
|
||||
};
|
||||
|
||||
static const char * const msdc30_2_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d2",
|
||||
"msdcpll_d4",
|
||||
"univpll1_d4",
|
||||
"syspll2_d2",
|
||||
"syspll_d7",
|
||||
"univpll_d7",
|
||||
"vencpll_d2"
|
||||
};
|
||||
|
||||
static const char * const msdc30_3_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"msdcpll2_ck",
|
||||
"msdcpll2_d2",
|
||||
"univpll2_d2",
|
||||
"msdcpll2_d4",
|
||||
"msdcpll_d4",
|
||||
"univpll1_d4",
|
||||
"syspll2_d2",
|
||||
"syspll_d7",
|
||||
"univpll_d7",
|
||||
"vencpll_d4",
|
||||
"msdcpll_ck",
|
||||
"msdcpll_d2",
|
||||
"msdcpll_d4"
|
||||
};
|
||||
|
||||
static const char * const audio_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll3_d4",
|
||||
"syspll4_d4",
|
||||
"syspll1_d16"
|
||||
};
|
||||
|
||||
static const char * const aud_intbus_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d4",
|
||||
"syspll4_d2",
|
||||
"univpll3_d2",
|
||||
"univpll2_d8",
|
||||
"dmpll_d4",
|
||||
"dmpll_d8"
|
||||
};
|
||||
|
||||
static const char * const pmicspi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d8",
|
||||
"syspll3_d4",
|
||||
"syspll1_d16",
|
||||
"univpll3_d4",
|
||||
"univpll_d26",
|
||||
"dmpll_d8",
|
||||
"dmpll_d16"
|
||||
};
|
||||
|
||||
static const char * const scp_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"univpll_d5",
|
||||
"syspll_d5",
|
||||
"dmpll_d2",
|
||||
"dmpll_d4"
|
||||
};
|
||||
|
||||
static const char * const atb_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"univpll_d5",
|
||||
"dmpll_d2"
|
||||
};
|
||||
|
||||
static const char * const venc_lt_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll_d3",
|
||||
"vcodecpll_ck",
|
||||
"tvdpll_445p5m",
|
||||
"vencpll_d2",
|
||||
"syspll_d3",
|
||||
"univpll1_d2",
|
||||
"univpll2_d2",
|
||||
"syspll1_d2",
|
||||
"univpll_d5",
|
||||
"vcodecpll_370p5",
|
||||
"dmpll_ck"
|
||||
};
|
||||
|
||||
static const char * const dpi0_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"tvdpll_d2",
|
||||
"tvdpll_d4",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
"tvdpll_d8",
|
||||
"tvdpll_d16"
|
||||
};
|
||||
|
||||
static const char * const irda_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d4",
|
||||
"syspll2_d4"
|
||||
};
|
||||
|
||||
static const char * const cci400_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"vencpll_ck",
|
||||
"armca7pll_754m",
|
||||
"armca7pll_502m",
|
||||
"univpll_d2",
|
||||
"syspll_d2",
|
||||
"msdcpll_ck",
|
||||
"dmpll_ck"
|
||||
};
|
||||
|
||||
static const char * const aud_1_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"apll1_ck",
|
||||
"univpll2_d4",
|
||||
"univpll2_d8"
|
||||
};
|
||||
|
||||
static const char * const aud_2_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"apll2_ck",
|
||||
"univpll2_d4",
|
||||
"univpll2_d8"
|
||||
};
|
||||
|
||||
static const char * const mem_mfg_in_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"mmpll_ck",
|
||||
"dmpll_ck",
|
||||
"clk26m"
|
||||
};
|
||||
|
||||
static const char * const axi_mfg_in_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"axi_sel",
|
||||
"dmpll_d2"
|
||||
};
|
||||
|
||||
static const char * const scam_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll3_d2",
|
||||
"univpll2_d4",
|
||||
"dmpll_d4"
|
||||
};
|
||||
|
||||
static const char * const spinfi_ifr_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll2_d8",
|
||||
"univpll3_d4",
|
||||
"syspll4_d2",
|
||||
"univpll2_d4",
|
||||
"univpll3_d2",
|
||||
"syspll1_d4",
|
||||
"univpll1_d4"
|
||||
};
|
||||
|
||||
static const char * const hdmi_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"hdmitx_dig_cts",
|
||||
"hdmitxpll_d2",
|
||||
"hdmitxpll_d3"
|
||||
};
|
||||
|
||||
static const char * const dpilvds_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"lvdspll",
|
||||
"lvdspll_d2",
|
||||
"lvdspll_d4",
|
||||
"lvdspll_d8",
|
||||
"fpc_ck"
|
||||
};
|
||||
|
||||
static const char * const msdc50_2_h_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"syspll2_d2",
|
||||
"syspll4_d2",
|
||||
"univpll_d5",
|
||||
"univpll1_d4"
|
||||
};
|
||||
|
||||
static const char * const hdcp_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"syspll4_d2",
|
||||
"syspll3_d4",
|
||||
"univpll2_d4"
|
||||
};
|
||||
|
||||
static const char * const hdcp_24m_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"univpll_d26",
|
||||
"univpll_d52",
|
||||
"univpll2_d8"
|
||||
};
|
||||
|
||||
static const char * const rtc_parents[] __initconst = {
|
||||
"clkrtc_int",
|
||||
"clkrtc_ext",
|
||||
"clk26m",
|
||||
"univpll3_d8"
|
||||
};
|
||||
|
||||
static const char * const i2s0_m_ck_parents[] __initconst = {
|
||||
"apll1_div1",
|
||||
"apll2_div1"
|
||||
};
|
||||
|
||||
static const char * const i2s1_m_ck_parents[] __initconst = {
|
||||
"apll1_div2",
|
||||
"apll2_div2"
|
||||
};
|
||||
|
||||
static const char * const i2s2_m_ck_parents[] __initconst = {
|
||||
"apll1_div3",
|
||||
"apll2_div3"
|
||||
};
|
||||
|
||||
static const char * const i2s3_m_ck_parents[] __initconst = {
|
||||
"apll1_div4",
|
||||
"apll2_div4"
|
||||
};
|
||||
|
||||
static const char * const i2s3_b_ck_parents[] __initconst = {
|
||||
"apll1_div5",
|
||||
"apll2_div5"
|
||||
};
|
||||
|
||||
static const struct mtk_composite top_muxes[] __initconst = {
|
||||
/* CLK_CFG_0 */
|
||||
MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
|
||||
MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
|
||||
MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
|
||||
MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
|
||||
/* CLK_CFG_1 */
|
||||
MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
|
||||
MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
|
||||
MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
|
||||
/* CLK_CFG_2 */
|
||||
MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
|
||||
MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
|
||||
/* CLK_CFG_3 */
|
||||
MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
|
||||
MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
|
||||
/* CLK_CFG_4 */
|
||||
MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
|
||||
MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
|
||||
/* CLK_CFG_5 */
|
||||
MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
|
||||
MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
|
||||
/* CLK_CFG_6 */
|
||||
MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
|
||||
MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
|
||||
/* CLK_CFG_7 */
|
||||
MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
|
||||
/* CLK_CFG_12 */
|
||||
MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
|
||||
/* CLK_CFG_13 */
|
||||
MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
|
||||
MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
|
||||
MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
|
||||
|
||||
DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
|
||||
DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
|
||||
DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
|
||||
DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
|
||||
DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
|
||||
DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
|
||||
|
||||
DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
|
||||
DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
|
||||
DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
|
||||
DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
|
||||
DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
|
||||
DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
|
||||
|
||||
MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
|
||||
MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
|
||||
MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
|
||||
MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
|
||||
MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra_cg_regs = {
|
||||
.set_ofs = 0x0040,
|
||||
.clr_ofs = 0x0044,
|
||||
.sta_ofs = 0x0048,
|
||||
};
|
||||
|
||||
#define GATE_ICG(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] __initconst = {
|
||||
GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
|
||||
GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
|
||||
GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
|
||||
GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
|
||||
GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
|
||||
GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
|
||||
GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
|
||||
GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
|
||||
GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
|
||||
GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
|
||||
GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs peri0_cg_regs = {
|
||||
.set_ofs = 0x0008,
|
||||
.clr_ofs = 0x0010,
|
||||
.sta_ofs = 0x0018,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs peri1_cg_regs = {
|
||||
.set_ofs = 0x000c,
|
||||
.clr_ofs = 0x0014,
|
||||
.sta_ofs = 0x001c,
|
||||
};
|
||||
|
||||
#define GATE_PERI0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &peri0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_PERI1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &peri1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate peri_gates[] __initconst = {
|
||||
/* PERI0 */
|
||||
GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
|
||||
GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
|
||||
GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
|
||||
GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
|
||||
GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
|
||||
GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
|
||||
GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
|
||||
GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
|
||||
GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
|
||||
GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
|
||||
GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
|
||||
GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
|
||||
GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
|
||||
GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
|
||||
GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
|
||||
GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
|
||||
GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
|
||||
GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
|
||||
GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
|
||||
GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
|
||||
GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
|
||||
GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
|
||||
GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
|
||||
GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
|
||||
GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
|
||||
GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
|
||||
GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
|
||||
GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
|
||||
GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
|
||||
/* PERI1 */
|
||||
GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
|
||||
GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
|
||||
GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
|
||||
};
|
||||
|
||||
static const char * const uart_ck_sel_parents[] __initconst = {
|
||||
"clk26m",
|
||||
"uart_sel",
|
||||
};
|
||||
|
||||
static const struct mtk_composite peri_clks[] __initconst = {
|
||||
MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
|
||||
MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
|
||||
MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
|
||||
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
|
||||
};
|
||||
|
||||
static void __init mtk_topckgen_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
void __iomem *base;
|
||||
int r;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
|
||||
|
||||
mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
|
||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
|
||||
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
|
||||
&mt8173_clk_lock, clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
|
||||
|
||||
static void __init mtk_infrasys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
mtk_register_reset_controller(node, 2, 0x30);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
|
||||
|
||||
static void __init mtk_pericfg_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
void __iomem *base;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
|
||||
|
||||
mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
|
||||
clk_data);
|
||||
mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
|
||||
&mt8173_clk_lock, clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
|
||||
mtk_register_reset_controller(node, 2, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
|
||||
|
||||
#define MT8173_PLL_FMAX (3000UL * MHZ)
|
||||
|
||||
#define CON0_MT8173_RST_BAR BIT(24)
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
|
||||
_tuner_reg, _pcw_reg, _pcw_shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.reg = _reg, \
|
||||
.pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, \
|
||||
.flags = _flags, \
|
||||
.rst_bar_mask = CON0_MT8173_RST_BAR, \
|
||||
.fmax = MT8173_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, \
|
||||
.pd_reg = _pd_reg, \
|
||||
.pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, \
|
||||
.pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, \
|
||||
}
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
|
||||
PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
|
||||
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
|
||||
PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
|
||||
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
|
||||
PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
|
||||
PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
|
||||
PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
|
||||
PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
|
||||
PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
|
||||
PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
|
||||
PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
|
||||
PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
|
||||
PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
|
||||
};
|
||||
|
||||
static void __init mtk_apmixedsys_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
|
||||
if (!clk_data)
|
||||
return;
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
||||
|
||||
clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
|
||||
}
|
||||
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
|
||||
mtk_apmixedsys_init);
|
220
drivers/clk/mediatek/clk-mtk.c
Normal file
220
drivers/clk/mediatek/clk-mtk.c
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
|
||||
{
|
||||
int i;
|
||||
struct clk_onecell_data *clk_data;
|
||||
|
||||
clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return NULL;
|
||||
|
||||
clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
|
||||
if (!clk_data->clks)
|
||||
goto err_out;
|
||||
|
||||
clk_data->clk_num = clk_num;
|
||||
|
||||
for (i = 0; i < clk_num; i++)
|
||||
clk_data->clks[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
return clk_data;
|
||||
err_out:
|
||||
kfree(clk_data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
|
||||
struct clk_onecell_data *clk_data)
|
||||
{
|
||||
int i;
|
||||
struct clk *clk;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_fixed_factor *ff = &clks[i];
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
|
||||
CLK_SET_RATE_PARENT, ff->mult, ff->div);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("Failed to register clk %s: %ld\n",
|
||||
ff->name, PTR_ERR(clk));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clk_data)
|
||||
clk_data->clks[ff->id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
|
||||
int num, struct clk_onecell_data *clk_data)
|
||||
{
|
||||
int i;
|
||||
struct clk *clk;
|
||||
struct regmap *regmap;
|
||||
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
regmap = syscon_node_to_regmap(node);
|
||||
if (IS_ERR(regmap)) {
|
||||
pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_gate *gate = &clks[i];
|
||||
|
||||
clk = mtk_clk_register_gate(gate->name, gate->parent_name,
|
||||
regmap,
|
||||
gate->regs->set_ofs,
|
||||
gate->regs->clr_ofs,
|
||||
gate->regs->sta_ofs,
|
||||
gate->shift, gate->ops);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("Failed to register clk %s: %ld\n",
|
||||
gate->name, PTR_ERR(clk));
|
||||
continue;
|
||||
}
|
||||
|
||||
clk_data->clks[gate->id] = clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
|
||||
void __iomem *base, spinlock_t *lock)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_mux *mux = NULL;
|
||||
struct clk_gate *gate = NULL;
|
||||
struct clk_divider *div = NULL;
|
||||
struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
|
||||
const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
|
||||
const char * const *parent_names;
|
||||
const char *parent;
|
||||
int num_parents;
|
||||
int ret;
|
||||
|
||||
if (mc->mux_shift >= 0) {
|
||||
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mux->reg = base + mc->mux_reg;
|
||||
mux->mask = BIT(mc->mux_width) - 1;
|
||||
mux->shift = mc->mux_shift;
|
||||
mux->lock = lock;
|
||||
|
||||
mux_hw = &mux->hw;
|
||||
mux_ops = &clk_mux_ops;
|
||||
|
||||
parent_names = mc->parent_names;
|
||||
num_parents = mc->num_parents;
|
||||
} else {
|
||||
parent = mc->parent;
|
||||
parent_names = &parent;
|
||||
num_parents = 1;
|
||||
}
|
||||
|
||||
if (mc->gate_shift >= 0) {
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
gate->reg = base + mc->gate_reg;
|
||||
gate->bit_idx = mc->gate_shift;
|
||||
gate->flags = CLK_GATE_SET_TO_DISABLE;
|
||||
gate->lock = lock;
|
||||
|
||||
gate_hw = &gate->hw;
|
||||
gate_ops = &clk_gate_ops;
|
||||
}
|
||||
|
||||
if (mc->divider_shift >= 0) {
|
||||
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
||||
if (!div) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
div->reg = base + mc->divider_reg;
|
||||
div->shift = mc->divider_shift;
|
||||
div->width = mc->divider_width;
|
||||
div->lock = lock;
|
||||
|
||||
div_hw = &div->hw;
|
||||
div_ops = &clk_divider_ops;
|
||||
}
|
||||
|
||||
clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
|
||||
mux_hw, mux_ops,
|
||||
div_hw, div_ops,
|
||||
gate_hw, gate_ops,
|
||||
mc->flags);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(gate);
|
||||
kfree(mux);
|
||||
}
|
||||
|
||||
return clk;
|
||||
err_out:
|
||||
kfree(mux);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void mtk_clk_register_composites(const struct mtk_composite *mcs,
|
||||
int num, void __iomem *base, spinlock_t *lock,
|
||||
struct clk_onecell_data *clk_data)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_composite *mc = &mcs[i];
|
||||
|
||||
clk = mtk_clk_register_composite(mc, base, lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("Failed to register clk %s: %ld\n",
|
||||
mc->name, PTR_ERR(clk));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clk_data)
|
||||
clk_data->clks[mc->id] = clk;
|
||||
}
|
||||
}
|
169
drivers/clk/mediatek/clk-mtk.h
Normal file
169
drivers/clk/mediatek/clk-mtk.h
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __DRV_CLK_MTK_H
|
||||
#define __DRV_CLK_MTK_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#define MAX_MUX_GATE_BIT 31
|
||||
#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
|
||||
|
||||
#define MHZ (1000 * 1000)
|
||||
|
||||
struct mtk_fixed_factor {
|
||||
int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
int mult;
|
||||
int div;
|
||||
};
|
||||
|
||||
#define FACTOR(_id, _name, _parent, _mult, _div) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.mult = _mult, \
|
||||
.div = _div, \
|
||||
}
|
||||
|
||||
extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
|
||||
int num, struct clk_onecell_data *clk_data);
|
||||
|
||||
struct mtk_composite {
|
||||
int id;
|
||||
const char *name;
|
||||
const char * const *parent_names;
|
||||
const char *parent;
|
||||
unsigned flags;
|
||||
|
||||
uint32_t mux_reg;
|
||||
uint32_t divider_reg;
|
||||
uint32_t gate_reg;
|
||||
|
||||
signed char mux_shift;
|
||||
signed char mux_width;
|
||||
signed char gate_shift;
|
||||
|
||||
signed char divider_shift;
|
||||
signed char divider_width;
|
||||
|
||||
signed char num_parents;
|
||||
};
|
||||
|
||||
#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.mux_reg = _reg, \
|
||||
.mux_shift = _shift, \
|
||||
.mux_width = _width, \
|
||||
.gate_reg = _reg, \
|
||||
.gate_shift = _gate, \
|
||||
.divider_shift = -1, \
|
||||
.parent_names = _parents, \
|
||||
.num_parents = ARRAY_SIZE(_parents), \
|
||||
.flags = CLK_SET_RATE_PARENT, \
|
||||
}
|
||||
|
||||
#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.mux_reg = _reg, \
|
||||
.mux_shift = _shift, \
|
||||
.mux_width = _width, \
|
||||
.gate_shift = -1, \
|
||||
.divider_shift = -1, \
|
||||
.parent_names = _parents, \
|
||||
.num_parents = ARRAY_SIZE(_parents), \
|
||||
.flags = CLK_SET_RATE_PARENT, \
|
||||
}
|
||||
|
||||
#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \
|
||||
.id = _id, \
|
||||
.parent = _parent, \
|
||||
.name = _name, \
|
||||
.divider_reg = _div_reg, \
|
||||
.divider_shift = _div_shift, \
|
||||
.divider_width = _div_width, \
|
||||
.gate_reg = _gate_reg, \
|
||||
.gate_shift = _gate_shift, \
|
||||
.mux_shift = -1, \
|
||||
.flags = 0, \
|
||||
}
|
||||
|
||||
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
|
||||
void __iomem *base, spinlock_t *lock);
|
||||
|
||||
void mtk_clk_register_composites(const struct mtk_composite *mcs,
|
||||
int num, void __iomem *base, spinlock_t *lock,
|
||||
struct clk_onecell_data *clk_data);
|
||||
|
||||
struct mtk_gate_regs {
|
||||
u32 sta_ofs;
|
||||
u32 clr_ofs;
|
||||
u32 set_ofs;
|
||||
};
|
||||
|
||||
struct mtk_gate {
|
||||
int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
const struct mtk_gate_regs *regs;
|
||||
int shift;
|
||||
const struct clk_ops *ops;
|
||||
};
|
||||
|
||||
int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
|
||||
int num, struct clk_onecell_data *clk_data);
|
||||
|
||||
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
|
||||
|
||||
#define HAVE_RST_BAR BIT(0)
|
||||
|
||||
struct mtk_pll_data {
|
||||
int id;
|
||||
const char *name;
|
||||
uint32_t reg;
|
||||
uint32_t pwr_reg;
|
||||
uint32_t en_mask;
|
||||
uint32_t pd_reg;
|
||||
uint32_t tuner_reg;
|
||||
int pd_shift;
|
||||
unsigned int flags;
|
||||
const struct clk_ops *ops;
|
||||
u32 rst_bar_mask;
|
||||
unsigned long fmax;
|
||||
int pcwbits;
|
||||
uint32_t pcw_reg;
|
||||
int pcw_shift;
|
||||
};
|
||||
|
||||
void __init mtk_clk_register_plls(struct device_node *node,
|
||||
const struct mtk_pll_data *plls, int num_plls,
|
||||
struct clk_onecell_data *clk_data);
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
void mtk_register_reset_controller(struct device_node *np,
|
||||
unsigned int num_regs, int regofs);
|
||||
#else
|
||||
static inline void mtk_register_reset_controller(struct device_node *np,
|
||||
unsigned int num_regs, int regofs)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DRV_CLK_MTK_H */
|
332
drivers/clk/mediatek/clk-pll.c
Normal file
332
drivers/clk/mediatek/clk-pll.c
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: James Liao <jamesjj.liao@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
|
||||
#define REG_CON0 0
|
||||
#define REG_CON1 4
|
||||
|
||||
#define CON0_BASE_EN BIT(0)
|
||||
#define CON0_PWR_ON BIT(0)
|
||||
#define CON0_ISO_EN BIT(1)
|
||||
#define CON0_PCW_CHG BIT(31)
|
||||
|
||||
#define AUDPLL_TUNER_EN BIT(31)
|
||||
|
||||
#define POSTDIV_MASK 0x7
|
||||
#define INTEGER_BITS 7
|
||||
|
||||
/*
|
||||
* MediaTek PLLs are configured through their pcw value. The pcw value describes
|
||||
* a divider in the PLL feedback loop which consists of 7 bits for the integer
|
||||
* part and the remaining bits (if present) for the fractional part. Also they
|
||||
* have a 3 bit power-of-two post divider.
|
||||
*/
|
||||
|
||||
struct mtk_clk_pll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base_addr;
|
||||
void __iomem *pd_addr;
|
||||
void __iomem *pwr_addr;
|
||||
void __iomem *tuner_addr;
|
||||
void __iomem *pcw_addr;
|
||||
const struct mtk_pll_data *data;
|
||||
};
|
||||
|
||||
static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct mtk_clk_pll, hw);
|
||||
}
|
||||
|
||||
static int mtk_pll_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
|
||||
|
||||
return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
|
||||
}
|
||||
|
||||
static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
|
||||
u32 pcw, int postdiv)
|
||||
{
|
||||
int pcwbits = pll->data->pcwbits;
|
||||
int pcwfbits;
|
||||
u64 vco;
|
||||
u8 c = 0;
|
||||
|
||||
/* The fractional part of the PLL divider. */
|
||||
pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
|
||||
|
||||
vco = (u64)fin * pcw;
|
||||
|
||||
if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
|
||||
c = 1;
|
||||
|
||||
vco >>= pcwfbits;
|
||||
|
||||
if (c)
|
||||
vco++;
|
||||
|
||||
return ((unsigned long)vco + postdiv - 1) / postdiv;
|
||||
}
|
||||
|
||||
static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
|
||||
int postdiv)
|
||||
{
|
||||
u32 con1, pd, val;
|
||||
int pll_en;
|
||||
|
||||
/* set postdiv */
|
||||
pd = readl(pll->pd_addr);
|
||||
pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
|
||||
pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
|
||||
writel(pd, pll->pd_addr);
|
||||
|
||||
pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
|
||||
|
||||
/* set pcw */
|
||||
val = readl(pll->pcw_addr);
|
||||
|
||||
val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
|
||||
pll->data->pcw_shift);
|
||||
val |= pcw << pll->data->pcw_shift;
|
||||
writel(val, pll->pcw_addr);
|
||||
|
||||
con1 = readl(pll->base_addr + REG_CON1);
|
||||
|
||||
if (pll_en)
|
||||
con1 |= CON0_PCW_CHG;
|
||||
|
||||
writel(con1, pll->base_addr + REG_CON1);
|
||||
if (pll->tuner_addr)
|
||||
writel(con1 + 1, pll->tuner_addr);
|
||||
|
||||
if (pll_en)
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
/*
|
||||
* mtk_pll_calc_values - calculate good values for a given input frequency.
|
||||
* @pll: The pll
|
||||
* @pcw: The pcw value (output)
|
||||
* @postdiv: The post divider (output)
|
||||
* @freq: The desired target frequency
|
||||
* @fin: The input frequency
|
||||
*
|
||||
*/
|
||||
static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
|
||||
u32 freq, u32 fin)
|
||||
{
|
||||
unsigned long fmin = 1000 * MHZ;
|
||||
u64 _pcw;
|
||||
u32 val;
|
||||
|
||||
if (freq > pll->data->fmax)
|
||||
freq = pll->data->fmax;
|
||||
|
||||
for (val = 0; val < 4; val++) {
|
||||
*postdiv = 1 << val;
|
||||
if (freq * *postdiv >= fmin)
|
||||
break;
|
||||
}
|
||||
|
||||
/* _pcw = freq * postdiv / fin * 2^pcwfbits */
|
||||
_pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
|
||||
do_div(_pcw, fin);
|
||||
|
||||
*pcw = (u32)_pcw;
|
||||
}
|
||||
|
||||
static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
|
||||
u32 pcw = 0;
|
||||
u32 postdiv;
|
||||
|
||||
mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
|
||||
mtk_pll_set_rate_regs(pll, pcw, postdiv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
|
||||
u32 postdiv;
|
||||
u32 pcw;
|
||||
|
||||
postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
|
||||
postdiv = 1 << postdiv;
|
||||
|
||||
pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
|
||||
pcw &= GENMASK(pll->data->pcwbits - 1, 0);
|
||||
|
||||
return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
|
||||
}
|
||||
|
||||
static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
|
||||
u32 pcw = 0;
|
||||
int postdiv;
|
||||
|
||||
mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
|
||||
|
||||
return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
|
||||
}
|
||||
|
||||
static int mtk_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
|
||||
u32 r;
|
||||
|
||||
r = readl(pll->pwr_addr) | CON0_PWR_ON;
|
||||
writel(r, pll->pwr_addr);
|
||||
udelay(1);
|
||||
|
||||
r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
|
||||
writel(r, pll->pwr_addr);
|
||||
udelay(1);
|
||||
|
||||
r = readl(pll->base_addr + REG_CON0);
|
||||
r |= pll->data->en_mask;
|
||||
writel(r, pll->base_addr + REG_CON0);
|
||||
|
||||
if (pll->tuner_addr) {
|
||||
r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
|
||||
writel(r, pll->tuner_addr);
|
||||
}
|
||||
|
||||
udelay(20);
|
||||
|
||||
if (pll->data->flags & HAVE_RST_BAR) {
|
||||
r = readl(pll->base_addr + REG_CON0);
|
||||
r |= pll->data->rst_bar_mask;
|
||||
writel(r, pll->base_addr + REG_CON0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_pll_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
|
||||
u32 r;
|
||||
|
||||
if (pll->data->flags & HAVE_RST_BAR) {
|
||||
r = readl(pll->base_addr + REG_CON0);
|
||||
r &= ~pll->data->rst_bar_mask;
|
||||
writel(r, pll->base_addr + REG_CON0);
|
||||
}
|
||||
|
||||
if (pll->tuner_addr) {
|
||||
r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
|
||||
writel(r, pll->tuner_addr);
|
||||
}
|
||||
|
||||
r = readl(pll->base_addr + REG_CON0);
|
||||
r &= ~CON0_BASE_EN;
|
||||
writel(r, pll->base_addr + REG_CON0);
|
||||
|
||||
r = readl(pll->pwr_addr) | CON0_ISO_EN;
|
||||
writel(r, pll->pwr_addr);
|
||||
|
||||
r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
|
||||
writel(r, pll->pwr_addr);
|
||||
}
|
||||
|
||||
static const struct clk_ops mtk_pll_ops = {
|
||||
.is_prepared = mtk_pll_is_prepared,
|
||||
.prepare = mtk_pll_prepare,
|
||||
.unprepare = mtk_pll_unprepare,
|
||||
.recalc_rate = mtk_pll_recalc_rate,
|
||||
.round_rate = mtk_pll_round_rate,
|
||||
.set_rate = mtk_pll_set_rate,
|
||||
};
|
||||
|
||||
static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
|
||||
void __iomem *base)
|
||||
{
|
||||
struct mtk_clk_pll *pll;
|
||||
struct clk_init_data init = {};
|
||||
struct clk *clk;
|
||||
const char *parent_name = "clk26m";
|
||||
|
||||
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
|
||||
if (!pll)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pll->base_addr = base + data->reg;
|
||||
pll->pwr_addr = base + data->pwr_reg;
|
||||
pll->pd_addr = base + data->pd_reg;
|
||||
pll->pcw_addr = base + data->pcw_reg;
|
||||
if (data->tuner_reg)
|
||||
pll->tuner_addr = base + data->tuner_reg;
|
||||
pll->hw.init = &init;
|
||||
pll->data = data;
|
||||
|
||||
init.name = data->name;
|
||||
init.ops = &mtk_pll_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clk = clk_register(NULL, &pll->hw);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
kfree(pll);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init mtk_clk_register_plls(struct device_node *node,
|
||||
const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
|
||||
{
|
||||
void __iomem *base;
|
||||
int r, i;
|
||||
struct clk *clk;
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
if (!base) {
|
||||
pr_err("%s(): ioremap failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_plls; i++) {
|
||||
const struct mtk_pll_data *pll = &plls[i];
|
||||
|
||||
clk = mtk_clk_register_pll(pll, base);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("Failed to register clk %s: %ld\n",
|
||||
pll->name, PTR_ERR(clk));
|
||||
continue;
|
||||
}
|
||||
|
||||
clk_data->clks[pll->id] = clk;
|
||||
}
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
97
drivers/clk/mediatek/reset.c
Normal file
97
drivers/clk/mediatek/reset.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
|
||||
struct mtk_reset {
|
||||
struct regmap *regmap;
|
||||
int regofs;
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
static int mtk_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
|
||||
|
||||
return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
|
||||
BIT(id % 32), ~0);
|
||||
}
|
||||
|
||||
static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
|
||||
|
||||
return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
|
||||
BIT(id % 32), 0);
|
||||
}
|
||||
|
||||
static int mtk_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mtk_reset_assert(rcdev, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mtk_reset_deassert(rcdev, id);
|
||||
}
|
||||
|
||||
static struct reset_control_ops mtk_reset_ops = {
|
||||
.assert = mtk_reset_assert,
|
||||
.deassert = mtk_reset_deassert,
|
||||
.reset = mtk_reset,
|
||||
};
|
||||
|
||||
void mtk_register_reset_controller(struct device_node *np,
|
||||
unsigned int num_regs, int regofs)
|
||||
{
|
||||
struct mtk_reset *data;
|
||||
int ret;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap)) {
|
||||
pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
|
||||
PTR_ERR(regmap));
|
||||
return;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
data->regmap = regmap;
|
||||
data->regofs = regofs;
|
||||
data->rcdev.owner = THIS_MODULE;
|
||||
data->rcdev.nr_resets = num_regs * 32;
|
||||
data->rcdev.ops = &mtk_reset_ops;
|
||||
data->rcdev.of_node = np;
|
||||
|
||||
ret = reset_controller_register(&data->rcdev);
|
||||
if (ret) {
|
||||
pr_err("could not register reset controller: %d\n", ret);
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
}
|
6
drivers/clk/meson/Makefile
Normal file
6
drivers/clk/meson/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for Meson specific clk
|
||||
#
|
||||
|
||||
obj-y += clkc.o clk-pll.o clk-cpu.o
|
||||
obj-y += meson8b-clkc.o
|
242
drivers/clk/meson/clk-cpu.c
Normal file
242
drivers/clk/meson/clk-cpu.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CPU clock path:
|
||||
*
|
||||
* +-[/N]-----|3|
|
||||
* MUX2 +--[/3]-+----------|2| MUX1
|
||||
* [sys_pll]---|1| |--[/2]------------|1|-|1|
|
||||
* | |---+------------------|0| | |----- [a5_clk]
|
||||
* +--|0| | |
|
||||
* [xtal]---+-------------------------------|0|
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#define MESON_CPU_CLK_CNTL1 0x00
|
||||
#define MESON_CPU_CLK_CNTL 0x40
|
||||
|
||||
#define MESON_CPU_CLK_MUX1 BIT(7)
|
||||
#define MESON_CPU_CLK_MUX2 BIT(0)
|
||||
|
||||
#define MESON_N_WIDTH 9
|
||||
#define MESON_N_SHIFT 20
|
||||
#define MESON_SEL_WIDTH 2
|
||||
#define MESON_SEL_SHIFT 2
|
||||
|
||||
#include "clkc.h"
|
||||
|
||||
struct meson_clk_cpu {
|
||||
struct notifier_block clk_nb;
|
||||
const struct clk_div_table *div_table;
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
u16 reg_off;
|
||||
};
|
||||
#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
|
||||
#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
|
||||
|
||||
static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
|
||||
|
||||
return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
|
||||
MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
|
||||
}
|
||||
|
||||
static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
|
||||
unsigned int div, sel, N = 0;
|
||||
u32 reg;
|
||||
|
||||
div = DIV_ROUND_UP(parent_rate, rate);
|
||||
|
||||
if (div <= 3) {
|
||||
sel = div - 1;
|
||||
} else {
|
||||
sel = 3;
|
||||
N = div / 2;
|
||||
}
|
||||
|
||||
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
|
||||
reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
|
||||
writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
|
||||
|
||||
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
|
||||
reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
|
||||
writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
|
||||
unsigned int N, sel;
|
||||
unsigned int div = 1;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
|
||||
N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
|
||||
|
||||
reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
|
||||
sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
|
||||
|
||||
if (sel < 3)
|
||||
div = sel + 1;
|
||||
else
|
||||
div = 2 * N;
|
||||
|
||||
return parent_rate / div;
|
||||
}
|
||||
|
||||
static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
|
||||
struct clk_notifier_data *ndata)
|
||||
{
|
||||
u32 cpu_clk_cntl;
|
||||
|
||||
/* switch MUX1 to xtal */
|
||||
cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
|
||||
+ MESON_CPU_CLK_CNTL);
|
||||
cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
|
||||
writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
|
||||
+ MESON_CPU_CLK_CNTL);
|
||||
udelay(100);
|
||||
|
||||
/* switch MUX2 to sys-pll */
|
||||
cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
|
||||
writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
|
||||
+ MESON_CPU_CLK_CNTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
|
||||
struct clk_notifier_data *ndata)
|
||||
{
|
||||
u32 cpu_clk_cntl;
|
||||
|
||||
/* switch MUX1 to divisors' output */
|
||||
cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
|
||||
+ MESON_CPU_CLK_CNTL);
|
||||
cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
|
||||
writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
|
||||
+ MESON_CPU_CLK_CNTL);
|
||||
udelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This clock notifier is called when the frequency of the of the parent
|
||||
* PLL clock is to be changed. We use the xtal input as temporary parent
|
||||
* while the PLL frequency is stabilized.
|
||||
*/
|
||||
static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct clk_notifier_data *ndata = data;
|
||||
struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
|
||||
int ret = 0;
|
||||
|
||||
if (event == PRE_RATE_CHANGE)
|
||||
ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
|
||||
else if (event == POST_RATE_CHANGE)
|
||||
ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
|
||||
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static const struct clk_ops meson_clk_cpu_ops = {
|
||||
.recalc_rate = meson_clk_cpu_recalc_rate,
|
||||
.round_rate = meson_clk_cpu_round_rate,
|
||||
.set_rate = meson_clk_cpu_set_rate,
|
||||
};
|
||||
|
||||
struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
|
||||
void __iomem *reg_base,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
struct meson_clk_cpu *clk_cpu;
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
|
||||
if (!clk_cpu)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk_cpu->base = reg_base;
|
||||
clk_cpu->reg_off = clk_conf->reg_off;
|
||||
clk_cpu->div_table = clk_conf->conf.div_table;
|
||||
clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;
|
||||
|
||||
init.name = clk_conf->clk_name;
|
||||
init.ops = &meson_clk_cpu_ops;
|
||||
init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
|
||||
init.flags |= CLK_SET_RATE_PARENT;
|
||||
init.parent_names = clk_conf->clks_parent;
|
||||
init.num_parents = 1;
|
||||
|
||||
clk_cpu->hw.init = &init;
|
||||
|
||||
pclk = __clk_lookup(clk_conf->clks_parent[0]);
|
||||
if (!pclk) {
|
||||
pr_err("%s: could not lookup parent clock %s\n",
|
||||
__func__, clk_conf->clks_parent[0]);
|
||||
ret = -EINVAL;
|
||||
goto free_clk;
|
||||
}
|
||||
|
||||
ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register clock notifier for %s\n",
|
||||
__func__, clk_conf->clk_name);
|
||||
goto free_clk;
|
||||
}
|
||||
|
||||
clk = clk_register(NULL, &clk_cpu->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
goto unregister_clk_nb;
|
||||
}
|
||||
|
||||
return clk;
|
||||
|
||||
unregister_clk_nb:
|
||||
clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
|
||||
free_clk:
|
||||
kfree(clk_cpu);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
227
drivers/clk/meson/clk-pll.c
Normal file
227
drivers/clk/meson/clk-pll.c
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* In the most basic form, a Meson PLL is composed as follows:
|
||||
*
|
||||
* PLL
|
||||
* +------------------------------+
|
||||
* | |
|
||||
* in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
|
||||
* | ^ ^ |
|
||||
* +------------------------------+
|
||||
* | |
|
||||
* FREF VCO
|
||||
*
|
||||
* out = (in * M / N) >> OD
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "clkc.h"
|
||||
|
||||
#define MESON_PLL_RESET BIT(29)
|
||||
#define MESON_PLL_LOCK BIT(31)
|
||||
|
||||
struct meson_clk_pll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
struct pll_conf *conf;
|
||||
unsigned int rate_count;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
|
||||
|
||||
static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_pll *pll = to_meson_clk_pll(hw);
|
||||
struct parm *p;
|
||||
unsigned long parent_rate_mhz = parent_rate / 1000000;
|
||||
unsigned long rate_mhz;
|
||||
u16 n, m, od;
|
||||
u32 reg;
|
||||
|
||||
p = &pll->conf->n;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
n = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
p = &pll->conf->m;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
m = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
p = &pll->conf->od;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
od = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
rate_mhz = (parent_rate_mhz * m / n) >> od;
|
||||
|
||||
return rate_mhz * 1000000;
|
||||
}
|
||||
|
||||
static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct meson_clk_pll *pll = to_meson_clk_pll(hw);
|
||||
const struct pll_rate_table *rate_table = pll->conf->rate_table;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pll->rate_count; i++) {
|
||||
if (rate <= rate_table[i].rate)
|
||||
return rate_table[i].rate;
|
||||
}
|
||||
|
||||
/* else return the smallest value */
|
||||
return rate_table[0].rate;
|
||||
}
|
||||
|
||||
static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
|
||||
unsigned long rate)
|
||||
{
|
||||
const struct pll_rate_table *rate_table = pll->conf->rate_table;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pll->rate_count; i++) {
|
||||
if (rate == rate_table[i].rate)
|
||||
return &rate_table[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
|
||||
struct parm *p_n)
|
||||
{
|
||||
int delay = 24000000;
|
||||
u32 reg;
|
||||
|
||||
while (delay > 0) {
|
||||
reg = readl(pll->base + p_n->reg_off);
|
||||
|
||||
if (reg & MESON_PLL_LOCK)
|
||||
return 0;
|
||||
delay--;
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_pll *pll = to_meson_clk_pll(hw);
|
||||
struct parm *p;
|
||||
const struct pll_rate_table *rate_set;
|
||||
unsigned long old_rate;
|
||||
int ret = 0;
|
||||
u32 reg;
|
||||
|
||||
if (parent_rate == 0 || rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
old_rate = rate;
|
||||
|
||||
rate_set = meson_clk_get_pll_settings(pll, rate);
|
||||
if (!rate_set)
|
||||
return -EINVAL;
|
||||
|
||||
/* PLL reset */
|
||||
p = &pll->conf->n;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
|
||||
writel(reg, pll->base + p->reg_off);
|
||||
|
||||
p = &pll->conf->m;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
|
||||
writel(reg, pll->base + p->reg_off);
|
||||
|
||||
p = &pll->conf->od;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
|
||||
writel(reg, pll->base + p->reg_off);
|
||||
|
||||
p = &pll->conf->n;
|
||||
ret = meson_clk_pll_wait_lock(pll, p);
|
||||
if (ret) {
|
||||
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
|
||||
__func__, old_rate);
|
||||
meson_clk_pll_set_rate(hw, old_rate, parent_rate);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct clk_ops meson_clk_pll_ops = {
|
||||
.recalc_rate = meson_clk_pll_recalc_rate,
|
||||
.round_rate = meson_clk_pll_round_rate,
|
||||
.set_rate = meson_clk_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops meson_clk_pll_ro_ops = {
|
||||
.recalc_rate = meson_clk_pll_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
|
||||
void __iomem *reg_base,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct meson_clk_pll *clk_pll;
|
||||
struct clk_init_data init;
|
||||
|
||||
clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
|
||||
if (!clk_pll)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk_pll->base = reg_base + clk_conf->reg_off;
|
||||
clk_pll->lock = lock;
|
||||
clk_pll->conf = clk_conf->conf.pll;
|
||||
|
||||
init.name = clk_conf->clk_name;
|
||||
init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
|
||||
|
||||
init.parent_names = &clk_conf->clks_parent[0];
|
||||
init.num_parents = 1;
|
||||
init.ops = &meson_clk_pll_ro_ops;
|
||||
|
||||
/* If no rate_table is specified we assume the PLL is read-only */
|
||||
if (clk_pll->conf->rate_table) {
|
||||
int len;
|
||||
|
||||
for (len = 0; clk_pll->conf->rate_table[len].rate != 0; )
|
||||
len++;
|
||||
|
||||
clk_pll->rate_count = len;
|
||||
init.ops = &meson_clk_pll_ops;
|
||||
}
|
||||
|
||||
clk_pll->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &clk_pll->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(clk_pll);
|
||||
|
||||
return clk;
|
||||
}
|
250
drivers/clk/meson/clkc.c
Normal file
250
drivers/clk/meson/clkc.c
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clkc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(clk_lock);
|
||||
|
||||
static struct clk **clks;
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
||||
struct clk ** __init meson_clk_init(struct device_node *np,
|
||||
unsigned long nr_clks)
|
||||
{
|
||||
clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
|
||||
if (!clks)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk_data.clks = clks;
|
||||
clk_data.clk_num = nr_clks;
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||
|
||||
return clks;
|
||||
}
|
||||
|
||||
static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
|
||||
{
|
||||
if (clks && id)
|
||||
clks[id] = clk;
|
||||
}
|
||||
|
||||
static struct clk * __init
|
||||
meson_clk_register_composite(const struct clk_conf *clk_conf,
|
||||
void __iomem *clk_base)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_mux *mux = NULL;
|
||||
struct clk_divider *div = NULL;
|
||||
struct clk_gate *gate = NULL;
|
||||
const struct clk_ops *mux_ops = NULL;
|
||||
const struct composite_conf *composite_conf;
|
||||
|
||||
composite_conf = clk_conf->conf.composite;
|
||||
|
||||
if (clk_conf->num_parents > 1) {
|
||||
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mux->reg = clk_base + clk_conf->reg_off
|
||||
+ composite_conf->mux_parm.reg_off;
|
||||
mux->shift = composite_conf->mux_parm.shift;
|
||||
mux->mask = BIT(composite_conf->mux_parm.width) - 1;
|
||||
mux->flags = composite_conf->mux_flags;
|
||||
mux->lock = &clk_lock;
|
||||
mux->table = composite_conf->mux_table;
|
||||
mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
|
||||
&clk_mux_ro_ops : &clk_mux_ops;
|
||||
}
|
||||
|
||||
if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
|
||||
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
||||
if (!div) {
|
||||
clk = ERR_PTR(-ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
div->reg = clk_base + clk_conf->reg_off
|
||||
+ composite_conf->div_parm.reg_off;
|
||||
div->shift = composite_conf->div_parm.shift;
|
||||
div->width = composite_conf->div_parm.width;
|
||||
div->lock = &clk_lock;
|
||||
div->flags = composite_conf->div_flags;
|
||||
div->table = composite_conf->div_table;
|
||||
}
|
||||
|
||||
if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate) {
|
||||
clk = ERR_PTR(-ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
gate->reg = clk_base + clk_conf->reg_off
|
||||
+ composite_conf->div_parm.reg_off;
|
||||
gate->bit_idx = composite_conf->gate_parm.shift;
|
||||
gate->flags = composite_conf->gate_flags;
|
||||
gate->lock = &clk_lock;
|
||||
}
|
||||
|
||||
clk = clk_register_composite(NULL, clk_conf->clk_name,
|
||||
clk_conf->clks_parent,
|
||||
clk_conf->num_parents,
|
||||
mux ? &mux->hw : NULL, mux_ops,
|
||||
div ? &div->hw : NULL, &clk_divider_ops,
|
||||
gate ? &gate->hw : NULL, &clk_gate_ops,
|
||||
clk_conf->flags);
|
||||
if (IS_ERR(clk))
|
||||
goto error;
|
||||
|
||||
return clk;
|
||||
|
||||
error:
|
||||
kfree(gate);
|
||||
kfree(div);
|
||||
kfree(mux);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
static struct clk * __init
|
||||
meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
|
||||
void __iomem *clk_base)
|
||||
{
|
||||
struct clk *clk;
|
||||
const struct fixed_fact_conf *fixed_fact_conf;
|
||||
const struct parm *p;
|
||||
unsigned int mult, div;
|
||||
u32 reg;
|
||||
|
||||
fixed_fact_conf = &clk_conf->conf.fixed_fact;
|
||||
|
||||
mult = clk_conf->conf.fixed_fact.mult;
|
||||
div = clk_conf->conf.fixed_fact.div;
|
||||
|
||||
if (!mult) {
|
||||
mult = 1;
|
||||
p = &fixed_fact_conf->mult_parm;
|
||||
if (MESON_PARM_APPLICABLE(p)) {
|
||||
reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
|
||||
mult = PARM_GET(p->width, p->shift, reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!div) {
|
||||
div = 1;
|
||||
p = &fixed_fact_conf->div_parm;
|
||||
if (MESON_PARM_APPLICABLE(p)) {
|
||||
reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
|
||||
mult = PARM_GET(p->width, p->shift, reg);
|
||||
}
|
||||
}
|
||||
|
||||
clk = clk_register_fixed_factor(NULL,
|
||||
clk_conf->clk_name,
|
||||
clk_conf->clks_parent[0],
|
||||
clk_conf->flags,
|
||||
mult, div);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
static struct clk * __init
|
||||
meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
|
||||
void __iomem *clk_base)
|
||||
{
|
||||
struct clk *clk;
|
||||
const struct fixed_rate_conf *fixed_rate_conf;
|
||||
const struct parm *r;
|
||||
unsigned long rate;
|
||||
u32 reg;
|
||||
|
||||
fixed_rate_conf = &clk_conf->conf.fixed_rate;
|
||||
rate = fixed_rate_conf->rate;
|
||||
|
||||
if (!rate) {
|
||||
r = &fixed_rate_conf->rate_parm;
|
||||
reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
|
||||
rate = PARM_GET(r->width, r->shift, reg);
|
||||
}
|
||||
|
||||
rate *= 1000000;
|
||||
|
||||
clk = clk_register_fixed_rate(NULL,
|
||||
clk_conf->clk_name,
|
||||
clk_conf->num_parents
|
||||
? clk_conf->clks_parent[0] : NULL,
|
||||
clk_conf->flags, rate);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
|
||||
size_t nr_confs,
|
||||
void __iomem *clk_base)
|
||||
{
|
||||
unsigned int i;
|
||||
struct clk *clk = NULL;
|
||||
|
||||
for (i = 0; i < nr_confs; i++) {
|
||||
const struct clk_conf *clk_conf = &clk_confs[i];
|
||||
|
||||
switch (clk_conf->clk_type) {
|
||||
case CLK_FIXED_RATE:
|
||||
clk = meson_clk_register_fixed_rate(clk_conf,
|
||||
clk_base);
|
||||
break;
|
||||
case CLK_FIXED_FACTOR:
|
||||
clk = meson_clk_register_fixed_factor(clk_conf,
|
||||
clk_base);
|
||||
break;
|
||||
case CLK_COMPOSITE:
|
||||
clk = meson_clk_register_composite(clk_conf,
|
||||
clk_base);
|
||||
break;
|
||||
case CLK_CPU:
|
||||
clk = meson_clk_register_cpu(clk_conf, clk_base,
|
||||
&clk_lock);
|
||||
break;
|
||||
case CLK_PLL:
|
||||
clk = meson_clk_register_pll(clk_conf, clk_base,
|
||||
&clk_lock);
|
||||
break;
|
||||
default:
|
||||
clk = NULL;
|
||||
}
|
||||
|
||||
if (!clk) {
|
||||
pr_err("%s: unknown clock type %d\n", __func__,
|
||||
clk_conf->clk_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_warn("%s: Unable to create %s clock\n", __func__,
|
||||
clk_conf->clk_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
meson_clk_add_lookup(clk, clk_conf->clk_id);
|
||||
}
|
||||
}
|
187
drivers/clk/meson/clkc.h
Normal file
187
drivers/clk/meson/clkc.h
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CLKC_H
|
||||
#define __CLKC_H
|
||||
|
||||
#define PMASK(width) GENMASK(width - 1, 0)
|
||||
#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
|
||||
#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
|
||||
|
||||
#define PARM_GET(width, shift, reg) \
|
||||
(((reg) & SETPMASK(width, shift)) >> (shift))
|
||||
#define PARM_SET(width, shift, reg, val) \
|
||||
(((reg) & CLRPMASK(width, shift)) | (val << (shift)))
|
||||
|
||||
#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
|
||||
|
||||
struct parm {
|
||||
u16 reg_off;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
};
|
||||
#define PARM(_r, _s, _w) \
|
||||
{ \
|
||||
.reg_off = (_r), \
|
||||
.shift = (_s), \
|
||||
.width = (_w), \
|
||||
} \
|
||||
|
||||
struct pll_rate_table {
|
||||
unsigned long rate;
|
||||
u16 m;
|
||||
u16 n;
|
||||
u16 od;
|
||||
};
|
||||
#define PLL_RATE(_r, _m, _n, _od) \
|
||||
{ \
|
||||
.rate = (_r), \
|
||||
.m = (_m), \
|
||||
.n = (_n), \
|
||||
.od = (_od), \
|
||||
} \
|
||||
|
||||
struct pll_conf {
|
||||
const struct pll_rate_table *rate_table;
|
||||
struct parm m;
|
||||
struct parm n;
|
||||
struct parm od;
|
||||
};
|
||||
|
||||
struct fixed_fact_conf {
|
||||
unsigned int div;
|
||||
unsigned int mult;
|
||||
struct parm div_parm;
|
||||
struct parm mult_parm;
|
||||
};
|
||||
|
||||
struct fixed_rate_conf {
|
||||
unsigned long rate;
|
||||
struct parm rate_parm;
|
||||
};
|
||||
|
||||
struct composite_conf {
|
||||
struct parm mux_parm;
|
||||
struct parm div_parm;
|
||||
struct parm gate_parm;
|
||||
struct clk_div_table *div_table;
|
||||
u32 *mux_table;
|
||||
u8 mux_flags;
|
||||
u8 div_flags;
|
||||
u8 gate_flags;
|
||||
};
|
||||
|
||||
#define PNAME(x) static const char *x[]
|
||||
|
||||
enum clk_type {
|
||||
CLK_FIXED_FACTOR,
|
||||
CLK_FIXED_RATE,
|
||||
CLK_COMPOSITE,
|
||||
CLK_CPU,
|
||||
CLK_PLL,
|
||||
};
|
||||
|
||||
struct clk_conf {
|
||||
u16 reg_off;
|
||||
enum clk_type clk_type;
|
||||
unsigned int clk_id;
|
||||
const char *clk_name;
|
||||
const char **clks_parent;
|
||||
int num_parents;
|
||||
unsigned long flags;
|
||||
union {
|
||||
struct fixed_fact_conf fixed_fact;
|
||||
struct fixed_rate_conf fixed_rate;
|
||||
const struct composite_conf *composite;
|
||||
struct pll_conf *pll;
|
||||
const struct clk_div_table *div_table;
|
||||
} conf;
|
||||
};
|
||||
|
||||
#define FIXED_RATE_P(_ro, _ci, _cn, _f, _c) \
|
||||
{ \
|
||||
.reg_off = (_ro), \
|
||||
.clk_type = CLK_FIXED_RATE, \
|
||||
.clk_id = (_ci), \
|
||||
.clk_name = (_cn), \
|
||||
.flags = (_f), \
|
||||
.conf.fixed_rate.rate_parm = _c, \
|
||||
} \
|
||||
|
||||
#define FIXED_RATE(_ci, _cn, _f, _r) \
|
||||
{ \
|
||||
.clk_type = CLK_FIXED_RATE, \
|
||||
.clk_id = (_ci), \
|
||||
.clk_name = (_cn), \
|
||||
.flags = (_f), \
|
||||
.conf.fixed_rate.rate = (_r), \
|
||||
} \
|
||||
|
||||
#define PLL(_ro, _ci, _cn, _cp, _f, _c) \
|
||||
{ \
|
||||
.reg_off = (_ro), \
|
||||
.clk_type = CLK_PLL, \
|
||||
.clk_id = (_ci), \
|
||||
.clk_name = (_cn), \
|
||||
.clks_parent = (_cp), \
|
||||
.num_parents = ARRAY_SIZE(_cp), \
|
||||
.flags = (_f), \
|
||||
.conf.pll = (_c), \
|
||||
} \
|
||||
|
||||
#define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d) \
|
||||
{ \
|
||||
.clk_type = CLK_FIXED_FACTOR, \
|
||||
.clk_id = (_ci), \
|
||||
.clk_name = (_cn), \
|
||||
.clks_parent = (_cp), \
|
||||
.num_parents = ARRAY_SIZE(_cp), \
|
||||
.conf.fixed_fact.div = (_d), \
|
||||
} \
|
||||
|
||||
#define CPU(_ro, _ci, _cn, _cp, _dt) \
|
||||
{ \
|
||||
.reg_off = (_ro), \
|
||||
.clk_type = CLK_CPU, \
|
||||
.clk_id = (_ci), \
|
||||
.clk_name = (_cn), \
|
||||
.clks_parent = (_cp), \
|
||||
.num_parents = ARRAY_SIZE(_cp), \
|
||||
.conf.div_table = (_dt), \
|
||||
} \
|
||||
|
||||
#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c) \
|
||||
{ \
|
||||
.reg_off = (_ro), \
|
||||
.clk_type = CLK_COMPOSITE, \
|
||||
.clk_id = (_ci), \
|
||||
.clk_name = (_cn), \
|
||||
.clks_parent = (_cp), \
|
||||
.num_parents = ARRAY_SIZE(_cp), \
|
||||
.flags = (_f), \
|
||||
.conf.composite = (_c), \
|
||||
} \
|
||||
|
||||
struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
|
||||
void meson_clk_register_clks(const struct clk_conf *clk_confs,
|
||||
unsigned int nr_confs, void __iomem *clk_base);
|
||||
struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
|
||||
void __iomem *reg_base, spinlock_t *lock);
|
||||
struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
|
||||
void __iomem *reg_base, spinlock_t *lock);
|
||||
|
||||
#endif /* __CLKC_H */
|
196
drivers/clk/meson/meson8b-clkc.c
Normal file
196
drivers/clk/meson/meson8b-clkc.c
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Endless Mobile, Inc.
|
||||
* Author: Carlo Caione <carlo@endlessm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
||||
#include "clkc.h"
|
||||
|
||||
#define MESON8B_REG_CTL0_ADDR 0x0000
|
||||
#define MESON8B_REG_SYS_CPU_CNTL1 0x015c
|
||||
#define MESON8B_REG_HHI_MPEG 0x0174
|
||||
#define MESON8B_REG_MALI 0x01b0
|
||||
#define MESON8B_REG_PLL_FIXED 0x0280
|
||||
#define MESON8B_REG_PLL_SYS 0x0300
|
||||
#define MESON8B_REG_PLL_VID 0x0320
|
||||
|
||||
static const struct pll_rate_table sys_pll_rate_table[] = {
|
||||
PLL_RATE(312000000, 52, 1, 2),
|
||||
PLL_RATE(336000000, 56, 1, 2),
|
||||
PLL_RATE(360000000, 60, 1, 2),
|
||||
PLL_RATE(384000000, 64, 1, 2),
|
||||
PLL_RATE(408000000, 68, 1, 2),
|
||||
PLL_RATE(432000000, 72, 1, 2),
|
||||
PLL_RATE(456000000, 76, 1, 2),
|
||||
PLL_RATE(480000000, 80, 1, 2),
|
||||
PLL_RATE(504000000, 84, 1, 2),
|
||||
PLL_RATE(528000000, 88, 1, 2),
|
||||
PLL_RATE(552000000, 92, 1, 2),
|
||||
PLL_RATE(576000000, 96, 1, 2),
|
||||
PLL_RATE(600000000, 50, 1, 1),
|
||||
PLL_RATE(624000000, 52, 1, 1),
|
||||
PLL_RATE(648000000, 54, 1, 1),
|
||||
PLL_RATE(672000000, 56, 1, 1),
|
||||
PLL_RATE(696000000, 58, 1, 1),
|
||||
PLL_RATE(720000000, 60, 1, 1),
|
||||
PLL_RATE(744000000, 62, 1, 1),
|
||||
PLL_RATE(768000000, 64, 1, 1),
|
||||
PLL_RATE(792000000, 66, 1, 1),
|
||||
PLL_RATE(816000000, 68, 1, 1),
|
||||
PLL_RATE(840000000, 70, 1, 1),
|
||||
PLL_RATE(864000000, 72, 1, 1),
|
||||
PLL_RATE(888000000, 74, 1, 1),
|
||||
PLL_RATE(912000000, 76, 1, 1),
|
||||
PLL_RATE(936000000, 78, 1, 1),
|
||||
PLL_RATE(960000000, 80, 1, 1),
|
||||
PLL_RATE(984000000, 82, 1, 1),
|
||||
PLL_RATE(1008000000, 84, 1, 1),
|
||||
PLL_RATE(1032000000, 86, 1, 1),
|
||||
PLL_RATE(1056000000, 88, 1, 1),
|
||||
PLL_RATE(1080000000, 90, 1, 1),
|
||||
PLL_RATE(1104000000, 92, 1, 1),
|
||||
PLL_RATE(1128000000, 94, 1, 1),
|
||||
PLL_RATE(1152000000, 96, 1, 1),
|
||||
PLL_RATE(1176000000, 98, 1, 1),
|
||||
PLL_RATE(1200000000, 50, 1, 0),
|
||||
PLL_RATE(1224000000, 51, 1, 0),
|
||||
PLL_RATE(1248000000, 52, 1, 0),
|
||||
PLL_RATE(1272000000, 53, 1, 0),
|
||||
PLL_RATE(1296000000, 54, 1, 0),
|
||||
PLL_RATE(1320000000, 55, 1, 0),
|
||||
PLL_RATE(1344000000, 56, 1, 0),
|
||||
PLL_RATE(1368000000, 57, 1, 0),
|
||||
PLL_RATE(1392000000, 58, 1, 0),
|
||||
PLL_RATE(1416000000, 59, 1, 0),
|
||||
PLL_RATE(1440000000, 60, 1, 0),
|
||||
PLL_RATE(1464000000, 61, 1, 0),
|
||||
PLL_RATE(1488000000, 62, 1, 0),
|
||||
PLL_RATE(1512000000, 63, 1, 0),
|
||||
PLL_RATE(1536000000, 64, 1, 0),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct clk_div_table cpu_div_table[] = {
|
||||
{ .val = 1, .div = 1 },
|
||||
{ .val = 2, .div = 2 },
|
||||
{ .val = 3, .div = 3 },
|
||||
{ .val = 2, .div = 4 },
|
||||
{ .val = 3, .div = 6 },
|
||||
{ .val = 4, .div = 8 },
|
||||
{ .val = 5, .div = 10 },
|
||||
{ .val = 6, .div = 12 },
|
||||
{ .val = 7, .div = 14 },
|
||||
{ .val = 8, .div = 16 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
PNAME(p_xtal) = { "xtal" };
|
||||
PNAME(p_fclk_div) = { "fixed_pll" };
|
||||
PNAME(p_cpu_clk) = { "sys_pll" };
|
||||
PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" };
|
||||
PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5",
|
||||
"fclk_div7", "zero" };
|
||||
|
||||
static u32 mux_table_clk81[] = { 6, 5, 7 };
|
||||
static u32 mux_table_mali[] = { 6, 5, 7, 4, 0 };
|
||||
|
||||
static struct pll_conf pll_confs = {
|
||||
.m = PARM(0x00, 0, 9),
|
||||
.n = PARM(0x00, 9, 5),
|
||||
.od = PARM(0x00, 16, 2),
|
||||
};
|
||||
|
||||
static struct pll_conf sys_pll_conf = {
|
||||
.m = PARM(0x00, 0, 9),
|
||||
.n = PARM(0x00, 9, 5),
|
||||
.od = PARM(0x00, 16, 2),
|
||||
.rate_table = sys_pll_rate_table,
|
||||
};
|
||||
|
||||
static const struct composite_conf clk81_conf __initconst = {
|
||||
.mux_table = mux_table_clk81,
|
||||
.mux_flags = CLK_MUX_READ_ONLY,
|
||||
.mux_parm = PARM(0x00, 12, 3),
|
||||
.div_parm = PARM(0x00, 0, 7),
|
||||
.gate_parm = PARM(0x00, 7, 1),
|
||||
};
|
||||
|
||||
static const struct composite_conf mali_conf __initconst = {
|
||||
.mux_table = mux_table_mali,
|
||||
.mux_parm = PARM(0x00, 9, 3),
|
||||
.div_parm = PARM(0x00, 0, 7),
|
||||
.gate_parm = PARM(0x00, 8, 1),
|
||||
};
|
||||
|
||||
static const struct clk_conf meson8b_xtal_conf __initconst =
|
||||
FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal",
|
||||
CLK_IS_ROOT, PARM(0x00, 4, 7));
|
||||
|
||||
static const struct clk_conf meson8b_clk_confs[] __initconst = {
|
||||
FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0),
|
||||
PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll",
|
||||
p_xtal, 0, &pll_confs),
|
||||
PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll",
|
||||
p_xtal, 0, &pll_confs),
|
||||
PLL(MESON8B_REG_PLL_SYS, CLKID_PLL_SYS, "sys_pll",
|
||||
p_xtal, 0, &sys_pll_conf),
|
||||
FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2),
|
||||
FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3),
|
||||
FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4),
|
||||
FIXED_FACTOR_DIV(CLKID_FCLK_DIV5, "fclk_div5", p_fclk_div, 0, 5),
|
||||
FIXED_FACTOR_DIV(CLKID_FCLK_DIV7, "fclk_div7", p_fclk_div, 0, 7),
|
||||
CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk,
|
||||
cpu_div_table),
|
||||
COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81,
|
||||
CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
|
||||
COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
|
||||
CLK_IGNORE_UNUSED, &mali_conf),
|
||||
};
|
||||
|
||||
static void __init meson8b_clkc_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *clk_base;
|
||||
|
||||
if (!meson_clk_init(np, CLK_NR_CLKS))
|
||||
return;
|
||||
|
||||
/* XTAL */
|
||||
clk_base = of_iomap(np, 0);
|
||||
if (!clk_base) {
|
||||
pr_err("%s: Unable to map xtal base\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
meson_clk_register_clks(&meson8b_xtal_conf, 1, clk_base);
|
||||
iounmap(clk_base);
|
||||
|
||||
/* Generic clocks and PLLs */
|
||||
clk_base = of_iomap(np, 1);
|
||||
if (!clk_base) {
|
||||
pr_err("%s: Unable to map clk base\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
meson_clk_register_clks(meson8b_clk_confs,
|
||||
ARRAY_SIZE(meson8b_clk_confs),
|
||||
clk_base);
|
||||
}
|
||||
CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init);
|
@ -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,
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ static void clk_apmu_disable(struct clk_hw *hw)
|
||||
spin_unlock_irqrestore(apmu->lock, flags);
|
||||
}
|
||||
|
||||
struct clk_ops clk_apmu_ops = {
|
||||
static struct clk_ops clk_apmu_ops = {
|
||||
.enable = clk_apmu_enable,
|
||||
.disable = clk_apmu_disable,
|
||||
};
|
||||
|
@ -63,10 +63,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
|
||||
};
|
||||
|
||||
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
|
||||
{.num = 14634, .den = 2165}, /*14.745MHZ */
|
||||
{.num = 8125, .den = 1536}, /*14.745MHZ */
|
||||
{.num = 3521, .den = 689}, /*19.23MHZ */
|
||||
{.num = 9679, .den = 5728}, /*58.9824MHZ */
|
||||
{.num = 15850, .den = 9451}, /*59.429MHZ */
|
||||
};
|
||||
|
||||
static const char *uart_parent[] = {"uart_pll", "vctcxo"};
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define APBC_TWSI4 0x7c
|
||||
#define APBC_TWSI5 0x80
|
||||
#define APBC_KPC 0x18
|
||||
#define APBC_TIMER 0x24
|
||||
#define APBC_UART0 0x2c
|
||||
#define APBC_UART1 0x30
|
||||
#define APBC_UART2 0x34
|
||||
@ -98,10 +99,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
|
||||
};
|
||||
|
||||
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
|
||||
{.num = 14634, .den = 2165}, /*14.745MHZ */
|
||||
{.num = 8125, .den = 1536}, /*14.745MHZ */
|
||||
{.num = 3521, .den = 689}, /*19.23MHZ */
|
||||
{.num = 9679, .den = 5728}, /*58.9824MHZ */
|
||||
{.num = 15850, .den = 9451}, /*59.429MHZ */
|
||||
};
|
||||
|
||||
static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
|
||||
@ -134,6 +133,9 @@ static DEFINE_SPINLOCK(ssp2_lock);
|
||||
static DEFINE_SPINLOCK(ssp3_lock);
|
||||
static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
|
||||
|
||||
static DEFINE_SPINLOCK(timer_lock);
|
||||
static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"};
|
||||
|
||||
static DEFINE_SPINLOCK(reset_lock);
|
||||
|
||||
static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
@ -145,6 +147,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
|
||||
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
|
||||
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
|
||||
{0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_gate_clk apbc_gate_clks[] = {
|
||||
@ -170,6 +173,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
|
||||
{MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x7, 0x3, 0x0, 0, &ssp1_lock},
|
||||
{MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x7, 0x3, 0x0, 0, &ssp2_lock},
|
||||
{MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x7, 0x3, 0x0, 0, &ssp3_lock},
|
||||
{MMP2_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x7, 0x3, 0x0, 0, &timer_lock},
|
||||
};
|
||||
|
||||
static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define APBC_PWM1 0x10
|
||||
#define APBC_PWM2 0x14
|
||||
#define APBC_PWM3 0x18
|
||||
#define APBC_TIMER 0x34
|
||||
#define APBC_SSP0 0x81c
|
||||
#define APBC_SSP1 0x820
|
||||
#define APBC_SSP2 0x84c
|
||||
@ -58,6 +59,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
|
||||
{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
|
||||
{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
|
||||
{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
|
||||
{PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
|
||||
};
|
||||
|
||||
static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
|
||||
@ -70,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
|
||||
{PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
|
||||
{PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
|
||||
{PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
|
||||
{PXA168_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
|
||||
{PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
|
||||
{PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
|
||||
{PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
|
||||
@ -119,6 +122,9 @@ static DEFINE_SPINLOCK(ssp3_lock);
|
||||
static DEFINE_SPINLOCK(ssp4_lock);
|
||||
static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
|
||||
|
||||
static DEFINE_SPINLOCK(timer_lock);
|
||||
static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96", "pll1_192"};
|
||||
|
||||
static DEFINE_SPINLOCK(reset_lock);
|
||||
|
||||
static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
@ -130,6 +136,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
|
||||
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
|
||||
{0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock},
|
||||
{0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_gate_clk apbc_gate_clks[] = {
|
||||
@ -151,6 +158,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
|
||||
{PXA168_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x3, 0x3, 0x0, 0, &ssp2_lock},
|
||||
{PXA168_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x3, 0x3, 0x0, 0, &ssp3_lock},
|
||||
{PXA168_CLK_SSP4, "ssp4_clk", "ssp4_mux", CLK_SET_RATE_PARENT, APBC_SSP4, 0x3, 0x3, 0x0, 0, &ssp4_lock},
|
||||
{PXA168_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x3, 0x3, 0x0, 0, &timer_lock},
|
||||
};
|
||||
|
||||
static void pxa168_apb_periph_clk_init(struct pxa168_clk_unit *pxa_unit)
|
||||
|
265
drivers/clk/mmp/clk-of-pxa1928.c
Normal file
265
drivers/clk/mmp/clk-of-pxa1928.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* pxa1928 clock framework source file
|
||||
*
|
||||
* Copyright (C) 2015 Linaro, Ltd.
|
||||
* Rob Herring <robh@kernel.org>
|
||||
*
|
||||
* Based on drivers/clk/mmp/clk-of-mmp2.c:
|
||||
* Copyright (C) 2012 Marvell
|
||||
* Chao Xie <xiechao.mail@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <dt-bindings/clock/marvell,pxa1928.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "reset.h"
|
||||
|
||||
#define MPMU_UART_PLL 0x14
|
||||
|
||||
struct pxa1928_clk_unit {
|
||||
struct mmp_clk_unit unit;
|
||||
void __iomem *mpmu_base;
|
||||
void __iomem *apmu_base;
|
||||
void __iomem *apbc_base;
|
||||
void __iomem *apbcp_base;
|
||||
};
|
||||
|
||||
static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
|
||||
{0, "clk32", NULL, CLK_IS_ROOT, 32768},
|
||||
{0, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
|
||||
{0, "pll1_624", NULL, CLK_IS_ROOT, 624000000},
|
||||
{0, "pll5p", NULL, CLK_IS_ROOT, 832000000},
|
||||
{0, "pll5", NULL, CLK_IS_ROOT, 1248000000},
|
||||
{0, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
|
||||
};
|
||||
|
||||
static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
|
||||
{0, "pll1_d2", "pll1_624", 1, 2, 0},
|
||||
{0, "pll1_d9", "pll1_624", 1, 9, 0},
|
||||
{0, "pll1_d12", "pll1_624", 1, 12, 0},
|
||||
{0, "pll1_d16", "pll1_624", 1, 16, 0},
|
||||
{0, "pll1_d20", "pll1_624", 1, 20, 0},
|
||||
{0, "pll1_416", "pll1_624", 2, 3, 0},
|
||||
{0, "vctcxo_d2", "vctcxo", 1, 2, 0},
|
||||
{0, "vctcxo_d4", "vctcxo", 1, 4, 0},
|
||||
};
|
||||
|
||||
static struct mmp_clk_factor_masks uart_factor_masks = {
|
||||
.factor = 2,
|
||||
.num_mask = 0x1fff,
|
||||
.den_mask = 0x1fff,
|
||||
.num_shift = 16,
|
||||
.den_shift = 0,
|
||||
};
|
||||
|
||||
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
|
||||
{.num = 832, .den = 234}, /*58.5MHZ */
|
||||
{.num = 1, .den = 1}, /*26MHZ */
|
||||
};
|
||||
|
||||
static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct mmp_clk_unit *unit = &pxa_unit->unit;
|
||||
|
||||
mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
|
||||
ARRAY_SIZE(fixed_rate_clks));
|
||||
|
||||
mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
|
||||
ARRAY_SIZE(fixed_factor_clks));
|
||||
|
||||
clk = mmp_clk_register_factor("uart_pll", "pll1_416",
|
||||
CLK_SET_RATE_PARENT,
|
||||
pxa_unit->mpmu_base + MPMU_UART_PLL,
|
||||
&uart_factor_masks, uart_factor_tbl,
|
||||
ARRAY_SIZE(uart_factor_tbl), NULL);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(uart0_lock);
|
||||
static DEFINE_SPINLOCK(uart1_lock);
|
||||
static DEFINE_SPINLOCK(uart2_lock);
|
||||
static DEFINE_SPINLOCK(uart3_lock);
|
||||
static const char *uart_parent_names[] = {"uart_pll", "vctcxo"};
|
||||
|
||||
static DEFINE_SPINLOCK(ssp0_lock);
|
||||
static DEFINE_SPINLOCK(ssp1_lock);
|
||||
static const char *ssp_parent_names[] = {"vctcxo_d4", "vctcxo_d2", "vctcxo", "pll1_d12"};
|
||||
|
||||
static DEFINE_SPINLOCK(reset_lock);
|
||||
|
||||
static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
{0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 4, 3, 0, &uart0_lock},
|
||||
{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 4, 3, 0, &uart1_lock},
|
||||
{0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 4, 3, 0, &uart2_lock},
|
||||
{0, "uart3_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 4, 3, 0, &uart3_lock},
|
||||
{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 4, 3, 0, &ssp0_lock},
|
||||
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 4, 3, 0, &ssp1_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_gate_clk apbc_gate_clks[] = {
|
||||
{PXA1928_CLK_TWSI0, "twsi0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_TWSI1, "twsi1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_TWSI2, "twsi2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_TWSI3, "twsi3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_TWSI4, "twsi4_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI4 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_TWSI5, "twsi5_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI5 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_GPIO * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_KPC * 4, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
|
||||
{PXA1928_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_RTC * 4, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
|
||||
{PXA1928_CLK_PWM0, "pwm0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_PWM1, "pwm1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_PWM2, "pwm2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
{PXA1928_CLK_PWM3, "pwm3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
|
||||
/* The gate clocks has mux parent. */
|
||||
{PXA1928_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 0x3, 0x3, 0x0, 0, &uart0_lock},
|
||||
{PXA1928_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 0x3, 0x3, 0x0, 0, &uart1_lock},
|
||||
{PXA1928_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 0x3, 0x3, 0x0, 0, &uart2_lock},
|
||||
{PXA1928_CLK_UART3, "uart3_clk", "uart3_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 0x3, 0x3, 0x0, 0, &uart3_lock},
|
||||
{PXA1928_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 0x3, 0x3, 0x0, 0, &ssp0_lock},
|
||||
{PXA1928_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 0x3, 0x3, 0x0, 0, &ssp1_lock},
|
||||
};
|
||||
|
||||
static void pxa1928_apb_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
|
||||
{
|
||||
struct mmp_clk_unit *unit = &pxa_unit->unit;
|
||||
|
||||
mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base,
|
||||
ARRAY_SIZE(apbc_mux_clks));
|
||||
|
||||
mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
|
||||
ARRAY_SIZE(apbc_gate_clks));
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(sdh0_lock);
|
||||
static DEFINE_SPINLOCK(sdh1_lock);
|
||||
static DEFINE_SPINLOCK(sdh2_lock);
|
||||
static DEFINE_SPINLOCK(sdh3_lock);
|
||||
static DEFINE_SPINLOCK(sdh4_lock);
|
||||
static const char *sdh_parent_names[] = {"pll1_624", "pll5p", "pll5", "pll1_416"};
|
||||
|
||||
static DEFINE_SPINLOCK(usb_lock);
|
||||
|
||||
static struct mmp_param_mux_clk apmu_mux_clks[] = {
|
||||
{0, "sdh_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 8, 2, 0, &sdh0_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_div_clk apmu_div_clks[] = {
|
||||
{0, "sdh_div", "sdh_mux", 0, PXA1928_CLK_SDH0 * 4, 10, 4, CLK_DIVIDER_ONE_BASED, &sdh0_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_gate_clk apmu_gate_clks[] = {
|
||||
{PXA1928_CLK_USB, "usb_clk", "usb_pll", 0, PXA1928_CLK_USB * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
|
||||
{PXA1928_CLK_HSIC, "hsic_clk", "usb_pll", 0, PXA1928_CLK_HSIC * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
|
||||
/* The gate clocks has mux parent. */
|
||||
{PXA1928_CLK_SDH0, "sdh0_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 0x1b, 0x1b, 0x0, 0, &sdh0_lock},
|
||||
{PXA1928_CLK_SDH1, "sdh1_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH1 * 4, 0x1b, 0x1b, 0x0, 0, &sdh1_lock},
|
||||
{PXA1928_CLK_SDH2, "sdh2_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH2 * 4, 0x1b, 0x1b, 0x0, 0, &sdh2_lock},
|
||||
{PXA1928_CLK_SDH3, "sdh3_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH3 * 4, 0x1b, 0x1b, 0x0, 0, &sdh3_lock},
|
||||
{PXA1928_CLK_SDH4, "sdh4_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH4 * 4, 0x1b, 0x1b, 0x0, 0, &sdh4_lock},
|
||||
};
|
||||
|
||||
static void pxa1928_axi_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
|
||||
{
|
||||
struct mmp_clk_unit *unit = &pxa_unit->unit;
|
||||
|
||||
mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base,
|
||||
ARRAY_SIZE(apmu_mux_clks));
|
||||
|
||||
mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base,
|
||||
ARRAY_SIZE(apmu_div_clks));
|
||||
|
||||
mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base,
|
||||
ARRAY_SIZE(apmu_gate_clks));
|
||||
}
|
||||
|
||||
static void pxa1928_clk_reset_init(struct device_node *np,
|
||||
struct pxa1928_clk_unit *pxa_unit)
|
||||
{
|
||||
struct mmp_clk_reset_cell *cells;
|
||||
int i, base, nr_resets;
|
||||
|
||||
nr_resets = ARRAY_SIZE(apbc_gate_clks);
|
||||
cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL);
|
||||
if (!cells)
|
||||
return;
|
||||
|
||||
base = 0;
|
||||
for (i = 0; i < nr_resets; i++) {
|
||||
cells[base + i].clk_id = apbc_gate_clks[i].id;
|
||||
cells[base + i].reg =
|
||||
pxa_unit->apbc_base + apbc_gate_clks[i].offset;
|
||||
cells[base + i].flags = 0;
|
||||
cells[base + i].lock = apbc_gate_clks[i].lock;
|
||||
cells[base + i].bits = 0x4;
|
||||
}
|
||||
|
||||
mmp_clk_reset_register(np, cells, nr_resets);
|
||||
}
|
||||
|
||||
static void __init pxa1928_mpmu_clk_init(struct device_node *np)
|
||||
{
|
||||
struct pxa1928_clk_unit *pxa_unit;
|
||||
|
||||
pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
|
||||
if (!pxa_unit)
|
||||
return;
|
||||
|
||||
pxa_unit->mpmu_base = of_iomap(np, 0);
|
||||
if (!pxa_unit->mpmu_base) {
|
||||
pr_err("failed to map mpmu registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pxa1928_pll_init(pxa_unit);
|
||||
}
|
||||
CLK_OF_DECLARE(pxa1928_mpmu_clk, "marvell,pxa1928-mpmu", pxa1928_mpmu_clk_init);
|
||||
|
||||
static void __init pxa1928_apmu_clk_init(struct device_node *np)
|
||||
{
|
||||
struct pxa1928_clk_unit *pxa_unit;
|
||||
|
||||
pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
|
||||
if (!pxa_unit)
|
||||
return;
|
||||
|
||||
pxa_unit->apmu_base = of_iomap(np, 0);
|
||||
if (!pxa_unit->apmu_base) {
|
||||
pr_err("failed to map apmu registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mmp_clk_init(np, &pxa_unit->unit, PXA1928_APMU_NR_CLKS);
|
||||
|
||||
pxa1928_axi_periph_clk_init(pxa_unit);
|
||||
}
|
||||
CLK_OF_DECLARE(pxa1928_apmu_clk, "marvell,pxa1928-apmu", pxa1928_apmu_clk_init);
|
||||
|
||||
static void __init pxa1928_apbc_clk_init(struct device_node *np)
|
||||
{
|
||||
struct pxa1928_clk_unit *pxa_unit;
|
||||
|
||||
pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
|
||||
if (!pxa_unit)
|
||||
return;
|
||||
|
||||
pxa_unit->apbc_base = of_iomap(np, 0);
|
||||
if (!pxa_unit->apbc_base) {
|
||||
pr_err("failed to map apbc registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mmp_clk_init(np, &pxa_unit->unit, PXA1928_APBC_NR_CLKS);
|
||||
|
||||
pxa1928_apb_periph_clk_init(pxa_unit);
|
||||
pxa1928_clk_reset_init(np, pxa_unit);
|
||||
}
|
||||
CLK_OF_DECLARE(pxa1928_apbc_clk, "marvell,pxa1928-apbc", pxa1928_apbc_clk_init);
|
@ -35,6 +35,8 @@
|
||||
#define APBC_SSP0 0x1c
|
||||
#define APBC_SSP1 0x20
|
||||
#define APBC_SSP2 0x4c
|
||||
#define APBC_TIMER0 0x30
|
||||
#define APBC_TIMER1 0x44
|
||||
#define APBCP_TWSI1 0x28
|
||||
#define APBCP_UART2 0x1c
|
||||
#define APMU_SDH0 0x54
|
||||
@ -57,6 +59,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
|
||||
{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
|
||||
{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
|
||||
{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
|
||||
{PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
|
||||
};
|
||||
|
||||
static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
|
||||
@ -69,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
|
||||
{PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
|
||||
{PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
|
||||
{PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
|
||||
{PXA910_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
|
||||
{PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
|
||||
{PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
|
||||
{PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
|
||||
@ -115,6 +119,10 @@ static DEFINE_SPINLOCK(ssp0_lock);
|
||||
static DEFINE_SPINLOCK(ssp1_lock);
|
||||
static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
|
||||
|
||||
static DEFINE_SPINLOCK(timer0_lock);
|
||||
static DEFINE_SPINLOCK(timer1_lock);
|
||||
static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96"};
|
||||
|
||||
static DEFINE_SPINLOCK(reset_lock);
|
||||
|
||||
static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
@ -122,6 +130,8 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
|
||||
{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
|
||||
{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock},
|
||||
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
|
||||
{0, "timer0_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER0, 4, 3, 0, &timer0_lock},
|
||||
{0, "timer1_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER1, 4, 3, 0, &timer1_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_mux_clk apbcp_mux_clks[] = {
|
||||
@ -142,6 +152,8 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
|
||||
{PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock},
|
||||
{PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock},
|
||||
{PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock},
|
||||
{PXA910_CLK_TIMER0, "timer0_clk", "timer0_mux", CLK_SET_RATE_PARENT, APBC_TIMER0, 0x3, 0x3, 0x0, 0, &timer0_lock},
|
||||
{PXA910_CLK_TIMER1, "timer1_clk", "timer1_mux", CLK_SET_RATE_PARENT, APBC_TIMER1, 0x3, 0x3, 0x0, 0, &timer1_lock},
|
||||
};
|
||||
|
||||
static struct mmp_param_gate_clk apbcp_gate_clks[] = {
|
||||
|
@ -163,6 +163,7 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
|
||||
{ "pex1", "pex1_en", 9, 0 },
|
||||
{ "sata0", NULL, 15, 0 },
|
||||
{ "sdio", NULL, 17, 0 },
|
||||
{ "crypto", NULL, 23, 0 },
|
||||
{ "tdm", NULL, 25, 0 },
|
||||
{ "ddr", NULL, 28, CLK_IGNORE_UNUSED },
|
||||
{ "sata1", NULL, 30, 0 },
|
||||
|
@ -77,12 +77,12 @@ static void __init clk_misc_init(void)
|
||||
writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
|
||||
}
|
||||
|
||||
static const char *sel_pll[] __initdata = { "pll", "ref_xtal", };
|
||||
static const char *sel_cpu[] __initdata = { "ref_cpu", "ref_xtal", };
|
||||
static const char *sel_pix[] __initdata = { "ref_pix", "ref_xtal", };
|
||||
static const char *sel_io[] __initdata = { "ref_io", "ref_xtal", };
|
||||
static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
|
||||
static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
|
||||
static const char *const sel_pll[] __initconst = { "pll", "ref_xtal", };
|
||||
static const char *const sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
|
||||
static const char *const sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
|
||||
static const char *const sel_io[] __initconst = { "ref_io", "ref_xtal", };
|
||||
static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
|
||||
static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
|
||||
|
||||
enum imx23_clk {
|
||||
ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
|
||||
|
@ -125,15 +125,15 @@ static void __init clk_misc_init(void)
|
||||
writel_relaxed(val, FRAC0);
|
||||
}
|
||||
|
||||
static const char *sel_cpu[] __initdata = { "ref_cpu", "ref_xtal", };
|
||||
static const char *sel_io0[] __initdata = { "ref_io0", "ref_xtal", };
|
||||
static const char *sel_io1[] __initdata = { "ref_io1", "ref_xtal", };
|
||||
static const char *sel_pix[] __initdata = { "ref_pix", "ref_xtal", };
|
||||
static const char *sel_gpmi[] __initdata = { "ref_gpmi", "ref_xtal", };
|
||||
static const char *sel_pll0[] __initdata = { "pll0", "ref_xtal", };
|
||||
static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
|
||||
static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
|
||||
static const char *ptp_sels[] __initdata = { "ref_xtal", "pll0", };
|
||||
static const char *const sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
|
||||
static const char *const sel_io0[] __initconst = { "ref_io0", "ref_xtal", };
|
||||
static const char *const sel_io1[] __initconst = { "ref_io1", "ref_xtal", };
|
||||
static const char *const sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
|
||||
static const char *const sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", };
|
||||
static const char *const sel_pll0[] __initconst = { "pll0", "ref_xtal", };
|
||||
static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
|
||||
static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
|
||||
static const char *const ptp_sels[] __initconst = { "ref_xtal", "pll0", };
|
||||
|
||||
enum imx28_clk {
|
||||
ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1,
|
||||
|
@ -49,7 +49,7 @@ static inline struct clk *mxs_clk_gate(const char *name,
|
||||
}
|
||||
|
||||
static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
|
||||
u8 shift, u8 width, const char **parent_names, int num_parents)
|
||||
u8 shift, u8 width, const char *const *parent_names, int num_parents)
|
||||
{
|
||||
return clk_register_mux(NULL, name, parent_names, num_parents,
|
||||
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
|
||||
|
@ -6,9 +6,12 @@
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk.h"
|
||||
@ -50,6 +53,18 @@
|
||||
#define PLL_CTRL4 0x10
|
||||
#define PLL_FRAC_CTRL4_BYPASS BIT(28)
|
||||
|
||||
#define MIN_PFD 9600000UL
|
||||
#define MIN_VCO_LA 400000000UL
|
||||
#define MAX_VCO_LA 1600000000UL
|
||||
#define MIN_VCO_FRAC_INT 600000000UL
|
||||
#define MAX_VCO_FRAC_INT 1600000000UL
|
||||
#define MIN_VCO_FRAC_FRAC 600000000UL
|
||||
#define MAX_VCO_FRAC_FRAC 2400000000UL
|
||||
#define MIN_OUTPUT_LA 8000000UL
|
||||
#define MAX_OUTPUT_LA 1600000000UL
|
||||
#define MIN_OUTPUT_FRAC 12000000UL
|
||||
#define MAX_OUTPUT_FRAC 1600000000UL
|
||||
|
||||
struct pistachio_clk_pll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
@ -67,6 +82,12 @@ static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
|
||||
writel(val, pll->base + reg);
|
||||
}
|
||||
|
||||
static inline void pll_lock(struct pistachio_clk_pll *pll)
|
||||
{
|
||||
while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
|
||||
{
|
||||
dividend += divisor / 2;
|
||||
@ -124,6 +145,8 @@ static int pll_gf40lp_frac_enable(struct clk_hw *hw)
|
||||
val &= ~PLL_FRAC_CTRL4_BYPASS;
|
||||
pll_writel(pll, val, PLL_CTRL4);
|
||||
|
||||
pll_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -149,16 +172,29 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
{
|
||||
struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
|
||||
struct pistachio_pll_rate_table *params;
|
||||
bool was_enabled;
|
||||
u32 val;
|
||||
int enabled = pll_gf40lp_frac_is_enabled(hw);
|
||||
u32 val, vco, old_postdiv1, old_postdiv2;
|
||||
const char *name = __clk_get_name(hw->clk);
|
||||
|
||||
params = pll_get_params(pll, parent_rate, rate);
|
||||
if (!params)
|
||||
if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
|
||||
return -EINVAL;
|
||||
|
||||
was_enabled = pll_gf40lp_frac_is_enabled(hw);
|
||||
if (!was_enabled)
|
||||
pll_gf40lp_frac_enable(hw);
|
||||
params = pll_get_params(pll, parent_rate, rate);
|
||||
if (!params || !params->refdiv)
|
||||
return -EINVAL;
|
||||
|
||||
vco = params->fref * params->fbdiv / params->refdiv;
|
||||
if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
|
||||
pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
|
||||
MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
|
||||
|
||||
val = params->fref / params->refdiv;
|
||||
if (val < MIN_PFD)
|
||||
pr_warn("%s: PFD %u is too low (min %lu)\n",
|
||||
name, val, MIN_PFD);
|
||||
if (val > vco / 16)
|
||||
pr_warn("%s: PFD %u is too high (max %u)\n",
|
||||
name, val, vco / 16);
|
||||
|
||||
val = pll_readl(pll, PLL_CTRL1);
|
||||
val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
|
||||
@ -168,6 +204,19 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
pll_writel(pll, val, PLL_CTRL1);
|
||||
|
||||
val = pll_readl(pll, PLL_CTRL2);
|
||||
|
||||
old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
|
||||
PLL_FRAC_CTRL2_POSTDIV1_MASK;
|
||||
old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
|
||||
PLL_FRAC_CTRL2_POSTDIV2_MASK;
|
||||
if (enabled &&
|
||||
(params->postdiv1 != old_postdiv1 ||
|
||||
params->postdiv2 != old_postdiv2))
|
||||
pr_warn("%s: changing postdiv while PLL is enabled\n", name);
|
||||
|
||||
if (params->postdiv2 > params->postdiv1)
|
||||
pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
|
||||
|
||||
val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
|
||||
(PLL_FRAC_CTRL2_POSTDIV1_MASK <<
|
||||
PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
|
||||
@ -178,11 +227,8 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
(params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
|
||||
pll_writel(pll, val, PLL_CTRL2);
|
||||
|
||||
while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
|
||||
cpu_relax();
|
||||
|
||||
if (!was_enabled)
|
||||
pll_gf40lp_frac_disable(hw);
|
||||
if (enabled)
|
||||
pll_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -241,6 +287,8 @@ static int pll_gf40lp_laint_enable(struct clk_hw *hw)
|
||||
val &= ~PLL_INT_CTRL2_BYPASS;
|
||||
pll_writel(pll, val, PLL_CTRL2);
|
||||
|
||||
pll_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -266,18 +314,44 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
{
|
||||
struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
|
||||
struct pistachio_pll_rate_table *params;
|
||||
bool was_enabled;
|
||||
u32 val;
|
||||
int enabled = pll_gf40lp_laint_is_enabled(hw);
|
||||
u32 val, vco, old_postdiv1, old_postdiv2;
|
||||
const char *name = __clk_get_name(hw->clk);
|
||||
|
||||
params = pll_get_params(pll, parent_rate, rate);
|
||||
if (!params)
|
||||
if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
|
||||
return -EINVAL;
|
||||
|
||||
was_enabled = pll_gf40lp_laint_is_enabled(hw);
|
||||
if (!was_enabled)
|
||||
pll_gf40lp_laint_enable(hw);
|
||||
params = pll_get_params(pll, parent_rate, rate);
|
||||
if (!params || !params->refdiv)
|
||||
return -EINVAL;
|
||||
|
||||
vco = params->fref * params->fbdiv / params->refdiv;
|
||||
if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
|
||||
pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
|
||||
MIN_VCO_LA, MAX_VCO_LA);
|
||||
|
||||
val = params->fref / params->refdiv;
|
||||
if (val < MIN_PFD)
|
||||
pr_warn("%s: PFD %u is too low (min %lu)\n",
|
||||
name, val, MIN_PFD);
|
||||
if (val > vco / 16)
|
||||
pr_warn("%s: PFD %u is too high (max %u)\n",
|
||||
name, val, vco / 16);
|
||||
|
||||
val = pll_readl(pll, PLL_CTRL1);
|
||||
|
||||
old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
|
||||
PLL_INT_CTRL1_POSTDIV1_MASK;
|
||||
old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
|
||||
PLL_INT_CTRL1_POSTDIV2_MASK;
|
||||
if (enabled &&
|
||||
(params->postdiv1 != old_postdiv1 ||
|
||||
params->postdiv2 != old_postdiv2))
|
||||
pr_warn("%s: changing postdiv while PLL is enabled\n", name);
|
||||
|
||||
if (params->postdiv2 > params->postdiv1)
|
||||
pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
|
||||
|
||||
val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
|
||||
(PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
|
||||
(PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
|
||||
@ -288,11 +362,8 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
(params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
|
||||
pll_writel(pll, val, PLL_CTRL1);
|
||||
|
||||
while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
|
||||
cpu_relax();
|
||||
|
||||
if (!was_enabled)
|
||||
pll_gf40lp_laint_disable(hw);
|
||||
if (enabled)
|
||||
pll_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define _CLK_PXA_
|
||||
|
||||
#define PARENTS(name) \
|
||||
static const char *name ## _parents[] __initdata
|
||||
static const char *const name ## _parents[] __initconst
|
||||
#define MUX_RO_RATE_RO_OPS(name, clk_name) \
|
||||
static struct clk_hw name ## _mux_hw; \
|
||||
static struct clk_hw name ## _rate_hw; \
|
||||
@ -72,7 +72,7 @@ struct desc_clk_cken {
|
||||
const char *name;
|
||||
const char *dev_id;
|
||||
const char *con_id;
|
||||
const char **parent_names;
|
||||
const char * const *parent_names;
|
||||
struct clk_fixed_factor lp;
|
||||
struct clk_fixed_factor hp;
|
||||
struct clk_gate gate;
|
||||
|
@ -231,7 +231,7 @@ static int rockchip_cpuclk_notifier_cb(struct notifier_block *nb,
|
||||
}
|
||||
|
||||
struct clk *rockchip_clk_register_cpuclk(const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
const struct rockchip_cpuclk_reg_data *reg_data,
|
||||
const struct rockchip_cpuclk_rate_table *rates,
|
||||
int nrates, void __iomem *reg_base, spinlock_t *lock)
|
||||
|
@ -120,7 +120,7 @@ static const struct clk_ops rockchip_mmc_clk_ops = {
|
||||
};
|
||||
|
||||
struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *reg, int shift)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
|
@ -329,10 +329,10 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
|
||||
*/
|
||||
|
||||
struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
||||
const char *name, const char **parent_names, u8 num_parents,
|
||||
void __iomem *base, int con_offset, int grf_lock_offset,
|
||||
int lock_shift, int mode_offset, int mode_shift,
|
||||
struct rockchip_pll_rate_table *rate_table,
|
||||
const char *name, const char *const *parent_names,
|
||||
u8 num_parents, void __iomem *base, int con_offset,
|
||||
int grf_lock_offset, int lock_shift, int mode_offset,
|
||||
int mode_shift, struct rockchip_pll_rate_table *rate_table,
|
||||
u8 clk_pll_flags, spinlock_t *lock)
|
||||
{
|
||||
const char *pll_parents[3];
|
||||
|
@ -26,7 +26,7 @@ enum rk3188_plls {
|
||||
apll, cpll, dpll, gpll,
|
||||
};
|
||||
|
||||
struct rockchip_pll_rate_table rk3188_pll_rates[] = {
|
||||
static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
|
||||
RK3066_PLL_RATE(2208000000, 1, 92, 1),
|
||||
RK3066_PLL_RATE(2184000000, 1, 91, 1),
|
||||
RK3066_PLL_RATE(2160000000, 1, 90, 1),
|
||||
|
@ -27,7 +27,7 @@ enum rk3288_plls {
|
||||
apll, dpll, cpll, gpll, npll,
|
||||
};
|
||||
|
||||
struct rockchip_pll_rate_table rk3288_pll_rates[] = {
|
||||
static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
|
||||
RK3066_PLL_RATE(2208000000, 1, 92, 1),
|
||||
RK3066_PLL_RATE(2184000000, 1, 91, 1),
|
||||
RK3066_PLL_RATE(2160000000, 1, 90, 1),
|
||||
|
@ -39,7 +39,7 @@
|
||||
* sometimes without one of those components.
|
||||
*/
|
||||
static struct clk *rockchip_clk_register_branch(const char *name,
|
||||
const char **parent_names, u8 num_parents, void __iomem *base,
|
||||
const char *const *parent_names, u8 num_parents, void __iomem *base,
|
||||
int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
|
||||
u8 div_shift, u8 div_width, u8 div_flags,
|
||||
struct clk_div_table *div_table, int gate_offset,
|
||||
@ -103,8 +103,8 @@ static struct clk *rockchip_clk_register_branch(const char *name,
|
||||
}
|
||||
|
||||
static struct clk *rockchip_clk_register_frac_branch(const char *name,
|
||||
const char **parent_names, u8 num_parents, void __iomem *base,
|
||||
int muxdiv_offset, u8 div_flags,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *base, int muxdiv_offset, u8 div_flags,
|
||||
int gate_offset, u8 gate_shift, u8 gate_flags,
|
||||
unsigned long flags, spinlock_t *lock)
|
||||
{
|
||||
@ -297,7 +297,7 @@ void __init rockchip_clk_register_branches(
|
||||
}
|
||||
|
||||
void __init rockchip_clk_register_armclk(unsigned int lookup_id,
|
||||
const char *name, const char **parent_names,
|
||||
const char *name, const char *const *parent_names,
|
||||
u8 num_parents,
|
||||
const struct rockchip_cpuclk_reg_data *reg_data,
|
||||
const struct rockchip_cpuclk_rate_table *rates,
|
||||
|
@ -108,7 +108,7 @@ struct rockchip_pll_rate_table {
|
||||
struct rockchip_pll_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char **parent_names;
|
||||
const char *const *parent_names;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
int con_offset;
|
||||
@ -140,10 +140,10 @@ struct rockchip_pll_clock {
|
||||
}
|
||||
|
||||
struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
||||
const char *name, const char **parent_names, u8 num_parents,
|
||||
void __iomem *base, int con_offset, int grf_lock_offset,
|
||||
int lock_shift, int reg_mode, int mode_shift,
|
||||
struct rockchip_pll_rate_table *rate_table,
|
||||
const char *name, const char *const *parent_names,
|
||||
u8 num_parents, void __iomem *base, int con_offset,
|
||||
int grf_lock_offset, int lock_shift, int reg_mode,
|
||||
int mode_shift, struct rockchip_pll_rate_table *rate_table,
|
||||
u8 clk_pll_flags, spinlock_t *lock);
|
||||
|
||||
struct rockchip_cpuclk_clksel {
|
||||
@ -173,16 +173,16 @@ struct rockchip_cpuclk_reg_data {
|
||||
};
|
||||
|
||||
struct clk *rockchip_clk_register_cpuclk(const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
const struct rockchip_cpuclk_reg_data *reg_data,
|
||||
const struct rockchip_cpuclk_rate_table *rates,
|
||||
int nrates, void __iomem *reg_base, spinlock_t *lock);
|
||||
|
||||
struct clk *rockchip_clk_register_mmc(const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *reg, int shift);
|
||||
|
||||
#define PNAME(x) static const char *x[] __initdata
|
||||
#define PNAME(x) static const char *const x[] __initconst
|
||||
|
||||
enum rockchip_clk_branch_type {
|
||||
branch_composite,
|
||||
@ -197,7 +197,7 @@ struct rockchip_clk_branch {
|
||||
unsigned int id;
|
||||
enum rockchip_clk_branch_type branch_type;
|
||||
const char *name;
|
||||
const char **parent_names;
|
||||
const char *const *parent_names;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
int muxdiv_offset;
|
||||
@ -403,7 +403,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
|
||||
void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
|
||||
unsigned int nr_pll, int grf_lock_offset);
|
||||
void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
const struct rockchip_cpuclk_reg_data *reg_data,
|
||||
const struct rockchip_cpuclk_rate_table *rates,
|
||||
int nrates);
|
||||
|
@ -94,7 +94,7 @@ PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"};
|
||||
PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
|
||||
PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
|
||||
|
||||
struct samsung_mux_clock aud_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock aud_mux_clks[] __initdata = {
|
||||
MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
|
||||
MUX_SEL_AUD, 0, 1),
|
||||
MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
|
||||
@ -103,7 +103,7 @@ struct samsung_mux_clock aud_mux_clks[] __initdata = {
|
||||
MUX_SEL_AUD, 8, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock aud_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock aud_div_clks[] __initdata = {
|
||||
DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
|
||||
DIV_AUD0, 0, 4),
|
||||
|
||||
@ -115,7 +115,7 @@ struct samsung_div_clock aud_div_clks[] __initdata = {
|
||||
DIV_AUD1, 12, 4),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock aud_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock aud_gate_clks[] __initdata = {
|
||||
GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
|
||||
EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
|
||||
@ -135,7 +135,7 @@ struct samsung_gate_clock aud_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_aud_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = aud_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks);
|
||||
@ -203,7 +203,7 @@ PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll",
|
||||
PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
|
||||
"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
|
||||
|
||||
struct samsung_mux_clock disp_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock disp_mux_clks[] __initdata = {
|
||||
MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
|
||||
mout_aclk_disp_333_user_p,
|
||||
MUX_SEL_DISP0, 0, 1),
|
||||
@ -272,7 +272,7 @@ struct samsung_mux_clock disp_mux_clks[] __initdata = {
|
||||
MUX_SEL_DISP4, 4, 2),
|
||||
};
|
||||
|
||||
struct samsung_div_clock disp_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock disp_div_clks[] __initdata = {
|
||||
DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
|
||||
"mout_aclk_disp_222_user",
|
||||
DIV_DISP, 8, 4),
|
||||
@ -285,7 +285,7 @@ struct samsung_div_clock disp_div_clks[] __initdata = {
|
||||
DIV_DISP, 16, 4),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock disp_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock disp_gate_clks[] __initdata = {
|
||||
GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
|
||||
"mout_phyclk_hdmi_phy_pixel_clko_user",
|
||||
EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
|
||||
@ -325,7 +325,7 @@ struct samsung_gate_clock disp_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_disp_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = disp_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks);
|
||||
@ -363,13 +363,13 @@ static unsigned long egl_clk_regs[] __initdata = {
|
||||
PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
|
||||
PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
|
||||
|
||||
struct samsung_mux_clock egl_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock egl_mux_clks[] __initdata = {
|
||||
MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
|
||||
MUX_SEL_EGL, 4, 1),
|
||||
MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock egl_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock egl_div_clks[] __initdata = {
|
||||
DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
|
||||
DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
|
||||
DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
|
||||
@ -389,7 +389,7 @@ static struct samsung_pll_clock egl_pll_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_egl_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = egl_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks);
|
||||
@ -433,7 +433,7 @@ PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll",
|
||||
PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
|
||||
"phyclk_usbdrd30_udrd30_phyclock"};
|
||||
|
||||
struct samsung_mux_clock fsys_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
|
||||
MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
|
||||
"mout_phyclk_usbdrd30_phyclock_user",
|
||||
mout_phyclk_usbdrd30_phyclock_user_p,
|
||||
@ -456,7 +456,7 @@ struct samsung_mux_clock fsys_mux_clks[] __initdata = {
|
||||
MUX_SEL_FSYS1, 16, 1),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock fsys_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
|
||||
GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
|
||||
"mout_phyclk_usbdrd30_phyclock_user",
|
||||
EN_SCLK_FSYS, 1, 0, 0),
|
||||
@ -491,7 +491,7 @@ struct samsung_gate_clock fsys_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_fsys_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = fsys_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks);
|
||||
@ -537,18 +537,18 @@ static unsigned long g2d_clk_regs[] __initdata = {
|
||||
|
||||
PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
|
||||
|
||||
struct samsung_mux_clock g2d_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
|
||||
MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
|
||||
mout_aclk_g2d_333_user_p,
|
||||
MUX_SEL_G2D, 0, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock g2d_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock g2d_div_clks[] __initdata = {
|
||||
DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
|
||||
DIV_G2D, 0, 3),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock g2d_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
|
||||
GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
|
||||
EN_IP_G2D, 4, 0, 0),
|
||||
GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
|
||||
@ -580,7 +580,7 @@ struct samsung_gate_clock g2d_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_g2d_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = g2d_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks);
|
||||
@ -617,17 +617,17 @@ static unsigned long g3d_clk_regs[] __initdata = {
|
||||
|
||||
PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
|
||||
|
||||
struct samsung_mux_clock g3d_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
|
||||
MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
|
||||
MUX_SEL_G3D, 0, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock g3d_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock g3d_div_clks[] __initdata = {
|
||||
DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
|
||||
DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock g3d_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
|
||||
GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
|
||||
GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
|
||||
EN_IP_G3D, 3, 0, 0),
|
||||
@ -641,7 +641,7 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_g3d_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = g3d_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks);
|
||||
@ -694,7 +694,7 @@ PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
|
||||
PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
|
||||
PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
|
||||
|
||||
struct samsung_mux_clock gscl_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
|
||||
MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
|
||||
mout_aclk_gscl_333_user_p,
|
||||
MUX_SEL_GSCL, 0, 1),
|
||||
@ -708,7 +708,7 @@ struct samsung_mux_clock gscl_mux_clks[] __initdata = {
|
||||
MUX_SEL_GSCL, 24, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock gscl_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock gscl_div_clks[] __initdata = {
|
||||
DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
|
||||
"mout_aclk_m2m_400_user",
|
||||
DIV_GSCL, 0, 3),
|
||||
@ -717,7 +717,7 @@ struct samsung_div_clock gscl_div_clks[] __initdata = {
|
||||
DIV_GSCL, 4, 3),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock gscl_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
|
||||
GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
|
||||
EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
|
||||
@ -776,7 +776,7 @@ struct samsung_gate_clock gscl_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_gscl_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = gscl_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks);
|
||||
@ -813,14 +813,14 @@ static unsigned long isp_clk_regs[] __initdata = {
|
||||
PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
|
||||
PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"};
|
||||
|
||||
struct samsung_mux_clock isp_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock isp_mux_clks[] __initdata = {
|
||||
MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
|
||||
MUX_SEL_ISP0, 0, 1),
|
||||
MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
|
||||
MUX_SEL_ISP0, 4, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock isp_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock isp_div_clks[] __initdata = {
|
||||
DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
|
||||
DIV_ISP, 0, 3),
|
||||
DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
|
||||
@ -832,7 +832,7 @@ struct samsung_div_clock isp_div_clks[] __initdata = {
|
||||
DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock isp_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock isp_gate_clks[] __initdata = {
|
||||
GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
|
||||
EN_IP_ISP0, 15, 0, 0),
|
||||
|
||||
@ -895,7 +895,7 @@ struct samsung_gate_clock isp_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_isp_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = isp_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks);
|
||||
@ -934,13 +934,13 @@ static unsigned long kfc_clk_regs[] __initdata = {
|
||||
PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
|
||||
PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"};
|
||||
|
||||
struct samsung_mux_clock kfc_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock kfc_mux_clks[] __initdata = {
|
||||
MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
|
||||
MUX_SEL_KFC0, 0, 1),
|
||||
MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock kfc_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock kfc_div_clks[] __initdata = {
|
||||
DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
|
||||
DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
|
||||
DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
|
||||
@ -959,7 +959,7 @@ static struct samsung_pll_clock kfc_pll_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_kfc_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = kfc_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks);
|
||||
@ -993,18 +993,18 @@ static unsigned long mfc_clk_regs[] __initdata = {
|
||||
|
||||
PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
|
||||
|
||||
struct samsung_mux_clock mfc_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
|
||||
MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
|
||||
mout_aclk_mfc_333_user_p,
|
||||
MUX_SEL_MFC, 0, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock mfc_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock mfc_div_clks[] __initdata = {
|
||||
DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
|
||||
DIV_MFC, 0, 3),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock mfc_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
|
||||
GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
|
||||
EN_IP_MFC, 1, 0, 0),
|
||||
GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
|
||||
@ -1015,7 +1015,7 @@ struct samsung_gate_clock mfc_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_mfc_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = mfc_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks);
|
||||
@ -1078,7 +1078,7 @@ PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"};
|
||||
PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
|
||||
PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
|
||||
|
||||
struct samsung_mux_clock mif_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock mif_mux_clks[] __initdata = {
|
||||
MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
|
||||
MUX_SEL_MIF, 0, 1),
|
||||
MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
|
||||
@ -1095,7 +1095,7 @@ struct samsung_mux_clock mif_mux_clks[] __initdata = {
|
||||
MUX_SEL_MIF, 24, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock mif_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock mif_div_clks[] __initdata = {
|
||||
DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
|
||||
DIV_MIF, 0, 3),
|
||||
DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
|
||||
@ -1114,7 +1114,7 @@ struct samsung_div_clock mif_div_clks[] __initdata = {
|
||||
DIV_MIF, 28, 4),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock mif_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock mif_gate_clks[] __initdata = {
|
||||
GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
|
||||
EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
|
||||
@ -1162,7 +1162,7 @@ static struct samsung_pll_clock mif_pll_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_mif_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = mif_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks);
|
||||
@ -1221,7 +1221,7 @@ PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud",
|
||||
PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
|
||||
"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
|
||||
|
||||
struct samsung_mux_clock peri_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock peri_mux_clks[] __initdata = {
|
||||
MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
|
||||
MUX_SEL_PERI1, 4, 2),
|
||||
MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
|
||||
@ -1230,12 +1230,12 @@ struct samsung_mux_clock peri_mux_clks[] __initdata = {
|
||||
MUX_SEL_PERI1, 20, 2),
|
||||
};
|
||||
|
||||
struct samsung_div_clock peri_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock peri_div_clks[] __initdata = {
|
||||
DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
|
||||
DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock peri_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock peri_gate_clks[] __initdata = {
|
||||
GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
|
||||
CLK_SET_RATE_PARENT, 0),
|
||||
GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
|
||||
@ -1370,7 +1370,7 @@ struct samsung_gate_clock peri_gate_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_peri_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = peri_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks);
|
||||
@ -1432,7 +1432,7 @@ static unsigned long top_clk_regs[] __initdata = {
|
||||
};
|
||||
|
||||
/* fixed rate clocks generated inside the soc */
|
||||
struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
|
||||
static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
|
||||
FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
|
||||
CLK_IS_ROOT, 270000000),
|
||||
FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
|
||||
@ -1519,7 +1519,7 @@ PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a",
|
||||
PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
|
||||
"mout_mediatop_pll_user"};
|
||||
|
||||
struct samsung_mux_clock top_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock top_mux_clks[] __initdata = {
|
||||
MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
|
||||
mout_mediatop_pll_user_p,
|
||||
MUX_SEL_TOP_PLL0, 0, 1),
|
||||
@ -1679,7 +1679,7 @@ struct samsung_mux_clock top_mux_clks[] __initdata = {
|
||||
MUX_SEL_TOP_GSCL, 20, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock top_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock top_div_clks[] __initdata = {
|
||||
DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
|
||||
DIV_TOP_G2D_MFC, 0, 3),
|
||||
DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
|
||||
@ -1800,7 +1800,7 @@ struct samsung_div_clock top_div_clks[] __initdata = {
|
||||
|
||||
};
|
||||
|
||||
struct samsung_gate_clock top_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock top_gate_clks[] __initdata = {
|
||||
GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
|
||||
"dout_sclk_fsys_mmc0_sdclkin_b",
|
||||
EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
|
||||
@ -1826,7 +1826,7 @@ static struct samsung_pll_clock top_pll_clks[] __initdata = {
|
||||
|
||||
static void __init exynos5260_clk_top_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = {0};
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = top_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks);
|
||||
|
@ -504,7 +504,7 @@ static struct samsung_fixed_factor_clock
|
||||
FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
|
||||
};
|
||||
|
||||
struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
|
||||
MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
|
||||
MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
|
||||
MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
|
||||
@ -553,7 +553,7 @@ struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
|
||||
MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
|
||||
};
|
||||
|
||||
struct samsung_div_clock exynos5800_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
|
||||
DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3),
|
||||
|
||||
DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
|
||||
@ -569,14 +569,14 @@ struct samsung_div_clock exynos5800_div_clks[] __initdata = {
|
||||
DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
|
||||
static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
|
||||
GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
|
||||
GATE_BUS_TOP, 24, 0, 0),
|
||||
GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
|
||||
GATE_BUS_TOP, 27, 0, 0),
|
||||
};
|
||||
|
||||
struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
|
||||
static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
|
||||
MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
|
||||
MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
|
||||
TOP_SPARE2, 4, 1),
|
||||
@ -606,7 +606,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
|
||||
MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
|
||||
};
|
||||
|
||||
struct samsung_div_clock exynos5420_div_clks[] __initdata = {
|
||||
static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
|
||||
DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
|
||||
DIV_TOP0, 16, 3),
|
||||
};
|
||||
|
@ -835,6 +835,7 @@ static unsigned long cpif_clk_regs[] __initdata = {
|
||||
MPHY_PLL_CON1,
|
||||
MPHY_PLL_FREQ_DET,
|
||||
MUX_SEL_CPIF0,
|
||||
DIV_CPIF,
|
||||
ENABLE_SCLK_CPIF,
|
||||
};
|
||||
|
||||
@ -1389,7 +1390,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
|
||||
|
||||
/* ENABLE_ACLK_MIF2 */
|
||||
GATE(CLK_ACLK_MIFND_266, "aclk_mifnd_266", "div_aclk_mif_266",
|
||||
ENABLE_ACLK_MIF2, 20, 0, 0),
|
||||
ENABLE_ACLK_MIF2, 20, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_ACLK_PPMU_DREX1S3, "aclk_ppmu_drex1s3", "div_aclk_drex1",
|
||||
ENABLE_ACLK_MIF2, 17, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_ACLK_PPMU_DREX1S1, "aclk_ppmu_drex1s1", "div_aclk_drex1",
|
||||
@ -1832,39 +1833,39 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
|
||||
|
||||
/* ENABLE_PCLK_PERIS_SECURE_TZPC */
|
||||
GATE(CLK_PCLK_TZPC12, "pclk_tzpc12", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 12, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 12, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC11, "pclk_tzpc11", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 11, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 11, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC10, "pclk_tzpc10", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 10, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 10, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC9, "pclk_tzpc9", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 9, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 9, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC8, "pclk_tzpc8", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 8, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 8, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC7, "pclk_tzpc7", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 7, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 7, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC6, "pclk_tzpc6", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 6, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 6, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC5, "pclk_tzpc5", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 5, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 5, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC4, "pclk_tzpc4", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 4, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 4, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC3, "pclk_tzpc3", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 3, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 3, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC2, "pclk_tzpc2", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 2, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 2, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC1, "pclk_tzpc1", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 1, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 1, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_PCLK_TZPC0, "pclk_tzpc0", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 0, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_TZPC, 0, CLK_IGNORE_UNUSED, 0),
|
||||
|
||||
/* ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF */
|
||||
GATE(CLK_PCLK_SECKEY_APBIF, "pclk_seckey_apbif", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, CLK_IGNORE_UNUSED, 0),
|
||||
|
||||
/* ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF */
|
||||
GATE(CLK_PCLK_CHIPID_APBIF, "pclk_chipid_apbif", "aclk_peris_66",
|
||||
ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, 0, 0),
|
||||
ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, CLK_IGNORE_UNUSED, 0),
|
||||
|
||||
/* ENABLE_PCLK_PERIS_SECURE_TOPRTC */
|
||||
GATE(CLK_PCLK_TOPRTC, "pclk_toprtc", "aclk_peris_66",
|
||||
@ -1895,11 +1896,11 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
|
||||
|
||||
/* ENABLE_SCLK_PERIS_SECURE_SECKEY */
|
||||
GATE(CLK_SCLK_SECKEY, "sclk_seckey", "oscclk_efuse_common",
|
||||
ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, 0, 0),
|
||||
ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, CLK_IGNORE_UNUSED, 0),
|
||||
|
||||
/* ENABLE_SCLK_PERIS_SECURE_CHIPID */
|
||||
GATE(CLK_SCLK_CHIPID, "sclk_chipid", "oscclk_efuse_common",
|
||||
ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0),
|
||||
ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, CLK_IGNORE_UNUSED, 0),
|
||||
|
||||
/* ENABLE_SCLK_PERIS_SECURE_TOPRTC */
|
||||
GATE(CLK_SCLK_TOPRTC, "sclk_toprtc", "oscclk_efuse_common",
|
||||
@ -3286,10 +3287,10 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
|
||||
|
||||
static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
|
||||
/* MUX_SEL_G3D */
|
||||
MUX(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
|
||||
MUX_SEL_G3D, 8, 1),
|
||||
MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
|
||||
MUX_SEL_G3D, 0, 1),
|
||||
MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
|
||||
MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0),
|
||||
MUX_F(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
|
||||
MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static struct samsung_div_clock g3d_div_clks[] __initdata = {
|
||||
@ -3298,8 +3299,8 @@ static struct samsung_div_clock g3d_div_clks[] __initdata = {
|
||||
8, 2),
|
||||
DIV(CLK_DIV_PCLK_G3D, "div_pclk_g3d", "div_aclk_g3d", DIV_G3D,
|
||||
4, 3),
|
||||
DIV(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
|
||||
0, 3),
|
||||
DIV_F(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
|
||||
0, 3, CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
|
||||
@ -3309,9 +3310,9 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
|
||||
GATE(CLK_ACLK_BTS_G3D0, "aclk_bts_g3d0", "div_aclk_g3d",
|
||||
ENABLE_ACLK_G3D, 6, 0, 0),
|
||||
GATE(CLK_ACLK_ASYNCAPBS_G3D, "aclk_asyncapbs_g3d", "div_pclk_g3d",
|
||||
ENABLE_ACLK_G3D, 5, 0, 0),
|
||||
ENABLE_ACLK_G3D, 5, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_ACLK_ASYNCAPBM_G3D, "aclk_asyncapbm_g3d", "div_aclk_g3d",
|
||||
ENABLE_ACLK_G3D, 4, 0, 0),
|
||||
ENABLE_ACLK_G3D, 4, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_ACLK_AHB2APB_G3DP, "aclk_ahb2apb_g3dp", "div_pclk_g3d",
|
||||
ENABLE_ACLK_G3D, 3, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_ACLK_G3DNP_150, "aclk_g3dnp_150", "div_pclk_g3d",
|
||||
@ -3319,7 +3320,7 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
|
||||
GATE(CLK_ACLK_G3DND_600, "aclk_g3dnd_600", "div_aclk_g3d",
|
||||
ENABLE_ACLK_G3D, 1, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_ACLK_G3D, "aclk_g3d", "div_aclk_g3d",
|
||||
ENABLE_ACLK_G3D, 0, 0, 0),
|
||||
ENABLE_ACLK_G3D, 0, CLK_SET_RATE_PARENT, 0),
|
||||
|
||||
/* ENABLE_PCLK_G3D */
|
||||
GATE(CLK_PCLK_BTS_G3D1, "pclk_bts_g3d1", "div_pclk_g3d",
|
||||
@ -3582,7 +3583,7 @@ static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
|
||||
static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
|
||||
/* MUX_SEL_APOLLO0 */
|
||||
MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
|
||||
MUX_SEL_APOLLO0, 0, 1, 0, CLK_MUX_READ_ONLY),
|
||||
MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
|
||||
|
||||
/* MUX_SEL_APOLLO1 */
|
||||
MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
|
||||
@ -3590,7 +3591,7 @@ static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
|
||||
|
||||
/* MUX_SEL_APOLLO2 */
|
||||
MUX_F(CLK_MOUT_APOLLO, "mout_apollo", mout_apollo_p, MUX_SEL_APOLLO2,
|
||||
0, 1, 0, CLK_MUX_READ_ONLY),
|
||||
0, 1, CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static struct samsung_div_clock apollo_div_clks[] __initdata = {
|
||||
@ -3611,11 +3612,9 @@ static struct samsung_div_clock apollo_div_clks[] __initdata = {
|
||||
DIV_APOLLO0, 8, 3, CLK_GET_RATE_NOCACHE,
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
DIV_F(CLK_DIV_APOLLO2, "div_apollo2", "div_apollo1",
|
||||
DIV_APOLLO0, 4, 3, CLK_GET_RATE_NOCACHE,
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
DIV_APOLLO0, 4, 3, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(CLK_DIV_APOLLO1, "div_apollo1", "mout_apollo",
|
||||
DIV_APOLLO0, 0, 3, CLK_GET_RATE_NOCACHE,
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
DIV_APOLLO0, 0, 3, CLK_SET_RATE_PARENT, 0),
|
||||
|
||||
/* DIV_APOLLO1 */
|
||||
DIV_F(CLK_DIV_SCLK_HPM_APOLLO, "div_sclk_hpm_apollo", "mout_apollo",
|
||||
@ -3666,7 +3665,8 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
|
||||
GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
|
||||
ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2",
|
||||
ENABLE_SCLK_APOLLO, 0, CLK_IGNORE_UNUSED, 0),
|
||||
ENABLE_SCLK_APOLLO, 0,
|
||||
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static struct samsung_cmu_info apollo_cmu_info __initdata = {
|
||||
@ -3775,7 +3775,7 @@ static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
|
||||
static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
|
||||
/* MUX_SEL_ATLAS0 */
|
||||
MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
|
||||
MUX_SEL_ATLAS0, 0, 1, 0, CLK_MUX_READ_ONLY),
|
||||
MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
|
||||
|
||||
/* MUX_SEL_ATLAS1 */
|
||||
MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
|
||||
@ -3783,7 +3783,7 @@ static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
|
||||
|
||||
/* MUX_SEL_ATLAS2 */
|
||||
MUX_F(CLK_MOUT_ATLAS, "mout_atlas", mout_atlas_p, MUX_SEL_ATLAS2,
|
||||
0, 1, 0, CLK_MUX_READ_ONLY),
|
||||
0, 1, CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static struct samsung_div_clock atlas_div_clks[] __initdata = {
|
||||
@ -3804,11 +3804,9 @@ static struct samsung_div_clock atlas_div_clks[] __initdata = {
|
||||
DIV_ATLAS0, 8, 3, CLK_GET_RATE_NOCACHE,
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
DIV_F(CLK_DIV_ATLAS2, "div_atlas2", "div_atlas1",
|
||||
DIV_ATLAS0, 4, 3, CLK_GET_RATE_NOCACHE,
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
DIV_ATLAS0, 4, 3, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(CLK_DIV_ATLAS1, "div_atlas1", "mout_atlas",
|
||||
DIV_ATLAS0, 0, 3, CLK_GET_RATE_NOCACHE,
|
||||
CLK_DIVIDER_READ_ONLY),
|
||||
DIV_ATLAS0, 0, 3, CLK_SET_RATE_PARENT, 0),
|
||||
|
||||
/* DIV_ATLAS1 */
|
||||
DIV_F(CLK_DIV_SCLK_HPM_ATLAS, "div_sclk_hpm_atlas", "mout_atlas",
|
||||
@ -3885,7 +3883,8 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
|
||||
GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
|
||||
ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
|
||||
ENABLE_SCLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
|
||||
ENABLE_SCLK_ATLAS, 0,
|
||||
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static struct samsung_cmu_info atlas_cmu_info __initdata = {
|
||||
|
@ -1156,7 +1156,7 @@ static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
|
||||
};
|
||||
|
||||
static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
||||
struct samsung_pll_clock *pll_clk,
|
||||
const struct samsung_pll_clock *pll_clk,
|
||||
void __iomem *base)
|
||||
{
|
||||
struct samsung_clk_pll *pll;
|
||||
@ -1303,7 +1303,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
||||
}
|
||||
|
||||
void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
||||
struct samsung_pll_clock *pll_list,
|
||||
const struct samsung_pll_clock *pll_list,
|
||||
unsigned int nr_pll, void __iomem *base)
|
||||
{
|
||||
int cnt;
|
||||
|
@ -81,13 +81,13 @@ static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct clk_ops s3c24xx_clkout_ops = {
|
||||
static const struct clk_ops s3c24xx_clkout_ops = {
|
||||
.get_parent = s3c24xx_clkout_get_parent,
|
||||
.set_parent = s3c24xx_clkout_set_parent,
|
||||
.determine_rate = __clk_mux_determine_rate,
|
||||
};
|
||||
|
||||
struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
|
||||
static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
u8 shift, u32 mask)
|
||||
{
|
||||
@ -404,7 +404,7 @@ static struct s3c24xx_dclk_drv_data dclk_variants[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
|
||||
static const struct platform_device_id s3c24xx_dclk_driver_ids[] = {
|
||||
{
|
||||
.name = "s3c2410-dclk",
|
||||
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2410],
|
||||
|
@ -169,44 +169,44 @@ static inline void s5pv210_clk_sleep_init(void) { }
|
||||
#endif
|
||||
|
||||
/* Mux parent lists. */
|
||||
static const char *fin_pll_p[] __initdata = {
|
||||
static const char *const fin_pll_p[] __initconst = {
|
||||
"xxti",
|
||||
"xusbxti"
|
||||
};
|
||||
|
||||
static const char *mout_apll_p[] __initdata = {
|
||||
static const char *const mout_apll_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"fout_apll"
|
||||
};
|
||||
|
||||
static const char *mout_mpll_p[] __initdata = {
|
||||
static const char *const mout_mpll_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"fout_mpll"
|
||||
};
|
||||
|
||||
static const char *mout_epll_p[] __initdata = {
|
||||
static const char *const mout_epll_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"fout_epll"
|
||||
};
|
||||
|
||||
static const char *mout_vpllsrc_p[] __initdata = {
|
||||
static const char *const mout_vpllsrc_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"sclk_hdmi27m"
|
||||
};
|
||||
|
||||
static const char *mout_vpll_p[] __initdata = {
|
||||
static const char *const mout_vpll_p[] __initconst = {
|
||||
"mout_vpllsrc",
|
||||
"fout_vpll"
|
||||
};
|
||||
|
||||
static const char *mout_group1_p[] __initdata = {
|
||||
static const char *const mout_group1_p[] __initconst = {
|
||||
"dout_a2m",
|
||||
"mout_mpll",
|
||||
"mout_epll",
|
||||
"mout_vpll"
|
||||
};
|
||||
|
||||
static const char *mout_group2_p[] __initdata = {
|
||||
static const char *const mout_group2_p[] __initconst = {
|
||||
"xxti",
|
||||
"xusbxti",
|
||||
"sclk_hdmi27m",
|
||||
@ -218,7 +218,7 @@ static const char *mout_group2_p[] __initdata = {
|
||||
"mout_vpll",
|
||||
};
|
||||
|
||||
static const char *mout_audio0_p[] __initdata = {
|
||||
static const char *const mout_audio0_p[] __initconst = {
|
||||
"xxti",
|
||||
"pcmcdclk0",
|
||||
"sclk_hdmi27m",
|
||||
@ -230,7 +230,7 @@ static const char *mout_audio0_p[] __initdata = {
|
||||
"mout_vpll",
|
||||
};
|
||||
|
||||
static const char *mout_audio1_p[] __initdata = {
|
||||
static const char *const mout_audio1_p[] __initconst = {
|
||||
"i2scdclk1",
|
||||
"pcmcdclk1",
|
||||
"sclk_hdmi27m",
|
||||
@ -242,7 +242,7 @@ static const char *mout_audio1_p[] __initdata = {
|
||||
"mout_vpll",
|
||||
};
|
||||
|
||||
static const char *mout_audio2_p[] __initdata = {
|
||||
static const char *const mout_audio2_p[] __initconst = {
|
||||
"i2scdclk2",
|
||||
"pcmcdclk2",
|
||||
"sclk_hdmi27m",
|
||||
@ -254,63 +254,63 @@ static const char *mout_audio2_p[] __initdata = {
|
||||
"mout_vpll",
|
||||
};
|
||||
|
||||
static const char *mout_spdif_p[] __initdata = {
|
||||
static const char *const mout_spdif_p[] __initconst = {
|
||||
"dout_audio0",
|
||||
"dout_audio1",
|
||||
"dout_audio3",
|
||||
};
|
||||
|
||||
static const char *mout_group3_p[] __initdata = {
|
||||
static const char *const mout_group3_p[] __initconst = {
|
||||
"mout_apll",
|
||||
"mout_mpll"
|
||||
};
|
||||
|
||||
static const char *mout_group4_p[] __initdata = {
|
||||
static const char *const mout_group4_p[] __initconst = {
|
||||
"mout_mpll",
|
||||
"dout_a2m"
|
||||
};
|
||||
|
||||
static const char *mout_flash_p[] __initdata = {
|
||||
static const char *const mout_flash_p[] __initconst = {
|
||||
"dout_hclkd",
|
||||
"dout_hclkp"
|
||||
};
|
||||
|
||||
static const char *mout_dac_p[] __initdata = {
|
||||
static const char *const mout_dac_p[] __initconst = {
|
||||
"mout_vpll",
|
||||
"sclk_hdmiphy"
|
||||
};
|
||||
|
||||
static const char *mout_hdmi_p[] __initdata = {
|
||||
static const char *const mout_hdmi_p[] __initconst = {
|
||||
"sclk_hdmiphy",
|
||||
"dout_tblk"
|
||||
};
|
||||
|
||||
static const char *mout_mixer_p[] __initdata = {
|
||||
static const char *const mout_mixer_p[] __initconst = {
|
||||
"mout_dac",
|
||||
"mout_hdmi"
|
||||
};
|
||||
|
||||
static const char *mout_vpll_6442_p[] __initdata = {
|
||||
static const char *const mout_vpll_6442_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"fout_vpll"
|
||||
};
|
||||
|
||||
static const char *mout_mixer_6442_p[] __initdata = {
|
||||
static const char *const mout_mixer_6442_p[] __initconst = {
|
||||
"mout_vpll",
|
||||
"dout_mixer"
|
||||
};
|
||||
|
||||
static const char *mout_d0sync_6442_p[] __initdata = {
|
||||
static const char *const mout_d0sync_6442_p[] __initconst = {
|
||||
"mout_dsys",
|
||||
"div_apll"
|
||||
};
|
||||
|
||||
static const char *mout_d1sync_6442_p[] __initdata = {
|
||||
static const char *const mout_d1sync_6442_p[] __initconst = {
|
||||
"mout_psys",
|
||||
"div_apll"
|
||||
};
|
||||
|
||||
static const char *mout_group2_6442_p[] __initdata = {
|
||||
static const char *const mout_group2_6442_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"none",
|
||||
"none",
|
||||
@ -322,7 +322,7 @@ static const char *mout_group2_6442_p[] __initdata = {
|
||||
"mout_vpll",
|
||||
};
|
||||
|
||||
static const char *mout_audio0_6442_p[] __initdata = {
|
||||
static const char *const mout_audio0_6442_p[] __initconst = {
|
||||
"fin_pll",
|
||||
"pcmcdclk0",
|
||||
"none",
|
||||
@ -334,7 +334,7 @@ static const char *mout_audio0_6442_p[] __initdata = {
|
||||
"mout_vpll",
|
||||
};
|
||||
|
||||
static const char *mout_audio1_6442_p[] __initdata = {
|
||||
static const char *const mout_audio1_6442_p[] __initconst = {
|
||||
"i2scdclk1",
|
||||
"pcmcdclk1",
|
||||
"none",
|
||||
@ -347,7 +347,7 @@ static const char *mout_audio1_6442_p[] __initdata = {
|
||||
"fin_pll",
|
||||
};
|
||||
|
||||
static const char *mout_clksel_p[] __initdata = {
|
||||
static const char *const mout_clksel_p[] __initconst = {
|
||||
"fout_apll_clkout",
|
||||
"fout_mpll_clkout",
|
||||
"fout_epll",
|
||||
@ -370,7 +370,7 @@ static const char *mout_clksel_p[] __initdata = {
|
||||
"div_dclk"
|
||||
};
|
||||
|
||||
static const char *mout_clksel_6442_p[] __initdata = {
|
||||
static const char *const mout_clksel_6442_p[] __initconst = {
|
||||
"fout_apll_clkout",
|
||||
"fout_mpll_clkout",
|
||||
"fout_epll",
|
||||
@ -393,7 +393,7 @@ static const char *mout_clksel_6442_p[] __initdata = {
|
||||
"div_dclk"
|
||||
};
|
||||
|
||||
static const char *mout_clkout_p[] __initdata = {
|
||||
static const char *const mout_clkout_p[] __initconst = {
|
||||
"dout_clkout",
|
||||
"none",
|
||||
"xxti",
|
||||
@ -401,20 +401,20 @@ static const char *mout_clkout_p[] __initdata = {
|
||||
};
|
||||
|
||||
/* Common fixed factor clocks. */
|
||||
static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
|
||||
static const struct samsung_fixed_factor_clock ffactor_clks[] __initconst = {
|
||||
FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
|
||||
FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
|
||||
FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
|
||||
};
|
||||
|
||||
/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
|
||||
static struct samsung_mux_clock early_mux_clks[] __initdata = {
|
||||
static const struct samsung_mux_clock early_mux_clks[] __initconst = {
|
||||
MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
|
||||
CLK_MUX_READ_ONLY, 0),
|
||||
};
|
||||
|
||||
/* Common clock muxes. */
|
||||
static struct samsung_mux_clock mux_clks[] __initdata = {
|
||||
static const struct samsung_mux_clock mux_clks[] __initconst = {
|
||||
MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
|
||||
MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
|
||||
MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
|
||||
@ -427,7 +427,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5PV210-specific clock muxes. */
|
||||
static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
|
||||
static const struct samsung_mux_clock s5pv210_mux_clks[] __initconst = {
|
||||
MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
|
||||
|
||||
MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
|
||||
@ -472,7 +472,7 @@ static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5P6442-specific clock muxes. */
|
||||
static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
|
||||
static const struct samsung_mux_clock s5p6442_mux_clks[] __initconst = {
|
||||
MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
|
||||
|
||||
MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
|
||||
@ -504,7 +504,7 @@ static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5PV210-specific fixed rate clocks generated inside the SoC. */
|
||||
static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
|
||||
static const struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initconst = {
|
||||
FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
|
||||
FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
|
||||
FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
|
||||
@ -512,12 +512,12 @@ static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5P6442-specific fixed rate clocks generated inside the SoC. */
|
||||
static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
|
||||
static const struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initconst = {
|
||||
FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
|
||||
};
|
||||
|
||||
/* Common clock dividers. */
|
||||
static struct samsung_div_clock div_clks[] __initdata = {
|
||||
static const struct samsung_div_clock div_clks[] __initconst = {
|
||||
DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
|
||||
DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
|
||||
DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
|
||||
@ -549,7 +549,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5PV210-specific clock dividers. */
|
||||
static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
|
||||
static const struct samsung_div_clock s5pv210_div_clks[] __initconst = {
|
||||
DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
|
||||
DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
|
||||
DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
|
||||
@ -578,7 +578,7 @@ static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5P6442-specific clock dividers. */
|
||||
static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
|
||||
static const struct samsung_div_clock s5p6442_div_clks[] __initconst = {
|
||||
DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
|
||||
DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
|
||||
|
||||
@ -586,7 +586,7 @@ static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* Common clock gates. */
|
||||
static struct samsung_gate_clock gate_clks[] __initdata = {
|
||||
static const struct samsung_gate_clock gate_clks[] __initconst = {
|
||||
GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
|
||||
GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
|
||||
GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
|
||||
@ -666,7 +666,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5PV210-specific clock gates. */
|
||||
static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
|
||||
static const struct samsung_gate_clock s5pv210_gate_clks[] __initconst = {
|
||||
GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
|
||||
GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
|
||||
GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
|
||||
@ -728,7 +728,7 @@ static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5P6442-specific clock gates. */
|
||||
static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
|
||||
static const struct samsung_gate_clock s5p6442_gate_clks[] __initconst = {
|
||||
GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
|
||||
GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
|
||||
GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
|
||||
@ -748,14 +748,14 @@ static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
|
||||
* Clock aliases for legacy clkdev look-up.
|
||||
* NOTE: Needed only to support legacy board files.
|
||||
*/
|
||||
static struct samsung_clock_alias s5pv210_aliases[] = {
|
||||
static const struct samsung_clock_alias s5pv210_aliases[] __initconst = {
|
||||
ALIAS(DOUT_APLL, NULL, "armclk"),
|
||||
ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
|
||||
ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
|
||||
};
|
||||
|
||||
/* S5PV210-specific PLLs. */
|
||||
static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
|
||||
static const struct samsung_pll_clock s5pv210_pll_clks[] __initconst = {
|
||||
[apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
|
||||
APLL_LOCK, APLL_CON0, NULL),
|
||||
[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
|
||||
@ -767,7 +767,7 @@ static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
|
||||
};
|
||||
|
||||
/* S5P6442-specific PLLs. */
|
||||
static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
|
||||
static const struct samsung_pll_clock s5p6442_pll_clks[] __initconst = {
|
||||
[apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
|
||||
APLL_LOCK, APLL_CON0, NULL),
|
||||
[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
|
||||
|
@ -98,7 +98,7 @@ void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
|
||||
|
||||
/* register a list of aliases */
|
||||
void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
||||
struct samsung_clock_alias *list,
|
||||
const struct samsung_clock_alias *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -132,7 +132,8 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
||||
|
||||
/* register a list of fixed clocks */
|
||||
void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
|
||||
struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
|
||||
const struct samsung_fixed_rate_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx, ret;
|
||||
@ -161,7 +162,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
|
||||
|
||||
/* register a list of fixed factor clocks */
|
||||
void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
|
||||
struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
|
||||
const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx;
|
||||
@ -181,7 +182,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
|
||||
|
||||
/* register a list of mux clocks */
|
||||
void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
|
||||
struct samsung_mux_clock *list,
|
||||
const struct samsung_mux_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -213,7 +214,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
|
||||
|
||||
/* register a list of div clocks */
|
||||
void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
|
||||
struct samsung_div_clock *list,
|
||||
const struct samsung_div_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -252,7 +253,7 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
|
||||
|
||||
/* register a list of gate clocks */
|
||||
void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
|
||||
struct samsung_gate_clock *list,
|
||||
const struct samsung_gate_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -389,7 +390,7 @@ struct samsung_clk_provider * __init samsung_cmu_register_one(
|
||||
|
||||
ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
|
||||
if (!ctx) {
|
||||
panic("%s: unable to alllocate ctx\n", __func__);
|
||||
panic("%s: unable to allocate ctx\n", __func__);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ struct samsung_mux_clock {
|
||||
unsigned int id;
|
||||
const char *dev_name;
|
||||
const char *name;
|
||||
const char **parent_names;
|
||||
const char *const *parent_names;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
@ -368,28 +368,28 @@ extern void __init samsung_clk_of_register_fixed_ext(
|
||||
extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
|
||||
struct clk *clk, unsigned int id);
|
||||
|
||||
extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
||||
struct samsung_clock_alias *list,
|
||||
extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
||||
const struct samsung_clock_alias *list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_fixed_rate(
|
||||
struct samsung_clk_provider *ctx,
|
||||
struct samsung_fixed_rate_clock *clk_list,
|
||||
const struct samsung_fixed_rate_clock *clk_list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_fixed_factor(
|
||||
struct samsung_clk_provider *ctx,
|
||||
struct samsung_fixed_factor_clock *list,
|
||||
const struct samsung_fixed_factor_clock *list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
|
||||
struct samsung_mux_clock *clk_list,
|
||||
const struct samsung_mux_clock *clk_list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
|
||||
struct samsung_div_clock *clk_list,
|
||||
const struct samsung_div_clock *clk_list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
|
||||
struct samsung_gate_clock *clk_list,
|
||||
const struct samsung_gate_clock *clk_list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
||||
struct samsung_pll_clock *pll_list,
|
||||
const struct samsung_pll_clock *pll_list,
|
||||
unsigned int nr_clk, void __iomem *base);
|
||||
|
||||
extern struct samsung_clk_provider __init *samsung_cmu_register_one(
|
||||
|
@ -34,7 +34,7 @@
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
|
||||
/* not pretty, but hey */
|
||||
void __iomem *smu_base;
|
||||
static void __iomem *smu_base;
|
||||
|
||||
static void __init emev2_smu_write(unsigned long value, int offs)
|
||||
{
|
||||
|
@ -2,4 +2,4 @@
|
||||
# Makefile for sirf specific clk
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o
|
||||
obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o clk-atlas7.o
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user