Permalink
Browse files

+platform_device and small updates

  • Loading branch information...
makelinux committed Sep 15, 2012
1 parent fd1d178 commit e9983bbfdfb6bf6c96e35ca59200fd2b52b57710
Showing with 269 additions and 47 deletions.
  1. +7 −2 Makefile
  2. +10 −10 ldt-test
  3. +115 −35 ldt.c
  4. +68 −0 ldt_plat_dev.c
  5. +69 −0 ldt_plat_drv.c
View
@@ -1,10 +1,15 @@
-ccflags-y+=-Wfatal-errors
+#ccflags-y+=-Wfatal-errors
ccflags-y+=-include $M/ctracer.h
ccflags-y+=-D CTRACER_ON
-obj-m:= ldt.o
+ccflags-y+=-D USE_PLATFORM_DEVICE
+obj-m+= ldt.o
+obj-m+= ldt_plat_drv.o # implements platform_driver only
+obj-m+= ldt_plat_dev.o # implements platform_device and resource
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+all: mapper modules
+
modules:
$(MAKE) -C $(KERNELDIR) M=$$PWD modules
View
@@ -7,7 +7,7 @@ irq=0
tracing()
{
- sudo sh -c "cd $tracing; $1"
+ sudo sh -c "cd $tracing; $1" || true
}
tracing_start()
@@ -20,31 +20,31 @@ tracing_start()
sudo cat $tracing/function_profile_enabled
}
-traccing_stop()
+tracing_stop()
{
+ echo Profiling data per CPU
tracing "cat trace_stat/function*"
tracing "echo 0 > function_profile_enabled"
tracing "echo nop > current_tracer"
- sudo cp $tracing/trace .
+ sudo cp $tracing/trace ftrace.log && echo ftrace.log saved
}
# sudo rmmod parport_pc parport ppdev lp
-sudo rmmod ldt
+sudo rmmod ldt ldt_plat_dev
set -o errexit
make
sudo insmod ldt.ko irq=$irq
-tracing_start
+sudo insmod ldt_plat_dev.ko
+
+tracing_start || true
lsmod | grep ldt
id=`grep -w ldt /proc/misc | cut -c -3`
sudo sh -c "rm /dev/ldt;sudo mknod /dev/ldt c 10 $id; chmod o+rw /dev/ldt"
echo 123 > /dev/ldt
-head -n 1 /dev/ldt
sleep 0.5
head -n 1 /dev/ldt
grep ldt /proc/interrupts || true
-echo Profiling data per CPU
-traccing_stop
-sudo rmmod ldt
+tracing_stop || true
#sudo dmesg --show-delta --notime --read-clear > kernel.log
-sudo dmesg -c > kernel.log
+sudo dmesg -c > kernel.log && echo kernel.log saved
#sudo dmesg --show-delta --notime --read-clear > kernel.log
View
150 ldt.c
@@ -8,8 +8,8 @@
*
* The driver demonstrates usage of following Linux facilities:
*
- * module
- * file_operations
+ * Linux kernel module
+ * file_operations read and write
* kfifo
* completion
* interrupt
@@ -18,9 +18,9 @@
* timer
* misc device
* proc fs
+ * platform_driver and platform_device in another module
*/
-
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/delay.h>
@@ -32,6 +32,7 @@
#include <linux/kfifo.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
int irq = 0;
module_param(irq, int, 0);
@@ -50,7 +51,7 @@ module_param(irq, int, 0);
static int isr_counter;
static int ldt_work_counter;
-#define FIFO_SIZE 128 /* should be power of two */
+#define FIFO_SIZE 128 /* should be power of two */
static DEFINE_KFIFO(in_fifo, char, FIFO_SIZE);
static DEFINE_KFIFO(out_fifo, char, FIFO_SIZE);
@@ -59,20 +60,20 @@ spinlock_t fifo_lock;
/* ldt_received - called with data received from HW port
* Called from interrupt or emulated function
*/
-void ldt_received(void * data, int size)
+void ldt_received(void *data, int size)
{
kfifo_in_spinlocked(&in_fifo, data, size, &fifo_lock);
}
/* ldt_port_put - emulates sending data to HW port
*
*/
-void ldt_port_put(void * data, int size)
+void ldt_port_put(void *data, int size)
{
/*
* emulate loop back port
*/
- ldt_received(data,size);
+ ldt_received(data, size);
}
static DECLARE_COMPLETION(ldt_comlete);
@@ -108,8 +109,9 @@ void ldt_tasklet_func(unsigned long data)
_entry:;
once(print_context());
ret = kfifo_out_spinlocked(&out_fifo, &unit, sizeof(unit), &fifo_lock);
- if ( ret ) {
- trl_();trvd(unit);
+ if (ret) {
+ trl_();
+ trvd(unit);
ldt_port_put(&unit, sizeof(unit));
}
schedule_work(&ldt_work);
@@ -123,7 +125,7 @@ _entry:;
once(print_context());
isr_counter++;
tasklet_schedule(&ldt_tasklet);
- return IRQ_NONE; /* not our IRQ */
+ return IRQ_NONE; /* not our IRQ */
// return IRQ_HANDLED; /* our IRQ */
}
@@ -163,7 +165,6 @@ static ssize_t ldt_read(struct file *file, char __user * buf, size_t count, loff
return ret ? ret : copied;
}
-
static DEFINE_MUTEX(write_lock);
static ssize_t ldt_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos)
@@ -187,51 +188,130 @@ struct file_operations ldt_fops = {
.poll = NULL,
};
-static struct miscdevice ldt_dev = {
+static struct miscdevice ldt_miscdev = {
MISC_DYNAMIC_MINOR,
KBUILD_MODNAME,
&ldt_fops,
};
-int ldt_init(void)
+static __devinit int ldt_probe(struct platform_device *pdev)
{
- int ret = 0;
-_entry:;
- print_context();
- ret = check(misc_register(&ldt_dev));
- if (ret < 0)
- goto exit;
- trvd(ldt_dev.minor);
- trl_();
- trvd(irq);
- trvs(KBUILD_MODNAME);
- isr_counter = 0;
- if (irq) {
- ret = check(request_irq(irq, (void *)ldt_isr, IRQF_SHARED, KBUILD_MODNAME, THIS_MODULE));
- }
- proc_create(KBUILD_MODNAME, 0, NULL, &ldt_fops);
- mod_timer(&ldt_timer, jiffies + HZ / 10);
+ int ret;
+ char *data = NULL;
+ struct resource *r;
+_entry:
+ print_context();
+ trl_();
+ trvs_(KBUILD_MODNAME);
+ trvp_(pdev);
+ trvd_(irq);
+ trln();
+ if (pdev) {
+ data = pdev->dev.platform_data;
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq) {
+ irq = r->start;
+ }
+ }
+ trvp(data);
+ trvs(data);
+ ret = check(misc_register(&ldt_miscdev));
+ //ret = check(register_chrdev (0, KBUILD_MODNAME, &ldt_fops));
+ if (ret < 0)
+ goto exit;
+ trvd(ldt_miscdev.minor);
+ isr_counter = 0;
+ if (irq) {
+ ret = check(request_irq(irq, (void *)ldt_isr, IRQF_SHARED, KBUILD_MODNAME, THIS_MODULE));
+ }
+ proc_create(KBUILD_MODNAME, 0, NULL, &ldt_fops);
+ mod_timer(&ldt_timer, jiffies + HZ / 10);
exit:
- trvd(ret);
- return ret;
+ trl_();
+ trvd(ret);
+ return ret;
}
-void ldt_exit(void)
+static int __devexit ldt_remove(struct platform_device *pdev)
{
-_entry:;
+_entry:
remove_proc_entry(KBUILD_MODNAME, NULL);
- misc_deregister(&ldt_dev);
+ misc_deregister(&ldt_miscdev);
del_timer(&ldt_timer);
if (irq) {
free_irq(irq, THIS_MODULE);
}
- trl();
trvd(isr_counter);
trvd(ldt_work_counter);
+ return 0;
+}
+
+#ifdef USE_PLATFORM_DEVICE
+
+/*
+ * Folowing code requres platform_device (ldt_plat_dev.*) to work
+ */
+
+static struct platform_driver ldt_driver = {
+ .driver.name = "ldt_device_name",
+ .driver.owner = THIS_MODULE,
+ .probe = ldt_probe,
+ .remove = __devexit_p(ldt_remove),
+};
+
+#ifdef module_platform_driver
+module_platform_driver(ldt_driver);
+#else
+
+/*
+ * for releases before v3.1-12 without macro module_platform_driver
+ */
+
+static int ldt_init(void)
+{
+ int ret = 0;
+_entry:
+ ret = platform_driver_register(&ldt_driver);
+ return ret;
+}
+
+static void ldt_exit(void)
+{
+_entry:
+ platform_driver_unregister(&ldt_driver);
+}
+
+module_init(ldt_init);
+module_exit(ldt_exit);
+#endif // module_platform_driver
+
+#else // ! USE_PLATFORM_DEVICE
+
+/*
+ * Standalone module initialization to run without platform_device
+ */
+
+static int ldt_init(void)
+{
+ int ret = 0;
+_entry:
+ /*
+ * Call probe function directly, bypassing platform_device infrastructure
+ */
+ ret = ldt_probe(NULL);
+ return ret;
+}
+
+static void ldt_exit(void)
+{
+ int res;
+_entry:
+ res = ldt_remove(NULL);
}
module_init(ldt_init);
module_exit(ldt_exit);
+#endif
MODULE_DESCRIPTION("LDT - Linux Driver Template");
MODULE_AUTHOR("Constantine Shulyupin <const@makelinux.net>");
View
@@ -0,0 +1,68 @@
+/*
+ * LDT - Linux Driver Template
+ *
+ * Copyright (C) 2012 Constantine Shulyupin http://www.makelinux.net/
+ *
+ * Dual BSD/GPL License
+ *
+ * platform_device template driver
+ *
+ * uses
+ *
+ * platform_data
+ * resources
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static struct resource ldt_resource[] = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = 0,
+ .end = 0,
+ },
+ {
+ .flags = IORESOURCE_MEM,
+ .start = 0,
+ .end = 0,
+ },
+};
+
+void ldt_dev_release(struct device *dev)
+{
+_entry:;
+}
+
+static struct platform_device ldt_platform_device = {
+ .name = "ldt_device_name",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ldt_resource),
+ .resource = ldt_resource,
+ .dev.platform_data = "test data",
+ .dev.release = ldt_dev_release,
+};
+
+static int ldt_plat_dev_init(void)
+{
+ int ret = 0;
+_entry:
+ ret = platform_device_register(&ldt_platform_device);
+ trl_();
+ trvd(ret);
+ return ret;
+}
+
+static void ldt_plat_dev_exit(void)
+{
+_entry:
+ platform_device_unregister(&ldt_platform_device);
+}
+
+module_init(ldt_plat_dev_init);
+module_exit(ldt_plat_dev_exit);
+
+MODULE_DESCRIPTION("LDT - Linux Driver Template: platform_device");
+MODULE_AUTHOR("Constantine Shulyupin <const@makelinux.net>");
+MODULE_LICENSE("Dual BSD/GPL");
Oops, something went wrong.

0 comments on commit e9983bb

Please sign in to comment.