Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 5e754106dd3dc278eec33f0389773190a77b0e38 Mon Sep 17 00:00:00 2001
- From: Nishanth Menon <nm@ti.com>
- Date: Thu, 4 Apr 2013 23:34:57 -0500
- Subject: [RFC PATCH] regulator: introduce TI smartreflex class 2
- driver(proof-of-concept)
- Idea being:
- cpufreq-cpu0 driver will use avs class 2 regulator->control actual i2c regulator
- reference: 3.2 driver for avs class 2
- https://github.com/Angstrom-distribution/meta-ti/blob/master/recipes-kernel/linux/linux-am335x-3.2.0-psp04.06.00.08/0001-am33xx-Add-SmartReflex-support.patch
- If we ignore the details of the class 1.5 implementation, we will notice
- a) regulator set_voltage equivalent set_voltage() is required.
- b) this set_voltage does some 'magic stuff' depending on the SoC and AVS class
- and calls the 'real regulator' which talks to the PMIC over i2c/spi etc..
- So, start modeling this under regulator framework itself.
- Signed-off-by: Nishanth Menon <nm@ti.com>
- ---
- drivers/regulator/Kconfig | 5 +
- drivers/regulator/Makefile | 1 +
- .../regulator/ti-smartreflex-class2-regulator.c | 222 ++++++++++++++++++++
- 3 files changed, 228 insertions(+)
- create mode 100644 drivers/regulator/ti-smartreflex-class2-regulator.c
- diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
- index a5d97ea..c5289f0 100644
- --- a/drivers/regulator/Kconfig
- +++ b/drivers/regulator/Kconfig
- @@ -514,5 +514,10 @@ config REGULATOR_AS3711
- This driver provides support for the voltage regulators on the
- AS3711 PMIC
- +config REGULATOR_TIAVSCLASS2
- + tristate "Texas Instruments SoC regulator for SmartReflex class 2"
- + help
- + This driver.. blah blah avs class 2 TBD..
- +
- endif
- diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
- index 6e82503..ba3f24e 100644
- --- a/drivers/regulator/Makefile
- +++ b/drivers/regulator/Makefile
- @@ -70,6 +70,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
- obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
- obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
- obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
- +obj-$(CONFIG_REGULATOR_TIAVSCLASS2) += ti-smartreflex-class2-regulator.o
- ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
- diff --git a/drivers/regulator/ti-smartreflex-class2-regulator.c b/drivers/regulator/ti-smartreflex-class2-regulator.c
- new file mode 100644
- index 0000000..36d1295
- --- /dev/null
- +++ b/drivers/regulator/ti-smartreflex-class2-regulator.c
- @@ -0,0 +1,222 @@
- +/* Proof of concept regulator driver */
- +#include <linux/module.h>
- +#include <linux/string.h>
- +#include <linux/slab.h>
- +#include <linux/init.h>
- +#include <linux/err.h>
- +#include <linux/platform_device.h>
- +#include <linux/of.h>
- +#include <linux/of_device.h>
- +#include <linux/regulator/driver.h>
- +#include <linux/regulator/machine.h>
- +#include <linux/regulator/of_regulator.h>
- +#include <linux/regulator/consumer.h>
- +
- +static int tisr_class2_enable(struct regulator_dev *rdev)
- +{
- + struct regulator *reg = rdev_get_drvdata(rdev);
- +
- + if (!reg) {
- + pr_err("%s: no regulator drvdata dev\n", __func__);
- + return -ENODEV;
- + }
- + /* TODO: more magic things */
- + return regulator_enable(reg);
- +}
- +
- +static int tisr_class2_disable(struct regulator_dev *rdev)
- +{
- + struct regulator *reg = rdev_get_drvdata(rdev);
- +
- + if (!reg) {
- + pr_err("%s: no regulator drvdata dev\n", __func__);
- + return -ENODEV;
- + }
- + /* TODO: more magic things */
- + return regulator_disable(reg);
- +}
- +
- +static int tisr_class2_is_enabled(struct regulator_dev *rdev)
- +{
- + struct regulator *reg = rdev_get_drvdata(rdev);
- +
- + if (!reg) {
- + pr_err("%s: no regulator drvdata dev\n", __func__);
- + return -ENODEV;
- + }
- + /* TODO: more magic things */
- + return regulator_is_enabled(reg);
- +}
- +
- +static int tisr_class2_list_voltage(struct regulator_dev *rdev, unsigned sel)
- +{
- + struct regulator *reg = rdev_get_drvdata(rdev);
- +
- + if (!reg) {
- + pr_err("%s: no regulator drvdata dev\n", __func__);
- + return -ENODEV;
- + }
- + /* TODO: more magic things */
- + return regulator_list_voltage(reg, sel);
- +}
- +
- +static int tisr_class2_set_voltage(struct regulator_dev *rdev, int min_uV,
- + int max_uV, unsigned *selector)
- +{
- + struct regulator *reg = rdev_get_drvdata(rdev);
- +
- + if (!reg) {
- + pr_err("%s: no regulator drvdata dev\n", __func__);
- + return -ENODEV;
- + }
- + /* TODO: more magic things */
- + return regulator_set_voltage(reg, min_uV, max_uV);
- +}
- +
- +static int tisr_class2_get_voltage(struct regulator_dev *rdev)
- +{
- + struct regulator *reg = rdev_get_drvdata(rdev);
- +
- + if (!reg) {
- + pr_err("%s: no regulator drvdata dev\n", __func__);
- + return -ENODEV;
- + }
- +
- + /* TODO: more magic things */
- + return regulator_get_voltage(reg);
- +}
- +
- +static struct regulator_ops tisr_class2_ops = {
- + .enable = tisr_class2_enable,
- + .disable = tisr_class2_disable,
- + .is_enabled = tisr_class2_is_enabled,
- +
- + .list_voltage = tisr_class2_list_voltage,
- +
- + .set_voltage = tisr_class2_set_voltage,
- + .get_voltage = tisr_class2_get_voltage,
- +
- +};
- +
- +static struct regulator_desc tisr_class2_desc = {
- + .ops = &tisr_class2_ops,
- + .name = "avsclass2",
- + .owner = THIS_MODULE,
- +
- +};
- +
- +static const struct of_device_id tisr_class2_of_match[] = {
- + {.compatible = "ti,sr_class2",.data = &tisr_class2_desc},
- + {},
- +};
- +
- +MODULE_DEVICE_TABLE(of, tisr_class2_of_match);
- +
- +static int tisr_class2_probe(struct platform_device *pdev)
- +{
- + struct regulator_init_data *initdata = NULL;
- + struct regulation_constraints *c;
- + struct regulator_dev *rdev;
- + const struct of_device_id *match;
- + struct regulator_config config = { };
- + const void *temp;
- + struct regulator_desc *desc;
- + struct regulator *reg;
- +
- + dev_err(&pdev->dev, "%s: I STARTED\n", __func__);
- + match = of_match_device(tisr_class2_of_match, &pdev->dev);
- + if (match) {
- + temp = match->data;
- + initdata = of_get_regulator_init_data(&pdev->dev,
- + pdev->dev.of_node);
- + }
- + if (!initdata) {
- + dev_err(&pdev->dev, "XXXYippiee.. no proper OF?\n");
- + return -ENODEV;
- + }
- + if (!temp) {
- + dev_err(&pdev->dev, "XXXYippiee.. no proper desc?\n");
- + return -ENODEV;
- + }
- +
- + /* look for avs-supply */
- + reg = devm_regulator_get(&pdev->dev, "avs");
- + if (IS_ERR(reg)) {
- + dev_err(&pdev->dev, "failed to get sr_class2 regulator %ld\n",
- + PTR_ERR(reg));
- + reg = NULL;
- + /* try later? */
- + return -EPROBE_DEFER;
- + }
- +
- + desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- + if (!desc) {
- + dev_err(&pdev->dev, "no memory to alloc!\n");
- + return -ENOMEM;
- + }
- + memcpy(desc, temp, sizeof(*desc));
- +
- + /*
- + * Constrain board-specific capabilities according to what
- + * this driver and the chip itself can actually do.
- + */
- + c = &initdata->constraints;
- + c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
- + c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
- + | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS;
- + c->always_on = true;
- +
- + config.dev = &pdev->dev;
- + config.init_data = initdata;
- + config.driver_data = reg;
- + config.of_node = pdev->dev.of_node;
- +
- + rdev = regulator_register(desc, &config);
- + if (IS_ERR(rdev)) {
- + dev_err(&pdev->dev, "can't register %s, %ld\n",
- + desc->name, PTR_ERR(rdev));
- + return PTR_ERR(rdev);
- + }
- + platform_set_drvdata(pdev, rdev);
- +
- + dev_err(&pdev->dev, "%s: I AM DONE\n", __func__);
- + return 0;
- +}
- +
- +static int tisr_class2_remove(struct platform_device *pdev)
- +{
- + struct regulator_dev *rdev = platform_get_drvdata(pdev);
- +
- + regulator_unregister(rdev);
- + return 0;
- +}
- +
- +MODULE_ALIAS("platform:tisr_class2");
- +
- +static struct platform_driver tisr_class2_driver = {
- + .probe = tisr_class2_probe,
- + .remove = tisr_class2_remove,
- + .driver = {
- + .name = "tisr_class2",
- + .owner = THIS_MODULE,
- + .of_match_table = of_match_ptr(tisr_class2_of_match),
- + },
- +};
- +
- +static int __init tisr_class2_init(void)
- +{
- + return platform_driver_register(&tisr_class2_driver);
- +}
- +
- +subsys_initcall(tisr_class2_init);
- +
- +static void __exit tisr_class2_exit(void)
- +{
- + platform_driver_unregister(&tisr_class2_driver);
- +}
- +
- +module_exit(tisr_class2_exit)
- +
- +MODULE_DESCRIPTION("TI SmartReflex AVS class 2 regulator driver");
- +MODULE_AUTHOR("Texas Instruments Inc."
- +MODULE_LICENSE("GPL v2");
- --
- 1.7.9.5
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement