Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  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.
  5 *
  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.
 10 *
 11 * Copyright (C) 2012 ARM Limited
 12 */
 13
 14#define DRVNAME "vexpress-regulator"
 15#define pr_fmt(fmt) DRVNAME ": " fmt
 16
 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>
 25
 26struct vexpress_regulator {
 27	struct regulator_desc desc;
 28	struct regulator_dev *regdev;
 29	struct regmap *regmap;
 30};
 31
 32static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
 33{
 34	struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
 35	u32 uV;
 36	int err = regmap_read(reg->regmap, 0, &uV);
 37
 38	return err ? err : uV;
 39}
 40
 41static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
 42		int min_uV, int max_uV, unsigned *selector)
 43{
 44	struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
 45
 46	return regmap_write(reg->regmap, 0, min_uV);
 47}
 48
 49static struct regulator_ops vexpress_regulator_ops_ro = {
 50	.get_voltage = vexpress_regulator_get_voltage,
 51};
 52
 53static struct regulator_ops vexpress_regulator_ops = {
 54	.get_voltage = vexpress_regulator_get_voltage,
 55	.set_voltage = vexpress_regulator_set_voltage,
 56};
 57
 58static int vexpress_regulator_probe(struct platform_device *pdev)
 59{
 60	struct vexpress_regulator *reg;
 61	struct regulator_init_data *init_data;
 62	struct regulator_config config = { };
 63
 64	reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
 65	if (!reg)
 66		return -ENOMEM;
 67
 68	reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev);
 69	if (IS_ERR(reg->regmap))
 70		return PTR_ERR(reg->regmap);
 71
 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;
 76
 77	init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
 78					       &reg->desc);
 79	if (!init_data)
 80		return -EINVAL;
 81
 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;
 85	else
 86		reg->desc.ops = &vexpress_regulator_ops_ro;
 87
 88	config.dev = &pdev->dev;
 89	config.init_data = init_data;
 90	config.driver_data = reg;
 91	config.of_node = pdev->dev.of_node;
 92
 93	reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
 94	if (IS_ERR(reg->regdev))
 95		return PTR_ERR(reg->regdev);
 96
 97	platform_set_drvdata(pdev, reg);
 98
 99	return 0;
100}
101
102static const struct of_device_id vexpress_regulator_of_match[] = {
103	{ .compatible = "arm,vexpress-volt", },
104	{ }
105};
106MODULE_DEVICE_TABLE(of, vexpress_regulator_of_match);
107
108static struct platform_driver vexpress_regulator_driver = {
109	.probe = vexpress_regulator_probe,
110	.driver	= {
111		.name = DRVNAME,
112		.of_match_table = vexpress_regulator_of_match,
113	},
114};
115
116module_platform_driver(vexpress_regulator_driver);
117
118MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
119MODULE_DESCRIPTION("Versatile Express regulator");
120MODULE_LICENSE("GPL");
121MODULE_ALIAS("platform:vexpress-regulator");