一个简单的通过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

posted @ 2023-03-20 16:57  Amumu1  阅读(371)  评论(0编辑  收藏  举报