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 regmap
*regmap
;
32 static int vexpress_regulator_get_voltage(struct regulator_dev
*regdev
)
34 struct vexpress_regulator
*reg
= rdev_get_drvdata(regdev
);
36 int err
= regmap_read(reg
->regmap
, 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 regmap_write(reg
->regmap
, 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
)
60 struct vexpress_regulator
*reg
;
61 struct regulator_init_data
*init_data
;
62 struct regulator_config config
= { };
64 reg
= devm_kzalloc(&pdev
->dev
, sizeof(*reg
), GFP_KERNEL
);
68 reg
->regmap
= devm_regmap_init_vexpress_config(&pdev
->dev
);
69 if (IS_ERR(reg
->regmap
))
70 return PTR_ERR(reg
->regmap
);
72 reg
->desc
.name
= dev_name(&pdev
->dev
);
73 reg
->desc
.type
= REGULATOR_VOLTAGE
;
74 reg
->desc
.owner
= THIS_MODULE
;
75 reg
->desc
.continuous_voltage_range
= true;
77 init_data
= of_get_regulator_init_data(&pdev
->dev
, pdev
->dev
.of_node
,
82 init_data
->constraints
.apply_uV
= 0;
83 if (init_data
->constraints
.min_uV
&& init_data
->constraints
.max_uV
)
84 reg
->desc
.ops
= &vexpress_regulator_ops
;
86 reg
->desc
.ops
= &vexpress_regulator_ops_ro
;
88 config
.dev
= &pdev
->dev
;
89 config
.init_data
= init_data
;
90 config
.driver_data
= reg
;
91 config
.of_node
= pdev
->dev
.of_node
;
93 reg
->regdev
= devm_regulator_register(&pdev
->dev
, ®
->desc
, &config
);
94 if (IS_ERR(reg
->regdev
))
95 return PTR_ERR(reg
->regdev
);
97 platform_set_drvdata(pdev
, reg
);
102 static const struct of_device_id vexpress_regulator_of_match
[] = {
103 { .compatible
= "arm,vexpress-volt", },
107 static struct platform_driver vexpress_regulator_driver
= {
108 .probe
= vexpress_regulator_probe
,
111 .of_match_table
= vexpress_regulator_of_match
,
115 module_platform_driver(vexpress_regulator_driver
);
117 MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
118 MODULE_DESCRIPTION("Versatile Express regulator");
119 MODULE_LICENSE("GPL");
120 MODULE_ALIAS("platform:vexpress-regulator");