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

Merge tag 'clk-mvebu-3xx-3.15' of git://git.infradead.org/linux-mvebu into clk-next-mvebu

clock: mvebu new SoC changes for v3.15

- mvebu (Armada 375/380/385)
- extend corediv clock driver to support new SoCs
- add core and gating clock drivers for new SoCs

+536 -35
+14
Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
··· 11 11 3 = hclk (DRAM control clock) 12 12 4 = dramclk (DDR clock) 13 13 14 + The following is a list of provided IDs and clock names on Armada 375: 15 + 0 = tclk (Internal Bus clock) 16 + 1 = cpuclk (CPU clock) 17 + 2 = l2clk (L2 Cache clock) 18 + 3 = ddrclk (DDR clock) 19 + 20 + The following is a list of provided IDs and clock names on Armada 380/385: 21 + 0 = tclk (Internal Bus clock) 22 + 1 = cpuclk (CPU clock) 23 + 2 = l2clk (L2 Cache clock) 24 + 3 = ddrclk (DDR clock) 25 + 14 26 The following is a list of provided IDs and clock names on Kirkwood and Dove: 15 27 0 = tclk (Internal Bus clock) 16 28 1 = cpuclk (CPU0 clock) ··· 32 20 Required properties: 33 21 - compatible : shall be one of the following: 34 22 "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks 23 + "marvell,armada-375-core-clock" - For Armada 375 SoC core clocks 24 + "marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks 35 25 "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks 36 26 "marvell,dove-core-clock" - for Dove SoC core clocks 37 27 "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
+61 -4
Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
··· 1 1 * Gated Clock bindings for Marvell EBU SoCs 2 2 3 - Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be 4 - gated to save some power. The clock consumer should specify the desired clock 5 - by having the clock ID in its "clocks" phandle cell. The clock ID is directly 6 - mapped to the corresponding clock gating control bit in HW to ease manual clock 3 + Marvell Armada 370/375/380/385/XP, Dove and Kirkwood allow some 4 + peripheral clocks to be gated to save some power. The clock consumer 5 + should specify the desired clock by having the clock ID in its 6 + "clocks" phandle cell. The clock ID is directly mapped to the 7 + corresponding clock gating control bit in HW to ease manual clock 7 8 lookup in datasheet. 8 9 9 10 The following is a list of provided IDs for Armada 370: ··· 22 21 25 tdm Time Division Mplx 23 22 28 ddr DDR Cntrl 24 23 30 sata1 SATA Host 0 24 + 25 + The following is a list of provided IDs for Armada 375: 26 + ID Clock Peripheral 27 + ----------------------------------- 28 + 2 mu Management Unit 29 + 3 pp Packet Processor 30 + 4 ptp PTP 31 + 5 pex0 PCIe 0 Clock out 32 + 6 pex1 PCIe 1 Clock out 33 + 8 audio Audio Cntrl 34 + 11 nd_clk Nand Flash Cntrl 35 + 14 sata0_link SATA 0 Link 36 + 15 sata0_core SATA 0 Core 37 + 16 usb3 USB3 Host 38 + 17 sdio SDHCI Host 39 + 18 usb USB Host 40 + 19 gop Gigabit Ethernet MAC 41 + 20 sata1_link SATA 1 Link 42 + 21 sata1_core SATA 1 Core 43 + 22 xor0 XOR DMA 0 44 + 23 xor1 XOR DMA 0 45 + 24 copro Coprocessor 46 + 25 tdm Time Division Mplx 47 + 28 crypto0_enc Cryptographic Unit Port 0 Encryption 48 + 29 crypto0_core Cryptographic Unit Port 0 Core 49 + 30 crypto1_enc Cryptographic Unit Port 1 Encryption 50 + 31 crypto1_core Cryptographic Unit Port 1 Core 51 + 52 + The following is a list of provided IDs for Armada 380/385: 53 + ID Clock Peripheral 54 + ----------------------------------- 55 + 0 audio Audio 56 + 2 ge2 Gigabit Ethernet 2 57 + 3 ge1 Gigabit Ethernet 1 58 + 4 ge0 Gigabit Ethernet 0 59 + 5 pex1 PCIe 1 60 + 6 pex2 PCIe 2 61 + 7 pex3 PCIe 3 62 + 8 pex0 PCIe 0 63 + 9 usb3h0 USB3 Host 0 64 + 10 usb3h1 USB3 Host 1 65 + 11 usb3d USB3 Device 66 + 13 bm Buffer Management 67 + 14 crypto0z Cryptographic 0 Z 68 + 15 sata0 SATA 0 69 + 16 crypto1z Cryptographic 1 Z 70 + 17 sdio SDIO 71 + 18 usb2 USB 2 72 + 21 crypto1 Cryptographic 1 73 + 22 xor0 XOR 0 74 + 23 crypto0 Cryptographic 0 75 + 25 tdm Time Division Multiplexing 76 + 28 xor1 XOR 1 77 + 30 sata1 SATA 1 25 78 26 79 The following is a list of provided IDs for Armada XP: 27 80 ID Clock Peripheral ··· 150 95 Required properties: 151 96 - compatible : shall be one of the following: 152 97 "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating 98 + "marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating 99 + "marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating 153 100 "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating 154 101 "marvell,dove-gating-clock" - for Dove SoC clock gating 155 102 "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
+8
drivers/clk/mvebu/Kconfig
··· 13 13 select MVEBU_CLK_CPU 14 14 select MVEBU_CLK_COREDIV 15 15 16 + config ARMADA_375_CLK 17 + bool 18 + select MVEBU_CLK_COMMON 19 + 20 + config ARMADA_38X_CLK 21 + bool 22 + select MVEBU_CLK_COMMON 23 + 16 24 config ARMADA_XP_CLK 17 25 bool 18 26 select MVEBU_CLK_COMMON
+2
drivers/clk/mvebu/Makefile
··· 3 3 obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o 4 4 5 5 obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o 6 + obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o 7 + obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o 6 8 obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o 7 9 obj-$(CONFIG_DOVE_CLK) += dove.o 8 10 obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o
+184
drivers/clk/mvebu/armada-375.c
··· 1 + /* 2 + * Marvell Armada 375 SoC clocks 3 + * 4 + * Copyright (C) 2014 Marvell 5 + * 6 + * Gregory CLEMENT <gregory.clement@free-electrons.com> 7 + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 8 + * Andrew Lunn <andrew@lunn.ch> 9 + * 10 + * This file is licensed under the terms of the GNU General Public 11 + * License version 2. This program is licensed "as is" without any 12 + * warranty of any kind, whether express or implied. 13 + */ 14 + 15 + #include <linux/kernel.h> 16 + #include <linux/clk-provider.h> 17 + #include <linux/io.h> 18 + #include <linux/of.h> 19 + #include "common.h" 20 + 21 + /* 22 + * Core Clocks 23 + */ 24 + 25 + /* 26 + * For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are 27 + * all modified at the same time, and not separately as for the Armada 28 + * 370 or the Armada XP SoCs. 29 + * 30 + * SAR0[21:17] : CPU frequency DDR frequency L2 frequency 31 + * 6 = 400 MHz 400 MHz 200 MHz 32 + * 15 = 600 MHz 600 MHz 300 MHz 33 + * 21 = 800 MHz 534 MHz 400 MHz 34 + * 25 = 1000 MHz 500 MHz 500 MHz 35 + * others reserved. 36 + * 37 + * SAR0[22] : TCLK frequency 38 + * 0 = 166 MHz 39 + * 1 = 200 MHz 40 + */ 41 + 42 + #define SAR1_A375_TCLK_FREQ_OPT 22 43 + #define SAR1_A375_TCLK_FREQ_OPT_MASK 0x1 44 + #define SAR1_A375_CPU_DDR_L2_FREQ_OPT 17 45 + #define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F 46 + 47 + static const u32 armada_375_tclk_frequencies[] __initconst = { 48 + 166000000, 49 + 200000000, 50 + }; 51 + 52 + static u32 __init armada_375_get_tclk_freq(void __iomem *sar) 53 + { 54 + u8 tclk_freq_select; 55 + 56 + tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) & 57 + SAR1_A375_TCLK_FREQ_OPT_MASK); 58 + return armada_375_tclk_frequencies[tclk_freq_select]; 59 + } 60 + 61 + 62 + static const u32 armada_375_cpu_frequencies[] __initconst = { 63 + 0, 0, 0, 0, 0, 0, 64 + 400000000, 65 + 0, 0, 0, 0, 0, 0, 0, 0, 66 + 600000000, 67 + 0, 0, 0, 0, 0, 68 + 800000000, 69 + 0, 0, 0, 70 + 1000000000, 71 + }; 72 + 73 + static u32 __init armada_375_get_cpu_freq(void __iomem *sar) 74 + { 75 + u8 cpu_freq_select; 76 + 77 + cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & 78 + SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); 79 + if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) { 80 + pr_err("Selected CPU frequency (%d) unsupported\n", 81 + cpu_freq_select); 82 + return 0; 83 + } else 84 + return armada_375_cpu_frequencies[cpu_freq_select]; 85 + } 86 + 87 + enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 }; 88 + 89 + static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = { 90 + { .id = A375_CPU_TO_L2, .name = "l2clk" }, 91 + { .id = A375_CPU_TO_DDR, .name = "ddrclk" }, 92 + }; 93 + 94 + static const int armada_375_cpu_l2_ratios[32][2] __initconst = { 95 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 96 + {0, 1}, {0, 1}, {1, 2}, {0, 1}, 97 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 98 + {0, 1}, {0, 1}, {0, 1}, {1, 2}, 99 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 100 + {0, 1}, {1, 2}, {0, 1}, {0, 1}, 101 + {0, 1}, {1, 2}, {0, 1}, {0, 1}, 102 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 103 + }; 104 + 105 + static const int armada_375_cpu_ddr_ratios[32][2] __initconst = { 106 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 107 + {0, 1}, {0, 1}, {1, 1}, {0, 1}, 108 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 109 + {0, 1}, {0, 1}, {0, 1}, {2, 3}, 110 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 111 + {0, 1}, {2, 3}, {0, 1}, {0, 1}, 112 + {0, 1}, {1, 2}, {0, 1}, {0, 1}, 113 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 114 + }; 115 + 116 + static void __init armada_375_get_clk_ratio( 117 + void __iomem *sar, int id, int *mult, int *div) 118 + { 119 + u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & 120 + SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); 121 + 122 + switch (id) { 123 + case A375_CPU_TO_L2: 124 + *mult = armada_375_cpu_l2_ratios[opt][0]; 125 + *div = armada_375_cpu_l2_ratios[opt][1]; 126 + break; 127 + case A375_CPU_TO_DDR: 128 + *mult = armada_375_cpu_ddr_ratios[opt][0]; 129 + *div = armada_375_cpu_ddr_ratios[opt][1]; 130 + break; 131 + } 132 + } 133 + 134 + static const struct coreclk_soc_desc armada_375_coreclks = { 135 + .get_tclk_freq = armada_375_get_tclk_freq, 136 + .get_cpu_freq = armada_375_get_cpu_freq, 137 + .get_clk_ratio = armada_375_get_clk_ratio, 138 + .ratios = armada_375_coreclk_ratios, 139 + .num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios), 140 + }; 141 + 142 + static void __init armada_375_coreclk_init(struct device_node *np) 143 + { 144 + mvebu_coreclk_setup(np, &armada_375_coreclks); 145 + } 146 + CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock", 147 + armada_375_coreclk_init); 148 + 149 + /* 150 + * Clock Gating Control 151 + */ 152 + static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = { 153 + { "mu", NULL, 2 }, 154 + { "pp", NULL, 3 }, 155 + { "ptp", NULL, 4 }, 156 + { "pex0", NULL, 5 }, 157 + { "pex1", NULL, 6 }, 158 + { "audio", NULL, 8 }, 159 + { "nd_clk", "nand", 11 }, 160 + { "sata0_link", "sata0_core", 14 }, 161 + { "sata0_core", NULL, 15 }, 162 + { "usb3", NULL, 16 }, 163 + { "sdio", NULL, 17 }, 164 + { "usb", NULL, 18 }, 165 + { "gop", NULL, 19 }, 166 + { "sata1_link", "sata1_core", 20 }, 167 + { "sata1_core", NULL, 21 }, 168 + { "xor0", NULL, 22 }, 169 + { "xor1", NULL, 23 }, 170 + { "copro", NULL, 24 }, 171 + { "tdm", NULL, 25 }, 172 + { "crypto0_enc", NULL, 28 }, 173 + { "crypto0_core", NULL, 29 }, 174 + { "crypto1_enc", NULL, 30 }, 175 + { "crypto1_core", NULL, 31 }, 176 + { } 177 + }; 178 + 179 + static void __init armada_375_clk_gating_init(struct device_node *np) 180 + { 181 + mvebu_clk_gating_setup(np, armada_375_gating_desc); 182 + } 183 + CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock", 184 + armada_375_clk_gating_init);
+167
drivers/clk/mvebu/armada-38x.c
··· 1 + /* 2 + * Marvell Armada 380/385 SoC clocks 3 + * 4 + * Copyright (C) 2014 Marvell 5 + * 6 + * Gregory CLEMENT <gregory.clement@free-electrons.com> 7 + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 8 + * Andrew Lunn <andrew@lunn.ch> 9 + * 10 + * This file is licensed under the terms of the GNU General Public 11 + * License version 2. This program is licensed "as is" without any 12 + * warranty of any kind, whether express or implied. 13 + */ 14 + 15 + #include <linux/kernel.h> 16 + #include <linux/clk-provider.h> 17 + #include <linux/io.h> 18 + #include <linux/of.h> 19 + #include "common.h" 20 + 21 + /* 22 + * SAR[14:10] : Ratios between PCLK0, NBCLK, HCLK and DRAM clocks 23 + * 24 + * SAR[15] : TCLK frequency 25 + * 0 = 250 MHz 26 + * 1 = 200 MHz 27 + */ 28 + 29 + #define SAR_A380_TCLK_FREQ_OPT 15 30 + #define SAR_A380_TCLK_FREQ_OPT_MASK 0x1 31 + #define SAR_A380_CPU_DDR_L2_FREQ_OPT 10 32 + #define SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK 0x1F 33 + 34 + static const u32 armada_38x_tclk_frequencies[] __initconst = { 35 + 250000000, 36 + 200000000, 37 + }; 38 + 39 + static u32 __init armada_38x_get_tclk_freq(void __iomem *sar) 40 + { 41 + u8 tclk_freq_select; 42 + 43 + tclk_freq_select = ((readl(sar) >> SAR_A380_TCLK_FREQ_OPT) & 44 + SAR_A380_TCLK_FREQ_OPT_MASK); 45 + return armada_38x_tclk_frequencies[tclk_freq_select]; 46 + } 47 + 48 + static const u32 armada_38x_cpu_frequencies[] __initconst = { 49 + 0, 0, 0, 0, 50 + 1066 * 1000 * 1000, 0, 0, 0, 51 + 1332 * 1000 * 1000, 0, 0, 0, 52 + 1600 * 1000 * 1000, 53 + }; 54 + 55 + static u32 __init armada_38x_get_cpu_freq(void __iomem *sar) 56 + { 57 + u8 cpu_freq_select; 58 + 59 + cpu_freq_select = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) & 60 + SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK); 61 + if (cpu_freq_select >= ARRAY_SIZE(armada_38x_cpu_frequencies)) { 62 + pr_err("Selected CPU frequency (%d) unsupported\n", 63 + cpu_freq_select); 64 + return 0; 65 + } 66 + 67 + return armada_38x_cpu_frequencies[cpu_freq_select]; 68 + } 69 + 70 + enum { A380_CPU_TO_DDR, A380_CPU_TO_L2 }; 71 + 72 + static const struct coreclk_ratio armada_38x_coreclk_ratios[] __initconst = { 73 + { .id = A380_CPU_TO_L2, .name = "l2clk" }, 74 + { .id = A380_CPU_TO_DDR, .name = "ddrclk" }, 75 + }; 76 + 77 + static const int armada_38x_cpu_l2_ratios[32][2] __initconst = { 78 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 79 + {1, 2}, {0, 1}, {0, 1}, {0, 1}, 80 + {1, 2}, {0, 1}, {0, 1}, {0, 1}, 81 + {1, 2}, {0, 1}, {0, 1}, {0, 1}, 82 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 83 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 84 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 85 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 86 + }; 87 + 88 + static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = { 89 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 90 + {1, 2}, {0, 1}, {0, 1}, {0, 1}, 91 + {1, 2}, {0, 1}, {0, 1}, {0, 1}, 92 + {1, 2}, {0, 1}, {0, 1}, {0, 1}, 93 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 94 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 95 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 96 + {0, 1}, {0, 1}, {0, 1}, {0, 1}, 97 + }; 98 + 99 + static void __init armada_38x_get_clk_ratio( 100 + void __iomem *sar, int id, int *mult, int *div) 101 + { 102 + u32 opt = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) & 103 + SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK); 104 + 105 + switch (id) { 106 + case A380_CPU_TO_L2: 107 + *mult = armada_38x_cpu_l2_ratios[opt][0]; 108 + *div = armada_38x_cpu_l2_ratios[opt][1]; 109 + break; 110 + case A380_CPU_TO_DDR: 111 + *mult = armada_38x_cpu_ddr_ratios[opt][0]; 112 + *div = armada_38x_cpu_ddr_ratios[opt][1]; 113 + break; 114 + } 115 + } 116 + 117 + static const struct coreclk_soc_desc armada_38x_coreclks = { 118 + .get_tclk_freq = armada_38x_get_tclk_freq, 119 + .get_cpu_freq = armada_38x_get_cpu_freq, 120 + .get_clk_ratio = armada_38x_get_clk_ratio, 121 + .ratios = armada_38x_coreclk_ratios, 122 + .num_ratios = ARRAY_SIZE(armada_38x_coreclk_ratios), 123 + }; 124 + 125 + static void __init armada_38x_coreclk_init(struct device_node *np) 126 + { 127 + mvebu_coreclk_setup(np, &armada_38x_coreclks); 128 + } 129 + CLK_OF_DECLARE(armada_38x_core_clk, "marvell,armada-380-core-clock", 130 + armada_38x_coreclk_init); 131 + 132 + /* 133 + * Clock Gating Control 134 + */ 135 + static const struct clk_gating_soc_desc armada_38x_gating_desc[] __initconst = { 136 + { "audio", NULL, 0 }, 137 + { "ge2", NULL, 2 }, 138 + { "ge1", NULL, 3 }, 139 + { "ge0", NULL, 4 }, 140 + { "pex1", NULL, 5 }, 141 + { "pex2", NULL, 6 }, 142 + { "pex3", NULL, 7 }, 143 + { "pex0", NULL, 8 }, 144 + { "usb3h0", NULL, 9 }, 145 + { "usb3h1", NULL, 10 }, 146 + { "usb3d", NULL, 11 }, 147 + { "bm", NULL, 13 }, 148 + { "crypto0z", NULL, 14 }, 149 + { "sata0", NULL, 15 }, 150 + { "crypto1z", NULL, 16 }, 151 + { "sdio", NULL, 17 }, 152 + { "usb2", NULL, 18 }, 153 + { "crypto1", NULL, 21 }, 154 + { "xor0", NULL, 22 }, 155 + { "crypto0", NULL, 23 }, 156 + { "tdm", NULL, 25 }, 157 + { "xor1", NULL, 28 }, 158 + { "sata1", NULL, 30 }, 159 + { } 160 + }; 161 + 162 + static void __init armada_38x_clk_gating_init(struct device_node *np) 163 + { 164 + mvebu_clk_gating_setup(np, armada_38x_gating_desc); 165 + } 166 + CLK_OF_DECLARE(armada_38x_clk_gating, "marvell,armada-380-gating-clock", 167 + armada_38x_clk_gating_init);
+100 -31
drivers/clk/mvebu/clk-corediv.c
··· 18 18 #include "common.h" 19 19 20 20 #define CORE_CLK_DIV_RATIO_MASK 0xff 21 - #define CORE_CLK_DIV_RATIO_RELOAD BIT(8) 22 - #define CORE_CLK_DIV_ENABLE_OFFSET 24 23 - #define CORE_CLK_DIV_RATIO_OFFSET 0x8 24 21 22 + /* 23 + * This structure describes the hardware details (bit offset and mask) 24 + * to configure one particular core divider clock. Those hardware 25 + * details may differ from one SoC to another. This structure is 26 + * therefore typically instantiated statically to describe the 27 + * hardware details. 28 + */ 25 29 struct clk_corediv_desc { 26 30 unsigned int mask; 27 31 unsigned int offset; 28 32 unsigned int fieldbit; 29 33 }; 30 34 35 + /* 36 + * This structure describes the hardware details to configure the core 37 + * divider clocks on a given SoC. Amongst others, it points to the 38 + * array of core divider clock descriptors for this SoC, as well as 39 + * the corresponding operations to manipulate them. 40 + */ 41 + struct clk_corediv_soc_desc { 42 + const struct clk_corediv_desc *descs; 43 + unsigned int ndescs; 44 + const struct clk_ops ops; 45 + u32 ratio_reload; 46 + u32 enable_bit_offset; 47 + u32 ratio_offset; 48 + }; 49 + 50 + /* 51 + * This structure represents one core divider clock for the clock 52 + * framework, and is dynamically allocated for each core divider clock 53 + * existing in the current SoC. 54 + */ 31 55 struct clk_corediv { 32 56 struct clk_hw hw; 33 57 void __iomem *reg; 34 - struct clk_corediv_desc desc; 58 + const struct clk_corediv_desc *desc; 59 + const struct clk_corediv_soc_desc *soc_desc; 35 60 spinlock_t lock; 36 61 }; 37 62 38 63 static struct clk_onecell_data clk_data; 39 64 40 - static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = { 65 + /* 66 + * Description of the core divider clocks available. For now, we 67 + * support only NAND, and it is available at the same register 68 + * locations regardless of the SoC. 69 + */ 70 + static const struct clk_corediv_desc mvebu_corediv_desc[] = { 41 71 { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */ 42 72 }; 43 73 ··· 76 46 static int clk_corediv_is_enabled(struct clk_hw *hwclk) 77 47 { 78 48 struct clk_corediv *corediv = to_corediv_clk(hwclk); 79 - struct clk_corediv_desc *desc = &corediv->desc; 80 - u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET; 49 + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 50 + const struct clk_corediv_desc *desc = corediv->desc; 51 + u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset; 81 52 82 53 return !!(readl(corediv->reg) & enable_mask); 83 54 } ··· 86 55 static int clk_corediv_enable(struct clk_hw *hwclk) 87 56 { 88 57 struct clk_corediv *corediv = to_corediv_clk(hwclk); 89 - struct clk_corediv_desc *desc = &corediv->desc; 58 + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 59 + const struct clk_corediv_desc *desc = corediv->desc; 90 60 unsigned long flags = 0; 91 61 u32 reg; 92 62 93 63 spin_lock_irqsave(&corediv->lock, flags); 94 64 95 65 reg = readl(corediv->reg); 96 - reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); 66 + reg |= (BIT(desc->fieldbit) << soc_desc->enable_bit_offset); 97 67 writel(reg, corediv->reg); 98 68 99 69 spin_unlock_irqrestore(&corediv->lock, flags); ··· 105 73 static void clk_corediv_disable(struct clk_hw *hwclk) 106 74 { 107 75 struct clk_corediv *corediv = to_corediv_clk(hwclk); 108 - struct clk_corediv_desc *desc = &corediv->desc; 76 + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 77 + const struct clk_corediv_desc *desc = corediv->desc; 109 78 unsigned long flags = 0; 110 79 u32 reg; 111 80 112 81 spin_lock_irqsave(&corediv->lock, flags); 113 82 114 83 reg = readl(corediv->reg); 115 - reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); 84 + reg &= ~(BIT(desc->fieldbit) << soc_desc->enable_bit_offset); 116 85 writel(reg, corediv->reg); 117 86 118 87 spin_unlock_irqrestore(&corediv->lock, flags); ··· 123 90 unsigned long parent_rate) 124 91 { 125 92 struct clk_corediv *corediv = to_corediv_clk(hwclk); 126 - struct clk_corediv_desc *desc = &corediv->desc; 93 + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 94 + const struct clk_corediv_desc *desc = corediv->desc; 127 95 u32 reg, div; 128 96 129 - reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); 97 + reg = readl(corediv->reg + soc_desc->ratio_offset); 130 98 div = (reg >> desc->offset) & desc->mask; 131 99 return parent_rate / div; 132 100 } ··· 151 117 unsigned long parent_rate) 152 118 { 153 119 struct clk_corediv *corediv = to_corediv_clk(hwclk); 154 - struct clk_corediv_desc *desc = &corediv->desc; 120 + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 121 + const struct clk_corediv_desc *desc = corediv->desc; 155 122 unsigned long flags = 0; 156 123 u32 reg, div; 157 124 ··· 161 126 spin_lock_irqsave(&corediv->lock, flags); 162 127 163 128 /* Write new divider to the divider ratio register */ 164 - reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); 129 + reg = readl(corediv->reg + soc_desc->ratio_offset); 165 130 reg &= ~(desc->mask << desc->offset); 166 131 reg |= (div & desc->mask) << desc->offset; 167 - writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); 132 + writel(reg, corediv->reg + soc_desc->ratio_offset); 168 133 169 134 /* Set reload-force for this clock */ 170 135 reg = readl(corediv->reg) | BIT(desc->fieldbit); 171 136 writel(reg, corediv->reg); 172 137 173 138 /* Now trigger the clock update */ 174 - reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD; 139 + reg = readl(corediv->reg) | soc_desc->ratio_reload; 175 140 writel(reg, corediv->reg); 176 141 177 142 /* ··· 179 144 * ratios request and the reload request. 180 145 */ 181 146 udelay(1000); 182 - reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD); 147 + reg &= ~(CORE_CLK_DIV_RATIO_MASK | soc_desc->ratio_reload); 183 148 writel(reg, corediv->reg); 184 149 udelay(1000); 185 150 ··· 188 153 return 0; 189 154 } 190 155 191 - static const struct clk_ops corediv_ops = { 192 - .enable = clk_corediv_enable, 193 - .disable = clk_corediv_disable, 194 - .is_enabled = clk_corediv_is_enabled, 195 - .recalc_rate = clk_corediv_recalc_rate, 196 - .round_rate = clk_corediv_round_rate, 197 - .set_rate = clk_corediv_set_rate, 156 + static const struct clk_corediv_soc_desc armada370_corediv_soc = { 157 + .descs = mvebu_corediv_desc, 158 + .ndescs = ARRAY_SIZE(mvebu_corediv_desc), 159 + .ops = { 160 + .enable = clk_corediv_enable, 161 + .disable = clk_corediv_disable, 162 + .is_enabled = clk_corediv_is_enabled, 163 + .recalc_rate = clk_corediv_recalc_rate, 164 + .round_rate = clk_corediv_round_rate, 165 + .set_rate = clk_corediv_set_rate, 166 + }, 167 + .ratio_reload = BIT(8), 168 + .enable_bit_offset = 24, 169 + .ratio_offset = 0x8, 198 170 }; 199 171 200 - static void __init mvebu_corediv_clk_init(struct device_node *node) 172 + static const struct clk_corediv_soc_desc armada375_corediv_soc = { 173 + .descs = mvebu_corediv_desc, 174 + .ndescs = ARRAY_SIZE(mvebu_corediv_desc), 175 + .ops = { 176 + .recalc_rate = clk_corediv_recalc_rate, 177 + .round_rate = clk_corediv_round_rate, 178 + .set_rate = clk_corediv_set_rate, 179 + }, 180 + .ratio_reload = BIT(8), 181 + .ratio_offset = 0x8, 182 + }; 183 + 184 + static void __init 185 + mvebu_corediv_clk_init(struct device_node *node, 186 + const struct clk_corediv_soc_desc *soc_desc) 201 187 { 202 188 struct clk_init_data init; 203 189 struct clk_corediv *corediv; ··· 234 178 235 179 parent_name = of_clk_get_parent_name(node, 0); 236 180 237 - clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc); 181 + clk_data.clk_num = soc_desc->ndescs; 238 182 239 183 /* clks holds the clock array */ 240 184 clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), ··· 255 199 init.num_parents = 1; 256 200 init.parent_names = &parent_name; 257 201 init.name = clk_name; 258 - init.ops = &corediv_ops; 202 + init.ops = &soc_desc->ops; 259 203 init.flags = 0; 260 204 261 - corediv[i].desc = mvebu_corediv_desc[i]; 205 + corediv[i].soc_desc = soc_desc; 206 + corediv[i].desc = soc_desc->descs + i; 262 207 corediv[i].reg = base; 263 208 corediv[i].hw.init = &init; 264 209 ··· 276 219 err_unmap: 277 220 iounmap(base); 278 221 } 279 - CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock", 280 - mvebu_corediv_clk_init); 222 + 223 + static void __init armada370_corediv_clk_init(struct device_node *node) 224 + { 225 + return mvebu_corediv_clk_init(node, &armada370_corediv_soc); 226 + } 227 + CLK_OF_DECLARE(armada370_corediv_clk, "marvell,armada-370-corediv-clock", 228 + armada370_corediv_clk_init); 229 + 230 + static void __init armada375_corediv_clk_init(struct device_node *node) 231 + { 232 + return mvebu_corediv_clk_init(node, &armada375_corediv_soc); 233 + } 234 + CLK_OF_DECLARE(armada375_corediv_clk, "marvell,armada-375-corediv-clock", 235 + armada375_corediv_clk_init);