1f419069aSAngeloGioacchino Del Regno // SPDX-License-Identifier: GPL-2.0-only
2f419069aSAngeloGioacchino Del Regno /*
3f419069aSAngeloGioacchino Del Regno * Copyright (c) 2019 MediaTek Inc.
4f419069aSAngeloGioacchino Del Regno * James Liao <jamesjj.liao@mediatek.com>
5f419069aSAngeloGioacchino Del Regno * Fabien Parent <fparent@baylibre.com>
6f419069aSAngeloGioacchino Del Regno *
7f419069aSAngeloGioacchino Del Regno * Copyright (c) 2023 Collabora, Ltd.
8f419069aSAngeloGioacchino Del Regno * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
9f419069aSAngeloGioacchino Del Regno */
10f419069aSAngeloGioacchino Del Regno
11f419069aSAngeloGioacchino Del Regno #include <dt-bindings/clock/mt8516-clk.h>
12f419069aSAngeloGioacchino Del Regno #include <linux/clk.h>
13f419069aSAngeloGioacchino Del Regno #include <linux/of.h>
14f419069aSAngeloGioacchino Del Regno #include <linux/platform_device.h>
15f419069aSAngeloGioacchino Del Regno
16f419069aSAngeloGioacchino Del Regno #include "clk-mtk.h"
17f419069aSAngeloGioacchino Del Regno #include "clk-pll.h"
18f419069aSAngeloGioacchino Del Regno
19f419069aSAngeloGioacchino Del Regno #define MT8516_PLL_FMAX (1502UL * MHZ)
20f419069aSAngeloGioacchino Del Regno
21f419069aSAngeloGioacchino Del Regno #define CON0_MT8516_RST_BAR BIT(27)
22f419069aSAngeloGioacchino Del Regno
23f419069aSAngeloGioacchino Del Regno #define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
24f419069aSAngeloGioacchino Del Regno _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
25f419069aSAngeloGioacchino Del Regno _pcw_shift, _div_table) { \
26f419069aSAngeloGioacchino Del Regno .id = _id, \
27f419069aSAngeloGioacchino Del Regno .name = _name, \
28f419069aSAngeloGioacchino Del Regno .reg = _reg, \
29f419069aSAngeloGioacchino Del Regno .pwr_reg = _pwr_reg, \
30f419069aSAngeloGioacchino Del Regno .en_mask = _en_mask, \
31f419069aSAngeloGioacchino Del Regno .flags = _flags, \
32f419069aSAngeloGioacchino Del Regno .rst_bar_mask = CON0_MT8516_RST_BAR, \
33f419069aSAngeloGioacchino Del Regno .fmax = MT8516_PLL_FMAX, \
34f419069aSAngeloGioacchino Del Regno .pcwbits = _pcwbits, \
35f419069aSAngeloGioacchino Del Regno .pd_reg = _pd_reg, \
36f419069aSAngeloGioacchino Del Regno .pd_shift = _pd_shift, \
37f419069aSAngeloGioacchino Del Regno .tuner_reg = _tuner_reg, \
38f419069aSAngeloGioacchino Del Regno .pcw_reg = _pcw_reg, \
39f419069aSAngeloGioacchino Del Regno .pcw_shift = _pcw_shift, \
40f419069aSAngeloGioacchino Del Regno .div_table = _div_table, \
41f419069aSAngeloGioacchino Del Regno }
42f419069aSAngeloGioacchino Del Regno
43f419069aSAngeloGioacchino Del Regno #define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
44f419069aSAngeloGioacchino Del Regno _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
45f419069aSAngeloGioacchino Del Regno _pcw_shift) \
46f419069aSAngeloGioacchino Del Regno PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
47f419069aSAngeloGioacchino Del Regno _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
48f419069aSAngeloGioacchino Del Regno NULL)
49f419069aSAngeloGioacchino Del Regno
50f419069aSAngeloGioacchino Del Regno static const struct mtk_pll_div_table mmpll_div_table[] = {
51f419069aSAngeloGioacchino Del Regno { .div = 0, .freq = MT8516_PLL_FMAX },
52f419069aSAngeloGioacchino Del Regno { .div = 1, .freq = 1000000000 },
53f419069aSAngeloGioacchino Del Regno { .div = 2, .freq = 604500000 },
54f419069aSAngeloGioacchino Del Regno { .div = 3, .freq = 253500000 },
55f419069aSAngeloGioacchino Del Regno { .div = 4, .freq = 126750000 },
56f419069aSAngeloGioacchino Del Regno { } /* sentinel */
57f419069aSAngeloGioacchino Del Regno };
58f419069aSAngeloGioacchino Del Regno
59f419069aSAngeloGioacchino Del Regno static const struct mtk_pll_data plls[] = {
60f419069aSAngeloGioacchino Del Regno PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0, 0,
61f419069aSAngeloGioacchino Del Regno 21, 0x0104, 24, 0, 0x0104, 0),
62f419069aSAngeloGioacchino Del Regno PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0,
63f419069aSAngeloGioacchino Del Regno HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0),
64f419069aSAngeloGioacchino Del Regno PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000000,
65f419069aSAngeloGioacchino Del Regno HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0),
66f419069aSAngeloGioacchino Del Regno PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0, 0,
67f419069aSAngeloGioacchino Del Regno 21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table),
68f419069aSAngeloGioacchino Del Regno PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0, 0,
69f419069aSAngeloGioacchino Del Regno 31, 0x0180, 1, 0x0194, 0x0184, 0),
70f419069aSAngeloGioacchino Del Regno PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0, 0,
71f419069aSAngeloGioacchino Del Regno 31, 0x01A0, 1, 0x01B4, 0x01A4, 0),
72f419069aSAngeloGioacchino Del Regno };
73f419069aSAngeloGioacchino Del Regno
clk_mt8516_apmixed_probe(struct platform_device * pdev)74f419069aSAngeloGioacchino Del Regno static int clk_mt8516_apmixed_probe(struct platform_device *pdev)
75f419069aSAngeloGioacchino Del Regno {
76f419069aSAngeloGioacchino Del Regno void __iomem *base;
77f419069aSAngeloGioacchino Del Regno struct clk_hw_onecell_data *clk_data;
78f419069aSAngeloGioacchino Del Regno struct device_node *node = pdev->dev.of_node;
79f419069aSAngeloGioacchino Del Regno struct device *dev = &pdev->dev;
80f419069aSAngeloGioacchino Del Regno int ret;
81f419069aSAngeloGioacchino Del Regno
82f419069aSAngeloGioacchino Del Regno base = devm_platform_ioremap_resource(pdev, 0);
83f419069aSAngeloGioacchino Del Regno if (IS_ERR(base))
84f419069aSAngeloGioacchino Del Regno return PTR_ERR(base);
85f419069aSAngeloGioacchino Del Regno
86f419069aSAngeloGioacchino Del Regno clk_data = mtk_devm_alloc_clk_data(dev, CLK_APMIXED_NR_CLK);
87f419069aSAngeloGioacchino Del Regno if (!clk_data)
88f419069aSAngeloGioacchino Del Regno return -ENOMEM;
89f419069aSAngeloGioacchino Del Regno
90f419069aSAngeloGioacchino Del Regno ret = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
91f419069aSAngeloGioacchino Del Regno if (ret)
92f419069aSAngeloGioacchino Del Regno return ret;
93f419069aSAngeloGioacchino Del Regno
94f419069aSAngeloGioacchino Del Regno ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
95f419069aSAngeloGioacchino Del Regno if (ret)
96f419069aSAngeloGioacchino Del Regno goto unregister_plls;
97f419069aSAngeloGioacchino Del Regno
98f419069aSAngeloGioacchino Del Regno return 0;
99f419069aSAngeloGioacchino Del Regno
100f419069aSAngeloGioacchino Del Regno unregister_plls:
101f419069aSAngeloGioacchino Del Regno mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
102f419069aSAngeloGioacchino Del Regno
103f419069aSAngeloGioacchino Del Regno return ret;
104f419069aSAngeloGioacchino Del Regno }
105f419069aSAngeloGioacchino Del Regno
106f419069aSAngeloGioacchino Del Regno static const struct of_device_id of_match_clk_mt8516_apmixed[] = {
107f419069aSAngeloGioacchino Del Regno { .compatible = "mediatek,mt8516-apmixedsys" },
108f419069aSAngeloGioacchino Del Regno { /* sentinel */ }
109f419069aSAngeloGioacchino Del Regno };
110*65c9ad77SAngeloGioacchino Del Regno MODULE_DEVICE_TABLE(of, of_match_clk_mt8516_apmixed);
111f419069aSAngeloGioacchino Del Regno
112f419069aSAngeloGioacchino Del Regno static struct platform_driver clk_mt8516_apmixed_drv = {
113f419069aSAngeloGioacchino Del Regno .probe = clk_mt8516_apmixed_probe,
114f419069aSAngeloGioacchino Del Regno .driver = {
115f419069aSAngeloGioacchino Del Regno .name = "clk-mt8516-apmixed",
116f419069aSAngeloGioacchino Del Regno .of_match_table = of_match_clk_mt8516_apmixed,
117f419069aSAngeloGioacchino Del Regno },
118f419069aSAngeloGioacchino Del Regno };
119f419069aSAngeloGioacchino Del Regno builtin_platform_driver(clk_mt8516_apmixed_drv)
120f419069aSAngeloGioacchino Del Regno
121f419069aSAngeloGioacchino Del Regno MODULE_DESCRIPTION("MediaTek MT8516 apmixedsys clocks driver");
122f419069aSAngeloGioacchino Del Regno MODULE_LICENSE("GPL");
123