mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 17:17:04 -04:00
Merge tag 'clk-meson-v6.5-1' of https://github.com/BayLibre/clk-meson into clk-allwinner
Pull Amlogic clk driver updates from Jerome Brunet: - Add amlogic a1 SoC family PLL and peripheral clock controller support * tag 'clk-meson-v6.5-1' of https://github.com/BayLibre/clk-meson: clk: meson: a1: add Amlogic A1 Peripherals clock controller driver clk: meson: a1: add Amlogic A1 PLL clock controller driver clk: meson: introduce new pll power-on sequence for A1 SoC family clk: meson: make pll rst bit as optional dt-bindings: clock: meson: add A1 Peripherals clock controller bindings dt-bindings: clock: meson: add A1 PLL clock controller bindings
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/amlogic,a1-peripherals-clkc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic A1 Peripherals Clock Control Unit
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <neil.armstrong@linaro.org>
|
||||
- Jerome Brunet <jbrunet@baylibre.com>
|
||||
- Jian Hu <jian.hu@jian.hu.com>
|
||||
- Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: amlogic,a1-peripherals-clkc
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: input fixed pll div2
|
||||
- description: input fixed pll div3
|
||||
- description: input fixed pll div5
|
||||
- description: input fixed pll div7
|
||||
- description: input hifi pll
|
||||
- description: input oscillator (usually at 24MHz)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fclk_div2
|
||||
- const: fclk_div3
|
||||
- const: fclk_div5
|
||||
- const: fclk_div7
|
||||
- const: hifi_pll
|
||||
- const: xtal
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#clock-cells'
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
|
||||
apb {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
clock-controller@800 {
|
||||
compatible = "amlogic,a1-peripherals-clkc";
|
||||
reg = <0 0x800 0 0x104>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&clkc_pll CLKID_FCLK_DIV2>,
|
||||
<&clkc_pll CLKID_FCLK_DIV3>,
|
||||
<&clkc_pll CLKID_FCLK_DIV5>,
|
||||
<&clkc_pll CLKID_FCLK_DIV7>,
|
||||
<&clkc_pll CLKID_HIFI_PLL>,
|
||||
<&xtal>;
|
||||
clock-names = "fclk_div2", "fclk_div3",
|
||||
"fclk_div5", "fclk_div7",
|
||||
"hifi_pll", "xtal";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/amlogic,a1-pll-clkc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic A1 PLL Clock Control Unit
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <neil.armstrong@linaro.org>
|
||||
- Jerome Brunet <jbrunet@baylibre.com>
|
||||
- Jian Hu <jian.hu@jian.hu.com>
|
||||
- Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: amlogic,a1-pll-clkc
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: input fixpll_in
|
||||
- description: input hifipll_in
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fixpll_in
|
||||
- const: hifipll_in
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#clock-cells'
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
|
||||
apb {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
clock-controller@7c80 {
|
||||
compatible = "amlogic,a1-pll-clkc";
|
||||
reg = <0 0x7c80 0 0x18c>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&clkc_periphs CLKID_FIXPLL_IN>,
|
||||
<&clkc_periphs CLKID_HIFIPLL_IN>;
|
||||
clock-names = "fixpll_in", "hifipll_in";
|
||||
};
|
||||
};
|
||||
@@ -1888,6 +1888,7 @@ L: linux-amlogic@lists.infradead.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/clock/amlogic*
|
||||
F: drivers/clk/meson/
|
||||
F: include/dt-bindings/clock/a1*
|
||||
F: include/dt-bindings/clock/gxbb*
|
||||
F: include/dt-bindings/clock/meson*
|
||||
|
||||
|
||||
@@ -99,6 +99,26 @@ config COMMON_CLK_AXG_AUDIO
|
||||
Support for the audio clock controller on AmLogic A113D devices,
|
||||
aka axg, Say Y if you want audio subsystem to work.
|
||||
|
||||
config COMMON_CLK_A1_PLL
|
||||
tristate "Amlogic A1 SoC PLL controller support"
|
||||
depends on ARM64
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
select COMMON_CLK_MESON_PLL
|
||||
help
|
||||
Support for the PLL clock controller on Amlogic A113L based
|
||||
device, A1 SoC Family. Say Y if you want A1 PLL clock controller
|
||||
to work.
|
||||
|
||||
config COMMON_CLK_A1_PERIPHERALS
|
||||
tristate "Amlogic A1 SoC Peripherals clock controller support"
|
||||
depends on ARM64
|
||||
select COMMON_CLK_MESON_DUALDIV
|
||||
select COMMON_CLK_MESON_REGMAP
|
||||
help
|
||||
Support for the Peripherals clock controller on Amlogic A113L based
|
||||
device, A1 SoC Family. Say Y if you want A1 Peripherals clock
|
||||
controller to work.
|
||||
|
||||
config COMMON_CLK_G12A
|
||||
tristate "G12 and SM1 SoC clock controllers support"
|
||||
depends on ARM64
|
||||
|
||||
@@ -16,6 +16,8 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
|
||||
obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
|
||||
obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
|
||||
obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
|
||||
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
|
||||
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
|
||||
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
|
||||
|
||||
2243
drivers/clk/meson/a1-peripherals.c
Normal file
2243
drivers/clk/meson/a1-peripherals.c
Normal file
File diff suppressed because it is too large
Load Diff
113
drivers/clk/meson/a1-peripherals.h
Normal file
113
drivers/clk/meson/a1-peripherals.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Amlogic A1 Peripherals Clock Controller internals
|
||||
*
|
||||
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
||||
* Author: Jian Hu <jian.hu@amlogic.com>
|
||||
*
|
||||
* Copyright (c) 2023, SberDevices. All Rights Reserved.
|
||||
* Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
*/
|
||||
|
||||
#ifndef __A1_PERIPHERALS_H
|
||||
#define __A1_PERIPHERALS_H
|
||||
|
||||
/* peripherals clock controller register offset */
|
||||
#define SYS_OSCIN_CTRL 0x0
|
||||
#define RTC_BY_OSCIN_CTRL0 0x4
|
||||
#define RTC_BY_OSCIN_CTRL1 0x8
|
||||
#define RTC_CTRL 0xc
|
||||
#define SYS_CLK_CTRL0 0x10
|
||||
#define SYS_CLK_EN0 0x1c
|
||||
#define SYS_CLK_EN1 0x20
|
||||
#define AXI_CLK_EN 0x24
|
||||
#define DSPA_CLK_EN 0x28
|
||||
#define DSPB_CLK_EN 0x2c
|
||||
#define DSPA_CLK_CTRL0 0x30
|
||||
#define DSPB_CLK_CTRL0 0x34
|
||||
#define CLK12_24_CTRL 0x38
|
||||
#define GEN_CLK_CTRL 0x3c
|
||||
#define SAR_ADC_CLK_CTRL 0xc0
|
||||
#define PWM_CLK_AB_CTRL 0xc4
|
||||
#define PWM_CLK_CD_CTRL 0xc8
|
||||
#define PWM_CLK_EF_CTRL 0xcc
|
||||
#define SPICC_CLK_CTRL 0xd0
|
||||
#define TS_CLK_CTRL 0xd4
|
||||
#define SPIFC_CLK_CTRL 0xd8
|
||||
#define USB_BUSCLK_CTRL 0xdc
|
||||
#define SD_EMMC_CLK_CTRL 0xe0
|
||||
#define CECA_CLK_CTRL0 0xe4
|
||||
#define CECA_CLK_CTRL1 0xe8
|
||||
#define CECB_CLK_CTRL0 0xec
|
||||
#define CECB_CLK_CTRL1 0xf0
|
||||
#define PSRAM_CLK_CTRL 0xf4
|
||||
#define DMC_CLK_CTRL 0xf8
|
||||
|
||||
/* include the CLKIDs that have been made part of the DT binding */
|
||||
#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
|
||||
|
||||
/*
|
||||
* CLKID index values for internal clocks
|
||||
*
|
||||
* These indices are entirely contrived and do not map onto the hardware.
|
||||
* It has now been decided to expose everything by default in the DT header:
|
||||
* include/dt-bindings/clock/a1-peripherals-clkc.h.
|
||||
* Only the clocks ids we don't want to expose, such as the internal muxes and
|
||||
* dividers of composite clocks, will remain defined here.
|
||||
*/
|
||||
#define CLKID_XTAL_IN 0
|
||||
#define CLKID_DSPA_SEL 61
|
||||
#define CLKID_DSPB_SEL 62
|
||||
#define CLKID_SARADC_SEL 74
|
||||
#define CLKID_SYS_A_SEL 89
|
||||
#define CLKID_SYS_A_DIV 90
|
||||
#define CLKID_SYS_A 91
|
||||
#define CLKID_SYS_B_SEL 92
|
||||
#define CLKID_SYS_B_DIV 93
|
||||
#define CLKID_SYS_B 94
|
||||
#define CLKID_DSPA_A_DIV 96
|
||||
#define CLKID_DSPA_A 97
|
||||
#define CLKID_DSPA_B_DIV 99
|
||||
#define CLKID_DSPA_B 100
|
||||
#define CLKID_DSPB_A_DIV 102
|
||||
#define CLKID_DSPB_A 103
|
||||
#define CLKID_DSPB_B_DIV 105
|
||||
#define CLKID_DSPB_B 106
|
||||
#define CLKID_RTC_32K_IN 107
|
||||
#define CLKID_RTC_32K_DIV 108
|
||||
#define CLKID_RTC_32K_XTAL 109
|
||||
#define CLKID_RTC_32K_SEL 110
|
||||
#define CLKID_CECB_32K_IN 111
|
||||
#define CLKID_CECB_32K_DIV 112
|
||||
#define CLKID_CECA_32K_IN 115
|
||||
#define CLKID_CECA_32K_DIV 116
|
||||
#define CLKID_DIV2_PRE 119
|
||||
#define CLKID_24M_DIV2 120
|
||||
#define CLKID_GEN_DIV 122
|
||||
#define CLKID_SARADC_DIV 123
|
||||
#define CLKID_PWM_A_DIV 125
|
||||
#define CLKID_PWM_B_DIV 127
|
||||
#define CLKID_PWM_C_DIV 129
|
||||
#define CLKID_PWM_D_DIV 131
|
||||
#define CLKID_PWM_E_DIV 133
|
||||
#define CLKID_PWM_F_DIV 135
|
||||
#define CLKID_SPICC_SEL 136
|
||||
#define CLKID_SPICC_DIV 137
|
||||
#define CLKID_SPICC_SEL2 138
|
||||
#define CLKID_TS_DIV 139
|
||||
#define CLKID_SPIFC_SEL 140
|
||||
#define CLKID_SPIFC_DIV 141
|
||||
#define CLKID_SPIFC_SEL2 142
|
||||
#define CLKID_USB_BUS_SEL 143
|
||||
#define CLKID_USB_BUS_DIV 144
|
||||
#define CLKID_SD_EMMC_SEL 145
|
||||
#define CLKID_SD_EMMC_DIV 146
|
||||
#define CLKID_PSRAM_SEL 148
|
||||
#define CLKID_PSRAM_DIV 149
|
||||
#define CLKID_PSRAM_SEL2 150
|
||||
#define CLKID_DMC_SEL 151
|
||||
#define CLKID_DMC_DIV 152
|
||||
#define CLKID_DMC_SEL2 153
|
||||
#define NR_CLKS 154
|
||||
|
||||
#endif /* __A1_PERIPHERALS_H */
|
||||
356
drivers/clk/meson/a1-pll.c
Normal file
356
drivers/clk/meson/a1-pll.c
Normal file
@@ -0,0 +1,356 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
||||
* Author: Jian Hu <jian.hu@amlogic.com>
|
||||
*
|
||||
* Copyright (c) 2023, SberDevices. All Rights Reserved.
|
||||
* Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "a1-pll.h"
|
||||
#include "clk-regmap.h"
|
||||
|
||||
static struct clk_regmap fixed_pll_dco = {
|
||||
.data = &(struct meson_clk_pll_data){
|
||||
.en = {
|
||||
.reg_off = ANACTRL_FIXPLL_CTRL0,
|
||||
.shift = 28,
|
||||
.width = 1,
|
||||
},
|
||||
.m = {
|
||||
.reg_off = ANACTRL_FIXPLL_CTRL0,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.n = {
|
||||
.reg_off = ANACTRL_FIXPLL_CTRL0,
|
||||
.shift = 10,
|
||||
.width = 5,
|
||||
},
|
||||
.frac = {
|
||||
.reg_off = ANACTRL_FIXPLL_CTRL1,
|
||||
.shift = 0,
|
||||
.width = 19,
|
||||
},
|
||||
.l = {
|
||||
.reg_off = ANACTRL_FIXPLL_STS,
|
||||
.shift = 31,
|
||||
.width = 1,
|
||||
},
|
||||
.rst = {
|
||||
.reg_off = ANACTRL_FIXPLL_CTRL0,
|
||||
.shift = 29,
|
||||
.width = 1,
|
||||
},
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fixed_pll_dco",
|
||||
.ops = &meson_clk_pll_ro_ops,
|
||||
.parent_data = &(const struct clk_parent_data) {
|
||||
.fw_name = "fixpll_in",
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap fixed_pll = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = ANACTRL_FIXPLL_CTRL0,
|
||||
.bit_idx = 20,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "fixed_pll",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fixed_pll_dco.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pll_mult_range hifi_pll_mult_range = {
|
||||
.min = 32,
|
||||
.max = 64,
|
||||
};
|
||||
|
||||
static const struct reg_sequence hifi_init_regs[] = {
|
||||
{ .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 },
|
||||
{ .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 },
|
||||
{ .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 },
|
||||
{ .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 },
|
||||
{ .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 },
|
||||
};
|
||||
|
||||
static struct clk_regmap hifi_pll = {
|
||||
.data = &(struct meson_clk_pll_data){
|
||||
.en = {
|
||||
.reg_off = ANACTRL_HIFIPLL_CTRL0,
|
||||
.shift = 28,
|
||||
.width = 1,
|
||||
},
|
||||
.m = {
|
||||
.reg_off = ANACTRL_HIFIPLL_CTRL0,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.n = {
|
||||
.reg_off = ANACTRL_HIFIPLL_CTRL0,
|
||||
.shift = 10,
|
||||
.width = 5,
|
||||
},
|
||||
.frac = {
|
||||
.reg_off = ANACTRL_HIFIPLL_CTRL1,
|
||||
.shift = 0,
|
||||
.width = 19,
|
||||
},
|
||||
.l = {
|
||||
.reg_off = ANACTRL_HIFIPLL_STS,
|
||||
.shift = 31,
|
||||
.width = 1,
|
||||
},
|
||||
.current_en = {
|
||||
.reg_off = ANACTRL_HIFIPLL_CTRL0,
|
||||
.shift = 26,
|
||||
.width = 1,
|
||||
},
|
||||
.l_detect = {
|
||||
.reg_off = ANACTRL_HIFIPLL_CTRL2,
|
||||
.shift = 6,
|
||||
.width = 1,
|
||||
},
|
||||
.range = &hifi_pll_mult_range,
|
||||
.init_regs = hifi_init_regs,
|
||||
.init_count = ARRAY_SIZE(hifi_init_regs),
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hifi_pll",
|
||||
.ops = &meson_clk_pll_ops,
|
||||
.parent_data = &(const struct clk_parent_data) {
|
||||
.fw_name = "hifipll_in",
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor fclk_div2_div = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div2_div",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fixed_pll.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap fclk_div2 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = ANACTRL_FIXPLL_CTRL0,
|
||||
.bit_idx = 21,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div2",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fclk_div2_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
/*
|
||||
* This clock is used by DDR clock in BL2 firmware
|
||||
* and is required by the platform to operate correctly.
|
||||
* Until the following condition are met, we need this clock to
|
||||
* be marked as critical:
|
||||
* a) Mark the clock used by a firmware resource, if possible
|
||||
* b) CCF has a clock hand-off mechanism to make the sure the
|
||||
* clock stays on until the proper driver comes along
|
||||
*/
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor fclk_div3_div = {
|
||||
.mult = 1,
|
||||
.div = 3,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div3_div",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fixed_pll.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap fclk_div3 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = ANACTRL_FIXPLL_CTRL0,
|
||||
.bit_idx = 22,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div3",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fclk_div3_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
/*
|
||||
* This clock is used by APB bus which is set in boot ROM code
|
||||
* and is required by the platform to operate correctly.
|
||||
*/
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor fclk_div5_div = {
|
||||
.mult = 1,
|
||||
.div = 5,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div5_div",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fixed_pll.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap fclk_div5 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = ANACTRL_FIXPLL_CTRL0,
|
||||
.bit_idx = 23,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div5",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fclk_div5_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
/*
|
||||
* This clock is used by AXI bus which setted in Romcode
|
||||
* and is required by the platform to operate correctly.
|
||||
*/
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor fclk_div7_div = {
|
||||
.mult = 1,
|
||||
.div = 7,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div7_div",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fixed_pll.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap fclk_div7 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = ANACTRL_FIXPLL_CTRL0,
|
||||
.bit_idx = 24,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "fclk_div7",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&fclk_div7_div.hw
|
||||
},
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/* Array of all clocks registered by this provider */
|
||||
static struct clk_hw_onecell_data a1_pll_clks = {
|
||||
.hws = {
|
||||
[CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw,
|
||||
[CLKID_FIXED_PLL] = &fixed_pll.hw,
|
||||
[CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw,
|
||||
[CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw,
|
||||
[CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw,
|
||||
[CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw,
|
||||
[CLKID_FCLK_DIV2] = &fclk_div2.hw,
|
||||
[CLKID_FCLK_DIV3] = &fclk_div3.hw,
|
||||
[CLKID_FCLK_DIV5] = &fclk_div5.hw,
|
||||
[CLKID_FCLK_DIV7] = &fclk_div7.hw,
|
||||
[CLKID_HIFI_PLL] = &hifi_pll.hw,
|
||||
[NR_PLL_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_PLL_CLKS,
|
||||
};
|
||||
|
||||
static struct clk_regmap *const a1_pll_regmaps[] = {
|
||||
&fixed_pll_dco,
|
||||
&fixed_pll,
|
||||
&fclk_div2,
|
||||
&fclk_div3,
|
||||
&fclk_div5,
|
||||
&fclk_div7,
|
||||
&hifi_pll,
|
||||
};
|
||||
|
||||
static struct regmap_config a1_pll_regmap_cfg = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
static int meson_a1_pll_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *base;
|
||||
struct regmap *map;
|
||||
int clkid, i, err;
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return dev_err_probe(dev, PTR_ERR(base),
|
||||
"can't ioremap resource\n");
|
||||
|
||||
map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg);
|
||||
if (IS_ERR(map))
|
||||
return dev_err_probe(dev, PTR_ERR(map),
|
||||
"can't init regmap mmio region\n");
|
||||
|
||||
/* Populate regmap for the regmap backed clocks */
|
||||
for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++)
|
||||
a1_pll_regmaps[i]->map = map;
|
||||
|
||||
/* Register clocks */
|
||||
for (clkid = 0; clkid < a1_pll_clks.num; clkid++) {
|
||||
err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]);
|
||||
if (err)
|
||||
return dev_err_probe(dev, err,
|
||||
"clock[%d] registration failed\n",
|
||||
clkid);
|
||||
}
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
&a1_pll_clks);
|
||||
}
|
||||
|
||||
static const struct of_device_id a1_pll_clkc_match_table[] = {
|
||||
{ .compatible = "amlogic,a1-pll-clkc", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table);
|
||||
|
||||
static struct platform_driver a1_pll_clkc_driver = {
|
||||
.probe = meson_a1_pll_probe,
|
||||
.driver = {
|
||||
.name = "a1-pll-clkc",
|
||||
.of_match_table = a1_pll_clkc_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(a1_pll_clkc_driver);
|
||||
MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
|
||||
MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
|
||||
MODULE_LICENSE("GPL");
|
||||
47
drivers/clk/meson/a1-pll.h
Normal file
47
drivers/clk/meson/a1-pll.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Amlogic A1 PLL Clock Controller internals
|
||||
*
|
||||
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
||||
* Author: Jian Hu <jian.hu@amlogic.com>
|
||||
*
|
||||
* Copyright (c) 2023, SberDevices. All Rights Reserved.
|
||||
* Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
*/
|
||||
|
||||
#ifndef __A1_PLL_H
|
||||
#define __A1_PLL_H
|
||||
|
||||
#include "clk-pll.h"
|
||||
|
||||
/* PLL register offset */
|
||||
#define ANACTRL_FIXPLL_CTRL0 0x0
|
||||
#define ANACTRL_FIXPLL_CTRL1 0x4
|
||||
#define ANACTRL_FIXPLL_STS 0x14
|
||||
#define ANACTRL_HIFIPLL_CTRL0 0xc0
|
||||
#define ANACTRL_HIFIPLL_CTRL1 0xc4
|
||||
#define ANACTRL_HIFIPLL_CTRL2 0xc8
|
||||
#define ANACTRL_HIFIPLL_CTRL3 0xcc
|
||||
#define ANACTRL_HIFIPLL_CTRL4 0xd0
|
||||
#define ANACTRL_HIFIPLL_STS 0xd4
|
||||
|
||||
/* include the CLKIDs that have been made part of the DT binding */
|
||||
#include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
|
||||
|
||||
/*
|
||||
* CLKID index values for internal clocks
|
||||
*
|
||||
* These indices are entirely contrived and do not map onto the hardware.
|
||||
* It has now been decided to expose everything by default in the DT header:
|
||||
* include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want
|
||||
* to expose, such as the internal muxes and dividers of composite clocks,
|
||||
* will remain defined here.
|
||||
*/
|
||||
#define CLKID_FIXED_PLL_DCO 0
|
||||
#define CLKID_FCLK_DIV2_DIV 2
|
||||
#define CLKID_FCLK_DIV3_DIV 3
|
||||
#define CLKID_FCLK_DIV5_DIV 4
|
||||
#define CLKID_FCLK_DIV7_DIV 5
|
||||
#define NR_PLL_CLKS 11
|
||||
|
||||
#endif /* __A1_PLL_H */
|
||||
@@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw)
|
||||
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
|
||||
|
||||
if (pll->init_count) {
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
if (MESON_PARM_APPLICABLE(&pll->rst))
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
|
||||
regmap_multi_reg_write(clk->map, pll->init_regs,
|
||||
pll->init_count);
|
||||
meson_parm_write(clk->map, &pll->rst, 0);
|
||||
|
||||
if (MESON_PARM_APPLICABLE(&pll->rst))
|
||||
meson_parm_write(clk->map, &pll->rst, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw)
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
|
||||
|
||||
if (meson_parm_read(clk->map, &pll->rst) ||
|
||||
!meson_parm_read(clk->map, &pll->en) ||
|
||||
if (MESON_PARM_APPLICABLE(&pll->rst) &&
|
||||
meson_parm_read(clk->map, &pll->rst))
|
||||
return 0;
|
||||
|
||||
if (!meson_parm_read(clk->map, &pll->en) ||
|
||||
!meson_parm_read(clk->map, &pll->l))
|
||||
return 0;
|
||||
|
||||
@@ -341,13 +348,34 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
|
||||
return 0;
|
||||
|
||||
/* Make sure the pll is in reset */
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
if (MESON_PARM_APPLICABLE(&pll->rst))
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
|
||||
/* Enable the pll */
|
||||
meson_parm_write(clk->map, &pll->en, 1);
|
||||
|
||||
/* Take the pll out reset */
|
||||
meson_parm_write(clk->map, &pll->rst, 0);
|
||||
if (MESON_PARM_APPLICABLE(&pll->rst))
|
||||
meson_parm_write(clk->map, &pll->rst, 0);
|
||||
|
||||
/*
|
||||
* Compared with the previous SoCs, self-adaption current module
|
||||
* is newly added for A1, keep the new power-on sequence to enable the
|
||||
* PLL. The sequence is:
|
||||
* 1. enable the pll, delay for 10us
|
||||
* 2. enable the pll self-adaption current module, delay for 40us
|
||||
* 3. enable the lock detect module
|
||||
*/
|
||||
if (MESON_PARM_APPLICABLE(&pll->current_en)) {
|
||||
usleep_range(10, 20);
|
||||
meson_parm_write(clk->map, &pll->current_en, 1);
|
||||
usleep_range(40, 50);
|
||||
};
|
||||
|
||||
if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
|
||||
meson_parm_write(clk->map, &pll->l_detect, 1);
|
||||
meson_parm_write(clk->map, &pll->l_detect, 0);
|
||||
}
|
||||
|
||||
if (meson_clk_pll_wait_lock(hw))
|
||||
return -EIO;
|
||||
@@ -361,10 +389,15 @@ static void meson_clk_pll_disable(struct clk_hw *hw)
|
||||
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
|
||||
|
||||
/* Put the pll is in reset */
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
if (MESON_PARM_APPLICABLE(&pll->rst))
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
|
||||
/* Disable the pll */
|
||||
meson_parm_write(clk->map, &pll->en, 0);
|
||||
|
||||
/* Disable PLL internal self-adaption current module */
|
||||
if (MESON_PARM_APPLICABLE(&pll->current_en))
|
||||
meson_parm_write(clk->map, &pll->current_en, 0);
|
||||
}
|
||||
|
||||
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
@@ -36,6 +36,8 @@ struct meson_clk_pll_data {
|
||||
struct parm frac;
|
||||
struct parm l;
|
||||
struct parm rst;
|
||||
struct parm current_en;
|
||||
struct parm l_detect;
|
||||
const struct reg_sequence *init_regs;
|
||||
unsigned int init_count;
|
||||
const struct pll_params_table *table;
|
||||
|
||||
115
include/dt-bindings/clock/amlogic,a1-peripherals-clkc.h
Normal file
115
include/dt-bindings/clock/amlogic,a1-peripherals-clkc.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
||||
* Author: Jian Hu <jian.hu@amlogic.com>
|
||||
*
|
||||
* Copyright (c) 2023, SberDevices. All Rights Reserved.
|
||||
* Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
*/
|
||||
|
||||
#ifndef __A1_PERIPHERALS_CLKC_H
|
||||
#define __A1_PERIPHERALS_CLKC_H
|
||||
|
||||
#define CLKID_FIXPLL_IN 1
|
||||
#define CLKID_USB_PHY_IN 2
|
||||
#define CLKID_USB_CTRL_IN 3
|
||||
#define CLKID_HIFIPLL_IN 4
|
||||
#define CLKID_SYSPLL_IN 5
|
||||
#define CLKID_DDS_IN 6
|
||||
#define CLKID_SYS 7
|
||||
#define CLKID_CLKTREE 8
|
||||
#define CLKID_RESET_CTRL 9
|
||||
#define CLKID_ANALOG_CTRL 10
|
||||
#define CLKID_PWR_CTRL 11
|
||||
#define CLKID_PAD_CTRL 12
|
||||
#define CLKID_SYS_CTRL 13
|
||||
#define CLKID_TEMP_SENSOR 14
|
||||
#define CLKID_AM2AXI_DIV 15
|
||||
#define CLKID_SPICC_B 16
|
||||
#define CLKID_SPICC_A 17
|
||||
#define CLKID_MSR 18
|
||||
#define CLKID_AUDIO 19
|
||||
#define CLKID_JTAG_CTRL 20
|
||||
#define CLKID_SARADC_EN 21
|
||||
#define CLKID_PWM_EF 22
|
||||
#define CLKID_PWM_CD 23
|
||||
#define CLKID_PWM_AB 24
|
||||
#define CLKID_CEC 25
|
||||
#define CLKID_I2C_S 26
|
||||
#define CLKID_IR_CTRL 27
|
||||
#define CLKID_I2C_M_D 28
|
||||
#define CLKID_I2C_M_C 29
|
||||
#define CLKID_I2C_M_B 30
|
||||
#define CLKID_I2C_M_A 31
|
||||
#define CLKID_ACODEC 32
|
||||
#define CLKID_OTP 33
|
||||
#define CLKID_SD_EMMC_A 34
|
||||
#define CLKID_USB_PHY 35
|
||||
#define CLKID_USB_CTRL 36
|
||||
#define CLKID_SYS_DSPB 37
|
||||
#define CLKID_SYS_DSPA 38
|
||||
#define CLKID_DMA 39
|
||||
#define CLKID_IRQ_CTRL 40
|
||||
#define CLKID_NIC 41
|
||||
#define CLKID_GIC 42
|
||||
#define CLKID_UART_C 43
|
||||
#define CLKID_UART_B 44
|
||||
#define CLKID_UART_A 45
|
||||
#define CLKID_SYS_PSRAM 46
|
||||
#define CLKID_RSA 47
|
||||
#define CLKID_CORESIGHT 48
|
||||
#define CLKID_AM2AXI_VAD 49
|
||||
#define CLKID_AUDIO_VAD 50
|
||||
#define CLKID_AXI_DMC 51
|
||||
#define CLKID_AXI_PSRAM 52
|
||||
#define CLKID_RAMB 53
|
||||
#define CLKID_RAMA 54
|
||||
#define CLKID_AXI_SPIFC 55
|
||||
#define CLKID_AXI_NIC 56
|
||||
#define CLKID_AXI_DMA 57
|
||||
#define CLKID_CPU_CTRL 58
|
||||
#define CLKID_ROM 59
|
||||
#define CLKID_PROC_I2C 60
|
||||
#define CLKID_DSPA_EN 63
|
||||
#define CLKID_DSPA_EN_NIC 64
|
||||
#define CLKID_DSPB_EN 65
|
||||
#define CLKID_DSPB_EN_NIC 66
|
||||
#define CLKID_RTC 67
|
||||
#define CLKID_CECA_32K 68
|
||||
#define CLKID_CECB_32K 69
|
||||
#define CLKID_24M 70
|
||||
#define CLKID_12M 71
|
||||
#define CLKID_FCLK_DIV2_DIVN 72
|
||||
#define CLKID_GEN 73
|
||||
#define CLKID_SARADC 75
|
||||
#define CLKID_PWM_A 76
|
||||
#define CLKID_PWM_B 77
|
||||
#define CLKID_PWM_C 78
|
||||
#define CLKID_PWM_D 79
|
||||
#define CLKID_PWM_E 80
|
||||
#define CLKID_PWM_F 81
|
||||
#define CLKID_SPICC 82
|
||||
#define CLKID_TS 83
|
||||
#define CLKID_SPIFC 84
|
||||
#define CLKID_USB_BUS 85
|
||||
#define CLKID_SD_EMMC 86
|
||||
#define CLKID_PSRAM 87
|
||||
#define CLKID_DMC 88
|
||||
#define CLKID_DSPA_A_SEL 95
|
||||
#define CLKID_DSPA_B_SEL 98
|
||||
#define CLKID_DSPB_A_SEL 101
|
||||
#define CLKID_DSPB_B_SEL 104
|
||||
#define CLKID_CECB_32K_SEL_PRE 113
|
||||
#define CLKID_CECB_32K_SEL 114
|
||||
#define CLKID_CECA_32K_SEL_PRE 117
|
||||
#define CLKID_CECA_32K_SEL 118
|
||||
#define CLKID_GEN_SEL 121
|
||||
#define CLKID_PWM_A_SEL 124
|
||||
#define CLKID_PWM_B_SEL 126
|
||||
#define CLKID_PWM_C_SEL 128
|
||||
#define CLKID_PWM_D_SEL 130
|
||||
#define CLKID_PWM_E_SEL 132
|
||||
#define CLKID_PWM_F_SEL 134
|
||||
#define CLKID_SD_EMMC_SEL2 147
|
||||
|
||||
#endif /* __A1_PERIPHERALS_CLKC_H */
|
||||
20
include/dt-bindings/clock/amlogic,a1-pll-clkc.h
Normal file
20
include/dt-bindings/clock/amlogic,a1-pll-clkc.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
||||
* Author: Jian Hu <jian.hu@amlogic.com>
|
||||
*
|
||||
* Copyright (c) 2023, SberDevices. All Rights Reserved.
|
||||
* Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
|
||||
*/
|
||||
|
||||
#ifndef __A1_PLL_CLKC_H
|
||||
#define __A1_PLL_CLKC_H
|
||||
|
||||
#define CLKID_FIXED_PLL 1
|
||||
#define CLKID_FCLK_DIV2 6
|
||||
#define CLKID_FCLK_DIV3 7
|
||||
#define CLKID_FCLK_DIV5 8
|
||||
#define CLKID_FCLK_DIV7 9
|
||||
#define CLKID_HIFI_PLL 10
|
||||
|
||||
#endif /* __A1_PLL_CLKC_H */
|
||||
Reference in New Issue
Block a user