mirror of https://gitee.com/openkylin/linux.git
Merge branches 'clk-allwinner', 'clk-rockchip', 'clk-tegra', 'clk-berlin' and 'clk-qcom-mmagic' into clk-next
* clk-allwinner: clk: sunxi-ng: r40: export a regmap to access the GMAC register clk: sunxi-ng: r40: rewrite init code to a platform driver clk: sunxi-ng: add support for H6 PRCM CCU * clk-rockchip: clk: rockchip: remove deprecated gate-clk code and dt-binding clk: rockchip: use match_string() helper * clk-tegra: clk: tegra: Add quirk for getting CDEV1/2 clocks on Tegra20 clk: tegra20: Correct parents of CDEV1/2 clocks clk: tegra20: Add DEV1/DEV2 OSC dividers * clk-berlin: clk: berlin: switch to SPDX license identifier * clk-qcom-mmagic: clk: qcom: mmcc-msm8996: leave all mmagic gdscs and clocks always enabled clk: qcom: Register the gdscs before the clocks clk: qcom: gdsc: Add support for ALWAYS_ON gdscs
This commit is contained in:
commit
45ba387511
|
@ -1,77 +0,0 @@
|
|||
Device Tree Clock bindings for arch-rockchip
|
||||
|
||||
This binding uses the common clock binding[1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
== Gate clocks ==
|
||||
|
||||
These bindings are deprecated!
|
||||
Please use the soc specific CRU bindings instead.
|
||||
|
||||
The gate registers form a continuos block which makes the dt node
|
||||
structure a matter of taste, as either all gates can be put into
|
||||
one gate clock spanning all registers or they can be divided into
|
||||
the 10 individual gates containing 16 clocks each.
|
||||
The code supports both approaches.
|
||||
|
||||
Required properties:
|
||||
- compatible : "rockchip,rk2928-gate-clk"
|
||||
- reg : shall be the control register address(es) for the clock.
|
||||
- #clock-cells : from common clock binding; shall be set to 1
|
||||
- clock-output-names : the corresponding gate names that the clock controls
|
||||
- clocks : should contain the parent clock for each individual gate,
|
||||
therefore the number of clocks elements should match the number of
|
||||
clock-output-names
|
||||
|
||||
Example using multiple gate clocks:
|
||||
|
||||
clk_gates0: gate-clk@200000d0 {
|
||||
compatible = "rockchip,rk2928-gate-clk";
|
||||
reg = <0x200000d0 0x4>;
|
||||
clocks = <&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>,
|
||||
<&dummy>, <&dummy>;
|
||||
|
||||
clock-output-names =
|
||||
"gate_core_periph", "gate_cpu_gpll",
|
||||
"gate_ddrphy", "gate_aclk_cpu",
|
||||
"gate_hclk_cpu", "gate_pclk_cpu",
|
||||
"gate_atclk_cpu", "gate_i2s0",
|
||||
"gate_i2s0_frac", "gate_i2s1",
|
||||
"gate_i2s1_frac", "gate_i2s2",
|
||||
"gate_i2s2_frac", "gate_spdif",
|
||||
"gate_spdif_frac", "gate_testclk";
|
||||
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
clk_gates1: gate-clk@200000d4 {
|
||||
compatible = "rockchip,rk2928-gate-clk";
|
||||
reg = <0x200000d4 0x4>;
|
||||
clocks = <&xin24m>, <&xin24m>,
|
||||
<&xin24m>, <&dummy>,
|
||||
<&dummy>, <&xin24m>,
|
||||
<&xin24m>, <&dummy>,
|
||||
<&xin24m>, <&dummy>,
|
||||
<&xin24m>, <&dummy>,
|
||||
<&xin24m>, <&dummy>,
|
||||
<&xin24m>, <&dummy>;
|
||||
|
||||
clock-output-names =
|
||||
"gate_timer0", "gate_timer1",
|
||||
"gate_timer2", "gate_jtag",
|
||||
"gate_aclk_lcdc1_src", "gate_otgphy0",
|
||||
"gate_otgphy1", "gate_ddr_gpll",
|
||||
"gate_uart0", "gate_frac_uart0",
|
||||
"gate_uart1", "gate_frac_uart1",
|
||||
"gate_uart2", "gate_frac_uart2",
|
||||
"gate_uart3", "gate_frac_uart3";
|
||||
|
||||
#clock-cells = <1>;
|
||||
};
|
|
@ -21,6 +21,7 @@ Required properties :
|
|||
- "allwinner,sun50i-a64-r-ccu"
|
||||
- "allwinner,sun50i-h5-ccu"
|
||||
- "allwinner,sun50i-h6-ccu"
|
||||
- "allwinner,sun50i-h6-r-ccu"
|
||||
- "nextthing,gr8-ccu"
|
||||
|
||||
- reg: Must contain the registers base address and length
|
||||
|
@ -35,7 +36,7 @@ Required properties :
|
|||
For the main CCU on H6, one more clock is needed:
|
||||
- "iosc": the SoC's internal frequency oscillator
|
||||
|
||||
For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
|
||||
For the PRCM CCUs on A83T/H3/A64/H6, two more clocks are needed:
|
||||
- "pll-periph": the SoC's peripheral PLL from the main CCU
|
||||
- "iosc": the SoC's internal frequency oscillator
|
||||
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __BERLIN2_AVPLL_H
|
||||
#define __BERLIN2_AVPLL_H
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __BERLIN2_DIV_H
|
||||
#define __BERLIN2_DIV_H
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __BERLIN2_PLL_H
|
||||
#define __BERLIN2_PLL_H
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __BERLIN2_COMMON_H
|
||||
#define __BERLIN2_COMMON_H
|
||||
|
|
|
@ -228,22 +228,6 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
|||
if (!cc)
|
||||
return -ENOMEM;
|
||||
|
||||
cc->rclks = rclks;
|
||||
cc->num_rclks = num_clks;
|
||||
|
||||
for (i = 0; i < num_clks; i++) {
|
||||
if (!rclks[i])
|
||||
continue;
|
||||
|
||||
ret = devm_clk_register_regmap(dev, rclks[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reset = &cc->reset;
|
||||
reset->rcdev.of_node = dev->of_node;
|
||||
reset->rcdev.ops = &qcom_reset_ops;
|
||||
|
@ -272,6 +256,22 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
cc->rclks = rclks;
|
||||
cc->num_rclks = num_clks;
|
||||
|
||||
for (i = 0; i < num_clks; i++) {
|
||||
if (!rclks[i])
|
||||
continue;
|
||||
|
||||
ret = devm_clk_register_regmap(dev, rclks[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
|
||||
|
|
|
@ -3105,7 +3105,7 @@ static struct gdsc aggre0_noc_gdsc = {
|
|||
.name = "aggre0_noc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = VOTABLE,
|
||||
.flags = VOTABLE | ALWAYS_ON,
|
||||
};
|
||||
|
||||
static struct gdsc hlos1_vote_aggre0_noc_gdsc = {
|
||||
|
|
|
@ -291,6 +291,14 @@ static int gdsc_init(struct gdsc *sc)
|
|||
if ((sc->flags & VOTABLE) && on)
|
||||
gdsc_enable(&sc->pd);
|
||||
|
||||
/* If ALWAYS_ON GDSCs are not ON, turn them ON */
|
||||
if (sc->flags & ALWAYS_ON) {
|
||||
if (!on)
|
||||
gdsc_enable(&sc->pd);
|
||||
on = true;
|
||||
sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
}
|
||||
|
||||
if (on || (sc->pwrsts & PWRSTS_RET))
|
||||
gdsc_force_mem_on(sc);
|
||||
else
|
||||
|
|
|
@ -53,6 +53,7 @@ struct gdsc {
|
|||
#define VOTABLE BIT(0)
|
||||
#define CLAMP_IO BIT(1)
|
||||
#define HW_CTRL BIT(2)
|
||||
#define ALWAYS_ON BIT(3)
|
||||
struct reset_controller_dev *rcdev;
|
||||
unsigned int *resets;
|
||||
unsigned int reset_count;
|
||||
|
|
|
@ -1245,7 +1245,7 @@ static struct clk_branch mmss_mmagic_ahb_clk = {
|
|||
.name = "mmss_mmagic_ahb_clk",
|
||||
.parent_names = (const char *[]){ "ahb_clk_src" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1260,7 +1260,7 @@ static struct clk_branch mmss_mmagic_cfg_ahb_clk = {
|
|||
.name = "mmss_mmagic_cfg_ahb_clk",
|
||||
.parent_names = (const char *[]){ "ahb_clk_src" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1319,7 +1319,7 @@ static struct clk_branch mmagic_camss_axi_clk = {
|
|||
.name = "mmagic_camss_axi_clk",
|
||||
.parent_names = (const char *[]){ "axi_clk_src" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1334,7 +1334,7 @@ static struct clk_branch mmagic_camss_noc_cfg_ahb_clk = {
|
|||
.name = "mmagic_camss_noc_cfg_ahb_clk",
|
||||
.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1439,7 +1439,7 @@ static struct clk_branch mmagic_mdss_axi_clk = {
|
|||
.name = "mmagic_mdss_axi_clk",
|
||||
.parent_names = (const char *[]){ "axi_clk_src" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1454,7 +1454,7 @@ static struct clk_branch mmagic_mdss_noc_cfg_ahb_clk = {
|
|||
.name = "mmagic_mdss_noc_cfg_ahb_clk",
|
||||
.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1529,7 +1529,7 @@ static struct clk_branch mmagic_video_axi_clk = {
|
|||
.name = "mmagic_video_axi_clk",
|
||||
.parent_names = (const char *[]){ "axi_clk_src" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -1544,7 +1544,7 @@ static struct clk_branch mmagic_video_noc_cfg_ahb_clk = {
|
|||
.name = "mmagic_video_noc_cfg_ahb_clk",
|
||||
.parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -2919,7 +2919,7 @@ static struct gdsc mmagic_video_gdsc = {
|
|||
.name = "mmagic_video",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = VOTABLE,
|
||||
.flags = VOTABLE | ALWAYS_ON,
|
||||
};
|
||||
|
||||
static struct gdsc mmagic_mdss_gdsc = {
|
||||
|
@ -2929,7 +2929,7 @@ static struct gdsc mmagic_mdss_gdsc = {
|
|||
.name = "mmagic_mdss",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = VOTABLE,
|
||||
.flags = VOTABLE | ALWAYS_ON,
|
||||
};
|
||||
|
||||
static struct gdsc mmagic_camss_gdsc = {
|
||||
|
@ -2939,7 +2939,7 @@ static struct gdsc mmagic_camss_gdsc = {
|
|||
.name = "mmagic_camss",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = VOTABLE,
|
||||
.flags = VOTABLE | ALWAYS_ON,
|
||||
};
|
||||
|
||||
static struct gdsc venus_gdsc = {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Rockchip Clock specific Makefile
|
||||
#
|
||||
|
||||
obj-y += clk-rockchip.o
|
||||
obj-y += clk.o
|
||||
obj-y += clk-pll.o
|
||||
obj-y += clk-cpu.o
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013 MundoReader S.L.
|
||||
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
static DEFINE_SPINLOCK(clk_lock);
|
||||
|
||||
/*
|
||||
* Gate clocks
|
||||
*/
|
||||
|
||||
static void __init rk2928_gate_clk_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
const char *clk_parent;
|
||||
const char *clk_name;
|
||||
void __iomem *reg;
|
||||
void __iomem *reg_idx;
|
||||
int flags;
|
||||
int qty;
|
||||
int reg_bit;
|
||||
int clkflags = CLK_SET_RATE_PARENT;
|
||||
int i;
|
||||
|
||||
qty = of_property_count_strings(node, "clock-output-names");
|
||||
if (qty < 0) {
|
||||
pr_err("%s: error in clock-output-names %d\n", __func__, qty);
|
||||
return;
|
||||
}
|
||||
|
||||
if (qty == 0) {
|
||||
pr_info("%s: nothing to do\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
reg = of_iomap(node, 0);
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
|
||||
if (!clk_data) {
|
||||
iounmap(reg);
|
||||
return;
|
||||
}
|
||||
|
||||
clk_data->clks = kzalloc(qty * sizeof(struct clk *), GFP_KERNEL);
|
||||
if (!clk_data->clks) {
|
||||
kfree(clk_data);
|
||||
iounmap(reg);
|
||||
return;
|
||||
}
|
||||
|
||||
flags = CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE;
|
||||
|
||||
for (i = 0; i < qty; i++) {
|
||||
of_property_read_string_index(node, "clock-output-names",
|
||||
i, &clk_name);
|
||||
|
||||
/* ignore empty slots */
|
||||
if (!strcmp("reserved", clk_name))
|
||||
continue;
|
||||
|
||||
clk_parent = of_clk_get_parent_name(node, i);
|
||||
|
||||
/* keep all gates untouched for now */
|
||||
clkflags |= CLK_IGNORE_UNUSED;
|
||||
|
||||
reg_idx = reg + (4 * (i / 16));
|
||||
reg_bit = (i % 16);
|
||||
|
||||
clk_data->clks[i] = clk_register_gate(NULL, clk_name,
|
||||
clk_parent, clkflags,
|
||||
reg_idx, reg_bit,
|
||||
flags,
|
||||
&clk_lock);
|
||||
WARN_ON(IS_ERR(clk_data->clks[i]));
|
||||
}
|
||||
|
||||
clk_data->clk_num = qty;
|
||||
|
||||
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
}
|
||||
CLK_OF_DECLARE(rk2928_gate, "rockchip,rk2928-gate-clk", rk2928_gate_clk_init);
|
|
@ -274,18 +274,10 @@ static struct clk *rockchip_clk_register_frac_branch(
|
|||
struct clk_mux *frac_mux = &frac->mux;
|
||||
struct clk_init_data init;
|
||||
struct clk *mux_clk;
|
||||
int i, ret;
|
||||
|
||||
frac->mux_frac_idx = -1;
|
||||
for (i = 0; i < child->num_parents; i++) {
|
||||
if (!strcmp(name, child->parent_names[i])) {
|
||||
pr_debug("%s: found fractional parent in mux at pos %d\n",
|
||||
__func__, i);
|
||||
frac->mux_frac_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int ret;
|
||||
|
||||
frac->mux_frac_idx = match_string(child->parent_names,
|
||||
child->num_parents, name);
|
||||
frac->mux_ops = &clk_mux_ops;
|
||||
frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
|
||||
|
||||
|
@ -312,6 +304,8 @@ static struct clk *rockchip_clk_register_frac_branch(
|
|||
|
||||
/* notifier on the fraction divider to catch rate changes */
|
||||
if (frac->mux_frac_idx >= 0) {
|
||||
pr_debug("%s: found fractional parent in mux at pos %d\n",
|
||||
__func__, frac->mux_frac_idx);
|
||||
ret = clk_notifier_register(clk, &frac->clk_nb);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register clock notifier for %s\n",
|
||||
|
|
|
@ -16,6 +16,11 @@ config SUN50I_H6_CCU
|
|||
default ARM64 && ARCH_SUNXI
|
||||
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
|
||||
|
||||
config SUN50I_H6_R_CCU
|
||||
bool "Support for the Allwinner H6 PRCM CCU"
|
||||
default ARM64 && ARCH_SUNXI
|
||||
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
|
||||
|
||||
config SUN4I_A10_CCU
|
||||
bool "Support for the Allwinner A10/A20 CCU"
|
||||
default MACH_SUN4I
|
||||
|
|
|
@ -23,6 +23,7 @@ lib-$(CONFIG_SUNXI_CCU) += ccu_mp.o
|
|||
# SoC support
|
||||
obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
|
||||
obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o
|
||||
obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o
|
||||
obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o
|
||||
obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o
|
||||
obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
*/
|
||||
|
||||
#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-sun50i-h6-r.h"
|
||||
|
||||
/*
|
||||
* Information about AR100 and AHB/APB clocks in R_CCU are gathered from
|
||||
* clock definitions in the BSP source code.
|
||||
*/
|
||||
|
||||
static const char * const ar100_r_apb2_parents[] = { "osc24M", "osc32k",
|
||||
"pll-periph0", "iosc" };
|
||||
static const struct ccu_mux_var_prediv ar100_r_apb2_predivs[] = {
|
||||
{ .index = 2, .shift = 0, .width = 5 },
|
||||
};
|
||||
|
||||
static struct ccu_div ar100_clk = {
|
||||
.div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
|
||||
|
||||
.mux = {
|
||||
.shift = 24,
|
||||
.width = 2,
|
||||
|
||||
.var_predivs = ar100_r_apb2_predivs,
|
||||
.n_var_predivs = ARRAY_SIZE(ar100_r_apb2_predivs),
|
||||
},
|
||||
|
||||
.common = {
|
||||
.reg = 0x000,
|
||||
.features = CCU_FEATURE_VARIABLE_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("ar100",
|
||||
ar100_r_apb2_parents,
|
||||
&ccu_div_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
||||
static CLK_FIXED_FACTOR(r_ahb_clk, "r-ahb", "ar100", 1, 1, 0);
|
||||
|
||||
static struct ccu_div r_apb1_clk = {
|
||||
.div = _SUNXI_CCU_DIV(0, 2),
|
||||
|
||||
.common = {
|
||||
.reg = 0x00c,
|
||||
.hw.init = CLK_HW_INIT("r-apb1",
|
||||
"r-ahb",
|
||||
&ccu_div_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
||||
static struct ccu_div r_apb2_clk = {
|
||||
.div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
|
||||
|
||||
.mux = {
|
||||
.shift = 24,
|
||||
.width = 2,
|
||||
|
||||
.var_predivs = ar100_r_apb2_predivs,
|
||||
.n_var_predivs = ARRAY_SIZE(ar100_r_apb2_predivs),
|
||||
},
|
||||
|
||||
.common = {
|
||||
.reg = 0x010,
|
||||
.features = CCU_FEATURE_VARIABLE_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("r-apb2",
|
||||
ar100_r_apb2_parents,
|
||||
&ccu_div_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Information about the gate/resets are gathered from the clock header file
|
||||
* in the BSP source code, although most of them are unused. The existence
|
||||
* of the hardware block is verified with "3.1 Memory Mapping" chapter in
|
||||
* "Allwinner H6 V200 User Manual V1.1"; and the parent APB buses are verified
|
||||
* with "3.3.2.1 System Bus Tree" chapter inthe same document.
|
||||
*/
|
||||
static SUNXI_CCU_GATE(r_apb1_timer_clk, "r-apb1-timer", "r-apb1",
|
||||
0x11c, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(r_apb1_twd_clk, "r-apb1-twd", "r-apb1",
|
||||
0x12c, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(r_apb1_pwm_clk, "r-apb1-pwm", "r-apb1",
|
||||
0x13c, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(r_apb2_uart_clk, "r-apb2-uart", "r-apb2",
|
||||
0x18c, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(r_apb2_i2c_clk, "r-apb2-i2c", "r-apb2",
|
||||
0x19c, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(r_apb1_ir_clk, "r-apb1-ir", "r-apb1",
|
||||
0x1cc, BIT(0), 0);
|
||||
static SUNXI_CCU_GATE(r_apb1_w1_clk, "r-apb1-w1", "r-apb1",
|
||||
0x1cc, BIT(0), 0);
|
||||
|
||||
/* Information of IR(RX) mod clock is gathered from BSP source code */
|
||||
static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" };
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
|
||||
r_mod0_default_parents, 0x1c0,
|
||||
0, 5, /* M */
|
||||
8, 2, /* P */
|
||||
24, 1, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
|
||||
/*
|
||||
* BSP didn't use the 1-wire function at all now, and the information about
|
||||
* this mod clock is guessed from the IR mod clock above. The existence of
|
||||
* this mod clock is proven by BSP clock header, and the dividers are verified
|
||||
* by contents in the 1-wire related chapter of the User Manual.
|
||||
*/
|
||||
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(w1_clk, "w1",
|
||||
r_mod0_default_parents, 0x1e0,
|
||||
0, 5, /* M */
|
||||
8, 2, /* P */
|
||||
24, 1, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
|
||||
static struct ccu_common *sun50i_h6_r_ccu_clks[] = {
|
||||
&ar100_clk.common,
|
||||
&r_apb1_clk.common,
|
||||
&r_apb2_clk.common,
|
||||
&r_apb1_timer_clk.common,
|
||||
&r_apb1_twd_clk.common,
|
||||
&r_apb1_pwm_clk.common,
|
||||
&r_apb2_uart_clk.common,
|
||||
&r_apb2_i2c_clk.common,
|
||||
&r_apb1_ir_clk.common,
|
||||
&r_apb1_w1_clk.common,
|
||||
&ir_clk.common,
|
||||
&w1_clk.common,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
|
||||
.hws = {
|
||||
[CLK_AR100] = &ar100_clk.common.hw,
|
||||
[CLK_R_AHB] = &r_ahb_clk.hw,
|
||||
[CLK_R_APB1] = &r_apb1_clk.common.hw,
|
||||
[CLK_R_APB2] = &r_apb2_clk.common.hw,
|
||||
[CLK_R_APB1_TIMER] = &r_apb1_timer_clk.common.hw,
|
||||
[CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw,
|
||||
[CLK_R_APB1_PWM] = &r_apb1_pwm_clk.common.hw,
|
||||
[CLK_R_APB2_UART] = &r_apb2_uart_clk.common.hw,
|
||||
[CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw,
|
||||
[CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw,
|
||||
[CLK_R_APB1_W1] = &r_apb1_w1_clk.common.hw,
|
||||
[CLK_IR] = &ir_clk.common.hw,
|
||||
[CLK_W1] = &w1_clk.common.hw,
|
||||
},
|
||||
.num = CLK_NUMBER,
|
||||
};
|
||||
|
||||
static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
|
||||
[RST_R_APB1_TIMER] = { 0x11c, BIT(16) },
|
||||
[RST_R_APB1_TWD] = { 0x12c, BIT(16) },
|
||||
[RST_R_APB1_PWM] = { 0x13c, BIT(16) },
|
||||
[RST_R_APB2_UART] = { 0x18c, BIT(16) },
|
||||
[RST_R_APB2_I2C] = { 0x19c, BIT(16) },
|
||||
[RST_R_APB1_IR] = { 0x1cc, BIT(16) },
|
||||
[RST_R_APB1_W1] = { 0x1ec, BIT(16) },
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
|
||||
.ccu_clks = sun50i_h6_r_ccu_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks),
|
||||
|
||||
.hw_clks = &sun50i_h6_r_hw_clks,
|
||||
|
||||
.resets = sun50i_h6_r_ccu_resets,
|
||||
.num_resets = ARRAY_SIZE(sun50i_h6_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("%pOF: Could not map the clock registers\n", node);
|
||||
return;
|
||||
}
|
||||
|
||||
sunxi_ccu_probe(node, reg, desc);
|
||||
}
|
||||
|
||||
static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
|
||||
{
|
||||
sunxi_r_ccu_init(node, &sun50i_h6_r_ccu_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu",
|
||||
sun50i_h6_r_ccu_setup);
|
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright 2017 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
*/
|
||||
|
||||
#ifndef _CCU_SUN50I_H6_R_H
|
||||
#define _CCU_SUN50I_H6_R_H
|
||||
|
||||
#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
|
||||
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
|
||||
|
||||
/* AHB/APB bus clocks are not exported except APB1 for R_PIO */
|
||||
#define CLK_R_AHB 1
|
||||
|
||||
#define CLK_R_APB2 3
|
||||
|
||||
#define CLK_NUMBER (CLK_W1 + 1)
|
||||
|
||||
#endif /* _CCU_SUN50I_H6_R_H */
|
|
@ -12,7 +12,8 @@
|
|||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
#include "ccu_reset.h"
|
||||
|
@ -1250,17 +1251,45 @@ static struct ccu_mux_nb sun8i_r40_cpu_nb = {
|
|||
.bypass_index = 1, /* index of 24 MHz oscillator */
|
||||
};
|
||||
|
||||
static void __init sun8i_r40_ccu_setup(struct device_node *node)
|
||||
/*
|
||||
* Add a regmap for the GMAC driver (dwmac-sun8i) to access the
|
||||
* GMAC configuration register.
|
||||
* Only this register is allowed to be written, in order to
|
||||
* prevent overriding critical clock configuration.
|
||||
*/
|
||||
|
||||
#define SUN8I_R40_GMAC_CFG_REG 0x164
|
||||
static bool sun8i_r40_ccu_regmap_accessible_reg(struct device *dev,
|
||||
unsigned int reg)
|
||||
{
|
||||
if (reg == SUN8I_R40_GMAC_CFG_REG)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct regmap_config sun8i_r40_ccu_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = 0x320, /* PLL_LOCK_CTRL_REG */
|
||||
|
||||
/* other devices have no business accessing other registers */
|
||||
.readable_reg = sun8i_r40_ccu_regmap_accessible_reg,
|
||||
.writeable_reg = sun8i_r40_ccu_regmap_accessible_reg,
|
||||
};
|
||||
|
||||
static int sun8i_r40_ccu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct regmap *regmap;
|
||||
void __iomem *reg;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
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;
|
||||
}
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
reg = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(reg))
|
||||
return PTR_ERR(reg);
|
||||
|
||||
/* Force the PLL-Audio-1x divider to 4 */
|
||||
val = readl(reg + SUN8I_R40_PLL_AUDIO_REG);
|
||||
|
@ -1277,7 +1306,14 @@ static void __init sun8i_r40_ccu_setup(struct device_node *node)
|
|||
val &= ~GENMASK(25, 20);
|
||||
writel(val, reg + SUN8I_R40_USB_CLK_REG);
|
||||
|
||||
sunxi_ccu_probe(node, reg, &sun8i_r40_ccu_desc);
|
||||
regmap = devm_regmap_init_mmio(&pdev->dev, reg,
|
||||
&sun8i_r40_ccu_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Gate then ungate PLL CPU after any rate changes */
|
||||
ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb);
|
||||
|
@ -1285,6 +1321,20 @@ static void __init sun8i_r40_ccu_setup(struct device_node *node)
|
|||
/* Reparent CPU during PLL CPU rate changes */
|
||||
ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
|
||||
&sun8i_r40_cpu_nb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
CLK_OF_DECLARE(sun8i_r40_ccu, "allwinner,sun8i-r40-ccu",
|
||||
sun8i_r40_ccu_setup);
|
||||
|
||||
static const struct of_device_id sun8i_r40_ccu_ids[] = {
|
||||
{ .compatible = "allwinner,sun8i-r40-ccu" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver sun8i_r40_ccu_driver = {
|
||||
.probe = sun8i_r40_ccu_probe,
|
||||
.driver = {
|
||||
.name = "sun8i-r40-ccu",
|
||||
.of_match_table = sun8i_r40_ccu_ids,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(sun8i_r40_ccu_driver);
|
||||
|
|
|
@ -1367,7 +1367,7 @@ static void __init tegra114_clock_init(struct device_node *np)
|
|||
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks,
|
||||
&pll_x_params);
|
||||
|
||||
tegra_add_of_provider(np);
|
||||
tegra_add_of_provider(np, of_clk_src_onecell_get);
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
tegra_clk_apply_init_table = tegra114_clock_apply_init_table;
|
||||
|
|
|
@ -1479,7 +1479,7 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
|
|||
&pll_x_params);
|
||||
tegra_init_special_resets(1, tegra124_reset_assert,
|
||||
tegra124_reset_deassert);
|
||||
tegra_add_of_provider(np);
|
||||
tegra_add_of_provider(np, of_clk_src_onecell_get);
|
||||
|
||||
clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
|
||||
&emc_lock);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "clk.h"
|
||||
#include "clk-id.h"
|
||||
|
||||
#define MISC_CLK_ENB 0x48
|
||||
|
||||
#define OSC_CTRL 0x50
|
||||
#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
|
||||
#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
|
||||
|
@ -831,15 +833,25 @@ static void __init tegra20_periph_clk_init(void)
|
|||
periph_clk_enb_refcnt);
|
||||
clks[TEGRA20_CLK_PEX] = clk;
|
||||
|
||||
/* dev1 OSC divider */
|
||||
clk_register_divider(NULL, "dev1_osc_div", "clk_m",
|
||||
0, clk_base + MISC_CLK_ENB, 22, 2,
|
||||
CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_READ_ONLY,
|
||||
NULL);
|
||||
|
||||
/* dev2 OSC divider */
|
||||
clk_register_divider(NULL, "dev2_osc_div", "clk_m",
|
||||
0, clk_base + MISC_CLK_ENB, 20, 2,
|
||||
CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_READ_ONLY,
|
||||
NULL);
|
||||
|
||||
/* cdev1 */
|
||||
clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, 0, 26000000);
|
||||
clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0,
|
||||
clk = tegra_clk_register_periph_gate("cdev1", "cdev1_mux", 0,
|
||||
clk_base, 0, 94, periph_clk_enb_refcnt);
|
||||
clks[TEGRA20_CLK_CDEV1] = clk;
|
||||
|
||||
/* cdev2 */
|
||||
clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, 0, 26000000);
|
||||
clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0,
|
||||
clk = tegra_clk_register_periph_gate("cdev2", "cdev2_mux", 0,
|
||||
clk_base, 0, 93, periph_clk_enb_refcnt);
|
||||
clks[TEGRA20_CLK_CDEV2] = clk;
|
||||
|
||||
|
@ -1077,6 +1089,36 @@ static const struct of_device_id pmc_match[] __initconst = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static struct clk *tegra20_clk_src_onecell_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
struct clk_hw *parent_hw;
|
||||
struct clk_hw *hw;
|
||||
struct clk *clk;
|
||||
|
||||
clk = of_clk_src_onecell_get(clkspec, data);
|
||||
if (IS_ERR(clk))
|
||||
return clk;
|
||||
|
||||
/*
|
||||
* Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent
|
||||
* clock is created by the pinctrl driver. It is possible for clk user
|
||||
* to request these clocks before pinctrl driver got probed and hence
|
||||
* user will get an orphaned clock. That might be undesirable because
|
||||
* user may expect parent clock to be enabled by the child.
|
||||
*/
|
||||
if (clkspec->args[0] == TEGRA20_CLK_CDEV1 ||
|
||||
clkspec->args[0] == TEGRA20_CLK_CDEV2) {
|
||||
hw = __clk_get_hw(clk);
|
||||
|
||||
parent_hw = clk_hw_get_parent(hw);
|
||||
if (!parent_hw)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
static void __init tegra20_clock_init(struct device_node *np)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
@ -1115,7 +1157,7 @@ static void __init tegra20_clock_init(struct device_node *np)
|
|||
|
||||
tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA20_CLK_CLK_MAX);
|
||||
|
||||
tegra_add_of_provider(np);
|
||||
tegra_add_of_provider(np, tegra20_clk_src_onecell_get);
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
tegra_clk_apply_init_table = tegra20_clock_apply_init_table;
|
||||
|
|
|
@ -3567,7 +3567,7 @@ static void __init tegra210_clock_init(struct device_node *np)
|
|||
tegra_init_special_resets(2, tegra210_reset_assert,
|
||||
tegra210_reset_deassert);
|
||||
|
||||
tegra_add_of_provider(np);
|
||||
tegra_add_of_provider(np, of_clk_src_onecell_get);
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
tegra210_mbist_clk_init();
|
||||
|
|
|
@ -1349,7 +1349,7 @@ static void __init tegra30_clock_init(struct device_node *np)
|
|||
|
||||
tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX);
|
||||
|
||||
tegra_add_of_provider(np);
|
||||
tegra_add_of_provider(np, of_clk_src_onecell_get);
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
|
||||
|
|
|
@ -298,7 +298,8 @@ static struct reset_controller_dev rst_ctlr = {
|
|||
.of_reset_n_cells = 1,
|
||||
};
|
||||
|
||||
void __init tegra_add_of_provider(struct device_node *np)
|
||||
void __init tegra_add_of_provider(struct device_node *np,
|
||||
void *clk_src_onecell_get)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -314,7 +315,7 @@ void __init tegra_add_of_provider(struct device_node *np)
|
|||
|
||||
clk_data.clks = clks;
|
||||
clk_data.clk_num = clk_num;
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||
of_clk_add_provider(np, clk_src_onecell_get, &clk_data);
|
||||
|
||||
rst_ctlr.of_node = np;
|
||||
rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
|
||||
|
|
|
@ -763,7 +763,7 @@ struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
|
|||
|
||||
struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
|
||||
|
||||
void tegra_add_of_provider(struct device_node *np);
|
||||
void tegra_add_of_provider(struct device_node *np, void *clk_src_onecell_get);
|
||||
void tegra_register_devclks(struct tegra_devclk *dev_clks, int num);
|
||||
|
||||
void tegra_audio_clk_init(void __iomem *clk_base,
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_
|
||||
#define _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_
|
||||
|
||||
#define CLK_AR100 0
|
||||
|
||||
#define CLK_R_APB1 2
|
||||
|
||||
#define CLK_R_APB1_TIMER 4
|
||||
#define CLK_R_APB1_TWD 5
|
||||
#define CLK_R_APB1_PWM 6
|
||||
#define CLK_R_APB2_UART 7
|
||||
#define CLK_R_APB2_I2C 8
|
||||
#define CLK_R_APB1_IR 9
|
||||
#define CLK_R_APB1_W1 10
|
||||
|
||||
#define CLK_IR 11
|
||||
#define CLK_W1 12
|
||||
|
||||
#endif /* _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ */
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
|
||||
/*
|
||||
* Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_
|
||||
#define _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_
|
||||
|
||||
#define RST_R_APB1_TIMER 0
|
||||
#define RST_R_APB1_TWD 1
|
||||
#define RST_R_APB1_PWM 2
|
||||
#define RST_R_APB2_UART 3
|
||||
#define RST_R_APB2_I2C 4
|
||||
#define RST_R_APB1_IR 5
|
||||
#define RST_R_APB1_W1 6
|
||||
|
||||
#endif /* _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ */
|
Loading…
Reference in New Issue