Commit 5debcd01 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-mmp', 'clk-intel', 'clk-ingenic', 'clk-qcom' and 'clk-silabs' into clk-next

 - Start making audio and GPU clks work on Marvell MMP2/MMP3 SoCs
 - Add support for X1830 and X1000 Ingenic SoC clk controllers
 - Add support for Qualcomm's MSM8939 Generic Clock Controller
 - Add some GPU, NPU, and UFS clks to Qualcomm SM8150 driver
 - Enable supply regulators for GPU gdscs on Qualcomm SoCs
 - Add support for Si5342, Si5344 and Si5345 chips

* clk-mmp:
  clk: mmp2: Add audio clock controller driver
  dt-bindings: clock: Add Marvell MMP Audio Clock Controller binding
  clk: mmp2: Add support for power islands
  dt-bindings: marvell,mmp2: Add ids for the power domains
  dt-bindings: clock: Make marvell,mmp2-clock a power controller
  clk: mmp2: Add the audio clock
  clk: mmp2: Add the I2S clocks
  clk: mmp2: Rename mmp2_pll_init() to mmp2_main_clk_init()
  clk: mmp2: Move thermal register defines up a bit
  dt-bindings: marvell,mmp2: Add clock id for the Audio clock
  dt-bindings: marvell,mmp2: Add clock id for the I2S clocks
  clk: mmp: frac: Allow setting bits other than the numerator/denominator
  clk: mmp: frac: Do not lose last 4 digits of precision

* clk-intel:
  clk: intel: remove redundant initialization of variable rate64
  clk: intel: Add CGU clock driver for a new SoC
  dt-bindings: clk: intel: Add bindings document & header file for CGU

* clk-ingenic:
  clk: ingenic: Mark ingenic_tcu_of_match as __maybe_unused
  clk: X1000: Add FIXDIV for SSI clock of X1000.
  dt-bindings: clock: Add and reorder ABI for X1000.
  clk: Ingenic: Add CGU driver for X1830.
  dt-bindings: clock: Add X1830 clock bindings.
  clk: Ingenic: Adjust cgu code to make it compatible with X1830.
  clk: Ingenic: Remove unnecessary spinlock when reading registers.

* clk-qcom:
  clk: qcom: Add missing msm8998 ufs_unipro_core_clk_src
  dt-bindings: clock: Add YAML schemas for QCOM A53 PLL
  clk: qcom: gcc-msm8939: Add MSM8939 Generic Clock Controller
  clk: qcom: gcc: Add support for Secure control source clock
  dt-bindings: clock: Add gcc_sec_ctrl_clk_src clock ID
  clk: qcom: gcc: Add support for a new frequency for SC7180
  clk: qcom: Add DT bindings for MSM8939 GCC
  clk: qcom: gcc: Add missing UFS clocks for SM8150
  clk: qcom: gcc: Add GPU and NPU clocks for SM8150
  clk: qcom: mmcc-msm8996: Properly describe GPU_GX gdsc
  clk: qcom: gdsc: Handle GDSC regulator supplies
  clk: qcom: msm8916: Fix the address location of pll->config_reg

* clk-silabs:
  clk: clk-si5341: Add support for the Si5345 series
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/intel,cgu-lgm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel Lightning Mountain SoC's Clock Controller(CGU) Binding
maintainers:
- Rahul Tanwar <rahul.tanwar@linux.intel.com>
description: |
Lightning Mountain(LGM) SoC's Clock Generation Unit(CGU) driver provides
all means to access the CGU hardware module in order to generate a series
of clocks for the whole system and individual peripherals.
Please refer to include/dt-bindings/clock/intel,lgm-clk.h header file, it
defines all available clocks as macros. These macros can be used in device
tree sources.
properties:
compatible:
const: intel,cgu-lgm
reg:
maxItems: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- '#clock-cells'
examples:
- |
cgu: clock-controller@e0200000 {
compatible = "intel,cgu-lgm";
reg = <0xe0200000 0x33c>;
#clock-cells = <1>;
};
...
# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/marvell,mmp2-audio-clock.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell MMP2 Audio Clock Controller
maintainers:
- Lubomir Rintel <lkundrak@v3.sk>
description: |
The audio clock controller generates and supplies the clocks to the audio
codec.
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
All these identifiers could be found in
<dt-bindings/clock/marvell,mmp2-audio.h>.
properties:
compatible:
enum:
- marvell,mmp2-audio-clock
reg:
maxItems: 1
clocks:
items:
- description: Audio subsystem clock
- description: The crystal oscillator clock
- description: First I2S clock
- description: Second I2S clock
clock-names:
items:
- const: audio
- const: vctcxo
- const: i2s0
- const: i2s1
'#clock-cells':
const: 1
power-domains:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/marvell,mmp2-audio.h>
#include <dt-bindings/power/marvell,mmp2.h>
clock-controller@d42a0c30 {
compatible = "marvell,mmp2-audio-clock";
reg = <0xd42a0c30 0x10>;
clock-names = "audio", "vctcxo", "i2s0", "i2s1";
clocks = <&soc_clocks MMP2_CLK_AUDIO>,
<&soc_clocks MMP2_CLK_VCTCXO>,
<&soc_clocks MMP2_CLK_I2S0>,
<&soc_clocks MMP2_CLK_I2S1>;
power-domains = <&soc_clocks MMP2_POWER_DOMAIN_AUDIO>;
#clock-cells = <1>;
};
......@@ -42,12 +42,16 @@ properties:
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
required:
- compatible
- reg
- reg-names
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
......@@ -61,4 +65,5 @@ examples:
reg-names = "mpmu", "apmu", "apbc";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
Qualcomm MSM8916 A53 PLL Binding
--------------------------------
The A53 PLL on MSM8916 platforms is the main CPU PLL used used for frequencies
above 1GHz.
Required properties :
- compatible : Shall contain only one of the following:
"qcom,msm8916-a53pll"
- reg : shall contain base register location and length
- #clock-cells : must be set to <0>
Example:
a53pll: clock@b016000 {
compatible = "qcom,msm8916-a53pll";
reg = <0xb016000 0x40>;
#clock-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,a53pll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm A53 PLL Binding
maintainers:
- Sivaprakash Murugesan <sivaprak@codeaurora.org>
description:
The A53 PLL on few Qualcomm platforms is the main CPU PLL used used for
frequencies above 1GHz.
properties:
compatible:
const: qcom,msm8916-a53pll
reg:
maxItems: 1
'#clock-cells':
const: 0
required:
- compatible
- reg
- '#clock-cells'
additionalProperties: false
examples:
#Example 1 - A53 PLL found on MSM8916 devices
- |
a53pll: clock@b016000 {
compatible = "qcom,msm8916-a53pll";
reg = <0xb016000 0x40>;
#clock-cells = <0>;
};
......@@ -22,6 +22,8 @@ description: |
- dt-bindings/reset/qcom,gcc-ipq6018.h
- dt-bindings/clock/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
- dt-bindings/reset/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
- dt-bindings/clock/qcom,gcc-msm8939.h
- dt-bindings/reset/qcom,gcc-msm8939.h
- dt-bindings/clock/qcom,gcc-msm8660.h
- dt-bindings/reset/qcom,gcc-msm8660.h
- dt-bindings/clock/qcom,gcc-msm8974.h
......@@ -41,6 +43,7 @@ properties:
- qcom,gcc-ipq8064
- qcom,gcc-msm8660
- qcom,gcc-msm8916
- qcom,gcc-msm8939
- qcom,gcc-msm8960
- qcom,gcc-msm8974
- qcom,gcc-msm8974pro
......
......@@ -67,6 +67,10 @@ properties:
description:
Protected clock specifier list as per common clock binding
vdd-gfx-supply:
description:
Regulator supply for the GPU_GX GDSC
required:
- compatible
- reg
......
Binding for Silicon Labs Si5341 and Si5340 programmable i2c clock generator.
Binding for Silicon Labs Si5340, Si5341 Si5342, Si5344 and Si5345 programmable
i2c clock generator.
Reference
[1] Si5341 Data Sheet
https://www.silabs.com/documents/public/data-sheets/Si5341-40-D-DataSheet.pdf
[2] Si5341 Reference Manual
https://www.silabs.com/documents/public/reference-manuals/Si5341-40-D-RM.pdf
[3] Si5345 Reference Manual
https://www.silabs.com/documents/public/reference-manuals/Si5345-44-42-D-RM.pdf
The Si5341 and Si5340 are programmable i2c clock generators with up to 10 output
clocks. The chip contains a PLL that sources 5 (or 4) multisynth clocks, which
in turn can be directed to any of the 10 (or 4) outputs through a divider.
The internal structure of the clock generators can be found in [2].
The Si5345 is similar to the Si5341 with the addition of fractional input
dividers and automatic input selection, as described in [3].
The Si5342 and Si5344 are smaller versions of the Si5345, with 2 or 4 outputs.
The driver can be used in "as is" mode, reading the current settings from the
chip at boot, in case you have a (pre-)programmed device. If the PLL is not
......@@ -28,6 +34,9 @@ Required properties:
- compatible: shall be one of the following:
"silabs,si5340" - Si5340 A/B/C/D
"silabs,si5341" - Si5341 A/B/C/D
"silabs,si5342" - Si5342 A/B/C/D
"silabs,si5344" - Si5344 A/B/C/D
"silabs,si5345" - Si5345 A/B/C/D
- reg: i2c device address, usually 0x74
- #clock-cells: from common clock binding; shall be set to 2.
The first value is "0" for outputs, "1" for synthesizers.
......
......@@ -124,6 +124,8 @@ config MACH_MMP2_DT
select PINCTRL_SINGLE
select ARCH_HAS_RESET_CONTROLLER
select CPU_PJ4
select PM_GENERIC_DOMAINS if PM
select PM_GENERIC_DOMAINS_OF if PM && OF
help
Include support for Marvell MMP2 based platforms using
the device tree.
......
......@@ -341,6 +341,12 @@ config COMMON_CLK_MMP2
help
Support for Marvell MMP2 and MMP3 SoC clocks
config COMMON_CLK_MMP2_AUDIO
tristate "Clock driver for MMP2 Audio subsystem"
depends on COMMON_CLK_MMP2 || COMPILE_TEST
help
This driver supports clocks for Audio subsystem on MMP2 SoC.
config COMMON_CLK_BD718XX
tristate "Clock driver for 32K clk gates on ROHM PMICs"
depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828
......@@ -375,6 +381,7 @@ source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
source "drivers/clk/uniphier/Kconfig"
source "drivers/clk/x86/Kconfig"
source "drivers/clk/zynqmp/Kconfig"
endif
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Silicon Labs Si5341/Si5340 Clock generator
* Driver for Silicon Labs Si5340, Si5341, Si5342, Si5344 and Si5345
* Copyright (C) 2019 Topic Embedded Products
* Author: Mike Looijmans <mike.looijmans@topic.nl>
*
* The Si5341 has 10 outputs and 5 synthesizers.
* The Si5340 is a smaller version of the Si5341 with only 4 outputs.
* The Si5345 is similar to the Si5341, with the addition of fractional input
* dividers and automatic input selection.
* The Si5342 and Si5344 are smaller versions of the Si5345.
*/
#include <linux/clk.h>
......@@ -18,11 +24,17 @@
#define SI5341_NUM_INPUTS 4
#define SI5341_MAX_NUM_OUTPUTS 10
#define SI5340_MAX_NUM_OUTPUTS 4
#define SI5341_MAX_NUM_OUTPUTS 10
#define SI5342_MAX_NUM_OUTPUTS 2
#define SI5344_MAX_NUM_OUTPUTS 4
#define SI5345_MAX_NUM_OUTPUTS 10
#define SI5341_NUM_SYNTH 5
#define SI5340_NUM_SYNTH 4
#define SI5341_NUM_SYNTH 5
#define SI5342_NUM_SYNTH 2
#define SI5344_NUM_SYNTH 4
#define SI5345_NUM_SYNTH 5
/* Range of the synthesizer fractional divider */
#define SI5341_SYNTH_N_MIN 10
......@@ -65,6 +77,7 @@ struct clk_si5341 {
u64 freq_vco; /* 13500–14256 MHz */
u8 num_outputs;
u8 num_synth;
u16 chip_id;
};
#define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw)
......@@ -142,6 +155,7 @@ static const char * const si5341_input_clock_names[] = {
};
/* Output configuration registers 0..9 are not quite logically organized */
/* Also for si5345 */
static const u16 si5341_reg_output_offset[] = {
0x0108,
0x010D,
......@@ -155,6 +169,7 @@ static const u16 si5341_reg_output_offset[] = {
0x013A,
};
/* for si5340, si5342 and si5344 */
static const u16 si5340_reg_output_offset[] = {
0x0112,
0x0117,
......@@ -974,12 +989,32 @@ static int si5341_probe_chip_id(struct clk_si5341 *data)
data->reg_output_offset = si5341_reg_output_offset;
data->reg_rdiv_offset = si5341_reg_rdiv_offset;
break;
case 0x5342:
data->num_outputs = SI5342_MAX_NUM_OUTPUTS;
data->num_synth = SI5342_NUM_SYNTH;
data->reg_output_offset = si5340_reg_output_offset;
data->reg_rdiv_offset = si5340_reg_rdiv_offset;
break;
case 0x5344:
data->num_outputs = SI5344_MAX_NUM_OUTPUTS;
data->num_synth = SI5344_NUM_SYNTH;
data->reg_output_offset = si5340_reg_output_offset;
data->reg_rdiv_offset = si5340_reg_rdiv_offset;
break;
case 0x5345:
data->num_outputs = SI5345_MAX_NUM_OUTPUTS;
data->num_synth = SI5345_NUM_SYNTH;
data->reg_output_offset = si5341_reg_output_offset;
data->reg_rdiv_offset = si5341_reg_rdiv_offset;
break;
default:
dev_err(&data->i2c_client->dev, "Model '%x' not supported\n",
model);
return -EINVAL;
}
data->chip_id = model;
return 0;
}
......@@ -1054,6 +1089,11 @@ static const struct si5341_reg_default si5341_preamble[] = {
{ 0x0B4E, 0x1A },
};
static const struct si5341_reg_default si5345_preamble[] = {
{ 0x0B25, 0x00 },
{ 0x0540, 0x01 },
};
static int si5341_send_preamble(struct clk_si5341 *data)
{
int res;
......@@ -1068,8 +1108,14 @@ static int si5341_send_preamble(struct clk_si5341 *data)
res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xD8 : 0xC0);
if (res < 0)
return res;
res = si5341_write_multiple(data,
si5341_preamble, ARRAY_SIZE(si5341_preamble));
/* The si5342..si5345 require a different preamble */
if (data->chip_id > 0x5341)
res = si5341_write_multiple(data,
si5345_preamble, ARRAY_SIZE(si5345_preamble));
else
res = si5341_write_multiple(data,
si5341_preamble, ARRAY_SIZE(si5341_preamble));
if (res < 0)
return res;
......@@ -1095,6 +1141,13 @@ static int si5341_finalize_defaults(struct clk_si5341 *data)
if (res < 0)
return res;
/* The si5342..si5345 have an additional post-amble */
if (data->chip_id > 0x5341) {
res = regmap_write(data->regmap, 0x540, 0x0);
if (res < 0)
return res;
}
/* Datasheet does not explain these nameless registers */
res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xDB : 0xC3);
if (res < 0)
......@@ -1499,6 +1552,9 @@ static int si5341_probe(struct i2c_client *client,
static const struct i2c_device_id si5341_id[] = {
{ "si5340", 0 },
{ "si5341", 1 },
{ "si5342", 2 },
{ "si5344", 4 },
{ "si5345", 5 },
{ }
};
MODULE_DEVICE_TABLE(i2c, si5341_id);
......@@ -1506,6 +1562,9 @@ MODULE_DEVICE_TABLE(i2c, si5341_id);
static const struct of_device_id clk_si5341_of_match[] = {
{ .compatible = "silabs,si5340" },
{ .compatible = "silabs,si5341" },
{ .compatible = "silabs,si5342" },
{ .compatible = "silabs,si5344" },
{ .compatible = "silabs,si5345" },
{ }
};
MODULE_DEVICE_TABLE(of, clk_si5341_of_match);
......
......@@ -55,6 +55,16 @@ config INGENIC_CGU_X1000
If building for a X1000 SoC, you want to say Y here.
config INGENIC_CGU_X1830
bool "Ingenic X1830 CGU driver"
default MACH_X1830
select INGENIC_CGU_COMMON
help
Support the clocks provided by the CGU hardware on Ingenic X1830
and compatible SoCs.
If building for a X1830 SoC, you want to say Y here.
config INGENIC_TCU_CLK
bool "Ingenic JZ47xx TCU clocks driver"
default MACH_INGENIC
......
......@@ -5,4 +5,5 @@ obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o
obj-$(CONFIG_INGENIC_CGU_X1000) += x1000-cgu.o
obj-$(CONFIG_INGENIC_CGU_X1830) += x1830-cgu.o
obj-$(CONFIG_INGENIC_TCU_CLK) += tcu.o
......@@ -76,16 +76,13 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
const struct ingenic_cgu_pll_info *pll_info;
unsigned m, n, od_enc, od;
bool bypass;
unsigned long flags;
u32 ctl;
clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);
pll_info = &clk_info->pll;
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
spin_unlock_irqrestore(&cgu->lock, flags);
m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0);
m += pll_info->m_offset;
......@@ -93,6 +90,9 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0);
ctl = readl(cgu->base + pll_info->bypass_reg);
bypass = !pll_info->no_bypass_bit &&
!!(ctl & BIT(pll_info->bypass_bit));
......@@ -106,7 +106,8 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
BUG_ON(od == pll_info->od_max);
od++;
return div_u64((u64)parent_rate * m, n * od);
return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
n * od);
}
static unsigned long
......@@ -139,7 +140,8 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
if (pod)
*pod = od;
return div_u64((u64)parent_rate * m, n * od);
return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
n * od);
}
static inline const struct ingenic_cgu_clk_info *to_clk_info(
......@@ -212,9 +214,14 @@ static int ingenic_pll_enable(struct clk_hw *hw)
u32 ctl;
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
ctl = readl(cgu->base + pll_info->bypass_reg);
ctl &= ~BIT(pll_info->bypass_bit);
writel(ctl, cgu->base + pll_info->bypass_reg);
ctl = readl(cgu->base + pll_info->reg);
ctl |= BIT(pll_info->enable_bit);
writel(ctl, cgu->base + pll_info->reg);
......@@ -259,12 +266,9 @@ static int ingenic_pll_is_enabled(struct clk_hw *hw)
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long flags;
u32 ctl;
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
spin_unlock_irqrestore(&cgu->lock, flags);
return !!(ctl & BIT(pll_info->enable_bit));
}
......@@ -562,16 +566,12 @@ static int ingenic_clk_is_enabled(struct clk_hw *hw)
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
unsigned long flags;
int enabled = 1;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_GATE) {
spin_lock_irqsave(&cgu->lock, flags);
if (clk_info->type & CGU_CLK_GATE)
enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
spin_unlock_irqrestore(&cgu->lock, flags);
}
return enabled;
}
......
......@@ -17,6 +17,7 @@
/**
* struct ingenic_cgu_pll_info - information about a PLL
* @reg: the offset of the PLL's control register within the CGU
* @rate_multiplier: the multiplier needed by pll rate calculation
* @m_shift: the number of bits to shift the multiplier value by (ie. the
* index of the lowest bit of the multiplier value in the PLL's
* control register)
......@@ -37,6 +38,7 @@
* @od_encoding: a pointer to an array mapping post-VCO divider values to
* their encoded values in the PLL control register, or -1 for
* unsupported values
* @bypass_reg: the offset of the bypass control register within the CGU
* @bypass_bit: the index of the bypass bit in the PLL control register
* @enable_bit: the index of the enable bit in the PLL control register
* @stable_bit: the index of the stable bit in the PLL control register
......@@ -44,10 +46,12 @@
*/
struct ingenic_cgu_pll_info {
unsigned reg;
unsigned rate_multiplier;
const s8 *od_encoding;
u8 m_shift, m_bits, m_offset;
u8 n_shift, n_bits, n_offset;
u8 od_shift, od_bits, od_max;
unsigned bypass_reg;
u8 bypass_bit;
u8 enable_bit;
u8 stable_bit;
......
......@@ -9,7 +9,9 @@
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4725b-cgu.h>
#include "cgu.h"
#include "pm.h"
......@@ -54,6 +56,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
.rate_multiplier = 1,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
......@@ -65,6 +68,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 9,
.enable_bit = 8,
},
......
......@@ -10,7 +10,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4740-cgu.h>
#include "cgu.h"
#include "pm.h"
......@@ -69,6 +71,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
.parents = { JZ4740_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
.rate_multiplier = 1,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
......@@ -80,6 +83,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 9,
.enable_bit = 8,
},
......
......@@ -9,7 +9,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4770-cgu.h>
#include "cgu.h"
#include "pm.h"
......@@ -102,6 +104,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.parents = { JZ4770_CLK_EXT },
.pll = {
.reg = CGU_REG_CPPCR0,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
......@@ -112,6 +115,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR0,
.bypass_bit = 9,
.enable_bit = 8,
.stable_bit = 10,
......@@ -124,6 +128,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.parents = { JZ4770_CLK_EXT },
.pll = {
.reg = CGU_REG_CPPCR1,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
......@@ -134,9 +139,10 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR1,
.no_bypass_bit = true,
.enable_bit = 7,
.stable_bit = 6,
.no_bypass_bit = true,
},
},
......
......@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <dt-bindings/clock/jz4780-cgu.h>
#include "cgu.h"
#include "pm.h"
......@@ -266,6 +267,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
#define DEF_PLL(name) { \
.reg = CGU_REG_ ## name, \
.rate_multiplier = 1, \
.m_shift = 19, \
.m_bits = 13, \
.m_offset = 1, \
......@@ -277,6 +279,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
.od_max = 16, \
.od_encoding = pll_od_encoding, \
.stable_bit = 6, \
.bypass_reg = CGU_REG_ ## name, \
.bypass_bit = 1, \
.enable_bit = 0, \
}
......
......@@ -323,7 +323,7 @@ static const struct ingenic_soc_info x1000_soc_info = {
.has_tcu_clk = false,
};
static const struct of_device_id ingenic_tcu_of_match[] __initconst = {
static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initconst = {
{ .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
{ .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
{ .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, },
......
// SPDX-License-Identifier: GPL-2.0
/*
* X1000 SoC CGU driver
* Copyright (c) 2019 Zhou Yanjie <zhouyanjie@zoho.com>
* Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/x1000-cgu.h>
#include "cgu.h"
#include "pm.h"
......@@ -18,6 +21,9 @@
#define CGU_REG_CLKGR 0x20
#define CGU_REG_OPCR 0x24
#define CGU_REG_DDRCDR 0x2c
#define CGU_REG_USBPCR 0x3c
#define CGU_REG_USBPCR1 0x48
#define CGU_REG_USBCDR 0x50
#define CGU_REG_MACCDR 0x54
#define CGU_REG_I2SCDR 0x60
#define CGU_REG_LPCDR 0x64
......@@ -38,8 +44,47 @@
#define OPCR_SPENDN0 BIT(7)
#define OPCR_SPENDN1 BIT(6)
/* bits within the USBPCR register */
#define USBPCR_SIDDQ BIT(21)
#define USBPCR_OTG_DISABLE BIT(20)
static struct ingenic_cgu *cgu;
static int x1000_usb_phy_enable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
return 0;
}
static void x1000_usb_phy_disable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
}
static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
return (readl(reg_opcr) & OPCR_SPENDN0) &&
!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
}
static const struct clk_ops x1000_otg_phy_ops = {
.enable = x1000_usb_phy_enable,
.disable = x1000_usb_phy_disable,
.is_enabled = x1000_usb_phy_is_enabled,
};
static const s8 pll_od_encoding[8] = {
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
};
......@@ -58,6 +103,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_APLL,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
......@@ -68,6 +114,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_APLL,
.bypass_bit = 9,
.enable_bit = 8,
.stable_bit = 10,
......@@ -79,6 +126,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_MPLL,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
......@@ -89,12 +137,22 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_MPLL,
.bypass_bit = 6,
.enable_bit = 7,
.stable_bit = 0,
},
},
/* Custom (SoC-specific) OTG PHY */
[X1000_CLK_OTGPHY] = {
"otg_phy", CGU_CLK_CUSTOM,
.parents = { -1, -1, X1000_CLK_EXCLK, -1 },
.custom = { &x1000_otg_phy_ops },
},
/* Muxes & dividers */
[X1000_CLK_SCLKA] = {
......@@ -110,9 +168,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
[X1000_CLK_CPU] = {
"cpu", CGU_CLK_DIV,
"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
.gate = { CGU_REG_CLKGR, 30 },
},
[X1000_CLK_L2CACHE] = {
......@@ -141,9 +200,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
[X1000_CLK_PCLK] = {
"pclk", CGU_CLK_DIV,
"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
.gate = { CGU_REG_CLKGR, 28 },
},
[X1000_CLK_DDR] = {
......@@ -156,12 +216,20 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_MAC] = {
"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_MACCDR, 31, 1 },
.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 25 },
},
[X1000_CLK_LCD] = {
"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_LPCDR, 31, 1 },
.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
.gate = { CGU_REG_CLKGR, 23 },
},
[X1000_CLK_MSCMUX] = {
"msc_mux", CGU_CLK_MUX,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
......@@ -182,6 +250,15 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 5 },
},
[X1000_CLK_OTG] = {
"otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
.parents = { X1000_CLK_EXCLK, -1,
X1000_CLK_APLL, X1000_CLK_MPLL },
.mux = { CGU_REG_USBCDR, 30, 2 },
.div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 3 },
},
[X1000_CLK_SSIPLL] = {
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
......@@ -189,14 +266,32 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
},
[X1000_CLK_SSIPLL_DIV2] = {
"ssi_pll_div2", CGU_CLK_FIXDIV,
.parents = { X1000_CLK_SSIPLL },
.fixdiv = { 2 },
},
[X1000_CLK_SSIMUX] = {
"ssi_mux", CGU_CLK_MUX,
.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL, -1, -1 },
.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
.mux = { CGU_REG_SSICDR, 30, 1 },
},
/* Gate-only clocks */
[X1000_CLK_EMC] = {
"emc", CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 0 },
},
[X1000_CLK_EFUSE] = {
"efuse", CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 1 },
},
[X1000_CLK_SFC] = {
"sfc", CGU_CLK_GATE,
.parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
......@@ -239,12 +334,24 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 16 },
},
[X1000_CLK_TCU] = {
"tcu", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 18 },
},
[X1000_CLK_SSI] = {
"ssi", CGU_CLK_GATE,
.parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 19 },
},
[X1000_CLK_OST] = {
"ost", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 20 },
},
[X1000_CLK_PDMA] = {
"pdma", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
......@@ -271,4 +378,8 @@ static void __init x1000_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);
/*
* CGU has some children devices, this is useful for probing children devices
* in the case where the device node is compatible with "simple-mfd".
*/
CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);
// SPDX-License-Identifier: GPL-2.0
/*
* X1830 SoC CGU driver
* Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/x1830-cgu.h>
#include "cgu.h"
#include "pm.h"
/* CGU register offsets */
#define CGU_REG_CPCCR 0x00
#define CGU_REG_CPPCR 0x0c
#define CGU_REG_APLL 0x10
#define CGU_REG_MPLL 0x14
#define CGU_REG_CLKGR0 0x20
#define CGU_REG_OPCR 0x24
#define CGU_REG_CLKGR1 0x28
#define CGU_REG_DDRCDR 0x2c
#define CGU_REG_USBPCR 0x3c
#define CGU_REG_USBRDT 0x40
#define CGU_REG_USBVBFIL 0x44
#define CGU_REG_USBPCR1 0x48
#define CGU_REG_MACCDR 0x54
#define CGU_REG_EPLL 0x58
#define CGU_REG_I2SCDR 0x60
#define CGU_REG_LPCDR 0x64
#define CGU_REG_MSC0CDR 0x68
#define CGU_REG_I2SCDR1 0x70
#define CGU_REG_SSICDR 0x74
#define CGU_REG_CIMCDR 0x7c
#define CGU_REG_MSC1CDR 0xa4
#define CGU_REG_CMP_INTR 0xb0
#define CGU_REG_CMP_INTRE 0xb4
#define CGU_REG_DRCG 0xd0
#define CGU_REG_CPCSR 0xd4
#define CGU_REG_VPLL 0xe0
#define CGU_REG_MACPHYC 0xe8
/* bits within the OPCR register */
#define OPCR_GATE_USBPHYCLK BIT(23)
#define OPCR_SPENDN0 BIT(7)
#define OPCR_SPENDN1 BIT(6)
/* bits within the USBPCR register */
#define USBPCR_SIDDQ BIT(21)
#define USBPCR_OTG_DISABLE BIT(20)
static struct ingenic_cgu *cgu;
static int x1830_usb_phy_enable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel((readl(reg_opcr) | OPCR_SPENDN0) & ~OPCR_GATE_USBPHYCLK, reg_opcr);
writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
return 0;
}
static void x1830_usb_phy_disable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel((readl(reg_opcr) & ~OPCR_SPENDN0) | OPCR_GATE_USBPHYCLK, reg_opcr);
writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
}
static int x1830_usb_phy_is_enabled(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
return (readl(reg_opcr) & OPCR_SPENDN0) &&
!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
}
static const struct clk_ops x1830_otg_phy_ops = {
.enable = x1830_usb_phy_enable,
.disable = x1830_usb_phy_disable,
.is_enabled = x1830_usb_phy_is_enabled,
};
static const s8 pll_od_encoding[64] = {
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
-1, -1, -1, -1, -1, -1, -1, 0x4,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 0x5,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 0x6,
};
static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = {
/* External clocks */
[X1830_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
[X1830_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
/* PLLs */
[X1830_CLK_APLL] = {
"apll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_APLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 30,
.enable_bit = 0,
.stable_bit = 3,
},
},
[X1830_CLK_MPLL] = {
"mpll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_MPLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 28,
.enable_bit = 0,
.stable_bit = 3,
},
},
[X1830_CLK_EPLL] = {
"epll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_EPLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 24,
.enable_bit = 0,
.stable_bit = 3,
},
},
[X1830_CLK_VPLL] = {
"vpll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_VPLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 26,
.enable_bit = 0,
.stable_bit = 3,
},
},
/* Custom (SoC-specific) OTG PHY */
[X1830_CLK_OTGPHY] = {
"otg_phy", CGU_CLK_CUSTOM,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.custom = { &x1830_otg_phy_ops },
},
/* Muxes & dividers */
[X1830_CLK_SCLKA] = {
"sclk_a", CGU_CLK_MUX,
.parents = { -1, X1830_CLK_EXCLK, X1830_CLK_APLL, -1 },
.mux = { CGU_REG_CPCCR, 30, 2 },
},
[X1830_CLK_CPUMUX] = {
"cpu_mux", CGU_CLK_MUX,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_CPCCR, 28, 2 },
},
[X1830_CLK_CPU] = {
"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
.gate = { CGU_REG_CLKGR1, 15 },
},
[X1830_CLK_L2CACHE] = {
"l2cache", CGU_CLK_DIV,
.parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
},
[X1830_CLK_AHB0] = {
"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_CPCCR, 26, 2 },
.div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
},
[X1830_CLK_AHB2PMUX] = {
"ahb2_apb_mux", CGU_CLK_MUX,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_CPCCR, 24, 2 },
},
[X1830_CLK_AHB2] = {
"ahb2", CGU_CLK_DIV,
.parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
},
[X1830_CLK_PCLK] = {
"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
.gate = { CGU_REG_CLKGR1, 14 },
},
[X1830_CLK_DDR] = {
"ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_DDRCDR, 30, 2 },
.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
.gate = { CGU_REG_CLKGR0, 31 },
},
[X1830_CLK_MAC] = {
"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_MACCDR, 30, 2 },
.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR1, 4 },
},
[X1830_CLK_LCD] = {
"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_LPCDR, 30, 2 },
.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
.gate = { CGU_REG_CLKGR1, 9 },
},
[X1830_CLK_MSCMUX] = {
"msc_mux", CGU_CLK_MUX,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_MSC0CDR, 30, 2 },
},
[X1830_CLK_MSC0] = {
"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR0, 4 },
},
[X1830_CLK_MSC1] = {
"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR0, 5 },
},
[X1830_CLK_SSIPLL] = {
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_SSICDR, 30, 2 },
.div = { CGU_REG_SSICDR, 0, 1, 8, 28, 27, 26 },
},
[X1830_CLK_SSIPLL_DIV2] = {
"ssi_pll_div2", CGU_CLK_FIXDIV,
.parents = { X1830_CLK_SSIPLL },
.fixdiv = { 2 },
},
[X1830_CLK_SSIMUX] = {
"ssi_mux", CGU_CLK_MUX,
.parents = { X1830_CLK_EXCLK, X1830_CLK_SSIPLL_DIV2, -1, -1 },
.mux = { CGU_REG_SSICDR, 29, 1 },
},
/* Gate-only clocks */
[X1830_CLK_EMC] = {
"emc", CGU_CLK_GATE,
.parents = { X1830_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 0 },
},
[X1830_CLK_EFUSE] = {
"efuse", CGU_CLK_GATE,
.parents = { X1830_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 1 },
},
[X1830_CLK_OTG] = {
"otg", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 3 },
},
[X1830_CLK_SSI0] = {
"ssi0", CGU_CLK_GATE,
.parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 6 },
},
[X1830_CLK_SMB0] = {
"smb0", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 7 },
},
[X1830_CLK_SMB1] = {
"smb1", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 8 },
},
[X1830_CLK_SMB2] = {
"smb2", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 9 },
},
[X1830_CLK_UART0] = {
"uart0", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 14 },
},
[X1830_CLK_UART1] = {
"uart1", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 15 },
},
[X1830_CLK_SSI1] = {
"ssi1", CGU_CLK_GATE,
.parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 19 },
},
[X1830_CLK_SFC] = {
"sfc", CGU_CLK_GATE,
.parents = { X1830_CLK_SSIPLL, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 20 },
},
[X1830_CLK_PDMA] = {
"pdma", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 21 },
},
[X1830_CLK_TCU] = {
"tcu", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 30 },
},
[X1830_CLK_DTRNG] = {
"dtrng", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR1, 1 },
},
[X1830_CLK_OST] = {
"ost", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR1, 11 },
},
};
static void __init x1830_cgu_init(struct device_node *np)
{
int retval;
cgu = ingenic_cgu_new(x1830_cgu_clocks,
ARRAY_SIZE(x1830_cgu_clocks), np);
if (!cgu) {
pr_err("%s: failed to initialise CGU\n", __func__);
return;
}
retval = ingenic_cgu_register_clocks(cgu);
if (retval) {
pr_err("%s: failed to register CGU Clocks\n", __func__);
return;
}
ingenic_cgu_register_syscore_ops(cgu);
}
/*
* CGU has some children devices, this is useful for probing children devices
* in the case where the device node is compatible with "simple-mfd".
*/
CLK_OF_DECLARE_DRIVER(x1830_cgu, "ingenic,x1830-cgu", x1830_cgu_init);
......@@ -8,7 +8,8 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* MMP Audio Clock Controller driver
*
* Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <dt-bindings/clock/marvell,mmp2-audio.h>
/* Audio Controller Registers */
#define SSPA_AUD_CTRL 0x04
#define SSPA_AUD_PLL_CTRL0 0x08
#define SSPA_AUD_PLL_CTRL1 0x0c
/* SSPA Audio Control Register */
#define SSPA_AUD_CTRL_SYSCLK_SHIFT 0
#define SSPA_AUD_CTRL_SYSCLK_DIV_SHIFT 1
#define SSPA_AUD_CTRL_SSPA0_MUX_SHIFT 7
#define SSPA_AUD_CTRL_SSPA0_SHIFT 8
#define SSPA_AUD_CTRL_SSPA0_DIV_SHIFT 9
#define SSPA_AUD_CTRL_SSPA1_SHIFT 16
#define SSPA_AUD_CTRL_SSPA1_DIV_SHIFT 17
#define SSPA_AUD_CTRL_SSPA1_MUX_SHIFT 23
#define SSPA_AUD_CTRL_DIV_MASK 0x7e
/* SSPA Audio PLL Control 0 Register */
#define SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK (0x7 << 28)
#define SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(x) ((x) << 28)
#define SSPA_AUD_PLL_CTRL0_FRACT_MASK (0xfffff << 8)
#define SSPA_AUD_PLL_CTRL0_FRACT(x) ((x) << 8)
#define SSPA_AUD_PLL_CTRL0_ENA_DITHER (1 << 7)
#define SSPA_AUD_PLL_CTRL0_ICP_2UA (0 << 5)
#define SSPA_AUD_PLL_CTRL0_ICP_5UA (1 << 5)
#define SSPA_AUD_PLL_CTRL0_ICP_7UA (2 << 5)
#define SSPA_AUD_PLL_CTRL0_ICP_10UA (3 << 5)
#define SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK (0x3 << 3)
#define SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(x) ((x) << 3)
#define SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK (0x1 << 2)
#define SSPA_AUD_PLL_CTRL0_DIV_MCLK(x) ((x) << 2)
#define SSPA_AUD_PLL_CTRL0_PD_OVPROT_DIS (1 << 1)
#define SSPA_AUD_PLL_CTRL0_PU (1 << 0)
/* SSPA Audio PLL Control 1 Register */
#define SSPA_AUD_PLL_CTRL1_SEL_FAST_CLK (1 << 24)
#define SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK (1 << 11)
#define SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL (1 << 11)
#define SSPA_AUD_PLL_CTRL1_CLK_SEL_VCXO (0 << 11)
#define SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK (0x7ff << 0)
#define SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(x) ((x) << 0)
struct mmp2_audio_clk {
void __iomem *mmio_base;
struct clk_hw audio_pll_hw;
struct clk_mux sspa_mux;
struct clk_mux sspa1_mux;
struct clk_divider sysclk_div;
struct clk_divider sspa0_div;
struct clk_divider sspa1_div;
struct clk_gate sysclk_gate;
struct clk_gate sspa0_gate;
struct clk_gate sspa1_gate;
u32 aud_ctrl;
u32 aud_pll_ctrl0;
u32 aud_pll_ctrl1;
spinlock_t lock;
/* Must be last */
struct clk_hw_onecell_data clk_data;
};
static const struct {
unsigned long parent_rate;
unsigned long freq_vco;
unsigned char mclk;
unsigned char fbcclk;
unsigned short fract;
} predivs[] = {
{ 26000000, 135475200, 0, 0, 0x8a18 },
{ 26000000, 147456000, 0, 1, 0x0da1 },
{ 38400000, 135475200, 1, 2, 0x8208 },
{ 38400000, 147456000, 1, 3, 0xaaaa },
};
static const struct {
unsigned char divisor;
unsigned char modulo;
unsigned char pattern;
} postdivs[] = {
{ 1, 3, 0, },
{ 2, 5, 0, },
{ 4, 0, 0, },
{ 6, 1, 1, },
{ 8, 1, 0, },
{ 9, 1, 2, },
{ 12, 2, 1, },
{ 16, 2, 0, },
{ 18, 2, 2, },
{ 24, 4, 1, },
{ 36, 4, 2, },
{ 48, 6, 1, },
{ 72, 6, 2, },
};
static unsigned long audio_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
unsigned int prediv;
unsigned int postdiv;
u32 aud_pll_ctrl0;
u32 aud_pll_ctrl1;
aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
aud_pll_ctrl0 &= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK |
SSPA_AUD_PLL_CTRL0_FRACT_MASK |
SSPA_AUD_PLL_CTRL0_ENA_DITHER |
SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK |
SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK |
SSPA_AUD_PLL_CTRL0_PU;
aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
aud_pll_ctrl1 &= SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK |
SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
unsigned long freq;
u32 val;
val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
val |= SSPA_AUD_PLL_CTRL0_PU;
val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);
if (val != aud_pll_ctrl0)
continue;
val = SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL;
val |= SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(postdivs[postdiv].pattern);
if (val != aud_pll_ctrl1)
continue;
freq = predivs[prediv].freq_vco;
freq /= postdivs[postdiv].divisor;
return freq;
}
}
return 0;
}
static long audio_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned int prediv;
unsigned int postdiv;
long rounded = 0;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != *parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
long freq = predivs[prediv].freq_vco;
freq /= postdivs[postdiv].divisor;
if (freq == rate)
return rate;
if (freq < rate)
continue;
if (rounded && freq > rounded)
continue;
rounded = freq;
}
}
return rounded;
}
static int audio_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
unsigned int prediv;
unsigned int postdiv;
unsigned long val;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
if (rate * postdivs[postdiv].divisor != predivs[prediv].freq_vco)
continue;
val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
val |= SSPA_AUD_PLL_CTRL0_PU;
val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);
writel(val, priv->mmio_base + SSPA_AUD_PLL_CTRL0);
val = SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL;
val |= SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(postdivs[postdiv].pattern);
writel(val, priv->mmio_base + SSPA_AUD_PLL_CTRL1);
return 0;
}
}
return -ERANGE;
}
static const struct clk_ops audio_pll_ops = {
.recalc_rate = audio_pll_recalc_rate,
.round_rate = audio_pll_round_rate,
.set_rate = audio_pll_set_rate,
};
static int register_clocks(struct mmp2_audio_clk *priv, struct device *dev)
{
const struct clk_parent_data sspa_mux_parents[] = {
{ .hw = &priv->audio_pll_hw },
{ .fw_name = "i2s0" },
};
const struct clk_parent_data sspa1_mux_parents[] = {
{ .hw = &priv->audio_pll_hw },
{ .fw_name = "i2s1" },
};
int ret;
priv->audio_pll_hw.init = CLK_HW_INIT_FW_NAME("audio_pll",
"vctcxo", &audio_pll_ops,
CLK_SET_RATE_PARENT);
ret = devm_clk_hw_register(dev, &priv->audio_pll_hw);
if (ret)
return ret;
priv->sspa_mux.hw.init = CLK_HW_INIT_PARENTS_DATA("sspa_mux",
sspa_mux_parents, &clk_mux_ops,
CLK_SET_RATE_PARENT);
priv->sspa_mux.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa_mux.mask = 1;
priv->sspa_mux.shift = SSPA_AUD_CTRL_SSPA0_MUX_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa_mux.hw);
if (ret)
return ret;
priv->sysclk_div.hw.init = CLK_HW_INIT_HW("sys_div",
&priv->sspa_mux.hw, &clk_divider_ops,
CLK_SET_RATE_PARENT);
priv->sysclk_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sysclk_div.shift = SSPA_AUD_CTRL_SYSCLK_DIV_SHIFT;
priv->sysclk_div.width = 6;
priv->sysclk_div.flags = CLK_DIVIDER_ONE_BASED;
priv->sysclk_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
priv->sysclk_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
ret = devm_clk_hw_register(dev, &priv->sysclk_div.hw);
if (ret)
return ret;
priv->sysclk_gate.hw.init = CLK_HW_INIT_HW("sys_clk",
&priv->sysclk_div.hw, &clk_gate_ops,
CLK_SET_RATE_PARENT);
priv->sysclk_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sysclk_gate.bit_idx = SSPA_AUD_CTRL_SYSCLK_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sysclk_gate.hw);
if (ret)
return ret;
priv->sspa0_div.hw.init = CLK_HW_INIT_HW("sspa0_div",
&priv->sspa_mux.hw, &clk_divider_ops, 0);
priv->sspa0_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa0_div.shift = SSPA_AUD_CTRL_SSPA0_DIV_SHIFT;
priv->sspa0_div.width = 6;
priv->sspa0_div.flags = CLK_DIVIDER_ONE_BASED;
priv->sspa0_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
priv->sspa0_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
ret = devm_clk_hw_register(dev, &priv->sspa0_div.hw);
if (ret)
return ret;
priv->sspa0_gate.hw.init = CLK_HW_INIT_HW("sspa0_clk",
&priv->sspa0_div.hw, &clk_gate_ops,
CLK_SET_RATE_PARENT);
priv->sspa0_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa0_gate.bit_idx = SSPA_AUD_CTRL_SSPA0_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa0_gate.hw);
if (ret)
return ret;
priv->sspa1_mux.hw.init = CLK_HW_INIT_PARENTS_DATA("sspa1_mux",
sspa1_mux_parents, &clk_mux_ops,
CLK_SET_RATE_PARENT);
priv->sspa1_mux.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa1_mux.mask = 1;
priv->sspa1_mux.shift = SSPA_AUD_CTRL_SSPA1_MUX_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa1_mux.hw);
if (ret)
return ret;
priv->sspa1_div.hw.init = CLK_HW_INIT_HW("sspa1_div",
&priv->sspa1_mux.hw, &clk_divider_ops, 0);
priv->sspa1_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa1_div.shift = SSPA_AUD_CTRL_SSPA1_DIV_SHIFT;
priv->sspa1_div.width = 6;
priv->sspa1_div.flags = CLK_DIVIDER_ONE_BASED;
priv->sspa1_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
priv->sspa1_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
ret = devm_clk_hw_register(dev, &priv->sspa1_div.hw);
if (ret)
return ret;
priv->sspa1_gate.hw.init = CLK_HW_INIT_HW("sspa1_clk",
&priv->sspa1_div.hw, &clk_gate_ops,
CLK_SET_RATE_PARENT);
priv->sspa1_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa1_gate.bit_idx = SSPA_AUD_CTRL_SSPA1_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa1_gate.hw);
if (ret)
return ret;
priv->clk_data.hws[MMP2_CLK_AUDIO_SYSCLK] = &priv->sysclk_gate.hw;
priv->clk_data.hws[MMP2_CLK_AUDIO_SSPA0] = &priv->sspa0_gate.hw;
priv->clk_data.hws[MMP2_CLK_AUDIO_SSPA1] = &priv->sspa1_gate.hw;
priv->clk_data.num = MMP2_CLK_AUDIO_NR_CLKS;
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
&priv->clk_data);
}
static int mmp2_audio_clk_probe(struct platform_device *pdev)
{
struct mmp2_audio_clk *priv;
int ret;
priv = devm_kzalloc(&pdev->dev,
struct_size(priv, clk_data.hws,
MMP2_CLK_AUDIO_NR_CLKS),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
platform_set_drvdata(pdev, priv);
priv->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->mmio_base))
return PTR_ERR(priv->mmio_base);
pm_runtime_enable(&pdev->dev);
ret = pm_clk_create(&pdev->dev);
if (ret)
goto disable_pm_runtime;
ret = pm_clk_add(&pdev->dev, "audio");
if (ret)
goto destroy_pm_clk;
ret = register_clocks(priv, &pdev->dev);
if (ret)
goto destroy_pm_clk;
return 0;
destroy_pm_clk:
pm_clk_destroy(&pdev->dev);
disable_pm_runtime:
pm_runtime_disable(&pdev->dev);
return ret;
}
static int mmp2_audio_clk_remove(struct platform_device *pdev)
{
pm_clk_destroy(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
static int __maybe_unused mmp2_audio_clk_suspend(struct device *dev)
{
struct mmp2_audio_clk *priv = dev_get_drvdata(dev);
priv->aud_ctrl = readl(priv->mmio_base + SSPA_AUD_CTRL);
priv->aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
priv->aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
pm_clk_suspend(dev);
return 0;
}
static int __maybe_unused mmp2_audio_clk_resume(struct device *dev)
{
struct mmp2_audio_clk *priv = dev_get_drvdata(dev);
pm_clk_resume(dev);
writel(priv->aud_ctrl, priv->mmio_base + SSPA_AUD_CTRL);
writel(priv->aud_pll_ctrl0, priv->mmio_base + SSPA_AUD_PLL_CTRL0);
writel(priv->aud_pll_ctrl1, priv->mmio_base + SSPA_AUD_PLL_CTRL1);
return 0;
}
static const struct dev_pm_ops mmp2_audio_clk_pm_ops = {
SET_RUNTIME_PM_OPS(mmp2_audio_clk_suspend, mmp2_audio_clk_resume, NULL)
};
static const struct of_device_id mmp2_audio_clk_of_match[] = {
{ .compatible = "marvell,mmp2-audio-clock" },
{}
};
MODULE_DEVICE_TABLE(of, mmp2_audio_clk_of_match);
static struct platform_driver mmp2_audio_clk_driver = {
.driver = {
.name = "mmp2-audio-clock",
.of_match_table = of_match_ptr(mmp2_audio_clk_of_match),
.pm = &mmp2_audio_clk_pm_ops,
},
.probe = mmp2_audio_clk_probe,
.remove = mmp2_audio_clk_remove,
};
module_platform_driver(mmp2_audio_clk_driver);
MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
MODULE_DESCRIPTION("Clock driver for MMP2 Audio subsystem");
MODULE_LICENSE("GPL");
......@@ -28,13 +28,15 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
unsigned long rate = 0, prev_rate;
u64 rate = 0, prev_rate;
int i;
for (i = 0; i < factor->ftbl_cnt; i++) {
prev_rate = rate;
rate = (((*prate / 10000) * factor->ftbl[i].den) /
(factor->ftbl[i].num * factor->masks->factor)) * 10000;
rate = *prate;
rate *= factor->ftbl[i].den;
do_div(rate, factor->ftbl[i].num * factor->masks->factor);
if (rate > drate)
break;
}
......@@ -54,6 +56,7 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
unsigned int val, num, den;
u64 rate;
val = readl_relaxed(factor->base);
......@@ -66,8 +69,11 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
if (!den)
return 0;
return (((parent_rate / 10000) * den) /
(num * factor->masks->factor)) * 10000;
rate = parent_rate;
rate *= den;
do_div(rate, num * factor->masks->factor);
return rate;
}
/* Configures new clock rate*/
......@@ -78,12 +84,14 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
struct mmp_clk_factor_masks *masks = factor->masks;
int i;
unsigned long val;
unsigned long rate = 0;
unsigned long flags = 0;
u64 rate = 0;
for (i = 0; i < factor->ftbl_cnt; i++) {
rate = (((prate / 10000) * factor->ftbl[i].den) /
(factor->ftbl[i].num * factor->masks->factor)) * 10000;
rate = prate;
rate *= factor->ftbl[i].den;
do_div(rate, factor->ftbl[i].num * factor->masks->factor);
if (rate > drate)
break;
}
......@@ -140,7 +148,10 @@ static int clk_factor_init(struct clk_hw *hw)
val &= ~(masks->den_mask << masks->den_shift);
val |= (factor->ftbl[0].den & masks->den_mask) <<
masks->den_shift;
}
if (!(val & masks->enable_mask) || i >= factor->ftbl_cnt) {
val |= masks->enable_mask;
writel(val, factor->base);
}
......
......@@ -17,8 +17,10 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/of_address.h>
#include <linux/clk.h>
#include <dt-bindings/clock/marvell,mmp2.h>
#include <dt-bindings/power/marvell,mmp2.h>
#include "clk.h"
#include "reset.h"
......@@ -45,6 +47,10 @@
#define APBC_SSP1 0x54
#define APBC_SSP2 0x58
#define APBC_SSP3 0x5c
#define APBC_THERMAL0 0x90
#define APBC_THERMAL1 0x98
#define APBC_THERMAL2 0x9c
#define APBC_THERMAL3 0xa0
#define APMU_SDH0 0x54
#define APMU_SDH1 0x58
#define APMU_SDH2 0xe8
......@@ -55,18 +61,19 @@
#define APMU_DISP1 0x110
#define APMU_CCIC0 0x50
#define APMU_CCIC1 0xf4
#define APBC_THERMAL0 0x90
#define APBC_THERMAL1 0x98
#define APBC_THERMAL2 0x9c
#define APBC_THERMAL3 0xa0
#define APMU_USBHSIC0 0xf8
#define APMU_USBHSIC1 0xfc
#define APMU_GPU 0xcc
#define APMU_AUDIO 0x10c
#define APMU_CAMERA 0x1fc
#define MPMU_FCCR 0x8
#define MPMU_POSR 0x10
#define MPMU_UART_PLL 0x14
#define MPMU_PLL2_CR 0x34
#define MPMU_I2S0_PLL 0x40
#define MPMU_I2S1_PLL 0x44
#define MPMU_ACGR 0x1024
/* MMP3 specific below */
#define MPMU_PLL3_CR 0x50
#define MPMU_PLL3_CTRL1 0x58
......@@ -82,6 +89,8 @@ enum mmp2_clk_model {
struct mmp2_clk_unit {
struct mmp_clk_unit unit;
enum mmp2_clk_model model;
struct genpd_onecell_data pd_data;
struct generic_pm_domain *pm_domains[MMP2_NR_POWER_DOMAINS];
void __iomem *mpmu_base;
void __iomem *apmu_base;
void __iomem *apbc_base;
......@@ -91,6 +100,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{MMP2_CLK_CLK32, "clk32", NULL, 0, 32768},
{MMP2_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000},
{MMP2_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000},
{0, "i2s_pll", NULL, 0, 99666667},
};
static struct mmp_param_pll_clk pll_clks[] = {
......@@ -139,7 +149,35 @@ static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 3521, .den = 689}, /*19.23MHZ */
};
static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
static struct mmp_clk_factor_masks i2s_factor_masks = {
.factor = 2,
.num_mask = 0x7fff,
.den_mask = 0x1fff,
.num_shift = 0,
.den_shift = 15,
.enable_mask = 0xd0000000,
};
static struct mmp_clk_factor_tbl i2s_factor_tbl[] = {
{.num = 24868, .den = 511}, /* 2.0480 MHz */
{.num = 28003, .den = 793}, /* 2.8224 MHz */
{.num = 24941, .den = 1025}, /* 4.0960 MHz */
{.num = 28003, .den = 1586}, /* 5.6448 MHz */
{.num = 31158, .den = 2561}, /* 8.1920 MHz */
{.num = 16288, .den = 1845}, /* 11.2896 MHz */
{.num = 20772, .den = 2561}, /* 12.2880 MHz */
{.num = 8144, .den = 1845}, /* 22.5792 MHz */
{.num = 10386, .den = 2561}, /* 24.5760 MHz */
};
static DEFINE_SPINLOCK(acgr_lock);
static struct mmp_param_gate_clk mpmu_gate_clks[] = {
{MMP2_CLK_I2S0, "i2s0_clk", "i2s0_pll", CLK_SET_RATE_PARENT, MPMU_ACGR, 0x200000, 0x200000, 0x0, 0, &acgr_lock},
{MMP2_CLK_I2S1, "i2s1_clk", "i2s1_pll", CLK_SET_RATE_PARENT, MPMU_ACGR, 0x100000, 0x100000, 0x0, 0, &acgr_lock},
};
static void mmp2_main_clk_init(struct mmp2_clk_unit *pxa_unit)
{
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
......@@ -166,6 +204,20 @@ static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
&uart_factor_masks, uart_factor_tbl,
ARRAY_SIZE(uart_factor_tbl), NULL);
mmp_clk_add(unit, MMP2_CLK_UART_PLL, clk);
mmp_clk_register_factor("i2s0_pll", "pll1_4",
CLK_SET_RATE_PARENT,
pxa_unit->mpmu_base + MPMU_I2S0_PLL,
&i2s_factor_masks, i2s_factor_tbl,
ARRAY_SIZE(i2s_factor_tbl), NULL);
mmp_clk_register_factor("i2s1_pll", "pll1_4",
CLK_SET_RATE_PARENT,
pxa_unit->mpmu_base + MPMU_I2S1_PLL,
&i2s_factor_masks, i2s_factor_tbl,
ARRAY_SIZE(i2s_factor_tbl), NULL);
mmp_register_gate_clks(unit, mpmu_gate_clks, pxa_unit->mpmu_base,
ARRAY_SIZE(mpmu_gate_clks));
}
static DEFINE_SPINLOCK(uart0_lock);
......@@ -271,6 +323,8 @@ static u32 mmp2_gpu_bus_parent_table[] = { 0x0000, 0x0020, 0x0030,
static const char * const mmp3_gpu_bus_parent_names[] = {"pll1_4", "pll1_6", "pll1_2", "pll2_2"};
static const char * const mmp3_gpu_gc_parent_names[] = {"pll1", "pll2", "pll1_p", "pll2_p"};
static DEFINE_SPINLOCK(audio_lock);
static struct mmp_clk_mix_config ccic0_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(4, 17, 2, 6, 32),
};
......@@ -326,6 +380,7 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
{MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
{MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
{MMP2_CLK_GPU_BUS, "gpu_bus_clk", "gpu_bus_mux", CLK_SET_RATE_PARENT, APMU_GPU, 0xa, 0xa, 0x0, MMP_CLK_GATE_NEED_DELAY, &gpu_lock},
{MMP2_CLK_AUDIO, "audio_clk", "audio_mix_clk", CLK_SET_RATE_PARENT, APMU_AUDIO, 0x12, 0x12, 0x0, 0, &audio_lock},
};
static struct mmp_param_gate_clk mmp2_apmu_gate_clks[] = {
......@@ -423,6 +478,41 @@ static void mmp2_clk_reset_init(struct device_node *np,
mmp_clk_reset_register(np, cells, nr_resets);
}
static void mmp2_pm_domain_init(struct device_node *np,
struct mmp2_clk_unit *pxa_unit)
{
if (pxa_unit->model == CLK_MODEL_MMP3) {
pxa_unit->pm_domains[MMP2_POWER_DOMAIN_GPU]
= mmp_pm_domain_register("gpu",
pxa_unit->apmu_base + APMU_GPU,
0x0600, 0x40003, 0x18000c, 0, &gpu_lock);
} else {
pxa_unit->pm_domains[MMP2_POWER_DOMAIN_GPU]
= mmp_pm_domain_register("gpu",
pxa_unit->apmu_base + APMU_GPU,
0x8600, 0x00003, 0x00000c,
MMP_PM_DOMAIN_NO_DISABLE, &gpu_lock);
}
pxa_unit->pd_data.num_domains++;
pxa_unit->pm_domains[MMP2_POWER_DOMAIN_AUDIO]
= mmp_pm_domain_register("audio",
pxa_unit->apmu_base + APMU_AUDIO,
0x600, 0x2, 0, 0, &audio_lock);
pxa_unit->pd_data.num_domains++;
if (pxa_unit->model == CLK_MODEL_MMP3) {
pxa_unit->pm_domains[MMP3_POWER_DOMAIN_CAMERA]
= mmp_pm_domain_register("camera",
pxa_unit->apmu_base + APMU_CAMERA,
0x600, 0, 0, 0, NULL);
pxa_unit->pd_data.num_domains++;
}
pxa_unit->pd_data.domains = pxa_unit->pm_domains;
of_genpd_add_provider_onecell(np, &pxa_unit->pd_data);
}
static void __init mmp2_clk_init(struct device_node *np)
{
struct mmp2_clk_unit *pxa_unit;
......@@ -454,9 +544,11 @@ static void __init mmp2_clk_init(struct device_node *np)
goto unmap_apmu_region;
}
mmp2_pm_domain_init(np, pxa_unit);
mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
mmp2_pll_init(pxa_unit);
mmp2_main_clk_init(pxa_unit);
mmp2_apb_periph_clk_init(pxa_unit);
......
......@@ -3,6 +3,7 @@
#define __MACH_MMP_CLK_H
#include <linux/clk-provider.h>
#include <linux/pm_domain.h>
#include <linux/clkdev.h>
#define APBC_NO_BUS_CTRL BIT(0)
......@@ -16,6 +17,7 @@ struct mmp_clk_factor_masks {
unsigned int den_mask;
unsigned int num_shift;
unsigned int den_shift;
unsigned int enable_mask;
};
struct mmp_clk_factor_tbl {
......@@ -258,4 +260,13 @@ void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
int nr_clks);
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
struct clk *clk);
/* Power islands */
#define MMP_PM_DOMAIN_NO_DISABLE BIT(0)
struct generic_pm_domain *mmp_pm_domain_register(const char *name,
void __iomem *reg,
u32 power_on, u32 reset, u32 clock_enable,
unsigned int flags, spinlock_t *lock);
#endif
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* MMP PMU power island support
*
* Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/io.h>
#include "clk.h"
#define to_mmp_pm_domain(genpd) container_of(genpd, struct mmp_pm_domain, genpd)
struct mmp_pm_domain {
struct generic_pm_domain genpd;
void __iomem *reg;
spinlock_t *lock;
u32 power_on;
u32 reset;
u32 clock_enable;
unsigned int flags;
};
static int mmp_pm_domain_power_on(struct generic_pm_domain *genpd)
{
struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);
unsigned long flags = 0;
u32 val;
if (pm_domain->lock)
spin_lock_irqsave(pm_domain->lock, flags);
val = readl(pm_domain->reg);
/* Turn on the power island */
val |= pm_domain->power_on;
writel(val, pm_domain->reg);
/* Disable isolation */
val |= 0x100;
writel(val, pm_domain->reg);
/* Some blocks need to be reset after a power up */
if (pm_domain->reset || pm_domain->clock_enable) {
u32 after_power_on = val;
val &= ~pm_domain->reset;
writel(val, pm_domain->reg);
val |= pm_domain->clock_enable;
writel(val, pm_domain->reg);
val |= pm_domain->reset;
writel(val, pm_domain->reg);
writel(after_power_on, pm_domain->reg);
}
if (pm_domain->lock)
spin_unlock_irqrestore(pm_domain->lock, flags);
return 0;
}
static int mmp_pm_domain_power_off(struct generic_pm_domain *genpd)
{
struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);
unsigned long flags = 0;
u32 val;
if (pm_domain->flags & MMP_PM_DOMAIN_NO_DISABLE)
return 0;
if (pm_domain->lock)
spin_lock_irqsave(pm_domain->lock, flags);
/* Turn off and isolate the the power island. */
val = readl(pm_domain->reg);
val &= ~pm_domain->power_on;
val &= ~0x100;
writel(val, pm_domain->reg);
if (pm_domain->lock)
spin_unlock_irqrestore(pm_domain->lock, flags);
return 0;
}
struct generic_pm_domain *mmp_pm_domain_register(const char *name,
void __iomem *reg,
u32 power_on, u32 reset, u32 clock_enable,
unsigned int flags, spinlock_t *lock)
{
struct mmp_pm_domain *pm_domain;
pm_domain = kzalloc(sizeof(*pm_domain), GFP_KERNEL);
if (!pm_domain)
return ERR_PTR(-ENOMEM);
pm_domain->reg = reg;
pm_domain->power_on = power_on;
pm_domain->reset = reset;
pm_domain->clock_enable = clock_enable;
pm_domain->flags = flags;
pm_domain->lock = lock;
pm_genpd_init(&pm_domain->genpd, NULL, true);
pm_domain->genpd.name = name;
pm_domain->genpd.power_on = mmp_pm_domain_power_on;
pm_domain->genpd.power_off = mmp_pm_domain_power_off;
return &pm_domain->genpd;
}
......@@ -142,6 +142,14 @@ config MSM_GCC_8916
Say Y if you want to use devices such as UART, SPI i2c, USB,
SD/eMMC, display, graphics, camera etc.
config MSM_GCC_8939
tristate "MSM8939 Global Clock Controller"
select QCOM_GDSC
help
Support for the global clock controller on msm8939 devices.
Say Y if you want to use devices such as UART, SPI i2c, USB,
SD/eMMC, display, graphics, camera etc.
config MSM_GCC_8960
tristate "APQ8064/MSM8960 Global Clock Controller"
help
......
......@@ -28,6 +28,7 @@ obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
obj-$(CONFIG_MSM_GCC_8939) += gcc-msm8939.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
......
......@@ -260,7 +260,7 @@ static struct clk_pll gpll0 = {
.l_reg = 0x21004,
.m_reg = 0x21008,
.n_reg = 0x2100c,
.config_reg = 0x21014,
.config_reg = 0x21010,
.mode_reg = 0x21000,
.status_reg = 0x2101c,
.status_bit = 17,
......@@ -287,7 +287,7 @@ static struct clk_pll gpll1 = {
.l_reg = 0x20004,
.m_reg = 0x20008,
.n_reg = 0x2000c,
.config_reg = 0x20014,
.config_reg = 0x20010,
.mode_reg = 0x20000,
.status_reg = 0x2001c,
.status_bit = 17,
......@@ -314,7 +314,7 @@ static struct clk_pll gpll2 = {
.l_reg = 0x4a004,
.m_reg = 0x4a008,
.n_reg = 0x4a00c,
.config_reg = 0x4a014,
.config_reg = 0x4a010,
.mode_reg = 0x4a000,
.status_reg = 0x4a01c,
.status_bit = 17,
......@@ -341,7 +341,7 @@ static struct clk_pll bimc_pll = {
.l_reg = 0x23004,
.m_reg = 0x23008,
.n_reg = 0x2300c,
.config_reg = 0x23014,
.config_reg = 0x23010,
.mode_reg = 0x23000,
.status_reg = 0x2301c,
.status_bit = 17,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1110,6 +1110,27 @@ static struct clk_rcg2 ufs_axi_clk_src = {
},
};
static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
F(37500000, P_GPLL0_OUT_MAIN, 16, 0, 0),
F(75000000, P_GPLL0_OUT_MAIN, 8, 0, 0),
F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
{ }
};
static struct clk_rcg2 ufs_unipro_core_clk_src = {
.cmd_rcgr = 0x76028,
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_ufs_unipro_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_unipro_core_clk_src",
.parent_names = gcc_parent_names_0,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
};
static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
......@@ -2549,6 +2570,11 @@ static struct clk_branch gcc_ufs_unipro_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_unipro_core_clk",
.parent_names = (const char *[]){
"ufs_unipro_core_clk_src",
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
......@@ -2904,6 +2930,7 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
[SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
[TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
[UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
[UFS_UNIPRO_CORE_CLK_SRC] = &ufs_unipro_core_clk_src.clkr,
[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
[USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
[USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
......
......@@ -390,6 +390,7 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625),
F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75),
F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25),
F(51200000, P_GPLL6_OUT_MAIN, 7.5, 0, 0),
F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75),
F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15),
......@@ -405,8 +406,8 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
.name = "gcc_qupv3_wrap0_s0_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -414,15 +415,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
.cmd_rcgr = 0x17034,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
.name = "gcc_qupv3_wrap0_s1_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -430,15 +431,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
.cmd_rcgr = 0x17164,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
.name = "gcc_qupv3_wrap0_s2_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -446,15 +447,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
.cmd_rcgr = 0x17294,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
.name = "gcc_qupv3_wrap0_s3_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -462,15 +463,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
.cmd_rcgr = 0x173c4,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
.name = "gcc_qupv3_wrap0_s4_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -478,15 +479,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
.cmd_rcgr = 0x174f4,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
.name = "gcc_qupv3_wrap0_s5_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -494,15 +495,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
.cmd_rcgr = 0x17624,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = {
.name = "gcc_qupv3_wrap1_s0_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -510,15 +511,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
.cmd_rcgr = 0x18018,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = {
.name = "gcc_qupv3_wrap1_s1_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -526,15 +527,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
.cmd_rcgr = 0x18148,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = {
.name = "gcc_qupv3_wrap1_s2_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -542,15 +543,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
.cmd_rcgr = 0x18278,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = {
.name = "gcc_qupv3_wrap1_s3_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -558,15 +559,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
.cmd_rcgr = 0x183a8,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = {
.name = "gcc_qupv3_wrap1_s4_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -574,15 +575,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
.cmd_rcgr = 0x184d8,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = {
.name = "gcc_qupv3_wrap1_s5_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
......@@ -590,7 +591,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
.cmd_rcgr = 0x18608,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init,
};
......@@ -816,6 +817,26 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
},
};
static const struct freq_tbl ftbl_gcc_sec_ctrl_clk_src[] = {
F(4800000, P_BI_TCXO, 4, 0, 0),
F(19200000, P_BI_TCXO, 1, 0, 0),
{ }
};
static struct clk_rcg2 gcc_sec_ctrl_clk_src = {
.cmd_rcgr = 0x3d030,
.mnd_width = 0,
.hid_width = 5,
.parent_map = gcc_parent_map_3,
.freq_tbl = ftbl_gcc_sec_ctrl_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_sec_ctrl_clk_src",
.parent_data = gcc_parent_data_3,
.num_parents = ARRAY_SIZE(gcc_parent_data_3),
.ops = &clk_rcg2_ops,
},
};
static struct clk_branch gcc_aggre_ufs_phy_axi_clk = {
.halt_reg = 0x82024,
.halt_check = BRANCH_HALT_DELAY,
......@@ -2406,6 +2427,7 @@ static struct clk_regmap *gcc_sc7180_clocks[] = {
[GCC_MSS_NAV_AXI_CLK] = &gcc_mss_nav_axi_clk.clkr,
[GCC_MSS_Q6_MEMNOC_AXI_CLK] = &gcc_mss_q6_memnoc_axi_clk.clkr,
[GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
[GCC_SEC_CTRL_CLK_SRC] = &gcc_sec_ctrl_clk_src.clkr,
};
static const struct qcom_reset_map gcc_sc7180_resets[] = {
......
......@@ -1617,6 +1617,36 @@ static struct clk_branch gcc_gpu_cfg_ahb_clk = {
},
};
static struct clk_branch gcc_gpu_gpll0_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(15),
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_gpll0_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gpll0.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(16),
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_gpll0_div_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gcc_gpu_gpll0_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_gpu_iref_clk = {
.halt_reg = 0x8c010,
.halt_check = BRANCH_HALT,
......@@ -1699,6 +1729,36 @@ static struct clk_branch gcc_npu_cfg_ahb_clk = {
},
};
static struct clk_branch gcc_npu_gpll0_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(18),
.hw.init = &(struct clk_init_data){
.name = "gcc_npu_gpll0_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gpll0.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_npu_gpll0_div_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(19),
.hw.init = &(struct clk_init_data){
.name = "gcc_npu_gpll0_div_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gcc_npu_gpll0_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_npu_trig_clk = {
.halt_reg = 0x4d00c,
.halt_check = BRANCH_VOTED,
......@@ -2813,6 +2873,45 @@ static struct clk_branch gcc_ufs_card_phy_aux_hw_ctl_clk = {
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_card_rx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x7501c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_card_rx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_card_rx_symbol_1_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x750ac,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_card_rx_symbol_1_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_card_tx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x75018,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_card_tx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_card_unipro_core_clk = {
.halt_reg = 0x75058,
.halt_check = BRANCH_HALT,
......@@ -2993,6 +3092,45 @@ static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = {
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x7701c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_rx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x770ac,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_rx_symbol_1_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x77018,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_tx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
.halt_reg = 0x77058,
.halt_check = BRANCH_HALT,
......@@ -3375,12 +3513,16 @@ static struct clk_regmap *gcc_sm8150_clocks[] = {
[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
[GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
[GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
[GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr,
[GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr,
[GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr,
[GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
[GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
[GCC_NPU_AT_CLK] = &gcc_npu_at_clk.clkr,
[GCC_NPU_AXI_CLK] = &gcc_npu_axi_clk.clkr,
[GCC_NPU_CFG_AHB_CLK] = &gcc_npu_cfg_ahb_clk.clkr,
[GCC_NPU_GPLL0_CLK_SRC] = &gcc_npu_gpll0_clk_src.clkr,
[GCC_NPU_GPLL0_DIV_CLK_SRC] = &gcc_npu_gpll0_div_clk_src.clkr,
[GCC_NPU_TRIG_CLK] = &gcc_npu_trig_clk.clkr,
[GCC_PCIE0_PHY_REFGEN_CLK] = &gcc_pcie0_phy_refgen_clk.clkr,
[GCC_PCIE1_PHY_REFGEN_CLK] = &gcc_pcie1_phy_refgen_clk.clkr,
......@@ -3485,6 +3627,9 @@ static struct clk_regmap *gcc_sm8150_clocks[] = {
[GCC_UFS_CARD_PHY_AUX_CLK_SRC] = &gcc_ufs_card_phy_aux_clk_src.clkr,
[GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK] =
&gcc_ufs_card_phy_aux_hw_ctl_clk.clkr,
[GCC_UFS_CARD_RX_SYMBOL_0_CLK] = &gcc_ufs_card_rx_symbol_0_clk.clkr,
[GCC_UFS_CARD_RX_SYMBOL_1_CLK] = &gcc_ufs_card_rx_symbol_1_clk.clkr,
[GCC_UFS_CARD_TX_SYMBOL_0_CLK] = &gcc_ufs_card_tx_symbol_0_clk.clkr,
[GCC_UFS_CARD_UNIPRO_CORE_CLK] = &gcc_ufs_card_unipro_core_clk.clkr,
[GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC] =
&gcc_ufs_card_unipro_core_clk_src.clkr,
......@@ -3502,6 +3647,9 @@ static struct clk_regmap *gcc_sm8150_clocks[] = {
[GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
[GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
[GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr,
[GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
[GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr,
[GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
[GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
[GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] =
&gcc_ufs_phy_unipro_core_clk_src.clkr,
......
......@@ -11,6 +11,7 @@
#include <linux/ktime.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include "gdsc.h"
......@@ -112,6 +113,12 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
int ret;
u32 val = (status == GDSC_ON) ? 0 : SW_COLLAPSE_MASK;
if (status == GDSC_ON && sc->rsupply) {
ret = regulator_enable(sc->rsupply);
if (ret < 0)
return ret;
}
ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
if (ret)
return ret;
......@@ -143,6 +150,13 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
ret = gdsc_poll_status(sc, status);
WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n");
if (!ret && status == GDSC_OFF && sc->rsupply) {
ret = regulator_disable(sc->rsupply);
if (ret < 0)
return ret;
}
return ret;
}
......@@ -371,6 +385,15 @@ int gdsc_register(struct gdsc_desc *desc,
if (!data->domains)
return -ENOMEM;
for (i = 0; i < num; i++) {
if (!scs[i] || !scs[i]->supply)
continue;
scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
if (IS_ERR(scs[i]->rsupply))
return PTR_ERR(scs[i]->rsupply);
}
data->num_domains = num;
for (i = 0; i < num; i++) {
if (!scs[i])
......
......@@ -10,6 +10,7 @@
#include <linux/pm_domain.h>
struct regmap;
struct regulator;
struct reset_controller_dev;
/**
......@@ -52,6 +53,9 @@ struct gdsc {
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;
const char *supply;
struct regulator *rsupply;
};
struct gdsc_desc {
......
......@@ -3064,7 +3064,9 @@ static struct gdsc gpu_gx_gdsc = {
.name = "gpu_gx",
},
.pwrsts = PWRSTS_OFF_ON,
.parent = &gpu_gdsc.pd,
.flags = CLAMP_IO,
.supply = "vdd-gfx",
};
static struct clk_regmap *mmcc_msm8996_clocks[] = {
......
# SPDX-License-Identifier: GPL-2.0-only
config CLK_LGM_CGU
depends on OF && HAS_IOMEM && (X86 || COMPILE_TEST)
select OF_EARLY_FLATTREE
bool "Clock driver for Lightning Mountain(LGM) platform"
help
Clock Generation Unit(CGU) driver for Intel Lightning Mountain(LGM)
network processor SoC.
......@@ -3,3 +3,4 @@ obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE) += clk-st.o
clk-x86-lpss-objs := clk-lpt.o
obj-$(CONFIG_X86_INTEL_LPSS) += clk-x86-lpss.o
obj-$(CONFIG_CLK_LGM_CGU) += clk-cgu.o clk-cgu-pll.o clk-lgm.o
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Intel Corporation.
* Zhu YiXin <yixin.zhu@intel.com>
* Rahul Tanwar <rahul.tanwar@intel.com>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include "clk-cgu.h"
#define to_lgm_clk_pll(_hw) container_of(_hw, struct lgm_clk_pll, hw)
#define PLL_REF_DIV(x) ((x) + 0x08)
/*
* Calculate formula:
* rate = (prate * mult + (prate * frac) / frac_div) / div
*/
static unsigned long
lgm_pll_calc_rate(unsigned long prate, unsigned int mult,
unsigned int div, unsigned int frac, unsigned int frac_div)
{
u64 crate, frate, rate64;
rate64 = prate;
crate = rate64 * mult;
frate = rate64 * frac;
do_div(frate, frac_div);
crate += frate;
do_div(crate, div);
return crate;
}
static unsigned long lgm_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
unsigned int div, mult, frac;
unsigned long flags;
spin_lock_irqsave(&pll->lock, flags);
mult = lgm_get_clk_val(pll->membase, PLL_REF_DIV(pll->reg), 0, 12);
div = lgm_get_clk_val(pll->membase, PLL_REF_DIV(pll->reg), 18, 6);
frac = lgm_get_clk_val(pll->membase, pll->reg, 2, 24);
spin_unlock_irqrestore(&pll->lock, flags);
if (pll->type == TYPE_LJPLL)
div *= 4;
return lgm_pll_calc_rate(prate, mult, div, frac, BIT(24));
}
static int lgm_pll_is_enabled(struct clk_hw *hw)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
unsigned long flags;
unsigned int ret;
spin_lock_irqsave(&pll->lock, flags);
ret = lgm_get_clk_val(pll->membase, pll->reg, 0, 1);
spin_unlock_irqrestore(&pll->lock, flags);
return ret;
}
static int lgm_pll_enable(struct clk_hw *hw)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
unsigned long flags;
u32 val;
int ret;
spin_lock_irqsave(&pll->lock, flags);
lgm_set_clk_val(pll->membase, pll->reg, 0, 1, 1);
ret = readl_poll_timeout_atomic(pll->membase + pll->reg,
val, (val & 0x1), 1, 100);
spin_unlock_irqrestore(&pll->lock, flags);
return ret;
}
static void lgm_pll_disable(struct clk_hw *hw)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
unsigned long flags;
spin_lock_irqsave(&pll->lock, flags);
lgm_set_clk_val(pll->membase, pll->reg, 0, 1, 0);
spin_unlock_irqrestore(&pll->lock, flags);
}
static const struct clk_ops lgm_pll_ops = {
.recalc_rate = lgm_pll_recalc_rate,
.is_enabled = lgm_pll_is_enabled,
.enable = lgm_pll_enable,
.disable = lgm_pll_disable,
};
static struct clk_hw *
lgm_clk_register_pll(struct lgm_clk_provider *ctx,
const struct lgm_pll_clk_data *list)
{
struct clk_init_data init = {};
struct lgm_clk_pll *pll;
struct device *dev = ctx->dev;
struct clk_hw *hw;
int ret;
init.ops = &lgm_pll_ops;
init.name = list->name;
init.flags = list->flags;
init.parent_data = list->parent_data;
init.num_parents = list->num_parents;
pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
pll->membase = ctx->membase;
pll->lock = ctx->lock;
pll->reg = list->reg;
pll->flags = list->flags;
pll->type = list->type;
pll->hw.init = &init;
hw = &pll->hw;
ret = clk_hw_register(dev, hw);
if (ret)
return ERR_PTR(ret);
return hw;
}
int lgm_clk_register_plls(struct lgm_clk_provider *ctx,
const struct lgm_pll_clk_data *list,
unsigned int nr_clk)
{
struct clk_hw *hw;
int i;
for (i = 0; i < nr_clk; i++, list++) {
hw = lgm_clk_register_pll(ctx, list);
if (IS_ERR(hw)) {
dev_err(ctx->dev, "failed to register pll: %s\n",
list->name);
return PTR_ERR(hw);
}
ctx->clk_data.hws[list->id] = hw;
}
return 0;
}
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Intel Corporation.
* Zhu YiXin <yixin.zhu@intel.com>
* Rahul Tanwar <rahul.tanwar@intel.com>
*/
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/of.h>
#include "clk-cgu.h"
#define GATE_HW_REG_STAT(reg) ((reg) + 0x0)
#define GATE_HW_REG_EN(reg) ((reg) + 0x4)
#define GATE_HW_REG_DIS(reg) ((reg) + 0x8)
#define MAX_DDIV_REG 8
#define MAX_DIVIDER_VAL 64
#define to_lgm_clk_mux(_hw) container_of(_hw, struct lgm_clk_mux, hw)
#define to_lgm_clk_divider(_hw) container_of(_hw, struct lgm_clk_divider, hw)
#define to_lgm_clk_gate(_hw) container_of(_hw, struct lgm_clk_gate, hw)
#define to_lgm_clk_ddiv(_hw) container_of(_hw, struct lgm_clk_ddiv, hw)
static struct clk_hw *lgm_clk_register_fixed(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
unsigned long flags;
if (list->div_flags & CLOCK_FLAG_VAL_INIT) {
spin_lock_irqsave(&ctx->lock, flags);
lgm_set_clk_val(ctx->membase, list->div_off, list->div_shift,
list->div_width, list->div_val);
spin_unlock_irqrestore(&ctx->lock, flags);
}
return clk_hw_register_fixed_rate(NULL, list->name,
list->parent_data[0].name,
list->flags, list->mux_flags);
}
static u8 lgm_clk_mux_get_parent(struct clk_hw *hw)
{
struct lgm_clk_mux *mux = to_lgm_clk_mux(hw);
unsigned long flags;
u32 val;
spin_lock_irqsave(&mux->lock, flags);
if (mux->flags & MUX_CLK_SW)
val = mux->reg;
else
val = lgm_get_clk_val(mux->membase, mux->reg, mux->shift,
mux->width);
spin_unlock_irqrestore(&mux->lock, flags);
return clk_mux_val_to_index(hw, NULL, mux->flags, val);
}
static int lgm_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct lgm_clk_mux *mux = to_lgm_clk_mux(hw);
unsigned long flags;
u32 val;
val = clk_mux_index_to_val(NULL, mux->flags, index);
spin_lock_irqsave(&mux->lock, flags);
if (mux->flags & MUX_CLK_SW)
mux->reg = val;
else
lgm_set_clk_val(mux->membase, mux->reg, mux->shift,
mux->width, val);
spin_unlock_irqrestore(&mux->lock, flags);
return 0;
}
static int lgm_clk_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lgm_clk_mux *mux = to_lgm_clk_mux(hw);
return clk_mux_determine_rate_flags(hw, req, mux->flags);
}
static const struct clk_ops lgm_clk_mux_ops = {
.get_parent = lgm_clk_mux_get_parent,
.set_parent = lgm_clk_mux_set_parent,
.determine_rate = lgm_clk_mux_determine_rate,
};
static struct clk_hw *
lgm_clk_register_mux(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
unsigned long flags, cflags = list->mux_flags;
struct device *dev = ctx->dev;
u8 shift = list->mux_shift;
u8 width = list->mux_width;
struct clk_init_data init = {};
struct lgm_clk_mux *mux;
u32 reg = list->mux_off;
struct clk_hw *hw;
int ret;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux)
return ERR_PTR(-ENOMEM);
init.name = list->name;
init.ops = &lgm_clk_mux_ops;
init.flags = list->flags;
init.parent_data = list->parent_data;
init.num_parents = list->num_parents;
mux->membase = ctx->membase;
mux->lock = ctx->lock;
mux->reg = reg;
mux->shift = shift;
mux->width = width;
mux->flags = cflags;
mux->hw.init = &init;
hw = &mux->hw;
ret = clk_hw_register(dev, hw);
if (ret)
return ERR_PTR(ret);
if (cflags & CLOCK_FLAG_VAL_INIT) {
spin_lock_irqsave(&mux->lock, flags);
lgm_set_clk_val(mux->membase, reg, shift, width, list->mux_val);
spin_unlock_irqrestore(&mux->lock, flags);
}
return hw;
}
static unsigned long
lgm_clk_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct lgm_clk_divider *divider = to_lgm_clk_divider(hw);
unsigned long flags;
unsigned int val;
spin_lock_irqsave(&divider->lock, flags);
val = lgm_get_clk_val(divider->membase, divider->reg,
divider->shift, divider->width);
spin_unlock_irqrestore(&divider->lock, flags);
return divider_recalc_rate(hw, parent_rate, val, divider->table,
divider->flags, divider->width);
}
static long
lgm_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct lgm_clk_divider *divider = to_lgm_clk_divider(hw);
return divider_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags);
}
static int
lgm_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
struct lgm_clk_divider *divider = to_lgm_clk_divider(hw);
unsigned long flags;
int value;
value = divider_get_val(rate, prate, divider->table,
divider->width, divider->flags);
if (value < 0)
return value;
spin_lock_irqsave(&divider->lock, flags);
lgm_set_clk_val(divider->membase, divider->reg,
divider->shift, divider->width, value);
spin_unlock_irqrestore(&divider->lock, flags);
return 0;
}
static int lgm_clk_divider_enable_disable(struct clk_hw *hw, int enable)
{
struct lgm_clk_divider *div = to_lgm_clk_divider(hw);
unsigned long flags;
spin_lock_irqsave(&div->lock, flags);
lgm_set_clk_val(div->membase, div->reg, div->shift_gate,
div->width_gate, enable);
spin_unlock_irqrestore(&div->lock, flags);
return 0;
}
static int lgm_clk_divider_enable(struct clk_hw *hw)
{
return lgm_clk_divider_enable_disable(hw, 1);
}
static void lgm_clk_divider_disable(struct clk_hw *hw)
{
lgm_clk_divider_enable_disable(hw, 0);
}
static const struct clk_ops lgm_clk_divider_ops = {
.recalc_rate = lgm_clk_divider_recalc_rate,
.round_rate = lgm_clk_divider_round_rate,
.set_rate = lgm_clk_divider_set_rate,
.enable = lgm_clk_divider_enable,
.disable = lgm_clk_divider_disable,
};
static struct clk_hw *
lgm_clk_register_divider(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
unsigned long flags, cflags = list->div_flags;
struct device *dev = ctx->dev;
struct lgm_clk_divider *div;
struct clk_init_data init = {};
u8 shift = list->div_shift;
u8 width = list->div_width;
u8 shift_gate = list->div_shift_gate;
u8 width_gate = list->div_width_gate;
u32 reg = list->div_off;
struct clk_hw *hw;
int ret;
div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
init.name = list->name;
init.ops = &lgm_clk_divider_ops;
init.flags = list->flags;
init.parent_data = list->parent_data;
init.num_parents = 1;
div->membase = ctx->membase;
div->lock = ctx->lock;
div->reg = reg;
div->shift = shift;
div->width = width;
div->shift_gate = shift_gate;
div->width_gate = width_gate;
div->flags = cflags;
div->table = list->div_table;
div->hw.init = &init;
hw = &div->hw;
ret = clk_hw_register(dev, hw);
if (ret)
return ERR_PTR(ret);
if (cflags & CLOCK_FLAG_VAL_INIT) {
spin_lock_irqsave(&div->lock, flags);
lgm_set_clk_val(div->membase, reg, shift, width, list->div_val);
spin_unlock_irqrestore(&div->lock, flags);
}
return hw;
}
static struct clk_hw *
lgm_clk_register_fixed_factor(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
unsigned long flags;
struct clk_hw *hw;
hw = clk_hw_register_fixed_factor(ctx->dev, list->name,
list->parent_data[0].name, list->flags,
list->mult, list->div);
if (IS_ERR(hw))
return ERR_CAST(hw);
if (list->div_flags & CLOCK_FLAG_VAL_INIT) {
spin_lock_irqsave(&ctx->lock, flags);
lgm_set_clk_val(ctx->membase, list->div_off, list->div_shift,
list->div_width, list->div_val);
spin_unlock_irqrestore(&ctx->lock, flags);
}
return hw;
}
static int lgm_clk_gate_enable(struct clk_hw *hw)
{
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned long flags;
unsigned int reg;
spin_lock_irqsave(&gate->lock, flags);
reg = GATE_HW_REG_EN(gate->reg);
lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
spin_unlock_irqrestore(&gate->lock, flags);
return 0;
}
static void lgm_clk_gate_disable(struct clk_hw *hw)
{
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned long flags;
unsigned int reg;
spin_lock_irqsave(&gate->lock, flags);
reg = GATE_HW_REG_DIS(gate->reg);
lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
spin_unlock_irqrestore(&gate->lock, flags);
}
static int lgm_clk_gate_is_enabled(struct clk_hw *hw)
{
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned int reg, ret;
unsigned long flags;
spin_lock_irqsave(&gate->lock, flags);
reg = GATE_HW_REG_STAT(gate->reg);
ret = lgm_get_clk_val(gate->membase, reg, gate->shift, 1);
spin_unlock_irqrestore(&gate->lock, flags);
return ret;
}
static const struct clk_ops lgm_clk_gate_ops = {
.enable = lgm_clk_gate_enable,
.disable = lgm_clk_gate_disable,
.is_enabled = lgm_clk_gate_is_enabled,
};
static struct clk_hw *
lgm_clk_register_gate(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
unsigned long flags, cflags = list->gate_flags;
const char *pname = list->parent_data[0].name;
struct device *dev = ctx->dev;
u8 shift = list->gate_shift;
struct clk_init_data init = {};
struct lgm_clk_gate *gate;
u32 reg = list->gate_off;
struct clk_hw *hw;
int ret;
gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
init.name = list->name;
init.ops = &lgm_clk_gate_ops;
init.flags = list->flags;
init.parent_names = pname ? &pname : NULL;
init.num_parents = pname ? 1 : 0;
gate->membase = ctx->membase;
gate->lock = ctx->lock;
gate->reg = reg;
gate->shift = shift;
gate->flags = cflags;
gate->hw.init = &init;
hw = &gate->hw;
ret = clk_hw_register(dev, hw);
if (ret)
return ERR_PTR(ret);
if (cflags & CLOCK_FLAG_VAL_INIT) {
spin_lock_irqsave(&gate->lock, flags);
lgm_set_clk_val(gate->membase, reg, shift, 1, list->gate_val);
spin_unlock_irqrestore(&gate->lock, flags);
}
return hw;
}
int lgm_clk_register_branches(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list,
unsigned int nr_clk)
{
struct clk_hw *hw;
unsigned int idx;
for (idx = 0; idx < nr_clk; idx++, list++) {
switch (list->type) {
case CLK_TYPE_FIXED:
hw = lgm_clk_register_fixed(ctx, list);
break;
case CLK_TYPE_MUX:
hw = lgm_clk_register_mux(ctx, list);
break;
case CLK_TYPE_DIVIDER:
hw = lgm_clk_register_divider(ctx, list);
break;
case CLK_TYPE_FIXED_FACTOR:
hw = lgm_clk_register_fixed_factor(ctx, list);
break;
case CLK_TYPE_GATE:
hw = lgm_clk_register_gate(ctx, list);
break;
default:
dev_err(ctx->dev, "invalid clk type\n");
return -EINVAL;
}
if (IS_ERR(hw)) {
dev_err(ctx->dev,
"register clk: %s, type: %u failed!\n",
list->name, list->type);
return -EIO;
}
ctx->clk_data.hws[list->id] = hw;
}
return 0;
}
static unsigned long
lgm_clk_ddiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
unsigned int div0, div1, exdiv;
unsigned long flags;
u64 prate;
spin_lock_irqsave(&ddiv->lock, flags);
div0 = lgm_get_clk_val(ddiv->membase, ddiv->reg,
ddiv->shift0, ddiv->width0) + 1;
div1 = lgm_get_clk_val(ddiv->membase, ddiv->reg,
ddiv->shift1, ddiv->width1) + 1;
exdiv = lgm_get_clk_val(ddiv->membase, ddiv->reg,
ddiv->shift2, ddiv->width2);
spin_unlock_irqrestore(&ddiv->lock, flags);
prate = (u64)parent_rate;
do_div(prate, div0);
do_div(prate, div1);
if (exdiv) {
do_div(prate, ddiv->div);
prate *= ddiv->mult;
}
return prate;
}
static int lgm_clk_ddiv_enable(struct clk_hw *hw)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
unsigned long flags;
spin_lock_irqsave(&ddiv->lock, flags);
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift_gate,
ddiv->width_gate, 1);
spin_unlock_irqrestore(&ddiv->lock, flags);
return 0;
}
static void lgm_clk_ddiv_disable(struct clk_hw *hw)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
unsigned long flags;
spin_lock_irqsave(&ddiv->lock, flags);
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift_gate,
ddiv->width_gate, 0);
spin_unlock_irqrestore(&ddiv->lock, flags);
}
static int
lgm_clk_get_ddiv_val(u32 div, u32 *ddiv1, u32 *ddiv2)
{
u32 idx, temp;
*ddiv1 = 1;
*ddiv2 = 1;
if (div > MAX_DIVIDER_VAL)
div = MAX_DIVIDER_VAL;
if (div > 1) {
for (idx = 2; idx <= MAX_DDIV_REG; idx++) {
temp = DIV_ROUND_UP_ULL((u64)div, idx);
if (div % idx == 0 && temp <= MAX_DDIV_REG)
break;
}
if (idx > MAX_DDIV_REG)
return -EINVAL;
*ddiv1 = temp;
*ddiv2 = idx;
}
return 0;
}
static int
lgm_clk_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
u32 div, ddiv1, ddiv2;
unsigned long flags;
div = DIV_ROUND_CLOSEST_ULL((u64)prate, rate);
spin_lock_irqsave(&ddiv->lock, flags);
if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);
div = div * 2;
}
if (div <= 0) {
spin_unlock_irqrestore(&ddiv->lock, flags);
return -EINVAL;
}
if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2)) {
spin_unlock_irqrestore(&ddiv->lock, flags);
return -EINVAL;
}
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift0, ddiv->width0,
ddiv1 - 1);
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift1, ddiv->width1,
ddiv2 - 1);
spin_unlock_irqrestore(&ddiv->lock, flags);
return 0;
}
static long
lgm_clk_ddiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
u32 div, ddiv1, ddiv2;
unsigned long flags;
u64 rate64;
div = DIV_ROUND_CLOSEST_ULL((u64)*prate, rate);
/* if predivide bit is enabled, modify div by factor of 2.5 */
spin_lock_irqsave(&ddiv->lock, flags);
if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
div = div * 2;
div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);
}
if (div <= 0) {
spin_unlock_irqrestore(&ddiv->lock, flags);
return *prate;
}
if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2) != 0) {
if (lgm_clk_get_ddiv_val(div + 1, &ddiv1, &ddiv2) != 0) {
spin_unlock_irqrestore(&ddiv->lock, flags);
return -EINVAL;
}
}
rate64 = *prate;
do_div(rate64, ddiv1);
do_div(rate64, ddiv2);
/* if predivide bit is enabled, modify rounded rate by factor of 2.5 */
if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
rate64 = rate64 * 2;
rate64 = DIV_ROUND_CLOSEST_ULL(rate64, 5);
}
spin_unlock_irqrestore(&ddiv->lock, flags);
return rate64;
}
static const struct clk_ops lgm_clk_ddiv_ops = {
.recalc_rate = lgm_clk_ddiv_recalc_rate,
.enable = lgm_clk_ddiv_enable,
.disable = lgm_clk_ddiv_disable,
.set_rate = lgm_clk_ddiv_set_rate,
.round_rate = lgm_clk_ddiv_round_rate,
};
int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx,
const struct lgm_clk_ddiv_data *list,
unsigned int nr_clk)
{
struct device *dev = ctx->dev;
struct clk_init_data init = {};
struct lgm_clk_ddiv *ddiv;
struct clk_hw *hw;
unsigned int idx;
int ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
ddiv = NULL;
ddiv = devm_kzalloc(dev, sizeof(*ddiv), GFP_KERNEL);
if (!ddiv)
return -ENOMEM;
memset(&init, 0, sizeof(init));
init.name = list->name;
init.ops = &lgm_clk_ddiv_ops;
init.flags = list->flags;
init.parent_data = list->parent_data;
init.num_parents = 1;
ddiv->membase = ctx->membase;
ddiv->lock = ctx->lock;
ddiv->reg = list->reg;
ddiv->shift0 = list->shift0;
ddiv->width0 = list->width0;
ddiv->shift1 = list->shift1;
ddiv->width1 = list->width1;
ddiv->shift_gate = list->shift_gate;
ddiv->width_gate = list->width_gate;
ddiv->shift2 = list->ex_shift;
ddiv->width2 = list->ex_width;
ddiv->flags = list->div_flags;
ddiv->mult = 2;
ddiv->div = 5;
ddiv->hw.init = &init;
hw = &ddiv->hw;
ret = clk_hw_register(dev, hw);
if (ret) {
dev_err(dev, "register clk: %s failed!\n", list->name);
return ret;
}
ctx->clk_data.hws[list->id] = hw;
}
return 0;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright(c) 2020 Intel Corporation.
* Zhu YiXin <yixin.zhu@intel.com>
* Rahul Tanwar <rahul.tanwar@intel.com>
*/
#ifndef __CLK_CGU_H
#define __CLK_CGU_H
#include <linux/io.h>
struct lgm_clk_mux {
struct clk_hw hw;
void __iomem *membase;
unsigned int reg;
u8 shift;
u8 width;
unsigned long flags;
spinlock_t lock;
};
struct lgm_clk_divider {
struct clk_hw hw;
void __iomem *membase;
unsigned int reg;
u8 shift;
u8 width;
u8 shift_gate;
u8 width_gate;
unsigned long flags;
const struct clk_div_table *table;
spinlock_t lock;
};
struct lgm_clk_ddiv {
struct clk_hw hw;
void __iomem *membase;
unsigned int reg;
u8 shift0;
u8 width0;
u8 shift1;
u8 width1;
u8 shift2;
u8 width2;
u8 shift_gate;
u8 width_gate;
unsigned int mult;
unsigned int div;
unsigned long flags;
spinlock_t lock;
};
struct lgm_clk_gate {
struct clk_hw hw;
void __iomem *membase;
unsigned int reg;
u8 shift;
unsigned long flags;
spinlock_t lock;
};
enum lgm_clk_type {
CLK_TYPE_FIXED,
CLK_TYPE_MUX,
CLK_TYPE_DIVIDER,
CLK_TYPE_FIXED_FACTOR,
CLK_TYPE_GATE,
CLK_TYPE_NONE,
};
/**
* struct lgm_clk_provider
* @membase: IO mem base address for CGU.
* @np: device node
* @dev: device
* @clk_data: array of hw clocks and clk number.
*/
struct lgm_clk_provider {
void __iomem *membase;
struct device_node *np;
struct device *dev;
struct clk_hw_onecell_data clk_data;
spinlock_t lock;
};
enum pll_type {
TYPE_ROPLL,
TYPE_LJPLL,
TYPE_NONE,
};
struct lgm_clk_pll {
struct clk_hw hw;
void __iomem *membase;
unsigned int reg;
unsigned long flags;
enum pll_type type;
spinlock_t lock;
};
/**
* struct lgm_pll_clk_data
* @id: platform specific id of the clock.
* @name: name of this pll clock.
* @parent_data: parent clock data.
* @num_parents: number of parents.
* @flags: optional flags for basic clock.
* @type: platform type of pll.
* @reg: offset of the register.
*/
struct lgm_pll_clk_data {
unsigned int id;
const char *name;
const struct clk_parent_data *parent_data;
u8 num_parents;
unsigned long flags;
enum pll_type type;
int reg;
};
#define LGM_PLL(_id, _name, _pdata, _flags, \
_reg, _type) \
{ \
.id = _id, \
.name = _name, \
.parent_data = _pdata, \
.num_parents = ARRAY_SIZE(_pdata), \
.flags = _flags, \
.reg = _reg, \
.type = _type, \
}
struct lgm_clk_ddiv_data {
unsigned int id;
const char *name;
const struct clk_parent_data *parent_data;
u8 flags;
unsigned long div_flags;
unsigned int reg;
u8 shift0;
u8 width0;
u8 shift1;
u8 width1;
u8 shift_gate;
u8 width_gate;
u8 ex_shift;
u8 ex_width;
};
#define LGM_DDIV(_id, _name, _pname, _flags, _reg, \
_shft0, _wdth0, _shft1, _wdth1, \
_shft_gate, _wdth_gate, _xshft, _df) \
{ \
.id = _id, \
.name = _name, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = _pname, \
.name = _pname, \
}, \
.flags = _flags, \
.reg = _reg, \
.shift0 = _shft0, \
.width0 = _wdth0, \
.shift1 = _shft1, \
.width1 = _wdth1, \
.shift_gate = _shft_gate, \
.width_gate = _wdth_gate, \
.ex_shift = _xshft, \
.ex_width = 1, \
.div_flags = _df, \
}
struct lgm_clk_branch {
unsigned int id;
enum lgm_clk_type type;
const char *name;
const struct clk_parent_data *parent_data;
u8 num_parents;
unsigned long flags;
unsigned int mux_off;
u8 mux_shift;
u8 mux_width;
unsigned long mux_flags;
unsigned int mux_val;
unsigned int div_off;
u8 div_shift;
u8 div_width;
u8 div_shift_gate;
u8 div_width_gate;
unsigned long div_flags;
unsigned int div_val;
const struct clk_div_table *div_table;
unsigned int gate_off;
u8 gate_shift;
unsigned long gate_flags;
unsigned int gate_val;
unsigned int mult;
unsigned int div;
};
/* clock flags definition */
#define CLOCK_FLAG_VAL_INIT BIT(16)
#define MUX_CLK_SW BIT(17)
#define LGM_MUX(_id, _name, _pdata, _f, _reg, \
_shift, _width, _cf, _v) \
{ \
.id = _id, \
.type = CLK_TYPE_MUX, \
.name = _name, \
.parent_data = _pdata, \
.num_parents = ARRAY_SIZE(_pdata), \
.flags = _f, \
.mux_off = _reg, \
.mux_shift = _shift, \
.mux_width = _width, \
.mux_flags = _cf, \
.mux_val = _v, \
}
#define LGM_DIV(_id, _name, _pname, _f, _reg, _shift, _width, \
_shift_gate, _width_gate, _cf, _v, _dtable) \
{ \
.id = _id, \
.type = CLK_TYPE_DIVIDER, \
.name = _name, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = _pname, \
.name = _pname, \
}, \
.num_parents = 1, \
.flags = _f, \
.div_off = _reg, \
.div_shift = _shift, \
.div_width = _width, \
.div_shift_gate = _shift_gate, \
.div_width_gate = _width_gate, \
.div_flags = _cf, \
.div_val = _v, \
.div_table = _dtable, \
}
#define LGM_GATE(_id, _name, _pname, _f, _reg, \
_shift, _cf, _v) \
{ \
.id = _id, \
.type = CLK_TYPE_GATE, \
.name = _name, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = _pname, \
.name = _pname, \
}, \
.num_parents = !_pname ? 0 : 1, \
.flags = _f, \
.gate_off = _reg, \
.gate_shift = _shift, \
.gate_flags = _cf, \
.gate_val = _v, \
}
#define LGM_FIXED(_id, _name, _pname, _f, _reg, \
_shift, _width, _cf, _freq, _v) \
{ \
.id = _id, \
.type = CLK_TYPE_FIXED, \
.name = _name, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = _pname, \
.name = _pname, \
}, \
.num_parents = !_pname ? 0 : 1, \
.flags = _f, \
.div_off = _reg, \
.div_shift = _shift, \
.div_width = _width, \
.div_flags = _cf, \
.div_val = _v, \
.mux_flags = _freq, \
}
#define LGM_FIXED_FACTOR(_id, _name, _pname, _f, _reg, \
_shift, _width, _cf, _v, _m, _d) \
{ \
.id = _id, \
.type = CLK_TYPE_FIXED_FACTOR, \
.name = _name, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = _pname, \
.name = _pname, \
}, \
.num_parents = 1, \
.flags = _f, \
.div_off = _reg, \
.div_shift = _shift, \
.div_width = _width, \
.div_flags = _cf, \
.div_val = _v, \
.mult = _m, \
.div = _d, \
}
static inline void lgm_set_clk_val(void __iomem *membase, u32 reg,
u8 shift, u8 width, u32 set_val)
{
u32 mask = (GENMASK(width - 1, 0) << shift);
u32 regval;
regval = readl(membase + reg);
regval = (regval & ~mask) | ((set_val << shift) & mask);
writel(regval, membase + reg);
}
static inline u32 lgm_get_clk_val(void __iomem *membase, u32 reg,
u8 shift, u8 width)
{
u32 mask = (GENMASK(width - 1, 0) << shift);
u32 val;
val = readl(membase + reg);
val = (val & mask) >> shift;
return val;
}
int lgm_clk_register_branches(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list,
unsigned int nr_clk);
int lgm_clk_register_plls(struct lgm_clk_provider *ctx,
const struct lgm_pll_clk_data *list,
unsigned int nr_clk);
int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx,
const struct lgm_clk_ddiv_data *list,
unsigned int nr_clk);
#endif /* __CLK_CGU_H */
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Intel Corporation.
* Zhu YiXin <yixin.zhu@intel.com>
* Rahul Tanwar <rahul.tanwar@intel.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/intel,lgm-clk.h>
#include "clk-cgu.h"
#define PLL_DIV_WIDTH 4
#define PLL_DDIV_WIDTH 3
/* Gate0 clock shift */
#define G_C55_SHIFT 7
#define G_QSPI_SHIFT 9
#define G_EIP197_SHIFT 11
#define G_VAULT130_SHIFT 12
#define G_TOE_SHIFT 13
#define G_SDXC_SHIFT 14
#define G_EMMC_SHIFT 15
#define G_SPIDBG_SHIFT 17
#define G_DMA3_SHIFT 28
/* Gate1 clock shift */
#define G_DMA0_SHIFT 0
#define G_LEDC0_SHIFT 1
#define G_LEDC1_SHIFT 2
#define G_I2S0_SHIFT 3
#define G_I2S1_SHIFT 4
#define G_EBU_SHIFT 5
#define G_PWM_SHIFT 6
#define G_I2C0_SHIFT 7
#define G_I2C1_SHIFT 8
#define G_I2C2_SHIFT 9
#define G_I2C3_SHIFT 10
#define G_SSC0_SHIFT 12
#define G_SSC1_SHIFT 13
#define G_SSC2_SHIFT 14
#define G_SSC3_SHIFT 15
#define G_GPTC0_SHIFT 17
#define G_GPTC1_SHIFT 18
#define G_GPTC2_SHIFT 19
#define G_GPTC3_SHIFT 20
#define G_ASC0_SHIFT 22
#define G_ASC1_SHIFT 23
#define G_ASC2_SHIFT 24
#define G_ASC3_SHIFT 25
#define G_PCM0_SHIFT 27
#define G_PCM1_SHIFT 28
#define G_PCM2_SHIFT 29
/* Gate2 clock shift */
#define G_PCIE10_SHIFT 1
#define G_PCIE11_SHIFT 2
#define G_PCIE30_SHIFT 3
#define G_PCIE31_SHIFT 4
#define G_PCIE20_SHIFT 5
#define G_PCIE21_SHIFT 6
#define G_PCIE40_SHIFT 7
#define G_PCIE41_SHIFT 8
#define G_XPCS0_SHIFT 10
#define G_XPCS1_SHIFT 11
#define G_XPCS2_SHIFT 12
#define G_XPCS3_SHIFT 13
#define G_SATA0_SHIFT 14
#define G_SATA1_SHIFT 15
#define G_SATA2_SHIFT 16
#define G_SATA3_SHIFT 17
/* Gate3 clock shift */
#define G_ARCEM4_SHIFT 0
#define G_IDMAR1_SHIFT 2
#define G_IDMAT0_SHIFT 3
#define G_IDMAT1_SHIFT 4
#define G_IDMAT2_SHIFT 5
#define G_PPV4_SHIFT 8
#define G_GSWIPO_SHIFT 9
#define G_CQEM_SHIFT 10
#define G_XPCS5_SHIFT 14
#define G_USB1_SHIFT 25
#define G_USB2_SHIFT 26
/* Register definition */
#define CGU_PLL0CZ_CFG0 0x000
#define CGU_PLL0CM0_CFG0 0x020
#define CGU_PLL0CM1_CFG0 0x040
#define CGU_PLL0B_CFG0 0x060
#define CGU_PLL1_CFG0 0x080
#define CGU_PLL2_CFG0 0x0A0
#define CGU_PLLPP_CFG0 0x0C0
#define CGU_LJPLL3_CFG0 0x0E0
#define CGU_LJPLL4_CFG0 0x100
#define CGU_C55_PCMCR 0x18C
#define CGU_PCMCR 0x190
#define CGU_IF_CLK1 0x1A0
#define CGU_IF_CLK2 0x1A4
#define CGU_GATE0 0x300
#define CGU_GATE1 0x310
#define CGU_GATE2 0x320
#define CGU_GATE3 0x310
#define PLL_DIV(x) ((x) + 0x04)
#define PLL_SSC(x) ((x) + 0x10)
#define CLK_NR_CLKS (LGM_GCLK_USB2 + 1)
/*
* Below table defines the pair's of regval & effective dividers.
* It's more efficient to provide an explicit table due to non-linear
* relation between values.
*/
static const struct clk_div_table pll_div[] = {
{ .val = 0, .div = 1 },
{ .val = 1, .div = 2 },
{ .val = 2, .div = 3 },
{ .val = 3, .div = 4 },
{ .val = 4, .div = 5 },
{ .val = 5, .div = 6 },
{ .val = 6, .div = 8 },
{ .val = 7, .div = 10 },
{ .val = 8, .div = 12 },
{ .val = 9, .div = 16 },
{ .val = 10, .div = 20 },
{ .val = 11, .div = 24 },
{ .val = 12, .div = 32 },
{ .val = 13, .div = 40 },
{ .val = 14, .div = 48 },
{ .val = 15, .div = 64 },
{}
};
static const struct clk_div_table dcl_div[] = {
{ .val = 0, .div = 6 },
{ .val = 1, .div = 12 },
{ .val = 2, .div = 24 },
{ .val = 3, .div = 32 },
{ .val = 4, .div = 48 },
{ .val = 5, .div = 96 },
{}
};
static const struct clk_parent_data pll_p[] = {
{ .fw_name = "osc", .name = "osc" },
};
static const struct clk_parent_data pllcm_p[] = {
{ .fw_name = "cpu_cm", .name = "cpu_cm" },
};
static const struct clk_parent_data emmc_p[] = {
{ .fw_name = "emmc4", .name = "emmc4" },
{ .fw_name = "noc4", .name = "noc4" },
};
static const struct clk_parent_data sdxc_p[] = {
{ .fw_name = "sdxc3", .name = "sdxc3" },
{ .fw_name = "sdxc2", .name = "sdxc2" },
};
static const struct clk_parent_data pcm_p[] = {
{ .fw_name = "v_docsis", .name = "v_docsis" },
{ .fw_name = "dcl", .name = "dcl" },
};
static const struct clk_parent_data cbphy_p[] = {
{ .fw_name = "dd_serdes", .name = "dd_serdes" },
{ .fw_name = "dd_pcie", .name = "dd_pcie" },
};
static const struct lgm_pll_clk_data lgm_pll_clks[] = {
LGM_PLL(LGM_CLK_PLL0CZ, "pll0cz", pll_p, CLK_IGNORE_UNUSED,
CGU_PLL0CZ_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_PLL0CM0, "pll0cm0", pllcm_p, CLK_IGNORE_UNUSED,
CGU_PLL0CM0_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_PLL0CM1, "pll0cm1", pllcm_p, CLK_IGNORE_UNUSED,
CGU_PLL0CM1_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_PLL0B, "pll0b", pll_p, CLK_IGNORE_UNUSED,
CGU_PLL0B_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_PLL1, "pll1", pll_p, 0, CGU_PLL1_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_PLL2, "pll2", pll_p, CLK_IGNORE_UNUSED,
CGU_PLL2_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_PLLPP, "pllpp", pll_p, 0, CGU_PLLPP_CFG0, TYPE_ROPLL),
LGM_PLL(LGM_CLK_LJPLL3, "ljpll3", pll_p, 0, CGU_LJPLL3_CFG0, TYPE_LJPLL),
LGM_PLL(LGM_CLK_LJPLL4, "ljpll4", pll_p, 0, CGU_LJPLL4_CFG0, TYPE_LJPLL),
};
static const struct lgm_clk_branch lgm_branch_clks[] = {
LGM_DIV(LGM_CLK_PP_HW, "pp_hw", "pllpp", 0, PLL_DIV(CGU_PLLPP_CFG0),
0, PLL_DIV_WIDTH, 24, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_PP_UC, "pp_uc", "pllpp", 0, PLL_DIV(CGU_PLLPP_CFG0),
4, PLL_DIV_WIDTH, 25, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_PP_FXD, "pp_fxd", "pllpp", 0, PLL_DIV(CGU_PLLPP_CFG0),
8, PLL_DIV_WIDTH, 26, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_PP_TBM, "pp_tbm", "pllpp", 0, PLL_DIV(CGU_PLLPP_CFG0),
12, PLL_DIV_WIDTH, 27, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_DDR, "ddr", "pll2", CLK_IGNORE_UNUSED,
PLL_DIV(CGU_PLL2_CFG0), 0, PLL_DIV_WIDTH, 24, 1, 0, 0,
pll_div),
LGM_DIV(LGM_CLK_CM, "cpu_cm", "pll0cz", 0, PLL_DIV(CGU_PLL0CZ_CFG0),
0, PLL_DIV_WIDTH, 24, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_IC, "cpu_ic", "pll0cz", CLK_IGNORE_UNUSED,
PLL_DIV(CGU_PLL0CZ_CFG0), 4, PLL_DIV_WIDTH, 25,
1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_SDXC3, "sdxc3", "pll0cz", 0, PLL_DIV(CGU_PLL0CZ_CFG0),
8, PLL_DIV_WIDTH, 26, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_CPU0, "cm0", "pll0cm0",
CLK_IGNORE_UNUSED, PLL_DIV(CGU_PLL0CM0_CFG0),
0, PLL_DIV_WIDTH, 24, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_CPU1, "cm1", "pll0cm1",
CLK_IGNORE_UNUSED, PLL_DIV(CGU_PLL0CM1_CFG0),
0, PLL_DIV_WIDTH, 24, 1, 0, 0, pll_div),
/*
* Marking ngi_clk (next generation interconnect) and noc_clk
* (network on chip peripheral clk) as critical clocks because
* these are shared parent clock sources for many different
* peripherals.
*/
LGM_DIV(LGM_CLK_NGI, "ngi", "pll0b",
(CLK_IGNORE_UNUSED|CLK_IS_CRITICAL), PLL_DIV(CGU_PLL0B_CFG0),
0, PLL_DIV_WIDTH, 24, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_NOC4, "noc4", "pll0b",
(CLK_IGNORE_UNUSED|CLK_IS_CRITICAL), PLL_DIV(CGU_PLL0B_CFG0),
4, PLL_DIV_WIDTH, 25, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_SW, "switch", "pll0b", 0, PLL_DIV(CGU_PLL0B_CFG0),
8, PLL_DIV_WIDTH, 26, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_QSPI, "qspi", "pll0b", 0, PLL_DIV(CGU_PLL0B_CFG0),
12, PLL_DIV_WIDTH, 27, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_CT, "v_ct", "pll1", 0, PLL_DIV(CGU_PLL1_CFG0),
0, PLL_DIV_WIDTH, 24, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_DSP, "v_dsp", "pll1", 0, PLL_DIV(CGU_PLL1_CFG0),
8, PLL_DIV_WIDTH, 26, 1, 0, 0, pll_div),
LGM_DIV(LGM_CLK_VIF, "v_ifclk", "pll1", 0, PLL_DIV(CGU_PLL1_CFG0),
12, PLL_DIV_WIDTH, 27, 1, 0, 0, pll_div),
LGM_FIXED_FACTOR(LGM_CLK_EMMC4, "emmc4", "sdxc3", 0, 0,
0, 0, 0, 0, 1, 4),
LGM_FIXED_FACTOR(LGM_CLK_SDXC2, "sdxc2", "noc4", 0, 0,
0, 0, 0, 0, 1, 4),
LGM_MUX(LGM_CLK_EMMC, "emmc", emmc_p, 0, CGU_IF_CLK1,
0, 1, CLK_MUX_ROUND_CLOSEST, 0),
LGM_MUX(LGM_CLK_SDXC, "sdxc", sdxc_p, 0, CGU_IF_CLK1,
1, 1, CLK_MUX_ROUND_CLOSEST, 0),
LGM_FIXED(LGM_CLK_OSC, "osc", NULL, 0, 0, 0, 0, 0, 40000000, 0),
LGM_FIXED(LGM_CLK_SLIC, "slic", NULL, 0, CGU_IF_CLK1,
8, 2, CLOCK_FLAG_VAL_INIT, 8192000, 2),
LGM_FIXED(LGM_CLK_DOCSIS, "v_docsis", NULL, 0, 0, 0, 0, 0, 16000000, 0),
LGM_DIV(LGM_CLK_DCL, "dcl", "v_ifclk", 0, CGU_PCMCR,
25, 3, 0, 0, 0, 0, dcl_div),
LGM_MUX(LGM_CLK_PCM, "pcm", pcm_p, 0, CGU_C55_PCMCR,
0, 1, CLK_MUX_ROUND_CLOSEST, 0),
LGM_FIXED_FACTOR(LGM_CLK_DDR_PHY, "ddr_phy", "ddr",
CLK_IGNORE_UNUSED, 0,
0, 0, 0, 0, 2, 1),
LGM_FIXED_FACTOR(LGM_CLK_PONDEF, "pondef", "dd_pool",
CLK_SET_RATE_PARENT, 0, 0, 0, 0, 0, 1, 2),
LGM_MUX(LGM_CLK_CBPHY0, "cbphy0", cbphy_p, 0, 0,
0, 0, MUX_CLK_SW | CLK_MUX_ROUND_CLOSEST, 0),
LGM_MUX(LGM_CLK_CBPHY1, "cbphy1", cbphy_p, 0, 0,
0, 0, MUX_CLK_SW | CLK_MUX_ROUND_CLOSEST, 0),
LGM_MUX(LGM_CLK_CBPHY2, "cbphy2", cbphy_p, 0, 0,
0, 0, MUX_CLK_SW | CLK_MUX_ROUND_CLOSEST, 0),
LGM_MUX(LGM_CLK_CBPHY3, "cbphy3", cbphy_p, 0, 0,
0, 0, MUX_CLK_SW | CLK_MUX_ROUND_CLOSEST, 0),
LGM_GATE(LGM_GCLK_C55, "g_c55", NULL, 0, CGU_GATE0,
G_C55_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_QSPI, "g_qspi", "qspi", 0, CGU_GATE0,
G_QSPI_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_EIP197, "g_eip197", NULL, 0, CGU_GATE0,
G_EIP197_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_VAULT, "g_vault130", NULL, 0, CGU_GATE0,
G_VAULT130_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_TOE, "g_toe", NULL, 0, CGU_GATE0,
G_TOE_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SDXC, "g_sdxc", "sdxc", 0, CGU_GATE0,
G_SDXC_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_EMMC, "g_emmc", "emmc", 0, CGU_GATE0,
G_EMMC_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SPI_DBG, "g_spidbg", NULL, 0, CGU_GATE0,
G_SPIDBG_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_DMA3, "g_dma3", NULL, 0, CGU_GATE0,
G_DMA3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_DMA0, "g_dma0", NULL, 0, CGU_GATE1,
G_DMA0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_LEDC0, "g_ledc0", NULL, 0, CGU_GATE1,
G_LEDC0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_LEDC1, "g_ledc1", NULL, 0, CGU_GATE1,
G_LEDC1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_I2S0, "g_i2s0", NULL, 0, CGU_GATE1,
G_I2S0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_I2S1, "g_i2s1", NULL, 0, CGU_GATE1,
G_I2S1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_EBU, "g_ebu", NULL, 0, CGU_GATE1,
G_EBU_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PWM, "g_pwm", NULL, 0, CGU_GATE1,
G_PWM_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_I2C0, "g_i2c0", NULL, 0, CGU_GATE1,
G_I2C0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_I2C1, "g_i2c1", NULL, 0, CGU_GATE1,
G_I2C1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_I2C2, "g_i2c2", NULL, 0, CGU_GATE1,
G_I2C2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_I2C3, "g_i2c3", NULL, 0, CGU_GATE1,
G_I2C3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SSC0, "g_ssc0", "noc4", 0, CGU_GATE1,
G_SSC0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SSC1, "g_ssc1", "noc4", 0, CGU_GATE1,
G_SSC1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SSC2, "g_ssc2", "noc4", 0, CGU_GATE1,
G_SSC2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SSC3, "g_ssc3", "noc4", 0, CGU_GATE1,
G_SSC3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_GPTC0, "g_gptc0", "noc4", 0, CGU_GATE1,
G_GPTC0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_GPTC1, "g_gptc1", "noc4", 0, CGU_GATE1,
G_GPTC1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_GPTC2, "g_gptc2", "noc4", 0, CGU_GATE1,
G_GPTC2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_GPTC3, "g_gptc3", "osc", 0, CGU_GATE1,
G_GPTC3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_ASC0, "g_asc0", "noc4", 0, CGU_GATE1,
G_ASC0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_ASC1, "g_asc1", "noc4", 0, CGU_GATE1,
G_ASC1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_ASC2, "g_asc2", "noc4", 0, CGU_GATE1,
G_ASC2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_ASC3, "g_asc3", "osc", 0, CGU_GATE1,
G_ASC3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCM0, "g_pcm0", NULL, 0, CGU_GATE1,
G_PCM0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCM1, "g_pcm1", NULL, 0, CGU_GATE1,
G_PCM1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCM2, "g_pcm2", NULL, 0, CGU_GATE1,
G_PCM2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE10, "g_pcie10", NULL, 0, CGU_GATE2,
G_PCIE10_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE11, "g_pcie11", NULL, 0, CGU_GATE2,
G_PCIE11_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE30, "g_pcie30", NULL, 0, CGU_GATE2,
G_PCIE30_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE31, "g_pcie31", NULL, 0, CGU_GATE2,
G_PCIE31_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE20, "g_pcie20", NULL, 0, CGU_GATE2,
G_PCIE20_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE21, "g_pcie21", NULL, 0, CGU_GATE2,
G_PCIE21_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE40, "g_pcie40", NULL, 0, CGU_GATE2,
G_PCIE40_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PCIE41, "g_pcie41", NULL, 0, CGU_GATE2,
G_PCIE41_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_XPCS0, "g_xpcs0", NULL, 0, CGU_GATE2,
G_XPCS0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_XPCS1, "g_xpcs1", NULL, 0, CGU_GATE2,
G_XPCS1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_XPCS2, "g_xpcs2", NULL, 0, CGU_GATE2,
G_XPCS2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_XPCS3, "g_xpcs3", NULL, 0, CGU_GATE2,
G_XPCS3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SATA0, "g_sata0", NULL, 0, CGU_GATE2,
G_SATA0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SATA1, "g_sata1", NULL, 0, CGU_GATE2,
G_SATA1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SATA2, "g_sata2", NULL, 0, CGU_GATE2,
G_SATA2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_SATA3, "g_sata3", NULL, 0, CGU_GATE2,
G_SATA3_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_ARCEM4, "g_arcem4", NULL, 0, CGU_GATE3,
G_ARCEM4_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_IDMAR1, "g_idmar1", NULL, 0, CGU_GATE3,
G_IDMAR1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_IDMAT0, "g_idmat0", NULL, 0, CGU_GATE3,
G_IDMAT0_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_IDMAT1, "g_idmat1", NULL, 0, CGU_GATE3,
G_IDMAT1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_IDMAT2, "g_idmat2", NULL, 0, CGU_GATE3,
G_IDMAT2_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_PPV4, "g_ppv4", NULL, 0, CGU_GATE3,
G_PPV4_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_GSWIPO, "g_gswipo", "switch", 0, CGU_GATE3,
G_GSWIPO_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_CQEM, "g_cqem", "switch", 0, CGU_GATE3,
G_CQEM_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_XPCS5, "g_xpcs5", NULL, 0, CGU_GATE3,
G_XPCS5_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_USB1, "g_usb1", NULL, 0, CGU_GATE3,
G_USB1_SHIFT, 0, 0),
LGM_GATE(LGM_GCLK_USB2, "g_usb2", NULL, 0, CGU_GATE3,
G_USB2_SHIFT, 0, 0),
};
static const struct lgm_clk_ddiv_data lgm_ddiv_clks[] = {
LGM_DDIV(LGM_CLK_CML, "dd_cml", "ljpll3", 0,
PLL_DIV(CGU_LJPLL3_CFG0), 0, PLL_DDIV_WIDTH,
3, PLL_DDIV_WIDTH, 24, 1, 29, 0),
LGM_DDIV(LGM_CLK_SERDES, "dd_serdes", "ljpll3", 0,
PLL_DIV(CGU_LJPLL3_CFG0), 6, PLL_DDIV_WIDTH,
9, PLL_DDIV_WIDTH, 25, 1, 28, 0),
LGM_DDIV(LGM_CLK_POOL, "dd_pool", "ljpll3", 0,
PLL_DIV(CGU_LJPLL3_CFG0), 12, PLL_DDIV_WIDTH,
15, PLL_DDIV_WIDTH, 26, 1, 28, 0),
LGM_DDIV(LGM_CLK_PTP, "dd_ptp", "ljpll3", 0,
PLL_DIV(CGU_LJPLL3_CFG0), 18, PLL_DDIV_WIDTH,
21, PLL_DDIV_WIDTH, 27, 1, 28, 0),
LGM_DDIV(LGM_CLK_PCIE, "dd_pcie", "ljpll4", 0,
PLL_DIV(CGU_LJPLL4_CFG0), 0, PLL_DDIV_WIDTH,
3, PLL_DDIV_WIDTH, 24, 1, 29, 0),
};
static int lgm_cgu_probe(struct platform_device *pdev)
{
struct lgm_clk_provider *ctx;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int ret;
ctx = devm_kzalloc(dev, struct_size(ctx, clk_data.hws, CLK_NR_CLKS),
GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->clk_data.num = CLK_NR_CLKS;
ctx->membase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctx->membase))
return PTR_ERR(ctx->membase);
ctx->np = np;
ctx->dev = dev;
spin_lock_init(&ctx->lock);
ret = lgm_clk_register_plls(ctx, lgm_pll_clks,
ARRAY_SIZE(lgm_pll_clks));
if (ret)
return ret;
ret = lgm_clk_register_branches(ctx, lgm_branch_clks,
ARRAY_SIZE(lgm_branch_clks));
if (ret)
return ret;
ret = lgm_clk_register_ddiv(ctx, lgm_ddiv_clks,
ARRAY_SIZE(lgm_ddiv_clks));
if (ret)
return ret;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
&ctx->clk_data);
}
static const struct of_device_id of_lgm_cgu_match[] = {
{ .compatible = "intel,cgu-lgm" },
{}
};
static struct platform_driver lgm_cgu_driver = {
.probe = lgm_cgu_probe,
.driver = {
.name = "cgu-lgm",
.of_match_table = of_lgm_cgu_match,
},
};
builtin_platform_driver(lgm_cgu_driver);
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (C) 2020 Intel Corporation.
* Lei Chuanhua <Chuanhua.lei@intel.com>
* Zhu Yixin <Yixin.zhu@intel.com>
*/
#ifndef __INTEL_LGM_CLK_H
#define __INTEL_LGM_CLK_H
/* PLL clocks */
#define LGM_CLK_OSC 1
#define LGM_CLK_PLLPP 2
#define LGM_CLK_PLL2 3
#define LGM_CLK_PLL0CZ 4
#define LGM_CLK_PLL0B 5
#define LGM_CLK_PLL1 6
#define LGM_CLK_LJPLL3 7
#define LGM_CLK_LJPLL4 8
#define LGM_CLK_PLL0CM0 9
#define LGM_CLK_PLL0CM1 10
/* clocks from PLLs */
/* ROPLL clocks */
#define LGM_CLK_PP_HW 15
#define LGM_CLK_PP_UC 16
#define LGM_CLK_PP_FXD 17
#define LGM_CLK_PP_TBM 18
/* PLL2 clocks */
#define LGM_CLK_DDR 20
/* PLL0CZ */
#define LGM_CLK_CM 25
#define LGM_CLK_IC 26
#define LGM_CLK_SDXC3 27
/* PLL0B */
#define LGM_CLK_NGI 30
#define LGM_CLK_NOC4 31
#define LGM_CLK_SW 32
#define LGM_CLK_QSPI 33
#define LGM_CLK_CQEM LGM_CLK_SW
#define LGM_CLK_EMMC5 LGM_CLK_NOC4
/* PLL1 */
#define LGM_CLK_CT 35
#define LGM_CLK_DSP 36
#define LGM_CLK_VIF 37
/* LJPLL3 */
#define LGM_CLK_CML 40
#define LGM_CLK_SERDES 41
#define LGM_CLK_POOL 42
#define LGM_CLK_PTP 43
/* LJPLL4 */
#define LGM_CLK_PCIE 45
#define LGM_CLK_SATA LGM_CLK_PCIE
/* PLL0CM0 */
#define LGM_CLK_CPU0 50
/* PLL0CM1 */
#define LGM_CLK_CPU1 55
/* Miscellaneous clocks */
#define LGM_CLK_EMMC4 60
#define LGM_CLK_SDXC2 61
#define LGM_CLK_EMMC 62
#define LGM_CLK_SDXC 63
#define LGM_CLK_SLIC 64
#define LGM_CLK_DCL 65
#define LGM_CLK_DOCSIS 66
#define LGM_CLK_PCM 67
#define LGM_CLK_DDR_PHY 68
#define LGM_CLK_PONDEF 69
#define LGM_CLK_PL25M 70
#define LGM_CLK_PL10M 71
#define LGM_CLK_PL1544K 72
#define LGM_CLK_PL2048K 73
#define LGM_CLK_PL8K 74
#define LGM_CLK_PON_NTR 75
#define LGM_CLK_SYNC0 76
#define LGM_CLK_SYNC1 77
#define LGM_CLK_PROGDIV 78
#define LGM_CLK_OD0 79
#define LGM_CLK_OD1 80
#define LGM_CLK_CBPHY0 81
#define LGM_CLK_CBPHY1 82
#define LGM_CLK_CBPHY2 83
#define LGM_CLK_CBPHY3 84
/* Gate clocks */
/* Gate CLK0 */
#define LGM_GCLK_C55 100
#define LGM_GCLK_QSPI 101
#define LGM_GCLK_EIP197 102
#define LGM_GCLK_VAULT 103
#define LGM_GCLK_TOE 104
#define LGM_GCLK_SDXC 105
#define LGM_GCLK_EMMC 106
#define LGM_GCLK_SPI_DBG 107
#define LGM_GCLK_DMA3 108
/* Gate CLK1 */
#define LGM_GCLK_DMA0 120
#define LGM_GCLK_LEDC0 121
#define LGM_GCLK_LEDC1 122
#define LGM_GCLK_I2S0 123
#define LGM_GCLK_I2S1 124
#define LGM_GCLK_EBU 125
#define LGM_GCLK_PWM 126
#define LGM_GCLK_I2C0 127
#define LGM_GCLK_I2C1 128
#define LGM_GCLK_I2C2 129
#define LGM_GCLK_I2C3 130
#define LGM_GCLK_SSC0 131
#define LGM_GCLK_SSC1 132
#define LGM_GCLK_SSC2 133
#define LGM_GCLK_SSC3 134
#define LGM_GCLK_GPTC0 135
#define LGM_GCLK_GPTC1 136
#define LGM_GCLK_GPTC2 137
#define LGM_GCLK_GPTC3 138
#define LGM_GCLK_ASC0 139
#define LGM_GCLK_ASC1 140
#define LGM_GCLK_ASC2 141
#define LGM_GCLK_ASC3 142
#define LGM_GCLK_PCM0 143
#define LGM_GCLK_PCM1 144
#define LGM_GCLK_PCM2 145
/* Gate CLK2 */
#define LGM_GCLK_PCIE10 150
#define LGM_GCLK_PCIE11 151
#define LGM_GCLK_PCIE30 152
#define LGM_GCLK_PCIE31 153
#define LGM_GCLK_PCIE20 154
#define LGM_GCLK_PCIE21 155
#define LGM_GCLK_PCIE40 156
#define LGM_GCLK_PCIE41 157
#define LGM_GCLK_XPCS0 158
#define LGM_GCLK_XPCS1 159
#define LGM_GCLK_XPCS2 160
#define LGM_GCLK_XPCS3 161
#define LGM_GCLK_SATA0 162
#define LGM_GCLK_SATA1 163
#define LGM_GCLK_SATA2 164
#define LGM_GCLK_SATA3 165
/* Gate CLK3 */
#define LGM_GCLK_ARCEM4 170
#define LGM_GCLK_IDMAR1 171
#define LGM_GCLK_IDMAT0 172
#define LGM_GCLK_IDMAT1 173
#define LGM_GCLK_IDMAT2 174
#define LGM_GCLK_PPV4 175
#define LGM_GCLK_GSWIPO 176
#define LGM_GCLK_CQEM 177
#define LGM_GCLK_XPCS5 178
#define LGM_GCLK_USB1 179
#define LGM_GCLK_USB2 180
#endif /* __INTEL_LGM_CLK_H */
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) */
#ifndef __DT_BINDINGS_CLOCK_MARVELL_MMP2_AUDIO_H
#define __DT_BINDINGS_CLOCK_MARVELL_MMP2_AUDIO_H
#define MMP2_CLK_AUDIO_SYSCLK 0
#define MMP2_CLK_AUDIO_SSPA0 1
#define MMP2_CLK_AUDIO_SSPA1 2
#define MMP2_CLK_AUDIO_NR_CLKS 3
#endif
......@@ -29,6 +29,8 @@
#define MMP3_CLK_PLL1_P 28
#define MMP3_CLK_PLL2_P 29
#define MMP3_CLK_PLL3 30
#define MMP2_CLK_I2S0 31
#define MMP2_CLK_I2S1 32
/* apb periphrals */
#define MMP2_CLK_TWSI0 60
......@@ -87,6 +89,7 @@
#define MMP3_CLK_GPU_3D MMP2_CLK_GPU_3D
#define MMP3_CLK_GPU_2D 125
#define MMP3_CLK_SDH4 126
#define MMP2_CLK_AUDIO 127
#define MMP2_NR_CLKS 200
#endif
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2020 Linaro Limited
*/
#ifndef _DT_BINDINGS_CLK_MSM_GCC_8939_H
#define _DT_BINDINGS_CLK_MSM_GCC_8939_H
#define GPLL0 0
#define GPLL0_VOTE 1
#define BIMC_PLL 2
#define BIMC_PLL_VOTE 3
#define GPLL1 4
#define GPLL1_VOTE 5
#define GPLL2 6
#define GPLL2_VOTE 7
#define PCNOC_BFDCD_CLK_SRC 8
#define SYSTEM_NOC_BFDCD_CLK_SRC 9
#define CAMSS_AHB_CLK_SRC 10
#define APSS_AHB_CLK_SRC 11
#define CSI0_CLK_SRC 12
#define CSI1_CLK_SRC 13
#define GFX3D_CLK_SRC 14
#define VFE0_CLK_SRC 15
#define BLSP1_QUP1_I2C_APPS_CLK_SRC 16
#define BLSP1_QUP1_SPI_APPS_CLK_SRC 17
#define BLSP1_QUP2_I2C_APPS_CLK_SRC 18
#define BLSP1_QUP2_SPI_APPS_CLK_SRC 19
#define BLSP1_QUP3_I2C_APPS_CLK_SRC 20
#define BLSP1_QUP3_SPI_APPS_CLK_SRC 21
#define BLSP1_QUP4_I2C_APPS_CLK_SRC 22
#define BLSP1_QUP4_SPI_APPS_CLK_SRC 23
#define BLSP1_QUP5_I2C_APPS_CLK_SRC 24
#define BLSP1_QUP5_SPI_APPS_CLK_SRC 25
#define BLSP1_QUP6_I2C_APPS_CLK_SRC 26
#define BLSP1_QUP6_SPI_APPS_CLK_SRC 27
#define BLSP1_UART1_APPS_CLK_SRC 28
#define BLSP1_UART2_APPS_CLK_SRC 29
#define CCI_CLK_SRC 30
#define CAMSS_GP0_CLK_SRC 31
#define CAMSS_GP1_CLK_SRC 32
#define JPEG0_CLK_SRC 33
#define MCLK0_CLK_SRC 34
#define MCLK1_CLK_SRC 35
#define CSI0PHYTIMER_CLK_SRC 36
#define CSI1PHYTIMER_CLK_SRC 37
#define CPP_CLK_SRC 38
#define CRYPTO_CLK_SRC 39
#define GP1_CLK_SRC 40
#define GP2_CLK_SRC 41
#define GP3_CLK_SRC 42
#define BYTE0_CLK_SRC 43
#define ESC0_CLK_SRC 44
#define MDP_CLK_SRC 45
#define PCLK0_CLK_SRC 46
#define VSYNC_CLK_SRC 47
#define PDM2_CLK_SRC 48
#define SDCC1_APPS_CLK_SRC 49
#define SDCC2_APPS_CLK_SRC 50
#define APSS_TCU_CLK_SRC 51
#define USB_HS_SYSTEM_CLK_SRC 52
#define VCODEC0_CLK_SRC 53
#define GCC_BLSP1_AHB_CLK 54
#define GCC_BLSP1_SLEEP_CLK 55
#define GCC_BLSP1_QUP1_I2C_APPS_CLK 56
#define GCC_BLSP1_QUP1_SPI_APPS_CLK 57
#define GCC_BLSP1_QUP2_I2C_APPS_CLK 58
#define GCC_BLSP1_QUP2_SPI_APPS_CLK 59
#define GCC_BLSP1_QUP3_I2C_APPS_CLK 60
#define GCC_BLSP1_QUP3_SPI_APPS_CLK 61
#define GCC_BLSP1_QUP4_I2C_APPS_CLK 62
#define GCC_BLSP1_QUP4_SPI_APPS_CLK 63
#define GCC_BLSP1_QUP5_I2C_APPS_CLK 64
#define GCC_BLSP1_QUP5_SPI_APPS_CLK 65
#define GCC_BLSP1_QUP6_I2C_APPS_CLK 66
#define GCC_BLSP1_QUP6_SPI_APPS_CLK 67
#define GCC_BLSP1_UART1_APPS_CLK 68
#define GCC_BLSP1_UART2_APPS_CLK 69
#define GCC_BOOT_ROM_AHB_CLK 70
#define GCC_CAMSS_CCI_AHB_CLK 71
#define GCC_CAMSS_CCI_CLK 72
#define GCC_CAMSS_CSI0_AHB_CLK 73
#define GCC_CAMSS_CSI0_CLK 74
#define GCC_CAMSS_CSI0PHY_CLK 75
#define GCC_CAMSS_CSI0PIX_CLK 76
#define GCC_CAMSS_CSI0RDI_CLK 77
#define GCC_CAMSS_CSI1_AHB_CLK 78
#define GCC_CAMSS_CSI1_CLK 79
#define GCC_CAMSS_CSI1PHY_CLK 80
#define GCC_CAMSS_CSI1PIX_CLK 81
#define GCC_CAMSS_CSI1RDI_CLK 82
#define GCC_CAMSS_CSI_VFE0_CLK 83
#define GCC_CAMSS_GP0_CLK 84
#define GCC_CAMSS_GP1_CLK 85
#define GCC_CAMSS_ISPIF_AHB_CLK 86
#define GCC_CAMSS_JPEG0_CLK 87
#define GCC_CAMSS_JPEG_AHB_CLK 88
#define GCC_CAMSS_JPEG_AXI_CLK 89
#define GCC_CAMSS_MCLK0_CLK 90
#define GCC_CAMSS_MCLK1_CLK 91
#define GCC_CAMSS_MICRO_AHB_CLK 92
#define GCC_CAMSS_CSI0PHYTIMER_CLK 93
#define GCC_CAMSS_CSI1PHYTIMER_CLK 94
#define GCC_CAMSS_AHB_CLK 95
#define GCC_CAMSS_TOP_AHB_CLK 96
#define GCC_CAMSS_CPP_AHB_CLK 97
#define GCC_CAMSS_CPP_CLK 98
#define GCC_CAMSS_VFE0_CLK 99
#define GCC_CAMSS_VFE_AHB_CLK 100
#define GCC_CAMSS_VFE_AXI_CLK 101
#define GCC_CRYPTO_AHB_CLK 102
#define GCC_CRYPTO_AXI_CLK 103
#define GCC_CRYPTO_CLK 104
#define GCC_OXILI_GMEM_CLK 105
#define GCC_GP1_CLK 106
#define GCC_GP2_CLK 107
#define GCC_GP3_CLK 108
#define GCC_MDSS_AHB_CLK 109
#define GCC_MDSS_AXI_CLK 110
#define GCC_MDSS_BYTE0_CLK 111
#define GCC_MDSS_ESC0_CLK 112
#define GCC_MDSS_MDP_CLK 113
#define GCC_MDSS_PCLK0_CLK 114
#define GCC_MDSS_VSYNC_CLK 115
#define GCC_MSS_CFG_AHB_CLK 116
#define GCC_OXILI_AHB_CLK 117
#define GCC_OXILI_GFX3D_CLK 118
#define GCC_PDM2_CLK 119
#define GCC_PDM_AHB_CLK 120
#define GCC_PRNG_AHB_CLK 121
#define GCC_SDCC1_AHB_CLK 122
#define GCC_SDCC1_APPS_CLK 123
#define GCC_SDCC2_AHB_CLK 124
#define GCC_SDCC2_APPS_CLK 125
#define GCC_GTCU_AHB_CLK 126
#define GCC_JPEG_TBU_CLK 127
#define GCC_MDP_TBU_CLK 128
#define GCC_SMMU_CFG_CLK 129
#define GCC_VENUS_TBU_CLK 130
#define GCC_VFE_TBU_CLK 131
#define GCC_USB2A_PHY_SLEEP_CLK 132
#define GCC_USB_HS_AHB_CLK 133
#define GCC_USB_HS_SYSTEM_CLK 134
#define GCC_VENUS0_AHB_CLK 135
#define GCC_VENUS0_AXI_CLK 136
#define GCC_VENUS0_VCODEC0_CLK 137
#define BIMC_DDR_CLK_SRC 138
#define GCC_APSS_TCU_CLK 139
#define GCC_GFX_TCU_CLK 140
#define BIMC_GPU_CLK_SRC 141
#define GCC_BIMC_GFX_CLK 142
#define GCC_BIMC_GPU_CLK 143
#define ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC 144
#define ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC 145
#define ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC 146
#define ULTAUDIO_XO_CLK_SRC 147
#define ULTAUDIO_AHBFABRIC_CLK_SRC 148
#define CODEC_DIGCODEC_CLK_SRC 149
#define GCC_ULTAUDIO_PCNOC_MPORT_CLK 150
#define GCC_ULTAUDIO_PCNOC_SWAY_CLK 151
#define GCC_ULTAUDIO_AVSYNC_XO_CLK 152
#define GCC_ULTAUDIO_STC_XO_CLK 153
#define GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK 154
#define GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK 155
#define GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK 156
#define GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK 157
#define GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK 158
#define GCC_CODEC_DIGCODEC_CLK 159
#define GCC_MSS_Q6_BIMC_AXI_CLK 160
#define GPLL3 161
#define GPLL3_VOTE 162
#define GPLL4 163
#define GPLL4_VOTE 164
#define GPLL5 165
#define GPLL5_VOTE 166
#define GPLL6 167
#define GPLL6_VOTE 168
#define BYTE1_CLK_SRC 169
#define GCC_MDSS_BYTE1_CLK 170
#define ESC1_CLK_SRC 171
#define GCC_MDSS_ESC1_CLK 172
#define PCLK1_CLK_SRC 173
#define GCC_MDSS_PCLK1_CLK 174
#define GCC_GFX_TBU_CLK 175
#define GCC_CPP_TBU_CLK 176
#define GCC_MDP_RT_TBU_CLK 177
#define USB_FS_SYSTEM_CLK_SRC 178
#define USB_FS_IC_CLK_SRC 179
#define GCC_USB_FS_AHB_CLK 180
#define GCC_USB_FS_IC_CLK 181
#define GCC_USB_FS_SYSTEM_CLK 182
#define GCC_VENUS0_CORE0_VCODEC0_CLK 183
#define GCC_VENUS0_CORE1_VCODEC0_CLK 184
#define GCC_OXILI_TIMER_CLK 185
/* Indexes for GDSCs */
#define BIMC_GDSC 0
#define VENUS_GDSC 1
#define MDSS_GDSC 2
#define JPEG_GDSC 3
#define VFE_GDSC 4
#define OXILI_GDSC 5
#define VENUS_CORE0_GDSC 6
#define VENUS_CORE1_GDSC 7
#endif
......@@ -183,6 +183,7 @@
#define GCC_MSS_SNOC_AXI_CLK 174
#define GCC_MSS_MNOC_BIMC_AXI_CLK 175
#define GCC_BIMC_GFX_CLK 176
#define UFS_UNIPRO_CORE_CLK_SRC 177
#define PCIE_0_GDSC 0
#define UFS_GDSC 1
......
......@@ -137,6 +137,7 @@
#define GCC_MSS_NAV_AXI_CLK 127
#define GCC_MSS_Q6_MEMNOC_AXI_CLK 128
#define GCC_MSS_SNOC_AXI_CLK 129
#define GCC_SEC_CTRL_CLK_SRC 130
/* GCC resets */
#define GCC_QUSB2PHY_PRIM_BCR 0
......
......@@ -12,33 +12,41 @@
#ifndef __DT_BINDINGS_CLOCK_X1000_CGU_H__
#define __DT_BINDINGS_CLOCK_X1000_CGU_H__
#define X1000_CLK_EXCLK 0
#define X1000_CLK_RTCLK 1
#define X1000_CLK_APLL 2
#define X1000_CLK_MPLL 3
#define X1000_CLK_SCLKA 4
#define X1000_CLK_CPUMUX 5
#define X1000_CLK_CPU 6
#define X1000_CLK_L2CACHE 7
#define X1000_CLK_AHB0 8
#define X1000_CLK_AHB2PMUX 9
#define X1000_CLK_AHB2 10
#define X1000_CLK_PCLK 11
#define X1000_CLK_DDR 12
#define X1000_CLK_MAC 13
#define X1000_CLK_MSCMUX 14
#define X1000_CLK_MSC0 15
#define X1000_CLK_MSC1 16
#define X1000_CLK_SSIPLL 17
#define X1000_CLK_SSIMUX 18
#define X1000_CLK_SFC 19
#define X1000_CLK_I2C0 20
#define X1000_CLK_I2C1 21
#define X1000_CLK_I2C2 22
#define X1000_CLK_UART0 23
#define X1000_CLK_UART1 24
#define X1000_CLK_UART2 25
#define X1000_CLK_SSI 26
#define X1000_CLK_PDMA 27
#define X1000_CLK_EXCLK 0
#define X1000_CLK_RTCLK 1
#define X1000_CLK_APLL 2
#define X1000_CLK_MPLL 3
#define X1000_CLK_OTGPHY 4
#define X1000_CLK_SCLKA 5
#define X1000_CLK_CPUMUX 6
#define X1000_CLK_CPU 7
#define X1000_CLK_L2CACHE 8
#define X1000_CLK_AHB0 9
#define X1000_CLK_AHB2PMUX 10
#define X1000_CLK_AHB2 11
#define X1000_CLK_PCLK 12
#define X1000_CLK_DDR 13
#define X1000_CLK_MAC 14
#define X1000_CLK_LCD 15
#define X1000_CLK_MSCMUX 16
#define X1000_CLK_MSC0 17
#define X1000_CLK_MSC1 18
#define X1000_CLK_OTG 19
#define X1000_CLK_SSIPLL 20
#define X1000_CLK_SSIPLL_DIV2 21
#define X1000_CLK_SSIMUX 22
#define X1000_CLK_EMC 23
#define X1000_CLK_EFUSE 24
#define X1000_CLK_SFC 25
#define X1000_CLK_I2C0 26
#define X1000_CLK_I2C1 27
#define X1000_CLK_I2C2 28
#define X1000_CLK_UART0 29
#define X1000_CLK_UART1 30
#define X1000_CLK_UART2 31
#define X1000_CLK_TCU 32
#define X1000_CLK_SSI 33
#define X1000_CLK_OST 34
#define X1000_CLK_PDMA 35
#endif /* __DT_BINDINGS_CLOCK_X1000_CGU_H__ */
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This header provides clock numbers for the ingenic,x1830-cgu DT binding.
*
* They are roughly ordered as:
* - external clocks
* - PLLs
* - muxes/dividers in the order they appear in the x1830 programmers manual
* - gates in order of their bit in the CLKGR* registers
*/
#ifndef __DT_BINDINGS_CLOCK_X1830_CGU_H__
#define __DT_BINDINGS_CLOCK_X1830_CGU_H__
#define X1830_CLK_EXCLK 0
#define X1830_CLK_RTCLK 1
#define X1830_CLK_APLL 2
#define X1830_CLK_MPLL 3
#define X1830_CLK_EPLL 4
#define X1830_CLK_VPLL 5
#define X1830_CLK_OTGPHY 6
#define X1830_CLK_SCLKA 7
#define X1830_CLK_CPUMUX 8
#define X1830_CLK_CPU 9
#define X1830_CLK_L2CACHE 10
#define X1830_CLK_AHB0 11
#define X1830_CLK_AHB2PMUX 12
#define X1830_CLK_AHB2 13
#define X1830_CLK_PCLK 14
#define X1830_CLK_DDR 15
#define X1830_CLK_MAC 16
#define X1830_CLK_LCD 17
#define X1830_CLK_MSCMUX 18
#define X1830_CLK_MSC0 19
#define X1830_CLK_MSC1 20
#define X1830_CLK_SSIPLL 21
#define X1830_CLK_SSIPLL_DIV2 22
#define X1830_CLK_SSIMUX 23
#define X1830_CLK_EMC 24
#define X1830_CLK_EFUSE 25
#define X1830_CLK_OTG 26
#define X1830_CLK_SSI0 27
#define X1830_CLK_SMB0 28
#define X1830_CLK_SMB1 29
#define X1830_CLK_SMB2 30
#define X1830_CLK_UART0 31
#define X1830_CLK_UART1 32
#define X1830_CLK_SSI1 33
#define X1830_CLK_SFC 34
#define X1830_CLK_PDMA 35
#define X1830_CLK_TCU 36
#define X1830_CLK_DTRNG 37
#define X1830_CLK_OST 38
#endif /* __DT_BINDINGS_CLOCK_X1830_CGU_H__ */
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DTS_MARVELL_MMP2_POWER_H
#define __DTS_MARVELL_MMP2_POWER_H
#define MMP2_POWER_DOMAIN_GPU 0
#define MMP2_POWER_DOMAIN_AUDIO 1
#define MMP3_POWER_DOMAIN_CAMERA 2
#define MMP2_NR_POWER_DOMAINS 3
#endif
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2020 Linaro Limited
*/
#ifndef _DT_BINDINGS_RESET_MSM_GCC_8939_H
#define _DT_BINDINGS_RESET_MSM_GCC_8939_H
#define GCC_BLSP1_BCR 0
#define GCC_BLSP1_QUP1_BCR 1
#define GCC_BLSP1_UART1_BCR 2
#define GCC_BLSP1_QUP2_BCR 3
#define GCC_BLSP1_UART2_BCR 4
#define GCC_BLSP1_QUP3_BCR 5
#define GCC_BLSP1_QUP4_BCR 6
#define GCC_BLSP1_QUP5_BCR 7
#define GCC_BLSP1_QUP6_BCR 8
#define GCC_IMEM_BCR 9
#define GCC_SMMU_BCR 10
#define GCC_APSS_TCU_BCR 11
#define GCC_SMMU_XPU_BCR 12
#define GCC_PCNOC_TBU_BCR 13
#define GCC_PRNG_BCR 14
#define GCC_BOOT_ROM_BCR 15
#define GCC_CRYPTO_BCR 16
#define GCC_SEC_CTRL_BCR 17
#define GCC_AUDIO_CORE_BCR 18
#define GCC_ULT_AUDIO_BCR 19
#define GCC_DEHR_BCR 20
#define GCC_SYSTEM_NOC_BCR 21
#define GCC_PCNOC_BCR 22
#define GCC_TCSR_BCR 23
#define GCC_QDSS_BCR 24
#define GCC_DCD_BCR 25
#define GCC_MSG_RAM_BCR 26
#define GCC_MPM_BCR 27
#define GCC_SPMI_BCR 28
#define GCC_SPDM_BCR 29
#define GCC_MM_SPDM_BCR 30
#define GCC_BIMC_BCR 31
#define GCC_RBCPR_BCR 32
#define GCC_TLMM_BCR 33
#define GCC_USB_HS_BCR 34
#define GCC_USB2A_PHY_BCR 35
#define GCC_SDCC1_BCR 36
#define GCC_SDCC2_BCR 37
#define GCC_PDM_BCR 38
#define GCC_SNOC_BUS_TIMEOUT0_BCR 39
#define GCC_PCNOC_BUS_TIMEOUT0_BCR 40
#define GCC_PCNOC_BUS_TIMEOUT1_BCR 41
#define GCC_PCNOC_BUS_TIMEOUT2_BCR 42
#define GCC_PCNOC_BUS_TIMEOUT3_BCR 43
#define GCC_PCNOC_BUS_TIMEOUT4_BCR 44
#define GCC_PCNOC_BUS_TIMEOUT5_BCR 45
#define GCC_PCNOC_BUS_TIMEOUT6_BCR 46
#define GCC_PCNOC_BUS_TIMEOUT7_BCR 47
#define GCC_PCNOC_BUS_TIMEOUT8_BCR 48
#define GCC_PCNOC_BUS_TIMEOUT9_BCR 49
#define GCC_MMSS_BCR 50
#define GCC_VENUS0_BCR 51
#define GCC_MDSS_BCR 52
#define GCC_CAMSS_PHY0_BCR 53
#define GCC_CAMSS_CSI0_BCR 54
#define GCC_CAMSS_CSI0PHY_BCR 55
#define GCC_CAMSS_CSI0RDI_BCR 56
#define GCC_CAMSS_CSI0PIX_BCR 57
#define GCC_CAMSS_PHY1_BCR 58
#define GCC_CAMSS_CSI1_BCR 59
#define GCC_CAMSS_CSI1PHY_BCR 60
#define GCC_CAMSS_CSI1RDI_BCR 61
#define GCC_CAMSS_CSI1PIX_BCR 62
#define GCC_CAMSS_ISPIF_BCR 63
#define GCC_CAMSS_CCI_BCR 64
#define GCC_CAMSS_MCLK0_BCR 65
#define GCC_CAMSS_MCLK1_BCR 66
#define GCC_CAMSS_GP0_BCR 67
#define GCC_CAMSS_GP1_BCR 68
#define GCC_CAMSS_TOP_BCR 69
#define GCC_CAMSS_MICRO_BCR 70
#define GCC_CAMSS_JPEG_BCR 71
#define GCC_CAMSS_VFE_BCR 72
#define GCC_CAMSS_CSI_VFE0_BCR 73
#define GCC_OXILI_BCR 74
#define GCC_GMEM_BCR 75
#define GCC_CAMSS_AHB_BCR 76
#define GCC_MDP_TBU_BCR 77
#define GCC_GFX_TBU_BCR 78
#define GCC_GFX_TCU_BCR 79
#define GCC_MSS_TBU_AXI_BCR 80
#define GCC_MSS_TBU_GSS_AXI_BCR 81
#define GCC_MSS_TBU_Q6_AXI_BCR 82
#define GCC_GTCU_AHB_BCR 83
#define GCC_SMMU_CFG_BCR 84
#define GCC_VFE_TBU_BCR 85
#define GCC_VENUS_TBU_BCR 86
#define GCC_JPEG_TBU_BCR 87
#define GCC_PRONTO_TBU_BCR 88
#define GCC_SMMU_CATS_BCR 89
#define GCC_BLSP1_UART3_BCR 90
#define GCC_CAMSS_CSI2_BCR 91
#define GCC_CAMSS_CSI2PHY_BCR 92
#define GCC_CAMSS_CSI2RDI_BCR 93
#define GCC_CAMSS_CSI2PIX_BCR 94
#define GCC_USB_FS_BCR 95
#define GCC_BLSP1_QUP4_SPI_APPS_CBCR 96
#define GCC_CAMSS_MCLK2_BCR 97
#define GCC_CPP_TBU_BCR 98
#define GCC_MDP_RT_TBU_BCR 99
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment