Sort of on the quieter side this time, which is probably due more
to me not catching up as quickly on patch review than anything else. Overall it seems normal though, a few small changes to the core, mostly small non-critical fixes here and there as well as driver updates for new and existing hardware support. The biggest things are the TI clk driver rework to lay the groundwork for clkctrl support in the next merge window and the AmLogic audio/graphics clk support. Core: * clk_possible_parents debugfs file so we know which parents a clk could possibly have * Fix to make clk rate change notifiers stop on the first failure instead of continuing New Drivers: * Mediatek MT6797 SoCs * hi655x PMIC clks * AmLogic Meson SoC i2s and spdif audio clks and Mali graphics clks * Allwinner H5 SoCs and PRCM hardware Updates: * Nvidia Tegra T210 cleanups and non-critical fixes * TI OMAP cleanups in preparation for clkctrl support * Trivial fixes like kcalloc(), devm_* conversions, and seq_puts() * ZTE zx296718 SoC VGA clks * Rockchip clk-ids, fixups, and rename of rk1108 to rv1108 * Support for IDT VersaClock 5P49V5935 * Renesas R-Car H3 and M3-W IMR clks and ES2.0 rev of R-Car H3 support -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJZE0YJAAoJEK0CiJfG5JUl9tEQAKVJx8VztYGt1REoFMtEEHmO azhxT/uYGgdOMAr9a3mQxqfm5cJbjnb1EZj2RfC1XHs31BF66j40y9+5d8hY8Hzu 5IkY86s77TlqxGLwQcAsU75Q9cFrEW9X0KJ6OSzlrcc5hKlAEk/Z5lBKoQAm3mlU JqD4DSyFqP0X3YSxV5R7yfarb/X3ekCiQ13EDrPRRhyvHUi6ReUJDDgbPHtA+O2c ftLAARmxjzitzyvdXokXudkfNm8F5KePK+QkVikf6D/q+kx1D0BNJwZIjhpoiksn z6LImLQ8l91AWghmqqpOFXolxQncPU+bJIL9Pox76p5b3EzbQuthIafiso8KsDST 4g3mHm42Yfx9uoF+U+pR8IeZfj5yQT91bvf8naPz/ngWMAlLP1IKJUvJN6jeTiwe cO6GIec1OH40Xl7v/9EafMwDcnFG0cwQmzr/M6wi1dUlmbSygP9NOMTHlr6W/0wa K2hCD6b5UHEgHmdfiJbZ2tKxLO0e8LABW+AU8fQH5S2eNe14vY0GvCzfAq5MArIz QRpso/kdtGpTpwMEvV6PUmJ0IxYEjtNJVjGJYbORwios0SK0Xl6bJWf7gwn5crB6 nua9tVZtJEOHJS7S+ESp3VvuXj2/UGPoRRf5OsERo1S6ydGUQH+wDi1SJMdo/vtX bIPzIw6WPxMp24JyKOhh =/5a/ -----END PGP SIGNATURE----- Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux Pull clk updates from Stephen Boyd: "Sort of on the quieter side this time, which is probably due more to me not catching up as quickly on patch review than anything else. Overall it seems normal though, a few small changes to the core, mostly small non-critical fixes here and there as well as driver updates for new and existing hardware support. The biggest things are the TI clk driver rework to lay the groundwork for clkctrl support in the next merge window and the AmLogic audio/graphics clk support. Core: - clk_possible_parents debugfs file so we know which parents a clk could possibly have - Fix to make clk rate change notifiers stop on the first failure instead of continuing New Drivers: - Mediatek MT6797 SoCs - hi655x PMIC clks - AmLogic Meson SoC i2s and spdif audio clks and Mali graphics clks - Allwinner H5 SoCs and PRCM hardware Updates: - Nvidia Tegra T210 cleanups and non-critical fixes - TI OMAP cleanups in preparation for clkctrl support - trivial fixes like kcalloc(), devm_* conversions, and seq_puts() - ZTE zx296718 SoC VGA clks - Rockchip clk-ids, fixups, and rename of rk1108 to rv1108 - IDT VersaClock 5P49V5935 support - Renesas R-Car H3 and M3-W IMR clks and ES2.0 rev of R-Car H3 support" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (151 commits) clk: x86: pmc-atom: Checking for IS_ERR() instead of NULL clk: ti: divider: try to fix ti_clk_register_divider clk: mvebu: Use kcalloc() in two functions clk: mvebu: Use kcalloc() in of_cpu_clk_setup() clk: nomadik: Delete error messages for a failed memory allocation in two functions clk: nomadik: Use seq_puts() in nomadik_src_clk_show() clk: Improve a size determination in two functions clk: Replace four seq_printf() calls by seq_putc() clk: si5351: Delete an error message for a failed memory allocation in si5351_i2c_probe() clk: si5351: Use devm_kcalloc() in si5351_i2c_probe() clk: at91: Use kcalloc() in of_at91_clk_pll_get_characteristics() reset: mediatek: Add MT2701 ethsys reset controller include file clk: mediatek: add mt2701 ethernet reset clk: hi6220: Add the hi655x's pmic clock clk: ti: fix building without legacy omap3 clk: ti: fix linker error with !SOC_OMAP4 clk: hi3620: Fix a typo in one variable name clk: hi3620: Delete error messages for a failed memory allocation in two functions clk: hi3620: Use kcalloc() in hi3620_mmc_clk_init() clk: hisilicon: Delete error messages for failed memory allocations in hisi_clk_init() ...
This commit is contained in:
commit
b5a53b61a2
|
@ -7,6 +7,7 @@ Required Properties:
|
|||
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-apmixedsys"
|
||||
- "mediatek,mt6797-apmixedsys"
|
||||
- "mediatek,mt8135-apmixedsys"
|
||||
- "mediatek,mt8173-apmixedsys"
|
||||
- #clock-cells: Must be 1
|
||||
|
|
|
@ -7,6 +7,7 @@ Required Properties:
|
|||
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-imgsys", "syscon"
|
||||
- "mediatek,mt6797-imgsys", "syscon"
|
||||
- "mediatek,mt8173-imgsys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ Required Properties:
|
|||
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-infracfg", "syscon"
|
||||
- "mediatek,mt6797-infracfg", "syscon"
|
||||
- "mediatek,mt8135-infracfg", "syscon"
|
||||
- "mediatek,mt8173-infracfg", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
|
|
@ -7,6 +7,7 @@ Required Properties:
|
|||
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-mmsys", "syscon"
|
||||
- "mediatek,mt6797-mmsys", "syscon"
|
||||
- "mediatek,mt8173-mmsys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ Required Properties:
|
|||
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-topckgen"
|
||||
- "mediatek,mt6797-topckgen"
|
||||
- "mediatek,mt8135-topckgen"
|
||||
- "mediatek,mt8173-topckgen"
|
||||
- #clock-cells: Must be 1
|
||||
|
|
|
@ -7,6 +7,7 @@ Required Properties:
|
|||
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-vdecsys", "syscon"
|
||||
- "mediatek,mt6797-vdecsys", "syscon"
|
||||
- "mediatek,mt8173-vdecsys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ The Mediatek vencsys controller provides various clocks to the system.
|
|||
|
||||
Required Properties:
|
||||
|
||||
- compatible: Should be:
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt6797-vencsys", "syscon"
|
||||
- "mediatek,mt8173-vencsys", "syscon"
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
|
|
|
@ -6,18 +6,21 @@ from 3 to 12 output clocks.
|
|||
==I2C device node==
|
||||
|
||||
Required properties:
|
||||
- compatible: shall be one of "idt,5p49v5923" , "idt,5p49v5933".
|
||||
- compatible: shall be one of "idt,5p49v5923" , "idt,5p49v5933" ,
|
||||
"idt,5p49v5935".
|
||||
- reg: i2c device address, shall be 0x68 or 0x6a.
|
||||
- #clock-cells: from common clock binding; shall be set to 1.
|
||||
- clocks: from common clock binding; list of parent clock handles,
|
||||
- 5p49v5923: (required) either or both of XTAL or CLKIN
|
||||
reference clock.
|
||||
- 5p49v5933: (optional) property not present (internal
|
||||
- 5p49v5933 and
|
||||
- 5p49v5935: (optional) property not present (internal
|
||||
Xtal used) or CLKIN reference
|
||||
clock.
|
||||
- clock-names: from common clock binding; clock input names, can be
|
||||
- 5p49v5923: (required) either or both of "xin", "clkin".
|
||||
- 5p49v5933: (optional) property not present or "clkin".
|
||||
- 5p49v5933 and
|
||||
- 5p49v5935: (optional) property not present or "clkin".
|
||||
|
||||
==Mapping between clock specifier and physical pins==
|
||||
|
||||
|
@ -34,6 +37,13 @@ clock specifier, the following mapping applies:
|
|||
1 -- OUT1
|
||||
2 -- OUT4
|
||||
|
||||
5P49V5935:
|
||||
0 -- OUT0_SEL_I2CB
|
||||
1 -- OUT1
|
||||
2 -- OUT2
|
||||
3 -- OUT3
|
||||
4 -- OUT4
|
||||
|
||||
==Example==
|
||||
|
||||
/* 25MHz reference crystal */
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
* Rockchip RK1108 Clock and Reset Unit
|
||||
* Rockchip RV1108 Clock and Reset Unit
|
||||
|
||||
The RK1108 clock controller generates and supplies clock to various
|
||||
The RV1108 clock controller generates and supplies clock to various
|
||||
controllers within the SoC and also implements a reset controller for SoC
|
||||
peripherals.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "rockchip,rk1108-cru"
|
||||
- compatible: should be "rockchip,rv1108-cru"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
|
@ -19,7 +19,7 @@ Optional Properties:
|
|||
|
||||
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/rk1108-cru.h headers and can be
|
||||
preprocessor macros in the dt-bindings/clock/rv1108-cru.h headers and can be
|
||||
used in device tree sources. Similar macros exist for the reset sources in
|
||||
these files.
|
||||
|
||||
|
@ -38,7 +38,7 @@ clock-output-names:
|
|||
Example: Clock controller node:
|
||||
|
||||
cru: cru@20200000 {
|
||||
compatible = "rockchip,rk1108-cru";
|
||||
compatible = "rockchip,rv1108-cru";
|
||||
reg = <0x20200000 0x1000>;
|
||||
rockchip,grf = <&grf>;
|
||||
|
||||
|
@ -50,7 +50,7 @@ Example: UART controller node that consumes the clock generated by the clock
|
|||
controller:
|
||||
|
||||
uart0: serial@10230000 {
|
||||
compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
|
||||
compatible = "rockchip,rv1108-uart", "snps,dw-apb-uart";
|
||||
reg = <0x10230000 0x100>;
|
||||
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg-shift = <2>;
|
|
@ -7,9 +7,12 @@ Required properties :
|
|||
- "allwinner,sun8i-a23-ccu"
|
||||
- "allwinner,sun8i-a33-ccu"
|
||||
- "allwinner,sun8i-h3-ccu"
|
||||
- "allwinner,sun8i-h3-r-ccu"
|
||||
- "allwinner,sun8i-v3s-ccu"
|
||||
- "allwinner,sun9i-a80-ccu"
|
||||
- "allwinner,sun50i-a64-ccu"
|
||||
- "allwinner,sun50i-a64-r-ccu"
|
||||
- "allwinner,sun50i-h5-ccu"
|
||||
|
||||
- reg: Must contain the registers base address and length
|
||||
- clocks: phandle to the oscillators feeding the CCU. Two are needed:
|
||||
|
@ -19,7 +22,10 @@ Required properties :
|
|||
- #clock-cells : must contain 1
|
||||
- #reset-cells : must contain 1
|
||||
|
||||
Example:
|
||||
For the PRCM CCUs on H3/A64, one more clock is needed:
|
||||
- "iosc": the SoC's internal frequency oscillator
|
||||
|
||||
Example for generic CCU:
|
||||
ccu: clock@01c20000 {
|
||||
compatible = "allwinner,sun8i-h3-ccu";
|
||||
reg = <0x01c20000 0x400>;
|
||||
|
@ -28,3 +34,13 @@ ccu: clock@01c20000 {
|
|||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Example for PRCM CCU:
|
||||
r_ccu: clock@01f01400 {
|
||||
compatible = "allwinner,sun50i-a64-r-ccu";
|
||||
reg = <0x01f01400 0x100>;
|
||||
clocks = <&osc24M>, <&osc32k>, <&iosc>;
|
||||
clock-names = "hosc", "losc", "iosc";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -1085,6 +1085,16 @@ F: drivers/pinctrl/meson/
|
|||
F: drivers/mmc/host/meson*
|
||||
N: meson
|
||||
|
||||
ARM/Amlogic Meson SoC CLOCK FRAMEWORK
|
||||
M: Neil Armstrong <narmstrong@baylibre.com>
|
||||
M: Jerome Brunet <jbrunet@baylibre.com>
|
||||
L: linux-amlogic@lists.infradead.org
|
||||
S: Maintained
|
||||
F: drivers/clk/meson/
|
||||
F: include/dt-bindings/clock/meson*
|
||||
F: include/dt-bindings/clock/gxbb*
|
||||
F: Documentation/devicetree/bindings/clock/amlogic*
|
||||
|
||||
ARM/Annapurna Labs ALPINE ARCHITECTURE
|
||||
M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
|
||||
M: Antoine Tenart <antoine.tenart@free-electrons.com>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/rk1108-cru.h>
|
||||
#include <dt-bindings/clock/rv1108-cru.h>
|
||||
#include <dt-bindings/pinctrl/rockchip.h>
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
|
|
|
@ -138,7 +138,8 @@ int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate,
|
|||
if (!dd)
|
||||
return -EINVAL;
|
||||
|
||||
tmpset.cm_clksel1_pll = readl_relaxed(dd->mult_div1_reg);
|
||||
tmpset.cm_clksel1_pll =
|
||||
omap_clk_ll_ops.clk_readl(&dd->mult_div1_reg);
|
||||
tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
|
||||
dd->div1_mask);
|
||||
div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
|
||||
|
|
|
@ -54,9 +54,10 @@ u16 cpu_mask;
|
|||
#define OMAP3PLUS_DPLL_FINT_MIN 32000
|
||||
#define OMAP3PLUS_DPLL_FINT_MAX 52000000
|
||||
|
||||
static struct ti_clk_ll_ops omap_clk_ll_ops = {
|
||||
struct ti_clk_ll_ops omap_clk_ll_ops = {
|
||||
.clkdm_clk_enable = clkdm_clk_enable,
|
||||
.clkdm_clk_disable = clkdm_clk_disable,
|
||||
.clkdm_lookup = clkdm_lookup,
|
||||
.cm_wait_module_ready = omap_cm_wait_module_ready,
|
||||
.cm_split_idlest_reg = cm_split_idlest_reg,
|
||||
};
|
||||
|
@ -78,38 +79,6 @@ int __init omap2_clk_setup_ll_ops(void)
|
|||
* OMAP2+ specific clock functions
|
||||
*/
|
||||
|
||||
/* Public functions */
|
||||
|
||||
/**
|
||||
* omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
|
||||
* @clk: OMAP clock struct ptr to use
|
||||
*
|
||||
* Convert a clockdomain name stored in a struct clk 'clk' into a
|
||||
* clockdomain pointer, and save it into the struct clk. Intended to be
|
||||
* called during clk_register(). No return value.
|
||||
*/
|
||||
void omap2_init_clk_clkdm(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||
struct clockdomain *clkdm;
|
||||
const char *clk_name;
|
||||
|
||||
if (!clk->clkdm_name)
|
||||
return;
|
||||
|
||||
clk_name = __clk_get_name(hw->clk);
|
||||
|
||||
clkdm = clkdm_lookup(clk->clkdm_name);
|
||||
if (clkdm) {
|
||||
pr_debug("clock: associated clk %s to clkdm %s\n",
|
||||
clk_name, clk->clkdm_name);
|
||||
clk->clkdm = clkdm;
|
||||
} else {
|
||||
pr_debug("clock: could not associate clk %s to clkdm %s\n",
|
||||
clk_name, clk->clkdm_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_clk_init_features - init clock features struct for the SoC
|
||||
*
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6
|
||||
#define OMAP4XXX_EN_DPLL_LOCKED 0x7
|
||||
|
||||
extern struct ti_clk_ll_ops omap_clk_ll_ops;
|
||||
|
||||
extern u16 cpu_mask;
|
||||
|
||||
extern const struct clkops clkops_omap2_dflt_wait;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define MAX_MODULE_READY_TIME 2000
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
#include <linux/clk/ti.h>
|
||||
extern void __iomem *cm_base;
|
||||
extern void __iomem *cm2_base;
|
||||
extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
|
||||
|
@ -50,7 +51,7 @@ extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
|
|||
* @module_disable: ptr to the SoC CM-specific module_disable impl
|
||||
*/
|
||||
struct cm_ll_data {
|
||||
int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
|
||||
int (*split_idlest_reg)(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
|
||||
u8 *idlest_reg_id);
|
||||
int (*wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
|
||||
u8 idlest_shift);
|
||||
|
@ -60,7 +61,7 @@ struct cm_ll_data {
|
|||
void (*module_disable)(u8 part, u16 inst, u16 clkctrl_offs);
|
||||
};
|
||||
|
||||
extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
|
||||
extern int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
|
||||
u8 *idlest_reg_id);
|
||||
int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
|
||||
u8 idlest_shift);
|
||||
|
|
|
@ -204,7 +204,7 @@ void omap2xxx_cm_apll96_disable(void)
|
|||
* XXX This function is only needed until absolute register addresses are
|
||||
* removed from the OMAP struct clk records.
|
||||
*/
|
||||
static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
|
||||
static int omap2xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
|
||||
s16 *prcm_inst,
|
||||
u8 *idlest_reg_id)
|
||||
{
|
||||
|
@ -212,10 +212,7 @@ static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
|
|||
u8 idlest_offs;
|
||||
int i;
|
||||
|
||||
if (idlest_reg < cm_base || idlest_reg > (cm_base + 0x0fff))
|
||||
return -EINVAL;
|
||||
|
||||
idlest_offs = (unsigned long)idlest_reg & 0xff;
|
||||
idlest_offs = idlest_reg->offset & 0xff;
|
||||
for (i = 0; i < ARRAY_SIZE(omap2xxx_cm_idlest_offs); i++) {
|
||||
if (idlest_offs == omap2xxx_cm_idlest_offs[i]) {
|
||||
*idlest_reg_id = i + 1;
|
||||
|
@ -226,7 +223,7 @@ static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
|
|||
if (i == ARRAY_SIZE(omap2xxx_cm_idlest_offs))
|
||||
return -EINVAL;
|
||||
|
||||
offs = idlest_reg - cm_base;
|
||||
offs = idlest_reg->offset;
|
||||
offs &= 0xff00;
|
||||
*prcm_inst = offs;
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
|
|||
* XXX This function is only needed until absolute register addresses are
|
||||
* removed from the OMAP struct clk records.
|
||||
*/
|
||||
static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
|
||||
static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
|
||||
s16 *prcm_inst,
|
||||
u8 *idlest_reg_id)
|
||||
{
|
||||
|
@ -126,11 +126,7 @@ static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
|
|||
u8 idlest_offs;
|
||||
int i;
|
||||
|
||||
if (idlest_reg < (cm_base + OMAP3430_IVA2_MOD) ||
|
||||
idlest_reg > (cm_base + 0x1ffff))
|
||||
return -EINVAL;
|
||||
|
||||
idlest_offs = (unsigned long)idlest_reg & 0xff;
|
||||
idlest_offs = idlest_reg->offset & 0xff;
|
||||
for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
|
||||
if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
|
||||
*idlest_reg_id = i + 1;
|
||||
|
@ -141,7 +137,7 @@ static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
|
|||
if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
|
||||
return -EINVAL;
|
||||
|
||||
offs = idlest_reg - cm_base;
|
||||
offs = idlest_reg->offset;
|
||||
offs &= 0xff00;
|
||||
*prcm_inst = offs;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ void __init omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2)
|
|||
* or 0 upon success. XXX This function is only needed until absolute
|
||||
* register addresses are removed from the OMAP struct clk records.
|
||||
*/
|
||||
int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
|
||||
int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
|
||||
u8 *idlest_reg_id)
|
||||
{
|
||||
if (!cm_ll_data->split_idlest_reg) {
|
||||
|
|
|
@ -47,6 +47,14 @@ config COMMON_CLK_RK808
|
|||
clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
|
||||
by control register.
|
||||
|
||||
config COMMON_CLK_HI655X
|
||||
tristate "Clock driver for Hi655x"
|
||||
depends on MFD_HI655X_PMIC || COMPILE_TEST
|
||||
---help---
|
||||
This driver supports the hi655x PMIC clock. This
|
||||
multi-function device has one fixed-rate oscillator, clocked
|
||||
at 32KHz.
|
||||
|
||||
config COMMON_CLK_SCPI
|
||||
tristate "Clock driver controlled via SCPI interface"
|
||||
depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
|
||||
|
|
|
@ -36,6 +36,7 @@ obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
|
|||
obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
|
||||
obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
|
||||
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o
|
||||
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
||||
|
|
|
@ -399,18 +399,18 @@ of_at91_clk_pll_get_characteristics(struct device_node *np)
|
|||
if (!characteristics)
|
||||
return NULL;
|
||||
|
||||
output = kzalloc(sizeof(*output) * num_output, GFP_KERNEL);
|
||||
output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
|
||||
if (!output)
|
||||
goto out_free_characteristics;
|
||||
|
||||
if (num_cells > 2) {
|
||||
out = kzalloc(sizeof(*out) * num_output, GFP_KERNEL);
|
||||
out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
|
||||
if (!out)
|
||||
goto out_free_output;
|
||||
}
|
||||
|
||||
if (num_cells > 3) {
|
||||
icpll = kzalloc(sizeof(*icpll) * num_output, GFP_KERNEL);
|
||||
icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
|
||||
if (!icpll)
|
||||
goto out_free_output;
|
||||
}
|
||||
|
|
|
@ -277,7 +277,7 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
|
|||
if (rate >= VCO_LOW && rate < VCO_HIGH) {
|
||||
ki = 4;
|
||||
kp_index = KP_BAND_MID;
|
||||
} else if (rate >= VCO_HIGH && rate && rate < VCO_HIGH_HIGH) {
|
||||
} else if (rate >= VCO_HIGH && rate < VCO_HIGH_HIGH) {
|
||||
ki = 3;
|
||||
kp_index = KP_BAND_HIGH;
|
||||
} else if (rate >= VCO_HIGH_HIGH && rate < VCO_MAX) {
|
||||
|
|
|
@ -103,7 +103,7 @@ CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
|
|||
|
||||
static const struct iproc_pll_ctrl genpll_sw = {
|
||||
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
|
||||
.aon = AON_VAL(0x0, 2, 9, 8),
|
||||
.aon = AON_VAL(0x0, 1, 11, 10),
|
||||
.reset = RESET_VAL(0x4, 2, 1),
|
||||
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
|
||||
.ndiv_int = REG_VAL(0x8, 4, 10),
|
||||
|
|
|
@ -36,15 +36,35 @@
|
|||
|
||||
/* DEVICE_CTRL */
|
||||
#define PLL_UNLOCK (1 << 7)
|
||||
#define AUXOUTDIS (1 << 1)
|
||||
#define CLKOUTDIS (1 << 0)
|
||||
|
||||
/* DEVICE_CFG1 */
|
||||
#define RSEL(x) (((x) & 0x3) << 3)
|
||||
#define RSEL_MASK RSEL(0x3)
|
||||
#define ENDEV1 (0x1)
|
||||
|
||||
/* DEVICE_CFG2 */
|
||||
#define AUTORMOD (1 << 3)
|
||||
#define LOCKCLK(x) (((x) & 0x3) << 1)
|
||||
#define LOCKCLK_MASK LOCKCLK(0x3)
|
||||
#define FRACNSRC_MASK (1 << 0)
|
||||
#define FRACNSRC_STATIC (0 << 0)
|
||||
#define FRACNSRC_DYNAMIC (1 << 1)
|
||||
|
||||
/* GLOBAL_CFG */
|
||||
#define ENDEV2 (0x1)
|
||||
|
||||
/* FUNC_CFG1 */
|
||||
#define CLKSKIPEN (1 << 7)
|
||||
#define REFCLKDIV(x) (((x) & 0x3) << 3)
|
||||
#define REFCLKDIV_MASK REFCLKDIV(0x3)
|
||||
|
||||
/* FUNC_CFG2 */
|
||||
#define LFRATIO_MASK (1 << 3)
|
||||
#define LFRATIO_20_12 (0 << 3)
|
||||
#define LFRATIO_12_20 (1 << 3)
|
||||
|
||||
#define CH_SIZE_ERR(ch) ((ch < 0) || (ch >= CH_MAX))
|
||||
#define hw_to_priv(_hw) container_of(_hw, struct cs2000_priv, hw)
|
||||
#define priv_to_client(priv) (priv->client)
|
||||
|
@ -110,6 +130,17 @@ static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_bset(priv, FUNC_CFG1, CLKSKIPEN,
|
||||
enable ? CLKSKIPEN : 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* FIXME: for Static ratio mode */
|
||||
ret = cs2000_bset(priv, FUNC_CFG2, LFRATIO_MASK,
|
||||
LFRATIO_12_20);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -127,7 +158,9 @@ static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv,
|
|||
else
|
||||
return -EINVAL;
|
||||
|
||||
return cs2000_bset(priv, FUNC_CFG1, 0x3 << 3, val << 3);
|
||||
return cs2000_bset(priv, FUNC_CFG1,
|
||||
REFCLKDIV_MASK,
|
||||
REFCLKDIV(val));
|
||||
}
|
||||
|
||||
static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
|
||||
|
@ -153,7 +186,10 @@ static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
|
|||
static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable)
|
||||
{
|
||||
/* enable both AUX_OUT, CLK_OUT */
|
||||
return cs2000_write(priv, DEVICE_CTRL, enable ? 0 : 0x3);
|
||||
return cs2000_bset(priv, DEVICE_CTRL,
|
||||
(AUXOUTDIS | CLKOUTDIS),
|
||||
enable ? 0 :
|
||||
(AUXOUTDIS | CLKOUTDIS));
|
||||
}
|
||||
|
||||
static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out)
|
||||
|
@ -243,7 +279,9 @@ static int cs2000_ratio_select(struct cs2000_priv *priv, int ch)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_write(priv, DEVICE_CFG2, 0x0);
|
||||
ret = cs2000_bset(priv, DEVICE_CFG2,
|
||||
(AUTORMOD | LOCKCLK_MASK | FRACNSRC_MASK),
|
||||
(LOCKCLK(ch) | FRACNSRC_STATIC));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -351,8 +389,7 @@ static const struct clk_ops cs2000_ops = {
|
|||
|
||||
static int cs2000_clk_get(struct cs2000_priv *priv)
|
||||
{
|
||||
struct i2c_client *client = priv_to_client(priv);
|
||||
struct device *dev = &client->dev;
|
||||
struct device *dev = priv_to_dev(priv);
|
||||
struct clk *clk_in, *ref_clk;
|
||||
|
||||
clk_in = devm_clk_get(dev, "clk_in");
|
||||
|
@ -420,8 +457,7 @@ static int cs2000_clk_register(struct cs2000_priv *priv)
|
|||
|
||||
static int cs2000_version_print(struct cs2000_priv *priv)
|
||||
{
|
||||
struct i2c_client *client = priv_to_client(priv);
|
||||
struct device *dev = &client->dev;
|
||||
struct device *dev = priv_to_dev(priv);
|
||||
s32 val;
|
||||
const char *revision;
|
||||
|
||||
|
@ -452,7 +488,7 @@ static int cs2000_version_print(struct cs2000_priv *priv)
|
|||
static int cs2000_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cs2000_priv *priv = i2c_get_clientdata(client);
|
||||
struct device *dev = &client->dev;
|
||||
struct device *dev = priv_to_dev(priv);
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
of_clk_del_provider(np);
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Clock driver for Hi655x
|
||||
*
|
||||
* Copyright (c) 2017, Linaro Ltd.
|
||||
*
|
||||
* Author: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/hi655x-pmic.h>
|
||||
|
||||
#define HI655X_CLK_BASE HI655X_BUS_ADDR(0x1c)
|
||||
#define HI655X_CLK_SET BIT(6)
|
||||
|
||||
struct hi655x_clk {
|
||||
struct hi655x_pmic *hi655x;
|
||||
struct clk_hw clk_hw;
|
||||
};
|
||||
|
||||
static unsigned long hi655x_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return 32768;
|
||||
}
|
||||
|
||||
static int hi655x_clk_enable(struct clk_hw *hw, bool enable)
|
||||
{
|
||||
struct hi655x_clk *hi655x_clk =
|
||||
container_of(hw, struct hi655x_clk, clk_hw);
|
||||
|
||||
struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
|
||||
|
||||
return regmap_update_bits(hi655x->regmap, HI655X_CLK_BASE,
|
||||
HI655X_CLK_SET, enable ? HI655X_CLK_SET : 0);
|
||||
}
|
||||
|
||||
static int hi655x_clk_prepare(struct clk_hw *hw)
|
||||
{
|
||||
return hi655x_clk_enable(hw, true);
|
||||
}
|
||||
|
||||
static void hi655x_clk_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
hi655x_clk_enable(hw, false);
|
||||
}
|
||||
|
||||
static int hi655x_clk_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct hi655x_clk *hi655x_clk =
|
||||
container_of(hw, struct hi655x_clk, clk_hw);
|
||||
struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
|
||||
int ret;
|
||||
uint32_t val;
|
||||
|
||||
ret = regmap_read(hi655x->regmap, HI655X_CLK_BASE, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return val & HI655X_CLK_BASE;
|
||||
}
|
||||
|
||||
static const struct clk_ops hi655x_clk_ops = {
|
||||
.prepare = hi655x_clk_prepare,
|
||||
.unprepare = hi655x_clk_unprepare,
|
||||
.is_prepared = hi655x_clk_is_prepared,
|
||||
.recalc_rate = hi655x_clk_recalc_rate,
|
||||
};
|
||||
|
||||
static int hi655x_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *parent = pdev->dev.parent;
|
||||
struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
|
||||
struct hi655x_clk *hi655x_clk;
|
||||
const char *clk_name = "hi655x-clk";
|
||||
struct clk_init_data init = {
|
||||
.name = clk_name,
|
||||
.ops = &hi655x_clk_ops
|
||||
};
|
||||
int ret;
|
||||
|
||||
hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
|
||||
if (!hi655x_clk)
|
||||
return -ENOMEM;
|
||||
|
||||
of_property_read_string_index(parent->of_node, "clock-output-names",
|
||||
0, &clk_name);
|
||||
|
||||
hi655x_clk->clk_hw.init = &init;
|
||||
hi655x_clk->hi655x = hi655x;
|
||||
|
||||
platform_set_drvdata(pdev, hi655x_clk);
|
||||
|
||||
ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
|
||||
&hi655x_clk->clk_hw);
|
||||
}
|
||||
|
||||
static struct platform_driver hi655x_clk_driver = {
|
||||
.probe = hi655x_clk_probe,
|
||||
.driver = {
|
||||
.name = "hi655x-clk",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(hi655x_clk_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Clk driver for the hi655x series PMICs");
|
||||
MODULE_AUTHOR("Daniel Lezcano <daniel.lezcano@linaro.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:hi655x-clk");
|
|
@ -267,10 +267,8 @@ pll_clk_register(struct device *dev, const char *name,
|
|||
}
|
||||
|
||||
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
|
||||
if (!pll) {
|
||||
pr_err("%s: could not allocate PLL clk\n", __func__);
|
||||
if (!pll)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &pll_clk_ops;
|
||||
|
@ -356,11 +354,9 @@ src_clk_register(struct device *dev, const char *name,
|
|||
struct clk_init_data init;
|
||||
|
||||
sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
|
||||
if (!sclk) {
|
||||
pr_err("could not allocate SRC clock %s\n",
|
||||
name);
|
||||
if (!sclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &src_clk_ops;
|
||||
/* Do not force-disable the static SDRAM controller */
|
||||
|
@ -467,7 +463,7 @@ static int nomadik_src_clk_show(struct seq_file *s, void *what)
|
|||
u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
|
||||
u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
|
||||
|
||||
seq_printf(s, "Clock: Boot: Now: Request: ASKED:\n");
|
||||
seq_puts(s, "Clock: Boot: Now: Request: ASKED:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
|
||||
u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
|
||||
u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
|
||||
|
|
|
@ -1354,10 +1354,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|||
return -EINVAL;
|
||||
|
||||
drvdata = devm_kzalloc(&client->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (drvdata == NULL) {
|
||||
dev_err(&client->dev, "unable to allocate driver data\n");
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, drvdata);
|
||||
drvdata->client = client;
|
||||
|
@ -1535,9 +1533,9 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|||
else
|
||||
parent_names[1] = si5351_pll_names[1];
|
||||
|
||||
drvdata->msynth = devm_kzalloc(&client->dev, num_clocks *
|
||||
drvdata->msynth = devm_kcalloc(&client->dev, num_clocks,
|
||||
sizeof(*drvdata->msynth), GFP_KERNEL);
|
||||
drvdata->clkout = devm_kzalloc(&client->dev, num_clocks *
|
||||
drvdata->clkout = devm_kcalloc(&client->dev, num_clocks,
|
||||
sizeof(*drvdata->clkout), GFP_KERNEL);
|
||||
drvdata->num_clkout = num_clocks;
|
||||
|
||||
|
|
|
@ -531,19 +531,26 @@ static int stm32f4_pll_is_enabled(struct clk_hw *hw)
|
|||
return clk_gate_ops.is_enabled(hw);
|
||||
}
|
||||
|
||||
#define PLL_TIMEOUT 10000
|
||||
|
||||
static int stm32f4_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate *gate = to_clk_gate(hw);
|
||||
struct stm32f4_pll *pll = to_stm32f4_pll(gate);
|
||||
int ret = 0;
|
||||
unsigned long reg;
|
||||
int bit_status;
|
||||
unsigned int timeout = PLL_TIMEOUT;
|
||||
|
||||
ret = clk_gate_ops.enable(hw);
|
||||
if (clk_gate_ops.is_enabled(hw))
|
||||
return 0;
|
||||
|
||||
ret = readl_relaxed_poll_timeout_atomic(base + STM32F4_RCC_CR, reg,
|
||||
reg & (1 << pll->bit_rdy_idx), 0, 10000);
|
||||
clk_gate_ops.enable(hw);
|
||||
|
||||
return ret;
|
||||
do {
|
||||
bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx));
|
||||
|
||||
} while (bit_status && --timeout);
|
||||
|
||||
return bit_status;
|
||||
}
|
||||
|
||||
static void stm32f4_pll_disable(struct clk_hw *hw)
|
||||
|
@ -834,24 +841,32 @@ struct stm32_rgate {
|
|||
u8 bit_rdy_idx;
|
||||
};
|
||||
|
||||
#define RTC_TIMEOUT 1000000
|
||||
#define RGATE_TIMEOUT 50000
|
||||
|
||||
static int rgclk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate *gate = to_clk_gate(hw);
|
||||
struct stm32_rgate *rgate = to_rgclk(gate);
|
||||
u32 reg;
|
||||
int ret;
|
||||
int bit_status;
|
||||
unsigned int timeout = RGATE_TIMEOUT;
|
||||
|
||||
if (clk_gate_ops.is_enabled(hw))
|
||||
return 0;
|
||||
|
||||
disable_power_domain_write_protection();
|
||||
|
||||
clk_gate_ops.enable(hw);
|
||||
|
||||
ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg,
|
||||
reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT);
|
||||
do {
|
||||
bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx));
|
||||
if (bit_status)
|
||||
udelay(100);
|
||||
|
||||
} while (bit_status && --timeout);
|
||||
|
||||
enable_power_domain_write_protection();
|
||||
return ret;
|
||||
|
||||
return bit_status;
|
||||
}
|
||||
|
||||
static void rgclk_disable(struct clk_hw *hw)
|
||||
|
@ -1533,7 +1548,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
|
|||
}
|
||||
|
||||
clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
|
||||
base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock);
|
||||
base + STM32F4_RCC_CSR, 0, 1, 0, &stm32f4_clk_lock);
|
||||
|
||||
if (IS_ERR(clks[CLK_LSI])) {
|
||||
pr_err("Unable to register lsi clock\n");
|
||||
|
@ -1541,7 +1556,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
|
|||
}
|
||||
|
||||
clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
|
||||
base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock);
|
||||
base + STM32F4_RCC_BDCR, 0, 1, 0, &stm32f4_clk_lock);
|
||||
|
||||
if (IS_ERR(clks[CLK_LSE])) {
|
||||
pr_err("Unable to register lse clock\n");
|
||||
|
|
|
@ -113,10 +113,29 @@
|
|||
#define VC5_MUX_IN_XIN BIT(0)
|
||||
#define VC5_MUX_IN_CLKIN BIT(1)
|
||||
|
||||
/* Maximum number of clk_out supported by this driver */
|
||||
#define VC5_MAX_CLK_OUT_NUM 5
|
||||
|
||||
/* Maximum number of FODs supported by this driver */
|
||||
#define VC5_MAX_FOD_NUM 4
|
||||
|
||||
/* flags to describe chip features */
|
||||
/* chip has built-in oscilator */
|
||||
#define VC5_HAS_INTERNAL_XTAL BIT(0)
|
||||
|
||||
/* Supported IDT VC5 models. */
|
||||
enum vc5_model {
|
||||
IDT_VC5_5P49V5923,
|
||||
IDT_VC5_5P49V5933,
|
||||
IDT_VC5_5P49V5935,
|
||||
};
|
||||
|
||||
/* Structure to describe features of a particular VC5 model */
|
||||
struct vc5_chip_info {
|
||||
const enum vc5_model model;
|
||||
const unsigned int clk_fod_cnt;
|
||||
const unsigned int clk_out_cnt;
|
||||
const u32 flags;
|
||||
};
|
||||
|
||||
struct vc5_driver_data;
|
||||
|
@ -132,15 +151,15 @@ struct vc5_hw_data {
|
|||
struct vc5_driver_data {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
enum vc5_model model;
|
||||
const struct vc5_chip_info *chip_info;
|
||||
|
||||
struct clk *pin_xin;
|
||||
struct clk *pin_clkin;
|
||||
unsigned char clk_mux_ins;
|
||||
struct clk_hw clk_mux;
|
||||
struct vc5_hw_data clk_pll;
|
||||
struct vc5_hw_data clk_fod[2];
|
||||
struct vc5_hw_data clk_out[3];
|
||||
struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM];
|
||||
struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM];
|
||||
};
|
||||
|
||||
static const char * const vc5_mux_names[] = {
|
||||
|
@ -563,7 +582,7 @@ static struct clk_hw *vc5_of_clk_get(struct of_phandle_args *clkspec,
|
|||
struct vc5_driver_data *vc5 = data;
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx > 2)
|
||||
if (idx >= vc5->chip_info->clk_out_cnt)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return &vc5->clk_out[idx].hw;
|
||||
|
@ -576,6 +595,7 @@ static int vc5_map_index_to_output(const enum vc5_model model,
|
|||
case IDT_VC5_5P49V5933:
|
||||
return (n == 0) ? 0 : 3;
|
||||
case IDT_VC5_5P49V5923:
|
||||
case IDT_VC5_5P49V5935:
|
||||
default:
|
||||
return n;
|
||||
}
|
||||
|
@ -586,12 +606,10 @@ static const struct of_device_id clk_vc5_of_match[];
|
|||
static int vc5_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(clk_vc5_of_match, &client->dev);
|
||||
struct vc5_driver_data *vc5;
|
||||
struct clk_init_data init;
|
||||
const char *parent_names[2];
|
||||
unsigned int n, idx;
|
||||
unsigned int n, idx = 0;
|
||||
int ret;
|
||||
|
||||
vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL);
|
||||
|
@ -600,7 +618,7 @@ static int vc5_probe(struct i2c_client *client,
|
|||
|
||||
i2c_set_clientdata(client, vc5);
|
||||
vc5->client = client;
|
||||
vc5->model = (enum vc5_model)of_id->data;
|
||||
vc5->chip_info = of_device_get_match_data(&client->dev);
|
||||
|
||||
vc5->pin_xin = devm_clk_get(&client->dev, "xin");
|
||||
if (PTR_ERR(vc5->pin_xin) == -EPROBE_DEFER)
|
||||
|
@ -622,8 +640,7 @@ static int vc5_probe(struct i2c_client *client,
|
|||
if (!IS_ERR(vc5->pin_xin)) {
|
||||
vc5->clk_mux_ins |= VC5_MUX_IN_XIN;
|
||||
parent_names[init.num_parents++] = __clk_get_name(vc5->pin_xin);
|
||||
} else if (vc5->model == IDT_VC5_5P49V5933) {
|
||||
/* IDT VC5 5P49V5933 has built-in oscilator. */
|
||||
} else if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL) {
|
||||
vc5->pin_xin = clk_register_fixed_rate(&client->dev,
|
||||
"internal-xtal", NULL,
|
||||
0, 25000000);
|
||||
|
@ -672,8 +689,8 @@ static int vc5_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
/* Register FODs */
|
||||
for (n = 0; n < 2; n++) {
|
||||
idx = vc5_map_index_to_output(vc5->model, n);
|
||||
for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {
|
||||
idx = vc5_map_index_to_output(vc5->chip_info->model, n);
|
||||
memset(&init, 0, sizeof(init));
|
||||
init.name = vc5_fod_names[idx];
|
||||
init.ops = &vc5_fod_ops;
|
||||
|
@ -709,8 +726,8 @@ static int vc5_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
/* Register FOD-connected OUTx outputs */
|
||||
for (n = 1; n < 3; n++) {
|
||||
idx = vc5_map_index_to_output(vc5->model, n - 1);
|
||||
for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {
|
||||
idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1);
|
||||
parent_names[0] = vc5_fod_names[idx];
|
||||
if (n == 1)
|
||||
parent_names[1] = vc5_mux_names[0];
|
||||
|
@ -744,7 +761,7 @@ static int vc5_probe(struct i2c_client *client,
|
|||
return 0;
|
||||
|
||||
err_clk:
|
||||
if (vc5->model == IDT_VC5_5P49V5933)
|
||||
if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
|
||||
clk_unregister_fixed_rate(vc5->pin_xin);
|
||||
return ret;
|
||||
}
|
||||
|
@ -755,22 +772,45 @@ static int vc5_remove(struct i2c_client *client)
|
|||
|
||||
of_clk_del_provider(client->dev.of_node);
|
||||
|
||||
if (vc5->model == IDT_VC5_5P49V5933)
|
||||
if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
|
||||
clk_unregister_fixed_rate(vc5->pin_xin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct vc5_chip_info idt_5p49v5923_info = {
|
||||
.model = IDT_VC5_5P49V5923,
|
||||
.clk_fod_cnt = 2,
|
||||
.clk_out_cnt = 3,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static const struct vc5_chip_info idt_5p49v5933_info = {
|
||||
.model = IDT_VC5_5P49V5933,
|
||||
.clk_fod_cnt = 2,
|
||||
.clk_out_cnt = 3,
|
||||
.flags = VC5_HAS_INTERNAL_XTAL,
|
||||
};
|
||||
|
||||
static const struct vc5_chip_info idt_5p49v5935_info = {
|
||||
.model = IDT_VC5_5P49V5935,
|
||||
.clk_fod_cnt = 4,
|
||||
.clk_out_cnt = 5,
|
||||
.flags = VC5_HAS_INTERNAL_XTAL,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id vc5_id[] = {
|
||||
{ "5p49v5923", .driver_data = IDT_VC5_5P49V5923 },
|
||||
{ "5p49v5933", .driver_data = IDT_VC5_5P49V5933 },
|
||||
{ "5p49v5935", .driver_data = IDT_VC5_5P49V5935 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, vc5_id);
|
||||
|
||||
static const struct of_device_id clk_vc5_of_match[] = {
|
||||
{ .compatible = "idt,5p49v5923", .data = (void *)IDT_VC5_5P49V5923 },
|
||||
{ .compatible = "idt,5p49v5933", .data = (void *)IDT_VC5_5P49V5933 },
|
||||
{ .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info },
|
||||
{ .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info },
|
||||
{ .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clk_vc5_of_match);
|
||||
|
|
|
@ -966,6 +966,8 @@ static int __clk_notify(struct clk_core *core, unsigned long msg,
|
|||
cnd.clk = cn->clk;
|
||||
ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
|
||||
&cnd);
|
||||
if (ret & NOTIFY_STOP_MASK)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2081,11 +2083,11 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
|
|||
clk_dump_one(s, c, level);
|
||||
|
||||
hlist_for_each_entry(child, &c->children, child_node) {
|
||||
seq_printf(s, ",");
|
||||
seq_putc(s, ',');
|
||||
clk_dump_subtree(s, child, level + 1);
|
||||
}
|
||||
|
||||
seq_printf(s, "}");
|
||||
seq_putc(s, '}');
|
||||
}
|
||||
|
||||
static int clk_dump(struct seq_file *s, void *data)
|
||||
|
@ -2094,14 +2096,13 @@ static int clk_dump(struct seq_file *s, void *data)
|
|||
bool first_node = true;
|
||||
struct hlist_head **lists = (struct hlist_head **)s->private;
|
||||
|
||||
seq_printf(s, "{");
|
||||
|
||||
seq_putc(s, '{');
|
||||
clk_prepare_lock();
|
||||
|
||||
for (; *lists; lists++) {
|
||||
hlist_for_each_entry(c, *lists, child_node) {
|
||||
if (!first_node)
|
||||
seq_puts(s, ",");
|
||||
seq_putc(s, ',');
|
||||
first_node = false;
|
||||
clk_dump_subtree(s, c, 0);
|
||||
}
|
||||
|
@ -2126,6 +2127,31 @@ static const struct file_operations clk_dump_fops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int possible_parents_dump(struct seq_file *s, void *data)
|
||||
{
|
||||
struct clk_core *core = s->private;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < core->num_parents - 1; i++)
|
||||
seq_printf(s, "%s ", core->parent_names[i]);
|
||||
|
||||
seq_printf(s, "%s\n", core->parent_names[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int possible_parents_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, possible_parents_dump, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations possible_parents_fops = {
|
||||
.open = possible_parents_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
@ -2177,6 +2203,13 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
|
|||
if (!d)
|
||||
goto err_out;
|
||||
|
||||
if (core->num_parents > 1) {
|
||||
d = debugfs_create_file("clk_possible_parents", S_IRUGO,
|
||||
core->dentry, core, &possible_parents_fops);
|
||||
if (!d)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (core->ops->debug_init) {
|
||||
ret = core->ops->debug_init(core->hw, core->dentry);
|
||||
if (ret)
|
||||
|
@ -2940,7 +2973,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
|
|||
|
||||
/* if clk wasn't in the notifier list, allocate new clk_notifier */
|
||||
if (cn->clk != clk) {
|
||||
cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
|
||||
cn = kzalloc(sizeof(*cn), GFP_KERNEL);
|
||||
if (!cn)
|
||||
goto out;
|
||||
|
||||
|
@ -3088,7 +3121,7 @@ int of_clk_add_provider(struct device_node *np,
|
|||
struct of_clk_provider *cp;
|
||||
int ret;
|
||||
|
||||
cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
|
||||
cp = kzalloc(sizeof(*cp), GFP_KERNEL);
|
||||
if (!cp)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ static struct hisi_divider_clock hi3620_div_clks[] __initdata = {
|
|||
{ HI3620_MMC3_DIV, "mmc3_div", "mmc3_mux", 0, 0x140, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
|
||||
};
|
||||
|
||||
static struct hisi_gate_clock hi3620_seperated_gate_clks[] __initdata = {
|
||||
static struct hisi_gate_clock hi3620_separated_gate_clks[] __initdata = {
|
||||
{ HI3620_TIMERCLK01, "timerclk01", "timer_rclk01", CLK_SET_RATE_PARENT, 0x20, 0, 0, },
|
||||
{ HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo", CLK_SET_RATE_PARENT, 0x20, 1, 0, },
|
||||
{ HI3620_TIMERCLK23, "timerclk23", "timer_rclk23", CLK_SET_RATE_PARENT, 0x20, 2, 0, },
|
||||
|
@ -224,8 +224,8 @@ static void __init hi3620_clk_init(struct device_node *np)
|
|||
clk_data);
|
||||
hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks),
|
||||
clk_data);
|
||||
hisi_clk_register_gate_sep(hi3620_seperated_gate_clks,
|
||||
ARRAY_SIZE(hi3620_seperated_gate_clks),
|
||||
hisi_clk_register_gate_sep(hi3620_separated_gate_clks,
|
||||
ARRAY_SIZE(hi3620_separated_gate_clks),
|
||||
clk_data);
|
||||
}
|
||||
CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
|
||||
|
@ -430,10 +430,8 @@ static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
|
|||
struct clk_init_data init;
|
||||
|
||||
mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
|
||||
if (!mclk) {
|
||||
pr_err("%s: fail to allocate mmc clk\n", __func__);
|
||||
if (!mclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = mmc_clk->name;
|
||||
init.ops = &clk_mmc_ops;
|
||||
|
@ -482,11 +480,9 @@ static void __init hi3620_mmc_clk_init(struct device_node *node)
|
|||
if (WARN_ON(!clk_data))
|
||||
return;
|
||||
|
||||
clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
|
||||
if (!clk_data->clks) {
|
||||
pr_err("%s: fail to allocate mmc clk\n", __func__);
|
||||
clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
|
||||
if (!clk_data->clks)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
|
||||
|
|
|
@ -134,6 +134,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
|
|||
{ 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_DAPB_CLK, "dapb_clk", "cs_dapb", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x230, 18, 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, },
|
||||
|
|
|
@ -54,8 +54,9 @@ struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
|
|||
if (!clk_data->base)
|
||||
return NULL;
|
||||
|
||||
clk_table = devm_kmalloc(&pdev->dev, sizeof(struct clk *) * nr_clks,
|
||||
GFP_KERNEL);
|
||||
clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
|
||||
sizeof(*clk_table),
|
||||
GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
return NULL;
|
||||
|
||||
|
@ -80,17 +81,14 @@ struct hisi_clock_data *hisi_clk_init(struct device_node *np,
|
|||
}
|
||||
|
||||
clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
|
||||
if (!clk_data) {
|
||||
pr_err("%s: could not allocate clock data\n", __func__);
|
||||
if (!clk_data)
|
||||
goto err;
|
||||
}
|
||||
clk_data->base = base;
|
||||
|
||||
clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
|
||||
if (!clk_table) {
|
||||
pr_err("%s: could not allocate clock lookup table\n", __func__);
|
||||
clk_data->base = base;
|
||||
clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
goto err_data;
|
||||
}
|
||||
|
||||
clk_data->clk_data.clks = clk_table;
|
||||
clk_data->clk_data.clk_num = nr_clks;
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
|
||||
|
|
|
@ -73,7 +73,7 @@ static struct clk *clks[IMX6UL_CLK_END];
|
|||
static struct clk_onecell_data clk_data;
|
||||
|
||||
static int const clks_init_on[] __initconst = {
|
||||
IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AIPSTZ3,
|
||||
IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2,
|
||||
IMX6UL_CLK_AXI, IMX6UL_CLK_ARM, IMX6UL_CLK_ROM,
|
||||
IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG,
|
||||
};
|
||||
|
@ -341,9 +341,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
|||
clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt2_serial", "perclk", base + 0x68, 26);
|
||||
clks[IMX6UL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
|
||||
clks[IMX6UL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
|
||||
if (clk_on_imx6ul())
|
||||
clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30);
|
||||
else if (clk_on_imx6ull())
|
||||
if (clk_on_imx6ull())
|
||||
clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x80, 18);
|
||||
|
||||
/* CCGR1 */
|
||||
|
@ -360,7 +358,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
|||
clks[IMX6UL_CLK_GPT1_BUS] = imx_clk_gate2("gpt1_bus", "perclk", base + 0x6c, 20);
|
||||
clks[IMX6UL_CLK_GPT1_SERIAL] = imx_clk_gate2("gpt1_serial", "perclk", base + 0x6c, 22);
|
||||
clks[IMX6UL_CLK_UART4_IPG] = imx_clk_gate2("uart4_ipg", "ipg", base + 0x6c, 24);
|
||||
clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
|
||||
clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serial", "uart_podf", base + 0x6c, 24);
|
||||
|
||||
/* CCGR2 */
|
||||
if (clk_on_imx6ull()) {
|
||||
|
@ -482,6 +480,9 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
|||
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
|
||||
clk_prepare_enable(clks[clks_init_on[i]]);
|
||||
|
||||
if (clk_on_imx6ull())
|
||||
clk_prepare_enable(clks[IMX6UL_CLK_AIPSTZ3]);
|
||||
|
||||
if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
|
||||
clk_prepare_enable(clks[IMX6UL_CLK_USBPHY1_GATE]);
|
||||
clk_prepare_enable(clks[IMX6UL_CLK_USBPHY2_GATE]);
|
||||
|
|
|
@ -386,7 +386,7 @@ static int const clks_init_on[] __initconst = {
|
|||
IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
|
||||
IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
|
||||
IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
|
||||
IMX7D_AHB_CHANNEL_ROOT_CLK,
|
||||
IMX7D_AHB_CHANNEL_ROOT_CLK, IMX7D_IPG_ROOT_CLK,
|
||||
};
|
||||
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
@ -724,8 +724,9 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
|
||||
clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
|
||||
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
|
||||
clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
|
||||
clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6);
|
||||
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
|
||||
clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
|
||||
clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2);
|
||||
clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
|
||||
clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
|
||||
clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
|
||||
|
@ -796,9 +797,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
|
||||
clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
|
||||
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0);
|
||||
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0);
|
||||
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
|
||||
clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0);
|
||||
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
|
||||
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
|
||||
|
|
|
@ -50,6 +50,38 @@ config COMMON_CLK_MT2701_BDPSYS
|
|||
---help---
|
||||
This driver supports Mediatek MT2701 bdpsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797
|
||||
bool "Clock driver for Mediatek MT6797"
|
||||
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK && ARM64
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 basic clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_MMSYS
|
||||
bool "Clock driver for Mediatek MT6797 mmsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 mmsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_IMGSYS
|
||||
bool "Clock driver for Mediatek MT6797 imgsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_VDECSYS
|
||||
bool "Clock driver for Mediatek MT6797 vdecsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 vdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_VENCSYS
|
||||
bool "Clock driver for Mediatek MT6797 vencsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 vencsys clocks.
|
||||
|
||||
config COMMON_CLK_MT8135
|
||||
bool "Clock driver for Mediatek MT8135"
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_VDECSYS) += clk-mt6797-vdec.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_VENCSYS) += clk-mt6797-venc.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
|
||||
|
|
|
@ -66,6 +66,8 @@ static int clk_mt2701_eth_probe(struct platform_device *pdev)
|
|||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
mtk_register_reset_controller(node, 1, 0x34);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Kevin Chen <kevin-cw.chen@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <dt-bindings/clock/mt6797-clk.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
static const struct mtk_gate_regs img_cg_regs = {
|
||||
.set_ofs = 0x0004,
|
||||
.clr_ofs = 0x0008,
|
||||
.sta_ofs = 0x0000,
|
||||
};
|
||||
|
||||
#define GATE_IMG(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &img_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate img_clks[] = {
|
||||
GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_sel", 11),
|
||||
GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_sel", 10),
|
||||
GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_sel", 6),
|
||||
GATE_IMG(CLK_IMG_LARB6, "img_larb6", "mm_sel", 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt6797_img[] = {
|
||||
{ .compatible = "mediatek,mt6797-imgsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt6797_img_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
|
||||
|
||||
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt6797_img_drv = {
|
||||
.probe = clk_mt6797_img_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt6797-img",
|
||||
.of_match_table = of_match_clk_mt6797_img,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt6797_img_drv);
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Kevin Chen <kevin-cw.chen@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <dt-bindings/clock/mt6797-clk.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
static const struct mtk_gate_regs mm0_cg_regs = {
|
||||
.set_ofs = 0x0104,
|
||||
.clr_ofs = 0x0108,
|
||||
.sta_ofs = 0x0100,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs mm1_cg_regs = {
|
||||
.set_ofs = 0x0114,
|
||||
.clr_ofs = 0x0118,
|
||||
.sta_ofs = 0x0110,
|
||||
};
|
||||
|
||||
#define GATE_MM0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &mm0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_MM1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &mm1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate mm_clks[] = {
|
||||
GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
|
||||
GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
|
||||
GATE_MM0(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 2),
|
||||
GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 3),
|
||||
GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 4),
|
||||
GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 5),
|
||||
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 6),
|
||||
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 7),
|
||||
GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 8),
|
||||
GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
|
||||
GATE_MM0(CLK_MM_MDP_COLOR, "mm_mdp_color", "mm_sel", 10),
|
||||
GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
|
||||
GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
|
||||
GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
|
||||
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
|
||||
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 15),
|
||||
GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 16),
|
||||
GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 17),
|
||||
GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 18),
|
||||
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 19),
|
||||
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 20),
|
||||
GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
|
||||
GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
|
||||
GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 23),
|
||||
GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "mm_sel", 24),
|
||||
GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
|
||||
GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
|
||||
GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 27),
|
||||
GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "mm_sel", 28),
|
||||
GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 29),
|
||||
GATE_MM0(CLK_MM_DISP_DSC, "mm_disp_dsc", "mm_sel", 30),
|
||||
GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
|
||||
GATE_MM1(CLK_MM_DSI0_MM_CLOCK, "mm_dsi0_mm_clock", "mm_sel", 0),
|
||||
GATE_MM1(CLK_MM_DSI1_MM_CLOCK, "mm_dsi1_mm_clock", "mm_sel", 2),
|
||||
GATE_MM1(CLK_MM_DPI_MM_CLOCK, "mm_dpi_mm_clock", "mm_sel", 4),
|
||||
GATE_MM1(CLK_MM_DPI_INTERFACE_CLOCK, "mm_dpi_interface_clock",
|
||||
"dpi0_sel", 5),
|
||||
GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MM_CLOCK, "mm_larb4_axi_asif_mm_clock",
|
||||
"mm_sel", 6),
|
||||
GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK, "mm_larb4_axi_asif_mjc_clock",
|
||||
"mjc_sel", 7),
|
||||
GATE_MM1(CLK_MM_DISP_OVL0_MOUT_CLOCK, "mm_disp_ovl0_mout_clock",
|
||||
"mm_sel", 8),
|
||||
GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 9),
|
||||
GATE_MM1(CLK_MM_DSI0_INTERFACE_CLOCK, "mm_dsi0_interface_clock",
|
||||
"clk26m", 1),
|
||||
GATE_MM1(CLK_MM_DSI1_INTERFACE_CLOCK, "mm_dsi1_interface_clock",
|
||||
"clk26m", 3),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt6797_mm[] = {
|
||||
{ .compatible = "mediatek,mt6797-mmsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt6797_mm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_MM_NR);
|
||||
|
||||
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt6797_mm_drv = {
|
||||
.probe = clk_mt6797_mm_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt6797-mm",
|
||||
.of_match_table = of_match_clk_mt6797_mm,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt6797_mm_drv);
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Kevin-CW Chen <kevin-cw.chen@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt6797-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs vdec0_cg_regs = {
|
||||
.set_ofs = 0x0000,
|
||||
.clr_ofs = 0x0004,
|
||||
.sta_ofs = 0x0000,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs vdec1_cg_regs = {
|
||||
.set_ofs = 0x0008,
|
||||
.clr_ofs = 0x000c,
|
||||
.sta_ofs = 0x0008,
|
||||
};
|
||||
|
||||
#define GATE_VDEC0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &vdec0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
#define GATE_VDEC1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &vdec1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate vdec_clks[] = {
|
||||
GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "vdec_sel", 8),
|
||||
GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4),
|
||||
GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
|
||||
GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "mm_sel", 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt6797_vdec[] = {
|
||||
{ .compatible = "mediatek,mt6797-vdecsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt6797_vdec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
|
||||
|
||||
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt6797_vdec_drv = {
|
||||
.probe = clk_mt6797_vdec_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt6797-vdec",
|
||||
.of_match_table = of_match_clk_mt6797_vdec,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt6797_vdec_drv);
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Kevin Chen <kevin-cw.chen@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt6797-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs venc_cg_regs = {
|
||||
.set_ofs = 0x0004,
|
||||
.clr_ofs = 0x0008,
|
||||
.sta_ofs = 0x0000,
|
||||
};
|
||||
|
||||
#define GATE_VENC(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &venc_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate venc_clks[] = {
|
||||
GATE_VENC(CLK_VENC_0, "venc_0", "mm_sel", 0),
|
||||
GATE_VENC(CLK_VENC_1, "venc_1", "venc_sel", 4),
|
||||
GATE_VENC(CLK_VENC_2, "venc_2", "venc_sel", 8),
|
||||
GATE_VENC(CLK_VENC_3, "venc_3", "venc_sel", 12),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt6797_venc[] = {
|
||||
{ .compatible = "mediatek,mt6797-vencsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt6797_venc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_VENC_NR);
|
||||
|
||||
mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt6797_venc_drv = {
|
||||
.probe = clk_mt6797_venc_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt6797-venc",
|
||||
.of_match_table = of_match_clk_mt6797_venc,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt6797_venc_drv);
|
|
@ -0,0 +1,714 @@
|
|||
/*
|
||||
* Copyright (c) 2016 MediaTek Inc.
|
||||
* Author: Kevin Chen <kevin-cw.chen@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/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt6797-clk.h>
|
||||
|
||||
/*
|
||||
* For some clocks, we don't care what their actual rates are. And these
|
||||
* clocks may change their rate on different products or different scenarios.
|
||||
* So we model these clocks' rate as 0, to denote it's not an actual rate.
|
||||
*/
|
||||
|
||||
static DEFINE_SPINLOCK(mt6797_clk_lock);
|
||||
|
||||
static const struct mtk_fixed_factor top_fixed_divs[] = {
|
||||
FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, 1),
|
||||
FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
|
||||
FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
|
||||
FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
|
||||
FACTOR(CLK_TOP_SYSPLL_D3_D3, "syspll_d3_d3", "syspll_d3", 1, 3),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
|
||||
FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
|
||||
FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
|
||||
FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
|
||||
FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
|
||||
FACTOR(CLK_TOP_SSUSB_PHY_48M_CK, "ssusb_phy_48m_ck", "univpll", 1, 1),
|
||||
FACTOR(CLK_TOP_USB_PHY48M_CK, "usb_phy48m_ck", "univpll", 1, 1),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8),
|
||||
FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
|
||||
FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
|
||||
FACTOR(CLK_TOP_ULPOSC_CK_ORG, "ulposc_ck_org", "ulposc", 1, 1),
|
||||
FACTOR(CLK_TOP_ULPOSC_CK, "ulposc_ck", "ulposc_ck_org", 1, 3),
|
||||
FACTOR(CLK_TOP_ULPOSC_D2, "ulposc_d2", "ulposc_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_ULPOSC_D3, "ulposc_d3", "ulposc_ck", 1, 4),
|
||||
FACTOR(CLK_TOP_ULPOSC_D4, "ulposc_d4", "ulposc_ck", 1, 8),
|
||||
FACTOR(CLK_TOP_ULPOSC_D8, "ulposc_d8", "ulposc_ck", 1, 10),
|
||||
FACTOR(CLK_TOP_ULPOSC_D10, "ulposc_d10", "ulposc_ck_org", 1, 1),
|
||||
FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
|
||||
FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
|
||||
FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1),
|
||||
FACTOR(CLK_TOP_MFGPLL_D2, "mfgpll_d2", "mfgpll_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_IMGPLL_CK, "imgpll_ck", "imgpll", 1, 1),
|
||||
FACTOR(CLK_TOP_IMGPLL_D2, "imgpll_d2", "imgpll_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_IMGPLL_D4, "imgpll_d4", "imgpll_ck", 1, 4),
|
||||
FACTOR(CLK_TOP_CODECPLL_CK, "codecpll_ck", "codecpll", 1, 1),
|
||||
FACTOR(CLK_TOP_CODECPLL_D2, "codecpll_d2", "codecpll_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_VDECPLL_CK, "vdecpll_ck", "vdecpll", 1, 1),
|
||||
FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1),
|
||||
FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4),
|
||||
FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8),
|
||||
FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16),
|
||||
FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
|
||||
FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2),
|
||||
FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, 4),
|
||||
FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll_ck", 1, 8),
|
||||
};
|
||||
|
||||
static const char * const axi_parents[] = {
|
||||
"clk26m",
|
||||
"syspll_d7",
|
||||
"ulposc_axi_ck_mux",
|
||||
};
|
||||
|
||||
static const char * const ulposc_axi_ck_mux_parents[] = {
|
||||
"syspll1_d4",
|
||||
"ulposc_axi_ck_mux_pre",
|
||||
};
|
||||
|
||||
static const char * const ulposc_axi_ck_mux_pre_parents[] = {
|
||||
"ulposc_d2",
|
||||
"ulposc_d3",
|
||||
};
|
||||
|
||||
static const char * const ddrphycfg_parents[] = {
|
||||
"clk26m",
|
||||
"syspll3_d2",
|
||||
"syspll2_d4",
|
||||
"syspll1_d8",
|
||||
};
|
||||
|
||||
static const char * const mm_parents[] = {
|
||||
"clk26m",
|
||||
"imgpll_ck",
|
||||
"univpll1_d2",
|
||||
"syspll1_d2",
|
||||
};
|
||||
|
||||
static const char * const pwm_parents[] = {
|
||||
"clk26m",
|
||||
"univpll2_d4",
|
||||
"ulposc_d2",
|
||||
"ulposc_d3",
|
||||
"ulposc_d8",
|
||||
"ulposc_d10",
|
||||
"ulposc_d4",
|
||||
};
|
||||
|
||||
static const char * const vdec_parents[] = {
|
||||
"clk26m",
|
||||
"vdecpll_ck",
|
||||
"imgpll_ck",
|
||||
"syspll_d3",
|
||||
"univpll_d5",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
};
|
||||
|
||||
static const char * const venc_parents[] = {
|
||||
"clk26m",
|
||||
"codecpll_ck",
|
||||
"syspll_d3",
|
||||
};
|
||||
|
||||
static const char * const mfg_parents[] = {
|
||||
"clk26m",
|
||||
"mfgpll_ck",
|
||||
"syspll_d3",
|
||||
"univpll_d3",
|
||||
};
|
||||
|
||||
static const char * const camtg[] = {
|
||||
"clk26m",
|
||||
"univpll_d26",
|
||||
"univpll2_d2",
|
||||
};
|
||||
|
||||
static const char * const uart_parents[] = {
|
||||
"clk26m",
|
||||
"univpll2_d8",
|
||||
};
|
||||
|
||||
static const char * const spi_parents[] = {
|
||||
"clk26m",
|
||||
"syspll3_d2",
|
||||
"syspll2_d4",
|
||||
"ulposc_spi_ck_mux",
|
||||
};
|
||||
|
||||
static const char * const ulposc_spi_ck_mux_parents[] = {
|
||||
"ulposc_d2",
|
||||
"ulposc_d3",
|
||||
};
|
||||
|
||||
static const char * const usb20_parents[] = {
|
||||
"clk26m",
|
||||
"univpll1_d8",
|
||||
"syspll4_d2",
|
||||
};
|
||||
|
||||
static const char * const msdc50_0_hclk_parents[] = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"syspll2_d2",
|
||||
"syspll4_d2",
|
||||
};
|
||||
|
||||
static const char * const msdc50_0_parents[] = {
|
||||
"clk26m",
|
||||
"msdcpll",
|
||||
"syspll_d3",
|
||||
"univpll1_d4",
|
||||
"syspll2_d2",
|
||||
"syspll_d7",
|
||||
"msdcpll_d2",
|
||||
"univpll1_d2",
|
||||
"univpll_d3",
|
||||
};
|
||||
|
||||
static const char * const msdc30_1_parents[] = {
|
||||
"clk26m",
|
||||
"univpll2_d2",
|
||||
"msdcpll_d2",
|
||||
"univpll1_d4",
|
||||
"syspll2_d2",
|
||||
"syspll_d7",
|
||||
"univpll_d7",
|
||||
};
|
||||
|
||||
static const char * const msdc30_2_parents[] = {
|
||||
"clk26m",
|
||||
"univpll2_d8",
|
||||
"syspll2_d8",
|
||||
"syspll1_d8",
|
||||
"msdcpll_d8",
|
||||
"syspll3_d4",
|
||||
"univpll_d26",
|
||||
};
|
||||
|
||||
static const char * const audio_parents[] = {
|
||||
"clk26m",
|
||||
"syspll3_d4",
|
||||
"syspll4_d4",
|
||||
"syspll1_d16",
|
||||
};
|
||||
|
||||
static const char * const aud_intbus_parents[] = {
|
||||
"clk26m",
|
||||
"syspll1_d4",
|
||||
"syspll4_d2",
|
||||
};
|
||||
|
||||
static const char * const pmicspi_parents[] = {
|
||||
"clk26m",
|
||||
"univpll_d26",
|
||||
"syspll3_d4",
|
||||
"syspll1_d8",
|
||||
"ulposc_d4",
|
||||
"ulposc_d8",
|
||||
"syspll2_d8",
|
||||
};
|
||||
|
||||
static const char * const scp_parents[] = {
|
||||
"clk26m",
|
||||
"syspll_d3",
|
||||
"ulposc_ck",
|
||||
"univpll_d5",
|
||||
};
|
||||
|
||||
static const char * const atb_parents[] = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"syspll_d5",
|
||||
};
|
||||
|
||||
static const char * const mjc_parents[] = {
|
||||
"clk26m",
|
||||
"imgpll_ck",
|
||||
"univpll_d5",
|
||||
"syspll1_d2",
|
||||
};
|
||||
|
||||
static const char * const dpi0_parents[] = {
|
||||
"clk26m",
|
||||
"tvdpll_d2",
|
||||
"tvdpll_d4",
|
||||
"tvdpll_d8",
|
||||
"tvdpll_d16",
|
||||
"clk26m",
|
||||
"clk26m",
|
||||
};
|
||||
|
||||
static const char * const aud_1_parents[] = {
|
||||
"clk26m",
|
||||
"apll1_ck",
|
||||
};
|
||||
|
||||
static const char * const aud_2_parents[] = {
|
||||
"clk26m",
|
||||
"apll2_ck",
|
||||
};
|
||||
|
||||
static const char * const ssusb_top_sys_parents[] = {
|
||||
"clk26m",
|
||||
"univpll3_d2",
|
||||
};
|
||||
|
||||
static const char * const spm_parents[] = {
|
||||
"clk26m",
|
||||
"syspll1_d8",
|
||||
};
|
||||
|
||||
static const char * const bsi_spi_parents[] = {
|
||||
"clk26m",
|
||||
"syspll_d3_d3",
|
||||
"syspll1_d4",
|
||||
"syspll_d7",
|
||||
};
|
||||
|
||||
static const char * const audio_h_parents[] = {
|
||||
"clk26m",
|
||||
"apll2_ck",
|
||||
"apll1_ck",
|
||||
"univpll_d7",
|
||||
};
|
||||
|
||||
static const char * const mfg_52m_parents[] = {
|
||||
"clk26m",
|
||||
"univpll2_d8",
|
||||
"univpll2_d4",
|
||||
"univpll2_d4",
|
||||
};
|
||||
|
||||
static const char * const anc_md32_parents[] = {
|
||||
"clk26m",
|
||||
"syspll1_d2",
|
||||
"univpll_d5",
|
||||
};
|
||||
|
||||
static const struct mtk_composite top_muxes[] = {
|
||||
MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre",
|
||||
ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1),
|
||||
MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX, "ulposc_axi_ck_mux",
|
||||
ulposc_axi_ck_mux_parents, 0x0040, 2, 1),
|
||||
MUX(CLK_TOP_MUX_AXI, "axi_sel", axi_parents,
|
||||
0x0040, 0, 2),
|
||||
MUX(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents,
|
||||
0x0040, 16, 2),
|
||||
MUX(CLK_TOP_MUX_MM, "mm_sel", mm_parents,
|
||||
0x0040, 24, 2),
|
||||
MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel", pwm_parents, 0x0050, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel", vdec_parents, 0x0050, 8, 3, 15),
|
||||
MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel", venc_parents, 0x0050, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel", mfg_parents, 0x0050, 24, 2, 31),
|
||||
MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel", camtg, 0x0060, 0, 2, 7),
|
||||
MUX_GATE(CLK_TOP_MUX_UART, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
|
||||
MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, 0x0060, 16, 2, 23),
|
||||
MUX(CLK_TOP_MUX_ULPOSC_SPI_CK_MUX, "ulposc_spi_ck_mux",
|
||||
ulposc_spi_ck_mux_parents, 0x0060, 18, 1),
|
||||
MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel", usb20_parents,
|
||||
0x0060, 24, 2, 31),
|
||||
MUX(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_0_hclk_sel",
|
||||
msdc50_0_hclk_parents, 0x0070, 8, 2),
|
||||
MUX_GATE(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", msdc50_0_parents,
|
||||
0x0070, 16, 4, 23),
|
||||
MUX_GATE(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", msdc30_1_parents,
|
||||
0x0070, 24, 3, 31),
|
||||
MUX_GATE(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", msdc30_2_parents,
|
||||
0x0080, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents,
|
||||
0x0080, 16, 2, 23),
|
||||
MUX(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel", aud_intbus_parents,
|
||||
0x0080, 24, 2),
|
||||
MUX(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", pmicspi_parents,
|
||||
0x0090, 0, 3),
|
||||
MUX(CLK_TOP_MUX_SCP, "scp_sel", scp_parents,
|
||||
0x0090, 8, 2),
|
||||
MUX(CLK_TOP_MUX_ATB, "atb_sel", atb_parents,
|
||||
0x0090, 16, 2),
|
||||
MUX_GATE(CLK_TOP_MUX_MJC, "mjc_sel", mjc_parents, 0x0090, 24, 2, 31),
|
||||
MUX_GATE(CLK_TOP_MUX_DPI0, "dpi0_sel", dpi0_parents, 0x00A0, 0, 3, 7),
|
||||
MUX_GATE(CLK_TOP_MUX_AUD_1, "aud_1_sel", aud_1_parents,
|
||||
0x00A0, 16, 1, 23),
|
||||
MUX_GATE(CLK_TOP_MUX_AUD_2, "aud_2_sel", aud_2_parents,
|
||||
0x00A0, 24, 1, 31),
|
||||
MUX(CLK_TOP_MUX_SSUSB_TOP_SYS, "ssusb_top_sys_sel",
|
||||
ssusb_top_sys_parents, 0x00B0, 8, 1),
|
||||
MUX(CLK_TOP_MUX_SPM, "spm_sel", spm_parents,
|
||||
0x00C0, 0, 1),
|
||||
MUX(CLK_TOP_MUX_BSI_SPI, "bsi_spi_sel", bsi_spi_parents,
|
||||
0x00C0, 8, 2),
|
||||
MUX_GATE(CLK_TOP_MUX_AUDIO_H, "audio_h_sel", audio_h_parents,
|
||||
0x00C0, 16, 2, 23),
|
||||
MUX_GATE(CLK_TOP_MUX_ANC_MD32, "anc_md32_sel", anc_md32_parents,
|
||||
0x00C0, 24, 2, 31),
|
||||
MUX(CLK_TOP_MUX_MFG_52M, "mfg_52m_sel", mfg_52m_parents,
|
||||
0x0104, 1, 2),
|
||||
};
|
||||
|
||||
static int mtk_topckgen_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
void __iomem *base;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
|
||||
|
||||
mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
|
||||
clk_data);
|
||||
|
||||
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
|
||||
&mt6797_clk_lock, clk_data);
|
||||
|
||||
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
static const struct mtk_gate_regs infra0_cg_regs = {
|
||||
.set_ofs = 0x0080,
|
||||
.clr_ofs = 0x0084,
|
||||
.sta_ofs = 0x0090,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra1_cg_regs = {
|
||||
.set_ofs = 0x0088,
|
||||
.clr_ofs = 0x008c,
|
||||
.sta_ofs = 0x0094,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs infra2_cg_regs = {
|
||||
.set_ofs = 0x00a8,
|
||||
.clr_ofs = 0x00ac,
|
||||
.sta_ofs = 0x00b0,
|
||||
};
|
||||
|
||||
#define GATE_ICG0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_ICG1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_ICG2(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &infra2_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate infra_clks[] = {
|
||||
GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "ulposc", 0),
|
||||
GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pmicspi_sel", 1),
|
||||
GATE_ICG0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pmicspi_sel", 2),
|
||||
GATE_ICG0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pmicspi_sel", 3),
|
||||
GATE_ICG0(CLK_INFRA_SCP, "infra_scp", "scp_sel", 4),
|
||||
GATE_ICG0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5),
|
||||
GATE_ICG0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6),
|
||||
GATE_ICG0(CLK_INFRA_SEJ_13M, "infra_sej_13m", "clk26m", 7),
|
||||
GATE_ICG0(CLK_INFRA_ICUSB, "infra_icusb", "usb20_sel", 8),
|
||||
GATE_ICG0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 9),
|
||||
GATE_ICG0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10),
|
||||
GATE_ICG0(CLK_INFRA_I2C0, "infra_i2c0", "axi_sel", 11),
|
||||
GATE_ICG0(CLK_INFRA_I2C1, "infra_i2c1", "axi_sel", 12),
|
||||
GATE_ICG0(CLK_INFRA_I2C2, "infra_i2c2", "axi_sel", 13),
|
||||
GATE_ICG0(CLK_INFRA_I2C3, "infra_i2c3", "axi_sel", 14),
|
||||
GATE_ICG0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", "axi_sel", 15),
|
||||
GATE_ICG0(CLK_INFRA_PWM1, "infra_pwm1", "axi_sel", 16),
|
||||
GATE_ICG0(CLK_INFRA_PWM2, "infra_pwm2", "axi_sel", 17),
|
||||
GATE_ICG0(CLK_INFRA_PWM3, "infra_pwm3", "axi_sel", 18),
|
||||
GATE_ICG0(CLK_INFRA_PWM4, "infra_pwm4", "axi_sel", 19),
|
||||
GATE_ICG0(CLK_INFRA_PWM, "infra_pwm", "axi_sel", 21),
|
||||
GATE_ICG0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22),
|
||||
GATE_ICG0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23),
|
||||
GATE_ICG0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24),
|
||||
GATE_ICG0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25),
|
||||
GATE_ICG0(CLK_INFRA_MD2MD_CCIF_0, "infra_md2md_ccif_0", "axi_sel", 27),
|
||||
GATE_ICG0(CLK_INFRA_MD2MD_CCIF_1, "infra_md2md_ccif_1", "axi_sel", 28),
|
||||
GATE_ICG0(CLK_INFRA_MD2MD_CCIF_2, "infra_md2md_ccif_2", "axi_sel", 29),
|
||||
GATE_ICG0(CLK_INFRA_FHCTL, "infra_fhctl", "clk26m", 30),
|
||||
GATE_ICG0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31),
|
||||
GATE_ICG1(CLK_INFRA_MD2MD_CCIF_3, "infra_md2md_ccif_3", "axi_sel", 0),
|
||||
GATE_ICG1(CLK_INFRA_SPI, "infra_spi", "spi_sel", 1),
|
||||
GATE_ICG1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_sel", 2),
|
||||
GATE_ICG1(CLK_INFRA_MD2MD_CCIF_4, "infra_md2md_ccif_4", "axi_sel", 3),
|
||||
GATE_ICG1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc30_1_sel", 4),
|
||||
GATE_ICG1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc30_2_sel", 5),
|
||||
GATE_ICG1(CLK_INFRA_MD2MD_CCIF_5, "infra_md2md_ccif_5", "axi_sel", 7),
|
||||
GATE_ICG1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8),
|
||||
GATE_ICG1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9),
|
||||
GATE_ICG1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10),
|
||||
GATE_ICG1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11),
|
||||
GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_0, "infra_ap_c2k_ccif_0",
|
||||
"axi_sel", 12),
|
||||
GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_1, "infra_ap_c2k_ccif_1",
|
||||
"axi_sel", 13),
|
||||
GATE_ICG1(CLK_INFRA_CLDMA, "infra_cldma", "axi_sel", 16),
|
||||
GATE_ICG1(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "pwm_sel", 17),
|
||||
GATE_ICG1(CLK_INFRA_AP_DMA, "infra_ap_dma", "axi_sel", 18),
|
||||
GATE_ICG1(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20),
|
||||
GATE_ICG1(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "mm_sel", 22),
|
||||
GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23),
|
||||
GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25),
|
||||
GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26),
|
||||
GATE_ICG1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31),
|
||||
GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4", "axi_sel", 0),
|
||||
GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm", "axi_sel", 1),
|
||||
GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm", "axi_sel", 2),
|
||||
GATE_ICG2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "axi_sel", 3),
|
||||
GATE_ICG2(CLK_INFRA_I2C2_ARB, "infra_i2c2_arb", "axi_sel", 4),
|
||||
GATE_ICG2(CLK_INFRA_I2C3_IMM, "infra_i2c3_imm", "axi_sel", 5),
|
||||
GATE_ICG2(CLK_INFRA_I2C3_ARB, "infra_i2c3_arb", "axi_sel", 6),
|
||||
GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5", "axi_sel", 7),
|
||||
GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq", "axi_sel", 8),
|
||||
GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 10),
|
||||
GATE_ICG2(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m", "clk26m", 11),
|
||||
GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32", "anc_md32_sel", 12),
|
||||
GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k", "clk26m", 13),
|
||||
GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1", "axi_sel", 15),
|
||||
GATE_ICG2(CLK_INFRA_AES_TOP0, "infra_aes_top0", "axi_sel", 16),
|
||||
GATE_ICG2(CLK_INFRA_AES_TOP1, "infra_aes_top1", "axi_sel", 17),
|
||||
GATE_ICG2(CLK_INFRA_SSUSB_BUS, "infra_ssusb_bus", "axi_sel", 18),
|
||||
GATE_ICG2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 19),
|
||||
GATE_ICG2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 20),
|
||||
GATE_ICG2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 21),
|
||||
GATE_ICG2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 22),
|
||||
GATE_ICG2(CLK_INFRA_IRTX, "infra_irtx", "spi_sel", 23),
|
||||
GATE_ICG2(CLK_INFRA_SSUSB_SYS, "infra_ssusb_sys",
|
||||
"ssusb_top_sys_sel", 24),
|
||||
GATE_ICG2(CLK_INFRA_SSUSB_REF, "infra_ssusb_ref", "clk26m", 9),
|
||||
GATE_ICG2(CLK_INFRA_AUDIO_26M, "infra_audio_26m", "clk26m", 26),
|
||||
GATE_ICG2(CLK_INFRA_AUDIO_26M_PAD_TOP, "infra_audio_26m_pad_top",
|
||||
"clk26m", 27),
|
||||
GATE_ICG2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share",
|
||||
"axi_sel", 28),
|
||||
GATE_ICG2(CLK_INFRA_VAD_WRAP_SOC, "infra_vad_wrap_soc", "axi_sel", 29),
|
||||
GATE_ICG2(CLK_INFRA_DRAMC_CONF, "infra_dramc_conf", "axi_sel", 30),
|
||||
GATE_ICG2(CLK_INFRA_DRAMC_B_CONF, "infra_dramc_b_conf", "axi_sel", 31),
|
||||
GATE_ICG1(CLK_INFRA_MFG_VCG, "infra_mfg_vcg", "mfg_52m_sel", 14),
|
||||
};
|
||||
|
||||
static const struct mtk_fixed_factor infra_fixed_divs[] = {
|
||||
FACTOR(CLK_INFRA_13M, "clk13m", "clk26m", 1, 2),
|
||||
};
|
||||
|
||||
static struct clk_onecell_data *infra_clk_data;
|
||||
|
||||
static void mtk_infrasys_init_early(struct device_node *node)
|
||||
{
|
||||
int r, i;
|
||||
|
||||
if (!infra_clk_data) {
|
||||
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
|
||||
|
||||
for (i = 0; i < CLK_INFRA_NR; i++)
|
||||
infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
|
||||
infra_clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
|
||||
if (r)
|
||||
pr_err("%s(): could not register clock provider: %d\n",
|
||||
__func__, r);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt6797-infracfg",
|
||||
mtk_infrasys_init_early);
|
||||
|
||||
static int mtk_infrasys_init(struct platform_device *pdev)
|
||||
{
|
||||
int r, i;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
if (!infra_clk_data) {
|
||||
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
|
||||
} else {
|
||||
for (i = 0; i < CLK_INFRA_NR; i++) {
|
||||
if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
|
||||
infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||
infra_clk_data);
|
||||
mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
|
||||
infra_clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MT6797_PLL_FMAX (3000UL * MHZ)
|
||||
|
||||
#define CON0_MT6797_RST_BAR BIT(24)
|
||||
|
||||
#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
|
||||
_pcw_shift, _div_table) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.reg = _reg, \
|
||||
.pwr_reg = _pwr_reg, \
|
||||
.en_mask = _en_mask, \
|
||||
.flags = _flags, \
|
||||
.rst_bar_mask = CON0_MT6797_RST_BAR, \
|
||||
.fmax = MT6797_PLL_FMAX, \
|
||||
.pcwbits = _pcwbits, \
|
||||
.pd_reg = _pd_reg, \
|
||||
.pd_shift = _pd_shift, \
|
||||
.tuner_reg = _tuner_reg, \
|
||||
.pcw_reg = _pcw_reg, \
|
||||
.pcw_shift = _pcw_shift, \
|
||||
.div_table = _div_table, \
|
||||
}
|
||||
|
||||
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
|
||||
_pcw_shift) \
|
||||
PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
|
||||
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
|
||||
NULL)
|
||||
|
||||
static const struct mtk_pll_data plls[] = {
|
||||
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000101, PLL_AO,
|
||||
21, 0x220, 4, 0x0, 0x224, 0),
|
||||
PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000011, 0, 7,
|
||||
0x230, 4, 0x0, 0x234, 14),
|
||||
PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000101, 0, 21,
|
||||
0x244, 24, 0x0, 0x244, 0),
|
||||
PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000121, 0, 21,
|
||||
0x250, 4, 0x0, 0x254, 0),
|
||||
PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000121, 0, 21,
|
||||
0x260, 4, 0x0, 0x264, 0),
|
||||
PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000121, 0, 21,
|
||||
0x270, 4, 0x0, 0x274, 0),
|
||||
PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000121, 0, 21,
|
||||
0x290, 4, 0x0, 0x294, 0),
|
||||
PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000121, 0, 21,
|
||||
0x2E4, 4, 0x0, 0x2E8, 0),
|
||||
PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000131, 0, 31,
|
||||
0x2A0, 4, 0x2A8, 0x2A4, 0),
|
||||
PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000131, 0, 31,
|
||||
0x2B4, 4, 0x2BC, 0x2B8, 0),
|
||||
};
|
||||
|
||||
static int mtk_apmixedsys_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
||||
|
||||
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt6797[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt6797-topckgen",
|
||||
.data = mtk_topckgen_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6797-infracfg",
|
||||
.data = mtk_infrasys_init,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6797-apmixedsys",
|
||||
.data = mtk_apmixedsys_init,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static int clk_mt6797_probe(struct platform_device *pdev)
|
||||
{
|
||||
int (*clk_init)(struct platform_device *);
|
||||
int r;
|
||||
|
||||
clk_init = of_device_get_match_data(&pdev->dev);
|
||||
if (!clk_init)
|
||||
return -EINVAL;
|
||||
|
||||
r = clk_init(pdev);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt6797_drv = {
|
||||
.probe = clk_mt6797_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt6797",
|
||||
.of_match_table = of_match_clk_mt6797,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init clk_mt6797_init(void)
|
||||
{
|
||||
return platform_driver_register(&clk_mt6797_drv);
|
||||
}
|
||||
|
||||
arch_initcall(clk_mt6797_init);
|
|
@ -2,6 +2,6 @@
|
|||
# Makefile for Meson specific clk
|
||||
#
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
|
||||
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
|
||||
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2017 AmLogic, Inc.
|
||||
* Author: Jerome Brunet <jbrunet@baylibre.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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i2s master clock divider: The algorithm of the generic clk-divider used with
|
||||
* a very precise clock parent such as the mpll tends to select a low divider
|
||||
* factor. This gives poor results with this particular divider, especially with
|
||||
* high frequencies (> 100 MHz)
|
||||
*
|
||||
* This driver try to select the maximum possible divider with the rate the
|
||||
* upstream clock can provide.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clkc.h"
|
||||
|
||||
#define to_meson_clk_audio_divider(_hw) container_of(_hw, \
|
||||
struct meson_clk_audio_divider, hw)
|
||||
|
||||
static int _div_round(unsigned long parent_rate, unsigned long rate,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (flags & CLK_DIVIDER_ROUND_CLOSEST)
|
||||
return DIV_ROUND_CLOSEST_ULL((u64)parent_rate, rate);
|
||||
|
||||
return DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||
}
|
||||
|
||||
static int _get_val(unsigned long parent_rate, unsigned long rate)
|
||||
{
|
||||
return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
|
||||
}
|
||||
|
||||
static int _valid_divider(struct clk_hw *hw, int divider)
|
||||
{
|
||||
struct meson_clk_audio_divider *adiv =
|
||||
to_meson_clk_audio_divider(hw);
|
||||
int max_divider;
|
||||
u8 width;
|
||||
|
||||
width = adiv->div.width;
|
||||
max_divider = 1 << width;
|
||||
|
||||
return clamp(divider, 1, max_divider);
|
||||
}
|
||||
|
||||
static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_audio_divider *adiv =
|
||||
to_meson_clk_audio_divider(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg, divider;
|
||||
|
||||
p = &adiv->div;
|
||||
reg = readl(adiv->base + p->reg_off);
|
||||
divider = PARM_GET(p->width, p->shift, reg) + 1;
|
||||
|
||||
return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
|
||||
}
|
||||
|
||||
static long audio_divider_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct meson_clk_audio_divider *adiv =
|
||||
to_meson_clk_audio_divider(hw);
|
||||
unsigned long max_prate;
|
||||
int divider;
|
||||
|
||||
if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
|
||||
divider = _div_round(*parent_rate, rate, adiv->flags);
|
||||
divider = _valid_divider(hw, divider);
|
||||
return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
|
||||
}
|
||||
|
||||
/* Get the maximum parent rate */
|
||||
max_prate = clk_hw_round_rate(clk_hw_get_parent(hw), ULONG_MAX);
|
||||
|
||||
/* Get the corresponding rounded down divider */
|
||||
divider = max_prate / rate;
|
||||
divider = _valid_divider(hw, divider);
|
||||
|
||||
/* Get actual rate of the parent */
|
||||
*parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||
divider * rate);
|
||||
|
||||
return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
|
||||
}
|
||||
|
||||
static int audio_divider_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_audio_divider *adiv =
|
||||
to_meson_clk_audio_divider(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg, flags = 0;
|
||||
int val;
|
||||
|
||||
val = _get_val(parent_rate, rate);
|
||||
|
||||
if (adiv->lock)
|
||||
spin_lock_irqsave(adiv->lock, flags);
|
||||
else
|
||||
__acquire(adiv->lock);
|
||||
|
||||
p = &adiv->div;
|
||||
reg = readl(adiv->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, val);
|
||||
writel(reg, adiv->base + p->reg_off);
|
||||
|
||||
if (adiv->lock)
|
||||
spin_unlock_irqrestore(adiv->lock, flags);
|
||||
else
|
||||
__release(adiv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops meson_clk_audio_divider_ro_ops = {
|
||||
.recalc_rate = audio_divider_recalc_rate,
|
||||
.round_rate = audio_divider_round_rate,
|
||||
};
|
||||
|
||||
const struct clk_ops meson_clk_audio_divider_ops = {
|
||||
.recalc_rate = audio_divider_recalc_rate,
|
||||
.round_rate = audio_divider_round_rate,
|
||||
.set_rate = audio_divider_set_rate,
|
||||
};
|
|
@ -64,17 +64,51 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include "clkc.h"
|
||||
|
||||
#define SDM_MAX 16384
|
||||
#define SDM_DEN 16384
|
||||
#define N2_MIN 4
|
||||
#define N2_MAX 511
|
||||
|
||||
#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
|
||||
|
||||
static long rate_from_params(unsigned long parent_rate,
|
||||
unsigned long sdm,
|
||||
unsigned long n2)
|
||||
{
|
||||
unsigned long divisor = (SDM_DEN * n2) + sdm;
|
||||
|
||||
if (n2 < N2_MIN)
|
||||
return -EINVAL;
|
||||
|
||||
return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
|
||||
}
|
||||
|
||||
static void params_from_rate(unsigned long requested_rate,
|
||||
unsigned long parent_rate,
|
||||
unsigned long *sdm,
|
||||
unsigned long *n2)
|
||||
{
|
||||
uint64_t div = parent_rate;
|
||||
unsigned long rem = do_div(div, requested_rate);
|
||||
|
||||
if (div < N2_MIN) {
|
||||
*n2 = N2_MIN;
|
||||
*sdm = 0;
|
||||
} else if (div > N2_MAX) {
|
||||
*n2 = N2_MAX;
|
||||
*sdm = SDM_DEN - 1;
|
||||
} else {
|
||||
*n2 = div;
|
||||
*sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long mpll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long rate = 0;
|
||||
unsigned long reg, sdm, n2;
|
||||
long rate;
|
||||
|
||||
p = &mpll->sdm;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
|
@ -84,11 +118,123 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw,
|
|||
reg = readl(mpll->base + p->reg_off);
|
||||
n2 = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
|
||||
rate = rate_from_params(parent_rate, sdm, n2);
|
||||
if (rate < 0)
|
||||
return 0;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static long mpll_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
unsigned long sdm, n2;
|
||||
|
||||
params_from_rate(rate, *parent_rate, &sdm, &n2);
|
||||
return rate_from_params(*parent_rate, sdm, n2);
|
||||
}
|
||||
|
||||
static int mpll_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg, sdm, n2;
|
||||
unsigned long flags = 0;
|
||||
|
||||
params_from_rate(rate, parent_rate, &sdm, &n2);
|
||||
|
||||
if (mpll->lock)
|
||||
spin_lock_irqsave(mpll->lock, flags);
|
||||
else
|
||||
__acquire(mpll->lock);
|
||||
|
||||
p = &mpll->sdm;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, sdm);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
p = &mpll->sdm_en;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, 1);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
p = &mpll->n2;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, n2);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
if (mpll->lock)
|
||||
spin_unlock_irqrestore(mpll->lock, flags);
|
||||
else
|
||||
__release(mpll->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpll_enable_core(struct clk_hw *hw, int enable)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (mpll->lock)
|
||||
spin_lock_irqsave(mpll->lock, flags);
|
||||
else
|
||||
__acquire(mpll->lock);
|
||||
|
||||
p = &mpll->en;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
|
||||
writel(reg, mpll->base + p->reg_off);
|
||||
|
||||
if (mpll->lock)
|
||||
spin_unlock_irqrestore(mpll->lock, flags);
|
||||
else
|
||||
__release(mpll->lock);
|
||||
}
|
||||
|
||||
|
||||
static int mpll_enable(struct clk_hw *hw)
|
||||
{
|
||||
mpll_enable_core(hw, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpll_disable(struct clk_hw *hw)
|
||||
{
|
||||
mpll_enable_core(hw, 0);
|
||||
}
|
||||
|
||||
static int mpll_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
|
||||
struct parm *p;
|
||||
unsigned long reg;
|
||||
int en;
|
||||
|
||||
p = &mpll->en;
|
||||
reg = readl(mpll->base + p->reg_off);
|
||||
en = PARM_GET(p->width, p->shift, reg);
|
||||
|
||||
return en;
|
||||
}
|
||||
|
||||
const struct clk_ops meson_clk_mpll_ro_ops = {
|
||||
.recalc_rate = mpll_recalc_rate,
|
||||
.recalc_rate = mpll_recalc_rate,
|
||||
.round_rate = mpll_round_rate,
|
||||
.is_enabled = mpll_is_enabled,
|
||||
};
|
||||
|
||||
const struct clk_ops meson_clk_mpll_ops = {
|
||||
.recalc_rate = mpll_recalc_rate,
|
||||
.round_rate = mpll_round_rate,
|
||||
.set_rate = mpll_set_rate,
|
||||
.enable = mpll_enable,
|
||||
.disable = mpll_disable,
|
||||
.is_enabled = mpll_is_enabled,
|
||||
};
|
||||
|
|
|
@ -116,6 +116,30 @@ static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Specific wait loop for GXL/GXM GP0 PLL */
|
||||
static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll,
|
||||
struct parm *p_n)
|
||||
{
|
||||
int delay = 100;
|
||||
u32 reg;
|
||||
|
||||
while (delay > 0) {
|
||||
reg = readl(pll->base + p_n->reg_off);
|
||||
writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off);
|
||||
udelay(10);
|
||||
writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off);
|
||||
|
||||
/* This delay comes from AMLogic tree clk-gp0-gxl driver */
|
||||
mdelay(1);
|
||||
|
||||
reg = readl(pll->base + p_n->reg_off);
|
||||
if (reg & MESON_PLL_LOCK)
|
||||
return 0;
|
||||
delay--;
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
|
||||
struct parm *p_n)
|
||||
{
|
||||
|
@ -132,6 +156,15 @@ static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void meson_clk_pll_init_params(struct meson_clk_pll *pll)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < pll->params.params_count ; ++i)
|
||||
writel(pll->params.params_table[i].value,
|
||||
pll->base + pll->params.params_table[i].reg_off);
|
||||
}
|
||||
|
||||
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
@ -151,10 +184,16 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
if (!rate_set)
|
||||
return -EINVAL;
|
||||
|
||||
/* Initialize the PLL in a clean state if specified */
|
||||
if (pll->params.params_count)
|
||||
meson_clk_pll_init_params(pll);
|
||||
|
||||
/* PLL reset */
|
||||
p = &pll->n;
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
/* If no_init_reset is provided, avoid resetting at this point */
|
||||
if (!pll->params.no_init_reset)
|
||||
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);
|
||||
|
@ -184,7 +223,17 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
}
|
||||
|
||||
p = &pll->n;
|
||||
ret = meson_clk_pll_wait_lock(pll, p);
|
||||
/* If clear_reset_for_lock is provided, remove the reset bit here */
|
||||
if (pll->params.clear_reset_for_lock) {
|
||||
reg = readl(pll->base + p->reg_off);
|
||||
writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
|
||||
}
|
||||
|
||||
/* If reset_lock_loop, use a special loop including resetting */
|
||||
if (pll->params.reset_lock_loop)
|
||||
ret = meson_clk_pll_wait_lock_reset(pll, p);
|
||||
else
|
||||
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);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#define PARM_GET(width, shift, reg) \
|
||||
(((reg) & SETPMASK(width, shift)) >> (shift))
|
||||
#define PARM_SET(width, shift, reg, val) \
|
||||
(((reg) & CLRPMASK(width, shift)) | (val << (shift)))
|
||||
(((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
|
||||
|
||||
#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
|
||||
|
||||
|
@ -62,6 +62,28 @@ struct pll_rate_table {
|
|||
.frac = (_frac), \
|
||||
} \
|
||||
|
||||
struct pll_params_table {
|
||||
unsigned int reg_off;
|
||||
unsigned int value;
|
||||
};
|
||||
|
||||
#define PLL_PARAM(_reg, _val) \
|
||||
{ \
|
||||
.reg_off = (_reg), \
|
||||
.value = (_val), \
|
||||
}
|
||||
|
||||
struct pll_setup_params {
|
||||
struct pll_params_table *params_table;
|
||||
unsigned int params_count;
|
||||
/* Workaround for GP0, do not reset before configuring */
|
||||
bool no_init_reset;
|
||||
/* Workaround for GP0, unreset right before checking for lock */
|
||||
bool clear_reset_for_lock;
|
||||
/* Workaround for GXL GP0, reset in the lock checking loop */
|
||||
bool reset_lock_loop;
|
||||
};
|
||||
|
||||
struct meson_clk_pll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
|
@ -70,6 +92,7 @@ struct meson_clk_pll {
|
|||
struct parm frac;
|
||||
struct parm od;
|
||||
struct parm od2;
|
||||
const struct pll_setup_params params;
|
||||
const struct pll_rate_table *rate_table;
|
||||
unsigned int rate_count;
|
||||
spinlock_t *lock;
|
||||
|
@ -92,8 +115,17 @@ struct meson_clk_mpll {
|
|||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
struct parm sdm;
|
||||
struct parm sdm_en;
|
||||
struct parm n2;
|
||||
/* FIXME ssen gate control? */
|
||||
struct parm en;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
struct meson_clk_audio_divider {
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
struct parm div;
|
||||
u8 flags;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
|
@ -116,5 +148,8 @@ extern const struct clk_ops meson_clk_pll_ro_ops;
|
|||
extern const struct clk_ops meson_clk_pll_ops;
|
||||
extern const struct clk_ops meson_clk_cpu_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ro_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ops;
|
||||
extern const struct clk_ops meson_clk_audio_divider_ro_ops;
|
||||
extern const struct clk_ops meson_clk_audio_divider_ops;
|
||||
|
||||
#endif /* __CLKC_H */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
|
@ -120,7 +121,7 @@ static const struct pll_rate_table sys_pll_rate_table[] = {
|
|||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct pll_rate_table gp0_pll_rate_table[] = {
|
||||
static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
|
||||
PLL_RATE(96000000, 32, 1, 3),
|
||||
PLL_RATE(99000000, 33, 1, 3),
|
||||
PLL_RATE(102000000, 34, 1, 3),
|
||||
|
@ -248,6 +249,35 @@ static const struct pll_rate_table gp0_pll_rate_table[] = {
|
|||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
|
||||
PLL_RATE(504000000, 42, 1, 1),
|
||||
PLL_RATE(516000000, 43, 1, 1),
|
||||
PLL_RATE(528000000, 44, 1, 1),
|
||||
PLL_RATE(540000000, 45, 1, 1),
|
||||
PLL_RATE(552000000, 46, 1, 1),
|
||||
PLL_RATE(564000000, 47, 1, 1),
|
||||
PLL_RATE(576000000, 48, 1, 1),
|
||||
PLL_RATE(588000000, 49, 1, 1),
|
||||
PLL_RATE(600000000, 50, 1, 1),
|
||||
PLL_RATE(612000000, 51, 1, 1),
|
||||
PLL_RATE(624000000, 52, 1, 1),
|
||||
PLL_RATE(636000000, 53, 1, 1),
|
||||
PLL_RATE(648000000, 54, 1, 1),
|
||||
PLL_RATE(660000000, 55, 1, 1),
|
||||
PLL_RATE(672000000, 56, 1, 1),
|
||||
PLL_RATE(684000000, 57, 1, 1),
|
||||
PLL_RATE(696000000, 58, 1, 1),
|
||||
PLL_RATE(708000000, 59, 1, 1),
|
||||
PLL_RATE(720000000, 60, 1, 1),
|
||||
PLL_RATE(732000000, 61, 1, 1),
|
||||
PLL_RATE(744000000, 62, 1, 1),
|
||||
PLL_RATE(756000000, 63, 1, 1),
|
||||
PLL_RATE(768000000, 64, 1, 1),
|
||||
PLL_RATE(780000000, 65, 1, 1),
|
||||
PLL_RATE(792000000, 66, 1, 1),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct clk_div_table cpu_div_table[] = {
|
||||
{ .val = 1, .div = 1 },
|
||||
{ .val = 2, .div = 2 },
|
||||
|
@ -352,6 +382,13 @@ static struct meson_clk_pll gxbb_sys_pll = {
|
|||
},
|
||||
};
|
||||
|
||||
struct pll_params_table gxbb_gp0_params_table[] = {
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d),
|
||||
};
|
||||
|
||||
static struct meson_clk_pll gxbb_gp0_pll = {
|
||||
.m = {
|
||||
.reg_off = HHI_GP0_PLL_CNTL,
|
||||
|
@ -368,8 +405,57 @@ static struct meson_clk_pll gxbb_gp0_pll = {
|
|||
.shift = 16,
|
||||
.width = 2,
|
||||
},
|
||||
.rate_table = gp0_pll_rate_table,
|
||||
.rate_count = ARRAY_SIZE(gp0_pll_rate_table),
|
||||
.params = {
|
||||
.params_table = gxbb_gp0_params_table,
|
||||
.params_count = ARRAY_SIZE(gxbb_gp0_params_table),
|
||||
.no_init_reset = true,
|
||||
.clear_reset_for_lock = true,
|
||||
},
|
||||
.rate_table = gxbb_gp0_pll_rate_table,
|
||||
.rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table),
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gp0_pll",
|
||||
.ops = &meson_clk_pll_ops,
|
||||
.parent_names = (const char *[]){ "xtal" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
struct pll_params_table gxl_gp0_params_table[] = {
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
|
||||
PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
|
||||
};
|
||||
|
||||
static struct meson_clk_pll gxl_gp0_pll = {
|
||||
.m = {
|
||||
.reg_off = HHI_GP0_PLL_CNTL,
|
||||
.shift = 0,
|
||||
.width = 9,
|
||||
},
|
||||
.n = {
|
||||
.reg_off = HHI_GP0_PLL_CNTL,
|
||||
.shift = 9,
|
||||
.width = 5,
|
||||
},
|
||||
.od = {
|
||||
.reg_off = HHI_GP0_PLL_CNTL,
|
||||
.shift = 16,
|
||||
.width = 2,
|
||||
},
|
||||
.params = {
|
||||
.params_table = gxl_gp0_params_table,
|
||||
.params_count = ARRAY_SIZE(gxl_gp0_params_table),
|
||||
.no_init_reset = true,
|
||||
.reset_lock_loop = true,
|
||||
},
|
||||
.rate_table = gxl_gp0_pll_rate_table,
|
||||
.rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table),
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gp0_pll",
|
||||
|
@ -441,15 +527,25 @@ static struct meson_clk_mpll gxbb_mpll0 = {
|
|||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
.ops = &meson_clk_mpll_ro_ops,
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
|
@ -461,15 +557,25 @@ static struct meson_clk_mpll gxbb_mpll1 = {
|
|||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll1",
|
||||
.ops = &meson_clk_mpll_ro_ops,
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
|
@ -481,15 +587,25 @@ static struct meson_clk_mpll gxbb_mpll2 = {
|
|||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll2",
|
||||
.ops = &meson_clk_mpll_ro_ops,
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
|
@ -604,6 +720,237 @@ static struct clk_gate gxbb_sar_adc_clk = {
|
|||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
|
||||
* muxed by a glitch-free switch.
|
||||
*/
|
||||
|
||||
static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
static const char *gxbb_mali_0_1_parent_names[] = {
|
||||
"xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
|
||||
"fclk_div4", "fclk_div3", "fclk_div5"
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_mali_0_sel = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.table = mux_table_mali_0_1,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali_0_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bits 10:9 selects from 8 possible parents:
|
||||
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
|
||||
* fclk_div4, fclk_div3, fclk_div5
|
||||
*/
|
||||
.parent_names = gxbb_mali_0_1_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_mali_0_div = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali_0_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "mali_0_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_mali_0 = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali_0",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "mali_0_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_mali_1_sel = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 25,
|
||||
.table = mux_table_mali_0_1,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali_1_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
/*
|
||||
* bits 10:9 selects from 8 possible parents:
|
||||
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
|
||||
* fclk_div4, fclk_div3, fclk_div5
|
||||
*/
|
||||
.parent_names = gxbb_mali_0_1_parent_names,
|
||||
.num_parents = 8,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_mali_1_div = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.shift = 16,
|
||||
.width = 7,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali_1_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "mali_1_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_mali_1 = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali_1",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "mali_1_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_mali[] = {0, 1};
|
||||
static const char *gxbb_mali_parent_names[] = {
|
||||
"mali_0", "mali_1"
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_mali = {
|
||||
.reg = (void *)HHI_MALI_CLK_CNTL,
|
||||
.mask = 1,
|
||||
.shift = 31,
|
||||
.table = mux_table_mali,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mali",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = gxbb_mali_parent_names,
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_cts_amclk_sel = {
|
||||
.reg = (void *) HHI_AUD_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
/* Default parent unknown (register reset value: 0) */
|
||||
.table = (u32[]){ 1, 2, 3 },
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_amclk_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
|
||||
.num_parents = 3,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
|
||||
.div = {
|
||||
.reg_off = HHI_AUD_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_amclk_div",
|
||||
.ops = &meson_clk_audio_divider_ops,
|
||||
.parent_names = (const char *[]){ "cts_amclk_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_cts_amclk = {
|
||||
.reg = (void *) HHI_AUD_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_amclk",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "cts_amclk_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_cts_mclk_i958_sel = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.mask = 0x3,
|
||||
.shift = 25,
|
||||
/* Default parent unknown (register reset value: 0) */
|
||||
.table = (u32[]){ 1, 2, 3 },
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_mclk_i958_sel",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
|
||||
.num_parents = 3,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_divider gxbb_cts_mclk_i958_div = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.shift = 16,
|
||||
.width = 8,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_mclk_i958_div",
|
||||
.ops = &clk_divider_ops,
|
||||
.parent_names = (const char *[]){ "cts_mclk_i958_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_gate gxbb_cts_mclk_i958 = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.bit_idx = 24,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_mclk_i958",
|
||||
.ops = &clk_gate_ops,
|
||||
.parent_names = (const char *[]){ "cts_mclk_i958_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_mux gxbb_cts_i958 = {
|
||||
.reg = (void *)HHI_AUD_CLK_CNTL2,
|
||||
.mask = 0x1,
|
||||
.shift = 27,
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_i958",
|
||||
.ops = &clk_mux_ops,
|
||||
.parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
|
||||
.num_parents = 2,
|
||||
/*
|
||||
*The parent is specific to origin of the audio data. Let the
|
||||
* consumer choose the appropriate parent
|
||||
*/
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
|
||||
},
|
||||
};
|
||||
|
||||
/* Everything Else (EE) domain gates */
|
||||
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
|
||||
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
|
||||
|
@ -797,6 +1144,140 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
|
|||
[CLKID_SAR_ADC_CLK] = &gxbb_sar_adc_clk.hw,
|
||||
[CLKID_SAR_ADC_SEL] = &gxbb_sar_adc_clk_sel.hw,
|
||||
[CLKID_SAR_ADC_DIV] = &gxbb_sar_adc_clk_div.hw,
|
||||
[CLKID_MALI_0_SEL] = &gxbb_mali_0_sel.hw,
|
||||
[CLKID_MALI_0_DIV] = &gxbb_mali_0_div.hw,
|
||||
[CLKID_MALI_0] = &gxbb_mali_0.hw,
|
||||
[CLKID_MALI_1_SEL] = &gxbb_mali_1_sel.hw,
|
||||
[CLKID_MALI_1_DIV] = &gxbb_mali_1_div.hw,
|
||||
[CLKID_MALI_1] = &gxbb_mali_1.hw,
|
||||
[CLKID_MALI] = &gxbb_mali.hw,
|
||||
[CLKID_CTS_AMCLK] = &gxbb_cts_amclk.hw,
|
||||
[CLKID_CTS_AMCLK_SEL] = &gxbb_cts_amclk_sel.hw,
|
||||
[CLKID_CTS_AMCLK_DIV] = &gxbb_cts_amclk_div.hw,
|
||||
[CLKID_CTS_MCLK_I958] = &gxbb_cts_mclk_i958.hw,
|
||||
[CLKID_CTS_MCLK_I958_SEL] = &gxbb_cts_mclk_i958_sel.hw,
|
||||
[CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw,
|
||||
[CLKID_CTS_I958] = &gxbb_cts_i958.hw,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data gxl_hw_onecell_data = {
|
||||
.hws = {
|
||||
[CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
|
||||
[CLKID_CPUCLK] = &gxbb_cpu_clk.hw,
|
||||
[CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw,
|
||||
[CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
|
||||
[CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
|
||||
[CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw,
|
||||
[CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw,
|
||||
[CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw,
|
||||
[CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw,
|
||||
[CLKID_GP0_PLL] = &gxl_gp0_pll.hw,
|
||||
[CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw,
|
||||
[CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw,
|
||||
[CLKID_CLK81] = &gxbb_clk81.hw,
|
||||
[CLKID_MPLL0] = &gxbb_mpll0.hw,
|
||||
[CLKID_MPLL1] = &gxbb_mpll1.hw,
|
||||
[CLKID_MPLL2] = &gxbb_mpll2.hw,
|
||||
[CLKID_DDR] = &gxbb_ddr.hw,
|
||||
[CLKID_DOS] = &gxbb_dos.hw,
|
||||
[CLKID_ISA] = &gxbb_isa.hw,
|
||||
[CLKID_PL301] = &gxbb_pl301.hw,
|
||||
[CLKID_PERIPHS] = &gxbb_periphs.hw,
|
||||
[CLKID_SPICC] = &gxbb_spicc.hw,
|
||||
[CLKID_I2C] = &gxbb_i2c.hw,
|
||||
[CLKID_SAR_ADC] = &gxbb_sar_adc.hw,
|
||||
[CLKID_SMART_CARD] = &gxbb_smart_card.hw,
|
||||
[CLKID_RNG0] = &gxbb_rng0.hw,
|
||||
[CLKID_UART0] = &gxbb_uart0.hw,
|
||||
[CLKID_SDHC] = &gxbb_sdhc.hw,
|
||||
[CLKID_STREAM] = &gxbb_stream.hw,
|
||||
[CLKID_ASYNC_FIFO] = &gxbb_async_fifo.hw,
|
||||
[CLKID_SDIO] = &gxbb_sdio.hw,
|
||||
[CLKID_ABUF] = &gxbb_abuf.hw,
|
||||
[CLKID_HIU_IFACE] = &gxbb_hiu_iface.hw,
|
||||
[CLKID_ASSIST_MISC] = &gxbb_assist_misc.hw,
|
||||
[CLKID_SPI] = &gxbb_spi.hw,
|
||||
[CLKID_I2S_SPDIF] = &gxbb_i2s_spdif.hw,
|
||||
[CLKID_ETH] = &gxbb_eth.hw,
|
||||
[CLKID_DEMUX] = &gxbb_demux.hw,
|
||||
[CLKID_AIU_GLUE] = &gxbb_aiu_glue.hw,
|
||||
[CLKID_IEC958] = &gxbb_iec958.hw,
|
||||
[CLKID_I2S_OUT] = &gxbb_i2s_out.hw,
|
||||
[CLKID_AMCLK] = &gxbb_amclk.hw,
|
||||
[CLKID_AIFIFO2] = &gxbb_aififo2.hw,
|
||||
[CLKID_MIXER] = &gxbb_mixer.hw,
|
||||
[CLKID_MIXER_IFACE] = &gxbb_mixer_iface.hw,
|
||||
[CLKID_ADC] = &gxbb_adc.hw,
|
||||
[CLKID_BLKMV] = &gxbb_blkmv.hw,
|
||||
[CLKID_AIU] = &gxbb_aiu.hw,
|
||||
[CLKID_UART1] = &gxbb_uart1.hw,
|
||||
[CLKID_G2D] = &gxbb_g2d.hw,
|
||||
[CLKID_USB0] = &gxbb_usb0.hw,
|
||||
[CLKID_USB1] = &gxbb_usb1.hw,
|
||||
[CLKID_RESET] = &gxbb_reset.hw,
|
||||
[CLKID_NAND] = &gxbb_nand.hw,
|
||||
[CLKID_DOS_PARSER] = &gxbb_dos_parser.hw,
|
||||
[CLKID_USB] = &gxbb_usb.hw,
|
||||
[CLKID_VDIN1] = &gxbb_vdin1.hw,
|
||||
[CLKID_AHB_ARB0] = &gxbb_ahb_arb0.hw,
|
||||
[CLKID_EFUSE] = &gxbb_efuse.hw,
|
||||
[CLKID_BOOT_ROM] = &gxbb_boot_rom.hw,
|
||||
[CLKID_AHB_DATA_BUS] = &gxbb_ahb_data_bus.hw,
|
||||
[CLKID_AHB_CTRL_BUS] = &gxbb_ahb_ctrl_bus.hw,
|
||||
[CLKID_HDMI_INTR_SYNC] = &gxbb_hdmi_intr_sync.hw,
|
||||
[CLKID_HDMI_PCLK] = &gxbb_hdmi_pclk.hw,
|
||||
[CLKID_USB1_DDR_BRIDGE] = &gxbb_usb1_ddr_bridge.hw,
|
||||
[CLKID_USB0_DDR_BRIDGE] = &gxbb_usb0_ddr_bridge.hw,
|
||||
[CLKID_MMC_PCLK] = &gxbb_mmc_pclk.hw,
|
||||
[CLKID_DVIN] = &gxbb_dvin.hw,
|
||||
[CLKID_UART2] = &gxbb_uart2.hw,
|
||||
[CLKID_SANA] = &gxbb_sana.hw,
|
||||
[CLKID_VPU_INTR] = &gxbb_vpu_intr.hw,
|
||||
[CLKID_SEC_AHB_AHB3_BRIDGE] = &gxbb_sec_ahb_ahb3_bridge.hw,
|
||||
[CLKID_CLK81_A53] = &gxbb_clk81_a53.hw,
|
||||
[CLKID_VCLK2_VENCI0] = &gxbb_vclk2_venci0.hw,
|
||||
[CLKID_VCLK2_VENCI1] = &gxbb_vclk2_venci1.hw,
|
||||
[CLKID_VCLK2_VENCP0] = &gxbb_vclk2_vencp0.hw,
|
||||
[CLKID_VCLK2_VENCP1] = &gxbb_vclk2_vencp1.hw,
|
||||
[CLKID_GCLK_VENCI_INT0] = &gxbb_gclk_venci_int0.hw,
|
||||
[CLKID_GCLK_VENCI_INT] = &gxbb_gclk_vencp_int.hw,
|
||||
[CLKID_DAC_CLK] = &gxbb_dac_clk.hw,
|
||||
[CLKID_AOCLK_GATE] = &gxbb_aoclk_gate.hw,
|
||||
[CLKID_IEC958_GATE] = &gxbb_iec958_gate.hw,
|
||||
[CLKID_ENC480P] = &gxbb_enc480p.hw,
|
||||
[CLKID_RNG1] = &gxbb_rng1.hw,
|
||||
[CLKID_GCLK_VENCI_INT1] = &gxbb_gclk_venci_int1.hw,
|
||||
[CLKID_VCLK2_VENCLMCC] = &gxbb_vclk2_venclmcc.hw,
|
||||
[CLKID_VCLK2_VENCL] = &gxbb_vclk2_vencl.hw,
|
||||
[CLKID_VCLK_OTHER] = &gxbb_vclk_other.hw,
|
||||
[CLKID_EDP] = &gxbb_edp.hw,
|
||||
[CLKID_AO_MEDIA_CPU] = &gxbb_ao_media_cpu.hw,
|
||||
[CLKID_AO_AHB_SRAM] = &gxbb_ao_ahb_sram.hw,
|
||||
[CLKID_AO_AHB_BUS] = &gxbb_ao_ahb_bus.hw,
|
||||
[CLKID_AO_IFACE] = &gxbb_ao_iface.hw,
|
||||
[CLKID_AO_I2C] = &gxbb_ao_i2c.hw,
|
||||
[CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw,
|
||||
[CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw,
|
||||
[CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw,
|
||||
[CLKID_SAR_ADC_CLK] = &gxbb_sar_adc_clk.hw,
|
||||
[CLKID_SAR_ADC_SEL] = &gxbb_sar_adc_clk_sel.hw,
|
||||
[CLKID_SAR_ADC_DIV] = &gxbb_sar_adc_clk_div.hw,
|
||||
[CLKID_MALI_0_SEL] = &gxbb_mali_0_sel.hw,
|
||||
[CLKID_MALI_0_DIV] = &gxbb_mali_0_div.hw,
|
||||
[CLKID_MALI_0] = &gxbb_mali_0.hw,
|
||||
[CLKID_MALI_1_SEL] = &gxbb_mali_1_sel.hw,
|
||||
[CLKID_MALI_1_DIV] = &gxbb_mali_1_div.hw,
|
||||
[CLKID_MALI_1] = &gxbb_mali_1.hw,
|
||||
[CLKID_MALI] = &gxbb_mali.hw,
|
||||
[CLKID_CTS_AMCLK] = &gxbb_cts_amclk.hw,
|
||||
[CLKID_CTS_AMCLK_SEL] = &gxbb_cts_amclk_sel.hw,
|
||||
[CLKID_CTS_AMCLK_DIV] = &gxbb_cts_amclk_div.hw,
|
||||
[CLKID_CTS_MCLK_I958] = &gxbb_cts_mclk_i958.hw,
|
||||
[CLKID_CTS_MCLK_I958_SEL] = &gxbb_cts_mclk_i958_sel.hw,
|
||||
[CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw,
|
||||
[CLKID_CTS_I958] = &gxbb_cts_i958.hw,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
};
|
||||
|
@ -810,13 +1291,20 @@ static struct meson_clk_pll *const gxbb_clk_plls[] = {
|
|||
&gxbb_gp0_pll,
|
||||
};
|
||||
|
||||
static struct meson_clk_pll *const gxl_clk_plls[] = {
|
||||
&gxbb_fixed_pll,
|
||||
&gxbb_hdmi_pll,
|
||||
&gxbb_sys_pll,
|
||||
&gxl_gp0_pll,
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll *const gxbb_clk_mplls[] = {
|
||||
&gxbb_mpll0,
|
||||
&gxbb_mpll1,
|
||||
&gxbb_mpll2,
|
||||
};
|
||||
|
||||
static struct clk_gate *gxbb_clk_gates[] = {
|
||||
static struct clk_gate *const gxbb_clk_gates[] = {
|
||||
&gxbb_clk81,
|
||||
&gxbb_ddr,
|
||||
&gxbb_dos,
|
||||
|
@ -900,16 +1388,105 @@ static struct clk_gate *gxbb_clk_gates[] = {
|
|||
&gxbb_emmc_b,
|
||||
&gxbb_emmc_c,
|
||||
&gxbb_sar_adc_clk,
|
||||
&gxbb_mali_0,
|
||||
&gxbb_mali_1,
|
||||
&gxbb_cts_amclk,
|
||||
&gxbb_cts_mclk_i958,
|
||||
};
|
||||
|
||||
static struct clk_mux *const gxbb_clk_muxes[] = {
|
||||
&gxbb_mpeg_clk_sel,
|
||||
&gxbb_sar_adc_clk_sel,
|
||||
&gxbb_mali_0_sel,
|
||||
&gxbb_mali_1_sel,
|
||||
&gxbb_mali,
|
||||
&gxbb_cts_amclk_sel,
|
||||
&gxbb_cts_mclk_i958_sel,
|
||||
&gxbb_cts_i958,
|
||||
};
|
||||
|
||||
static struct clk_divider *const gxbb_clk_dividers[] = {
|
||||
&gxbb_mpeg_clk_div,
|
||||
&gxbb_sar_adc_clk_div,
|
||||
&gxbb_mali_0_div,
|
||||
&gxbb_mali_1_div,
|
||||
&gxbb_cts_mclk_i958_div,
|
||||
};
|
||||
|
||||
static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
|
||||
&gxbb_cts_amclk_div,
|
||||
};
|
||||
|
||||
struct clkc_data {
|
||||
struct clk_gate *const *clk_gates;
|
||||
unsigned int clk_gates_count;
|
||||
struct meson_clk_mpll *const *clk_mplls;
|
||||
unsigned int clk_mplls_count;
|
||||
struct meson_clk_pll *const *clk_plls;
|
||||
unsigned int clk_plls_count;
|
||||
struct clk_mux *const *clk_muxes;
|
||||
unsigned int clk_muxes_count;
|
||||
struct clk_divider *const *clk_dividers;
|
||||
unsigned int clk_dividers_count;
|
||||
struct meson_clk_audio_divider *const *clk_audio_dividers;
|
||||
unsigned int clk_audio_dividers_count;
|
||||
struct meson_clk_cpu *cpu_clk;
|
||||
struct clk_hw_onecell_data *hw_onecell_data;
|
||||
};
|
||||
|
||||
static const struct clkc_data gxbb_clkc_data = {
|
||||
.clk_gates = gxbb_clk_gates,
|
||||
.clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
|
||||
.clk_mplls = gxbb_clk_mplls,
|
||||
.clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
|
||||
.clk_plls = gxbb_clk_plls,
|
||||
.clk_plls_count = ARRAY_SIZE(gxbb_clk_plls),
|
||||
.clk_muxes = gxbb_clk_muxes,
|
||||
.clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
|
||||
.clk_dividers = gxbb_clk_dividers,
|
||||
.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
|
||||
.clk_audio_dividers = gxbb_audio_dividers,
|
||||
.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
|
||||
.cpu_clk = &gxbb_cpu_clk,
|
||||
.hw_onecell_data = &gxbb_hw_onecell_data,
|
||||
};
|
||||
|
||||
static const struct clkc_data gxl_clkc_data = {
|
||||
.clk_gates = gxbb_clk_gates,
|
||||
.clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
|
||||
.clk_mplls = gxbb_clk_mplls,
|
||||
.clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
|
||||
.clk_plls = gxl_clk_plls,
|
||||
.clk_plls_count = ARRAY_SIZE(gxl_clk_plls),
|
||||
.clk_muxes = gxbb_clk_muxes,
|
||||
.clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
|
||||
.clk_dividers = gxbb_clk_dividers,
|
||||
.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
|
||||
.clk_audio_dividers = gxbb_audio_dividers,
|
||||
.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
|
||||
.cpu_clk = &gxbb_cpu_clk,
|
||||
.hw_onecell_data = &gxl_hw_onecell_data,
|
||||
};
|
||||
|
||||
static const struct of_device_id clkc_match_table[] = {
|
||||
{ .compatible = "amlogic,gxbb-clkc", .data = &gxbb_clkc_data },
|
||||
{ .compatible = "amlogic,gxl-clkc", .data = &gxl_clkc_data },
|
||||
{},
|
||||
};
|
||||
|
||||
static int gxbb_clkc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct clkc_data *clkc_data;
|
||||
void __iomem *clk_base;
|
||||
int ret, clkid, i;
|
||||
struct clk_hw *parent_hw;
|
||||
struct clk *parent_clk;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
clkc_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!clkc_data)
|
||||
return -EINVAL;
|
||||
|
||||
/* Generic clocks and PLLs */
|
||||
clk_base = of_iomap(dev->of_node, 0);
|
||||
if (!clk_base) {
|
||||
|
@ -918,34 +1495,45 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Populate base address for PLLs */
|
||||
for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++)
|
||||
gxbb_clk_plls[i]->base = clk_base;
|
||||
for (i = 0; i < clkc_data->clk_plls_count; i++)
|
||||
clkc_data->clk_plls[i]->base = clk_base;
|
||||
|
||||
/* Populate base address for MPLLs */
|
||||
for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++)
|
||||
gxbb_clk_mplls[i]->base = clk_base;
|
||||
for (i = 0; i < clkc_data->clk_mplls_count; i++)
|
||||
clkc_data->clk_mplls[i]->base = clk_base;
|
||||
|
||||
/* Populate the base address for CPU clk */
|
||||
gxbb_cpu_clk.base = clk_base;
|
||||
|
||||
/* Populate the base address for the MPEG clks */
|
||||
gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
|
||||
gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
|
||||
|
||||
/* Populate the base address for the SAR ADC clks */
|
||||
gxbb_sar_adc_clk_sel.reg = clk_base + (u64)gxbb_sar_adc_clk_sel.reg;
|
||||
gxbb_sar_adc_clk_div.reg = clk_base + (u64)gxbb_sar_adc_clk_div.reg;
|
||||
clkc_data->cpu_clk->base = clk_base;
|
||||
|
||||
/* Populate base address for gates */
|
||||
for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
|
||||
gxbb_clk_gates[i]->reg = clk_base +
|
||||
(u64)gxbb_clk_gates[i]->reg;
|
||||
for (i = 0; i < clkc_data->clk_gates_count; i++)
|
||||
clkc_data->clk_gates[i]->reg = clk_base +
|
||||
(u64)clkc_data->clk_gates[i]->reg;
|
||||
|
||||
/* Populate base address for muxes */
|
||||
for (i = 0; i < clkc_data->clk_muxes_count; i++)
|
||||
clkc_data->clk_muxes[i]->reg = clk_base +
|
||||
(u64)clkc_data->clk_muxes[i]->reg;
|
||||
|
||||
/* Populate base address for dividers */
|
||||
for (i = 0; i < clkc_data->clk_dividers_count; i++)
|
||||
clkc_data->clk_dividers[i]->reg = clk_base +
|
||||
(u64)clkc_data->clk_dividers[i]->reg;
|
||||
|
||||
/* Populate base address for the audio dividers */
|
||||
for (i = 0; i < clkc_data->clk_audio_dividers_count; i++)
|
||||
clkc_data->clk_audio_dividers[i]->base = clk_base;
|
||||
|
||||
/*
|
||||
* register all clks
|
||||
*/
|
||||
for (clkid = 0; clkid < NR_CLKS; clkid++) {
|
||||
ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]);
|
||||
for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
|
||||
/* array might be sparse */
|
||||
if (!clkc_data->hw_onecell_data->hws[clkid])
|
||||
continue;
|
||||
|
||||
ret = devm_clk_hw_register(dev,
|
||||
clkc_data->hw_onecell_data->hws[clkid]);
|
||||
if (ret)
|
||||
goto iounmap;
|
||||
}
|
||||
|
@ -964,9 +1552,9 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
|||
* a new clk_hw, and this hack will no longer work. Releasing the ccr
|
||||
* feature before that time solves the problem :-)
|
||||
*/
|
||||
parent_hw = clk_hw_get_parent(&gxbb_cpu_clk.hw);
|
||||
parent_hw = clk_hw_get_parent(&clkc_data->cpu_clk->hw);
|
||||
parent_clk = parent_hw->clk;
|
||||
ret = clk_notifier_register(parent_clk, &gxbb_cpu_clk.clk_nb);
|
||||
ret = clk_notifier_register(parent_clk, &clkc_data->cpu_clk->clk_nb);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register clock notifier for cpu_clk\n",
|
||||
__func__);
|
||||
|
@ -974,23 +1562,18 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
|
||||
&gxbb_hw_onecell_data);
|
||||
clkc_data->hw_onecell_data);
|
||||
|
||||
iounmap:
|
||||
iounmap(clk_base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id gxbb_clkc_match_table[] = {
|
||||
{ .compatible = "amlogic,gxbb-clkc" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver gxbb_driver = {
|
||||
.probe = gxbb_clkc_probe,
|
||||
.driver = {
|
||||
.name = "gxbb-clkc",
|
||||
.of_match_table = gxbb_clkc_match_table,
|
||||
.of_match_table = clkc_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
#define HHI_GP0_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */
|
||||
#define HHI_GP0_PLL_CNTL3 0x48 /* 0x12 offset in data sheet */
|
||||
#define HHI_GP0_PLL_CNTL4 0x4c /* 0x13 offset in data sheet */
|
||||
#define HHI_GP0_PLL_CNTL5 0x50 /* 0x14 offset in data sheet */
|
||||
#define HHI_GP0_PLL_CNTL1 0x58 /* 0x16 offset in data sheet */
|
||||
|
||||
#define HHI_XTAL_DIVN_CNTL 0xbc /* 0x2f offset in data sheet */
|
||||
#define HHI_TIMER90K 0xec /* 0x3b offset in data sheet */
|
||||
|
@ -275,8 +277,15 @@
|
|||
#define CLKID_MALI_1_DIV 104
|
||||
/* CLKID_MALI_1 */
|
||||
/* CLKID_MALI */
|
||||
#define CLKID_CTS_AMCLK 107
|
||||
#define CLKID_CTS_AMCLK_SEL 108
|
||||
#define CLKID_CTS_AMCLK_DIV 109
|
||||
#define CLKID_CTS_MCLK_I958 110
|
||||
#define CLKID_CTS_MCLK_I958_SEL 111
|
||||
#define CLKID_CTS_MCLK_I958_DIV 112
|
||||
#define CLKID_CTS_I958 113
|
||||
|
||||
#define NR_CLKS 107
|
||||
#define NR_CLKS 114
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
|
|
|
@ -245,6 +245,96 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll meson8b_mpll0 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL7,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll0",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll meson8b_mpll1 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL8,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll1",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct meson_clk_mpll meson8b_mpll2 = {
|
||||
.sdm = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 0,
|
||||
.width = 14,
|
||||
},
|
||||
.sdm_en = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 15,
|
||||
.width = 1,
|
||||
},
|
||||
.n2 = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 16,
|
||||
.width = 9,
|
||||
},
|
||||
.en = {
|
||||
.reg_off = HHI_MPLL_CNTL9,
|
||||
.shift = 14,
|
||||
.width = 1,
|
||||
},
|
||||
.lock = &clk_lock,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "mpll2",
|
||||
.ops = &meson_clk_mpll_ops,
|
||||
.parent_names = (const char *[]){ "fixed_pll" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
|
||||
* post-dividers and should be modeled with their respective PLLs via the
|
||||
|
@ -491,6 +581,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
|
|||
[CLKID_AO_AHB_SRAM] = &meson8b_ao_ahb_sram.hw,
|
||||
[CLKID_AO_AHB_BUS] = &meson8b_ao_ahb_bus.hw,
|
||||
[CLKID_AO_IFACE] = &meson8b_ao_iface.hw,
|
||||
[CLKID_MPLL0] = &meson8b_mpll0.hw,
|
||||
[CLKID_MPLL1] = &meson8b_mpll1.hw,
|
||||
[CLKID_MPLL2] = &meson8b_mpll2.hw,
|
||||
},
|
||||
.num = CLK_NR_CLKS,
|
||||
};
|
||||
|
@ -501,7 +594,13 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
|
|||
&meson8b_sys_pll,
|
||||
};
|
||||
|
||||
static struct clk_gate *meson8b_clk_gates[] = {
|
||||
static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
|
||||
&meson8b_mpll0,
|
||||
&meson8b_mpll1,
|
||||
&meson8b_mpll2,
|
||||
};
|
||||
|
||||
static struct clk_gate *const meson8b_clk_gates[] = {
|
||||
&meson8b_clk81,
|
||||
&meson8b_ddr,
|
||||
&meson8b_dos,
|
||||
|
@ -582,6 +681,14 @@ static struct clk_gate *meson8b_clk_gates[] = {
|
|||
&meson8b_ao_iface,
|
||||
};
|
||||
|
||||
static struct clk_mux *const meson8b_clk_muxes[] = {
|
||||
&meson8b_mpeg_clk_sel,
|
||||
};
|
||||
|
||||
static struct clk_divider *const meson8b_clk_dividers[] = {
|
||||
&meson8b_mpeg_clk_div,
|
||||
};
|
||||
|
||||
static int meson8b_clkc_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *clk_base;
|
||||
|
@ -601,18 +708,28 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
|
|||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
|
||||
meson8b_clk_plls[i]->base = clk_base;
|
||||
|
||||
/* Populate base address for MPLLs */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
|
||||
meson8b_clk_mplls[i]->base = clk_base;
|
||||
|
||||
/* Populate the base address for CPU clk */
|
||||
meson8b_cpu_clk.base = clk_base;
|
||||
|
||||
/* Populate the base address for the MPEG clks */
|
||||
meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg;
|
||||
meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
|
||||
|
||||
/* Populate base address for gates */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
|
||||
meson8b_clk_gates[i]->reg = clk_base +
|
||||
(u32)meson8b_clk_gates[i]->reg;
|
||||
|
||||
/* Populate base address for muxes */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
|
||||
meson8b_clk_muxes[i]->reg = clk_base +
|
||||
(u32)meson8b_clk_muxes[i]->reg;
|
||||
|
||||
/* Populate base address for dividers */
|
||||
for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
|
||||
meson8b_clk_dividers[i]->reg = clk_base +
|
||||
(u32)meson8b_clk_dividers[i]->reg;
|
||||
|
||||
/*
|
||||
* register all clks
|
||||
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
|
||||
|
|
|
@ -41,6 +41,21 @@
|
|||
#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */
|
||||
#define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
|
||||
|
||||
/*
|
||||
* MPLL register offeset taken from the S905 datasheet. Vendor kernel source
|
||||
* confirm these are the same for the S805.
|
||||
*/
|
||||
#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL2 0x284 /* 0xa1 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL3 0x288 /* 0xa2 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL4 0x28C /* 0xa3 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL5 0x290 /* 0xa4 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL6 0x294 /* 0xa5 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL7 0x298 /* 0xa6 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL8 0x29C /* 0xa7 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL9 0x2A0 /* 0xa8 offset in data sheet */
|
||||
#define HHI_MPLL_CNTL10 0x2A4 /* 0xa9 offset in data sheet */
|
||||
|
||||
/*
|
||||
* CLKID index values
|
||||
*
|
||||
|
@ -142,8 +157,11 @@
|
|||
#define CLKID_AO_AHB_SRAM 90
|
||||
#define CLKID_AO_AHB_BUS 91
|
||||
#define CLKID_AO_IFACE 92
|
||||
#define CLKID_MPLL0 93
|
||||
#define CLKID_MPLL1 94
|
||||
#define CLKID_MPLL2 95
|
||||
|
||||
#define CLK_NR_CLKS 93
|
||||
#define CLK_NR_CLKS 96
|
||||
|
||||
/* include the CLKIDs that have been made part of the stable DT binding */
|
||||
#include <dt-bindings/clock/meson8b-clkc.h>
|
||||
|
|
|
@ -186,11 +186,11 @@ static void __init of_cpu_clk_setup(struct device_node *node)
|
|||
for_each_node_by_type(dn, "cpu")
|
||||
ncpus++;
|
||||
|
||||
cpuclk = kzalloc(ncpus * sizeof(*cpuclk), GFP_KERNEL);
|
||||
cpuclk = kcalloc(ncpus, sizeof(*cpuclk), GFP_KERNEL);
|
||||
if (WARN_ON(!cpuclk))
|
||||
goto cpuclk_out;
|
||||
|
||||
clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
|
||||
clks = kcalloc(ncpus, sizeof(*clks), GFP_KERNEL);
|
||||
if (WARN_ON(!clks))
|
||||
goto clks_out;
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ void __init mvebu_coreclk_setup(struct device_node *np,
|
|||
if (desc->get_refclk_freq)
|
||||
clk_data.clk_num += 1;
|
||||
|
||||
clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
|
||||
clk_data.clks = kcalloc(clk_data.clk_num, sizeof(*clk_data.clks),
|
||||
GFP_KERNEL);
|
||||
if (WARN_ON(!clk_data.clks)) {
|
||||
iounmap(base);
|
||||
|
@ -270,7 +270,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
|
|||
n++;
|
||||
|
||||
ctrl->num_gates = n;
|
||||
ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
|
||||
ctrl->gates = kcalloc(ctrl->num_gates, sizeof(*ctrl->gates),
|
||||
GFP_KERNEL);
|
||||
if (WARN_ON(!ctrl->gates))
|
||||
goto gates_out;
|
||||
|
|
|
@ -165,7 +165,7 @@ static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)
|
|||
struct clk_smd_rpm_req req = {
|
||||
.key = cpu_to_le32(r->rpm_key),
|
||||
.nbytes = cpu_to_le32(sizeof(u32)),
|
||||
.value = cpu_to_le32(INT_MAX),
|
||||
.value = cpu_to_le32(r->branch ? 1 : INT_MAX),
|
||||
};
|
||||
|
||||
ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
|
|
|
@ -2944,6 +2944,7 @@ static struct gdsc venus_core0_gdsc = {
|
|||
.pd = {
|
||||
.name = "venus_core0",
|
||||
},
|
||||
.parent = &venus_gdsc.pd,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = HW_CTRL,
|
||||
};
|
||||
|
@ -2955,6 +2956,7 @@ static struct gdsc venus_core1_gdsc = {
|
|||
.pd = {
|
||||
.name = "venus_core1",
|
||||
},
|
||||
.parent = &venus_gdsc.pd,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = HW_CTRL,
|
||||
};
|
||||
|
@ -2986,7 +2988,7 @@ static struct gdsc vfe1_gdsc = {
|
|||
.cxcs = (unsigned int []){ 0x36ac },
|
||||
.cxc_count = 1,
|
||||
.pd = {
|
||||
.name = "vfe0",
|
||||
.name = "vfe1",
|
||||
},
|
||||
.parent = &camss_gdsc.pd,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/soc/renesas/rcar-rst.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
|
||||
|
||||
|
@ -24,7 +25,7 @@
|
|||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R8A7795_CLK_OSC,
|
||||
LAST_DT_CORE_CLK = R8A7795_CLK_S0D12,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_EXTAL,
|
||||
|
@ -51,10 +52,10 @@ enum clk_ids {
|
|||
MOD_CLK_BASE
|
||||
};
|
||||
|
||||
static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
||||
static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
|
||||
|
@ -78,7 +79,12 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
|||
DEF_FIXED("zt", R8A7795_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED("zx", R8A7795_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_FIXED("s0d1", R8A7795_CLK_S0D1, CLK_S0, 1, 1),
|
||||
DEF_FIXED("s0d2", R8A7795_CLK_S0D2, CLK_S0, 2, 1),
|
||||
DEF_FIXED("s0d3", R8A7795_CLK_S0D3, CLK_S0, 3, 1),
|
||||
DEF_FIXED("s0d4", R8A7795_CLK_S0D4, CLK_S0, 4, 1),
|
||||
DEF_FIXED("s0d6", R8A7795_CLK_S0D6, CLK_S0, 6, 1),
|
||||
DEF_FIXED("s0d8", R8A7795_CLK_S0D8, CLK_S0, 8, 1),
|
||||
DEF_FIXED("s0d12", R8A7795_CLK_S0D12, CLK_S0, 12, 1),
|
||||
DEF_FIXED("s1d1", R8A7795_CLK_S1D1, CLK_S1, 1, 1),
|
||||
DEF_FIXED("s1d2", R8A7795_CLK_S1D2, CLK_S1, 2, 1),
|
||||
DEF_FIXED("s1d4", R8A7795_CLK_S1D4, CLK_S1, 4, 1),
|
||||
|
@ -89,29 +95,29 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
|||
DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x0078),
|
||||
DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x0268),
|
||||
DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x026c),
|
||||
DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
||||
DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
|
||||
DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
|
||||
DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
|
||||
DEF_DIV6P1("csi0", R8A7795_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
|
||||
DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
|
||||
DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
|
||||
|
||||
DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
|
||||
DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
|
||||
DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
|
||||
|
||||
DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
|
||||
DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
|
||||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
||||
DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fdp1-1", 118, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fdp1-0", 119, R8A7795_CLK_S2D1),
|
||||
static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
|
||||
DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("fdp1-1", 118, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fdp1-0", 119, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("scif5", 202, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scif4", 203, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scif3", 204, R8A7795_CLK_S3D4),
|
||||
|
@ -121,9 +127,9 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
|||
DEF_MOD("msiof2", 209, R8A7795_CLK_MSO),
|
||||
DEF_MOD("msiof1", 210, R8A7795_CLK_MSO),
|
||||
DEF_MOD("msiof0", 211, R8A7795_CLK_MSO),
|
||||
DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("cmt3", 300, R8A7795_CLK_R),
|
||||
DEF_MOD("cmt2", 301, R8A7795_CLK_R),
|
||||
DEF_MOD("cmt1", 302, R8A7795_CLK_R),
|
||||
|
@ -135,15 +141,15 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
|||
DEF_MOD("sdif0", 314, R8A7795_CLK_SD0),
|
||||
DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("usb3-if1", 327, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("usb3-if1", 327, R8A7795_CLK_S3D1), /* ES1.x */
|
||||
DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("rwdt0", 402, R8A7795_CLK_R),
|
||||
DEF_MOD("rwdt", 402, R8A7795_CLK_R),
|
||||
DEF_MOD("intc-ex", 407, R8A7795_CLK_CP),
|
||||
DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3),
|
||||
DEF_MOD("drif7", 508, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("drif6", 509, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("drif5", 510, R8A7795_CLK_S3D2),
|
||||
|
@ -159,35 +165,35 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
|||
DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("thermal", 522, R8A7795_CLK_CP),
|
||||
DEF_MOD("pwm", 523, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvd0", 603, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvb1", 606, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvb0", 607, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvi2", 609, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvi1", 610, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvi0", 611, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpf2", 613, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpf1", 614, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpf0", 615, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpci1", 616, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpci0", 617, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpcs", 619, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd3", 620, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd2", 621, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd1", 622, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd0", 623, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspbc", 624, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspbd", 626, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspi1", 630, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspi0", 631, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("fcpvd2", 601, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("fcpvd1", 602, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("fcpvd0", 603, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("fcpvb1", 606, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fcpvb0", 607, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fcpvi2", 609, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("fcpvi1", 610, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fcpvi0", 611, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fcpf2", 613, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("fcpf1", 614, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fcpf0", 615, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("fcpci1", 616, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("fcpci0", 617, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("fcpcs", 619, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("vspd3", 620, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("vspd2", 621, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vspd1", 622, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vspd0", 623, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vspbc", 624, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("vspbd", 626, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1), /* ES1.x */
|
||||
DEF_MOD("vspi1", 630, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("vspi0", 631, R8A7795_CLK_S0D1),
|
||||
DEF_MOD("ehci2", 701, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("csi21", 713, R8A7795_CLK_CSI0),
|
||||
DEF_MOD("csi21", 713, R8A7795_CLK_CSI0), /* ES1.x */
|
||||
DEF_MOD("csi20", 714, R8A7795_CLK_CSI0),
|
||||
DEF_MOD("csi41", 715, R8A7795_CLK_CSI0),
|
||||
DEF_MOD("csi40", 716, R8A7795_CLK_CSI0),
|
||||
|
@ -198,16 +204,20 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
|||
DEF_MOD("lvds", 727, R8A7795_CLK_S0D4),
|
||||
DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI),
|
||||
DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI),
|
||||
DEF_MOD("vin7", 804, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin6", 805, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin5", 806, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin4", 807, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin3", 808, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin2", 809, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin1", 810, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin0", 811, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("vin7", 804, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin6", 805, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin5", 806, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin4", 807, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin3", 808, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin2", 809, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin1", 810, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin0", 811, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("etheravb", 812, R8A7795_CLK_S0D6),
|
||||
DEF_MOD("sata0", 815, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("imr3", 820, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("imr2", 821, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("imr1", 822, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("imr0", 823, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("gpio7", 905, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio6", 906, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio5", 907, R8A7795_CLK_CP),
|
||||
|
@ -310,6 +320,82 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
|
|||
{ 2, 192, 192, },
|
||||
};
|
||||
|
||||
static const struct soc_device_attribute r8a7795es1[] __initconst = {
|
||||
{ .soc_id = "r8a7795", .revision = "ES1.*" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Fixups for R-Car H3 ES1.x
|
||||
*/
|
||||
|
||||
static const unsigned int r8a7795es1_mod_nullify[] __initconst = {
|
||||
MOD_CLK_ID(326), /* USB-DMAC3-0 */
|
||||
MOD_CLK_ID(329), /* USB-DMAC3-1 */
|
||||
MOD_CLK_ID(700), /* EHCI/OHCI3 */
|
||||
MOD_CLK_ID(705), /* HS-USB-IF3 */
|
||||
|
||||
};
|
||||
|
||||
static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
|
||||
{ MOD_CLK_ID(118), R8A7795_CLK_S2D1 }, /* FDP1-1 */
|
||||
{ MOD_CLK_ID(119), R8A7795_CLK_S2D1 }, /* FDP1-0 */
|
||||
{ MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */
|
||||
{ MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */
|
||||
{ MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */
|
||||
{ MOD_CLK_ID(501), R8A7795_CLK_S3D1 }, /* AUDMAC1 */
|
||||
{ MOD_CLK_ID(502), R8A7795_CLK_S3D1 }, /* AUDMAC0 */
|
||||
{ MOD_CLK_ID(601), R8A7795_CLK_S2D1 }, /* FCPVD2 */
|
||||
{ MOD_CLK_ID(602), R8A7795_CLK_S2D1 }, /* FCPVD1 */
|
||||
{ MOD_CLK_ID(603), R8A7795_CLK_S2D1 }, /* FCPVD0 */
|
||||
{ MOD_CLK_ID(606), R8A7795_CLK_S2D1 }, /* FCPVB1 */
|
||||
{ MOD_CLK_ID(607), R8A7795_CLK_S2D1 }, /* FCPVB0 */
|
||||
{ MOD_CLK_ID(610), R8A7795_CLK_S2D1 }, /* FCPVI1 */
|
||||
{ MOD_CLK_ID(611), R8A7795_CLK_S2D1 }, /* FCPVI0 */
|
||||
{ MOD_CLK_ID(614), R8A7795_CLK_S2D1 }, /* FCPF1 */
|
||||
{ MOD_CLK_ID(615), R8A7795_CLK_S2D1 }, /* FCPF0 */
|
||||
{ MOD_CLK_ID(619), R8A7795_CLK_S2D1 }, /* FCPCS */
|
||||
{ MOD_CLK_ID(621), R8A7795_CLK_S2D1 }, /* VSPD2 */
|
||||
{ MOD_CLK_ID(622), R8A7795_CLK_S2D1 }, /* VSPD1 */
|
||||
{ MOD_CLK_ID(623), R8A7795_CLK_S2D1 }, /* VSPD0 */
|
||||
{ MOD_CLK_ID(624), R8A7795_CLK_S2D1 }, /* VSPBC */
|
||||
{ MOD_CLK_ID(626), R8A7795_CLK_S2D1 }, /* VSPBD */
|
||||
{ MOD_CLK_ID(630), R8A7795_CLK_S2D1 }, /* VSPI1 */
|
||||
{ MOD_CLK_ID(631), R8A7795_CLK_S2D1 }, /* VSPI0 */
|
||||
{ MOD_CLK_ID(804), R8A7795_CLK_S2D1 }, /* VIN7 */
|
||||
{ MOD_CLK_ID(805), R8A7795_CLK_S2D1 }, /* VIN6 */
|
||||
{ MOD_CLK_ID(806), R8A7795_CLK_S2D1 }, /* VIN5 */
|
||||
{ MOD_CLK_ID(807), R8A7795_CLK_S2D1 }, /* VIN4 */
|
||||
{ MOD_CLK_ID(808), R8A7795_CLK_S2D1 }, /* VIN3 */
|
||||
{ MOD_CLK_ID(809), R8A7795_CLK_S2D1 }, /* VIN2 */
|
||||
{ MOD_CLK_ID(810), R8A7795_CLK_S2D1 }, /* VIN1 */
|
||||
{ MOD_CLK_ID(811), R8A7795_CLK_S2D1 }, /* VIN0 */
|
||||
{ MOD_CLK_ID(812), R8A7795_CLK_S3D2 }, /* EAVB-IF */
|
||||
{ MOD_CLK_ID(820), R8A7795_CLK_S2D1 }, /* IMR3 */
|
||||
{ MOD_CLK_ID(821), R8A7795_CLK_S2D1 }, /* IMR2 */
|
||||
{ MOD_CLK_ID(822), R8A7795_CLK_S2D1 }, /* IMR1 */
|
||||
{ MOD_CLK_ID(823), R8A7795_CLK_S2D1 }, /* IMR0 */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Fixups for R-Car H3 ES2.x
|
||||
*/
|
||||
|
||||
static const unsigned int r8a7795es2_mod_nullify[] __initconst = {
|
||||
MOD_CLK_ID(117), /* FDP1-2 */
|
||||
MOD_CLK_ID(327), /* USB3-IF1 */
|
||||
MOD_CLK_ID(600), /* FCPVD3 */
|
||||
MOD_CLK_ID(609), /* FCPVI2 */
|
||||
MOD_CLK_ID(613), /* FCPF2 */
|
||||
MOD_CLK_ID(616), /* FCPCI1 */
|
||||
MOD_CLK_ID(617), /* FCPCI0 */
|
||||
MOD_CLK_ID(620), /* VSPD3 */
|
||||
MOD_CLK_ID(629), /* VSPI2 */
|
||||
MOD_CLK_ID(713), /* CSI21 */
|
||||
};
|
||||
|
||||
static int __init r8a7795_cpg_mssr_init(struct device *dev)
|
||||
{
|
||||
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
|
||||
|
@ -326,7 +412,26 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
|
||||
if (soc_device_match(r8a7795es1)) {
|
||||
cpg_core_nullify_range(r8a7795_core_clks,
|
||||
ARRAY_SIZE(r8a7795_core_clks),
|
||||
R8A7795_CLK_S0D2, R8A7795_CLK_S0D12);
|
||||
mssr_mod_nullify(r8a7795_mod_clks,
|
||||
ARRAY_SIZE(r8a7795_mod_clks),
|
||||
r8a7795es1_mod_nullify,
|
||||
ARRAY_SIZE(r8a7795es1_mod_nullify));
|
||||
mssr_mod_reparent(r8a7795_mod_clks,
|
||||
ARRAY_SIZE(r8a7795_mod_clks),
|
||||
r8a7795es1_mod_reparent,
|
||||
ARRAY_SIZE(r8a7795es1_mod_reparent));
|
||||
} else {
|
||||
mssr_mod_nullify(r8a7795_mod_clks,
|
||||
ARRAY_SIZE(r8a7795_mod_clks),
|
||||
r8a7795es2_mod_nullify,
|
||||
ARRAY_SIZE(r8a7795es2_mod_nullify));
|
||||
}
|
||||
|
||||
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
|
||||
}
|
||||
|
||||
const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
|
||||
|
|
|
@ -54,8 +54,8 @@ enum clk_ids {
|
|||
|
||||
static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
|
||||
|
@ -95,10 +95,10 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
|
|||
DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1),
|
||||
|
||||
DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, CLK_SDSRC, 0x0074),
|
||||
DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, CLK_SDSRC, 0x0078),
|
||||
DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, CLK_SDSRC, 0x0268),
|
||||
DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x026c),
|
||||
DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, CLK_SDSRC, 0x074),
|
||||
DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, CLK_SDSRC, 0x078),
|
||||
DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, CLK_SDSRC, 0x268),
|
||||
DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x26c),
|
||||
|
||||
DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
@ -135,7 +135,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
|
|||
DEF_MOD("sdif2", 312, R8A7796_CLK_SD2),
|
||||
DEF_MOD("sdif1", 313, R8A7796_CLK_SD1),
|
||||
DEF_MOD("sdif0", 314, R8A7796_CLK_SD0),
|
||||
DEF_MOD("rwdt0", 402, R8A7796_CLK_R),
|
||||
DEF_MOD("rwdt", 402, R8A7796_CLK_R),
|
||||
DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1),
|
||||
DEF_MOD("drif7", 508, R8A7796_CLK_S3D2),
|
||||
DEF_MOD("drif6", 509, R8A7796_CLK_S3D2),
|
||||
|
@ -179,6 +179,8 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
|
|||
DEF_MOD("vin1", 810, R8A7796_CLK_S0D2),
|
||||
DEF_MOD("vin0", 811, R8A7796_CLK_S0D2),
|
||||
DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6),
|
||||
DEF_MOD("imr1", 822, R8A7796_CLK_S0D2),
|
||||
DEF_MOD("imr0", 823, R8A7796_CLK_S0D2),
|
||||
DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4),
|
||||
DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4),
|
||||
DEF_MOD("gpio5", 907, R8A7796_CLK_S3D4),
|
||||
|
@ -271,7 +273,7 @@ static int __init r8a7796_cpg_mssr_init(struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
|
||||
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
|
||||
}
|
||||
|
||||
const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
#include "rcar-gen3-cpg.h"
|
||||
|
@ -247,6 +248,27 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
|
|||
|
||||
static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
static u32 cpg_quirks __initdata;
|
||||
|
||||
#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
|
||||
#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
|
||||
|
||||
static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
|
||||
{
|
||||
.soc_id = "r8a7795", .revision = "ES1.0",
|
||||
.data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7795", .revision = "ES1.*",
|
||||
.data = (void *)RCKCR_CKSEL,
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7796", .revision = "ES1.0",
|
||||
.data = (void *)RCKCR_CKSEL,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
|
@ -275,6 +297,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
*/
|
||||
value = readl(base + CPG_PLL0CR);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
if (cpg_quirks & PLL_ERRATA)
|
||||
mult *= 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL1:
|
||||
|
@ -290,6 +314,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
*/
|
||||
value = readl(base + CPG_PLL2CR);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
if (cpg_quirks & PLL_ERRATA)
|
||||
mult *= 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL3:
|
||||
|
@ -305,24 +331,33 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
*/
|
||||
value = readl(base + CPG_PLL4CR);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
if (cpg_quirks & PLL_ERRATA)
|
||||
mult *= 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_SD:
|
||||
return cpg_sd_clk_register(core, base, __clk_get_name(parent));
|
||||
|
||||
case CLK_TYPE_GEN3_R:
|
||||
/*
|
||||
* RINT is default.
|
||||
* Only if EXTALR is populated, we switch to it.
|
||||
*/
|
||||
value = readl(base + CPG_RCKCR) & 0x3f;
|
||||
if (cpg_quirks & RCKCR_CKSEL) {
|
||||
/*
|
||||
* RINT is default.
|
||||
* Only if EXTALR is populated, we switch to it.
|
||||
*/
|
||||
value = readl(base + CPG_RCKCR) & 0x3f;
|
||||
|
||||
if (clk_get_rate(clks[cpg_clk_extalr])) {
|
||||
parent = clks[cpg_clk_extalr];
|
||||
value |= BIT(15);
|
||||
if (clk_get_rate(clks[cpg_clk_extalr])) {
|
||||
parent = clks[cpg_clk_extalr];
|
||||
value |= BIT(15);
|
||||
}
|
||||
|
||||
writel(value, base + CPG_RCKCR);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(value, base + CPG_RCKCR);
|
||||
/* Select parent clock of RCLK by MD28 */
|
||||
if (cpg_mode & BIT(28))
|
||||
parent = clks[cpg_clk_extalr];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -334,9 +369,16 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
}
|
||||
|
||||
int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
|
||||
unsigned int clk_extalr)
|
||||
unsigned int clk_extalr, u32 mode)
|
||||
{
|
||||
const struct soc_device_attribute *attr;
|
||||
|
||||
cpg_pll_config = config;
|
||||
cpg_clk_extalr = clk_extalr;
|
||||
cpg_mode = mode;
|
||||
attr = soc_device_match(cpg_quirks_match);
|
||||
if (attr)
|
||||
cpg_quirks = (uintptr_t)attr->data;
|
||||
pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,6 @@ struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
|
|||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base);
|
||||
int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
|
||||
unsigned int clk_extalr);
|
||||
unsigned int clk_extalr, u32 mode);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -265,6 +265,11 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
|||
WARN_DEBUG(id >= priv->num_core_clks);
|
||||
WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
|
||||
|
||||
if (!core->name) {
|
||||
/* Skip NULLified clock */
|
||||
return;
|
||||
}
|
||||
|
||||
switch (core->type) {
|
||||
case CLK_TYPE_IN:
|
||||
clk = of_clk_get_by_name(priv->dev->of_node, core->name);
|
||||
|
@ -335,6 +340,11 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
|
|||
WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
|
||||
WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
|
||||
|
||||
if (!mod->name) {
|
||||
/* Skip NULLified clock */
|
||||
return;
|
||||
}
|
||||
|
||||
parent = priv->clks[mod->parent];
|
||||
if (IS_ERR(parent)) {
|
||||
clk = parent;
|
||||
|
@ -734,5 +744,45 @@ static int __init cpg_mssr_init(void)
|
|||
|
||||
subsys_initcall(cpg_mssr_init);
|
||||
|
||||
void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks,
|
||||
unsigned int num_core_clks,
|
||||
unsigned int first_clk,
|
||||
unsigned int last_clk)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_core_clks; i++)
|
||||
if (core_clks[i].id >= first_clk &&
|
||||
core_clks[i].id <= last_clk)
|
||||
core_clks[i].name = NULL;
|
||||
}
|
||||
|
||||
void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
|
||||
unsigned int num_mod_clks,
|
||||
const unsigned int *clks, unsigned int n)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
|
||||
if (mod_clks[i].id == clks[j]) {
|
||||
mod_clks[i].name = NULL;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks,
|
||||
unsigned int num_mod_clks,
|
||||
const struct mssr_mod_reparent *clks,
|
||||
unsigned int n)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
|
||||
if (mod_clks[i].id == clks[j].clk) {
|
||||
mod_clks[i].parent = clks[j].parent;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -134,4 +134,26 @@ extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
|
|||
extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
|
||||
|
||||
|
||||
/*
|
||||
* Helpers for fixing up clock tables depending on SoC revision
|
||||
*/
|
||||
|
||||
struct mssr_mod_reparent {
|
||||
unsigned int clk, parent;
|
||||
};
|
||||
|
||||
|
||||
extern void cpg_core_nullify_range(struct cpg_core_clk *core_clks,
|
||||
unsigned int num_core_clks,
|
||||
unsigned int first_clk,
|
||||
unsigned int last_clk);
|
||||
extern void mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
|
||||
unsigned int num_mod_clks,
|
||||
const unsigned int *clks, unsigned int n);
|
||||
extern void mssr_mod_reparent(struct mssr_mod_clk *mod_clks,
|
||||
unsigned int num_mod_clks,
|
||||
const struct mssr_mod_reparent *clks,
|
||||
unsigned int n);
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@ obj-y += clk-muxgrf.o
|
|||
obj-y += clk-ddr.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
|
||||
|
||||
obj-y += clk-rk1108.o
|
||||
obj-y += clk-rv1108.o
|
||||
obj-y += clk-rk3036.o
|
||||
obj-y += clk-rk3188.o
|
||||
obj-y += clk-rk3228.o
|
||||
|
|
|
@ -269,6 +269,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
|
|||
|
||||
writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
|
||||
pll->reg_base + RK3036_PLLCON(1));
|
||||
rockchip_pll_wait_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -501,6 +502,7 @@ static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
|
|||
|
||||
writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0),
|
||||
pll->reg_base + RK3066_PLLCON(3));
|
||||
rockchip_pll_wait_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -746,6 +748,7 @@ static int rockchip_rk3399_pll_enable(struct clk_hw *hw)
|
|||
|
||||
writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0),
|
||||
pll->reg_base + RK3399_PLLCON(3));
|
||||
rockchip_rk3399_pll_wait_lock(pll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <dt-bindings/clock/rk3328-cru.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define RK3328_GRF_SOC_CON4 0x410
|
||||
#define RK3328_GRF_SOC_STATUS0 0x480
|
||||
#define RK3328_GRF_MAC_CON1 0x904
|
||||
#define RK3328_GRF_MAC_CON2 0x908
|
||||
|
@ -214,6 +215,8 @@ PNAME(mux_mac2io_src_p) = { "clk_mac2io_src",
|
|||
"gmac_clkin" };
|
||||
PNAME(mux_mac2phy_src_p) = { "clk_mac2phy_src",
|
||||
"phy_50m_out" };
|
||||
PNAME(mux_mac2io_ext_p) = { "clk_mac2io",
|
||||
"gmac_clkin" };
|
||||
|
||||
static struct rockchip_pll_clock rk3328_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p,
|
||||
|
@ -680,6 +683,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
|||
COMPOSITE(SCLK_MAC2IO_OUT, "clk_mac2io_out", mux_2plls_p, 0,
|
||||
RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3328_CLKGATE_CON(3), 5, GFLAGS),
|
||||
MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT,
|
||||
RK3328_GRF_MAC_CON1, 10, 1, MFLAGS),
|
||||
MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT,
|
||||
RK3328_GRF_SOC_CON4, 14, 1, MFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0,
|
||||
RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS,
|
||||
|
@ -691,6 +698,8 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
|||
COMPOSITE_NOMUX(SCLK_MAC2PHY_OUT, "clk_mac2phy_out", "clk_mac2phy", 0,
|
||||
RK3328_CLKSEL_CON(26), 8, 2, DFLAGS,
|
||||
RK3328_CLKGATE_CON(9), 2, GFLAGS),
|
||||
MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT,
|
||||
RK3328_GRF_MAC_CON2, 10, 1, MFLAGS),
|
||||
|
||||
FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
|
||||
|
||||
|
|
|
@ -835,18 +835,18 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 0, GFLAGS),
|
||||
|
||||
/* timer gates */
|
||||
GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
|
||||
GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
|
||||
GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
|
||||
GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
|
||||
GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
|
||||
GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
|
||||
GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
|
||||
GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
|
||||
GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
|
||||
GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
|
||||
GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
|
||||
GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
|
||||
GATE(SCLK_TIMER15, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
|
||||
GATE(SCLK_TIMER14, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
|
||||
GATE(SCLK_TIMER13, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
|
||||
GATE(SCLK_TIMER12, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
|
||||
GATE(SCLK_TIMER11, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
|
||||
GATE(SCLK_TIMER10, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
|
||||
GATE(SCLK_TIMER05, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
|
||||
GATE(SCLK_TIMER04, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
|
||||
GATE(SCLK_TIMER03, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
|
||||
GATE(SCLK_TIMER02, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
|
||||
GATE(SCLK_TIMER01, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
|
||||
GATE(SCLK_TIMER00, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
|
||||
};
|
||||
|
||||
static const char *const rk3368_critical_clocks[] __initconst = {
|
||||
|
@ -858,6 +858,9 @@ static const char *const rk3368_critical_clocks[] __initconst = {
|
|||
*/
|
||||
"pclk_pwm1",
|
||||
"pclk_pd_pmu",
|
||||
"pclk_pd_alive",
|
||||
"pclk_peri",
|
||||
"hclk_peri",
|
||||
};
|
||||
|
||||
static void __init rk3368_clk_init(struct device_node *np)
|
||||
|
|
|
@ -1477,10 +1477,10 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
|
|||
GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS),
|
||||
GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS),
|
||||
|
||||
GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS),
|
||||
GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS),
|
||||
GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS),
|
||||
GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS),
|
||||
GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS),
|
||||
GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS),
|
||||
GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS),
|
||||
GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS),
|
||||
GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS),
|
||||
};
|
||||
|
||||
|
|
|
@ -18,16 +18,16 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <dt-bindings/clock/rk1108-cru.h>
|
||||
#include <dt-bindings/clock/rv1108-cru.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define RK1108_GRF_SOC_STATUS0 0x480
|
||||
#define RV1108_GRF_SOC_STATUS0 0x480
|
||||
|
||||
enum rk1108_plls {
|
||||
enum rv1108_plls {
|
||||
apll, dpll, gpll,
|
||||
};
|
||||
|
||||
static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
|
||||
static struct rockchip_pll_rate_table rv1108_pll_rates[] = {
|
||||
/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
|
||||
RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
|
||||
|
@ -74,32 +74,32 @@ static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
|
|||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
#define RK1108_DIV_CORE_MASK 0xf
|
||||
#define RK1108_DIV_CORE_SHIFT 4
|
||||
#define RV1108_DIV_CORE_MASK 0xf
|
||||
#define RV1108_DIV_CORE_SHIFT 4
|
||||
|
||||
#define RK1108_CLKSEL0(_core_peri_div) \
|
||||
#define RV1108_CLKSEL0(_core_peri_div) \
|
||||
{ \
|
||||
.reg = RK1108_CLKSEL_CON(1), \
|
||||
.val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
|
||||
RK1108_DIV_CORE_SHIFT) \
|
||||
.reg = RV1108_CLKSEL_CON(1), \
|
||||
.val = HIWORD_UPDATE(_core_peri_div, RV1108_DIV_CORE_MASK,\
|
||||
RV1108_DIV_CORE_SHIFT) \
|
||||
}
|
||||
|
||||
#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \
|
||||
#define RV1108_CPUCLK_RATE(_prate, _core_peri_div) \
|
||||
{ \
|
||||
.prate = _prate, \
|
||||
.divs = { \
|
||||
RK1108_CLKSEL0(_core_peri_div), \
|
||||
RV1108_CLKSEL0(_core_peri_div), \
|
||||
}, \
|
||||
}
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
|
||||
RK1108_CPUCLK_RATE(816000000, 4),
|
||||
RK1108_CPUCLK_RATE(600000000, 4),
|
||||
RK1108_CPUCLK_RATE(312000000, 4),
|
||||
static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = {
|
||||
RV1108_CPUCLK_RATE(816000000, 4),
|
||||
RV1108_CPUCLK_RATE(600000000, 4),
|
||||
RV1108_CPUCLK_RATE(312000000, 4),
|
||||
};
|
||||
|
||||
static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
|
||||
.core_reg = RK1108_CLKSEL_CON(0),
|
||||
static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = {
|
||||
.core_reg = RV1108_CLKSEL_CON(0),
|
||||
.div_core_shift = 0,
|
||||
.div_core_mask = 0x1f,
|
||||
.mux_core_alt = 1,
|
||||
|
@ -131,13 +131,13 @@ PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" };
|
|||
PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" };
|
||||
PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" };
|
||||
|
||||
static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
|
||||
RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
|
||||
[dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
|
||||
RK1108_PLL_CON(11), 8, 31, 0, NULL),
|
||||
[gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
|
||||
RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
|
||||
static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0),
|
||||
RV1108_PLL_CON(3), 8, 31, 0, rv1108_pll_rates),
|
||||
[dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8),
|
||||
RV1108_PLL_CON(11), 8, 31, 0, NULL),
|
||||
[gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16),
|
||||
RV1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rv1108_pll_rates),
|
||||
};
|
||||
|
||||
#define MFLAGS CLK_MUX_HIWORD_MASK
|
||||
|
@ -145,56 +145,56 @@ static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
|
|||
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
|
||||
#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
|
||||
|
||||
static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
|
||||
static struct rockchip_clk_branch rv1108_uart0_fracmux __initdata =
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
|
||||
RV1108_CLKSEL_CON(13), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
|
||||
static struct rockchip_clk_branch rv1108_uart1_fracmux __initdata =
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
|
||||
RV1108_CLKSEL_CON(14), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
|
||||
static struct rockchip_clk_branch rv1108_uart2_fracmux __initdata =
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
|
||||
RV1108_CLKSEL_CON(15), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
|
||||
static struct rockchip_clk_branch rv1108_i2s0_fracmux __initdata =
|
||||
MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
|
||||
RV1108_CLKSEL_CON(5), 12, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
|
||||
static struct rockchip_clk_branch rv1108_i2s1_fracmux __initdata =
|
||||
MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
|
||||
RV1108_CLKSEL_CON(6), 12, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
|
||||
static struct rockchip_clk_branch rv1108_i2s2_fracmux __initdata =
|
||||
MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
|
||||
RV1108_CLKSEL_CON(7), 12, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
|
||||
static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = {
|
||||
MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_MISC_CON, 13, 2, MFLAGS),
|
||||
RV1108_MISC_CON, 13, 2, MFLAGS),
|
||||
MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_MISC_CON, 15, 2, MFLAGS),
|
||||
RV1108_MISC_CON, 15, 2, MFLAGS),
|
||||
/*
|
||||
* Clock-Architecture Diagram 2
|
||||
*/
|
||||
|
||||
/* PD_CORE */
|
||||
GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 1, GFLAGS),
|
||||
GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 0, GFLAGS),
|
||||
GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 2, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK1108_CLKGATE_CON(0), 5, GFLAGS),
|
||||
RV1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RV1108_CLKGATE_CON(0), 5, GFLAGS),
|
||||
COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK1108_CLKGATE_CON(0), 4, GFLAGS),
|
||||
RV1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RV1108_CLKGATE_CON(0), 4, GFLAGS),
|
||||
GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(11), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(11), 0, GFLAGS),
|
||||
GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(11), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(11), 1, GFLAGS),
|
||||
|
||||
/* PD_RKVENC */
|
||||
|
||||
|
@ -202,58 +202,58 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
|
|||
|
||||
/* PD_PMU_wrapper */
|
||||
COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(8), 12, GFLAGS),
|
||||
RV1108_CLKSEL_CON(38), 0, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(8), 12, GFLAGS),
|
||||
GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 0, GFLAGS),
|
||||
GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 1, GFLAGS),
|
||||
GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 2, GFLAGS),
|
||||
GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 3, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 3, GFLAGS),
|
||||
GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 4, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 4, GFLAGS),
|
||||
GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 5, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 5, GFLAGS),
|
||||
GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(10), 6, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 6, GFLAGS),
|
||||
COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(8), 15, GFLAGS),
|
||||
RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(8), 15, GFLAGS),
|
||||
COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(8), 14, GFLAGS),
|
||||
RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(8), 14, GFLAGS),
|
||||
GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(8), 13, GFLAGS),
|
||||
RV1108_CLKGATE_CON(8), 13, GFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 4
|
||||
*/
|
||||
COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(6), 0, GFLAGS),
|
||||
RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(6), 0, GFLAGS),
|
||||
GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(17), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(17), 0, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
|
||||
RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(7), 2, GFLAGS),
|
||||
RV1108_CLKSEL_CON(29), 0, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(7), 2, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
|
||||
RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(7), 3, GFLAGS),
|
||||
RV1108_CLKSEL_CON(29), 8, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(7), 3, GFLAGS),
|
||||
|
||||
INVERTER(0, "pclk_vip", "ext_vip",
|
||||
RK1108_CLKSEL_CON(31), 8, IFLAGS),
|
||||
RV1108_CLKSEL_CON(31), 8, IFLAGS),
|
||||
GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(7), 6, GFLAGS),
|
||||
RV1108_CLKGATE_CON(7), 6, GFLAGS),
|
||||
GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(18), 10, GFLAGS),
|
||||
RV1108_CLKGATE_CON(18), 10, GFLAGS),
|
||||
GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(6), 5, GFLAGS),
|
||||
RV1108_CLKGATE_CON(6), 5, GFLAGS),
|
||||
GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(6), 4, GFLAGS),
|
||||
RV1108_CLKGATE_CON(6), 4, GFLAGS),
|
||||
COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
|
||||
RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
|
||||
RV1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 5
|
||||
|
@ -262,153 +262,153 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
|
|||
FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
|
||||
|
||||
COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
|
||||
RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(2), 0, GFLAGS),
|
||||
RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(2), 0, GFLAGS),
|
||||
COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(8), 0,
|
||||
RK1108_CLKGATE_CON(2), 1, GFLAGS,
|
||||
&rk1108_i2s0_fracmux),
|
||||
RV1108_CLKSEL_CON(8), 0,
|
||||
RV1108_CLKGATE_CON(2), 1, GFLAGS,
|
||||
&rv1108_i2s0_fracmux),
|
||||
GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKGATE_CON(2), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(2), 2, GFLAGS),
|
||||
COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
|
||||
RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
|
||||
RK1108_CLKGATE_CON(2), 3, GFLAGS),
|
||||
RV1108_CLKSEL_CON(5), 15, 1, MFLAGS,
|
||||
RV1108_CLKGATE_CON(2), 3, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
|
||||
RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(2), 4, GFLAGS),
|
||||
RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(2), 4, GFLAGS),
|
||||
COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(9), 0,
|
||||
RK2928_CLKGATE_CON(2), 5, GFLAGS,
|
||||
&rk1108_i2s1_fracmux),
|
||||
&rv1108_i2s1_fracmux),
|
||||
GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKGATE_CON(2), 6, GFLAGS),
|
||||
RV1108_CLKGATE_CON(2), 6, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
|
||||
RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 8, GFLAGS),
|
||||
RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 8, GFLAGS),
|
||||
COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(10), 0,
|
||||
RK1108_CLKGATE_CON(2), 9, GFLAGS,
|
||||
&rk1108_i2s2_fracmux),
|
||||
RV1108_CLKSEL_CON(10), 0,
|
||||
RV1108_CLKGATE_CON(2), 9, GFLAGS,
|
||||
&rv1108_i2s2_fracmux),
|
||||
GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKGATE_CON(2), 10, GFLAGS),
|
||||
RV1108_CLKGATE_CON(2), 10, GFLAGS),
|
||||
|
||||
/* PD_BUS */
|
||||
GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 0, GFLAGS),
|
||||
GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 1, GFLAGS),
|
||||
GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 2, GFLAGS),
|
||||
COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
|
||||
RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
|
||||
RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
|
||||
COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
|
||||
RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(1), 4, GFLAGS),
|
||||
RV1108_CLKSEL_CON(3), 0, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(1), 4, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
|
||||
RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(1), 5, GFLAGS),
|
||||
RV1108_CLKSEL_CON(3), 8, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(1), 5, GFLAGS),
|
||||
GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 6, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 6, GFLAGS),
|
||||
GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 7, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 7, GFLAGS),
|
||||
GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 8, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 8, GFLAGS),
|
||||
GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 9, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 9, GFLAGS),
|
||||
GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(1), 10, GFLAGS),
|
||||
RV1108_CLKGATE_CON(1), 10, GFLAGS),
|
||||
GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 4, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 4, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 1, GFLAGS),
|
||||
RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 1, GFLAGS),
|
||||
COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 3, GFLAGS),
|
||||
RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 3, GFLAGS),
|
||||
COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 5, GFLAGS),
|
||||
RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 5, GFLAGS),
|
||||
|
||||
COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(16), 0,
|
||||
RK1108_CLKGATE_CON(3), 2, GFLAGS,
|
||||
&rk1108_uart0_fracmux),
|
||||
RV1108_CLKSEL_CON(16), 0,
|
||||
RV1108_CLKGATE_CON(3), 2, GFLAGS,
|
||||
&rv1108_uart0_fracmux),
|
||||
COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(17), 0,
|
||||
RK1108_CLKGATE_CON(3), 4, GFLAGS,
|
||||
&rk1108_uart1_fracmux),
|
||||
RV1108_CLKSEL_CON(17), 0,
|
||||
RV1108_CLKGATE_CON(3), 4, GFLAGS,
|
||||
&rv1108_uart1_fracmux),
|
||||
COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(18), 0,
|
||||
RK1108_CLKGATE_CON(3), 6, GFLAGS,
|
||||
&rk1108_uart2_fracmux),
|
||||
RV1108_CLKSEL_CON(18), 0,
|
||||
RV1108_CLKGATE_CON(3), 6, GFLAGS,
|
||||
&rv1108_uart2_fracmux),
|
||||
GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 10, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 10, GFLAGS),
|
||||
GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 11, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 11, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 12, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 12, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 7, GFLAGS),
|
||||
RV1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 7, GFLAGS),
|
||||
COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 8, GFLAGS),
|
||||
RV1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 8, GFLAGS),
|
||||
COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 9, GFLAGS),
|
||||
RV1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 9, GFLAGS),
|
||||
GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 0, GFLAGS),
|
||||
GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 1, GFLAGS),
|
||||
GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 2, GFLAGS),
|
||||
COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(3), 10, GFLAGS),
|
||||
RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(3), 10, GFLAGS),
|
||||
GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 6, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 6, GFLAGS),
|
||||
GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 3, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 3, GFLAGS),
|
||||
GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 7, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 7, GFLAGS),
|
||||
GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 8, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 8, GFLAGS),
|
||||
GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(13), 9, GFLAGS),
|
||||
RV1108_CLKGATE_CON(13), 9, GFLAGS),
|
||||
|
||||
GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(14), 0, GFLAGS),
|
||||
RV1108_CLKGATE_CON(14), 0, GFLAGS),
|
||||
|
||||
GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
|
||||
RK1108_CLKGATE_CON(12), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(12), 2, GFLAGS),
|
||||
GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(12), 3, GFLAGS),
|
||||
RV1108_CLKGATE_CON(12), 3, GFLAGS),
|
||||
GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(12), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(12), 1, GFLAGS),
|
||||
|
||||
/* PD_DDR */
|
||||
GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 8, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 8, GFLAGS),
|
||||
GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 9, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 9, GFLAGS),
|
||||
GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 10, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 10, GFLAGS),
|
||||
COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
|
||||
RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
|
||||
DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
|
||||
RK1108_CLKGATE_CON(10), 9, GFLAGS),
|
||||
RV1108_CLKGATE_CON(10), 9, GFLAGS),
|
||||
GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(12), 4, GFLAGS),
|
||||
RV1108_CLKGATE_CON(12), 4, GFLAGS),
|
||||
GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(12), 5, GFLAGS),
|
||||
RV1108_CLKGATE_CON(12), 5, GFLAGS),
|
||||
GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(12), 6, GFLAGS),
|
||||
RV1108_CLKGATE_CON(12), 6, GFLAGS),
|
||||
GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(0), 11, GFLAGS),
|
||||
RV1108_CLKGATE_CON(0), 11, GFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 6
|
||||
|
@ -416,73 +416,73 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
|
|||
|
||||
/* PD_PERI */
|
||||
COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
|
||||
RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(4), 5, GFLAGS),
|
||||
RV1108_CLKSEL_CON(23), 10, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(4), 5, GFLAGS),
|
||||
GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(15), 13, GFLAGS),
|
||||
RV1108_CLKGATE_CON(15), 13, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
|
||||
RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(4), 4, GFLAGS),
|
||||
RV1108_CLKSEL_CON(23), 5, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(4), 4, GFLAGS),
|
||||
GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(15), 12, GFLAGS),
|
||||
RV1108_CLKGATE_CON(15), 12, GFLAGS),
|
||||
|
||||
GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(4), 1, GFLAGS),
|
||||
RV1108_CLKGATE_CON(4), 1, GFLAGS),
|
||||
GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKGATE_CON(4), 2, GFLAGS),
|
||||
RV1108_CLKGATE_CON(4), 2, GFLAGS),
|
||||
COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
|
||||
RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(15), 11, GFLAGS),
|
||||
RV1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(15), 11, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
|
||||
RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
|
||||
RK1108_CLKGATE_CON(5), 0, GFLAGS),
|
||||
RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
|
||||
RV1108_CLKGATE_CON(5), 0, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
|
||||
RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
|
||||
RK1108_CLKGATE_CON(5), 2, GFLAGS),
|
||||
RV1108_CLKSEL_CON(25), 10, 2, MFLAGS,
|
||||
RV1108_CLKGATE_CON(5), 2, GFLAGS),
|
||||
DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
|
||||
RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
|
||||
RV1108_CLKSEL_CON(26), 0, 8, DFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
|
||||
RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
|
||||
RK1108_CLKGATE_CON(5), 1, GFLAGS),
|
||||
RV1108_CLKSEL_CON(25), 12, 2, MFLAGS,
|
||||
RV1108_CLKGATE_CON(5), 1, GFLAGS),
|
||||
DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
|
||||
RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
|
||||
GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
|
||||
GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
|
||||
GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
|
||||
GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 0, GFLAGS),
|
||||
GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 1, GFLAGS),
|
||||
GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
|
||||
RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(5), 3, GFLAGS),
|
||||
GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
|
||||
RV1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(5), 3, GFLAGS),
|
||||
GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
|
||||
RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK1108_CLKGATE_CON(5), 4, GFLAGS),
|
||||
GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
|
||||
RV1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RV1108_CLKGATE_CON(5), 4, GFLAGS),
|
||||
GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
|
||||
RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK1108_CLKGATE_CON(4), 10, GFLAGS),
|
||||
RV1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RV1108_CLKGATE_CON(4), 10, GFLAGS),
|
||||
MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
|
||||
RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
|
||||
GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
|
||||
GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
|
||||
GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
|
||||
RV1108_CLKSEL_CON(24), 8, 2, MFLAGS),
|
||||
GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS),
|
||||
GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS),
|
||||
GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS),
|
||||
|
||||
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
|
||||
MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
|
||||
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RV1108_SDMMC_CON0, 1),
|
||||
MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1),
|
||||
|
||||
MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1),
|
||||
MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1),
|
||||
MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RV1108_SDIO_CON0, 1),
|
||||
MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RV1108_SDIO_CON1, 1),
|
||||
|
||||
MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1),
|
||||
MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1),
|
||||
MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RV1108_EMMC_CON0, 1),
|
||||
MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RV1108_EMMC_CON1, 1),
|
||||
};
|
||||
|
||||
static const char *const rk1108_critical_clocks[] __initconst = {
|
||||
static const char *const rv1108_critical_clocks[] __initconst = {
|
||||
"aclk_core",
|
||||
"aclk_bus_src_gpll",
|
||||
"aclk_periph",
|
||||
|
@ -490,7 +490,7 @@ static const char *const rk1108_critical_clocks[] __initconst = {
|
|||
"pclk_periph",
|
||||
};
|
||||
|
||||
static void __init rk1108_clk_init(struct device_node *np)
|
||||
static void __init rv1108_clk_init(struct device_node *np)
|
||||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
|
@ -508,24 +508,24 @@ static void __init rk1108_clk_init(struct device_node *np)
|
|||
return;
|
||||
}
|
||||
|
||||
rockchip_clk_register_plls(ctx, rk1108_pll_clks,
|
||||
ARRAY_SIZE(rk1108_pll_clks),
|
||||
RK1108_GRF_SOC_STATUS0);
|
||||
rockchip_clk_register_branches(ctx, rk1108_clk_branches,
|
||||
ARRAY_SIZE(rk1108_clk_branches));
|
||||
rockchip_clk_protect_critical(rk1108_critical_clocks,
|
||||
ARRAY_SIZE(rk1108_critical_clocks));
|
||||
rockchip_clk_register_plls(ctx, rv1108_pll_clks,
|
||||
ARRAY_SIZE(rv1108_pll_clks),
|
||||
RV1108_GRF_SOC_STATUS0);
|
||||
rockchip_clk_register_branches(ctx, rv1108_clk_branches,
|
||||
ARRAY_SIZE(rv1108_clk_branches));
|
||||
rockchip_clk_protect_critical(rv1108_critical_clocks,
|
||||
ARRAY_SIZE(rv1108_critical_clocks));
|
||||
|
||||
rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
|
||||
mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
|
||||
&rk1108_cpuclk_data, rk1108_cpuclk_rates,
|
||||
ARRAY_SIZE(rk1108_cpuclk_rates));
|
||||
&rv1108_cpuclk_data, rv1108_cpuclk_rates,
|
||||
ARRAY_SIZE(rv1108_cpuclk_rates));
|
||||
|
||||
rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
|
||||
rockchip_register_softrst(np, 13, reg_base + RV1108_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
|
||||
rockchip_register_restart_notifier(ctx, RV1108_GLB_SRST_FST, NULL);
|
||||
|
||||
rockchip_clk_of_add_provider(np, ctx);
|
||||
}
|
||||
CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
|
||||
CLK_OF_DECLARE(rv1108_cru, "rockchip,rv1108-cru", rv1108_clk_init);
|
|
@ -34,20 +34,20 @@ struct clk;
|
|||
#define HIWORD_UPDATE(val, mask, shift) \
|
||||
((val) << (shift) | (mask) << ((shift) + 16))
|
||||
|
||||
/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
|
||||
#define RK1108_PLL_CON(x) ((x) * 0x4)
|
||||
#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
|
||||
#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
|
||||
#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
|
||||
#define RK1108_GLB_SRST_FST 0x1c0
|
||||
#define RK1108_GLB_SRST_SND 0x1c4
|
||||
#define RK1108_MISC_CON 0x1cc
|
||||
#define RK1108_SDMMC_CON0 0x1d8
|
||||
#define RK1108_SDMMC_CON1 0x1dc
|
||||
#define RK1108_SDIO_CON0 0x1e0
|
||||
#define RK1108_SDIO_CON1 0x1e4
|
||||
#define RK1108_EMMC_CON0 0x1e8
|
||||
#define RK1108_EMMC_CON1 0x1ec
|
||||
/* register positions shared by RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
|
||||
#define RV1108_PLL_CON(x) ((x) * 0x4)
|
||||
#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
|
||||
#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
|
||||
#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
|
||||
#define RV1108_GLB_SRST_FST 0x1c0
|
||||
#define RV1108_GLB_SRST_SND 0x1c4
|
||||
#define RV1108_MISC_CON 0x1cc
|
||||
#define RV1108_SDMMC_CON0 0x1d8
|
||||
#define RV1108_SDMMC_CON1 0x1dc
|
||||
#define RV1108_SDIO_CON0 0x1e0
|
||||
#define RV1108_SDIO_CON1 0x1e4
|
||||
#define RV1108_EMMC_CON0 0x1e8
|
||||
#define RV1108_EMMC_CON1 0x1ec
|
||||
|
||||
#define RK2928_PLL_CON(x) ((x) * 0x4)
|
||||
#define RK2928_MODE_CON 0x40
|
||||
|
|
|
@ -313,7 +313,7 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
|
|||
/* clock derived from apb clk */
|
||||
clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
|
||||
ADC_CLK_ENB, 0, &_lock);
|
||||
clk_register_clkdev(clk, NULL, "adc");
|
||||
clk_register_clkdev(clk, NULL, "d820b000.adc");
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "gpio0_clk", "apb_clk", 0, 1, 1);
|
||||
clk_register_clkdev(clk, NULL, "f0100000.gpio");
|
||||
|
|
|
@ -64,6 +64,7 @@ config SUN50I_A64_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default ARM64 && ARCH_SUNXI
|
||||
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
|
||||
|
||||
config SUN5I_CCU
|
||||
bool "Support for the Allwinner sun5i family CCM"
|
||||
|
@ -75,6 +76,7 @@ config SUN5I_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN5I
|
||||
depends on MACH_SUN5I || COMPILE_TEST
|
||||
|
||||
config SUN6I_A31_CCU
|
||||
bool "Support for the Allwinner A31/A31s CCU"
|
||||
|
@ -86,6 +88,7 @@ config SUN6I_A31_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN6I
|
||||
depends on MACH_SUN6I || COMPILE_TEST
|
||||
|
||||
config SUN8I_A23_CCU
|
||||
bool "Support for the Allwinner A23 CCU"
|
||||
|
@ -98,6 +101,7 @@ config SUN8I_A23_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN8I
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN8I_A33_CCU
|
||||
bool "Support for the Allwinner A33 CCU"
|
||||
|
@ -110,6 +114,7 @@ config SUN8I_A33_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN8I
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN8I_H3_CCU
|
||||
bool "Support for the Allwinner H3 CCU"
|
||||
|
@ -120,7 +125,8 @@ config SUN8I_H3_CCU
|
|||
select SUNXI_CCU_NM
|
||||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN8I
|
||||
default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
|
||||
depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST
|
||||
|
||||
config SUN8I_V3S_CCU
|
||||
bool "Support for the Allwinner V3s CCU"
|
||||
|
@ -132,6 +138,7 @@ config SUN8I_V3S_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN8I
|
||||
depends on MACH_SUN8I || COMPILE_TEST
|
||||
|
||||
config SUN9I_A80_CCU
|
||||
bool "Support for the Allwinner A80 CCU"
|
||||
|
@ -143,5 +150,12 @@ config SUN9I_A80_CCU
|
|||
select SUNXI_CCU_MP
|
||||
select SUNXI_CCU_PHASE
|
||||
default MACH_SUN9I
|
||||
depends on MACH_SUN9I || COMPILE_TEST
|
||||
|
||||
config SUN8I_R_CCU
|
||||
bool "Support for Allwinner SoCs' PRCM CCUs"
|
||||
select SUNXI_CCU_DIV
|
||||
select SUNXI_CCU_GATE
|
||||
default MACH_SUN8I || (ARCH_SUNXI && ARM64)
|
||||
|
||||
endif
|
||||
|
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o
|
|||
obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
|
||||
obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o
|
||||
obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o
|
||||
obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o
|
||||
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o
|
||||
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o
|
||||
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o
|
||||
|
|
|
@ -469,7 +469,7 @@ static const char * const csi_parents[] = { "hosc", "pll-video0", "pll-video1",
|
|||
static const u8 csi_table[] = { 0, 1, 2, 5, 6 };
|
||||
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_clk, "csi",
|
||||
csi_parents, csi_table,
|
||||
0x134, 0, 5, 24, 2, BIT(31), 0);
|
||||
0x134, 0, 5, 24, 3, BIT(31), 0);
|
||||
|
||||
static SUNXI_CCU_GATE(ve_clk, "ve", "pll-ve",
|
||||
0x13c, BIT(31), CLK_SET_RATE_PARENT);
|
||||
|
|
|
@ -159,13 +159,17 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
|
|||
BIT(28), /* lock */
|
||||
CLK_SET_RATE_UNGATE);
|
||||
|
||||
/* TODO: Fix N */
|
||||
static SUNXI_CCU_N_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
|
||||
"osc24M", 0x04c,
|
||||
8, 6, /* N */
|
||||
BIT(31), /* gate */
|
||||
BIT(28), /* lock */
|
||||
CLK_SET_RATE_UNGATE);
|
||||
static struct ccu_mult pll_ddr1_clk = {
|
||||
.enable = BIT(31),
|
||||
.lock = BIT(28),
|
||||
.mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 6, 0, 12, 0),
|
||||
.common = {
|
||||
.reg = 0x04c,
|
||||
.hw.init = CLK_HW_INIT("pll-ddr1", "osc24M",
|
||||
&ccu_mult_ops,
|
||||
CLK_SET_RATE_UNGATE),
|
||||
},
|
||||
};
|
||||
|
||||
static const char * const cpux_parents[] = { "osc32k", "osc24M",
|
||||
"pll-cpux" , "pll-cpux" };
|
||||
|
|
|
@ -300,8 +300,10 @@ static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2",
|
|||
0x06c, BIT(18), 0);
|
||||
static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2",
|
||||
0x06c, BIT(19), 0);
|
||||
static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2",
|
||||
static SUNXI_CCU_GATE(bus_scr0_clk, "bus-scr0", "apb2",
|
||||
0x06c, BIT(20), 0);
|
||||
static SUNXI_CCU_GATE(bus_scr1_clk, "bus-scr1", "apb2",
|
||||
0x06c, BIT(21), 0);
|
||||
|
||||
static SUNXI_CCU_GATE(bus_ephy_clk, "bus-ephy", "ahb1",
|
||||
0x070, BIT(0), 0);
|
||||
|
@ -546,7 +548,7 @@ static struct ccu_common *sun8i_h3_ccu_clks[] = {
|
|||
&bus_uart1_clk.common,
|
||||
&bus_uart2_clk.common,
|
||||
&bus_uart3_clk.common,
|
||||
&bus_scr_clk.common,
|
||||
&bus_scr0_clk.common,
|
||||
&bus_ephy_clk.common,
|
||||
&bus_dbg_clk.common,
|
||||
&ths_clk.common,
|
||||
|
@ -597,6 +599,114 @@ static struct ccu_common *sun8i_h3_ccu_clks[] = {
|
|||
&gpu_clk.common,
|
||||
};
|
||||
|
||||
static struct ccu_common *sun50i_h5_ccu_clks[] = {
|
||||
&pll_cpux_clk.common,
|
||||
&pll_audio_base_clk.common,
|
||||
&pll_video_clk.common,
|
||||
&pll_ve_clk.common,
|
||||
&pll_ddr_clk.common,
|
||||
&pll_periph0_clk.common,
|
||||
&pll_gpu_clk.common,
|
||||
&pll_periph1_clk.common,
|
||||
&pll_de_clk.common,
|
||||
&cpux_clk.common,
|
||||
&axi_clk.common,
|
||||
&ahb1_clk.common,
|
||||
&apb1_clk.common,
|
||||
&apb2_clk.common,
|
||||
&ahb2_clk.common,
|
||||
&bus_ce_clk.common,
|
||||
&bus_dma_clk.common,
|
||||
&bus_mmc0_clk.common,
|
||||
&bus_mmc1_clk.common,
|
||||
&bus_mmc2_clk.common,
|
||||
&bus_nand_clk.common,
|
||||
&bus_dram_clk.common,
|
||||
&bus_emac_clk.common,
|
||||
&bus_ts_clk.common,
|
||||
&bus_hstimer_clk.common,
|
||||
&bus_spi0_clk.common,
|
||||
&bus_spi1_clk.common,
|
||||
&bus_otg_clk.common,
|
||||
&bus_ehci0_clk.common,
|
||||
&bus_ehci1_clk.common,
|
||||
&bus_ehci2_clk.common,
|
||||
&bus_ehci3_clk.common,
|
||||
&bus_ohci0_clk.common,
|
||||
&bus_ohci1_clk.common,
|
||||
&bus_ohci2_clk.common,
|
||||
&bus_ohci3_clk.common,
|
||||
&bus_ve_clk.common,
|
||||
&bus_tcon0_clk.common,
|
||||
&bus_tcon1_clk.common,
|
||||
&bus_deinterlace_clk.common,
|
||||
&bus_csi_clk.common,
|
||||
&bus_tve_clk.common,
|
||||
&bus_hdmi_clk.common,
|
||||
&bus_de_clk.common,
|
||||
&bus_gpu_clk.common,
|
||||
&bus_msgbox_clk.common,
|
||||
&bus_spinlock_clk.common,
|
||||
&bus_codec_clk.common,
|
||||
&bus_spdif_clk.common,
|
||||
&bus_pio_clk.common,
|
||||
&bus_ths_clk.common,
|
||||
&bus_i2s0_clk.common,
|
||||
&bus_i2s1_clk.common,
|
||||
&bus_i2s2_clk.common,
|
||||
&bus_i2c0_clk.common,
|
||||
&bus_i2c1_clk.common,
|
||||
&bus_i2c2_clk.common,
|
||||
&bus_uart0_clk.common,
|
||||
&bus_uart1_clk.common,
|
||||
&bus_uart2_clk.common,
|
||||
&bus_uart3_clk.common,
|
||||
&bus_scr0_clk.common,
|
||||
&bus_scr1_clk.common,
|
||||
&bus_ephy_clk.common,
|
||||
&bus_dbg_clk.common,
|
||||
&ths_clk.common,
|
||||
&nand_clk.common,
|
||||
&mmc0_clk.common,
|
||||
&mmc1_clk.common,
|
||||
&mmc2_clk.common,
|
||||
&ts_clk.common,
|
||||
&ce_clk.common,
|
||||
&spi0_clk.common,
|
||||
&spi1_clk.common,
|
||||
&i2s0_clk.common,
|
||||
&i2s1_clk.common,
|
||||
&i2s2_clk.common,
|
||||
&spdif_clk.common,
|
||||
&usb_phy0_clk.common,
|
||||
&usb_phy1_clk.common,
|
||||
&usb_phy2_clk.common,
|
||||
&usb_phy3_clk.common,
|
||||
&usb_ohci0_clk.common,
|
||||
&usb_ohci1_clk.common,
|
||||
&usb_ohci2_clk.common,
|
||||
&usb_ohci3_clk.common,
|
||||
&dram_clk.common,
|
||||
&dram_ve_clk.common,
|
||||
&dram_csi_clk.common,
|
||||
&dram_deinterlace_clk.common,
|
||||
&dram_ts_clk.common,
|
||||
&de_clk.common,
|
||||
&tcon_clk.common,
|
||||
&tve_clk.common,
|
||||
&deinterlace_clk.common,
|
||||
&csi_misc_clk.common,
|
||||
&csi_sclk_clk.common,
|
||||
&csi_mclk_clk.common,
|
||||
&ve_clk.common,
|
||||
&ac_dig_clk.common,
|
||||
&avs_clk.common,
|
||||
&hdmi_clk.common,
|
||||
&hdmi_ddc_clk.common,
|
||||
&mbus_clk.common,
|
||||
&gpu_clk.common,
|
||||
};
|
||||
|
||||
/* We hardcode the divider to 4 for now */
|
||||
static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
|
||||
"pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
|
||||
|
@ -677,7 +787,7 @@ static struct clk_hw_onecell_data sun8i_h3_hw_clks = {
|
|||
[CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
|
||||
[CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
|
||||
[CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
|
||||
[CLK_BUS_SCR] = &bus_scr_clk.common.hw,
|
||||
[CLK_BUS_SCR0] = &bus_scr0_clk.common.hw,
|
||||
[CLK_BUS_EPHY] = &bus_ephy_clk.common.hw,
|
||||
[CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
|
||||
[CLK_THS] = &ths_clk.common.hw,
|
||||
|
@ -727,7 +837,123 @@ static struct clk_hw_onecell_data sun8i_h3_hw_clks = {
|
|||
[CLK_MBUS] = &mbus_clk.common.hw,
|
||||
[CLK_GPU] = &gpu_clk.common.hw,
|
||||
},
|
||||
.num = CLK_NUMBER,
|
||||
.num = CLK_NUMBER_H3,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data sun50i_h5_hw_clks = {
|
||||
.hws = {
|
||||
[CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
|
||||
[CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
|
||||
[CLK_PLL_AUDIO] = &pll_audio_clk.hw,
|
||||
[CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
|
||||
[CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
|
||||
[CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
|
||||
[CLK_PLL_VIDEO] = &pll_video_clk.common.hw,
|
||||
[CLK_PLL_VE] = &pll_ve_clk.common.hw,
|
||||
[CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
|
||||
[CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
|
||||
[CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
|
||||
[CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
|
||||
[CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
|
||||
[CLK_PLL_DE] = &pll_de_clk.common.hw,
|
||||
[CLK_CPUX] = &cpux_clk.common.hw,
|
||||
[CLK_AXI] = &axi_clk.common.hw,
|
||||
[CLK_AHB1] = &ahb1_clk.common.hw,
|
||||
[CLK_APB1] = &apb1_clk.common.hw,
|
||||
[CLK_APB2] = &apb2_clk.common.hw,
|
||||
[CLK_AHB2] = &ahb2_clk.common.hw,
|
||||
[CLK_BUS_CE] = &bus_ce_clk.common.hw,
|
||||
[CLK_BUS_DMA] = &bus_dma_clk.common.hw,
|
||||
[CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
|
||||
[CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
|
||||
[CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
|
||||
[CLK_BUS_NAND] = &bus_nand_clk.common.hw,
|
||||
[CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
|
||||
[CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
|
||||
[CLK_BUS_TS] = &bus_ts_clk.common.hw,
|
||||
[CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
|
||||
[CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
|
||||
[CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
|
||||
[CLK_BUS_OTG] = &bus_otg_clk.common.hw,
|
||||
[CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
|
||||
[CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
|
||||
[CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw,
|
||||
[CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw,
|
||||
[CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
|
||||
[CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
|
||||
[CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw,
|
||||
[CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw,
|
||||
[CLK_BUS_VE] = &bus_ve_clk.common.hw,
|
||||
[CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw,
|
||||
[CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw,
|
||||
[CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
|
||||
[CLK_BUS_CSI] = &bus_csi_clk.common.hw,
|
||||
[CLK_BUS_TVE] = &bus_tve_clk.common.hw,
|
||||
[CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
|
||||
[CLK_BUS_DE] = &bus_de_clk.common.hw,
|
||||
[CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
|
||||
[CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw,
|
||||
[CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw,
|
||||
[CLK_BUS_CODEC] = &bus_codec_clk.common.hw,
|
||||
[CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
|
||||
[CLK_BUS_PIO] = &bus_pio_clk.common.hw,
|
||||
[CLK_BUS_THS] = &bus_ths_clk.common.hw,
|
||||
[CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
|
||||
[CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
|
||||
[CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw,
|
||||
[CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
|
||||
[CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
|
||||
[CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
|
||||
[CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
|
||||
[CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
|
||||
[CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
|
||||
[CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
|
||||
[CLK_BUS_SCR0] = &bus_scr0_clk.common.hw,
|
||||
[CLK_BUS_SCR1] = &bus_scr1_clk.common.hw,
|
||||
[CLK_BUS_EPHY] = &bus_ephy_clk.common.hw,
|
||||
[CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
|
||||
[CLK_THS] = &ths_clk.common.hw,
|
||||
[CLK_NAND] = &nand_clk.common.hw,
|
||||
[CLK_MMC0] = &mmc0_clk.common.hw,
|
||||
[CLK_MMC1] = &mmc1_clk.common.hw,
|
||||
[CLK_MMC2] = &mmc2_clk.common.hw,
|
||||
[CLK_TS] = &ts_clk.common.hw,
|
||||
[CLK_CE] = &ce_clk.common.hw,
|
||||
[CLK_SPI0] = &spi0_clk.common.hw,
|
||||
[CLK_SPI1] = &spi1_clk.common.hw,
|
||||
[CLK_I2S0] = &i2s0_clk.common.hw,
|
||||
[CLK_I2S1] = &i2s1_clk.common.hw,
|
||||
[CLK_I2S2] = &i2s2_clk.common.hw,
|
||||
[CLK_SPDIF] = &spdif_clk.common.hw,
|
||||
[CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
|
||||
[CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
|
||||
[CLK_USB_PHY2] = &usb_phy2_clk.common.hw,
|
||||
[CLK_USB_PHY3] = &usb_phy3_clk.common.hw,
|
||||
[CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
|
||||
[CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
|
||||
[CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw,
|
||||
[CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw,
|
||||
[CLK_DRAM] = &dram_clk.common.hw,
|
||||
[CLK_DRAM_VE] = &dram_ve_clk.common.hw,
|
||||
[CLK_DRAM_CSI] = &dram_csi_clk.common.hw,
|
||||
[CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw,
|
||||
[CLK_DRAM_TS] = &dram_ts_clk.common.hw,
|
||||
[CLK_DE] = &de_clk.common.hw,
|
||||
[CLK_TCON0] = &tcon_clk.common.hw,
|
||||
[CLK_TVE] = &tve_clk.common.hw,
|
||||
[CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
|
||||
[CLK_CSI_MISC] = &csi_misc_clk.common.hw,
|
||||
[CLK_CSI_SCLK] = &csi_sclk_clk.common.hw,
|
||||
[CLK_CSI_MCLK] = &csi_mclk_clk.common.hw,
|
||||
[CLK_VE] = &ve_clk.common.hw,
|
||||
[CLK_AC_DIG] = &ac_dig_clk.common.hw,
|
||||
[CLK_AVS] = &avs_clk.common.hw,
|
||||
[CLK_HDMI] = &hdmi_clk.common.hw,
|
||||
[CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw,
|
||||
[CLK_MBUS] = &mbus_clk.common.hw,
|
||||
[CLK_GPU] = &gpu_clk.common.hw,
|
||||
},
|
||||
.num = CLK_NUMBER_H5,
|
||||
};
|
||||
|
||||
static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
|
||||
|
@ -790,7 +1016,71 @@ static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
|
|||
[RST_BUS_UART1] = { 0x2d8, BIT(17) },
|
||||
[RST_BUS_UART2] = { 0x2d8, BIT(18) },
|
||||
[RST_BUS_UART3] = { 0x2d8, BIT(19) },
|
||||
[RST_BUS_SCR] = { 0x2d8, BIT(20) },
|
||||
[RST_BUS_SCR0] = { 0x2d8, BIT(20) },
|
||||
};
|
||||
|
||||
static struct ccu_reset_map sun50i_h5_ccu_resets[] = {
|
||||
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
|
||||
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
|
||||
[RST_USB_PHY2] = { 0x0cc, BIT(2) },
|
||||
[RST_USB_PHY3] = { 0x0cc, BIT(3) },
|
||||
|
||||
[RST_MBUS] = { 0x0fc, BIT(31) },
|
||||
|
||||
[RST_BUS_CE] = { 0x2c0, BIT(5) },
|
||||
[RST_BUS_DMA] = { 0x2c0, BIT(6) },
|
||||
[RST_BUS_MMC0] = { 0x2c0, BIT(8) },
|
||||
[RST_BUS_MMC1] = { 0x2c0, BIT(9) },
|
||||
[RST_BUS_MMC2] = { 0x2c0, BIT(10) },
|
||||
[RST_BUS_NAND] = { 0x2c0, BIT(13) },
|
||||
[RST_BUS_DRAM] = { 0x2c0, BIT(14) },
|
||||
[RST_BUS_EMAC] = { 0x2c0, BIT(17) },
|
||||
[RST_BUS_TS] = { 0x2c0, BIT(18) },
|
||||
[RST_BUS_HSTIMER] = { 0x2c0, BIT(19) },
|
||||
[RST_BUS_SPI0] = { 0x2c0, BIT(20) },
|
||||
[RST_BUS_SPI1] = { 0x2c0, BIT(21) },
|
||||
[RST_BUS_OTG] = { 0x2c0, BIT(23) },
|
||||
[RST_BUS_EHCI0] = { 0x2c0, BIT(24) },
|
||||
[RST_BUS_EHCI1] = { 0x2c0, BIT(25) },
|
||||
[RST_BUS_EHCI2] = { 0x2c0, BIT(26) },
|
||||
[RST_BUS_EHCI3] = { 0x2c0, BIT(27) },
|
||||
[RST_BUS_OHCI0] = { 0x2c0, BIT(28) },
|
||||
[RST_BUS_OHCI1] = { 0x2c0, BIT(29) },
|
||||
[RST_BUS_OHCI2] = { 0x2c0, BIT(30) },
|
||||
[RST_BUS_OHCI3] = { 0x2c0, BIT(31) },
|
||||
|
||||
[RST_BUS_VE] = { 0x2c4, BIT(0) },
|
||||
[RST_BUS_TCON0] = { 0x2c4, BIT(3) },
|
||||
[RST_BUS_TCON1] = { 0x2c4, BIT(4) },
|
||||
[RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) },
|
||||
[RST_BUS_CSI] = { 0x2c4, BIT(8) },
|
||||
[RST_BUS_TVE] = { 0x2c4, BIT(9) },
|
||||
[RST_BUS_HDMI0] = { 0x2c4, BIT(10) },
|
||||
[RST_BUS_HDMI1] = { 0x2c4, BIT(11) },
|
||||
[RST_BUS_DE] = { 0x2c4, BIT(12) },
|
||||
[RST_BUS_GPU] = { 0x2c4, BIT(20) },
|
||||
[RST_BUS_MSGBOX] = { 0x2c4, BIT(21) },
|
||||
[RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) },
|
||||
[RST_BUS_DBG] = { 0x2c4, BIT(31) },
|
||||
|
||||
[RST_BUS_EPHY] = { 0x2c8, BIT(2) },
|
||||
|
||||
[RST_BUS_CODEC] = { 0x2d0, BIT(0) },
|
||||
[RST_BUS_SPDIF] = { 0x2d0, BIT(1) },
|
||||
[RST_BUS_THS] = { 0x2d0, BIT(8) },
|
||||
[RST_BUS_I2S0] = { 0x2d0, BIT(12) },
|
||||
[RST_BUS_I2S1] = { 0x2d0, BIT(13) },
|
||||
[RST_BUS_I2S2] = { 0x2d0, BIT(14) },
|
||||
|
||||
[RST_BUS_I2C0] = { 0x2d8, BIT(0) },
|
||||
[RST_BUS_I2C1] = { 0x2d8, BIT(1) },
|
||||
[RST_BUS_I2C2] = { 0x2d8, BIT(2) },
|
||||
[RST_BUS_UART0] = { 0x2d8, BIT(16) },
|
||||
[RST_BUS_UART1] = { 0x2d8, BIT(17) },
|
||||
[RST_BUS_UART2] = { 0x2d8, BIT(18) },
|
||||
[RST_BUS_UART3] = { 0x2d8, BIT(19) },
|
||||
[RST_BUS_SCR0] = { 0x2d8, BIT(20) },
|
||||
[RST_BUS_SCR1] = { 0x2d8, BIT(20) },
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
|
||||
|
@ -803,6 +1093,16 @@ static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
|
|||
.num_resets = ARRAY_SIZE(sun8i_h3_ccu_resets),
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun50i_h5_ccu_desc = {
|
||||
.ccu_clks = sun50i_h5_ccu_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun50i_h5_ccu_clks),
|
||||
|
||||
.hw_clks = &sun50i_h5_hw_clks,
|
||||
|
||||
.resets = sun50i_h5_ccu_resets,
|
||||
.num_resets = ARRAY_SIZE(sun50i_h5_ccu_resets),
|
||||
};
|
||||
|
||||
static struct ccu_mux_nb sun8i_h3_cpu_nb = {
|
||||
.common = &cpux_clk.common,
|
||||
.cm = &cpux_clk.mux,
|
||||
|
@ -810,7 +1110,8 @@ static struct ccu_mux_nb sun8i_h3_cpu_nb = {
|
|||
.bypass_index = 1, /* index of 24 MHz oscillator */
|
||||
};
|
||||
|
||||
static void __init sun8i_h3_ccu_setup(struct device_node *node)
|
||||
static void __init sunxi_h3_h5_ccu_init(struct device_node *node,
|
||||
const struct sunxi_ccu_desc *desc)
|
||||
{
|
||||
void __iomem *reg;
|
||||
u32 val;
|
||||
|
@ -827,10 +1128,22 @@ static void __init sun8i_h3_ccu_setup(struct device_node *node)
|
|||
val &= ~GENMASK(19, 16);
|
||||
writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
|
||||
|
||||
sunxi_ccu_probe(node, reg, &sun8i_h3_ccu_desc);
|
||||
sunxi_ccu_probe(node, reg, desc);
|
||||
|
||||
ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
|
||||
&sun8i_h3_cpu_nb);
|
||||
}
|
||||
|
||||
static void __init sun8i_h3_ccu_setup(struct device_node *node)
|
||||
{
|
||||
sunxi_h3_h5_ccu_init(node, &sun8i_h3_ccu_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu",
|
||||
sun8i_h3_ccu_setup);
|
||||
|
||||
static void __init sun50i_h5_ccu_setup(struct device_node *node)
|
||||
{
|
||||
sunxi_h3_h5_ccu_init(node, &sun50i_h5_ccu_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(sun50i_h5_ccu, "allwinner,sun50i-h5-ccu",
|
||||
sun50i_h5_ccu_setup);
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
|
||||
/* And the GPU module clock is exported */
|
||||
|
||||
#define CLK_NUMBER (CLK_GPU + 1)
|
||||
#define CLK_NUMBER_H3 (CLK_GPU + 1)
|
||||
#define CLK_NUMBER_H5 (CLK_BUS_SCR1 + 1)
|
||||
|
||||
#endif /* _CCU_SUN8I_H3_H_ */
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
#include "ccu_reset.h"
|
||||
|
||||
#include "ccu_div.h"
|
||||
#include "ccu_gate.h"
|
||||
#include "ccu_mp.h"
|
||||
#include "ccu_nm.h"
|
||||
|
||||
#include "ccu-sun8i-r.h"
|
||||
|
||||
static const char * const ar100_parents[] = { "osc32k", "osc24M",
|
||||
"pll-periph0", "iosc" };
|
||||
|
||||
static struct ccu_div ar100_clk = {
|
||||
.div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
|
||||
|
||||
.mux = {
|
||||
.shift = 16,
|
||||
.width = 2,
|
||||
|
||||
.variable_prediv = {
|
||||
.index = 2,
|
||||
.shift = 8,
|
||||
.width = 5,
|
||||
},
|
||||
},
|
||||
|
||||
.common = {
|
||||
.reg = 0x00,
|
||||
.features = CCU_FEATURE_VARIABLE_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("ar100",
|
||||
ar100_parents,
|
||||
&ccu_div_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
||||
static CLK_FIXED_FACTOR(ahb0_clk, "ahb0", "ar100", 1, 1, 0);
|
||||
|
||||
static struct ccu_div apb0_clk = {
|
||||
.div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
|
||||
|
||||
.common = {
|
||||
.reg = 0x0c,
|
||||
.hw.init = CLK_HW_INIT("apb0",
|
||||
"ahb0",
|
||||
&ccu_div_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
||||
static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0",
|
||||
0x28, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(apb0_ir_clk, "apb0-ir", "apb0",
|
||||
0x28, BIT(1), 0);
|
||||
static SUNXI_CCU_GATE(apb0_timer_clk, "apb0-timer", "apb0",
|
||||
0x28, BIT(2), 0);
|
||||
static SUNXI_CCU_GATE(apb0_rsb_clk, "apb0-rsb", "apb0",
|
||||
0x28, BIT(3), 0);
|
||||
static SUNXI_CCU_GATE(apb0_uart_clk, "apb0-uart", "apb0",
|
||||
0x28, BIT(4), 0);
|
||||
static SUNXI_CCU_GATE(apb0_i2c_clk, "apb0-i2c", "apb0",
|
||||
0x28, BIT(6), 0);
|
||||
static SUNXI_CCU_GATE(apb0_twd_clk, "apb0-twd", "apb0",
|
||||
0x28, BIT(7), 0);
|
||||
|
||||
static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" };
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
|
||||
r_mod0_default_parents, 0x54,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
|
||||
static struct ccu_common *sun8i_h3_r_ccu_clks[] = {
|
||||
&ar100_clk.common,
|
||||
&apb0_clk.common,
|
||||
&apb0_pio_clk.common,
|
||||
&apb0_ir_clk.common,
|
||||
&apb0_timer_clk.common,
|
||||
&apb0_uart_clk.common,
|
||||
&apb0_i2c_clk.common,
|
||||
&apb0_twd_clk.common,
|
||||
&ir_clk.common,
|
||||
};
|
||||
|
||||
static struct ccu_common *sun50i_a64_r_ccu_clks[] = {
|
||||
&ar100_clk.common,
|
||||
&apb0_clk.common,
|
||||
&apb0_pio_clk.common,
|
||||
&apb0_ir_clk.common,
|
||||
&apb0_timer_clk.common,
|
||||
&apb0_rsb_clk.common,
|
||||
&apb0_uart_clk.common,
|
||||
&apb0_i2c_clk.common,
|
||||
&apb0_twd_clk.common,
|
||||
&ir_clk.common,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data sun8i_h3_r_hw_clks = {
|
||||
.hws = {
|
||||
[CLK_AR100] = &ar100_clk.common.hw,
|
||||
[CLK_AHB0] = &ahb0_clk.hw,
|
||||
[CLK_APB0] = &apb0_clk.common.hw,
|
||||
[CLK_APB0_PIO] = &apb0_pio_clk.common.hw,
|
||||
[CLK_APB0_IR] = &apb0_ir_clk.common.hw,
|
||||
[CLK_APB0_TIMER] = &apb0_timer_clk.common.hw,
|
||||
[CLK_APB0_UART] = &apb0_uart_clk.common.hw,
|
||||
[CLK_APB0_I2C] = &apb0_i2c_clk.common.hw,
|
||||
[CLK_APB0_TWD] = &apb0_twd_clk.common.hw,
|
||||
[CLK_IR] = &ir_clk.common.hw,
|
||||
},
|
||||
.num = CLK_NUMBER,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data sun50i_a64_r_hw_clks = {
|
||||
.hws = {
|
||||
[CLK_AR100] = &ar100_clk.common.hw,
|
||||
[CLK_AHB0] = &ahb0_clk.hw,
|
||||
[CLK_APB0] = &apb0_clk.common.hw,
|
||||
[CLK_APB0_PIO] = &apb0_pio_clk.common.hw,
|
||||
[CLK_APB0_IR] = &apb0_ir_clk.common.hw,
|
||||
[CLK_APB0_TIMER] = &apb0_timer_clk.common.hw,
|
||||
[CLK_APB0_RSB] = &apb0_rsb_clk.common.hw,
|
||||
[CLK_APB0_UART] = &apb0_uart_clk.common.hw,
|
||||
[CLK_APB0_I2C] = &apb0_i2c_clk.common.hw,
|
||||
[CLK_APB0_TWD] = &apb0_twd_clk.common.hw,
|
||||
[CLK_IR] = &ir_clk.common.hw,
|
||||
},
|
||||
.num = CLK_NUMBER,
|
||||
};
|
||||
|
||||
static struct ccu_reset_map sun8i_h3_r_ccu_resets[] = {
|
||||
[RST_APB0_IR] = { 0xb0, BIT(1) },
|
||||
[RST_APB0_TIMER] = { 0xb0, BIT(2) },
|
||||
[RST_APB0_UART] = { 0xb0, BIT(4) },
|
||||
[RST_APB0_I2C] = { 0xb0, BIT(6) },
|
||||
};
|
||||
|
||||
static struct ccu_reset_map sun50i_a64_r_ccu_resets[] = {
|
||||
[RST_APB0_IR] = { 0xb0, BIT(1) },
|
||||
[RST_APB0_TIMER] = { 0xb0, BIT(2) },
|
||||
[RST_APB0_RSB] = { 0xb0, BIT(3) },
|
||||
[RST_APB0_UART] = { 0xb0, BIT(4) },
|
||||
[RST_APB0_I2C] = { 0xb0, BIT(6) },
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun8i_h3_r_ccu_desc = {
|
||||
.ccu_clks = sun8i_h3_r_ccu_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun8i_h3_r_ccu_clks),
|
||||
|
||||
.hw_clks = &sun8i_h3_r_hw_clks,
|
||||
|
||||
.resets = sun8i_h3_r_ccu_resets,
|
||||
.num_resets = ARRAY_SIZE(sun8i_h3_r_ccu_resets),
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun50i_a64_r_ccu_desc = {
|
||||
.ccu_clks = sun50i_a64_r_ccu_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun50i_a64_r_ccu_clks),
|
||||
|
||||
.hw_clks = &sun50i_a64_r_hw_clks,
|
||||
|
||||
.resets = sun50i_a64_r_ccu_resets,
|
||||
.num_resets = ARRAY_SIZE(sun50i_a64_r_ccu_resets),
|
||||
};
|
||||
|
||||
static void __init sunxi_r_ccu_init(struct device_node *node,
|
||||
const struct sunxi_ccu_desc *desc)
|
||||
{
|
||||
void __iomem *reg;
|
||||
|
||||
reg = of_io_request_and_map(node, 0, of_node_full_name(node));
|
||||
if (IS_ERR(reg)) {
|
||||
pr_err("%s: Could not map the clock registers\n",
|
||||
of_node_full_name(node));
|
||||
return;
|
||||
}
|
||||
|
||||
sunxi_ccu_probe(node, reg, desc);
|
||||
}
|
||||
|
||||
static void __init sun8i_h3_r_ccu_setup(struct device_node *node)
|
||||
{
|
||||
sunxi_r_ccu_init(node, &sun8i_h3_r_ccu_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(sun8i_h3_r_ccu, "allwinner,sun8i-h3-r-ccu",
|
||||
sun8i_h3_r_ccu_setup);
|
||||
|
||||
static void __init sun50i_a64_r_ccu_setup(struct device_node *node)
|
||||
{
|
||||
sunxi_r_ccu_init(node, &sun50i_a64_r_ccu_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(sun50i_a64_r_ccu, "allwinner,sun50i-a64-r-ccu",
|
||||
sun50i_a64_r_ccu_setup);
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2016 Icenowy <icenowy@aosc.xyz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 _CCU_SUN8I_R_H
|
||||
#define _CCU_SUN8I_R_H_
|
||||
|
||||
#include <dt-bindings/clock/sun8i-r-ccu.h>
|
||||
#include <dt-bindings/reset/sun8i-r-ccu.h>
|
||||
|
||||
/* AHB/APB bus clocks are not exported */
|
||||
#define CLK_AHB0 1
|
||||
#define CLK_APB0 2
|
||||
|
||||
#define CLK_NUMBER (CLK_IR + 1)
|
||||
|
||||
#endif /* _CCU_SUN8I_R_H */
|
|
@ -29,49 +29,48 @@
|
|||
|
||||
#define CCU_SUN9I_LOCK_REG 0x09c
|
||||
|
||||
static struct clk_div_table pll_cpux_p_div_table[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 1, .div = 4 },
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
||||
/*
|
||||
* The CPU PLLs are actually NP clocks, but P is /1 or /4, so here we
|
||||
* use the NM clocks with a divider table for M.
|
||||
* The CPU PLLs are actually NP clocks, with P being /1 or /4. However
|
||||
* P should only be used for output frequencies lower than 228 MHz.
|
||||
* Neither mainline Linux, U-boot, nor the vendor BSPs use these.
|
||||
*
|
||||
* For now we can just model it as a multiplier clock, and force P to /1.
|
||||
*/
|
||||
static struct ccu_nm pll_c0cpux_clk = {
|
||||
#define SUN9I_A80_PLL_C0CPUX_REG 0x000
|
||||
#define SUN9I_A80_PLL_C1CPUX_REG 0x004
|
||||
|
||||
static struct ccu_mult pll_c0cpux_clk = {
|
||||
.enable = BIT(31),
|
||||
.lock = BIT(0),
|
||||
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
|
||||
.m = _SUNXI_CCU_DIV_TABLE(16, 1, pll_cpux_p_div_table),
|
||||
.mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
|
||||
.common = {
|
||||
.reg = 0x000,
|
||||
.reg = SUN9I_A80_PLL_C0CPUX_REG,
|
||||
.lock_reg = CCU_SUN9I_LOCK_REG,
|
||||
.features = CCU_FEATURE_LOCK_REG,
|
||||
.hw.init = CLK_HW_INIT("pll-c0cpux", "osc24M",
|
||||
&ccu_nm_ops, CLK_SET_RATE_UNGATE),
|
||||
&ccu_mult_ops,
|
||||
CLK_SET_RATE_UNGATE),
|
||||
},
|
||||
};
|
||||
|
||||
static struct ccu_nm pll_c1cpux_clk = {
|
||||
static struct ccu_mult pll_c1cpux_clk = {
|
||||
.enable = BIT(31),
|
||||
.lock = BIT(1),
|
||||
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
|
||||
.m = _SUNXI_CCU_DIV_TABLE(16, 1, pll_cpux_p_div_table),
|
||||
.mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
|
||||
.common = {
|
||||
.reg = 0x004,
|
||||
.reg = SUN9I_A80_PLL_C1CPUX_REG,
|
||||
.lock_reg = CCU_SUN9I_LOCK_REG,
|
||||
.features = CCU_FEATURE_LOCK_REG,
|
||||
.hw.init = CLK_HW_INIT("pll-c1cpux", "osc24M",
|
||||
&ccu_nm_ops, CLK_SET_RATE_UNGATE),
|
||||
&ccu_mult_ops,
|
||||
CLK_SET_RATE_UNGATE),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* The Audio PLL has d1, d2 dividers in addition to the usual N, M
|
||||
* factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
|
||||
* and 24.576 MHz, ignore them for now. Enforce the default for them,
|
||||
* which is d1 = 0, d2 = 1.
|
||||
* and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
|
||||
*/
|
||||
#define SUN9I_A80_PLL_AUDIO_REG 0x008
|
||||
|
||||
|
@ -1189,6 +1188,36 @@ static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
|
|||
.num_resets = ARRAY_SIZE(sun9i_a80_ccu_resets),
|
||||
};
|
||||
|
||||
#define SUN9I_A80_PLL_P_SHIFT 16
|
||||
#define SUN9I_A80_PLL_N_SHIFT 8
|
||||
#define SUN9I_A80_PLL_N_WIDTH 8
|
||||
|
||||
static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
|
||||
{
|
||||
u32 val = readl(reg);
|
||||
|
||||
/* bail out if P divider is not used */
|
||||
if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If P is used, output should be less than 288 MHz. When we
|
||||
* set P to 1, we should also decrease the multiplier so the
|
||||
* output doesn't go out of range, but not too much such that
|
||||
* the multiplier stays above 12, the minimal operation value.
|
||||
*
|
||||
* To keep it simple, set the multiplier to 17, the reset value.
|
||||
*/
|
||||
val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
|
||||
SUN9I_A80_PLL_N_SHIFT);
|
||||
val |= 17 << SUN9I_A80_PLL_N_SHIFT;
|
||||
|
||||
/* And clear P */
|
||||
val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
|
||||
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
static int sun9i_a80_ccu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
|
@ -1205,6 +1234,10 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev)
|
|||
val &= (BIT(16) & BIT(18));
|
||||
writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
|
||||
|
||||
/* Enforce P = 1 for both CPU cluster PLLs */
|
||||
sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
|
||||
sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
|
||||
|
||||
return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,8 +112,8 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
|
|||
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
if (ret) {
|
||||
pr_err("Couldn't register clock %s\n",
|
||||
clk_hw_get_name(hw));
|
||||
pr_err("Couldn't register clock %d - %s\n",
|
||||
i, clk_hw_get_name(hw));
|
||||
goto err_clk_unreg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,8 +75,55 @@ static int ccu_gate_is_enabled(struct clk_hw *hw)
|
|||
return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
|
||||
}
|
||||
|
||||
static unsigned long ccu_gate_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_gate *cg = hw_to_ccu_gate(hw);
|
||||
unsigned long rate = parent_rate;
|
||||
|
||||
if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
|
||||
rate /= cg->common.prediv;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static long ccu_gate_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct ccu_gate *cg = hw_to_ccu_gate(hw);
|
||||
int div = 1;
|
||||
|
||||
if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
|
||||
div = cg->common.prediv;
|
||||
|
||||
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
|
||||
unsigned long best_parent = rate;
|
||||
|
||||
if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
|
||||
best_parent *= div;
|
||||
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
|
||||
}
|
||||
|
||||
return *prate / div;
|
||||
}
|
||||
|
||||
static int ccu_gate_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;
|
||||
}
|
||||
|
||||
const struct clk_ops ccu_gate_ops = {
|
||||
.disable = ccu_gate_disable,
|
||||
.enable = ccu_gate_enable,
|
||||
.is_enabled = ccu_gate_is_enabled,
|
||||
.round_rate = ccu_gate_round_rate,
|
||||
.set_rate = ccu_gate_set_rate,
|
||||
.recalc_rate = ccu_gate_recalc_rate,
|
||||
};
|
||||
|
|
|
@ -137,6 +137,8 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
|
||||
spin_unlock_irqrestore(cm->common.lock, flags);
|
||||
|
||||
ccu_helper_wait_for_lock(&cm->common, cm->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ struct ccu_mult_internal {
|
|||
|
||||
struct ccu_mult {
|
||||
u32 enable;
|
||||
u32 lock;
|
||||
|
||||
struct ccu_frac_internal frac;
|
||||
struct ccu_mult_internal mult;
|
||||
|
@ -45,6 +46,7 @@ struct ccu_mult {
|
|||
_flags) \
|
||||
struct ccu_mult _struct = { \
|
||||
.enable = _gate, \
|
||||
.lock = _lock, \
|
||||
.mult = _SUNXI_CCU_MULT(_mshift, _mwidth), \
|
||||
.common = { \
|
||||
.reg = _reg, \
|
||||
|
|
|
@ -102,9 +102,9 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate *= nk->fixed_post_div;
|
||||
|
||||
_nk.min_n = nk->n.min;
|
||||
_nk.min_n = nk->n.min ?: 1;
|
||||
_nk.max_n = nk->n.max ?: 1 << nk->n.width;
|
||||
_nk.min_k = nk->k.min;
|
||||
_nk.min_k = nk->k.min ?: 1;
|
||||
_nk.max_k = nk->k.max ?: 1 << nk->k.width;
|
||||
|
||||
ccu_nk_find_best(*parent_rate, rate, &_nk);
|
||||
|
@ -127,9 +127,9 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate = rate * nk->fixed_post_div;
|
||||
|
||||
_nk.min_n = nk->n.min;
|
||||
_nk.min_n = nk->n.min ?: 1;
|
||||
_nk.max_n = nk->n.max ?: 1 << nk->n.width;
|
||||
_nk.min_k = nk->k.min;
|
||||
_nk.min_k = nk->k.min ?: 1;
|
||||
_nk.max_k = nk->k.max ?: 1 << nk->k.width;
|
||||
|
||||
ccu_nk_find_best(parent_rate, rate, &_nk);
|
||||
|
|
|
@ -109,9 +109,9 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
|
|||
struct ccu_nkm *nkm = data;
|
||||
struct _ccu_nkm _nkm;
|
||||
|
||||
_nkm.min_n = nkm->n.min;
|
||||
_nkm.min_n = nkm->n.min ?: 1;
|
||||
_nkm.max_n = nkm->n.max ?: 1 << nkm->n.width;
|
||||
_nkm.min_k = nkm->k.min;
|
||||
_nkm.min_k = nkm->k.min ?: 1;
|
||||
_nkm.max_k = nkm->k.max ?: 1 << nkm->k.width;
|
||||
_nkm.min_m = 1;
|
||||
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
|
||||
|
@ -138,9 +138,9 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
_nkm.min_n = nkm->n.min;
|
||||
_nkm.min_n = nkm->n.min ?: 1;
|
||||
_nkm.max_n = nkm->n.max ?: 1 << nkm->n.width;
|
||||
_nkm.min_k = nkm->k.min;
|
||||
_nkm.min_k = nkm->k.min ?: 1;
|
||||
_nkm.max_k = nkm->k.max ?: 1 << nkm->k.width;
|
||||
_nkm.min_m = 1;
|
||||
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
|
||||
|
|
|
@ -116,9 +116,9 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
|
||||
struct _ccu_nkmp _nkmp;
|
||||
|
||||
_nkmp.min_n = nkmp->n.min;
|
||||
_nkmp.min_n = nkmp->n.min ?: 1;
|
||||
_nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
|
||||
_nkmp.min_k = nkmp->k.min;
|
||||
_nkmp.min_k = nkmp->k.min ?: 1;
|
||||
_nkmp.max_k = nkmp->k.max ?: 1 << nkmp->k.width;
|
||||
_nkmp.min_m = 1;
|
||||
_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
|
||||
|
@ -138,9 +138,9 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
_nkmp.min_n = 1;
|
||||
_nkmp.min_n = nkmp->n.min ?: 1;
|
||||
_nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
|
||||
_nkmp.min_k = 1;
|
||||
_nkmp.min_k = nkmp->k.min ?: 1;
|
||||
_nkmp.max_k = nkmp->k.max ?: 1 << nkmp->k.width;
|
||||
_nkmp.min_m = 1;
|
||||
_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
|
||||
|
|
|
@ -99,7 +99,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
struct ccu_nm *nm = hw_to_ccu_nm(hw);
|
||||
struct _ccu_nm _nm;
|
||||
|
||||
_nm.min_n = nm->n.min;
|
||||
_nm.min_n = nm->n.min ?: 1;
|
||||
_nm.max_n = nm->n.max ?: 1 << nm->n.width;
|
||||
_nm.min_m = 1;
|
||||
_nm.max_m = nm->m.max ?: 1 << nm->m.width;
|
||||
|
@ -122,7 +122,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
else
|
||||
ccu_frac_helper_disable(&nm->common, &nm->frac);
|
||||
|
||||
_nm.min_n = 1;
|
||||
_nm.min_n = nm->n.min ?: 1;
|
||||
_nm.max_n = nm->n.max ?: 1 << nm->n.width;
|
||||
_nm.min_m = 1;
|
||||
_nm.max_m = nm->m.max ?: 1 << nm->m.width;
|
||||
|
|
|
@ -307,6 +307,23 @@ enum clk_id {
|
|||
tegra_clk_xusb_ssp_src,
|
||||
tegra_clk_sclk_mux,
|
||||
tegra_clk_sor_safe,
|
||||
tegra_clk_cec,
|
||||
tegra_clk_ispa,
|
||||
tegra_clk_dmic1,
|
||||
tegra_clk_dmic2,
|
||||
tegra_clk_dmic3,
|
||||
tegra_clk_dmic1_sync_clk,
|
||||
tegra_clk_dmic2_sync_clk,
|
||||
tegra_clk_dmic3_sync_clk,
|
||||
tegra_clk_dmic1_sync_clk_mux,
|
||||
tegra_clk_dmic2_sync_clk_mux,
|
||||
tegra_clk_dmic3_sync_clk_mux,
|
||||
tegra_clk_iqc1,
|
||||
tegra_clk_iqc2,
|
||||
tegra_clk_pll_a_out_adsp,
|
||||
tegra_clk_pll_a_out0_out_adsp,
|
||||
tegra_clk_adsp,
|
||||
tegra_clk_adsp_neon,
|
||||
tegra_clk_max,
|
||||
};
|
||||
|
||||
|
|
|
@ -159,6 +159,9 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
|
|||
gate->enable_refcnt = enable_refcnt;
|
||||
gate->regs = pregs;
|
||||
|
||||
if (read_enb(gate) & periph_clk_to_bit(gate))
|
||||
enable_refcnt[clk_num]++;
|
||||
|
||||
/* Data in .init is copied by clk_register(), so stack variable OK */
|
||||
gate->hw.init = &init;
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = {
|
|||
};
|
||||
|
||||
static struct clk *_tegra_clk_register_periph(const char *name,
|
||||
const char **parent_names, int num_parents,
|
||||
const char * const *parent_names, int num_parents,
|
||||
struct tegra_clk_periph *periph,
|
||||
void __iomem *clk_base, u32 offset,
|
||||
unsigned long flags)
|
||||
|
@ -186,7 +186,7 @@ static struct clk *_tegra_clk_register_periph(const char *name,
|
|||
}
|
||||
|
||||
struct clk *tegra_clk_register_periph(const char *name,
|
||||
const char **parent_names, int num_parents,
|
||||
const char * const *parent_names, int num_parents,
|
||||
struct tegra_clk_periph *periph, void __iomem *clk_base,
|
||||
u32 offset, unsigned long flags)
|
||||
{
|
||||
|
@ -195,7 +195,7 @@ struct clk *tegra_clk_register_periph(const char *name,
|
|||
}
|
||||
|
||||
struct clk *tegra_clk_register_periph_nodiv(const char *name,
|
||||
const char **parent_names, int num_parents,
|
||||
const char * const *parent_names, int num_parents,
|
||||
struct tegra_clk_periph *periph, void __iomem *clk_base,
|
||||
u32 offset)
|
||||
{
|
||||
|
|
|
@ -2517,152 +2517,6 @@ static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
|
|||
return val & PLLE_BASE_ENABLE ? 1 : 0;
|
||||
}
|
||||
|
||||
static int clk_pllu_tegra210_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||
struct clk_hw *pll_ref = clk_hw_get_parent(hw);
|
||||
struct clk_hw *osc = clk_hw_get_parent(pll_ref);
|
||||
const struct utmi_clk_param *params = NULL;
|
||||
unsigned long flags = 0, input_rate;
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
u32 value;
|
||||
|
||||
if (!osc) {
|
||||
pr_err("%s: failed to get OSC clock\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input_rate = clk_hw_get_rate(osc);
|
||||
|
||||
if (pll->lock)
|
||||
spin_lock_irqsave(pll->lock, flags);
|
||||
|
||||
_clk_pll_enable(hw);
|
||||
|
||||
ret = clk_pll_wait_for_lock(pll);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
|
||||
if (input_rate == utmi_parameters[i].osc_frequency) {
|
||||
params = &utmi_parameters[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!params) {
|
||||
pr_err("%s: unexpected input rate %lu Hz\n", __func__,
|
||||
input_rate);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = pll_readl_base(pll);
|
||||
value &= ~PLLU_BASE_OVERRIDE;
|
||||
pll_writel_base(value, pll);
|
||||
|
||||
/* Put PLLU under HW control */
|
||||
value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
value |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
|
||||
PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
|
||||
PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
|
||||
value &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
|
||||
PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
|
||||
writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
|
||||
value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
|
||||
value &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY;
|
||||
writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
value |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
|
||||
writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Disable PLLU clock branch to UTMIPLL since it uses OSC */
|
||||
value = pll_readl_base(pll);
|
||||
value &= ~PLLU_BASE_CLKENABLE_USB;
|
||||
pll_writel_base(value, pll);
|
||||
|
||||
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
if (value & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE) {
|
||||
pr_debug("UTMIPLL already enabled\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
|
||||
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
|
||||
/* Program UTMIP PLL stable and active counts */
|
||||
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
|
||||
value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
|
||||
value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
|
||||
value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
|
||||
value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
|
||||
value |= UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN;
|
||||
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
|
||||
|
||||
/* Program UTMIP PLL delay and oscillator frequency counts */
|
||||
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
|
||||
value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
|
||||
value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
|
||||
value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
|
||||
value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
|
||||
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
|
||||
|
||||
/* Remove power downs from UTMIP PLL control bits */
|
||||
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
|
||||
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
|
||||
value |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
|
||||
writel(value, pll->clk_base + UTMIP_PLL_CFG1);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
|
||||
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
|
||||
value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
|
||||
value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
|
||||
value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
|
||||
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
|
||||
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
|
||||
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
|
||||
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
|
||||
|
||||
/* Setup HW control of UTMIPLL */
|
||||
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
|
||||
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
|
||||
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
|
||||
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
|
||||
|
||||
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
|
||||
value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
|
||||
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
|
||||
value &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
|
||||
writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Enable HW control of UTMIPLL */
|
||||
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
|
||||
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
|
||||
out:
|
||||
if (pll->lock)
|
||||
spin_unlock_irqrestore(pll->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct clk_ops tegra_clk_plle_tegra210_ops = {
|
||||
.is_enabled = clk_plle_tegra210_is_enabled,
|
||||
.enable = clk_plle_tegra210_enable,
|
||||
|
@ -2670,13 +2524,6 @@ static const struct clk_ops tegra_clk_plle_tegra210_ops = {
|
|||
.recalc_rate = clk_pll_recalc_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops tegra_clk_pllu_tegra210_ops = {
|
||||
.is_enabled = clk_pll_is_enabled,
|
||||
.enable = clk_pllu_tegra210_enable,
|
||||
.disable = clk_pll_disable,
|
||||
.recalc_rate = clk_pllre_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk *tegra_clk_register_plle_tegra210(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *clk_base, unsigned long flags,
|
||||
|
@ -2918,25 +2765,4 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
|
|||
return clk;
|
||||
}
|
||||
|
||||
struct clk *tegra_clk_register_pllu_tegra210(const char *name,
|
||||
const char *parent_name, void __iomem *clk_base,
|
||||
unsigned long flags, struct tegra_clk_pll_params *pll_params,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct tegra_clk_pll *pll;
|
||||
struct clk *clk;
|
||||
|
||||
pll_params->flags |= TEGRA_PLLU;
|
||||
|
||||
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
|
||||
if (IS_ERR(pll))
|
||||
return ERR_CAST(pll);
|
||||
|
||||
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
|
||||
&tegra_clk_pllu_tegra210_ops);
|
||||
if (IS_ERR(clk))
|
||||
kfree(pll);
|
||||
|
||||
return clk;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -121,9 +121,50 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
const struct clk_ops tegra_clk_super_mux_ops = {
|
||||
.get_parent = clk_super_get_parent,
|
||||
.set_parent = clk_super_set_parent,
|
||||
};
|
||||
|
||||
static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||
struct clk_hw *div_hw = &super->frac_div.hw;
|
||||
|
||||
__clk_hw_set_clk(div_hw, hw);
|
||||
|
||||
return super->div_ops->round_rate(div_hw, rate, parent_rate);
|
||||
}
|
||||
|
||||
static unsigned long clk_super_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||
struct clk_hw *div_hw = &super->frac_div.hw;
|
||||
|
||||
__clk_hw_set_clk(div_hw, hw);
|
||||
|
||||
return super->div_ops->recalc_rate(div_hw, parent_rate);
|
||||
}
|
||||
|
||||
static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||
struct clk_hw *div_hw = &super->frac_div.hw;
|
||||
|
||||
__clk_hw_set_clk(div_hw, hw);
|
||||
|
||||
return super->div_ops->set_rate(div_hw, rate, parent_rate);
|
||||
}
|
||||
|
||||
const struct clk_ops tegra_clk_super_ops = {
|
||||
.get_parent = clk_super_get_parent,
|
||||
.set_parent = clk_super_set_parent,
|
||||
.set_rate = clk_super_set_rate,
|
||||
.round_rate = clk_super_round_rate,
|
||||
.recalc_rate = clk_super_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk *tegra_clk_register_super_mux(const char *name,
|
||||
|
@ -136,13 +177,11 @@ struct clk *tegra_clk_register_super_mux(const char *name,
|
|||
struct clk_init_data init;
|
||||
|
||||
super = kzalloc(sizeof(*super), GFP_KERNEL);
|
||||
if (!super) {
|
||||
pr_err("%s: could not allocate super clk\n", __func__);
|
||||
if (!super)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &tegra_clk_super_ops;
|
||||
init.ops = &tegra_clk_super_mux_ops;
|
||||
init.flags = flags;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
|
@ -163,3 +202,43 @@ struct clk *tegra_clk_register_super_mux(const char *name,
|
|||
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct clk *tegra_clk_register_super_clk(const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct tegra_clk_super_mux *super;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
|
||||
super = kzalloc(sizeof(*super), GFP_KERNEL);
|
||||
if (!super)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &tegra_clk_super_ops;
|
||||
init.flags = flags;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
|
||||
super->reg = reg;
|
||||
super->lock = lock;
|
||||
super->width = 4;
|
||||
super->flags = clk_super_flags;
|
||||
super->frac_div.reg = reg + 4;
|
||||
super->frac_div.shift = 16;
|
||||
super->frac_div.width = 8;
|
||||
super->frac_div.frac_width = 1;
|
||||
super->frac_div.lock = lock;
|
||||
super->div_ops = &tegra_clk_frac_div_ops;
|
||||
|
||||
/* Data in .init is copied by clk_register(), so stack variable OK */
|
||||
super->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &super->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(super);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#define AUDIO_SYNC_CLK_I2S3 0x4ac
|
||||
#define AUDIO_SYNC_CLK_I2S4 0x4b0
|
||||
#define AUDIO_SYNC_CLK_SPDIF 0x4b4
|
||||
#define AUDIO_SYNC_CLK_DMIC1 0x560
|
||||
#define AUDIO_SYNC_CLK_DMIC2 0x564
|
||||
#define AUDIO_SYNC_CLK_DMIC3 0x6b8
|
||||
|
||||
#define AUDIO_SYNC_DOUBLER 0x49c
|
||||
|
||||
|
@ -91,8 +94,14 @@ struct tegra_audio2x_clk_initdata {
|
|||
|
||||
static DEFINE_SPINLOCK(clk_doubler_lock);
|
||||
|
||||
static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
|
||||
"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
|
||||
static const char * const mux_audio_sync_clk[] = { "spdif_in_sync",
|
||||
"i2s0_sync", "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync",
|
||||
"pll_a_out0", "vimclk_sync",
|
||||
};
|
||||
|
||||
static const char * const mux_dmic_sync_clk[] = { "unused", "i2s0_sync",
|
||||
"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "pll_a_out0",
|
||||
"vimclk_sync",
|
||||
};
|
||||
|
||||
static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {
|
||||
|
@ -114,6 +123,12 @@ static struct tegra_audio_clk_initdata audio_clks[] = {
|
|||
AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),
|
||||
};
|
||||
|
||||
static struct tegra_audio_clk_initdata dmic_clks[] = {
|
||||
AUDIO(dmic1_sync_clk, AUDIO_SYNC_CLK_DMIC1),
|
||||
AUDIO(dmic2_sync_clk, AUDIO_SYNC_CLK_DMIC2),
|
||||
AUDIO(dmic3_sync_clk, AUDIO_SYNC_CLK_DMIC3),
|
||||
};
|
||||
|
||||
static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
|
||||
AUDIO2X(audio0, 113, 24),
|
||||
AUDIO2X(audio1, 114, 25),
|
||||
|
@ -123,6 +138,41 @@ static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
|
|||
AUDIO2X(spdif, 118, 29),
|
||||
};
|
||||
|
||||
static void __init tegra_audio_sync_clk_init(void __iomem *clk_base,
|
||||
struct tegra_clk *tegra_clks,
|
||||
struct tegra_audio_clk_initdata *sync,
|
||||
int num_sync_clks,
|
||||
const char * const *mux_names,
|
||||
int num_mux_inputs)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk **dt_clk;
|
||||
struct tegra_audio_clk_initdata *data;
|
||||
int i;
|
||||
|
||||
for (i = 0, data = sync; i < num_sync_clks; i++, data++) {
|
||||
dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
|
||||
if (!dt_clk)
|
||||
continue;
|
||||
|
||||
clk = clk_register_mux(NULL, data->mux_name, mux_names,
|
||||
num_mux_inputs,
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
clk_base + data->offset, 0, 3, 0,
|
||||
NULL);
|
||||
*dt_clk = clk;
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
|
||||
if (!dt_clk)
|
||||
continue;
|
||||
|
||||
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
|
||||
0, clk_base + data->offset, 4,
|
||||
CLK_GATE_SET_TO_DISABLE, NULL);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void __init tegra_audio_clk_init(void __iomem *clk_base,
|
||||
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||
struct tegra_audio_clk_info *audio_info,
|
||||
|
@ -176,30 +226,17 @@ void __init tegra_audio_clk_init(void __iomem *clk_base,
|
|||
*dt_clk = clk;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(audio_clks); i++) {
|
||||
struct tegra_audio_clk_initdata *data;
|
||||
tegra_audio_sync_clk_init(clk_base, tegra_clks, audio_clks,
|
||||
ARRAY_SIZE(audio_clks), mux_audio_sync_clk,
|
||||
ARRAY_SIZE(mux_audio_sync_clk));
|
||||
|
||||
data = &audio_clks[i];
|
||||
dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
|
||||
/* make sure the DMIC sync clocks have a valid parent */
|
||||
for (i = 0; i < ARRAY_SIZE(dmic_clks); i++)
|
||||
writel_relaxed(1, clk_base + dmic_clks[i].offset);
|
||||
|
||||
if (!dt_clk)
|
||||
continue;
|
||||
clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk,
|
||||
ARRAY_SIZE(mux_audio_sync_clk),
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
clk_base + data->offset, 0, 3, 0,
|
||||
NULL);
|
||||
*dt_clk = clk;
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
|
||||
if (!dt_clk)
|
||||
continue;
|
||||
|
||||
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
|
||||
0, clk_base + data->offset, 4,
|
||||
CLK_GATE_SET_TO_DISABLE, NULL);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
tegra_audio_sync_clk_init(clk_base, tegra_clks, dmic_clks,
|
||||
ARRAY_SIZE(dmic_clks), mux_dmic_sync_clk,
|
||||
ARRAY_SIZE(mux_dmic_sync_clk));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) {
|
||||
struct tegra_audio2x_clk_initdata *data;
|
||||
|
|
|
@ -138,6 +138,9 @@
|
|||
#define CLK_SOURCE_TSECB 0x6d8
|
||||
#define CLK_SOURCE_MAUD 0x6d4
|
||||
#define CLK_SOURCE_USB2_HSIC_TRK 0x6cc
|
||||
#define CLK_SOURCE_DMIC1 0x64c
|
||||
#define CLK_SOURCE_DMIC2 0x650
|
||||
#define CLK_SOURCE_DMIC3 0x6bc
|
||||
|
||||
#define MASK(x) (BIT(x) - 1)
|
||||
|
||||
|
@ -168,6 +171,12 @@
|
|||
0, TEGRA_PERIPH_NO_GATE, _clk_id,\
|
||||
_parents##_idx, 0, _lock)
|
||||
|
||||
#define MUX8_NOGATE(_name, _parents, _offset, _clk_id) \
|
||||
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
|
||||
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
|
||||
0, TEGRA_PERIPH_NO_GATE, _clk_id,\
|
||||
_parents##_idx, 0, NULL)
|
||||
|
||||
#define INT(_name, _parents, _offset, \
|
||||
_clk_num, _gate_flags, _clk_id) \
|
||||
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||
|
@ -619,6 +628,21 @@ static const char *mux_clkm_plldp_sor0lvds[] = {
|
|||
};
|
||||
#define mux_clkm_plldp_sor0lvds_idx NULL
|
||||
|
||||
static const char * const mux_dmic1[] = {
|
||||
"pll_a_out0", "dmic1_sync_clk", "pll_p", "clk_m"
|
||||
};
|
||||
#define mux_dmic1_idx NULL
|
||||
|
||||
static const char * const mux_dmic2[] = {
|
||||
"pll_a_out0", "dmic2_sync_clk", "pll_p", "clk_m"
|
||||
};
|
||||
#define mux_dmic2_idx NULL
|
||||
|
||||
static const char * const mux_dmic3[] = {
|
||||
"pll_a_out0", "dmic3_sync_clk", "pll_p", "clk_m"
|
||||
};
|
||||
#define mux_dmic3_idx NULL
|
||||
|
||||
static struct tegra_periph_init_data periph_clks[] = {
|
||||
AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio),
|
||||
AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0),
|
||||
|
@ -739,7 +763,7 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
|
||||
MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
|
||||
MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
|
||||
MUX8("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_9),
|
||||
MUX8_NOGATE("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, tegra_clk_isp_9),
|
||||
MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy),
|
||||
MUX8("entropy", mux_pllp_clkm_clk32_plle, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy_8),
|
||||
MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
|
||||
|
@ -788,6 +812,9 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape),
|
||||
MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb),
|
||||
MUX8("maud", mux_pllp_pllp_out3_clkm_clk32k_plla, CLK_SOURCE_MAUD, 202, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_maud),
|
||||
MUX8("dmic1", mux_dmic1, CLK_SOURCE_DMIC1, 161, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic1),
|
||||
MUX8("dmic2", mux_dmic2, CLK_SOURCE_DMIC2, 162, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic2),
|
||||
MUX8("dmic3", mux_dmic3, CLK_SOURCE_DMIC3, 197, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic3),
|
||||
};
|
||||
|
||||
static struct tegra_periph_init_data gate_clks[] = {
|
||||
|
@ -809,7 +836,7 @@ static struct tegra_periph_init_data gate_clks[] = {
|
|||
GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
|
||||
GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
|
||||
GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0),
|
||||
GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0),
|
||||
GATE("afi", "mselect", 72, 0, tegra_clk_afi, 0),
|
||||
GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0),
|
||||
GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0),
|
||||
GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0),
|
||||
|
@ -819,7 +846,8 @@ static struct tegra_periph_init_data gate_clks[] = {
|
|||
GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
|
||||
GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
|
||||
GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
|
||||
GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
|
||||
GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0),
|
||||
GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0),
|
||||
GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
|
||||
GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
|
||||
GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
|
||||
|
@ -830,6 +858,13 @@ static struct tegra_periph_init_data gate_clks[] = {
|
|||
GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0),
|
||||
GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0),
|
||||
GATE("apb2ape", "clk_m", 107, 0, tegra_clk_apb2ape, 0),
|
||||
GATE("cec", "pclk", 136, 0, tegra_clk_cec, 0),
|
||||
GATE("iqc1", "clk_m", 221, 0, tegra_clk_iqc1, 0),
|
||||
GATE("iqc2", "clk_m", 220, 0, tegra_clk_iqc1, 0),
|
||||
GATE("pll_a_out_adsp", "pll_a", 188, 0, tegra_clk_pll_a_out_adsp, 0),
|
||||
GATE("pll_a_out0_out_adsp", "pll_a", 188, 0, tegra_clk_pll_a_out0_out_adsp, 0),
|
||||
GATE("adsp", "aclk", 199, 0, tegra_clk_adsp, 0),
|
||||
GATE("adsp_neon", "aclk", 218, 0, tegra_clk_adsp_neon, 0),
|
||||
};
|
||||
|
||||
static struct tegra_periph_init_data div_clks[] = {
|
||||
|
|
|
@ -95,7 +95,8 @@ void __init tegra_pmc_clk_init(void __iomem *pmc_base,
|
|||
continue;
|
||||
|
||||
clk = clk_register_mux(NULL, data->mux_name, data->parents,
|
||||
data->num_parents, CLK_SET_RATE_NO_REPARENT,
|
||||
data->num_parents,
|
||||
CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
|
||||
pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
|
||||
3, 0, &clk_out_lock);
|
||||
*dt_clk = clk;
|
||||
|
@ -106,7 +107,8 @@ void __init tegra_pmc_clk_init(void __iomem *pmc_base,
|
|||
continue;
|
||||
|
||||
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
|
||||
0, pmc_base + PMC_CLK_OUT_CNTRL,
|
||||
CLK_SET_RATE_PARENT,
|
||||
pmc_base + PMC_CLK_OUT_CNTRL,
|
||||
data->gate_shift, 0, &clk_out_lock);
|
||||
*dt_clk = clk;
|
||||
clk_register_clkdev(clk, data->dev_name, data->gate_name);
|
||||
|
|
|
@ -819,6 +819,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
|
|||
[tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_3_MUX, .present = true },
|
||||
[tegra_clk_dsia_mux] = { .dt_id = TEGRA114_CLK_DSIA_MUX, .present = true },
|
||||
[tegra_clk_dsib_mux] = { .dt_id = TEGRA114_CLK_DSIB_MUX, .present = true },
|
||||
[tegra_clk_cec] = { .dt_id = TEGRA114_CLK_CEC, .present = true },
|
||||
};
|
||||
|
||||
static struct tegra_devclk devclks[] __initdata = {
|
||||
|
|
|
@ -928,6 +928,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
|
|||
[tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true },
|
||||
[tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true },
|
||||
[tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true },
|
||||
[tegra_clk_cec] = { .dt_id = TEGRA124_CLK_CEC, .present = true },
|
||||
};
|
||||
|
||||
static struct tegra_devclk devclks[] __initdata = {
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <dt-bindings/clock/tegra210-car.h>
|
||||
#include <dt-bindings/reset/tegra210-car.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-id.h"
|
||||
|
@ -155,9 +157,35 @@
|
|||
#define PMC_PLLM_WB0_OVERRIDE 0x1dc
|
||||
#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
|
||||
|
||||
#define UTMIP_PLL_CFG2 0x488
|
||||
#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6)
|
||||
#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24)
|
||||
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25)
|
||||
|
||||
#define UTMIP_PLL_CFG1 0x484
|
||||
#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
|
||||
#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
|
||||
#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
|
||||
#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
|
||||
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
|
||||
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
|
||||
#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
|
||||
|
||||
#define SATA_PLL_CFG0 0x490
|
||||
#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
|
||||
#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2)
|
||||
#define SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL BIT(4)
|
||||
#define SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE BIT(5)
|
||||
#define SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE BIT(6)
|
||||
#define SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE BIT(7)
|
||||
|
||||
#define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13)
|
||||
#define SATA_PLL_CFG0_SEQ_ENABLE BIT(24)
|
||||
|
||||
|
@ -196,6 +224,12 @@
|
|||
#define CLK_M_DIVISOR_SHIFT 2
|
||||
#define CLK_M_DIVISOR_MASK 0x3
|
||||
|
||||
#define RST_DFLL_DVCO 0x2f4
|
||||
#define DVFS_DFLL_RESET_SHIFT 0
|
||||
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
|
||||
|
||||
/*
|
||||
* SDM fractional divisor is 16-bit 2's complement signed number within
|
||||
* (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
|
||||
|
@ -454,6 +488,26 @@ void tegra210_sata_pll_hw_sequence_start(void)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start);
|
||||
|
||||
void tegra210_set_sata_pll_seq_sw(bool state)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(clk_base + SATA_PLL_CFG0);
|
||||
if (state) {
|
||||
val |= SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL;
|
||||
val |= SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE;
|
||||
val |= SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE;
|
||||
val |= SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE;
|
||||
} else {
|
||||
val &= ~SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL;
|
||||
val &= ~SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE;
|
||||
val &= ~SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE;
|
||||
val &= ~SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE;
|
||||
}
|
||||
writel_relaxed(val, clk_base + SATA_PLL_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw);
|
||||
|
||||
static inline void _pll_misc_chk_default(void __iomem *base,
|
||||
struct tegra_clk_pll_params *params,
|
||||
u8 misc_num, u32 default_val, u32 mask)
|
||||
|
@ -501,12 +555,12 @@ static void tegra210_pllcx_set_defaults(const char *name,
|
|||
{
|
||||
pllcx->params->defaults_set = true;
|
||||
|
||||
if (readl_relaxed(clk_base + pllcx->params->base_reg) &
|
||||
PLL_ENABLE) {
|
||||
if (readl_relaxed(clk_base + pllcx->params->base_reg) & PLL_ENABLE) {
|
||||
/* PLL is ON: only check if defaults already set */
|
||||
pllcx_check_defaults(pllcx->params);
|
||||
pr_warn("%s already enabled. Postponing set full defaults\n",
|
||||
name);
|
||||
if (!pllcx->params->defaults_set)
|
||||
pr_warn("%s already enabled. Postponing set full defaults\n",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -608,7 +662,6 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
|
|||
|
||||
if (readl_relaxed(clk_base + plld->params->base_reg) &
|
||||
PLL_ENABLE) {
|
||||
pr_warn("PLL_D already enabled. Postponing set full defaults\n");
|
||||
|
||||
/*
|
||||
* PLL is ON: check if defaults already set, then set those
|
||||
|
@ -625,6 +678,9 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
|
|||
_pll_misc_chk_default(clk_base, plld->params, 0, val,
|
||||
~mask & PLLD_MISC0_WRITE_MASK);
|
||||
|
||||
if (!plld->params->defaults_set)
|
||||
pr_warn("PLL_D already enabled. Postponing set full defaults\n");
|
||||
|
||||
/* Enable lock detect */
|
||||
mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE;
|
||||
val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
|
||||
|
@ -896,7 +952,6 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
|
|||
val |= step_b << PLLX_MISC2_DYNRAMP_STEPB_SHIFT;
|
||||
|
||||
if (readl_relaxed(clk_base + pllx->params->base_reg) & PLL_ENABLE) {
|
||||
pr_warn("PLL_X already enabled. Postponing set full defaults\n");
|
||||
|
||||
/*
|
||||
* PLL is ON: check if defaults already set, then set those
|
||||
|
@ -904,6 +959,8 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
|
|||
*/
|
||||
pllx_check_defaults(pllx);
|
||||
|
||||
if (!pllx->params->defaults_set)
|
||||
pr_warn("PLL_X already enabled. Postponing set full defaults\n");
|
||||
/* Configure dyn ramp, disable lock override */
|
||||
writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
|
||||
|
||||
|
@ -948,7 +1005,6 @@ static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
|
|||
pllmb->params->defaults_set = true;
|
||||
|
||||
if (val & PLL_ENABLE) {
|
||||
pr_warn("PLL_MB already enabled. Postponing set full defaults\n");
|
||||
|
||||
/*
|
||||
* PLL is ON: check if defaults already set, then set those
|
||||
|
@ -959,6 +1015,8 @@ static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
|
|||
_pll_misc_chk_default(clk_base, pllmb->params, 0, val,
|
||||
~mask & PLLMB_MISC1_WRITE_MASK);
|
||||
|
||||
if (!pllmb->params->defaults_set)
|
||||
pr_warn("PLL_MB already enabled. Postponing set full defaults\n");
|
||||
/* Enable lock detect */
|
||||
val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]);
|
||||
val &= ~mask;
|
||||
|
@ -1008,13 +1066,14 @@ static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
|
|||
pllp->params->defaults_set = true;
|
||||
|
||||
if (val & PLL_ENABLE) {
|
||||
pr_warn("PLL_P already enabled. Postponing set full defaults\n");
|
||||
|
||||
/*
|
||||
* PLL is ON: check if defaults already set, then set those
|
||||
* that can be updated in flight.
|
||||
*/
|
||||
pllp_check_defaults(pllp, true);
|
||||
if (!pllp->params->defaults_set)
|
||||
pr_warn("PLL_P already enabled. Postponing set full defaults\n");
|
||||
|
||||
/* Enable lock detect */
|
||||
val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]);
|
||||
|
@ -1046,47 +1105,49 @@ static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
|
|||
* Both VCO and post-divider output rates are fixed at 480MHz and 240MHz,
|
||||
* respectively.
|
||||
*/
|
||||
static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control)
|
||||
static void pllu_check_defaults(struct tegra_clk_pll_params *params,
|
||||
bool hw_control)
|
||||
{
|
||||
u32 val, mask;
|
||||
|
||||
/* Ignore lock enable (will be set) and IDDQ if under h/w control */
|
||||
val = PLLU_MISC0_DEFAULT_VALUE & (~PLLU_MISC0_IDDQ);
|
||||
mask = PLLU_MISC0_LOCK_ENABLE | (hw_control ? PLLU_MISC0_IDDQ : 0);
|
||||
_pll_misc_chk_default(clk_base, pll->params, 0, val,
|
||||
_pll_misc_chk_default(clk_base, params, 0, val,
|
||||
~mask & PLLU_MISC0_WRITE_MASK);
|
||||
|
||||
val = PLLU_MISC1_DEFAULT_VALUE;
|
||||
mask = PLLU_MISC1_LOCK_OVERRIDE;
|
||||
_pll_misc_chk_default(clk_base, pll->params, 1, val,
|
||||
_pll_misc_chk_default(clk_base, params, 1, val,
|
||||
~mask & PLLU_MISC1_WRITE_MASK);
|
||||
}
|
||||
|
||||
static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
|
||||
static void tegra210_pllu_set_defaults(struct tegra_clk_pll_params *pllu)
|
||||
{
|
||||
u32 val = readl_relaxed(clk_base + pllu->params->base_reg);
|
||||
u32 val = readl_relaxed(clk_base + pllu->base_reg);
|
||||
|
||||
pllu->params->defaults_set = true;
|
||||
pllu->defaults_set = true;
|
||||
|
||||
if (val & PLL_ENABLE) {
|
||||
pr_warn("PLL_U already enabled. Postponing set full defaults\n");
|
||||
|
||||
/*
|
||||
* PLL is ON: check if defaults already set, then set those
|
||||
* that can be updated in flight.
|
||||
*/
|
||||
pllu_check_defaults(pllu, false);
|
||||
if (!pllu->defaults_set)
|
||||
pr_warn("PLL_U already enabled. Postponing set full defaults\n");
|
||||
|
||||
/* Enable lock detect */
|
||||
val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[0]);
|
||||
val = readl_relaxed(clk_base + pllu->ext_misc_reg[0]);
|
||||
val &= ~PLLU_MISC0_LOCK_ENABLE;
|
||||
val |= PLLU_MISC0_DEFAULT_VALUE & PLLU_MISC0_LOCK_ENABLE;
|
||||
writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[0]);
|
||||
writel_relaxed(val, clk_base + pllu->ext_misc_reg[0]);
|
||||
|
||||
val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[1]);
|
||||
val = readl_relaxed(clk_base + pllu->ext_misc_reg[1]);
|
||||
val &= ~PLLU_MISC1_LOCK_OVERRIDE;
|
||||
val |= PLLU_MISC1_DEFAULT_VALUE & PLLU_MISC1_LOCK_OVERRIDE;
|
||||
writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[1]);
|
||||
writel_relaxed(val, clk_base + pllu->ext_misc_reg[1]);
|
||||
udelay(1);
|
||||
|
||||
return;
|
||||
|
@ -1094,9 +1155,9 @@ static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
|
|||
|
||||
/* set IDDQ, enable lock detect */
|
||||
writel_relaxed(PLLU_MISC0_DEFAULT_VALUE,
|
||||
clk_base + pllu->params->ext_misc_reg[0]);
|
||||
clk_base + pllu->ext_misc_reg[0]);
|
||||
writel_relaxed(PLLU_MISC1_DEFAULT_VALUE,
|
||||
clk_base + pllu->params->ext_misc_reg[1]);
|
||||
clk_base + pllu->ext_misc_reg[1]);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
|
@ -1216,6 +1277,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
|
|||
cfg->n = p_rate / cf;
|
||||
|
||||
cfg->sdm_data = 0;
|
||||
cfg->output_rate = input_rate;
|
||||
if (params->sdm_ctrl_reg) {
|
||||
unsigned long rem = p_rate - cf * cfg->n;
|
||||
/* If ssc is enabled SDM enabled as well, even for integer n */
|
||||
|
@ -1226,10 +1288,15 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
|
|||
s -= PLL_SDM_COEFF / 2;
|
||||
cfg->sdm_data = sdin_din_to_data(s);
|
||||
}
|
||||
cfg->output_rate *= cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 +
|
||||
sdin_data_to_din(cfg->sdm_data);
|
||||
cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF;
|
||||
} else {
|
||||
cfg->output_rate *= cfg->n;
|
||||
cfg->output_rate /= p * cfg->m;
|
||||
}
|
||||
|
||||
cfg->input_rate = input_rate;
|
||||
cfg->output_rate = rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1772,7 +1839,7 @@ static struct tegra_clk_pll_params pll_a1_params = {
|
|||
.misc_reg = PLLA1_MISC0,
|
||||
.lock_mask = PLLCX_BASE_LOCK,
|
||||
.lock_delay = 300,
|
||||
.iddq_reg = PLLA1_MISC0,
|
||||
.iddq_reg = PLLA1_MISC1,
|
||||
.iddq_bit_idx = PLLCX_IDDQ_BIT,
|
||||
.reset_reg = PLLA1_MISC0,
|
||||
.reset_bit_idx = PLLCX_RESET_BIT,
|
||||
|
@ -1987,9 +2054,9 @@ static struct div_nmp pllu_nmp = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
|
||||
{ 12000000, 480000000, 40, 1, 1, 0 },
|
||||
{ 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */
|
||||
{ 38400000, 480000000, 25, 2, 1, 0 },
|
||||
{ 12000000, 480000000, 40, 1, 0, 0 },
|
||||
{ 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */
|
||||
{ 38400000, 480000000, 25, 2, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -2013,8 +2080,47 @@ static struct tegra_clk_pll_params pll_u_vco_params = {
|
|||
.div_nmp = &pllu_nmp,
|
||||
.freq_table = pll_u_freq_table,
|
||||
.flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT,
|
||||
.set_defaults = tegra210_pllu_set_defaults,
|
||||
.calc_rate = tegra210_pll_fixed_mdiv_cfg,
|
||||
};
|
||||
|
||||
struct utmi_clk_param {
|
||||
/* Oscillator Frequency in KHz */
|
||||
u32 osc_frequency;
|
||||
/* UTMIP PLL Enable Delay Count */
|
||||
u8 enable_delay_count;
|
||||
/* UTMIP PLL Stable count */
|
||||
u16 stable_count;
|
||||
/* UTMIP PLL Active delay count */
|
||||
u8 active_delay_count;
|
||||
/* UTMIP PLL Xtal frequency count */
|
||||
u16 xtal_freq_count;
|
||||
};
|
||||
|
||||
static const struct utmi_clk_param utmi_parameters[] = {
|
||||
{
|
||||
.osc_frequency = 38400000, .enable_delay_count = 0x0,
|
||||
.stable_count = 0x0, .active_delay_count = 0x6,
|
||||
.xtal_freq_count = 0x80
|
||||
}, {
|
||||
.osc_frequency = 13000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x33, .active_delay_count = 0x05,
|
||||
.xtal_freq_count = 0x7f
|
||||
}, {
|
||||
.osc_frequency = 19200000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x4b, .active_delay_count = 0x06,
|
||||
.xtal_freq_count = 0xbb
|
||||
}, {
|
||||
.osc_frequency = 12000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x2f, .active_delay_count = 0x08,
|
||||
.xtal_freq_count = 0x76
|
||||
}, {
|
||||
.osc_frequency = 26000000, .enable_delay_count = 0x04,
|
||||
.stable_count = 0x66, .active_delay_count = 0x09,
|
||||
.xtal_freq_count = 0xfe
|
||||
}, {
|
||||
.osc_frequency = 16800000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x41, .active_delay_count = 0x0a,
|
||||
.xtal_freq_count = 0xa4
|
||||
},
|
||||
};
|
||||
|
||||
static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
|
@ -2115,7 +2221,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
|||
[tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present = true },
|
||||
[tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present = true },
|
||||
[tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present = true },
|
||||
[tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1, .present = true },
|
||||
[tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present = true },
|
||||
[tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1, .present = true },
|
||||
[tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3, .present = true },
|
||||
|
@ -2209,6 +2314,25 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
|||
[tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true },
|
||||
[tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true },
|
||||
[tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true },
|
||||
[tegra_clk_pll_a1] = { .dt_id = TEGRA210_CLK_PLL_A1, .present = true },
|
||||
[tegra_clk_ispa] = { .dt_id = TEGRA210_CLK_ISPA, .present = true },
|
||||
[tegra_clk_cec] = { .dt_id = TEGRA210_CLK_CEC, .present = true },
|
||||
[tegra_clk_dmic1] = { .dt_id = TEGRA210_CLK_DMIC1, .present = true },
|
||||
[tegra_clk_dmic2] = { .dt_id = TEGRA210_CLK_DMIC2, .present = true },
|
||||
[tegra_clk_dmic3] = { .dt_id = TEGRA210_CLK_DMIC3, .present = true },
|
||||
[tegra_clk_dmic1_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC1_SYNC_CLK, .present = true },
|
||||
[tegra_clk_dmic2_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC2_SYNC_CLK, .present = true },
|
||||
[tegra_clk_dmic3_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC3_SYNC_CLK, .present = true },
|
||||
[tegra_clk_dmic1_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC1_SYNC_CLK_MUX, .present = true },
|
||||
[tegra_clk_dmic2_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC2_SYNC_CLK_MUX, .present = true },
|
||||
[tegra_clk_dmic3_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC3_SYNC_CLK_MUX, .present = true },
|
||||
[tegra_clk_dp2] = { .dt_id = TEGRA210_CLK_DP2, .present = true },
|
||||
[tegra_clk_iqc1] = { .dt_id = TEGRA210_CLK_IQC1, .present = true },
|
||||
[tegra_clk_iqc2] = { .dt_id = TEGRA210_CLK_IQC2, .present = true },
|
||||
[tegra_clk_pll_a_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_A_OUT_ADSP, .present = true },
|
||||
[tegra_clk_pll_a_out0_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_A_OUT0_OUT_ADSP, .present = true },
|
||||
[tegra_clk_adsp] = { .dt_id = TEGRA210_CLK_ADSP, .present = true },
|
||||
[tegra_clk_adsp_neon] = { .dt_id = TEGRA210_CLK_ADSP_NEON, .present = true },
|
||||
};
|
||||
|
||||
static struct tegra_devclk devclks[] __initdata = {
|
||||
|
@ -2227,7 +2351,6 @@ static struct tegra_devclk devclks[] __initdata = {
|
|||
{ .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 },
|
||||
{ .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 },
|
||||
{ .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M },
|
||||
{ .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 },
|
||||
{ .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X },
|
||||
{ .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 },
|
||||
{ .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U },
|
||||
|
@ -2286,6 +2409,221 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = {
|
|||
|
||||
static struct clk **clks;
|
||||
|
||||
static const char * const aclk_parents[] = {
|
||||
"pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3",
|
||||
"clk_m"
|
||||
};
|
||||
|
||||
void tegra210_put_utmipll_in_iddq(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
|
||||
if (reg & UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK) {
|
||||
pr_err("trying to assert IDDQ while UTMIPLL is locked\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
|
||||
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_put_utmipll_in_iddq);
|
||||
|
||||
void tegra210_put_utmipll_out_iddq(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
|
||||
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_put_utmipll_out_iddq);
|
||||
|
||||
static void tegra210_utmi_param_configure(void)
|
||||
{
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
|
||||
if (osc_freq == utmi_parameters[i].osc_frequency)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(utmi_parameters)) {
|
||||
pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
|
||||
osc_freq);
|
||||
return;
|
||||
}
|
||||
|
||||
reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
|
||||
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
|
||||
udelay(10);
|
||||
|
||||
reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
|
||||
|
||||
/* Program UTMIP PLL stable and active counts */
|
||||
/* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
|
||||
reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
|
||||
reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
|
||||
|
||||
reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
|
||||
|
||||
reg |=
|
||||
UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].active_delay_count);
|
||||
writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
|
||||
|
||||
/* Program UTMIP PLL delay and oscillator frequency counts */
|
||||
reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
|
||||
reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
|
||||
|
||||
reg |=
|
||||
UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].enable_delay_count);
|
||||
|
||||
reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
|
||||
reg |=
|
||||
UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].xtal_freq_count);
|
||||
|
||||
reg |= UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
|
||||
writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
|
||||
|
||||
/* Remove power downs from UTMIP PLL control bits */
|
||||
reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
|
||||
reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
|
||||
reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
|
||||
writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
|
||||
udelay(1);
|
||||
|
||||
/* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
|
||||
reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
|
||||
reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
|
||||
reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
|
||||
reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
|
||||
reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
|
||||
reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
|
||||
reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
|
||||
writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
|
||||
|
||||
/* Setup HW control of UTMIPLL */
|
||||
reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
|
||||
reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
|
||||
reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
|
||||
writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
|
||||
|
||||
reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
|
||||
reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
|
||||
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
reg = readl_relaxed(clk_base + XUSB_PLL_CFG0);
|
||||
reg &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
|
||||
writel_relaxed(reg, clk_base + XUSB_PLL_CFG0);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Enable HW control UTMIPLL */
|
||||
reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
|
||||
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
}
|
||||
|
||||
static int tegra210_enable_pllu(void)
|
||||
{
|
||||
struct tegra_clk_pll_freq_table *fentry;
|
||||
struct tegra_clk_pll pllu;
|
||||
u32 reg;
|
||||
|
||||
for (fentry = pll_u_freq_table; fentry->input_rate; fentry++) {
|
||||
if (fentry->input_rate == pll_ref_freq)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fentry->input_rate) {
|
||||
pr_err("Unknown PLL_U reference frequency %lu\n", pll_ref_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* clear IDDQ bit */
|
||||
pllu.params = &pll_u_vco_params;
|
||||
reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]);
|
||||
reg &= ~BIT(pllu.params->iddq_bit_idx);
|
||||
writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]);
|
||||
|
||||
reg = readl_relaxed(clk_base + PLLU_BASE);
|
||||
reg &= ~GENMASK(20, 0);
|
||||
reg |= fentry->m;
|
||||
reg |= fentry->n << 8;
|
||||
reg |= fentry->p << 16;
|
||||
writel(reg, clk_base + PLLU_BASE);
|
||||
reg |= PLL_ENABLE;
|
||||
writel(reg, clk_base + PLLU_BASE);
|
||||
|
||||
readl_relaxed_poll_timeout(clk_base + PLLU_BASE, reg,
|
||||
reg & PLL_BASE_LOCK, 2, 1000);
|
||||
if (!(reg & PLL_BASE_LOCK)) {
|
||||
pr_err("Timed out waiting for PLL_U to lock\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_init_pllu(void)
|
||||
{
|
||||
u32 reg;
|
||||
int err;
|
||||
|
||||
tegra210_pllu_set_defaults(&pll_u_vco_params);
|
||||
/* skip initialization when pllu is in hw controlled mode */
|
||||
reg = readl_relaxed(clk_base + PLLU_BASE);
|
||||
if (reg & PLLU_BASE_OVERRIDE) {
|
||||
if (!(reg & PLL_ENABLE)) {
|
||||
err = tegra210_enable_pllu();
|
||||
if (err < 0) {
|
||||
WARN_ON(1);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/* enable hw controlled mode */
|
||||
reg = readl_relaxed(clk_base + PLLU_BASE);
|
||||
reg &= ~PLLU_BASE_OVERRIDE;
|
||||
writel(reg, clk_base + PLLU_BASE);
|
||||
|
||||
reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
reg |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
|
||||
PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
|
||||
PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
|
||||
reg &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
|
||||
PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
|
||||
writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
|
||||
reg = readl_relaxed(clk_base + XUSB_PLL_CFG0);
|
||||
reg &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK;
|
||||
writel_relaxed(reg, clk_base + XUSB_PLL_CFG0);
|
||||
udelay(1);
|
||||
|
||||
reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
reg |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
|
||||
writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
|
||||
udelay(1);
|
||||
|
||||
reg = readl_relaxed(clk_base + PLLU_BASE);
|
||||
reg &= ~PLLU_BASE_CLKENABLE_USB;
|
||||
writel_relaxed(reg, clk_base + PLLU_BASE);
|
||||
}
|
||||
|
||||
/* enable UTMIPLL hw control if not yet done by the bootloader */
|
||||
reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
if (!(reg & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE))
|
||||
tegra210_utmi_param_configure();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
||||
void __iomem *pmc_base)
|
||||
{
|
||||
|
@ -2347,6 +2685,11 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
|||
clk_register_clkdev(clk, "cml1", NULL);
|
||||
clks[TEGRA210_CLK_CML1] = clk;
|
||||
|
||||
clk = tegra_clk_register_super_clk("aclk", aclk_parents,
|
||||
ARRAY_SIZE(aclk_parents), 0, clk_base + 0x6e0,
|
||||
0, NULL);
|
||||
clks[TEGRA210_CLK_ACLK] = clk;
|
||||
|
||||
tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params);
|
||||
}
|
||||
|
||||
|
@ -2402,9 +2745,6 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
|
|||
clk_register_clkdev(clk, "pll_mb", NULL);
|
||||
clks[TEGRA210_CLK_PLL_MB] = clk;
|
||||
|
||||
clk_register_clkdev(clk, "pll_m_out1", NULL);
|
||||
clks[TEGRA210_CLK_PLL_M_OUT1] = clk;
|
||||
|
||||
/* PLLM_UD */
|
||||
clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
|
||||
CLK_SET_RATE_PARENT, 1, 1);
|
||||
|
@ -2412,11 +2752,12 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
|
|||
clks[TEGRA210_CLK_PLL_M_UD] = clk;
|
||||
|
||||
/* PLLU_VCO */
|
||||
clk = tegra_clk_register_pllu_tegra210("pll_u_vco", "pll_ref",
|
||||
clk_base, 0, &pll_u_vco_params,
|
||||
&pll_u_lock);
|
||||
clk_register_clkdev(clk, "pll_u_vco", NULL);
|
||||
clks[TEGRA210_CLK_PLL_U] = clk;
|
||||
if (!tegra210_init_pllu()) {
|
||||
clk = clk_register_fixed_rate(NULL, "pll_u_vco", "pll_ref", 0,
|
||||
480*1000*1000);
|
||||
clk_register_clkdev(clk, "pll_u_vco", NULL);
|
||||
clks[TEGRA210_CLK_PLL_U] = clk;
|
||||
}
|
||||
|
||||
/* PLLU_OUT */
|
||||
clk = clk_register_divider_table(NULL, "pll_u_out", "pll_u_vco", 0,
|
||||
|
@ -2651,6 +2992,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
|
|||
{ TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 },
|
||||
/* TODO find a way to enable this on-demand */
|
||||
{ TEGRA210_CLK_DBGAPB, TEGRA210_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA210_CLK_TSENSOR, TEGRA210_CLK_CLK_M, 400000, 0 },
|
||||
{ TEGRA210_CLK_I2C1, TEGRA210_CLK_PLL_P, 0, 0 },
|
||||
{ TEGRA210_CLK_I2C2, TEGRA210_CLK_PLL_P, 0, 0 },
|
||||
|
@ -2661,6 +3004,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
|
|||
{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 },
|
||||
{ TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 },
|
||||
{ TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
|
||||
{ TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
|
||||
/* This MUST be the last entry. */
|
||||
{ TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 },
|
||||
};
|
||||
|
@ -2678,6 +3023,81 @@ static void __init tegra210_clock_apply_init_table(void)
|
|||
tegra_init_from_table(init_table, clks, TEGRA210_CLK_CLK_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_car_barrier - wait for pending writes to the CAR to complete
|
||||
*
|
||||
* Wait for any outstanding writes to the CAR MMIO space from this CPU
|
||||
* to complete before continuing execution. No return value.
|
||||
*/
|
||||
static void tegra210_car_barrier(void)
|
||||
{
|
||||
readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
|
||||
*
|
||||
* Assert the reset line of the DFLL's DVCO. No return value.
|
||||
*/
|
||||
static void tegra210_clock_assert_dfll_dvco_reset(void)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||
v |= (1 << DVFS_DFLL_RESET_SHIFT);
|
||||
writel_relaxed(v, clk_base + RST_DFLL_DVCO);
|
||||
tegra210_car_barrier();
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
|
||||
*
|
||||
* Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
|
||||
* operate. No return value.
|
||||
*/
|
||||
static void tegra210_clock_deassert_dfll_dvco_reset(void)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||
v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
|
||||
writel_relaxed(v, clk_base + RST_DFLL_DVCO);
|
||||
tegra210_car_barrier();
|
||||
}
|
||||
|
||||
static int tegra210_reset_assert(unsigned long id)
|
||||
{
|
||||
if (id == TEGRA210_RST_DFLL_DVCO)
|
||||
tegra210_clock_assert_dfll_dvco_reset();
|
||||
else if (id == TEGRA210_RST_ADSP)
|
||||
writel(GENMASK(26, 21) | BIT(7),
|
||||
clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_SET);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_reset_deassert(unsigned long id)
|
||||
{
|
||||
if (id == TEGRA210_RST_DFLL_DVCO)
|
||||
tegra210_clock_deassert_dfll_dvco_reset();
|
||||
else if (id == TEGRA210_RST_ADSP) {
|
||||
writel(BIT(21), clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR);
|
||||
/*
|
||||
* Considering adsp cpu clock (min: 12.5MHZ, max: 1GHz)
|
||||
* a delay of 5us ensures that it's at least
|
||||
* 6 * adsp_cpu_cycle_period long.
|
||||
*/
|
||||
udelay(5);
|
||||
writel(GENMASK(26, 22) | BIT(7),
|
||||
clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR);
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_clock_init - Tegra210-specific clock initialization
|
||||
* @np: struct device_node * of the DT node for the SoC CAR IP block
|
||||
|
@ -2742,6 +3162,9 @@ static void __init tegra210_clock_init(struct device_node *np)
|
|||
|
||||
tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks,
|
||||
&pll_x_params);
|
||||
tegra_init_special_resets(2, tegra210_reset_assert,
|
||||
tegra210_reset_deassert);
|
||||
|
||||
tegra_add_of_provider(np);
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
|
|
|
@ -817,6 +817,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
|
|||
[tegra_clk_pll_p_out4] = { .dt_id = TEGRA30_CLK_PLL_P_OUT4, .present = true },
|
||||
[tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
|
||||
[tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
|
||||
[tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true },
|
||||
};
|
||||
|
||||
static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue