|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
| 2 | +// |
| 3 | +// Copyright (c) 2021 MediaTek Inc. |
| 4 | +// Author: Chun-Jie Chen <[email protected]> |
| 5 | + |
| 6 | +#include "clk-mtk.h" |
| 7 | + |
| 8 | +#include <dt-bindings/clock/mt8195-clk.h> |
| 9 | +#include <linux/clk-provider.h> |
| 10 | +#include <linux/platform_device.h> |
| 11 | + |
| 12 | +#define MT8195_PLL_FMAX (3800UL * MHZ) |
| 13 | +#define MT8195_PLL_FMIN (1500UL * MHZ) |
| 14 | +#define MT8195_INTEGER_BITS (8) |
| 15 | +#define MT8195_PCW_BITS (22) |
| 16 | +#define MT8195_POSDIV_SHIFT (24) |
| 17 | +#define MT8195_PLL_EN_BIT (0) |
| 18 | +#define MT8195_PCW_SHIFT (0) |
| 19 | + |
| 20 | +/* |
| 21 | + * The "en_reg" and "pcw_chg_reg" fields are standard offset register compared |
| 22 | + * with "reg" field, so set zero to imply it. |
| 23 | + * No tuner control in apu pll, so set "tuner_XXX" as zero to imply it. |
| 24 | + * No rst or post divider enable in apu pll, so set "rst_bar_mask" and "en_mask" |
| 25 | + * as zero to imply it. |
| 26 | + */ |
| 27 | +#define PLL(_id, _name, _reg, _pwr_reg, _pd_reg, _pcw_reg) { \ |
| 28 | + .id = _id, \ |
| 29 | + .name = _name, \ |
| 30 | + .reg = _reg, \ |
| 31 | + .pwr_reg = _pwr_reg, \ |
| 32 | + .en_mask = 0, \ |
| 33 | + .flags = 0, \ |
| 34 | + .rst_bar_mask = 0, \ |
| 35 | + .fmax = MT8195_PLL_FMAX, \ |
| 36 | + .fmin = MT8195_PLL_FMIN, \ |
| 37 | + .pcwbits = MT8195_PCW_BITS, \ |
| 38 | + .pcwibits = MT8195_INTEGER_BITS, \ |
| 39 | + .pd_reg = _pd_reg, \ |
| 40 | + .pd_shift = MT8195_POSDIV_SHIFT, \ |
| 41 | + .tuner_reg = 0, \ |
| 42 | + .tuner_en_reg = 0, \ |
| 43 | + .tuner_en_bit = 0, \ |
| 44 | + .pcw_reg = _pcw_reg, \ |
| 45 | + .pcw_shift = MT8195_PCW_SHIFT, \ |
| 46 | + .pcw_chg_reg = 0, \ |
| 47 | + .en_reg = 0, \ |
| 48 | + .pll_en_bit = MT8195_PLL_EN_BIT, \ |
| 49 | + } |
| 50 | + |
| 51 | +static const struct mtk_pll_data apusys_plls[] = { |
| 52 | + PLL(CLK_APUSYS_PLL_APUPLL, "apusys_pll_apupll", 0x008, 0x014, 0x00c, 0x00c), |
| 53 | + PLL(CLK_APUSYS_PLL_NPUPLL, "apusys_pll_npupll", 0x018, 0x024, 0x01c, 0x01c), |
| 54 | + PLL(CLK_APUSYS_PLL_APUPLL1, "apusys_pll_apupll1", 0x028, 0x034, 0x02c, 0x02c), |
| 55 | + PLL(CLK_APUSYS_PLL_APUPLL2, "apusys_pll_apupll2", 0x038, 0x044, 0x03c, 0x03c), |
| 56 | +}; |
| 57 | + |
| 58 | +static int clk_mt8195_apusys_pll_probe(struct platform_device *pdev) |
| 59 | +{ |
| 60 | + struct clk_onecell_data *clk_data; |
| 61 | + struct device_node *node = pdev->dev.of_node; |
| 62 | + int r; |
| 63 | + |
| 64 | + clk_data = mtk_alloc_clk_data(CLK_APUSYS_PLL_NR_CLK); |
| 65 | + if (!clk_data) |
| 66 | + return -ENOMEM; |
| 67 | + |
| 68 | + mtk_clk_register_plls(node, apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); |
| 69 | + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
| 70 | + if (r) |
| 71 | + goto free_apusys_pll_data; |
| 72 | + |
| 73 | + return r; |
| 74 | + |
| 75 | +free_apusys_pll_data: |
| 76 | + mtk_free_clk_data(clk_data); |
| 77 | + return r; |
| 78 | +} |
| 79 | + |
| 80 | +static const struct of_device_id of_match_clk_mt8195_apusys_pll[] = { |
| 81 | + { .compatible = "mediatek,mt8195-apusys_pll", }, |
| 82 | + {} |
| 83 | +}; |
| 84 | + |
| 85 | +static struct platform_driver clk_mt8195_apusys_pll_drv = { |
| 86 | + .probe = clk_mt8195_apusys_pll_probe, |
| 87 | + .driver = { |
| 88 | + .name = "clk-mt8195-apusys_pll", |
| 89 | + .of_match_table = of_match_clk_mt8195_apusys_pll, |
| 90 | + }, |
| 91 | +}; |
| 92 | +builtin_platform_driver(clk_mt8195_apusys_pll_drv); |
0 commit comments