2 * Copyright (C) 2014 Free Electrons
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
7 * Allwinner PRCM (Power/Reset/Clock Management) driver
11 #include <linux/mfd/core.h>
12 #include <linux/module.h>
17 const struct mfd_cell
*subdevs
;
20 static const struct resource sun6i_a31_ar100_clk_res
[] = {
24 .flags
= IORESOURCE_MEM
,
28 static const struct resource sun6i_a31_apb0_clk_res
[] = {
32 .flags
= IORESOURCE_MEM
,
36 static const struct resource sun6i_a31_apb0_gates_clk_res
[] = {
40 .flags
= IORESOURCE_MEM
,
44 static const struct resource sun6i_a31_ir_clk_res
[] = {
48 .flags
= IORESOURCE_MEM
,
52 static const struct resource sun6i_a31_apb0_rstc_res
[] = {
56 .flags
= IORESOURCE_MEM
,
60 static const struct mfd_cell sun6i_a31_prcm_subdevs
[] = {
62 .name
= "sun6i-a31-ar100-clk",
63 .of_compatible
= "allwinner,sun6i-a31-ar100-clk",
64 .num_resources
= ARRAY_SIZE(sun6i_a31_ar100_clk_res
),
65 .resources
= sun6i_a31_ar100_clk_res
,
68 .name
= "sun6i-a31-apb0-clk",
69 .of_compatible
= "allwinner,sun6i-a31-apb0-clk",
70 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_clk_res
),
71 .resources
= sun6i_a31_apb0_clk_res
,
74 .name
= "sun6i-a31-apb0-gates-clk",
75 .of_compatible
= "allwinner,sun6i-a31-apb0-gates-clk",
76 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res
),
77 .resources
= sun6i_a31_apb0_gates_clk_res
,
80 .name
= "sun6i-a31-ir-clk",
81 .of_compatible
= "allwinner,sun4i-a10-mod0-clk",
82 .num_resources
= ARRAY_SIZE(sun6i_a31_ir_clk_res
),
83 .resources
= sun6i_a31_ir_clk_res
,
86 .name
= "sun6i-a31-apb0-clock-reset",
87 .of_compatible
= "allwinner,sun6i-a31-clock-reset",
88 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_rstc_res
),
89 .resources
= sun6i_a31_apb0_rstc_res
,
93 static const struct mfd_cell sun8i_a23_prcm_subdevs
[] = {
95 .name
= "sun8i-a23-apb0-clk",
96 .of_compatible
= "allwinner,sun8i-a23-apb0-clk",
97 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_clk_res
),
98 .resources
= sun6i_a31_apb0_clk_res
,
101 .name
= "sun6i-a31-apb0-gates-clk",
102 .of_compatible
= "allwinner,sun8i-a23-apb0-gates-clk",
103 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res
),
104 .resources
= sun6i_a31_apb0_gates_clk_res
,
107 .name
= "sun6i-a31-apb0-clock-reset",
108 .of_compatible
= "allwinner,sun6i-a31-clock-reset",
109 .num_resources
= ARRAY_SIZE(sun6i_a31_apb0_rstc_res
),
110 .resources
= sun6i_a31_apb0_rstc_res
,
114 static const struct prcm_data sun6i_a31_prcm_data
= {
115 .nsubdevs
= ARRAY_SIZE(sun6i_a31_prcm_subdevs
),
116 .subdevs
= sun6i_a31_prcm_subdevs
,
119 static const struct prcm_data sun8i_a23_prcm_data
= {
120 .nsubdevs
= ARRAY_SIZE(sun8i_a23_prcm_subdevs
),
121 .subdevs
= sun8i_a23_prcm_subdevs
,
124 static const struct of_device_id sun6i_prcm_dt_ids
[] = {
126 .compatible
= "allwinner,sun6i-a31-prcm",
127 .data
= &sun6i_a31_prcm_data
,
130 .compatible
= "allwinner,sun8i-a23-prcm",
131 .data
= &sun8i_a23_prcm_data
,
136 static int sun6i_prcm_probe(struct platform_device
*pdev
)
138 struct device_node
*np
= pdev
->dev
.of_node
;
139 const struct of_device_id
*match
;
140 const struct prcm_data
*data
;
141 struct resource
*res
;
144 match
= of_match_node(sun6i_prcm_dt_ids
, np
);
150 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
152 dev_err(&pdev
->dev
, "no prcm memory region provided\n");
156 ret
= mfd_add_devices(&pdev
->dev
, 0, data
->subdevs
, data
->nsubdevs
,
159 dev_err(&pdev
->dev
, "failed to add subdevices\n");
166 static struct platform_driver sun6i_prcm_driver
= {
168 .name
= "sun6i-prcm",
169 .of_match_table
= sun6i_prcm_dt_ids
,
171 .probe
= sun6i_prcm_probe
,
173 module_platform_driver(sun6i_prcm_driver
);
175 MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
176 MODULE_DESCRIPTION("Allwinner sun6i PRCM driver");
177 MODULE_LICENSE("GPL v2");