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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTCDYfAAoJEP45WPkGe8ZnWmIP/1+nOfhLVcHhZTn/eu0TKblX gD/Sd7goRArfFU/JnOYrwx8iqe8U2IgRVhndRHc3FRouvFF/u3CS0f9BHcUZ1CRb jWHN0FAw7ZzD3Qp3mFtnjs4ltqdGSqvmtqYC66AlkB7ssppr0Esfvei8bcrsB1Y7 J9L6p6xgQhBXO8VZWmQqvJdUls2d0KyJRP+GQVwFcCxHXLLyYM2SW+ypKpDHSsej Ux0qmLxGsj+YEvlJk/s7F6JFcRT7PTzAfd+0zzXTip+gG0euDm3mB/IvxY4tBTCt qscgB/JFJ1tu02CXJpznBLm4VGcTtEq4SfGGWUxUx92ZDodUratzqEjKTN0Hti84 t7IsYb+Miz1X3/+BlEzHf91V2nVW96CHAJiwcukPvjrbGV+KTAKBpOA7f8GUy1CD kEvebiKSZgwROCcO+vfLYAAgirc2Bu8tI5SL55VbX6NnmTa+B986Ebxw8orIM6lb 9KmwkClkquHM/0hFqvHYDPi4IRT5rki6ayZRvXVV0tSDBDRiELdLeFe90e+UMzs8 g0pWCb6q5ozXnwrELJSuQCxwu85I0K78FCGAbXw4UTWnorxNTu2kzMnsABVMFy6j /Hp2hYyCaTvxinVUld2Kg3Eqvi6w4N+FBW30zqh9yyJpEgQfKLqwzPDwoiJ7+c/k daqB4goGPLbc00RdNr1B =Aah7 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
05135b4cb4
|
@ -11,6 +11,18 @@ The following is a list of provided IDs and clock names on Armada 370/XP:
|
|||
3 = hclk (DRAM control clock)
|
||||
4 = dramclk (DDR clock)
|
||||
|
||||
The following is a list of provided IDs and clock names on Armada 375:
|
||||
0 = tclk (Internal Bus clock)
|
||||
1 = cpuclk (CPU clock)
|
||||
2 = l2clk (L2 Cache clock)
|
||||
3 = ddrclk (DDR clock)
|
||||
|
||||
The following is a list of provided IDs and clock names on Armada 380/385:
|
||||
0 = tclk (Internal Bus clock)
|
||||
1 = cpuclk (CPU clock)
|
||||
2 = l2clk (L2 Cache clock)
|
||||
3 = ddrclk (DDR clock)
|
||||
|
||||
The following is a list of provided IDs and clock names on Kirkwood and Dove:
|
||||
0 = tclk (Internal Bus clock)
|
||||
1 = cpuclk (CPU0 clock)
|
||||
|
@ -20,6 +32,8 @@ The following is a list of provided IDs and clock names on Kirkwood and Dove:
|
|||
Required properties:
|
||||
- compatible : shall be one of the following:
|
||||
"marvell,armada-370-core-clock" - For Armada 370 SoC core clocks
|
||||
"marvell,armada-375-core-clock" - For Armada 375 SoC core clocks
|
||||
"marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks
|
||||
"marvell,armada-xp-core-clock" - For Armada XP SoC core clocks
|
||||
"marvell,dove-core-clock" - for Dove SoC core clocks
|
||||
"marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
* Gated Clock bindings for Marvell EBU SoCs
|
||||
|
||||
Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be
|
||||
gated to save some power. The clock consumer should specify the desired clock
|
||||
by having the clock ID in its "clocks" phandle cell. The clock ID is directly
|
||||
mapped to the corresponding clock gating control bit in HW to ease manual clock
|
||||
Marvell Armada 370/375/380/385/XP, Dove and Kirkwood allow some
|
||||
peripheral clocks to be gated to save some power. The clock consumer
|
||||
should specify the desired clock by having the clock ID in its
|
||||
"clocks" phandle cell. The clock ID is directly mapped to the
|
||||
corresponding clock gating control bit in HW to ease manual clock
|
||||
lookup in datasheet.
|
||||
|
||||
The following is a list of provided IDs for Armada 370:
|
||||
|
@ -22,6 +23,60 @@ ID Clock Peripheral
|
|||
28 ddr DDR Cntrl
|
||||
30 sata1 SATA Host 0
|
||||
|
||||
The following is a list of provided IDs for Armada 375:
|
||||
ID Clock Peripheral
|
||||
-----------------------------------
|
||||
2 mu Management Unit
|
||||
3 pp Packet Processor
|
||||
4 ptp PTP
|
||||
5 pex0 PCIe 0 Clock out
|
||||
6 pex1 PCIe 1 Clock out
|
||||
8 audio Audio Cntrl
|
||||
11 nd_clk Nand Flash Cntrl
|
||||
14 sata0_link SATA 0 Link
|
||||
15 sata0_core SATA 0 Core
|
||||
16 usb3 USB3 Host
|
||||
17 sdio SDHCI Host
|
||||
18 usb USB Host
|
||||
19 gop Gigabit Ethernet MAC
|
||||
20 sata1_link SATA 1 Link
|
||||
21 sata1_core SATA 1 Core
|
||||
22 xor0 XOR DMA 0
|
||||
23 xor1 XOR DMA 0
|
||||
24 copro Coprocessor
|
||||
25 tdm Time Division Mplx
|
||||
28 crypto0_enc Cryptographic Unit Port 0 Encryption
|
||||
29 crypto0_core Cryptographic Unit Port 0 Core
|
||||
30 crypto1_enc Cryptographic Unit Port 1 Encryption
|
||||
31 crypto1_core Cryptographic Unit Port 1 Core
|
||||
|
||||
The following is a list of provided IDs for Armada 380/385:
|
||||
ID Clock Peripheral
|
||||
-----------------------------------
|
||||
0 audio Audio
|
||||
2 ge2 Gigabit Ethernet 2
|
||||
3 ge1 Gigabit Ethernet 1
|
||||
4 ge0 Gigabit Ethernet 0
|
||||
5 pex1 PCIe 1
|
||||
6 pex2 PCIe 2
|
||||
7 pex3 PCIe 3
|
||||
8 pex0 PCIe 0
|
||||
9 usb3h0 USB3 Host 0
|
||||
10 usb3h1 USB3 Host 1
|
||||
11 usb3d USB3 Device
|
||||
13 bm Buffer Management
|
||||
14 crypto0z Cryptographic 0 Z
|
||||
15 sata0 SATA 0
|
||||
16 crypto1z Cryptographic 1 Z
|
||||
17 sdio SDIO
|
||||
18 usb2 USB 2
|
||||
21 crypto1 Cryptographic 1
|
||||
22 xor0 XOR 0
|
||||
23 crypto0 Cryptographic 0
|
||||
25 tdm Time Division Multiplexing
|
||||
28 xor1 XOR 1
|
||||
30 sata1 SATA 1
|
||||
|
||||
The following is a list of provided IDs for Armada XP:
|
||||
ID Clock Peripheral
|
||||
-----------------------------------
|
||||
|
@ -95,6 +150,8 @@ ID Clock Peripheral
|
|||
Required properties:
|
||||
- compatible : shall be one of the following:
|
||||
"marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating
|
||||
"marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating
|
||||
"marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating
|
||||
"marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating
|
||||
"marvell,dove-gating-clock" - for Dove SoC clock gating
|
||||
"marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
|
||||
|
|
|
@ -13,6 +13,14 @@ config ARMADA_370_CLK
|
|||
select MVEBU_CLK_CPU
|
||||
select MVEBU_CLK_COREDIV
|
||||
|
||||
config ARMADA_375_CLK
|
||||
bool
|
||||
select MVEBU_CLK_COMMON
|
||||
|
||||
config ARMADA_38X_CLK
|
||||
bool
|
||||
select MVEBU_CLK_COMMON
|
||||
|
||||
config ARMADA_XP_CLK
|
||||
bool
|
||||
select MVEBU_CLK_COMMON
|
||||
|
|
|
@ -3,6 +3,8 @@ obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
|
|||
obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o
|
||||
|
||||
obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o
|
||||
obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o
|
||||
obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o
|
||||
obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o
|
||||
obj-$(CONFIG_DOVE_CLK) += dove.o
|
||||
obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Marvell Armada 375 SoC clocks
|
||||
*
|
||||
* Copyright (C) 2014 Marvell
|
||||
*
|
||||
* Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Andrew Lunn <andrew@lunn.ch>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Core Clocks
|
||||
*/
|
||||
|
||||
/*
|
||||
* For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are
|
||||
* all modified at the same time, and not separately as for the Armada
|
||||
* 370 or the Armada XP SoCs.
|
||||
*
|
||||
* SAR0[21:17] : CPU frequency DDR frequency L2 frequency
|
||||
* 6 = 400 MHz 400 MHz 200 MHz
|
||||
* 15 = 600 MHz 600 MHz 300 MHz
|
||||
* 21 = 800 MHz 534 MHz 400 MHz
|
||||
* 25 = 1000 MHz 500 MHz 500 MHz
|
||||
* others reserved.
|
||||
*
|
||||
* SAR0[22] : TCLK frequency
|
||||
* 0 = 166 MHz
|
||||
* 1 = 200 MHz
|
||||
*/
|
||||
|
||||
#define SAR1_A375_TCLK_FREQ_OPT 22
|
||||
#define SAR1_A375_TCLK_FREQ_OPT_MASK 0x1
|
||||
#define SAR1_A375_CPU_DDR_L2_FREQ_OPT 17
|
||||
#define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F
|
||||
|
||||
static const u32 armada_375_tclk_frequencies[] __initconst = {
|
||||
166000000,
|
||||
200000000,
|
||||
};
|
||||
|
||||
static u32 __init armada_375_get_tclk_freq(void __iomem *sar)
|
||||
{
|
||||
u8 tclk_freq_select;
|
||||
|
||||
tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) &
|
||||
SAR1_A375_TCLK_FREQ_OPT_MASK);
|
||||
return armada_375_tclk_frequencies[tclk_freq_select];
|
||||
}
|
||||
|
||||
|
||||
static const u32 armada_375_cpu_frequencies[] __initconst = {
|
||||
0, 0, 0, 0, 0, 0,
|
||||
400000000,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
600000000,
|
||||
0, 0, 0, 0, 0,
|
||||
800000000,
|
||||
0, 0, 0,
|
||||
1000000000,
|
||||
};
|
||||
|
||||
static u32 __init armada_375_get_cpu_freq(void __iomem *sar)
|
||||
{
|
||||
u8 cpu_freq_select;
|
||||
|
||||
cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) &
|
||||
SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK);
|
||||
if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) {
|
||||
pr_err("Selected CPU frequency (%d) unsupported\n",
|
||||
cpu_freq_select);
|
||||
return 0;
|
||||
} else
|
||||
return armada_375_cpu_frequencies[cpu_freq_select];
|
||||
}
|
||||
|
||||
enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 };
|
||||
|
||||
static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = {
|
||||
{ .id = A375_CPU_TO_L2, .name = "l2clk" },
|
||||
{ .id = A375_CPU_TO_DDR, .name = "ddrclk" },
|
||||
};
|
||||
|
||||
static const int armada_375_cpu_l2_ratios[32][2] __initconst = {
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {1, 2}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {1, 2},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {1, 2}, {0, 1}, {0, 1},
|
||||
{0, 1}, {1, 2}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
};
|
||||
|
||||
static const int armada_375_cpu_ddr_ratios[32][2] __initconst = {
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {1, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {2, 3},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {2, 3}, {0, 1}, {0, 1},
|
||||
{0, 1}, {1, 2}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
};
|
||||
|
||||
static void __init armada_375_get_clk_ratio(
|
||||
void __iomem *sar, int id, int *mult, int *div)
|
||||
{
|
||||
u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) &
|
||||
SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK);
|
||||
|
||||
switch (id) {
|
||||
case A375_CPU_TO_L2:
|
||||
*mult = armada_375_cpu_l2_ratios[opt][0];
|
||||
*div = armada_375_cpu_l2_ratios[opt][1];
|
||||
break;
|
||||
case A375_CPU_TO_DDR:
|
||||
*mult = armada_375_cpu_ddr_ratios[opt][0];
|
||||
*div = armada_375_cpu_ddr_ratios[opt][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct coreclk_soc_desc armada_375_coreclks = {
|
||||
.get_tclk_freq = armada_375_get_tclk_freq,
|
||||
.get_cpu_freq = armada_375_get_cpu_freq,
|
||||
.get_clk_ratio = armada_375_get_clk_ratio,
|
||||
.ratios = armada_375_coreclk_ratios,
|
||||
.num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios),
|
||||
};
|
||||
|
||||
static void __init armada_375_coreclk_init(struct device_node *np)
|
||||
{
|
||||
mvebu_coreclk_setup(np, &armada_375_coreclks);
|
||||
}
|
||||
CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock",
|
||||
armada_375_coreclk_init);
|
||||
|
||||
/*
|
||||
* Clock Gating Control
|
||||
*/
|
||||
static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = {
|
||||
{ "mu", NULL, 2 },
|
||||
{ "pp", NULL, 3 },
|
||||
{ "ptp", NULL, 4 },
|
||||
{ "pex0", NULL, 5 },
|
||||
{ "pex1", NULL, 6 },
|
||||
{ "audio", NULL, 8 },
|
||||
{ "nd_clk", "nand", 11 },
|
||||
{ "sata0_link", "sata0_core", 14 },
|
||||
{ "sata0_core", NULL, 15 },
|
||||
{ "usb3", NULL, 16 },
|
||||
{ "sdio", NULL, 17 },
|
||||
{ "usb", NULL, 18 },
|
||||
{ "gop", NULL, 19 },
|
||||
{ "sata1_link", "sata1_core", 20 },
|
||||
{ "sata1_core", NULL, 21 },
|
||||
{ "xor0", NULL, 22 },
|
||||
{ "xor1", NULL, 23 },
|
||||
{ "copro", NULL, 24 },
|
||||
{ "tdm", NULL, 25 },
|
||||
{ "crypto0_enc", NULL, 28 },
|
||||
{ "crypto0_core", NULL, 29 },
|
||||
{ "crypto1_enc", NULL, 30 },
|
||||
{ "crypto1_core", NULL, 31 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void __init armada_375_clk_gating_init(struct device_node *np)
|
||||
{
|
||||
mvebu_clk_gating_setup(np, armada_375_gating_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock",
|
||||
armada_375_clk_gating_init);
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Marvell Armada 380/385 SoC clocks
|
||||
*
|
||||
* Copyright (C) 2014 Marvell
|
||||
*
|
||||
* Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Andrew Lunn <andrew@lunn.ch>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* SAR[14:10] : Ratios between PCLK0, NBCLK, HCLK and DRAM clocks
|
||||
*
|
||||
* SAR[15] : TCLK frequency
|
||||
* 0 = 250 MHz
|
||||
* 1 = 200 MHz
|
||||
*/
|
||||
|
||||
#define SAR_A380_TCLK_FREQ_OPT 15
|
||||
#define SAR_A380_TCLK_FREQ_OPT_MASK 0x1
|
||||
#define SAR_A380_CPU_DDR_L2_FREQ_OPT 10
|
||||
#define SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK 0x1F
|
||||
|
||||
static const u32 armada_38x_tclk_frequencies[] __initconst = {
|
||||
250000000,
|
||||
200000000,
|
||||
};
|
||||
|
||||
static u32 __init armada_38x_get_tclk_freq(void __iomem *sar)
|
||||
{
|
||||
u8 tclk_freq_select;
|
||||
|
||||
tclk_freq_select = ((readl(sar) >> SAR_A380_TCLK_FREQ_OPT) &
|
||||
SAR_A380_TCLK_FREQ_OPT_MASK);
|
||||
return armada_38x_tclk_frequencies[tclk_freq_select];
|
||||
}
|
||||
|
||||
static const u32 armada_38x_cpu_frequencies[] __initconst = {
|
||||
0, 0, 0, 0,
|
||||
1066 * 1000 * 1000, 0, 0, 0,
|
||||
1332 * 1000 * 1000, 0, 0, 0,
|
||||
1600 * 1000 * 1000,
|
||||
};
|
||||
|
||||
static u32 __init armada_38x_get_cpu_freq(void __iomem *sar)
|
||||
{
|
||||
u8 cpu_freq_select;
|
||||
|
||||
cpu_freq_select = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) &
|
||||
SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK);
|
||||
if (cpu_freq_select >= ARRAY_SIZE(armada_38x_cpu_frequencies)) {
|
||||
pr_err("Selected CPU frequency (%d) unsupported\n",
|
||||
cpu_freq_select);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return armada_38x_cpu_frequencies[cpu_freq_select];
|
||||
}
|
||||
|
||||
enum { A380_CPU_TO_DDR, A380_CPU_TO_L2 };
|
||||
|
||||
static const struct coreclk_ratio armada_38x_coreclk_ratios[] __initconst = {
|
||||
{ .id = A380_CPU_TO_L2, .name = "l2clk" },
|
||||
{ .id = A380_CPU_TO_DDR, .name = "ddrclk" },
|
||||
};
|
||||
|
||||
static const int armada_38x_cpu_l2_ratios[32][2] __initconst = {
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{1, 2}, {0, 1}, {0, 1}, {0, 1},
|
||||
{1, 2}, {0, 1}, {0, 1}, {0, 1},
|
||||
{1, 2}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
};
|
||||
|
||||
static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = {
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{1, 2}, {0, 1}, {0, 1}, {0, 1},
|
||||
{1, 2}, {0, 1}, {0, 1}, {0, 1},
|
||||
{1, 2}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}, {0, 1}, {0, 1},
|
||||
};
|
||||
|
||||
static void __init armada_38x_get_clk_ratio(
|
||||
void __iomem *sar, int id, int *mult, int *div)
|
||||
{
|
||||
u32 opt = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) &
|
||||
SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK);
|
||||
|
||||
switch (id) {
|
||||
case A380_CPU_TO_L2:
|
||||
*mult = armada_38x_cpu_l2_ratios[opt][0];
|
||||
*div = armada_38x_cpu_l2_ratios[opt][1];
|
||||
break;
|
||||
case A380_CPU_TO_DDR:
|
||||
*mult = armada_38x_cpu_ddr_ratios[opt][0];
|
||||
*div = armada_38x_cpu_ddr_ratios[opt][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct coreclk_soc_desc armada_38x_coreclks = {
|
||||
.get_tclk_freq = armada_38x_get_tclk_freq,
|
||||
.get_cpu_freq = armada_38x_get_cpu_freq,
|
||||
.get_clk_ratio = armada_38x_get_clk_ratio,
|
||||
.ratios = armada_38x_coreclk_ratios,
|
||||
.num_ratios = ARRAY_SIZE(armada_38x_coreclk_ratios),
|
||||
};
|
||||
|
||||
static void __init armada_38x_coreclk_init(struct device_node *np)
|
||||
{
|
||||
mvebu_coreclk_setup(np, &armada_38x_coreclks);
|
||||
}
|
||||
CLK_OF_DECLARE(armada_38x_core_clk, "marvell,armada-380-core-clock",
|
||||
armada_38x_coreclk_init);
|
||||
|
||||
/*
|
||||
* Clock Gating Control
|
||||
*/
|
||||
static const struct clk_gating_soc_desc armada_38x_gating_desc[] __initconst = {
|
||||
{ "audio", NULL, 0 },
|
||||
{ "ge2", NULL, 2 },
|
||||
{ "ge1", NULL, 3 },
|
||||
{ "ge0", NULL, 4 },
|
||||
{ "pex1", NULL, 5 },
|
||||
{ "pex2", NULL, 6 },
|
||||
{ "pex3", NULL, 7 },
|
||||
{ "pex0", NULL, 8 },
|
||||
{ "usb3h0", NULL, 9 },
|
||||
{ "usb3h1", NULL, 10 },
|
||||
{ "usb3d", NULL, 11 },
|
||||
{ "bm", NULL, 13 },
|
||||
{ "crypto0z", NULL, 14 },
|
||||
{ "sata0", NULL, 15 },
|
||||
{ "crypto1z", NULL, 16 },
|
||||
{ "sdio", NULL, 17 },
|
||||
{ "usb2", NULL, 18 },
|
||||
{ "crypto1", NULL, 21 },
|
||||
{ "xor0", NULL, 22 },
|
||||
{ "crypto0", NULL, 23 },
|
||||
{ "tdm", NULL, 25 },
|
||||
{ "xor1", NULL, 28 },
|
||||
{ "sata1", NULL, 30 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void __init armada_38x_clk_gating_init(struct device_node *np)
|
||||
{
|
||||
mvebu_clk_gating_setup(np, armada_38x_gating_desc);
|
||||
}
|
||||
CLK_OF_DECLARE(armada_38x_clk_gating, "marvell,armada-380-gating-clock",
|
||||
armada_38x_clk_gating_init);
|
|
@ -18,26 +18,56 @@
|
|||
#include "common.h"
|
||||
|
||||
#define CORE_CLK_DIV_RATIO_MASK 0xff
|
||||
#define CORE_CLK_DIV_RATIO_RELOAD BIT(8)
|
||||
#define CORE_CLK_DIV_ENABLE_OFFSET 24
|
||||
#define CORE_CLK_DIV_RATIO_OFFSET 0x8
|
||||
|
||||
/*
|
||||
* This structure describes the hardware details (bit offset and mask)
|
||||
* to configure one particular core divider clock. Those hardware
|
||||
* details may differ from one SoC to another. This structure is
|
||||
* therefore typically instantiated statically to describe the
|
||||
* hardware details.
|
||||
*/
|
||||
struct clk_corediv_desc {
|
||||
unsigned int mask;
|
||||
unsigned int offset;
|
||||
unsigned int fieldbit;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure describes the hardware details to configure the core
|
||||
* divider clocks on a given SoC. Amongst others, it points to the
|
||||
* array of core divider clock descriptors for this SoC, as well as
|
||||
* the corresponding operations to manipulate them.
|
||||
*/
|
||||
struct clk_corediv_soc_desc {
|
||||
const struct clk_corediv_desc *descs;
|
||||
unsigned int ndescs;
|
||||
const struct clk_ops ops;
|
||||
u32 ratio_reload;
|
||||
u32 enable_bit_offset;
|
||||
u32 ratio_offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure represents one core divider clock for the clock
|
||||
* framework, and is dynamically allocated for each core divider clock
|
||||
* existing in the current SoC.
|
||||
*/
|
||||
struct clk_corediv {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
struct clk_corediv_desc desc;
|
||||
const struct clk_corediv_desc *desc;
|
||||
const struct clk_corediv_soc_desc *soc_desc;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
||||
static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = {
|
||||
/*
|
||||
* Description of the core divider clocks available. For now, we
|
||||
* support only NAND, and it is available at the same register
|
||||
* locations regardless of the SoC.
|
||||
*/
|
||||
static const struct clk_corediv_desc mvebu_corediv_desc[] = {
|
||||
{ .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */
|
||||
};
|
||||
|
||||
|
@ -46,8 +76,9 @@ static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = {
|
|||
static int clk_corediv_is_enabled(struct clk_hw *hwclk)
|
||||
{
|
||||
struct clk_corediv *corediv = to_corediv_clk(hwclk);
|
||||
struct clk_corediv_desc *desc = &corediv->desc;
|
||||
u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET;
|
||||
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
|
||||
const struct clk_corediv_desc *desc = corediv->desc;
|
||||
u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset;
|
||||
|
||||
return !!(readl(corediv->reg) & enable_mask);
|
||||
}
|
||||
|
@ -55,14 +86,15 @@ static int clk_corediv_is_enabled(struct clk_hw *hwclk)
|
|||
static int clk_corediv_enable(struct clk_hw *hwclk)
|
||||
{
|
||||
struct clk_corediv *corediv = to_corediv_clk(hwclk);
|
||||
struct clk_corediv_desc *desc = &corediv->desc;
|
||||
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
|
||||
const struct clk_corediv_desc *desc = corediv->desc;
|
||||
unsigned long flags = 0;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&corediv->lock, flags);
|
||||
|
||||
reg = readl(corediv->reg);
|
||||
reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET);
|
||||
reg |= (BIT(desc->fieldbit) << soc_desc->enable_bit_offset);
|
||||
writel(reg, corediv->reg);
|
||||
|
||||
spin_unlock_irqrestore(&corediv->lock, flags);
|
||||
|
@ -73,14 +105,15 @@ static int clk_corediv_enable(struct clk_hw *hwclk)
|
|||
static void clk_corediv_disable(struct clk_hw *hwclk)
|
||||
{
|
||||
struct clk_corediv *corediv = to_corediv_clk(hwclk);
|
||||
struct clk_corediv_desc *desc = &corediv->desc;
|
||||
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
|
||||
const struct clk_corediv_desc *desc = corediv->desc;
|
||||
unsigned long flags = 0;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&corediv->lock, flags);
|
||||
|
||||
reg = readl(corediv->reg);
|
||||
reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET);
|
||||
reg &= ~(BIT(desc->fieldbit) << soc_desc->enable_bit_offset);
|
||||
writel(reg, corediv->reg);
|
||||
|
||||
spin_unlock_irqrestore(&corediv->lock, flags);
|
||||
|
@ -90,10 +123,11 @@ static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk,
|
|||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_corediv *corediv = to_corediv_clk(hwclk);
|
||||
struct clk_corediv_desc *desc = &corediv->desc;
|
||||
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
|
||||
const struct clk_corediv_desc *desc = corediv->desc;
|
||||
u32 reg, div;
|
||||
|
||||
reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
|
||||
reg = readl(corediv->reg + soc_desc->ratio_offset);
|
||||
div = (reg >> desc->offset) & desc->mask;
|
||||
return parent_rate / div;
|
||||
}
|
||||
|
@ -117,7 +151,8 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
|
|||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_corediv *corediv = to_corediv_clk(hwclk);
|
||||
struct clk_corediv_desc *desc = &corediv->desc;
|
||||
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
|
||||
const struct clk_corediv_desc *desc = corediv->desc;
|
||||
unsigned long flags = 0;
|
||||
u32 reg, div;
|
||||
|
||||
|
@ -126,17 +161,17 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
|
|||
spin_lock_irqsave(&corediv->lock, flags);
|
||||
|
||||
/* Write new divider to the divider ratio register */
|
||||
reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
|
||||
reg = readl(corediv->reg + soc_desc->ratio_offset);
|
||||
reg &= ~(desc->mask << desc->offset);
|
||||
reg |= (div & desc->mask) << desc->offset;
|
||||
writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
|
||||
writel(reg, corediv->reg + soc_desc->ratio_offset);
|
||||
|
||||
/* Set reload-force for this clock */
|
||||
reg = readl(corediv->reg) | BIT(desc->fieldbit);
|
||||
writel(reg, corediv->reg);
|
||||
|
||||
/* Now trigger the clock update */
|
||||
reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD;
|
||||
reg = readl(corediv->reg) | soc_desc->ratio_reload;
|
||||
writel(reg, corediv->reg);
|
||||
|
||||
/*
|
||||
|
@ -144,7 +179,7 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
|
|||
* ratios request and the reload request.
|
||||
*/
|
||||
udelay(1000);
|
||||
reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD);
|
||||
reg &= ~(CORE_CLK_DIV_RATIO_MASK | soc_desc->ratio_reload);
|
||||
writel(reg, corediv->reg);
|
||||
udelay(1000);
|
||||
|
||||
|
@ -153,16 +188,37 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops corediv_ops = {
|
||||
.enable = clk_corediv_enable,
|
||||
.disable = clk_corediv_disable,
|
||||
.is_enabled = clk_corediv_is_enabled,
|
||||
.recalc_rate = clk_corediv_recalc_rate,
|
||||
.round_rate = clk_corediv_round_rate,
|
||||
.set_rate = clk_corediv_set_rate,
|
||||
static const struct clk_corediv_soc_desc armada370_corediv_soc = {
|
||||
.descs = mvebu_corediv_desc,
|
||||
.ndescs = ARRAY_SIZE(mvebu_corediv_desc),
|
||||
.ops = {
|
||||
.enable = clk_corediv_enable,
|
||||
.disable = clk_corediv_disable,
|
||||
.is_enabled = clk_corediv_is_enabled,
|
||||
.recalc_rate = clk_corediv_recalc_rate,
|
||||
.round_rate = clk_corediv_round_rate,
|
||||
.set_rate = clk_corediv_set_rate,
|
||||
},
|
||||
.ratio_reload = BIT(8),
|
||||
.enable_bit_offset = 24,
|
||||
.ratio_offset = 0x8,
|
||||
};
|
||||
|
||||
static void __init mvebu_corediv_clk_init(struct device_node *node)
|
||||
static const struct clk_corediv_soc_desc armada375_corediv_soc = {
|
||||
.descs = mvebu_corediv_desc,
|
||||
.ndescs = ARRAY_SIZE(mvebu_corediv_desc),
|
||||
.ops = {
|
||||
.recalc_rate = clk_corediv_recalc_rate,
|
||||
.round_rate = clk_corediv_round_rate,
|
||||
.set_rate = clk_corediv_set_rate,
|
||||
},
|
||||
.ratio_reload = BIT(8),
|
||||
.ratio_offset = 0x8,
|
||||
};
|
||||
|
||||
static void __init
|
||||
mvebu_corediv_clk_init(struct device_node *node,
|
||||
const struct clk_corediv_soc_desc *soc_desc)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_corediv *corediv;
|
||||
|
@ -178,7 +234,7 @@ static void __init mvebu_corediv_clk_init(struct device_node *node)
|
|||
|
||||
parent_name = of_clk_get_parent_name(node, 0);
|
||||
|
||||
clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc);
|
||||
clk_data.clk_num = soc_desc->ndescs;
|
||||
|
||||
/* clks holds the clock array */
|
||||
clks = kcalloc(clk_data.clk_num, sizeof(struct clk *),
|
||||
|
@ -199,10 +255,11 @@ static void __init mvebu_corediv_clk_init(struct device_node *node)
|
|||
init.num_parents = 1;
|
||||
init.parent_names = &parent_name;
|
||||
init.name = clk_name;
|
||||
init.ops = &corediv_ops;
|
||||
init.ops = &soc_desc->ops;
|
||||
init.flags = 0;
|
||||
|
||||
corediv[i].desc = mvebu_corediv_desc[i];
|
||||
corediv[i].soc_desc = soc_desc;
|
||||
corediv[i].desc = soc_desc->descs + i;
|
||||
corediv[i].reg = base;
|
||||
corediv[i].hw.init = &init;
|
||||
|
||||
|
@ -219,5 +276,17 @@ err_free_clks:
|
|||
err_unmap:
|
||||
iounmap(base);
|
||||
}
|
||||
CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock",
|
||||
mvebu_corediv_clk_init);
|
||||
|
||||
static void __init armada370_corediv_clk_init(struct device_node *node)
|
||||
{
|
||||
return mvebu_corediv_clk_init(node, &armada370_corediv_soc);
|
||||
}
|
||||
CLK_OF_DECLARE(armada370_corediv_clk, "marvell,armada-370-corediv-clock",
|
||||
armada370_corediv_clk_init);
|
||||
|
||||
static void __init armada375_corediv_clk_init(struct device_node *node)
|
||||
{
|
||||
return mvebu_corediv_clk_init(node, &armada375_corediv_soc);
|
||||
}
|
||||
CLK_OF_DECLARE(armada375_corediv_clk, "marvell,armada-375-corediv-clock",
|
||||
armada375_corediv_clk_init);
|
||||
|
|
Loading…
Reference in New Issue