1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Amlogic Meson8 DDR clock controller 4 * 5 * Copyright (C) 2019 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 6 */ 7 8 #include <dt-bindings/clock/meson8-ddr-clkc.h> 9 10 #include <linux/clk-provider.h> 11 #include <linux/platform_device.h> 12 13 #include "clk-regmap.h" 14 #include "clk-pll.h" 15 #include "meson-clkc-utils.h" 16 17 #define AM_DDR_PLL_CNTL 0x00 18 #define AM_DDR_PLL_CNTL1 0x04 19 #define AM_DDR_PLL_CNTL2 0x08 20 #define AM_DDR_PLL_CNTL3 0x0c 21 #define AM_DDR_PLL_CNTL4 0x10 22 #define AM_DDR_PLL_STS 0x14 23 #define DDR_CLK_CNTL 0x18 24 #define DDR_CLK_STS 0x1c 25 26 static struct clk_regmap meson8_ddr_pll_dco = { 27 .data = &(struct meson_clk_pll_data){ 28 .en = { 29 .reg_off = AM_DDR_PLL_CNTL, 30 .shift = 30, 31 .width = 1, 32 }, 33 .m = { 34 .reg_off = AM_DDR_PLL_CNTL, 35 .shift = 0, 36 .width = 9, 37 }, 38 .n = { 39 .reg_off = AM_DDR_PLL_CNTL, 40 .shift = 9, 41 .width = 5, 42 }, 43 .l = { 44 .reg_off = AM_DDR_PLL_CNTL, 45 .shift = 31, 46 .width = 1, 47 }, 48 .rst = { 49 .reg_off = AM_DDR_PLL_CNTL, 50 .shift = 29, 51 .width = 1, 52 }, 53 }, 54 .hw.init = &(struct clk_init_data){ 55 .name = "ddr_pll_dco", 56 .ops = &meson_clk_pll_ro_ops, 57 .parent_data = &(const struct clk_parent_data) { 58 .fw_name = "xtal", 59 }, 60 .num_parents = 1, 61 }, 62 }; 63 64 static struct clk_regmap meson8_ddr_pll = { 65 .data = &(struct clk_regmap_div_data){ 66 .offset = AM_DDR_PLL_CNTL, 67 .shift = 16, 68 .width = 2, 69 .flags = CLK_DIVIDER_POWER_OF_TWO, 70 }, 71 .hw.init = &(struct clk_init_data){ 72 .name = "ddr_pll", 73 .ops = &clk_regmap_divider_ro_ops, 74 .parent_hws = (const struct clk_hw *[]) { 75 &meson8_ddr_pll_dco.hw 76 }, 77 .num_parents = 1, 78 }, 79 }; 80 81 static struct clk_hw *meson8_ddr_hw_clks[] = { 82 [DDR_CLKID_DDR_PLL_DCO] = &meson8_ddr_pll_dco.hw, 83 [DDR_CLKID_DDR_PLL] = &meson8_ddr_pll.hw, 84 }; 85 86 static const struct meson_clkc_data meson8_ddr_clkc_data = { 87 .hw_clks = { 88 .hws = meson8_ddr_hw_clks, 89 .num = ARRAY_SIZE(meson8_ddr_hw_clks), 90 }, 91 }; 92 93 static const struct of_device_id meson8_ddr_clkc_match_table[] = { 94 { 95 .compatible = "amlogic,meson8-ddr-clkc", 96 .data = &meson8_ddr_clkc_data, 97 }, { 98 .compatible = "amlogic,meson8b-ddr-clkc", 99 .data = &meson8_ddr_clkc_data, 100 }, 101 { /* sentinel */ } 102 }; 103 104 static struct platform_driver meson8_ddr_clkc_driver = { 105 .probe = meson_clkc_mmio_probe, 106 .driver = { 107 .name = "meson8-ddr-clkc", 108 .of_match_table = meson8_ddr_clkc_match_table, 109 }, 110 }; 111 112 builtin_platform_driver(meson8_ddr_clkc_driver); 113