一个简单的通过regulator子系统控制gpio驱动,内核版本5.10
一个简单的通过regulator子系统控制gpio驱动,内核版本5.10
驱动
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/driver.h>
#include <linux/of.h>
struct ctrl_data {
struct regulator *rdev;
int states;
};
/*
* sysfs attributes
*/
static ssize_t show_regulator_status(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = container_of(dev,struct platform_device,dev);
struct ctrl_data *ctrl_dev = platform_get_drvdata(pdev);
if( regulator_is_enabled(ctrl_dev->rdev) > 0)
return sprintf(buf,"%s\n","enabled");
else
return sprintf(buf,"%s\n","disabled");
}
static ssize_t set_regulator_status(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct platform_device *pdev = container_of(dev,struct platform_device,dev);
struct ctrl_data *ctrl_dev = platform_get_drvdata(pdev);
int ret;
if( strncmp(buf,"enable",6) == 0 || strncmp(buf,"1",1) == 0){
ret = regulator_enable(ctrl_dev->rdev);
if ( ret < 0 )
dev_err(&pdev->dev, "failed enabled:%d\n",ret);
}
else if( strncmp(buf,"disable",7) == 0 || strncmp(buf,"0",1) == 0){
if(regulator_is_enabled(ctrl_dev->rdev) ){
//must be enable first.
ret = regulator_enable(ctrl_dev->rdev);
if ( ret < 0 )
dev_err(&pdev->dev, "failed enabled:%d\n",ret);
ret = regulator_disable(ctrl_dev->rdev);
if ( ret < 0 )
dev_err(&pdev->dev, "failed disabled:%d\n",ret);
}
}
return len;
}
static DEVICE_ATTR(status, S_IRUSR|S_IWUSR, show_regulator_status, set_regulator_status);
static int regulator_ctrl_probe(struct platform_device *pdev)
{
struct ctrl_data * ctrl_dev;
int error;
ctrl_dev = devm_kzalloc(&pdev->dev, sizeof(struct ctrl_data),
GFP_KERNEL);
if (!ctrl_dev)
return -ENOMEM;
ctrl_dev->rdev = devm_regulator_get(&pdev->dev, "ctrl");
if (IS_ERR(ctrl_dev->rdev)) {
error = PTR_ERR(ctrl_dev->rdev);
if (error != -EPROBE_DEFER)
dev_err(&pdev->dev, "Failed to get 'ctrl' regulator: %d\n",
error);
return error;
}
platform_set_drvdata(pdev, ctrl_dev);
if (device_create_file(&pdev->dev, &dev_attr_status) != 0) {
dev_err(&pdev->dev, "sysfs status entry creation failed\n");
return -ENOENT;
}
return 0;
}
static const struct of_device_id match_table[] = {
{ .compatible = "regulator-ctrl", },
{},
};
MODULE_DEVICE_TABLE(of, match_table);
static struct platform_driver vctrl_driver = {
.probe = regulator_ctrl_probe,
.driver = {
.name = "regulator-ctrl",
.of_match_table = of_match_ptr(match_table),
},
};
module_platform_driver(vctrl_driver);
MODULE_DESCRIPTION("Regulator Controlled Driver");
MODULE_AUTHOR("Amumu <643063358@qq.com>");
MODULE_LICENSE("GPL v2");
设备树配置
mcu_reset:mcu-reset {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
regulator-name = "mcu_reset";
regulator-boot-on;
enable-active-high;
pinctrl-names = "default";
pinctrl-0 = <&mcu_reset_pin>;
};
regulator-mcu {
compatible = "regulator-ctrl";
ctrl-supply = <&mcu_reset>;
};
测试结果
可以通过
/sys/devices/platform/regulator-mcu/status节点
或者/sys/class/regulator/regulator.17/regulator-mcu-ctrl/status (推荐),操作mcu_reset gpio状态
echo 0 > /sys/class/regulator/regulator.17/regulator-mcu-ctrl/status
echo 1 > //sys/class/regulator/regulator.17/regulator-mcu-ctrl/status
查看状态
cat /sys/class/regulator/regulator.17/regulator-mcu-ctrl/status
或
cat /sys/class/regulator/regulator.17/state
注意:
/sys/class/regulator/regulator.17/name 对应为mcu_reset