मिनिमल मॉड्यूल कोड उदाहरण
शायद अंतर भी कुछ ठोस उदाहरण के साथ स्पष्ट हो जाएगा।
प्लेटफार्म डिवाइस उदाहरण
कोड:
आगे एकीकरण नोट पर: https://stackoverflow.com/a/44612957/895245
देखें कैसे:
- रजिस्टर और बीच में पतों डिवाइस पेड़ में hardcoded कर रहे हैं और QEMU
-M versatilepb
मशीन वर्णन है, जो का प्रतिनिधित्व करता है से मेल खाते हैं SOC
- डिवाइस हार्डवेयर को हटाने का कोई तरीका नहीं है (क्योंकि यह एसओसी का हिस्सा है)
- सही ड्राइवर
compatible
डिवाइस पेड़ संपत्ति जो ड्राइवर
platform_driver_register
में platform_driver.name
से मेल खाता से चुना जाता है मुख्य रजिस्टर इंटरफ़ेस
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
MODULE_LICENSE("GPL");
static struct resource res;
static unsigned int irq;
static void __iomem *map;
static irqreturn_t lkmc_irq_handler(int irq, void *dev)
{
/* TODO this 34 and not 18 as in the DTS, likely the interrupt controller moves it around.
* Understand precisely. 34 = 18 + 16. */
pr_info("lkmc_irq_handler irq = %d dev = %llx\n", irq, *(unsigned long long *)dev);
/* ACK the IRQ. */
iowrite32(0x9ABCDEF0, map + 4);
return IRQ_HANDLED;
}
static int lkmc_platform_device_probe(struct platform_device *pdev)
{
int asdf;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
dev_info(dev, "probe\n");
/* Play with our custom poperty. */
if (of_property_read_u32(np, "lkmc-asdf", &asdf)) {
dev_err(dev, "of_property_read_u32\n");
return -EINVAL;
}
if (asdf != 0x12345678) {
dev_err(dev, "asdf = %llx\n", (unsigned long long)asdf);
return -EINVAL;
}
/* IRQ. */
irq = irq_of_parse_and_map(dev->of_node, 0);
if (request_irq(irq, lkmc_irq_handler, 0, "lkmc_platform_device", dev) < 0) {
dev_err(dev, "request_irq");
return -EINVAL;
}
dev_info(dev, "irq = %u\n", irq);
/* MMIO. */
if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
dev_err(dev, "of_address_to_resource");
return -EINVAL;
}
if (!request_mem_region(res.start, resource_size(&res), "lkmc_platform_device")) {
dev_err(dev, "request_mem_region");
return -EINVAL;
}
map = of_iomap(pdev->dev.of_node, 0);
if (!map) {
dev_err(dev, "of_iomap");
return -EINVAL;
}
dev_info(dev, "res.start = %llx resource_size = %llx\n",
(unsigned long long)res.start, (unsigned long long)resource_size(&res));
/* Test MMIO and IRQ. */
iowrite32(0x12345678, map);
return 0;
}
static int lkmc_platform_device_remove(struct platform_device *pdev)
{
dev_info(&pdev->dev, "remove\n");
free_irq(irq, &pdev->dev);
iounmap(map);
release_mem_region(res.start, resource_size(&res));
return 0;
}
static const struct of_device_id of_lkmc_platform_device_match[] = {
{ .compatible = "lkmc_platform_device", },
{},
};
MODULE_DEVICE_TABLE(of, of_lkmc_platform_device_match);
static struct platform_driver lkmc_plaform_driver = {
.probe = lkmc_platform_device_probe,
.remove = lkmc_platform_device_remove,
.driver = {
.name = "lkmc_platform_device",
.of_match_table = of_lkmc_platform_device_match,
.owner = THIS_MODULE,
},
};
static int lkmc_platform_device_init(void)
{
pr_info("lkmc_platform_device_init\n");
return platform_driver_register(&lkmc_plaform_driver);
}
static void lkmc_platform_device_exit(void)
{
pr_info("lkmc_platform_device_exit\n");
platform_driver_unregister(&lkmc_plaform_driver);
}
module_init(lkmc_platform_device_init)
module_exit(lkmc_platform_device_exit)
पीसीआई गैर मंच डिवाइस उदाहरण
है
देखें कैसे:
- रजिस्टर और व्यवधान से पतों गतिशील पीसीआई प्रणाली द्वारा आवंटित किए जाते हैं, कोई डिवाइस पेड़ प्रयोग किया जाता है
- सही ड्राइवर पीसीआई
vendor:device
आईडी के आधार पर चयन किया जाता है (उदाहरण पर QEMU_VENDOR_ID, EDU_DEVICE_ID
)। यह हर डिवाइस में बेक्ड है, और विक्रेताओं को विशिष्टता सुनिश्चित करना चाहिए।
- हम
device_add edu
और device_del edu
के साथ पीसीआई डिवाइस को सम्मिलित और हटा सकते हैं जैसा कि हम वास्तविक जीवन में कर सकते हैं। जांच स्वचालित नहीं है, लेकिन echo 1 > /sys/bus/pci/rescan
के साथ बूट के बाद किया जा सकता है। यह भी देखें: Why is the probe method needed in Linux device drivers in addition to init?
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#define BAR 0
#define CDEV_NAME "lkmc_hw_pci_min"
#define EDU_DEVICE_ID 0x11e9
#define QEMU_VENDOR_ID 0x1234
MODULE_LICENSE("GPL");
static struct pci_device_id id_table[] = {
{ PCI_DEVICE(QEMU_VENDOR_ID, EDU_DEVICE_ID), },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, id_table);
static int major;
static struct pci_dev *pdev;
static void __iomem *mmio;
static struct file_operations fops = {
.owner = THIS_MODULE,
};
static irqreturn_t irq_handler(int irq, void *dev)
{
pr_info("irq_handler irq = %d dev = %d\n", irq, *(int *)dev);
iowrite32(0, mmio + 4);
return IRQ_HANDLED;
}
static int probe(struct pci_dev *dev, const struct pci_device_id *id)
{
pr_info("probe\n");
major = register_chrdev(0, CDEV_NAME, &fops);
pdev = dev;
if (pci_enable_device(dev) < 0) {
dev_err(&(pdev->dev), "pci_enable_device\n");
goto error;
}
if (pci_request_region(dev, BAR, "myregion0")) {
dev_err(&(pdev->dev), "pci_request_region\n");
goto error;
}
mmio = pci_iomap(pdev, BAR, pci_resource_len(pdev, BAR));
pr_info("dev->irq = %u\n", dev->irq);
if (request_irq(dev->irq, irq_handler, IRQF_SHARED, "pci_irq_handler0", &major) < 0) {
dev_err(&(dev->dev), "request_irq\n");
goto error;
}
iowrite32(0x12345678, mmio);
return 0;
error:
return 1;
}
static void remove(struct pci_dev *dev)
{
pr_info("remove\n");
free_irq(dev->irq, &major);
pci_release_region(dev, BAR);
unregister_chrdev(major, CDEV_NAME);
}
static struct pci_driver pci_driver = {
.name = CDEV_NAME,
.id_table = id_table,
.probe = probe,
.remove = remove,
};
static int myinit(void)
{
if (pci_register_driver(&pci_driver) < 0) {
return 1;
}
return 0;
}
static void myexit(void)
{
pci_unregister_driver(&pci_driver);
}
module_init(myinit);
module_exit(myexit);
डिवाइस एक MFD- बहु समारोह उपकरण है। 'platform_device' में एक फ़ील्ड है; 'संरचना mfd सेल' जो' i2c_client' संरचना में नहीं है। शायद उस कारण से ड्राइवर प्लेटफॉर्म ड्राइवर के रूप में पंजीकृत है। कृपया इस पर टिप्पणी करें। !! – kzs
http://www.atmel.com/Images/doc32098.pdf ..... इसे जांचें ... यह –
मदद कर सकता है हाँ दस्तावेज़ अच्छा था .. मुझे लगता है कि मैं कुछ समय बाद उस दस्तावेज़ का उपयोग कर सकता था। लेकिन मैं अभी तक निष्कर्ष पर नहीं आ सकता था। मैंने एक मास्टर से पूछा है जो ड्राइवरों में अच्छा है .. जवाब मिलने के बाद मैं यहां पोस्ट करूंगा। – kzs