Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 167 lines 4.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2025 MediaTek Inc. 4 * Guangjie Song <guangjie.song@mediatek.com> 5 * Copyright (c) 2025 Collabora Ltd. 6 * Laura Nao <laura.nao@collabora.com> 7 */ 8#include <dt-bindings/clock/mediatek,mt8196-clock.h> 9 10#include <linux/clk.h> 11#include <linux/module.h> 12#include <linux/of.h> 13#include <linux/of_address.h> 14#include <linux/of_device.h> 15#include <linux/platform_device.h> 16 17#include "clk-mtk.h" 18#include "clk-pll.h" 19 20#define ARMPLL_LL_CON0 0x008 21#define ARMPLL_LL_CON1 0x00c 22#define ARMPLL_LL_CON2 0x010 23#define ARMPLL_LL_CON3 0x014 24#define ARMPLL_BL_CON0 0x008 25#define ARMPLL_BL_CON1 0x00c 26#define ARMPLL_BL_CON2 0x010 27#define ARMPLL_BL_CON3 0x014 28#define ARMPLL_B_CON0 0x008 29#define ARMPLL_B_CON1 0x00c 30#define ARMPLL_B_CON2 0x010 31#define ARMPLL_B_CON3 0x014 32#define CCIPLL_CON0 0x008 33#define CCIPLL_CON1 0x00c 34#define CCIPLL_CON2 0x010 35#define CCIPLL_CON3 0x014 36#define PTPPLL_CON0 0x008 37#define PTPPLL_CON1 0x00c 38#define PTPPLL_CON2 0x010 39#define PTPPLL_CON3 0x014 40 41#define MT8196_PLL_FMAX (3800UL * MHZ) 42#define MT8196_PLL_FMIN (1500UL * MHZ) 43#define MT8196_INTEGER_BITS 8 44 45#define PLL(_id, _name, _reg, _en_reg, _en_mask, _pll_en_bit, \ 46 _flags, _rst_bar_mask, \ 47 _pd_reg, _pd_shift, _tuner_reg, \ 48 _tuner_en_reg, _tuner_en_bit, \ 49 _pcw_reg, _pcw_shift, _pcwbits) { \ 50 .id = _id, \ 51 .name = _name, \ 52 .reg = _reg, \ 53 .en_reg = _en_reg, \ 54 .en_mask = _en_mask, \ 55 .pll_en_bit = _pll_en_bit, \ 56 .flags = _flags, \ 57 .rst_bar_mask = _rst_bar_mask, \ 58 .fmax = MT8196_PLL_FMAX, \ 59 .fmin = MT8196_PLL_FMIN, \ 60 .pd_reg = _pd_reg, \ 61 .pd_shift = _pd_shift, \ 62 .tuner_reg = _tuner_reg, \ 63 .tuner_en_reg = _tuner_en_reg, \ 64 .tuner_en_bit = _tuner_en_bit, \ 65 .pcw_reg = _pcw_reg, \ 66 .pcw_shift = _pcw_shift, \ 67 .pcwbits = _pcwbits, \ 68 .pcwibits = MT8196_INTEGER_BITS, \ 69 } 70 71static const struct mtk_pll_data cpu_bl_plls[] = { 72 PLL(CLK_CPBL_ARMPLL_BL, "armpll-bl", ARMPLL_BL_CON0, ARMPLL_BL_CON0, 0, 73 0, PLL_AO, BIT(0), ARMPLL_BL_CON1, 24, 0, 0, 0, ARMPLL_BL_CON1, 0, 22), 74}; 75 76static const struct mtk_pll_data cpu_b_plls[] = { 77 PLL(CLK_CPB_ARMPLL_B, "armpll-b", ARMPLL_B_CON0, ARMPLL_B_CON0, 0, 0, 78 PLL_AO, BIT(0), ARMPLL_B_CON1, 24, 0, 0, 0, ARMPLL_B_CON1, 0, 22), 79}; 80 81static const struct mtk_pll_data cpu_ll_plls[] = { 82 PLL(CLK_CPLL_ARMPLL_LL, "armpll-ll", ARMPLL_LL_CON0, ARMPLL_LL_CON0, 0, 83 0, PLL_AO, BIT(0), ARMPLL_LL_CON1, 24, 0, 0, 0, ARMPLL_LL_CON1, 0, 22), 84}; 85 86static const struct mtk_pll_data cci_plls[] = { 87 PLL(CLK_CCIPLL, "ccipll", CCIPLL_CON0, CCIPLL_CON0, 0, 0, PLL_AO, 88 BIT(0), CCIPLL_CON1, 24, 0, 0, 0, CCIPLL_CON1, 0, 22), 89}; 90 91static const struct mtk_pll_data ptp_plls[] = { 92 PLL(CLK_PTPPLL, "ptppll", PTPPLL_CON0, PTPPLL_CON0, 0, 0, PLL_AO, 93 BIT(0), PTPPLL_CON1, 24, 0, 0, 0, PTPPLL_CON1, 0, 22), 94}; 95 96static const struct of_device_id of_match_clk_mt8196_mcu[] = { 97 { .compatible = "mediatek,mt8196-armpll-bl-pll-ctrl", 98 .data = &cpu_bl_plls }, 99 { .compatible = "mediatek,mt8196-armpll-b-pll-ctrl", 100 .data = &cpu_b_plls }, 101 { .compatible = "mediatek,mt8196-armpll-ll-pll-ctrl", 102 .data = &cpu_ll_plls }, 103 { .compatible = "mediatek,mt8196-ccipll-pll-ctrl", .data = &cci_plls }, 104 { .compatible = "mediatek,mt8196-ptppll-pll-ctrl", .data = &ptp_plls }, 105 { /* sentinel */ } 106}; 107MODULE_DEVICE_TABLE(of, of_match_clk_mt8196_mcu); 108 109static int clk_mt8196_mcu_probe(struct platform_device *pdev) 110{ 111 const struct mtk_pll_data *plls; 112 struct clk_hw_onecell_data *clk_data; 113 struct device_node *node = pdev->dev.of_node; 114 const int num_plls = 1; 115 int r; 116 117 plls = of_device_get_match_data(&pdev->dev); 118 if (!plls) 119 return -EINVAL; 120 121 clk_data = mtk_alloc_clk_data(num_plls); 122 if (!clk_data) 123 return -ENOMEM; 124 125 r = mtk_clk_register_plls(&pdev->dev, plls, num_plls, clk_data); 126 if (r) 127 goto free_clk_data; 128 129 r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); 130 if (r) 131 goto unregister_plls; 132 133 platform_set_drvdata(pdev, clk_data); 134 135 return r; 136 137unregister_plls: 138 mtk_clk_unregister_plls(plls, num_plls, clk_data); 139free_clk_data: 140 mtk_free_clk_data(clk_data); 141 142 return r; 143} 144 145static void clk_mt8196_mcu_remove(struct platform_device *pdev) 146{ 147 const struct mtk_pll_data *plls = of_device_get_match_data(&pdev->dev); 148 struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); 149 struct device_node *node = pdev->dev.of_node; 150 151 of_clk_del_provider(node); 152 mtk_clk_unregister_plls(plls, 1, clk_data); 153 mtk_free_clk_data(clk_data); 154} 155 156static struct platform_driver clk_mt8196_mcu_drv = { 157 .probe = clk_mt8196_mcu_probe, 158 .remove = clk_mt8196_mcu_remove, 159 .driver = { 160 .name = "clk-mt8196-mcu", 161 .of_match_table = of_match_clk_mt8196_mcu, 162 }, 163}; 164module_platform_driver(clk_mt8196_mcu_drv); 165 166MODULE_DESCRIPTION("MediaTek MT8196 mcusys clocks driver"); 167MODULE_LICENSE("GPL");