Skip to content

Commit 03437e8

Browse files
LegoLivesMatterbebarino
authored andcommitted
clk: mmp: Add Marvell PXA1908 APMU driver
Add driver for the APMU controller block found on Marvell's PXA1908 SoC. This driver is incomplete, lacking support for (at least) GPU, VPU, DSI and CCIC (camera related) clocks. Signed-off-by: Duje Mihanović <duje.mihanovic@skole.hr> Link: https://lore.kernel.org/r/20241104-pxa1908-lkml-v13-7-e050609b8d6c@skole.hr Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent a89233d commit 03437e8

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

drivers/clk/mmp/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
1111
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
1212
obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o
1313

14-
obj-$(CONFIG_ARCH_MMP) += clk-of-pxa1928.o clk-pxa1908-apbc.o clk-pxa1908-apbcp.o
14+
obj-$(CONFIG_ARCH_MMP) += clk-of-pxa1928.o clk-pxa1908-apbc.o clk-pxa1908-apbcp.o clk-pxa1908-apmu.o

drivers/clk/mmp/clk-pxa1908-apmu.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <linux/clk-provider.h>
3+
#include <linux/module.h>
4+
#include <linux/platform_device.h>
5+
#include <linux/spinlock.h>
6+
7+
#include <dt-bindings/clock/marvell,pxa1908.h>
8+
9+
#include "clk.h"
10+
11+
#define APMU_CLK_GATE_CTRL 0x40
12+
#define APMU_CCIC1 0x24
13+
#define APMU_ISP 0x38
14+
#define APMU_DSI1 0x44
15+
#define APMU_DISP1 0x4c
16+
#define APMU_CCIC0 0x50
17+
#define APMU_SDH0 0x54
18+
#define APMU_SDH1 0x58
19+
#define APMU_USB 0x5c
20+
#define APMU_NF 0x60
21+
#define APMU_VPU 0xa4
22+
#define APMU_GC 0xcc
23+
#define APMU_SDH2 0xe0
24+
#define APMU_GC2D 0xf4
25+
#define APMU_TRACE 0x108
26+
#define APMU_DVC_DFC_DEBUG 0x140
27+
28+
#define APMU_NR_CLKS 17
29+
30+
struct pxa1908_clk_unit {
31+
struct mmp_clk_unit unit;
32+
void __iomem *base;
33+
};
34+
35+
static DEFINE_SPINLOCK(pll1_lock);
36+
static struct mmp_param_general_gate_clk pll1_gate_clks[] = {
37+
{PXA1908_CLK_PLL1_D2_GATE, "pll1_d2_gate", "pll1_d2", 0, APMU_CLK_GATE_CTRL, 29, 0, &pll1_lock},
38+
{PXA1908_CLK_PLL1_416_GATE, "pll1_416_gate", "pll1_416", 0, APMU_CLK_GATE_CTRL, 27, 0, &pll1_lock},
39+
{PXA1908_CLK_PLL1_624_GATE, "pll1_624_gate", "pll1_624", 0, APMU_CLK_GATE_CTRL, 26, 0, &pll1_lock},
40+
{PXA1908_CLK_PLL1_832_GATE, "pll1_832_gate", "pll1_832", 0, APMU_CLK_GATE_CTRL, 30, 0, &pll1_lock},
41+
{PXA1908_CLK_PLL1_1248_GATE, "pll1_1248_gate", "pll1_1248", 0, APMU_CLK_GATE_CTRL, 28, 0, &pll1_lock},
42+
};
43+
44+
static DEFINE_SPINLOCK(sdh0_lock);
45+
static DEFINE_SPINLOCK(sdh1_lock);
46+
static DEFINE_SPINLOCK(sdh2_lock);
47+
48+
static const char * const sdh_parent_names[] = {"pll1_416", "pll1_624"};
49+
50+
static struct mmp_clk_mix_config sdh_mix_config = {
51+
.reg_info = DEFINE_MIX_REG_INFO(3, 8, 2, 6, 11),
52+
};
53+
54+
static struct mmp_param_gate_clk apmu_gate_clks[] = {
55+
{PXA1908_CLK_USB, "usb_clk", NULL, 0, APMU_USB, 0x9, 0x9, 0x1, 0, NULL},
56+
{PXA1908_CLK_SDH0, "sdh0_clk", "sdh0_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH0, 0x12, 0x12, 0x0, 0, &sdh0_lock},
57+
{PXA1908_CLK_SDH1, "sdh1_clk", "sdh1_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH1, 0x12, 0x12, 0x0, 0, &sdh1_lock},
58+
{PXA1908_CLK_SDH2, "sdh2_clk", "sdh2_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH2, 0x12, 0x12, 0x0, 0, &sdh2_lock}
59+
};
60+
61+
static void pxa1908_axi_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
62+
{
63+
struct mmp_clk_unit *unit = &pxa_unit->unit;
64+
65+
mmp_register_general_gate_clks(unit, pll1_gate_clks,
66+
pxa_unit->base, ARRAY_SIZE(pll1_gate_clks));
67+
68+
sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->base + APMU_SDH0;
69+
mmp_clk_register_mix(NULL, "sdh0_mix_clk", sdh_parent_names,
70+
ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
71+
&sdh_mix_config, &sdh0_lock);
72+
sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->base + APMU_SDH1;
73+
mmp_clk_register_mix(NULL, "sdh1_mix_clk", sdh_parent_names,
74+
ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
75+
&sdh_mix_config, &sdh1_lock);
76+
sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->base + APMU_SDH2;
77+
mmp_clk_register_mix(NULL, "sdh2_mix_clk", sdh_parent_names,
78+
ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
79+
&sdh_mix_config, &sdh2_lock);
80+
81+
mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->base,
82+
ARRAY_SIZE(apmu_gate_clks));
83+
}
84+
85+
static int pxa1908_apmu_probe(struct platform_device *pdev)
86+
{
87+
struct pxa1908_clk_unit *pxa_unit;
88+
89+
pxa_unit = devm_kzalloc(&pdev->dev, sizeof(*pxa_unit), GFP_KERNEL);
90+
if (IS_ERR(pxa_unit))
91+
return PTR_ERR(pxa_unit);
92+
93+
pxa_unit->base = devm_platform_ioremap_resource(pdev, 0);
94+
if (IS_ERR(pxa_unit->base))
95+
return PTR_ERR(pxa_unit->base);
96+
97+
mmp_clk_init(pdev->dev.of_node, &pxa_unit->unit, APMU_NR_CLKS);
98+
99+
pxa1908_axi_periph_clk_init(pxa_unit);
100+
101+
return 0;
102+
}
103+
104+
static const struct of_device_id pxa1908_apmu_match_table[] = {
105+
{ .compatible = "marvell,pxa1908-apmu" },
106+
{ }
107+
};
108+
MODULE_DEVICE_TABLE(of, pxa1908_apmu_match_table);
109+
110+
static struct platform_driver pxa1908_apmu_driver = {
111+
.probe = pxa1908_apmu_probe,
112+
.driver = {
113+
.name = "pxa1908-apmu",
114+
.of_match_table = pxa1908_apmu_match_table
115+
}
116+
};
117+
module_platform_driver(pxa1908_apmu_driver);
118+
119+
MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
120+
MODULE_DESCRIPTION("Marvell PXA1908 APMU Clock Driver");
121+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)