aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/sun6i-prcm.c
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2014-05-09 07:11:47 -0400
committerLee Jones <lee.jones@linaro.org>2014-06-03 03:11:40 -0400
commitd58603cc304b717707e8f8ff05bf6aff9d9c82b5 (patch)
treee9a93f788e1b07a9db34439decbb64e1c3df7491 /drivers/mfd/sun6i-prcm.c
parente4e3d1b03695c458a954954c8efae745517dd44d (diff)
mfd: Add support for sun6i PRCM (Power/Reset/Clock Management) unit
The PRCM (Power/Reset/Clock Management) block exposes several subdevices in different subsystems (clk, reset ...) Add basic support for the PRCM unit with clk (AR100, AHB0, and APB0 clks) and reset controller subdevices. Other subdevices might be added later (if needed). Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd/sun6i-prcm.c')
-rw-r--r--drivers/mfd/sun6i-prcm.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
new file mode 100644
index 000000000000..718fc4d2adc0
--- /dev/null
+++ b/drivers/mfd/sun6i-prcm.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner PRCM (Power/Reset/Clock Management) driver
8 *
9 */
10
11#include <linux/mfd/core.h>
12#include <linux/module.h>
13#include <linux/of.h>
14
15struct prcm_data {
16 int nsubdevs;
17 const struct mfd_cell *subdevs;
18};
19
20static const struct resource sun6i_a31_ar100_clk_res[] = {
21 {
22 .start = 0x0,
23 .end = 0x3,
24 .flags = IORESOURCE_MEM,
25 },
26};
27
28static const struct resource sun6i_a31_apb0_clk_res[] = {
29 {
30 .start = 0xc,
31 .end = 0xf,
32 .flags = IORESOURCE_MEM,
33 },
34};
35
36static const struct resource sun6i_a31_apb0_gates_clk_res[] = {
37 {
38 .start = 0x28,
39 .end = 0x2b,
40 .flags = IORESOURCE_MEM,
41 },
42};
43
44static const struct resource sun6i_a31_apb0_rstc_res[] = {
45 {
46 .start = 0xb0,
47 .end = 0xb3,
48 .flags = IORESOURCE_MEM,
49 },
50};
51
52static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
53 {
54 .name = "sun6i-a31-ar100-clk",
55 .of_compatible = "allwinner,sun6i-a31-ar100-clk",
56 .num_resources = ARRAY_SIZE(sun6i_a31_ar100_clk_res),
57 .resources = sun6i_a31_ar100_clk_res,
58 },
59 {
60 .name = "sun6i-a31-apb0-clk",
61 .of_compatible = "allwinner,sun6i-a31-apb0-clk",
62 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res),
63 .resources = sun6i_a31_apb0_clk_res,
64 },
65 {
66 .name = "sun6i-a31-apb0-gates-clk",
67 .of_compatible = "allwinner,sun6i-a31-apb0-gates-clk",
68 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res),
69 .resources = sun6i_a31_apb0_gates_clk_res,
70 },
71 {
72 .name = "sun6i-a31-apb0-clock-reset",
73 .of_compatible = "allwinner,sun6i-a31-clock-reset",
74 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
75 .resources = sun6i_a31_apb0_rstc_res,
76 },
77};
78
79static const struct prcm_data sun6i_a31_prcm_data = {
80 .nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs),
81 .subdevs = sun6i_a31_prcm_subdevs,
82};
83
84static const struct of_device_id sun6i_prcm_dt_ids[] = {
85 {
86 .compatible = "allwinner,sun6i-a31-prcm",
87 .data = &sun6i_a31_prcm_data,
88 },
89 { /* sentinel */ },
90};
91
92static int sun6i_prcm_probe(struct platform_device *pdev)
93{
94 struct device_node *np = pdev->dev.of_node;
95 const struct of_device_id *match;
96 const struct prcm_data *data;
97 struct resource *res;
98 int ret;
99
100 match = of_match_node(sun6i_prcm_dt_ids, np);
101 if (!match)
102 return -EINVAL;
103
104 data = match->data;
105
106 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
107 if (!res) {
108 dev_err(&pdev->dev, "no prcm memory region provided\n");
109 return -ENOENT;
110 }
111
112 ret = mfd_add_devices(&pdev->dev, 0, data->subdevs, data->nsubdevs,
113 res, -1, NULL);
114 if (ret) {
115 dev_err(&pdev->dev, "failed to add subdevices\n");
116 return ret;
117 }
118
119 return 0;
120}
121
122static struct platform_driver sun6i_prcm_driver = {
123 .driver = {
124 .name = "sun6i-prcm",
125 .owner = THIS_MODULE,
126 .of_match_table = sun6i_prcm_dt_ids,
127 },
128 .probe = sun6i_prcm_probe,
129};
130module_platform_driver(sun6i_prcm_driver);
131
132MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
133MODULE_DESCRIPTION("Allwinner sun6i PRCM driver");
134MODULE_LICENSE("GPL v2");