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 #include <dt-bindings/reset/mediatek,mt8196-resets.h> 10 11 #include <linux/clk-provider.h> 12 #include <linux/module.h> 13 #include <linux/of_device.h> 14 #include <linux/platform_device.h> 15 16 #include "clk-gate.h" 17 #include "clk-mtk.h" 18 19 #define MT8196_UFSAO_RST0_SET_OFFSET 0x48 20 #define MT8196_UFSAO_RST1_SET_OFFSET 0x148 21 22 static const struct mtk_gate_regs ufsao0_cg_regs = { 23 .set_ofs = 0x108, 24 .clr_ofs = 0x10c, 25 .sta_ofs = 0x104, 26 }; 27 28 static const struct mtk_gate_regs ufsao1_cg_regs = { 29 .set_ofs = 0x8, 30 .clr_ofs = 0xc, 31 .sta_ofs = 0x4, 32 }; 33 34 #define GATE_UFSAO0(_id, _name, _parent, _shift) { \ 35 .id = _id, \ 36 .name = _name, \ 37 .parent_name = _parent, \ 38 .regs = &ufsao0_cg_regs, \ 39 .shift = _shift, \ 40 .ops = &mtk_clk_gate_ops_setclr, \ 41 } 42 43 #define GATE_UFSAO1(_id, _name, _parent, _shift) { \ 44 .id = _id, \ 45 .name = _name, \ 46 .parent_name = _parent, \ 47 .regs = &ufsao1_cg_regs, \ 48 .shift = _shift, \ 49 .ops = &mtk_clk_gate_ops_setclr, \ 50 } 51 52 static const struct mtk_gate ufsao_clks[] = { 53 /* UFSAO0 */ 54 GATE_UFSAO0(CLK_UFSAO_UFSHCI_UFS, "ufsao_ufshci_ufs", "ufs", 0), 55 GATE_UFSAO0(CLK_UFSAO_UFSHCI_AES, "ufsao_ufshci_aes", "aes_ufsfde", 1), 56 /* UFSAO1 */ 57 GATE_UFSAO1(CLK_UFSAO_UNIPRO_TX_SYM, "ufsao_unipro_tx_sym", "clk26m", 0), 58 GATE_UFSAO1(CLK_UFSAO_UNIPRO_RX_SYM0, "ufsao_unipro_rx_sym0", "clk26m", 1), 59 GATE_UFSAO1(CLK_UFSAO_UNIPRO_RX_SYM1, "ufsao_unipro_rx_sym1", "clk26m", 2), 60 GATE_UFSAO1(CLK_UFSAO_UNIPRO_SYS, "ufsao_unipro_sys", "ufs", 3), 61 GATE_UFSAO1(CLK_UFSAO_UNIPRO_SAP, "ufsao_unipro_sap", "clk26m", 4), 62 GATE_UFSAO1(CLK_UFSAO_PHY_SAP, "ufsao_phy_sap", "clk26m", 8), 63 }; 64 65 static u16 ufsao_rst_ofs[] = { 66 MT8196_UFSAO_RST0_SET_OFFSET, 67 MT8196_UFSAO_RST1_SET_OFFSET 68 }; 69 70 static u16 ufsao_rst_idx_map[] = { 71 [MT8196_UFSAO_RST0_UFS_MPHY] = 8, 72 [MT8196_UFSAO_RST1_UFS_UNIPRO] = 1 * RST_NR_PER_BANK + 0, 73 [MT8196_UFSAO_RST1_UFS_CRYPTO] = 1 * RST_NR_PER_BANK + 1, 74 [MT8196_UFSAO_RST1_UFSHCI] = 1 * RST_NR_PER_BANK + 2, 75 }; 76 77 static const struct mtk_clk_rst_desc ufsao_rst_desc = { 78 .version = MTK_RST_SET_CLR, 79 .rst_bank_ofs = ufsao_rst_ofs, 80 .rst_bank_nr = ARRAY_SIZE(ufsao_rst_ofs), 81 .rst_idx_map = ufsao_rst_idx_map, 82 .rst_idx_map_nr = ARRAY_SIZE(ufsao_rst_idx_map), 83 }; 84 85 static const struct mtk_clk_desc ufsao_mcd = { 86 .clks = ufsao_clks, 87 .num_clks = ARRAY_SIZE(ufsao_clks), 88 .rst_desc = &ufsao_rst_desc, 89 }; 90 91 static const struct of_device_id of_match_clk_mt8196_ufs_ao[] = { 92 { .compatible = "mediatek,mt8196-ufscfg-ao", .data = &ufsao_mcd }, 93 { /* sentinel */ } 94 }; 95 MODULE_DEVICE_TABLE(of, of_match_clk_mt8196_ufs_ao); 96 97 static struct platform_driver clk_mt8196_ufs_ao_drv = { 98 .probe = mtk_clk_simple_probe, 99 .remove = mtk_clk_simple_remove, 100 .driver = { 101 .name = "clk-mt8196-ufs-ao", 102 .of_match_table = of_match_clk_mt8196_ufs_ao, 103 }, 104 }; 105 106 module_platform_driver(clk_mt8196_ufs_ao_drv); 107 MODULE_DESCRIPTION("MediaTek MT8196 ufs_ao clocks driver"); 108 MODULE_LICENSE("GPL"); 109