1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| #include <linux/module.h> #include <linux/platform_device.h> #include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/device.h> #include <linux/of.h>
struct led_data { struct gpio_desc *led_desc; };
static ssize_t led_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_data *priv = dev_get_drvdata(dev); int ret, state;
ret = kstrtoint(buf, 10, &state); if (ret < 0) return ret;
gpiod_set_value(priv->led_desc, state); dev_info(dev, "User set LED to %d\n", state);
return count; }
static ssize_t led_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_data *priv = dev_get_drvdata(dev); int val = gpiod_get_value(priv->led_desc); return sprintf(buf, "%d\n", val); }
static DEVICE_ATTR(ctrl, 0644, led_ctrl_show, led_ctrl_store);
static int led_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct led_data *priv; int ret;
dev_info(dev, "LED Driver: Probing (Manual Mode)...\n");
priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
priv->led_desc = gpiod_get(dev, "my-run", GPIOD_OUT_LOW); if (IS_ERR(priv->led_desc)) { dev_err(dev, "Failed to get GPIO resource\n"); ret = PTR_ERR(priv->led_desc); goto err_free_mem; }
platform_set_drvdata(pdev, priv);
ret = device_create_file(dev, &dev_attr_ctrl); if (ret) { dev_err(dev, "Failed to create sysfs node\n"); goto err_free_gpio; }
dev_info(dev, "Probe successful.\n"); return 0;
err_free_gpio: gpiod_put(priv->led_desc); err_free_mem: kfree(priv); return ret; }
static int led_remove(struct platform_device *pdev) { struct led_data *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev;
device_remove_file(dev, &dev_attr_ctrl);
gpiod_set_value(priv->led_desc, 0);
gpiod_put(priv->led_desc); dev_info(dev, "GPIO released.\n");
kfree(priv); dev_info(dev, "Memory freed.\n"); return 0; }
static const struct of_device_id led_match[] = { { .compatible = "my,pin-manager" }, { }, };
MODULE_DEVICE_TABLE(of, led_match);
static struct platform_driver led_driver = { .probe = led_probe, .remove = led_remove, .driver = { .name = "demo-led-driver", .of_match_table = led_match, }, };
module_platform_driver(led_driver);
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jvle");
|