2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * Copyright (C) 2012 ARM Limited
14 #define DRVNAME "vexpress-regulator"
15 #define pr_fmt(fmt) DRVNAME ": " fmt
17 #include <linux/device.h>
18 #include <linux/err.h>
19 #include <linux/module.h>
20 #include <linux/of_device.h>
21 #include <linux/regulator/driver.h>
22 #include <linux/regulator/machine.h>
23 #include <linux/regulator/of_regulator.h>
24 #include <linux/vexpress.h>
26 struct vexpress_regulator
{
27 struct regulator_desc desc
;
28 struct regulator_dev
*regdev
;
29 struct vexpress_config_func
*func
;
32 static int vexpress_regulator_get_voltage(struct regulator_dev
*regdev
)
34 struct vexpress_regulator
*reg
= rdev_get_drvdata(regdev
);
36 int err
= vexpress_config_read(reg
->func
, 0, &uV
);
38 return err
? err
: uV
;
41 static int vexpress_regulator_set_voltage(struct regulator_dev
*regdev
,
42 int min_uV
, int max_uV
, unsigned *selector
)
44 struct vexpress_regulator
*reg
= rdev_get_drvdata(regdev
);
46 return vexpress_config_write(reg
->func
, 0, min_uV
);
49 static struct regulator_ops vexpress_regulator_ops_ro
= {
50 .get_voltage
= vexpress_regulator_get_voltage
,
53 static struct regulator_ops vexpress_regulator_ops
= {
54 .get_voltage
= vexpress_regulator_get_voltage
,
55 .set_voltage
= vexpress_regulator_set_voltage
,
58 static int vexpress_regulator_probe(struct platform_device
*pdev
)
61 struct vexpress_regulator
*reg
;
62 struct regulator_init_data
*init_data
;
63 struct regulator_config config
= { };
65 reg
= devm_kzalloc(&pdev
->dev
, sizeof(*reg
), GFP_KERNEL
);
71 reg
->func
= vexpress_config_func_get_by_dev(&pdev
->dev
);
77 reg
->desc
.name
= dev_name(&pdev
->dev
);
78 reg
->desc
.type
= REGULATOR_VOLTAGE
;
79 reg
->desc
.owner
= THIS_MODULE
;
80 reg
->desc
.continuous_voltage_range
= true;
82 init_data
= of_get_regulator_init_data(&pdev
->dev
, pdev
->dev
.of_node
);
85 goto error_get_regulator_init_data
;
88 init_data
->constraints
.apply_uV
= 0;
89 if (init_data
->constraints
.min_uV
&& init_data
->constraints
.max_uV
)
90 reg
->desc
.ops
= &vexpress_regulator_ops
;
92 reg
->desc
.ops
= &vexpress_regulator_ops_ro
;
94 config
.dev
= &pdev
->dev
;
95 config
.init_data
= init_data
;
96 config
.driver_data
= reg
;
97 config
.of_node
= pdev
->dev
.of_node
;
99 reg
->regdev
= regulator_register(®
->desc
, &config
);
100 if (IS_ERR(reg
->regdev
)) {
101 err
= PTR_ERR(reg
->regdev
);
102 goto error_regulator_register
;
105 platform_set_drvdata(pdev
, reg
);
109 error_regulator_register
:
110 error_get_regulator_init_data
:
111 vexpress_config_func_put(reg
->func
);
117 static int vexpress_regulator_remove(struct platform_device
*pdev
)
119 struct vexpress_regulator
*reg
= platform_get_drvdata(pdev
);
121 vexpress_config_func_put(reg
->func
);
122 regulator_unregister(reg
->regdev
);
127 static struct of_device_id vexpress_regulator_of_match
[] = {
128 { .compatible
= "arm,vexpress-volt", },
132 static struct platform_driver vexpress_regulator_driver
= {
133 .probe
= vexpress_regulator_probe
,
134 .remove
= vexpress_regulator_remove
,
137 .owner
= THIS_MODULE
,
138 .of_match_table
= vexpress_regulator_of_match
,
142 module_platform_driver(vexpress_regulator_driver
);
144 MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
145 MODULE_DESCRIPTION("Versatile Express regulator");
146 MODULE_LICENSE("GPL");
147 MODULE_ALIAS("platform:vexpress-regulator");