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