1*43c04ed7SYassine Oudjana // SPDX-License-Identifier: GPL-2.0 2*43c04ed7SYassine Oudjana /* 3*43c04ed7SYassine Oudjana * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com> 4*43c04ed7SYassine Oudjana */ 5*43c04ed7SYassine Oudjana 6*43c04ed7SYassine Oudjana #include <linux/clk-provider.h> 7*43c04ed7SYassine Oudjana #include <linux/platform_device.h> 8*43c04ed7SYassine Oudjana 9*43c04ed7SYassine Oudjana #include "clk-mtk.h" 10*43c04ed7SYassine Oudjana #include "clk-pll.h" 11*43c04ed7SYassine Oudjana 12*43c04ed7SYassine Oudjana #include <dt-bindings/clock/mediatek,mt6735-apmixedsys.h> 13*43c04ed7SYassine Oudjana 14*43c04ed7SYassine Oudjana #define AP_PLL_CON_5 0x014 15*43c04ed7SYassine Oudjana #define ARMPLL_CON0 0x200 16*43c04ed7SYassine Oudjana #define ARMPLL_CON1 0x204 17*43c04ed7SYassine Oudjana #define ARMPLL_PWR_CON0 0x20c 18*43c04ed7SYassine Oudjana #define MAINPLL_CON0 0x210 19*43c04ed7SYassine Oudjana #define MAINPLL_CON1 0x214 20*43c04ed7SYassine Oudjana #define MAINPLL_PWR_CON0 0x21c 21*43c04ed7SYassine Oudjana #define UNIVPLL_CON0 0x220 22*43c04ed7SYassine Oudjana #define UNIVPLL_CON1 0x224 23*43c04ed7SYassine Oudjana #define UNIVPLL_PWR_CON0 0x22c 24*43c04ed7SYassine Oudjana #define MMPLL_CON0 0x230 25*43c04ed7SYassine Oudjana #define MMPLL_CON1 0x234 26*43c04ed7SYassine Oudjana #define MMPLL_PWR_CON0 0x23c 27*43c04ed7SYassine Oudjana #define MSDCPLL_CON0 0x240 28*43c04ed7SYassine Oudjana #define MSDCPLL_CON1 0x244 29*43c04ed7SYassine Oudjana #define MSDCPLL_PWR_CON0 0x24c 30*43c04ed7SYassine Oudjana #define VENCPLL_CON0 0x250 31*43c04ed7SYassine Oudjana #define VENCPLL_CON1 0x254 32*43c04ed7SYassine Oudjana #define VENCPLL_PWR_CON0 0x25c 33*43c04ed7SYassine Oudjana #define TVDPLL_CON0 0x260 34*43c04ed7SYassine Oudjana #define TVDPLL_CON1 0x264 35*43c04ed7SYassine Oudjana #define TVDPLL_PWR_CON0 0x26c 36*43c04ed7SYassine Oudjana #define APLL1_CON0 0x270 37*43c04ed7SYassine Oudjana #define APLL1_CON1 0x274 38*43c04ed7SYassine Oudjana #define APLL1_CON2 0x278 39*43c04ed7SYassine Oudjana #define APLL1_PWR_CON0 0x280 40*43c04ed7SYassine Oudjana #define APLL2_CON0 0x284 41*43c04ed7SYassine Oudjana #define APLL2_CON1 0x288 42*43c04ed7SYassine Oudjana #define APLL2_CON2 0x28c 43*43c04ed7SYassine Oudjana #define APLL2_PWR_CON0 0x294 44*43c04ed7SYassine Oudjana 45*43c04ed7SYassine Oudjana #define CON0_RST_BAR BIT(24) 46*43c04ed7SYassine Oudjana 47*43c04ed7SYassine Oudjana #define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _rst_bar_mask, \ 48*43c04ed7SYassine Oudjana _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ 49*43c04ed7SYassine Oudjana _tuner_en_bit, _pcw_reg, _pcwbits, _flags) { \ 50*43c04ed7SYassine Oudjana .id = _id, \ 51*43c04ed7SYassine Oudjana .name = _name, \ 52*43c04ed7SYassine Oudjana .parent_name = "clk26m", \ 53*43c04ed7SYassine Oudjana .reg = _reg, \ 54*43c04ed7SYassine Oudjana .pwr_reg = _pwr_reg, \ 55*43c04ed7SYassine Oudjana .en_mask = _en_mask, \ 56*43c04ed7SYassine Oudjana .rst_bar_mask = _rst_bar_mask, \ 57*43c04ed7SYassine Oudjana .pd_reg = _pd_reg, \ 58*43c04ed7SYassine Oudjana .pd_shift = _pd_shift, \ 59*43c04ed7SYassine Oudjana .tuner_reg = _tuner_reg, \ 60*43c04ed7SYassine Oudjana .tuner_en_reg = _tuner_en_reg, \ 61*43c04ed7SYassine Oudjana .tuner_en_bit = _tuner_en_bit, \ 62*43c04ed7SYassine Oudjana .pcw_reg = _pcw_reg, \ 63*43c04ed7SYassine Oudjana .pcw_chg_reg = _pcw_reg, \ 64*43c04ed7SYassine Oudjana .pcwbits = _pcwbits, \ 65*43c04ed7SYassine Oudjana .flags = _flags, \ 66*43c04ed7SYassine Oudjana } 67*43c04ed7SYassine Oudjana 68*43c04ed7SYassine Oudjana static const struct mtk_pll_data apmixedsys_plls[] = { 69*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_ARMPLL, "armpll", ARMPLL_CON0, ARMPLL_PWR_CON0, 0x00000001, 0, ARMPLL_CON1, 24, 0, 0, 0, ARMPLL_CON1, 21, PLL_AO), 70*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_MAINPLL, "mainpll", MAINPLL_CON0, MAINPLL_PWR_CON0, 0xf0000101, CON0_RST_BAR, MAINPLL_CON1, 24, 0, 0, 0, MAINPLL_CON1, 21, HAVE_RST_BAR), 71*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_UNIVPLL, "univpll", UNIVPLL_CON0, UNIVPLL_PWR_CON0, 0xfc000001, CON0_RST_BAR, UNIVPLL_CON1, 24, 0, 0, 0, UNIVPLL_CON1, 21, HAVE_RST_BAR), 72*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_MMPLL, "mmpll", MMPLL_CON0, MMPLL_PWR_CON0, 0x00000001, 0, MMPLL_CON1, 24, 0, 0, 0, MMPLL_CON1, 21, 0), 73*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_MSDCPLL, "msdcpll", MSDCPLL_CON0, MSDCPLL_PWR_CON0, 0x00000001, 0, MSDCPLL_CON1, 24, 0, 0, 0, MSDCPLL_CON1, 21, 0), 74*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_VENCPLL, "vencpll", VENCPLL_CON0, VENCPLL_PWR_CON0, 0x00000001, CON0_RST_BAR, VENCPLL_CON1, 24, 0, 0, 0, VENCPLL_CON1, 21, HAVE_RST_BAR), 75*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_TVDPLL, "tvdpll", TVDPLL_CON0, TVDPLL_PWR_CON0, 0x00000001, 0, TVDPLL_CON1, 24, 0, 0, 0, TVDPLL_CON1, 21, 0), 76*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_APLL1, "apll1", APLL1_CON0, APLL1_PWR_CON0, 0x00000001, 0, APLL1_CON0, 4, APLL1_CON2, AP_PLL_CON_5, 0, APLL1_CON1, 31, 0), 77*43c04ed7SYassine Oudjana PLL(CLK_APMIXED_APLL2, "apll2", APLL2_CON0, APLL2_PWR_CON0, 0x00000001, 0, APLL2_CON0, 4, APLL2_CON2, AP_PLL_CON_5, 1, APLL2_CON1, 31, 0) 78*43c04ed7SYassine Oudjana }; 79*43c04ed7SYassine Oudjana 80*43c04ed7SYassine Oudjana static int clk_mt6735_apmixed_probe(struct platform_device *pdev) 81*43c04ed7SYassine Oudjana { 82*43c04ed7SYassine Oudjana void __iomem *base; 83*43c04ed7SYassine Oudjana struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 84*43c04ed7SYassine Oudjana struct clk_hw_onecell_data *clk_data; 85*43c04ed7SYassine Oudjana int ret; 86*43c04ed7SYassine Oudjana 87*43c04ed7SYassine Oudjana base = devm_ioremap_resource(&pdev->dev, res); 88*43c04ed7SYassine Oudjana if (IS_ERR(base)) 89*43c04ed7SYassine Oudjana return PTR_ERR(base); 90*43c04ed7SYassine Oudjana 91*43c04ed7SYassine Oudjana clk_data = mtk_alloc_clk_data(ARRAY_SIZE(apmixedsys_plls)); 92*43c04ed7SYassine Oudjana if (!clk_data) 93*43c04ed7SYassine Oudjana return -ENOMEM; 94*43c04ed7SYassine Oudjana platform_set_drvdata(pdev, clk_data); 95*43c04ed7SYassine Oudjana 96*43c04ed7SYassine Oudjana ret = mtk_clk_register_plls(pdev->dev.of_node, apmixedsys_plls, 97*43c04ed7SYassine Oudjana ARRAY_SIZE(apmixedsys_plls), clk_data); 98*43c04ed7SYassine Oudjana if (ret) { 99*43c04ed7SYassine Oudjana dev_err(&pdev->dev, "Failed to register PLLs: %d\n", ret); 100*43c04ed7SYassine Oudjana return ret; 101*43c04ed7SYassine Oudjana } 102*43c04ed7SYassine Oudjana 103*43c04ed7SYassine Oudjana ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, 104*43c04ed7SYassine Oudjana clk_data); 105*43c04ed7SYassine Oudjana if (ret) 106*43c04ed7SYassine Oudjana dev_err(&pdev->dev, 107*43c04ed7SYassine Oudjana "Failed to register clock provider: %d\n", ret); 108*43c04ed7SYassine Oudjana 109*43c04ed7SYassine Oudjana return ret; 110*43c04ed7SYassine Oudjana } 111*43c04ed7SYassine Oudjana 112*43c04ed7SYassine Oudjana static void clk_mt6735_apmixed_remove(struct platform_device *pdev) 113*43c04ed7SYassine Oudjana { 114*43c04ed7SYassine Oudjana struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); 115*43c04ed7SYassine Oudjana 116*43c04ed7SYassine Oudjana mtk_clk_unregister_plls(apmixedsys_plls, ARRAY_SIZE(apmixedsys_plls), clk_data); 117*43c04ed7SYassine Oudjana mtk_free_clk_data(clk_data); 118*43c04ed7SYassine Oudjana } 119*43c04ed7SYassine Oudjana 120*43c04ed7SYassine Oudjana static const struct of_device_id of_match_mt6735_apmixedsys[] = { 121*43c04ed7SYassine Oudjana { .compatible = "mediatek,mt6735-apmixedsys" }, 122*43c04ed7SYassine Oudjana { /* sentinel */ } 123*43c04ed7SYassine Oudjana }; 124*43c04ed7SYassine Oudjana MODULE_DEVICE_TABLE(of, of_match_mt6735_apmixedsys); 125*43c04ed7SYassine Oudjana 126*43c04ed7SYassine Oudjana static struct platform_driver clk_mt6735_apmixedsys = { 127*43c04ed7SYassine Oudjana .probe = clk_mt6735_apmixed_probe, 128*43c04ed7SYassine Oudjana .remove = clk_mt6735_apmixed_remove, 129*43c04ed7SYassine Oudjana .driver = { 130*43c04ed7SYassine Oudjana .name = "clk-mt6735-apmixedsys", 131*43c04ed7SYassine Oudjana .of_match_table = of_match_mt6735_apmixedsys, 132*43c04ed7SYassine Oudjana }, 133*43c04ed7SYassine Oudjana }; 134*43c04ed7SYassine Oudjana module_platform_driver(clk_mt6735_apmixedsys); 135*43c04ed7SYassine Oudjana 136*43c04ed7SYassine Oudjana MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>"); 137*43c04ed7SYassine Oudjana MODULE_DESCRIPTION("MediaTek MT6735 apmixedsys clock driver"); 138*43c04ed7SYassine Oudjana MODULE_LICENSE("GPL"); 139