Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Marvell Armada 375 SoC clocks
0004  *
0005  * Copyright (C) 2014 Marvell
0006  *
0007  * Gregory CLEMENT <gregory.clement@free-electrons.com>
0008  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
0009  * Andrew Lunn <andrew@lunn.ch>
0010  *
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/io.h>
0016 #include <linux/of.h>
0017 #include "common.h"
0018 
0019 /*
0020  * Core Clocks
0021  */
0022 
0023 /*
0024  * For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are
0025  * all modified at the same time, and not separately as for the Armada
0026  * 370 or the Armada XP SoCs.
0027  *
0028  * SAR1[21:17]   : CPU frequency    DDR frequency   L2 frequency
0029  *       6   =  400 MHz     400 MHz     200 MHz
0030  *       15  =  600 MHz     600 MHz     300 MHz
0031  *       21  =  800 MHz     534 MHz     400 MHz
0032  *       25  = 1000 MHz     500 MHz     500 MHz
0033  *       others reserved.
0034  *
0035  * SAR1[22]   : TCLK frequency
0036  *       0 = 166 MHz
0037  *       1 = 200 MHz
0038  */
0039 
0040 #define SAR1_A375_TCLK_FREQ_OPT        22
0041 #define SAR1_A375_TCLK_FREQ_OPT_MASK       0x1
0042 #define SAR1_A375_CPU_DDR_L2_FREQ_OPT      17
0043 #define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F
0044 
0045 static const u32 armada_375_tclk_frequencies[] __initconst = {
0046     166000000,
0047     200000000,
0048 };
0049 
0050 static u32 __init armada_375_get_tclk_freq(void __iomem *sar)
0051 {
0052     u8 tclk_freq_select;
0053 
0054     tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) &
0055                 SAR1_A375_TCLK_FREQ_OPT_MASK);
0056     return armada_375_tclk_frequencies[tclk_freq_select];
0057 }
0058 
0059 
0060 static const u32 armada_375_cpu_frequencies[] __initconst = {
0061     0, 0, 0, 0, 0, 0,
0062     400000000,
0063     0, 0, 0, 0, 0, 0, 0, 0,
0064     600000000,
0065     0, 0, 0, 0, 0,
0066     800000000,
0067     0, 0, 0,
0068     1000000000,
0069 };
0070 
0071 static u32 __init armada_375_get_cpu_freq(void __iomem *sar)
0072 {
0073     u8 cpu_freq_select;
0074 
0075     cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) &
0076                SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK);
0077     if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) {
0078         pr_err("Selected CPU frequency (%d) unsupported\n",
0079             cpu_freq_select);
0080         return 0;
0081     } else
0082         return armada_375_cpu_frequencies[cpu_freq_select];
0083 }
0084 
0085 enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 };
0086 
0087 static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = {
0088     { .id = A375_CPU_TO_L2,  .name = "l2clk" },
0089     { .id = A375_CPU_TO_DDR, .name = "ddrclk" },
0090 };
0091 
0092 static const int armada_375_cpu_l2_ratios[32][2] __initconst = {
0093     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0094     {0, 1}, {0, 1}, {1, 2}, {0, 1},
0095     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0096     {0, 1}, {0, 1}, {0, 1}, {1, 2},
0097     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0098     {0, 1}, {1, 2}, {0, 1}, {0, 1},
0099     {0, 1}, {1, 2}, {0, 1}, {0, 1},
0100     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0101 };
0102 
0103 static const int armada_375_cpu_ddr_ratios[32][2] __initconst = {
0104     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0105     {0, 1}, {0, 1}, {1, 1}, {0, 1},
0106     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0107     {0, 1}, {0, 1}, {0, 1}, {2, 3},
0108     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0109     {0, 1}, {2, 3}, {0, 1}, {0, 1},
0110     {0, 1}, {1, 2}, {0, 1}, {0, 1},
0111     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0112 };
0113 
0114 static void __init armada_375_get_clk_ratio(
0115     void __iomem *sar, int id, int *mult, int *div)
0116 {
0117     u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) &
0118         SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK);
0119 
0120     switch (id) {
0121     case A375_CPU_TO_L2:
0122         *mult = armada_375_cpu_l2_ratios[opt][0];
0123         *div = armada_375_cpu_l2_ratios[opt][1];
0124         break;
0125     case A375_CPU_TO_DDR:
0126         *mult = armada_375_cpu_ddr_ratios[opt][0];
0127         *div = armada_375_cpu_ddr_ratios[opt][1];
0128         break;
0129     }
0130 }
0131 
0132 static const struct coreclk_soc_desc armada_375_coreclks = {
0133     .get_tclk_freq = armada_375_get_tclk_freq,
0134     .get_cpu_freq = armada_375_get_cpu_freq,
0135     .get_clk_ratio = armada_375_get_clk_ratio,
0136     .ratios = armada_375_coreclk_ratios,
0137     .num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios),
0138 };
0139 
0140 static void __init armada_375_coreclk_init(struct device_node *np)
0141 {
0142     mvebu_coreclk_setup(np, &armada_375_coreclks);
0143 }
0144 CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock",
0145            armada_375_coreclk_init);
0146 
0147 /*
0148  * Clock Gating Control
0149  */
0150 static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = {
0151     { "mu", NULL, 2 },
0152     { "pp", NULL, 3 },
0153     { "ptp", NULL, 4 },
0154     { "pex0", NULL, 5 },
0155     { "pex1", NULL, 6 },
0156     { "audio", NULL, 8 },
0157     { "nd_clk", "nand", 11 },
0158     { "sata0_link", "sata0_core", 14 },
0159     { "sata0_core", NULL, 15 },
0160     { "usb3", NULL, 16 },
0161     { "sdio", NULL, 17 },
0162     { "usb", NULL, 18 },
0163     { "gop", NULL, 19 },
0164     { "sata1_link", "sata1_core", 20 },
0165     { "sata1_core", NULL, 21 },
0166     { "xor0", NULL, 22 },
0167     { "xor1", NULL, 23 },
0168     { "copro", NULL, 24 },
0169     { "tdm", NULL, 25 },
0170     { "crypto0_enc", NULL, 28 },
0171     { "crypto0_core", NULL, 29 },
0172     { "crypto1_enc", NULL, 30 },
0173     { "crypto1_core", NULL, 31 },
0174     { }
0175 };
0176 
0177 static void __init armada_375_clk_gating_init(struct device_node *np)
0178 {
0179     mvebu_clk_gating_setup(np, armada_375_gating_desc);
0180 }
0181 CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock",
0182            armada_375_clk_gating_init);