GPIO控制灯驱动

#include <linux/kernel.h>

#include <linux/types.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/gpio.h>

#include <linux/err.h>

#include <linux/device.h>

#include <linux/delay.h>

#include <linux/of_gpio.h>

#include <linux/clk.h>

#include <linux/interrupt.h>

#include <linux/rfkill.h>

#include <linux/regulator/consumer.h>

#include <linux/platform_device.h>

#include <linux/sunxi-gpio.h>

#include <linux/etherdevice.h>

#include <linux/miscdevice.h>

#include <linux/capability.h>

#include <linux/pm_wakeirq.h>

#include "sunxi-rfkill.h"

struct sunxi_wlan_platdata {

    struct pinctrl *pctrl;

    int gpio_red_led;

    int gpio_green_led;

    int gpio_blue_led;

    int gpio_power_en;

    struct platform_device *pdev;

};

static struct sunxi_wlan_platdata *wlan_data;

static int sunxi_wlan_on(struct sunxi_wlan_platdata *data, bool on_off);

static DEFINE_MUTEX(sunxi_wlan_mutex);

void sunxi_wl_poweren_set(int dev, int on_off)

{

    /* Only wifi and bt both close, power_en goes down,

     * otherwise, set power_en up to keep module work.

     * dev   : device to set power status. 0: wifi, 1: bt

     * on_off: power status to set. 0: off, 1: on

     */

    static int power_state;

    if (dev == WL_DEV_WIFI || dev == WL_DEV_BLUETOOTH) {

        power_state &= ~(1 << dev);

        power_state |= ((on_off > 0) << dev);

    }

    if (gpio_is_valid(wlan_data->gpio_power_en))

        gpio_set_value(wlan_data->gpio_power_en, (power_state != 0));

}

EXPORT_SYMBOL_GPL(sunxi_wl_poweren_set);

void sunxi_wlan_set_power(bool on_off)

{

    struct platform_device *pdev;

    int ret = 0;

    if (!wlan_data)

        return;

    pdev = wlan_data->pdev;

    mutex_lock(&sunxi_wlan_mutex);

    sunxi_wl_poweren_set(WL_DEV_WIFI, on_off);

    if (on_off != wlan_data->power_state) {

        ret = sunxi_wlan_on(wlan_data, on_off);

        if (ret)

            dev_err(&pdev->dev, "set power failed\n");

    }

    sunxi_wl_chipen_set(WL_DEV_WIFI, on_off);

    mutex_unlock(&sunxi_wlan_mutex);

}

EXPORT_SYMBOL_GPL(sunxi_wlan_set_power);

static int sunxi_wlan_on(struct sunxi_wlan_platdata *data, bool on_off)

{

    struct platform_device *pdev = data->pdev;

    struct device *dev = &pdev->dev;

    int ret = 0;

    if (!on_off && gpio_is_valid(data->gpio_wlan_regon))

        gpio_set_value(data->gpio_wlan_regon, 0);

    if (data->wlan_power_name) {

        data->wlan_power = regulator_get(dev, data->wlan_power_name);

        if (!IS_ERR(data->wlan_power)) {

            if (on_off) {

                ret = regulator_enable(data->wlan_power);

                if (ret < 0) {

                    dev_err(dev, "regulator wlan_power enable failed\n");

                    regulator_put(data->wlan_power);

                    return ret;

                }

                ret = regulator_get_voltage(data->wlan_power);

                if (ret < 0) {

                    dev_err(dev, "regulator wlan_power get voltage failed\n");

                    regulator_put(data->wlan_power);

                    return ret;

                }

                dev_info(dev, "check wlan wlan_power voltage: %d\n",

                         ret);

            } else {

                ret = regulator_disable(data->wlan_power);

                if (ret < 0) {

                    dev_err(dev, "regulator wlan_power disable failed\n");

                    regulator_put(data->wlan_power);

                    return ret;

                }

            }

            regulator_put(data->wlan_power);

        }

    }

    if (data->io_regulator_name) {

        data->io_regulator = regulator_get(dev,

                data->io_regulator_name);

        if (!IS_ERR(data->io_regulator)) {

            if (on_off) {

                ret = regulator_enable(data->io_regulator);

                if (ret < 0) {

                    dev_err(dev, "regulator io_regulator enable failed\n");

                    regulator_put(data->io_regulator);

                    return ret;

                }

                ret = regulator_get_voltage(data->io_regulator);

                if (ret < 0) {

                    dev_err(dev, "regulator io_regulator get voltage failed\n");

                    regulator_put(data->io_regulator);

                    return ret;

                }

                dev_info(dev, "check wlan io_regulator voltage: %d\n",

                        ret);

            } else {

                ret = regulator_disable(data->io_regulator);

                if (ret < 0) {

                    dev_err(dev, "regulator io_regulator disable failed\n");

                    regulator_put(data->io_regulator);

                    return ret;

                }

            }

            regulator_put(data->io_regulator);

        }

    }

    if (on_off && gpio_is_valid(data->gpio_wlan_regon)) {

        mdelay(10);

        gpio_set_value(data->gpio_wlan_regon, 1);

    }

    wlan_data->power_state = on_off;

    return 0;

}

static ssize_t power_state_show(struct device *dev,

    struct device_attribute *attr, char *buf)

{

    return sprintf(buf, "%d\n", wlan_data->power_state);

}

static ssize_t power_state_store(struct device *dev,

    struct device_attribute *attr, const char *buf, size_t count)

{

    unsigned long state;

    int err;

    if (!capable(CAP_NET_ADMIN))

        return -EPERM;

    err = kstrtoul(buf, 0, &state);

    if (err)

        return err;

    if (state > 1)

        return -EINVAL;

    if (state != wlan_data->power_state) {

        sunxi_wlan_set_power(state);

    }

    return count;

}

static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,

        power_state_show, power_state_store);

static ssize_t scan_device_store(struct device *dev,

    struct device_attribute *attr, const char *buf, size_t count)

{

    unsigned long state;

    int err;

    int bus = wlan_data->bus_index;

    err = kstrtoul(buf, 0, &state);

    if (err)

        return err;

    dev_info(dev, "start scan device on bus_index: %d\n",

            wlan_data->bus_index);

    if (bus < 0) {

        dev_err(dev, "scan device fail!\n");

        return -1;

    }

    sunxi_mmc_rescan_card(bus);

    return count;

}

static DEVICE_ATTR(scan_device, S_IRUGO | S_IWUSR,

        NULL, scan_device_store);

static struct attribute *misc_attributes[] = {

    &dev_attr_power_state.attr,

    &dev_attr_scan_device.attr,

    NULL,

};

static struct attribute_group misc_attribute_group = {

    .name  = "rf-ctrl",

    .attrs = misc_attributes,

};

static struct miscdevice sunxi_wlan_dev = {

    .minor = MISC_DYNAMIC_MINOR,

    .name  = "sunxi-led",

};

static int sunxi_wlan_probe(struct platform_device *pdev)

{

    struct device_node *np = pdev->dev.of_node;

    struct device *dev = &pdev->dev;

    struct sunxi_wlan_platdata *data;

    struct gpio_config config;

    int ret = 0;

    // struct pinctrl_state *pctrl_state = NULL;

    data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);

    if (!dev)

        return -ENOMEM;

    data->pdev = pdev;

    wlan_data = data;


 

    //RED

    data->gpio_red_led = of_get_named_gpio_flags(np, "h616_red",

            0, (enum of_gpio_flags *)&config);

    if (!gpio_is_valid(data->gpio_red_led)) {

        dev_err(dev, "get gpio gpio_red_led failed\n");

    } else {

        dev_info(dev, "wlan_regon gpio=%d  mul-sel=%d  pull=%d  drv_level=%d  data=%d\n",

                config.gpio,

                config.mul_sel,

                config.pull,

                config.drv_level,

                config.data);

        ret = devm_gpio_request(dev, data->gpio_red_led,

                "h616_red");

        if (ret < 0) {

            dev_err(dev, "can't request gpio_red_led gpio %d\n",

                data->gpio_red_led);

            return ret;

        }

        ret = gpio_direction_output(data->gpio_red_led, 0);

        if (ret < 0) {

            dev_err(dev, "can't request output direction gpio_red_led gpio %d\n",

                data->gpio_red_led);

            return ret;

        }

    }

    //GREEN

    data->gpio_green_led = of_get_named_gpio_flags(np, "h616_green",

            0, (enum of_gpio_flags *)&config);

    if (!gpio_is_valid(data->gpio_green_led)) {

        dev_err(dev, "get gpio gpio_green_led failed\n");

    } else {

        dev_info(dev, "gpio_green_led gpio=%d  mul-sel=%d  pull=%d  drv_level=%d  data=%d\n",

                config.gpio,

                config.mul_sel,

                config.pull,

                config.drv_level,

                config.data);

        ret = devm_gpio_request(dev, data->gpio_green_led,

                "h616_green");

        if (ret < 0) {

            dev_err(dev, "can't request gpio_green_led gpio %d\n",

                data->gpio_green_led);

            return ret;

        }

        ret = gpio_direction_output(data->gpio_green_led, 0);

        if (ret < 0) {

            dev_err(dev, "can't request output direction gpio_green_led gpio %d\n",

                data->gpio_green_led);

            return ret;

        }

    }

    //BLUE 

    data->gpio_blue_led = of_get_named_gpio_flags(np, "h616_blue",

            0, (enum of_gpio_flags *)&config);

    if (!gpio_is_valid(data->gpio_blue_led)) {

        dev_err(dev, "get gpio gpio_blue_led failed\n");

    } else {

        dev_info(dev, "gpio_blue_led gpio=%d  mul-sel=%d  pull=%d  drv_level=%d  data=%d\n",

                config.gpio,

                config.mul_sel,

                config.pull,

                config.drv_level,

                config.data);

        ret = devm_gpio_request(dev, data->gpio_blue_led,

                "h616_blue");

        if (ret < 0) {

            dev_err(dev, "can't request gpio_blue_led gpio %d\n",

                data->gpio_blue_led);

            return ret;

        }

        ret = gpio_direction_output(data->gpio_blue_led, 0);

        if (ret < 0) {

            dev_err(dev, "can't request output direction gpio_blue_led gpio %d\n",

                data->gpio_blue_led);

            return ret;

        }

    }      

    //获取某个GPIO状态

    // data->pctrl = devm_pinctrl_get(dev);

    // if (IS_ERR(data->pctrl)) {

    //  dev_warn(dev, "devm_pinctrl_get() failed!\n");

    // } else {

    //  pctrl_state = pinctrl_lookup_state(data->pctrl, pctrl_name);

    //  if (IS_ERR(pctrl_state)) {

    //      dev_warn(dev, "pinctrl_lookup_state(%s) failed! return %p \n",

    //              pctrl_name, pctrl_state);

    //  } else {

    //      ret = pinctrl_select_state(data->pctrl, pctrl_state);

    //      if (ret < 0) {

    //          dev_warn(dev, "pinctrl_select_state(%s) failed! return %d \n",

    //                  pctrl_name, ret);

    //      }

    //  }

    // }

    ret = misc_register(&sunxi_wlan_dev);

    if (ret) {

        dev_err(dev, "sunxi-wlan register driver as misc device error!\n");

        return ret;

    }

    ret = sysfs_create_group(&sunxi_wlan_dev.this_device->kobj,

            &misc_attribute_group);

    if (ret) {

        dev_err(dev, "sunxi-wlan register sysfs create group failed!\n");

        return ret;

    }

    return 0;

}

static int sunxi_wlan_remove(struct platform_device *pdev)

{

    misc_deregister(&sunxi_wlan_dev);

    sysfs_remove_group(&(sunxi_wlan_dev.this_device->kobj),

            &misc_attribute_group);

    return 0;

}

static const struct of_device_id sunxi_wlan_ids[] = {

    { .compatible = "allwinner,sunxi-led" },

    { /* Sentinel */ }

};

static struct platform_driver sunxi_wlan_driver = {

    .probe      = sunxi_wlan_probe,

    .remove = sunxi_wlan_remove,

    .driver = {

        .owner  = THIS_MODULE,

        .name   = "sunxi-led",

        .of_match_table = sunxi_wlan_ids,

    },

};

static int __init sunxi_h616_led_init(void) 

    return platform_driver_register(&sunxi_wlan_driver); 

module_init(sunxi_h616_led_init); 

static void __exit sunxi_h616_led_exit(void) 

    return platform_driver_unregister(&sunxi_wlan_driver); 

module_exit(sunxi_h616_led_exit);

//module_platform_driver(sunxi_wlan_driver);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("huangbenyan");

MODULE_DESCRIPTION("sunxi led driver");

MODULE_ALIAS("led");

dts配置

        led:led {
            compatible    = "allwinner,sunxi-led";
            h616_red      = <&pio PH 6 1 0xffffffff 0xffffffff 0>;
            h616_green      = <&pio PH 7 1 0xffffffff 0xffffffff 0>;
            h616_blue      = <&pio PH 8 1 0xffffffff 0xffffffff 0>;
            status        = "okay";
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值