Commit | Line | Data |
---|---|---|
0376148f | 1 | // SPDX-License-Identifier: GPL-2.0-only |
d58603cc BB |
2 | /* |
3 | * Copyright (C) 2014 Free Electrons | |
4 | * | |
d58603cc BB |
5 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> |
6 | * | |
7 | * Allwinner PRCM (Power/Reset/Clock Management) driver | |
d58603cc BB |
8 | */ |
9 | ||
10 | #include <linux/mfd/core.h> | |
391cd33a | 11 | #include <linux/init.h> |
d58603cc BB |
12 | #include <linux/of.h> |
13 | ||
ea1628e8 CYT |
14 | #define SUN8I_CODEC_ANALOG_BASE 0x1c0 |
15 | #define SUN8I_CODEC_ANALOG_SIZE 0x4 | |
16 | ||
d58603cc BB |
17 | struct prcm_data { |
18 | int nsubdevs; | |
19 | const struct mfd_cell *subdevs; | |
20 | }; | |
21 | ||
22 | static const struct resource sun6i_a31_ar100_clk_res[] = { | |
23 | { | |
24 | .start = 0x0, | |
25 | .end = 0x3, | |
26 | .flags = IORESOURCE_MEM, | |
27 | }, | |
28 | }; | |
29 | ||
30 | static const struct resource sun6i_a31_apb0_clk_res[] = { | |
31 | { | |
32 | .start = 0xc, | |
33 | .end = 0xf, | |
34 | .flags = IORESOURCE_MEM, | |
35 | }, | |
36 | }; | |
37 | ||
38 | static const struct resource sun6i_a31_apb0_gates_clk_res[] = { | |
39 | { | |
40 | .start = 0x28, | |
41 | .end = 0x2b, | |
42 | .flags = IORESOURCE_MEM, | |
43 | }, | |
44 | }; | |
45 | ||
6f262ecf HG |
46 | static const struct resource sun6i_a31_ir_clk_res[] = { |
47 | { | |
48 | .start = 0x54, | |
49 | .end = 0x57, | |
50 | .flags = IORESOURCE_MEM, | |
51 | }, | |
52 | }; | |
53 | ||
d58603cc BB |
54 | static const struct resource sun6i_a31_apb0_rstc_res[] = { |
55 | { | |
56 | .start = 0xb0, | |
57 | .end = 0xb3, | |
58 | .flags = IORESOURCE_MEM, | |
59 | }, | |
60 | }; | |
61 | ||
ea1628e8 CYT |
62 | static const struct resource sun8i_codec_analog_res[] = { |
63 | DEFINE_RES_MEM(SUN8I_CODEC_ANALOG_BASE, SUN8I_CODEC_ANALOG_SIZE), | |
64 | }; | |
65 | ||
d58603cc BB |
66 | static const struct mfd_cell sun6i_a31_prcm_subdevs[] = { |
67 | { | |
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, | |
72 | }, | |
73 | { | |
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, | |
78 | }, | |
79 | { | |
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, | |
84 | }, | |
6f262ecf HG |
85 | { |
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, | |
90 | }, | |
d58603cc BB |
91 | { |
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, | |
96 | }, | |
97 | }; | |
98 | ||
4eb9560b CYT |
99 | static const struct mfd_cell sun8i_a23_prcm_subdevs[] = { |
100 | { | |
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, | |
105 | }, | |
106 | { | |
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, | |
111 | }, | |
112 | { | |
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, | |
117 | }, | |
ea1628e8 CYT |
118 | { |
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, | |
123 | }, | |
4eb9560b CYT |
124 | }; |
125 | ||
d58603cc BB |
126 | static const struct prcm_data sun6i_a31_prcm_data = { |
127 | .nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs), | |
128 | .subdevs = sun6i_a31_prcm_subdevs, | |
129 | }; | |
130 | ||
4eb9560b CYT |
131 | static const struct prcm_data sun8i_a23_prcm_data = { |
132 | .nsubdevs = ARRAY_SIZE(sun8i_a23_prcm_subdevs), | |
133 | .subdevs = sun8i_a23_prcm_subdevs, | |
134 | }; | |
135 | ||
d58603cc BB |
136 | static const struct of_device_id sun6i_prcm_dt_ids[] = { |
137 | { | |
138 | .compatible = "allwinner,sun6i-a31-prcm", | |
139 | .data = &sun6i_a31_prcm_data, | |
140 | }, | |
4eb9560b CYT |
141 | { |
142 | .compatible = "allwinner,sun8i-a23-prcm", | |
143 | .data = &sun8i_a23_prcm_data, | |
144 | }, | |
d58603cc BB |
145 | { /* sentinel */ }, |
146 | }; | |
147 | ||
148 | static int sun6i_prcm_probe(struct platform_device *pdev) | |
149 | { | |
d58603cc BB |
150 | const struct of_device_id *match; |
151 | const struct prcm_data *data; | |
152 | struct resource *res; | |
153 | int ret; | |
154 | ||
8ca6ff16 | 155 | match = of_match_node(sun6i_prcm_dt_ids, pdev->dev.of_node); |
d58603cc BB |
156 | if (!match) |
157 | return -EINVAL; | |
158 | ||
159 | data = match->data; | |
160 | ||
161 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
162 | if (!res) { | |
163 | dev_err(&pdev->dev, "no prcm memory region provided\n"); | |
164 | return -ENOENT; | |
165 | } | |
166 | ||
167 | ret = mfd_add_devices(&pdev->dev, 0, data->subdevs, data->nsubdevs, | |
168 | res, -1, NULL); | |
169 | if (ret) { | |
170 | dev_err(&pdev->dev, "failed to add subdevices\n"); | |
171 | return ret; | |
172 | } | |
173 | ||
174 | return 0; | |
175 | } | |
176 | ||
177 | static struct platform_driver sun6i_prcm_driver = { | |
178 | .driver = { | |
179 | .name = "sun6i-prcm", | |
d58603cc BB |
180 | .of_match_table = sun6i_prcm_dt_ids, |
181 | }, | |
182 | .probe = sun6i_prcm_probe, | |
183 | }; | |
391cd33a | 184 | builtin_platform_driver(sun6i_prcm_driver); |