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

Merge branches 'clk-cleanup', 'clk-airoha', 'clk-mediatek', 'clk-sophgo' and...

Merge branches 'clk-cleanup', 'clk-airoha', 'clk-mediatek', 'clk-sophgo' and 'clk-loongson' into clk-next

 - Airoha EN7581 SoC clk driver
 - Sophgo CV1800B, CV1812H and SG2000 SoC clk driver
 - Loongson-2k0500 and Loongson-2k2000 SoC clk driver

* clk-cleanup:
  clk: gemini: Remove an unused field in struct clk_gemini_pci
  clk: highbank: Remove an unused field in struct hb_clk
  clk: ti: dpll: fix incorrect #ifdef checks
  clk: nxp: Remove an unused field in struct lpc18xx_pll

* clk-airoha:
  clk: en7523: Add EN7581 support
  clk: en7523: Add en_clk_soc_data data structure
  dt-bindings: clock: airoha: add EN7581 binding

* clk-mediatek:
  clk: mediatek: mt8365-mm: fix DPI0 parent
  clk: mediatek: pllfh: Don't log error for missing fhctl node

* clk-sophgo:
  clk: sophgo: avoid open-coded 64-bit division
  clk: sophgo: Make synthesizer struct static
  clk: sophgo: Add clock support for SG2000 SoC
  clk: sophgo: Add clock support for CV1810 SoC
  clk: sophgo: Add clock support for CV1800 SoC
  dt-bindings: clock: sophgo: Add clock controller of SG2000 series SoC

* clk-loongson:
  clk: clk-loongson2: Add Loongson-2K2000 clock support
  dt-bindings: clock: loongson2: Add Loongson-2K2000 compatible
  clk: clk-loongson2: Add Loongson-2K0500 clock support
  dt-bindings: clock: loongson2: Add Loongson-2K0500 compatible
  clk: clk-loongson2: Refactor driver for adding new platforms
  dt-bindings: clock: Add Loongson-2K expand clock index
......@@ -29,10 +29,13 @@ description: |
properties:
compatible:
items:
- const: airoha,en7523-scu
- enum:
- airoha,en7523-scu
- airoha,en7581-scu
reg:
maxItems: 2
minItems: 2
maxItems: 3
"#clock-cells":
description:
......@@ -45,6 +48,30 @@ required:
- reg
- '#clock-cells'
allOf:
- if:
properties:
compatible:
const: airoha,en7523-scu
then:
properties:
reg:
items:
- description: scu base address
- description: misc scu base address
- if:
properties:
compatible:
const: airoha,en7581-scu
then:
properties:
reg:
items:
- description: scu base address
- description: misc scu base address
- description: pb scu base address
additionalProperties: false
examples:
......
......@@ -16,7 +16,9 @@ description: |
properties:
compatible:
enum:
- loongson,ls2k-clk
- loongson,ls2k0500-clk
- loongson,ls2k-clk # This is for Loongson-2K1000
- loongson,ls2k2000-clk
reg:
maxItems: 1
......
......@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/clock/sophgo,cv1800-clk.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo CV1800 Series Clock Controller
title: Sophgo CV1800/SG2000 Series Clock Controller
maintainers:
- Inochi Amaoto <inochiama@outlook.com>
......@@ -14,6 +14,7 @@ properties:
enum:
- sophgo,cv1800-clk
- sophgo,cv1810-clk
- sophgo,sg2000-clk
reg:
maxItems: 1
......
......@@ -489,6 +489,7 @@ source "drivers/clk/rockchip/Kconfig"
source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sifive/Kconfig"
source "drivers/clk/socfpga/Kconfig"
source "drivers/clk/sophgo/Kconfig"
source "drivers/clk/sprd/Kconfig"
source "drivers/clk/starfive/Kconfig"
source "drivers/clk/sunxi/Kconfig"
......
......@@ -118,6 +118,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_CLK_SIFIVE) += sifive/
obj-y += socfpga/
obj-y += sophgo/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-y += sprd/
obj-$(CONFIG_ARCH_STI) += st/
......
......@@ -3,14 +3,16 @@
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <dt-bindings/clock/en7523-clk.h>
#define REG_PCI_CONTROL 0x88
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
#define REG_PCI_CONTROL_PERSTOUT1 BIT(26)
#define REG_PCI_CONTROL_REFCLK_EN0 BIT(23)
#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22)
#define REG_PCI_CONTROL_PERSTOUT2 BIT(16)
#define REG_GSW_CLK_DIV_SEL 0x1b4
#define REG_EMI_CLK_DIV_SEL 0x1b8
#define REG_BUS_CLK_DIV_SEL 0x1bc
......@@ -18,10 +20,25 @@
#define REG_SPI_CLK_FREQ_SEL 0x1c8
#define REG_NPU_CLK_DIV_SEL 0x1fc
#define REG_CRYPTO_CLKSRC 0x200
#define REG_RESET_CONTROL 0x834
#define REG_RESET_CONTROL2 0x830
#define REG_RESET2_CONTROL_PCIE2 BIT(27)
#define REG_RESET_CONTROL1 0x834
#define REG_RESET_CONTROL_PCIEHB BIT(29)
#define REG_RESET_CONTROL_PCIE1 BIT(27)
#define REG_RESET_CONTROL_PCIE2 BIT(26)
/* EN7581 */
#define REG_PCIE0_MEM 0x00
#define REG_PCIE0_MEM_MASK 0x04
#define REG_PCIE1_MEM 0x08
#define REG_PCIE1_MEM_MASK 0x0c
#define REG_PCIE2_MEM 0x10
#define REG_PCIE2_MEM_MASK 0x14
#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
#define REG_NP_SCU_PCIC 0x88
#define REG_NP_SCU_SSTR 0x9c
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
struct en_clk_desc {
int id;
......@@ -47,6 +64,12 @@ struct en_clk_gate {
struct clk_hw hw;
};
struct en_clk_soc_data {
const struct clk_ops pcie_ops;
int (*hw_init)(struct platform_device *pdev, void __iomem *base,
void __iomem *np_base);
};
static const u32 gsw_base[] = { 400000000, 500000000 };
static const u32 emi_base[] = { 333000000, 400000000 };
static const u32 bus_base[] = { 500000000, 540000000 };
......@@ -145,11 +168,6 @@ static const struct en_clk_desc en7523_base_clks[] = {
}
};
static const struct of_device_id of_match_clk_en7523[] = {
{ .compatible = "airoha,en7523-scu", },
{ /* sentinel */ }
};
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
{
const struct en_clk_desc *desc = &en7523_base_clks[i];
......@@ -212,14 +230,14 @@ static int en7523_pci_prepare(struct clk_hw *hw)
usleep_range(1000, 2000);
/* Reset to default */
val = readl(np_base + REG_RESET_CONTROL);
val = readl(np_base + REG_RESET_CONTROL1);
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
REG_RESET_CONTROL_PCIEHB;
writel(val & ~mask, np_base + REG_RESET_CONTROL);
writel(val & ~mask, np_base + REG_RESET_CONTROL1);
usleep_range(1000, 2000);
writel(val | mask, np_base + REG_RESET_CONTROL);
writel(val | mask, np_base + REG_RESET_CONTROL1);
msleep(100);
writel(val & ~mask, np_base + REG_RESET_CONTROL);
writel(val & ~mask, np_base + REG_RESET_CONTROL1);
usleep_range(5000, 10000);
/* Release device */
......@@ -247,14 +265,10 @@ static void en7523_pci_unprepare(struct clk_hw *hw)
static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
void __iomem *np_base)
{
static const struct clk_ops pcie_gate_ops = {
.is_enabled = en7523_pci_is_enabled,
.prepare = en7523_pci_prepare,
.unprepare = en7523_pci_unprepare,
};
const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
struct clk_init_data init = {
.name = "pcie",
.ops = &pcie_gate_ops,
.ops = &soc_data->pcie_ops,
};
struct en_clk_gate *cg;
......@@ -264,7 +278,10 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
cg->base = np_base;
cg->hw.init = &init;
en7523_pci_unprepare(&cg->hw);
if (init.ops->disable)
init.ops->disable(&cg->hw);
init.ops->unprepare(&cg->hw);
if (clk_hw_register(dev, &cg->hw))
return NULL;
......@@ -272,6 +289,111 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
return &cg->hw;
}
static int en7581_pci_is_enabled(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
u32 val, mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
val = readl(cg->base + REG_PCI_CONTROL);
return (val & mask) == mask;
}
static int en7581_pci_prepare(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
void __iomem *np_base = cg->base;
u32 val, mask;
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
REG_RESET_CONTROL_PCIEHB;
val = readl(np_base + REG_RESET_CONTROL1);
writel(val & ~mask, np_base + REG_RESET_CONTROL1);
val = readl(np_base + REG_RESET_CONTROL2);
writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
usleep_range(5000, 10000);
return 0;
}
static int en7581_pci_enable(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
void __iomem *np_base = cg->base;
u32 val, mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
REG_PCI_CONTROL_PERSTOUT;
val = readl(np_base + REG_PCI_CONTROL);
writel(val | mask, np_base + REG_PCI_CONTROL);
msleep(250);
return 0;
}
static void en7581_pci_unprepare(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
void __iomem *np_base = cg->base;
u32 val, mask;
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
REG_RESET_CONTROL_PCIEHB;
val = readl(np_base + REG_RESET_CONTROL1);
writel(val | mask, np_base + REG_RESET_CONTROL1);
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
writel(val | mask, np_base + REG_RESET_CONTROL1);
val = readl(np_base + REG_RESET_CONTROL2);
writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
msleep(100);
}
static void en7581_pci_disable(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
void __iomem *np_base = cg->base;
u32 val, mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
REG_PCI_CONTROL_PERSTOUT;
val = readl(np_base + REG_PCI_CONTROL);
writel(val & ~mask, np_base + REG_PCI_CONTROL);
usleep_range(1000, 2000);
}
static int en7581_clk_hw_init(struct platform_device *pdev,
void __iomem *base,
void __iomem *np_base)
{
void __iomem *pb_base;
u32 val;
pb_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(pb_base))
return PTR_ERR(pb_base);
val = readl(np_base + REG_NP_SCU_SSTR);
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
writel(val, np_base + REG_NP_SCU_SSTR);
val = readl(np_base + REG_NP_SCU_PCIC);
writel(val | 3, np_base + REG_NP_SCU_PCIC);
writel(0x20000000, pb_base + REG_PCIE0_MEM);
writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
writel(0x24000000, pb_base + REG_PCIE1_MEM);
writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
writel(0x28000000, pb_base + REG_PCIE2_MEM);
writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
base + REG_PCIE_RESET_OPEN_DRAIN);
return 0;
}
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
void __iomem *base, void __iomem *np_base)
{
......@@ -304,6 +426,7 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
static int en7523_clk_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
const struct en_clk_soc_data *soc_data;
struct clk_hw_onecell_data *clk_data;
void __iomem *base, *np_base;
int r;
......@@ -316,6 +439,13 @@ static int en7523_clk_probe(struct platform_device *pdev)
if (IS_ERR(np_base))
return PTR_ERR(np_base);
soc_data = device_get_match_data(&pdev->dev);
if (soc_data->hw_init) {
r = soc_data->hw_init(pdev, base, np_base);
if (r)
return r;
}
clk_data = devm_kzalloc(&pdev->dev,
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
GFP_KERNEL);
......@@ -333,6 +463,31 @@ static int en7523_clk_probe(struct platform_device *pdev)
return r;
}
static const struct en_clk_soc_data en7523_data = {
.pcie_ops = {
.is_enabled = en7523_pci_is_enabled,
.prepare = en7523_pci_prepare,
.unprepare = en7523_pci_unprepare,
},
};
static const struct en_clk_soc_data en7581_data = {
.pcie_ops = {
.is_enabled = en7581_pci_is_enabled,
.prepare = en7581_pci_prepare,
.enable = en7581_pci_enable,
.unprepare = en7581_pci_unprepare,
.disable = en7581_pci_disable,
},
.hw_init = en7581_clk_hw_init,
};
static const struct of_device_id of_match_clk_en7523[] = {
{ .compatible = "airoha,en7523-scu", .data = &en7523_data },
{ .compatible = "airoha,en7581-scu", .data = &en7581_data },
{ /* sentinel */ }
};
static struct platform_driver clk_en7523_drv = {
.probe = en7523_clk_probe,
.driver = {
......
This diff is collapsed.
......@@ -53,7 +53,7 @@ static const struct mtk_gate mm_clks[] = {
GATE_MM0(CLK_MM_MM_DSI0, "mm_dsi0", "mm_sel", 17),
GATE_MM0(CLK_MM_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 18),
GATE_MM0(CLK_MM_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 19),
GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "vpll_dpix", 20),
GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "dpi0_sel", 20),
GATE_MM0(CLK_MM_MM_FAKE, "mm_fake", "mm_sel", 21),
GATE_MM0(CLK_MM_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 22),
GATE_MM0(CLK_MM_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 23),
......
......@@ -68,7 +68,7 @@ void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs,
node = of_find_compatible_node(NULL, NULL, compatible_node);
if (!node) {
pr_err("cannot find \"%s\"\n", compatible_node);
pr_warn("cannot find \"%s\"\n", compatible_node);
return;
}
......
# SPDX-License-Identifier: GPL-2.0
# common clock support for SOPHGO SoC family.
config CLK_SOPHGO_CV1800
tristate "Support for the Sophgo CV1800 series SoCs clock controller"
depends on ARCH_SOPHGO || COMPILE_TEST
help
This driver supports clock controller of Sophgo CV18XX series SoC.
The driver require a 25MHz Oscillator to function generate clock.
It includes PLLs, common clock function and some vendor clock for
IPs of CV18XX series SoC
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CLK_SOPHGO_CV1800) += clk-sophgo-cv1800.o
clk-sophgo-cv1800-y += clk-cv1800.o
clk-sophgo-cv1800-y += clk-cv18xx-common.o
clk-sophgo-cv1800-y += clk-cv18xx-ip.o
clk-sophgo-cv1800-y += clk-cv18xx-pll.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#ifndef _CLK_SOPHGO_CV1800_H_
#define _CLK_SOPHGO_CV1800_H_
#include <dt-bindings/clock/sophgo,cv1800.h>
#define CV1800_CLK_MAX (CLK_XTAL_AP + 1)
#define CV1810_CLK_MAX (CLK_DISP_SRC_VIP + 1)
#define REG_PLL_G2_CTRL 0x800
#define REG_PLL_G2_STATUS 0x804
#define REG_MIPIMPLL_CSR 0x808
#define REG_A0PLL_CSR 0x80C
#define REG_DISPPLL_CSR 0x810
#define REG_CAM0PLL_CSR 0x814
#define REG_CAM1PLL_CSR 0x818
#define REG_PLL_G2_SSC_SYN_CTRL 0x840
#define REG_A0PLL_SSC_SYN_CTRL 0x850
#define REG_A0PLL_SSC_SYN_SET 0x854
#define REG_A0PLL_SSC_SYN_SPAN 0x858
#define REG_A0PLL_SSC_SYN_STEP 0x85C
#define REG_DISPPLL_SSC_SYN_CTRL 0x860
#define REG_DISPPLL_SSC_SYN_SET 0x864
#define REG_DISPPLL_SSC_SYN_SPAN 0x868
#define REG_DISPPLL_SSC_SYN_STEP 0x86C
#define REG_CAM0PLL_SSC_SYN_CTRL 0x870
#define REG_CAM0PLL_SSC_SYN_SET 0x874
#define REG_CAM0PLL_SSC_SYN_SPAN 0x878
#define REG_CAM0PLL_SSC_SYN_STEP 0x87C
#define REG_CAM1PLL_SSC_SYN_CTRL 0x880
#define REG_CAM1PLL_SSC_SYN_SET 0x884
#define REG_CAM1PLL_SSC_SYN_SPAN 0x888
#define REG_CAM1PLL_SSC_SYN_STEP 0x88C
#define REG_APLL_FRAC_DIV_CTRL 0x890
#define REG_APLL_FRAC_DIV_M 0x894
#define REG_APLL_FRAC_DIV_N 0x898
#define REG_MIPIMPLL_CLK_CSR 0x8A0
#define REG_A0PLL_CLK_CSR 0x8A4
#define REG_DISPPLL_CLK_CSR 0x8A8
#define REG_CAM0PLL_CLK_CSR 0x8AC
#define REG_CAM1PLL_CLK_CSR 0x8B0
#define REG_CLK_CAM0_SRC_DIV 0x8C0
#define REG_CLK_CAM1_SRC_DIV 0x8C4
/* top_pll_g6 */
#define REG_PLL_G6_CTRL 0x900
#define REG_PLL_G6_STATUS 0x904
#define REG_MPLL_CSR 0x908
#define REG_TPLL_CSR 0x90C
#define REG_FPLL_CSR 0x910
#define REG_PLL_G6_SSC_SYN_CTRL 0x940
#define REG_DPLL_SSC_SYN_CTRL 0x950
#define REG_DPLL_SSC_SYN_SET 0x954
#define REG_DPLL_SSC_SYN_SPAN 0x958
#define REG_DPLL_SSC_SYN_STEP 0x95C
#define REG_MPLL_SSC_SYN_CTRL 0x960
#define REG_MPLL_SSC_SYN_SET 0x964
#define REG_MPLL_SSC_SYN_SPAN 0x968
#define REG_MPLL_SSC_SYN_STEP 0x96C
#define REG_TPLL_SSC_SYN_CTRL 0x970
#define REG_TPLL_SSC_SYN_SET 0x974
#define REG_TPLL_SSC_SYN_SPAN 0x978
#define REG_TPLL_SSC_SYN_STEP 0x97C
/* clkgen */
#define REG_CLK_EN_0 0x000
#define REG_CLK_EN_1 0x004
#define REG_CLK_EN_2 0x008
#define REG_CLK_EN_3 0x00C
#define REG_CLK_EN_4 0x010
#define REG_CLK_SEL_0 0x020
#define REG_CLK_BYP_0 0x030
#define REG_CLK_BYP_1 0x034
#define REG_DIV_CLK_A53_0 0x040
#define REG_DIV_CLK_A53_1 0x044
#define REG_DIV_CLK_CPU_AXI0 0x048
#define REG_DIV_CLK_CPU_GIC 0x050
#define REG_DIV_CLK_TPU 0x054
#define REG_DIV_CLK_EMMC 0x064
#define REG_DIV_CLK_EMMC_100K 0x06C
#define REG_DIV_CLK_SD0 0x070
#define REG_DIV_CLK_SD0_100K 0x078
#define REG_DIV_CLK_SD1 0x07C
#define REG_DIV_CLK_SD1_100K 0x084
#define REG_DIV_CLK_SPI_NAND 0x088
#define REG_DIV_CLK_ETH0_500M 0x08C
#define REG_DIV_CLK_ETH1_500M 0x090
#define REG_DIV_CLK_GPIO_DB 0x094
#define REG_DIV_CLK_SDMA_AUD0 0x098
#define REG_DIV_CLK_SDMA_AUD1 0x09C
#define REG_DIV_CLK_SDMA_AUD2 0x0A0
#define REG_DIV_CLK_SDMA_AUD3 0x0A4
#define REG_DIV_CLK_CAM0_200 0x0A8
#define REG_DIV_CLK_AXI4 0x0B8
#define REG_DIV_CLK_AXI6 0x0BC
#define REG_DIV_CLK_DSI_ESC 0x0C4
#define REG_DIV_CLK_AXI_VIP 0x0C8
#define REG_DIV_CLK_SRC_VIP_SYS_0 0x0D0
#define REG_DIV_CLK_SRC_VIP_SYS_1 0x0D8
#define REG_DIV_CLK_DISP_SRC_VIP 0x0E0
#define REG_DIV_CLK_AXI_VIDEO_CODEC 0x0E4
#define REG_DIV_CLK_VC_SRC0 0x0EC
#define REG_DIV_CLK_1M 0x0FC
#define REG_DIV_CLK_SPI 0x100
#define REG_DIV_CLK_I2C 0x104
#define REG_DIV_CLK_SRC_VIP_SYS_2 0x110
#define REG_DIV_CLK_AUDSRC 0x118
#define REG_DIV_CLK_PWM_SRC_0 0x120
#define REG_DIV_CLK_AP_DEBUG 0x128
#define REG_DIV_CLK_RTCSYS_SRC_0 0x12C
#define REG_DIV_CLK_C906_0_0 0x130
#define REG_DIV_CLK_C906_0_1 0x134
#define REG_DIV_CLK_C906_1_0 0x138
#define REG_DIV_CLK_C906_1_1 0x13C
#define REG_DIV_CLK_SRC_VIP_SYS_3 0x140
#define REG_DIV_CLK_SRC_VIP_SYS_4 0x144
#endif /* _CLK_SOPHGO_CV1800_H_ */
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/spinlock.h>
#include <linux/bug.h>
#include "clk-cv18xx-common.h"
int cv1800_clk_setbit(struct cv1800_clk_common *common,
struct cv1800_clk_regbit *field)
{
u32 mask = BIT(field->shift);
u32 value;
unsigned long flags;
spin_lock_irqsave(common->lock, flags);
value = readl(common->base + field->reg);
writel(value | mask, common->base + field->reg);
spin_unlock_irqrestore(common->lock, flags);
return 0;
}
int cv1800_clk_clearbit(struct cv1800_clk_common *common,
struct cv1800_clk_regbit *field)
{
u32 mask = BIT(field->shift);
u32 value;
unsigned long flags;
spin_lock_irqsave(common->lock, flags);
value = readl(common->base + field->reg);
writel(value & ~mask, common->base + field->reg);
spin_unlock_irqrestore(common->lock, flags);
return 0;
}
int cv1800_clk_checkbit(struct cv1800_clk_common *common,
struct cv1800_clk_regbit *field)
{
return readl(common->base + field->reg) & BIT(field->shift);
}
#define PLL_LOCK_TIMEOUT_US (200 * 1000)
void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common,
u32 reg, u32 lock)
{
void __iomem *addr = common->base + reg;
u32 regval;
if (!lock)
return;
WARN_ON(readl_relaxed_poll_timeout(addr, regval, regval & lock,
100, PLL_LOCK_TIMEOUT_US));
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#ifndef _CLK_SOPHGO_CV18XX_IP_H_
#define _CLK_SOPHGO_CV18XX_IP_H_
#include <linux/compiler.h>
#include <linux/clk-provider.h>
#include <linux/bitfield.h>
struct cv1800_clk_common {
void __iomem *base;
spinlock_t *lock;
struct clk_hw hw;
unsigned long features;
};
#define CV1800_CLK_COMMON(_name, _parents, _op, _flags) \
{ \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents, \
_op, _flags), \
}
static inline struct cv1800_clk_common *
hw_to_cv1800_clk_common(struct clk_hw *hw)
{
return container_of(hw, struct cv1800_clk_common, hw);
}
struct cv1800_clk_regbit {
u16 reg;
s8 shift;
};
struct cv1800_clk_regfield {
u16 reg;
u8 shift;
u8 width;
s16 initval;
unsigned long flags;
};
#define CV1800_CLK_BIT(_reg, _shift) \
{ \
.reg = _reg, \
.shift = _shift, \
}
#define CV1800_CLK_REG(_reg, _shift, _width, _initval, _flags) \
{ \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.initval = _initval, \
.flags = _flags, \
}
#define cv1800_clk_regfield_genmask(_reg) \
GENMASK((_reg)->shift + (_reg)->width - 1, (_reg)->shift)
#define cv1800_clk_regfield_get(_val, _reg) \
(((_val) >> (_reg)->shift) & GENMASK((_reg)->width - 1, 0))
#define cv1800_clk_regfield_set(_val, _new, _reg) \
(((_val) & ~cv1800_clk_regfield_genmask((_reg))) | \
(((_new) & GENMASK((_reg)->width - 1, 0)) << (_reg)->shift))
#define _CV1800_SET_FIELD(_reg, _val, _field) \
(((_reg) & ~(_field)) | FIELD_PREP((_field), (_val)))
int cv1800_clk_setbit(struct cv1800_clk_common *common,
struct cv1800_clk_regbit *field);
int cv1800_clk_clearbit(struct cv1800_clk_common *common,
struct cv1800_clk_regbit *field);
int cv1800_clk_checkbit(struct cv1800_clk_common *common,
struct cv1800_clk_regbit *field);
void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common,
u32 reg, u32 lock);
#endif // _CLK_SOPHGO_CV18XX_IP_H_
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#ifndef _CLK_SOPHGO_CV1800_IP_H_
#define _CLK_SOPHGO_CV1800_IP_H_
#include "clk-cv18xx-common.h"
struct cv1800_clk_gate {
struct cv1800_clk_common common;
struct cv1800_clk_regbit gate;
};
struct cv1800_clk_div_data {
u32 reg;
u32 mask;
u32 width;
u32 init;
u32 flags;
};
struct cv1800_clk_div {
struct cv1800_clk_common common;
struct cv1800_clk_regbit gate;
struct cv1800_clk_regfield div;
};
struct cv1800_clk_bypass_div {
struct cv1800_clk_div div;
struct cv1800_clk_regbit bypass;
};
struct cv1800_clk_mux {
struct cv1800_clk_common common;
struct cv1800_clk_regbit gate;
struct cv1800_clk_regfield div;
struct cv1800_clk_regfield mux;
};
struct cv1800_clk_bypass_mux {
struct cv1800_clk_mux mux;
struct cv1800_clk_regbit bypass;
};
struct cv1800_clk_mmux {
struct cv1800_clk_common common;
struct cv1800_clk_regbit gate;
struct cv1800_clk_regfield div[2];
struct cv1800_clk_regfield mux[2];
struct cv1800_clk_regbit bypass;
struct cv1800_clk_regbit clk_sel;
const s8 *parent2sel;
const u8 *sel2parent[2];
};
struct cv1800_clk_audio {
struct cv1800_clk_common common;
struct cv1800_clk_regbit src_en;
struct cv1800_clk_regbit output_en;
struct cv1800_clk_regbit div_en;
struct cv1800_clk_regbit div_up;
struct cv1800_clk_regfield m;
struct cv1800_clk_regfield n;
u32 target_rate;
};
#define CV1800_GATE(_name, _parent, _gate_reg, _gate_shift, _flags) \
struct cv1800_clk_gate _name = { \
.common = CV1800_CLK_COMMON(#_name, _parent, \
&cv1800_clk_gate_ops, \
_flags), \
.gate = CV1800_CLK_BIT(_gate_reg, _gate_shift), \
}
#define _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init, \
_div_flag, _ops, _flags) \
{ \
.common = CV1800_CLK_COMMON(#_name, _parent, \
_ops, _flags), \
.gate = CV1800_CLK_BIT(_gate_reg, \
_gate_shift), \
.div = CV1800_CLK_REG(_div_reg, _div_shift, \
_div_width, _div_init, \
_div_flag), \
}
#define _CV1800_FIXED_DIV_FLAG \
(CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST)
#define _CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \
_fix_div, _ops, _flags) \
{ \
.common = CV1800_CLK_COMMON(#_name, _parent, \
_ops, _flags), \
.gate = CV1800_CLK_BIT(_gate_reg, \
_gate_shift), \
.div = CV1800_CLK_REG(0, 0, 0, \
_fix_div, \
_CV1800_FIXED_DIV_FLAG),\
}
#define CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init, \
_div_flag, _flags) \
struct cv1800_clk_div _name = \
_CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init,\
_div_flag, &cv1800_clk_div_ops, _flags)
#define CV1800_BYPASS_DIV(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init, \
_div_flag, _bypass_reg, _bypass_shift, _flags)\
struct cv1800_clk_bypass_div _name = { \
.div = _CV1800_DIV(_name, _parent, \
_gate_reg, _gate_shift, \
_div_reg, _div_shift, \
_div_width, _div_init, _div_flag, \
&cv1800_clk_bypass_div_ops, \
_flags), \
.bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \
}
#define CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \
_fix_div, _flags) \
struct cv1800_clk_div _name = \
_CV1800_FIXED_DIV(_name, _parent, \
_gate_reg, _gate_shift, \
_fix_div, \
&cv1800_clk_div_ops, _flags) \
#define CV1800_BYPASS_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \
_fix_div, _bypass_reg, _bypass_shift, \
_flags) \
struct cv1800_clk_bypass_div _name = { \
.div = _CV1800_FIXED_DIV(_name, _parent, \
_gate_reg, _gate_shift, \
_fix_div, \
&cv1800_clk_bypass_div_ops, \
_flags), \
.bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \
}
#define _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init, \
_div_flag, \
_mux_reg, _mux_shift, _mux_width, \
_ops, _flags) \
{ \
.common = CV1800_CLK_COMMON(#_name, _parent, \
_ops, _flags), \
.gate = CV1800_CLK_BIT(_gate_reg, \
_gate_shift), \
.div = CV1800_CLK_REG(_div_reg, _div_shift, \
_div_width, _div_init, \
_div_flag), \
.mux = CV1800_CLK_REG(_mux_reg, _mux_shift, \
_mux_width, 0, 0), \
}
#define CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init, \
_div_flag, \
_mux_reg, _mux_shift, _mux_width, _flags) \
struct cv1800_clk_mux _name = \
_CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init,\
_div_flag, _mux_reg, _mux_shift, _mux_width,\
&cv1800_clk_mux_ops, _flags)
#define CV1800_BYPASS_MUX(_name, _parent, _gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, _div_init, \
_div_flag, \
_mux_reg, _mux_shift, _mux_width, \
_bypass_reg, _bypass_shift, _flags) \
struct cv1800_clk_bypass_mux _name = { \
.mux = _CV1800_MUX(_name, _parent, \
_gate_reg, _gate_shift, \
_div_reg, _div_shift, _div_width, \
_div_init, _div_flag, \
_mux_reg, _mux_shift, _mux_width, \
&cv1800_clk_bypass_mux_ops, \
_flags), \
.bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \
}
#define CV1800_MMUX(_name, _parent, _gate_reg, _gate_shift, \
_div0_reg, _div0_shift, _div0_width, _div0_init, \
_div0_flag, \
_div1_reg, _div1_shift, _div1_width, _div1_init, \
_div1_flag, \
_mux0_reg, _mux0_shift, _mux0_width, \
_mux1_reg, _mux1_shift, _mux1_width, \
_bypass_reg, _bypass_shift, \
_clk_sel_reg, _clk_sel_shift, \
_parent2sel, _sel2parent0, _sel2parent1, _flags) \
struct cv1800_clk_mmux _name = { \
.common = CV1800_CLK_COMMON(#_name, _parent, \
&cv1800_clk_mmux_ops,\
_flags), \
.gate = CV1800_CLK_BIT(_gate_reg, _gate_shift),\
.div = { \
CV1800_CLK_REG(_div0_reg, _div0_shift, \
_div0_width, _div0_init, \
_div0_flag), \
CV1800_CLK_REG(_div1_reg, _div1_shift, \
_div1_width, _div1_init, \
_div1_flag), \
}, \
.mux = { \
CV1800_CLK_REG(_mux0_reg, _mux0_shift, \
_mux0_width, 0, 0), \
CV1800_CLK_REG(_mux1_reg, _mux1_shift, \
_mux1_width, 0, 0), \
}, \
.bypass = CV1800_CLK_BIT(_bypass_reg, \
_bypass_shift), \
.clk_sel = CV1800_CLK_BIT(_clk_sel_reg, \
_clk_sel_shift), \
.parent2sel = _parent2sel, \
.sel2parent = { _sel2parent0, _sel2parent1 }, \
}
#define CV1800_ACLK(_name, _parent, \
_src_en_reg, _src_en_reg_shift, \
_output_en_reg, _output_en_shift, \
_div_en_reg, _div_en_reg_shift, \
_div_up_reg, _div_up_reg_shift, \
_m_reg, _m_shift, _m_width, _m_flag, \
_n_reg, _n_shift, _n_width, _n_flag, \
_target_rate, _flags) \
struct cv1800_clk_audio _name = { \
.common = CV1800_CLK_COMMON(#_name, _parent, \
&cv1800_clk_audio_ops,\
_flags), \
.src_en = CV1800_CLK_BIT(_src_en_reg, \
_src_en_reg_shift), \
.output_en = CV1800_CLK_BIT(_output_en_reg, \
_output_en_shift), \
.div_en = CV1800_CLK_BIT(_div_en_reg, \
_div_en_reg_shift), \
.div_up = CV1800_CLK_BIT(_div_up_reg, \
_div_up_reg_shift), \
.m = CV1800_CLK_REG(_m_reg, _m_shift, \
_m_width, 0, _m_flag), \
.n = CV1800_CLK_REG(_n_reg, _n_shift, \
_n_width, 0, _n_flag), \
.target_rate = _target_rate, \
}
extern const struct clk_ops cv1800_clk_gate_ops;
extern const struct clk_ops cv1800_clk_div_ops;
extern const struct clk_ops cv1800_clk_bypass_div_ops;
extern const struct clk_ops cv1800_clk_mux_ops;
extern const struct clk_ops cv1800_clk_bypass_mux_ops;
extern const struct clk_ops cv1800_clk_mmux_ops;
extern const struct clk_ops cv1800_clk_audio_ops;
#endif // _CLK_SOPHGO_CV1800_IP_H_
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
*/
#ifndef _CLK_SOPHGO_CV1800_PLL_H_
#define _CLK_SOPHGO_CV1800_PLL_H_
#include "clk-cv18xx-common.h"
struct cv1800_clk_pll_limit {
struct {
u8 min;
u8 max;
} pre_div, div, post_div, ictrl, mode;
};
#define _CV1800_PLL_LIMIT(_min, _max) \
{ \
.min = _min, \
.max = _max, \
} \
#define for_each_pll_limit_range(_var, _restrict) \
for (_var = (_restrict)->min; _var <= (_restrict)->max; _var++)
struct cv1800_clk_pll_synthesizer {
struct cv1800_clk_regbit en;
struct cv1800_clk_regbit clk_half;
u32 ctrl;
u32 set;
};
#define _PLL_PRE_DIV_SEL_FIELD GENMASK(6, 0)
#define _PLL_POST_DIV_SEL_FIELD GENMASK(14, 8)
#define _PLL_SEL_MODE_FIELD GENMASK(16, 15)
#define _PLL_DIV_SEL_FIELD GENMASK(23, 17)
#define _PLL_ICTRL_FIELD GENMASK(26, 24)
#define _PLL_ALL_FIELD_MASK \
(_PLL_PRE_DIV_SEL_FIELD | \
_PLL_POST_DIV_SEL_FIELD | \
_PLL_SEL_MODE_FIELD | \
_PLL_DIV_SEL_FIELD | \
_PLL_ICTRL_FIELD)
#define PLL_COPY_REG(_dest, _src) \
(((_dest) & (~_PLL_ALL_FIELD_MASK)) | ((_src) & _PLL_ALL_FIELD_MASK))
#define PLL_GET_PRE_DIV_SEL(_reg) \
FIELD_GET(_PLL_PRE_DIV_SEL_FIELD, (_reg))
#define PLL_GET_POST_DIV_SEL(_reg) \
FIELD_GET(_PLL_POST_DIV_SEL_FIELD, (_reg))
#define PLL_GET_SEL_MODE(_reg) \
FIELD_GET(_PLL_SEL_MODE_FIELD, (_reg))
#define PLL_GET_DIV_SEL(_reg) \
FIELD_GET(_PLL_DIV_SEL_FIELD, (_reg))
#define PLL_GET_ICTRL(_reg) \
FIELD_GET(_PLL_ICTRL_FIELD, (_reg))
#define PLL_SET_PRE_DIV_SEL(_reg, _val) \
_CV1800_SET_FIELD((_reg), (_val), _PLL_PRE_DIV_SEL_FIELD)
#define PLL_SET_POST_DIV_SEL(_reg, _val) \
_CV1800_SET_FIELD((_reg), (_val), _PLL_POST_DIV_SEL_FIELD)
#define PLL_SET_SEL_MODE(_reg, _val) \
_CV1800_SET_FIELD((_reg), (_val), _PLL_SEL_MODE_FIELD)
#define PLL_SET_DIV_SEL(_reg, _val) \
_CV1800_SET_FIELD((_reg), (_val), _PLL_DIV_SEL_FIELD)
#define PLL_SET_ICTRL(_reg, _val) \
_CV1800_SET_FIELD((_reg), (_val), _PLL_ICTRL_FIELD)
struct cv1800_clk_pll {
struct cv1800_clk_common common;
u32 pll_reg;
struct cv1800_clk_regbit pll_pwd;
struct cv1800_clk_regbit pll_status;
const struct cv1800_clk_pll_limit *pll_limit;
struct cv1800_clk_pll_synthesizer *pll_syn;
};
#define CV1800_INTEGRAL_PLL(_name, _parent, _pll_reg, \
_pll_pwd_reg, _pll_pwd_shift, \
_pll_status_reg, _pll_status_shift, \
_pll_limit, _flags) \
struct cv1800_clk_pll _name = { \
.common = CV1800_CLK_COMMON(#_name, _parent, \
&cv1800_clk_ipll_ops,\
_flags), \
.pll_reg = _pll_reg, \
.pll_pwd = CV1800_CLK_BIT(_pll_pwd_reg, \
_pll_pwd_shift), \
.pll_status = CV1800_CLK_BIT(_pll_status_reg, \
_pll_status_shift), \
.pll_limit = _pll_limit, \
.pll_syn = NULL, \
}
#define CV1800_FACTIONAL_PLL(_name, _parent, _pll_reg, \
_pll_pwd_reg, _pll_pwd_shift, \
_pll_status_reg, _pll_status_shift, \
_pll_limit, _pll_syn, _flags) \
struct cv1800_clk_pll _name = { \
.common = CV1800_CLK_COMMON(#_name, _parent, \
&cv1800_clk_fpll_ops,\
_flags), \
.pll_reg = _pll_reg, \
.pll_pwd = CV1800_CLK_BIT(_pll_pwd_reg, \
_pll_pwd_shift), \
.pll_status = CV1800_CLK_BIT(_pll_status_reg, \
_pll_status_shift), \
.pll_limit = _pll_limit, \
.pll_syn = _pll_syn, \
}
extern const struct clk_ops cv1800_clk_ipll_ops;
extern const struct clk_ops cv1800_clk_fpll_ops;
#endif // _CLK_SOPHGO_CV1800_PLL_H_
......@@ -7,24 +7,40 @@
#ifndef __DT_BINDINGS_CLOCK_LOONGSON2_H
#define __DT_BINDINGS_CLOCK_LOONGSON2_H
#define LOONGSON2_REF_100M 0
#define LOONGSON2_NODE_PLL 1
#define LOONGSON2_DDR_PLL 2
#define LOONGSON2_DC_PLL 3
#define LOONGSON2_PIX0_PLL 4
#define LOONGSON2_PIX1_PLL 5
#define LOONGSON2_NODE_CLK 6
#define LOONGSON2_HDA_CLK 7
#define LOONGSON2_GPU_CLK 8
#define LOONGSON2_DDR_CLK 9
#define LOONGSON2_GMAC_CLK 10
#define LOONGSON2_DC_CLK 11
#define LOONGSON2_APB_CLK 12
#define LOONGSON2_USB_CLK 13
#define LOONGSON2_SATA_CLK 14
#define LOONGSON2_PIX0_CLK 15
#define LOONGSON2_PIX1_CLK 16
#define LOONGSON2_BOOT_CLK 17
#define LOONGSON2_CLK_END 18
#define LOONGSON2_REF_100M 0
#define LOONGSON2_NODE_PLL 1
#define LOONGSON2_DDR_PLL 2
#define LOONGSON2_DC_PLL 3
#define LOONGSON2_PIX0_PLL 4
#define LOONGSON2_PIX1_PLL 5
#define LOONGSON2_NODE_CLK 6
#define LOONGSON2_HDA_CLK 7
#define LOONGSON2_GPU_CLK 8
#define LOONGSON2_DDR_CLK 9
#define LOONGSON2_GMAC_CLK 10
#define LOONGSON2_DC_CLK 11
#define LOONGSON2_APB_CLK 12
#define LOONGSON2_USB_CLK 13
#define LOONGSON2_SATA_CLK 14
#define LOONGSON2_PIX0_CLK 15
#define LOONGSON2_PIX1_CLK 16
#define LOONGSON2_BOOT_CLK 17
#define LOONGSON2_OUT0_GATE 18
#define LOONGSON2_GMAC_GATE 19
#define LOONGSON2_RIO_GATE 20
#define LOONGSON2_DC_GATE 21
#define LOONGSON2_GPU_GATE 22
#define LOONGSON2_DDR_GATE 23
#define LOONGSON2_HDA_GATE 24
#define LOONGSON2_NODE_GATE 25
#define LOONGSON2_EMMC_GATE 26
#define LOONGSON2_PIX0_GATE 27
#define LOONGSON2_PIX1_GATE 28
#define LOONGSON2_OUT0_CLK 29
#define LOONGSON2_RIO_CLK 30
#define LOONGSON2_EMMC_CLK 31
#define LOONGSON2_DES_CLK 32
#define LOONGSON2_I2S_CLK 33
#define LOONGSON2_MISC_CLK 34
#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