1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2014 Free Electrons
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
7 * Allwinner PRCM (Power/Reset/Clock Management) driver
10 #include <linux/mfd/core.h>
11 #include <linux/init.h>
14 #define SUN8I_CODEC_ANALOG_BASE 0x1c0
15 #define SUN8I_CODEC_ANALOG_SIZE 0x4
19 const struct mfd_cell
*subdevs
;
22 static const struct resource sun6i_a31_ar100_clk_res
[] = {
26 .flags
= IORESOURCE_MEM
,
30 static const struct resource sun6i_a31_apb0_clk_res
[] = {
34 .flags
= IORESOURCE_MEM
,
38 static const struct resource sun6i_a31_apb0_gates_clk_res
[] = {
42 .flags
= IORESOURCE_MEM
,
46 static const struct resource sun6i_a31_ir_clk_res
[] = {
50 .flags
= IORESOURCE_MEM
,
54 static const struct resource sun6i_a31_apb0_rstc_res
[] = {
58 .flags
= IORESOURCE_MEM
,
62 static const struct resource sun8i_codec_analog_res
[] = {
63 DEFINE_RES_MEM(SUN8I_CODEC_ANALOG_BASE
, SUN8I_CODEC_ANALOG_SIZE
),
66 static const struct mfd_cell sun6i_a31_prcm_subdevs
[] = {
68 .name
= "sun6i-a31-ar100-clk",
69 .of_compatible
= "allwinner,sun6i-a31-ar100-clk",
70 .num_resources
= ARRAY_SIZE(sun6i_a31_ar100_clk_res
),
71 .resources
= sun6i_a31_ar100_clk_res
,
74 .name
= "sun6i-a31-apb0-clk",
75 .of_compatible
= "allwinner,sun6i-a31-apb0-clk",
76 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_clk_res
),
77 .resources
= sun6i_a31_apb0_clk_res
,
80 .name
= "sun6i-a31-apb0-gates-clk",
81 .of_compatible
= "allwinner,sun6i-a31-apb0-gates-clk",
82 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res
),
83 .resources
= sun6i_a31_apb0_gates_clk_res
,
86 .name
= "sun6i-a31-ir-clk",
87 .of_compatible
= "allwinner,sun4i-a10-mod0-clk",
88 .num_resources
= ARRAY_SIZE(sun6i_a31_ir_clk_res
),
89 .resources
= sun6i_a31_ir_clk_res
,
92 .name
= "sun6i-a31-apb0-clock-reset",
93 .of_compatible
= "allwinner,sun6i-a31-clock-reset",
94 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_rstc_res
),
95 .resources
= sun6i_a31_apb0_rstc_res
,
99 static const struct mfd_cell sun8i_a23_prcm_subdevs
[] = {
101 .name
= "sun8i-a23-apb0-clk",
102 .of_compatible
= "allwinner,sun8i-a23-apb0-clk",
103 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_clk_res
),
104 .resources
= sun6i_a31_apb0_clk_res
,
107 .name
= "sun6i-a31-apb0-gates-clk",
108 .of_compatible
= "allwinner,sun8i-a23-apb0-gates-clk",
109 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res
),
110 .resources
= sun6i_a31_apb0_gates_clk_res
,
113 .name
= "sun6i-a31-apb0-clock-reset",
114 .of_compatible
= "allwinner,sun6i-a31-clock-reset",
115 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_rstc_res
),
116 .resources
= sun6i_a31_apb0_rstc_res
,
119 .name
= "sun8i-codec-analog",
120 .of_compatible
= "allwinner,sun8i-a23-codec-analog",
121 .num_resources
= ARRAY_SIZE(sun8i_codec_analog_res
),
122 .resources
= sun8i_codec_analog_res
,
126 static const struct prcm_data sun6i_a31_prcm_data
= {
127 .nsubdevs
= ARRAY_SIZE(sun6i_a31_prcm_subdevs
),
128 .subdevs
= sun6i_a31_prcm_subdevs
,
131 static const struct prcm_data sun8i_a23_prcm_data
= {
132 .nsubdevs
= ARRAY_SIZE(sun8i_a23_prcm_subdevs
),
133 .subdevs
= sun8i_a23_prcm_subdevs
,
136 static const struct of_device_id sun6i_prcm_dt_ids
[] = {
138 .compatible
= "allwinner,sun6i-a31-prcm",
139 .data
= &sun6i_a31_prcm_data
,
142 .compatible
= "allwinner,sun8i-a23-prcm",
143 .data
= &sun8i_a23_prcm_data
,
148 static int sun6i_prcm_probe(struct platform_device
*pdev
)
150 const struct of_device_id
*match
;
151 const struct prcm_data
*data
;
152 struct resource
*res
;
155 match
= of_match_node(sun6i_prcm_dt_ids
, pdev
->dev
.of_node
);
161 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
163 dev_err(&pdev
->dev
, "no prcm memory region provided\n");
167 ret
= mfd_add_devices(&pdev
->dev
, 0, data
->subdevs
, data
->nsubdevs
,
170 dev_err(&pdev
->dev
, "failed to add subdevices\n");
177 static struct platform_driver sun6i_prcm_driver
= {
179 .name
= "sun6i-prcm",
180 .of_match_table
= sun6i_prcm_dt_ids
,
182 .probe
= sun6i_prcm_probe
,
184 builtin_platform_driver(sun6i_prcm_driver
);