一.在设备树添加一个GPIO
DTS路径:
mt9679_an14/kernel/mtktv-modules/arch/arm64/boot/dts/mediatek/common_ctrl.dtsi
配置gpio358:
ist_hall: ist-hall{
status ="okay";
compatible = "ist_hall";
ist_hall-gpios = <&pm_gpio0 58 0>;
};
在kernel里面,添加一个驱动定时读取gpio的状态:
#include <linux/miscdevice.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/compat.h>
#include <linux/printk.h>
#include <linux/kobject.h>
#include <linux/version.h>
#include <linux/kthread.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
#define DRIVER_NAME "IST_HALL"
/*define logging*/
#define IST_TEMP_DEBUG 0
#if IST_TEMP_DEBUG
#define DBG(format, args...) \
printk(KERN_DEBUG "%s: " format, DRIVER_NAME, ##args)
#define ERR(format, args...) \
printk(KERN_ERR "%s: " format, DRIVER_NAME, ##args)
#define WARNING(format, args...) \
printk(KERN_WARN "%s: " format, DRIVER_NAME, ##args)
#define INFO(format, args...) \
printk(KERN_INFO "%s: " format, DRIVER_NAME, ##args)
#else
#define DBG(format, args...)
#define ERR(format, args...)
#define WARNING(format, args...)
#define INFO(format, args...)
#endif
struct ist_hall_dev {
uint32_t value;
struct device *dev;
struct miscdevice miscdev;
struct gpio_desc *hall_gpio;
struct delayed_work check_status_work;
};
struct ist_hall_dev *g_ist_hall;
struct ist_hall_dev *ist_hall;
static int last_value = 0;//char
static long ist_hall_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
{
return 0;
}
static ssize_t ist_hall_write(struct file *file, const char __user *buf,
size_t size, loff_t *ppos)
{
return 1;
}
static ssize_t ist_hall_read(struct file *file, char __user *buf, size_t size,
loff_t *ppos)
{
return 1;
}
static ssize_t ist_hall_value_read(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ist_hall_dev *ist_hall = g_ist_hall;
pr_info("ist_hall_value_read ist_hall->value:%d\n",ist_hall->value);
return sprintf(buf, "%d\n", ist_hall->value);
}
static ssize_t ist_hall_value_write(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return count;
}
static DEVICE_ATTR(value, 0644,
ist_hall_value_read, ist_hall_value_write);
static const struct file_operations ist_hall_fops = {
.owner = THIS_MODULE,
.read = ist_hall_read,
.write = ist_hall_write,
.unlocked_ioctl = ist_hall_ioctl,
};
struct miscdevice ist_hall_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "ist_hall_dev",
.fops = &ist_hall_fops,
};
static void check_link_status(struct work_struct *work)
{
gpiod_direction_input(g_ist_hall->hall_gpio);
g_ist_hall->value = gpiod_get_value(g_ist_hall->hall_gpio);
pr_info("check_link_status g_ist_hall->value:%d\n",g_ist_hall->value);
schedule_delayed_work(&g_ist_hall->check_status_work, msecs_to_jiffies(500));
}
static int ist_hall_probe(struct platform_device *pdev)
{
struct ist_hall_dev *ist_hall;
int ret;
ist_hall = devm_kzalloc(&pdev->dev, sizeof(struct ist_hall_dev), GFP_KERNEL);
if (!ist_hall)
return -ENOMEM;
ist_hall->dev = &pdev->dev;
ist_hall->hall_gpio = devm_gpiod_get_optional(ist_hall->dev,
"ist_hall", GPIOD_OUT_HIGH);
if (IS_ERR(ist_hall->hall_gpio)) {
pr_info("Could not get hall_gpio",ist_hall->hall_gpio);
ist_hall->hall_gpio = NULL;
}
ret = misc_register(&ist_hall_miscdev);
if (ret) {
ERR(" ist_hall ERROR: could not register ist_hall device\n");
return ret;
}
ret = device_create_file(ist_hall_miscdev.this_device,
&dev_attr_value);
if (ret) {
dev_err(ist_hall->dev, " failed to create attr hdmirxsel!\n");
return ret;
}
g_ist_hall = ist_hall;
INIT_DELAYED_WORK(&ist_hall->check_status_work, check_link_status);
schedule_delayed_work(&ist_hall->check_status_work, msecs_to_jiffies(500));
return 0;
}
static int ist_hall_remove(struct platform_device *client)
{
return 0;
}
static const struct of_device_id ist_hall_of_match[] = {
{ .compatible = "ist_hall" },
{}
};
MODULE_DEVICE_TABLE(of, ist_hall_of_match);
static struct platform_driver ist_hall_driver = {
.probe = ist_hall_probe,
.remove = ist_hall_remove,
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ist_hall_of_match),
},
};
static int __init ist_hall_driver_init(void)
{
int ret = platform_driver_register(&ist_hall_driver);
if (ret != 0) {
pr_info("rtl8309_init Failed to register example driver: %d\n", ret);
return ret;
}
return 0;
}
static void __exit ist_hall_driver_exit(void)
{
platform_driver_unregister(&ist_hall_driver);
pr_info("Example driver exited\n");
}
module_init(ist_hall_driver_init);
module_exit(ist_hall_driver_exit);
MODULE_DESCRIPTION("rtl8309 GPIO Switch");
MODULE_AUTHOR("Zewei Ye <yezw@ist.com.hk>");
MODULE_LICENSE("GPL v2");