Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ldt.c simplified: removed work, ioctl

  • Loading branch information...
commit 7c7c6c60ff3af5ec1a2fbf378a65351584627fe2 1 parent 2df2eb0
@makelinux authored
View
1  Makefile
@@ -9,6 +9,7 @@ obj-m+= ldt_plat_drv.o # implements platform_driver only
obj-m+= ldt_plat_dev.o # implements platform_device and resource
#obj-m+= chrdev_region_sample.o
obj-m+= ldt_configfs_basic.o
+obj-m+= kthread_sample.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
View
49 kthread_sample.c
@@ -0,0 +1,49 @@
+#include <linux/kthread.h>
+#include <linux/module.h>
+
+static DECLARE_COMPLETION(completion);
+
+static int thread_sample(void *data)
+{
+ int ret = 0;
+ allow_signal(SIGINT);
+ while (!kthread_should_stop()) {
+ ret = wait_for_completion_interruptible(&completion);
+ if (ret == -ERESTARTSYS) {
+ pr_debug("%s: %s\n", __func__, "interrupted");
+ return -EINTR;
+ }
+ /*
+ perform here a useful work in scheduler context
+ */
+ }
+ return ret;
+}
+
+static struct task_struct *thread;
+
+static int thread_sample_init(void)
+{
+ int ret = 0;
+ thread = kthread_run(thread_sample, NULL, "%s", KBUILD_MODNAME);
+ if (IS_ERR(thread)) {
+ ret = PTR_ERR(thread);
+ goto exit;
+ }
+ complete(&completion);
+exit:
+ return ret;
+}
+
+static void thread_sample_exit(void)
+{
+ if (!IS_ERR_OR_NULL(thread)) {
+ send_sig(SIGINT, thread, 1);
+ kthread_stop(thread);
+ }
+}
+
+module_init(thread_sample_init);
+module_exit(thread_sample_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
View
31 ldt-test
@@ -3,11 +3,11 @@
#
# LDT - Linux Driver Template
#
-# Test script
+# Test script for driver LDT
#
# Copyright (C) 2012 Constantine Shulyupin http://www.makelinux.net/
#
-# Dual BSD/GPL License
+# Licensed under the GPLv2.
#
RED="\\033[0;31m"
@@ -28,15 +28,7 @@ tracing_start()
{
tracing "echo :mod:ldt > set_ftrace_filter"
tracing "echo function > current_tracer" # need for draw_functrace.py
- #tracing "echo function_graph > current_tracer"
tracing "echo 1 > function_profile_enabled"
- # useful optional command:
- #tracing "echo XXX > set_ftrace_notrace"
- #sudo cat $tracing/current_tracer
- #sudo cat $tracing/set_ftrace_filter
- #sudo cat $tracing/function_profile_enabled
- # available_filter_functions
- # echo $$ > set_ftrace_pid
}
tracing_stop()
@@ -53,10 +45,11 @@ tracing_stop()
< trace_pipe.log > functrace.log && echo functrace.log saved || true
}
-# sudo rmmod parport_pc parport ppdev lp
sudo dmesg -n 7
-sudo rmmod ldt ldt_plat_dev 2> /dev/null
+sudo rmmod ldt 2> /dev/null
sudo dmesg -c > /dev/null
+
+# configure UART because it is used for demostration of the driver
stty -F /dev/ttyS0 115200
make -s
set -o errexit
@@ -79,7 +72,6 @@ fi
# clean data
echo | ./dio --ignore_eof --loops 10 --delay 10 /dev/ttyS0 2> /dev/null > /dev/null
-sudo insmod ldt_plat_dev.ko
sudo insmod ldt.ko loopback=$loopback
tracing_start || true
@@ -125,20 +117,7 @@ echo expected $data
echo received $received
fi
-data=123ioctl
-received=`sudo echo $data | ./dio --ioctl /dev/ldt`
-if [ "$data" == "$received" ]; then
-echo -e "${GREEN}LDT ioctl test passed$NOCOLOR"
-else
-echo -e "${RED}LDT ioctl test failed$NOCOLOR"
-echo expected $data
-echo received $received
-fi
-
sudo ls -l /sys/kernel/debug/ldt
-#grep ldt /proc/interrupts || true
-
-#sudo rmmod ldt ldt_plat_dev 2> /dev/null
tracing_stop || true
sudo dmesg --notime --show-delta --read-clear 2>/dev/null > kernel.log || \
View
297 ldt.c
@@ -14,31 +14,27 @@
* blocking read and write
* polling
* mmap
- * ioctl
* kfifo
* completion
* interrupt
* tasklet
* timer
* work
- * kthread
* simple single misc device file (miscdevice, misc_register)
* debugfs
* platform_driver and platform_device in another module
* simple UART driver on port 0x3f8 with IRQ 4
- * Power Management (dev_pm_ops)
- * Device Tree (of_device_id)
*
- * Usermode test script and utility are located in tools/testing/ldt/
+ * Use test script ldt-test to see the driver running
*
*/
#include <linux/io.h>
+#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/delay.h>
-#include <linux/kthread.h>
#include <linux/timer.h>
#include <linux/kfifo.h>
#include <linux/fs.h>
@@ -46,23 +42,19 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
#include <linux/serial_reg.h>
#include <linux/debugfs.h>
#include <linux/cdev.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/mod_devicetable.h>
-static int port;
+static int port = 0x3f8;
module_param(port, int, 0);
MODULE_PARM_DESC(port, "io port number, default 0x3f8 - UART");
-static int port_size;
+static int port_size = 8;
module_param(port_size, int, 0);
MODULE_PARM_DESC(port_size, "number of io ports, default 8");
-static int irq;
+static int irq = 4;
module_param(irq, int, 0);
MODULE_PARM_DESC(irq, "interrupt request number, default 4 - UART");
@@ -73,8 +65,6 @@ MODULE_PARM_DESC(loopback, "loopback mode for testing, default 0");
#define FIFO_SIZE 128 /* must be power of two */
static int bufsize = 8 * PAGE_SIZE;
-static int uart_detected;
-static void __iomem *port_ptr;
/**
* struct ldt_data - the driver data
@@ -85,8 +75,11 @@ static void __iomem *port_ptr;
* @fifo_lock: lock for queues
* @readable: waitqueue for blocking read
* @writeable: waitqueue for blocking write
+ * @port_ptr: mapped io port
+ * @uart_detected: UART is detected and will be used.
+ * Otherwise emulation mode will be used.
*
- * stored in static global variable for simplicity.
+ * stored in static global variable drvdata for simplicity.
* Can be also retrieved from platform_device with
* struct ldt_data *drvdata = platform_get_drvdata(pdev);
*/
@@ -100,6 +93,8 @@ struct ldt_data {
wait_queue_head_t readable, writeable;
struct mutex read_lock;
struct mutex write_lock;
+ void __iomem *port_ptr;
+ int uart_detected;
};
static struct ldt_data *drvdata;
@@ -123,8 +118,8 @@ static void ldt_received(char data)
static void ldt_send(char data)
{
- if (uart_detected)
- iowrite8(data, port_ptr + UART_TX);
+ if (drvdata->uart_detected)
+ iowrite8(data, drvdata->port_ptr + UART_TX);
else
if (loopback)
ldt_received(data);
@@ -132,52 +127,35 @@ static void ldt_send(char data)
static inline u8 tx_ready(void)
{
- return ioread8(port_ptr + UART_LSR) & UART_LSR_THRE;
+ return ioread8(drvdata->port_ptr + UART_LSR) & UART_LSR_THRE;
}
static inline u8 rx_ready(void)
{
- return ioread8(port_ptr + UART_LSR) & UART_LSR_DR;
+ return ioread8(drvdata->port_ptr + UART_LSR) & UART_LSR_DR;
}
/*
- * work section
- *
- * empty template function for deferred call in scheduler context
- */
-
-static int ldt_work_counter;
-
-
-static void ldt_work_func(struct work_struct *work)
-{
- ldt_work_counter++;
-}
-
-static DECLARE_WORK(ldt_work, ldt_work_func);
-
-/*
* tasklet section
*
* template function for deferred call in interrupt context
*/
-static DECLARE_COMPLETION(ldt_complete);
static void ldt_tasklet_func(unsigned long d)
{
char data_out, data_in;
- if (uart_detected) {
+ if (drvdata->uart_detected) {
while (tx_ready() && kfifo_out_spinlocked(&drvdata->out_fifo,
&data_out, sizeof(data_out), &drvdata->fifo_lock)) {
wake_up_interruptible(&drvdata->writeable);
- pr_debug("%s: data_out=%d %c\n", __func__, data_out, data_out >= 32 ? data_out : 0);
+ pr_debug("%s: data_out=%d %c\n", __func__, data_out, data_out >= 32 ? data_out : ' ');
ldt_send(data_out);
}
while (rx_ready()) {
- data_in = ioread8(port_ptr + UART_RX);
- pr_debug("%s: data_in=%d %c\n", __func__, data_in, data_in >= 32 ? data_in : 0);
+ data_in = ioread8(drvdata->port_ptr + UART_RX);
+ pr_debug("%s: data_in=%d %c\n", __func__, data_in, data_in >= 32 ? data_in : ' ');
ldt_received(data_in);
}
} else {
@@ -188,8 +166,6 @@ static void ldt_tasklet_func(unsigned long d)
ldt_send(data_out);
}
}
- schedule_work(&ldt_work);
- complete(&ldt_complete);
}
static DECLARE_TASKLET(ldt_tasklet, ldt_tasklet_func, 0);
@@ -207,8 +183,8 @@ static irqreturn_t ldt_isr(int irq, void *dev_id)
* therefore fire ldt_tasklet from timer too
*/
isr_counter++;
- pr_debug("UART_FCR=0x%02X\n", ioread8(port_ptr + UART_FCR));
- pr_debug("UART_IIR=0x%02X\n", ioread8(port_ptr + UART_IIR));
+ pr_debug("UART_FCR=0x%02X\n", ioread8(drvdata->port_ptr + UART_FCR));
+ pr_debug("UART_IIR=0x%02X\n", ioread8(drvdata->port_ptr + UART_IIR));
tasklet_schedule(&ldt_tasklet);
return IRQ_HANDLED; /* our IRQ */
}
@@ -358,55 +334,6 @@ static int ldt_mmap(struct file *filp, struct vm_area_struct *vma)
return 0;
}
-#define trace_ioctl(nr) pr_debug("ioctl=(%c%c %c #%i %i)\n", \
- (_IOC_READ & _IOC_DIR(nr)) ? 'r' : ' ', \
- (_IOC_WRITE & _IOC_DIR(nr)) ? 'w' : ' ', \
- _IOC_TYPE(nr), _IOC_NR(nr), _IOC_SIZE(nr))
-
-static DEFINE_MUTEX(ioctl_lock);
-
-static long ldt_ioctl(struct file *f, unsigned int cmnd, unsigned long arg)
-{
- int ret = 0;
- void __user *user = (void __user *)arg;
-
- if (mutex_lock_interruptible(&ioctl_lock))
- return -EINTR;
- pr_debug("%s:\n", __func__);
- pr_debug("cmnd=0x%X\n", cmnd);
- pr_debug("arg=0x%lX\n", arg);
- trace_ioctl(cmnd);
- switch (_IOC_TYPE(cmnd)) {
- case 'A':
- switch (_IOC_NR(cmnd)) {
- case 0:
- if (_IOC_DIR(cmnd) == _IOC_WRITE) {
- if (copy_from_user(drvdata->in_buf, user,
- _IOC_SIZE(cmnd))) {
- ret = -EFAULT;
- goto exit;
- }
- /* copy data from in_buf to out_buf to emulate loopback for testing */
- memcpy(drvdata->out_buf, drvdata->in_buf, bufsize);
- memset(drvdata->in_buf, 0, bufsize);
- }
- if (_IOC_DIR(cmnd) == _IOC_READ) {
- if (copy_to_user(user, drvdata->out_buf,
- _IOC_SIZE(cmnd))) {
- ret = -EFAULT;
- goto exit;
- }
- memset(drvdata->out_buf, 0, bufsize);
- }
- break;
- }
- break;
- }
-exit:
- mutex_unlock(&ioctl_lock);
- return ret;
-}
-
static const struct file_operations ldt_fops = {
.owner = THIS_MODULE,
.open = ldt_open,
@@ -415,7 +342,6 @@ static const struct file_operations ldt_fops = {
.write = ldt_write,
.poll = ldt_poll,
.mmap = ldt_mmap,
- .unlocked_ioctl = ldt_ioctl,
};
static struct miscdevice ldt_miscdev = {
@@ -425,27 +351,6 @@ static struct miscdevice ldt_miscdev = {
};
/*
- * kthread section
- */
-
-static int ldt_thread(void *data)
-{
- int ret = 0;
- allow_signal(SIGINT);
- while (!kthread_should_stop()) {
- ret = wait_for_completion_interruptible(&ldt_complete);
- if (ret == -ERESTARTSYS) {
- pr_debug("%s: %s\n", __func__, "interrupted");
- return -EINTR;
- }
- /*
- perform here a useful work in scheduler context
- */
- }
- return ret;
-}
-
-/*
* UART initialization section
*/
@@ -461,14 +366,14 @@ static int uart_probe(void)
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "request_region failed");
return -EBUSY;
}
- port_ptr = ioport_map(port, port_size);
- pr_debug("%s: port_ptr=%p\n", __func__, port_ptr);
- if (!port_ptr) {
+ drvdata->port_ptr = ioport_map(port, port_size);
+ pr_debug("%s: drvdata->port_ptr=%p\n", __func__, drvdata->port_ptr);
+ if (!drvdata->port_ptr) {
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "ioport_map failed");
return -ENODEV;
}
}
- if (irq && port_ptr) {
+ if (irq && drvdata->port_ptr) {
/*
* Minimal configuration of UART for trivial I/O opertaions
* and ISR just to porform basic tests.
@@ -483,22 +388,22 @@ static int uart_probe(void)
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "request_irq failed");
return ret;
}
- iowrite8(UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_LOOP, port_ptr + UART_MCR);
- uart_detected = (ioread8(port_ptr + UART_MSR) & 0xF0) == (UART_MSR_DCD | UART_MSR_CTS);
- pr_debug("UART_MSR=0x%02X\n", ioread8(port_ptr + UART_MSR));
- pr_debug("%s: uart_detected=0x%X\n", __func__, uart_detected);
-
- if (uart_detected) {
- iowrite8(UART_IER_RDI | UART_IER_RLSI | UART_IER_THRI, port_ptr + UART_IER);
- iowrite8(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, port_ptr + UART_MCR);
+ iowrite8(UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_LOOP, drvdata->port_ptr + UART_MCR);
+ drvdata->uart_detected = (ioread8(drvdata->port_ptr + UART_MSR) & 0xF0) == (UART_MSR_DCD | UART_MSR_CTS);
+ pr_debug("UART_MSR=0x%02X\n", ioread8(drvdata->port_ptr + UART_MSR));
+ pr_debug("%s: drvdata->uart_detected=0x%X\n", __func__, drvdata->uart_detected);
+
+ if (drvdata->uart_detected) {
+ iowrite8(UART_IER_RDI | UART_IER_RLSI | UART_IER_THRI, drvdata->port_ptr + UART_IER);
+ iowrite8(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, drvdata->port_ptr + UART_MCR);
iowrite8(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
- port_ptr + UART_FCR);
+ drvdata->port_ptr + UART_FCR);
pr_debug("%s: loopback=%d\n", __func__, loopback);
if (loopback)
- iowrite8(ioread8(port_ptr + UART_MCR) | UART_MCR_LOOP,
- port_ptr + UART_MCR);
+ iowrite8(ioread8(drvdata->port_ptr + UART_MCR) | UART_MCR_LOOP,
+ drvdata->port_ptr + UART_MCR);
}
- if (!uart_detected && loopback)
+ if (!drvdata->uart_detected && loopback)
pr_warn("Emulating loopback in software\n");
}
return ret;
@@ -508,28 +413,20 @@ static int uart_probe(void)
* main initialization and cleanup section
*/
-static struct task_struct *thread;
static struct dentry *debugfs;
-static int ldt_cleanup(struct platform_device *pdev)
+static void ldt_cleanup(void)
{
- struct ldt_data *drvdata = platform_get_drvdata(pdev);
- dev_dbg(&pdev->dev, "%s\n", __func__);
-
debugfs_remove(debugfs);
if (ldt_miscdev.this_device)
misc_deregister(&ldt_miscdev);
- if (!IS_ERR_OR_NULL(thread)) {
- send_sig(SIGINT, thread, 1);
- kthread_stop(thread);
- }
del_timer(&ldt_timer);
if (irq) {
- if (uart_detected) {
- iowrite8(0, port_ptr + UART_IER);
- iowrite8(0, port_ptr + UART_FCR);
- iowrite8(0, port_ptr + UART_MCR);
- ioread8(port_ptr + UART_RX);
+ if (drvdata->uart_detected) {
+ iowrite8(0, drvdata->port_ptr + UART_IER);
+ iowrite8(0, drvdata->port_ptr + UART_FCR);
+ iowrite8(0, drvdata->port_ptr + UART_MCR);
+ ioread8(drvdata->port_ptr + UART_RX);
}
free_irq(irq, THIS_MODULE);
}
@@ -544,42 +441,38 @@ static int ldt_cleanup(struct platform_device *pdev)
}
pr_debug("%s: isr_counter=%d\n", __func__, isr_counter);
- pr_debug("%s: ldt_work_counter=%d\n", __func__, ldt_work_counter);
- if (port_ptr)
- ioport_unmap(port_ptr);
+ if (drvdata->port_ptr)
+ ioport_unmap(drvdata->port_ptr);
if (port_r)
release_region(port, port_size);
kfree(drvdata);
- platform_set_drvdata(pdev, NULL);
- return 0;
}
-int ldt_data_init(struct platform_device *pdev)
+struct ldt_data * ldt_data_init(void)
{
+ struct ldt_data *drvdata;
+
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
- return -ENOMEM;
+ return NULL;
init_waitqueue_head(&drvdata->readable);
init_waitqueue_head(&drvdata->writeable);
INIT_KFIFO(drvdata->in_fifo);
INIT_KFIFO(drvdata->out_fifo);
- platform_set_drvdata(pdev, drvdata);
mutex_init(&drvdata->read_lock);
mutex_init(&drvdata->write_lock);
- return 0;
+ return drvdata;
}
-static __devinit int ldt_probe(struct platform_device *pdev)
+static __devinit int ldt_init(void)
{
- int ret;
- char *data = NULL;
- struct resource *r;
- dev_dbg(&pdev->dev, "%s attaching device\n", __func__);
+ int ret = 0;
+
pr_debug("MODNAME=%s\n", KBUILD_MODNAME);
pr_debug("port = %d irq = %d\n", port, irq);
- ret = ldt_data_init(pdev);
- if (ret < 0) {
+ drvdata = ldt_data_init();
+ if (!drvdata) {
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "ldt_data_init failed");
goto exit;
}
@@ -600,20 +493,6 @@ static __devinit int ldt_probe(struct platform_device *pdev)
goto exit;
}
pages_flag(virt_to_page(drvdata->out_buf), PFN_UP(bufsize), PG_reserved, 1);
- pr_debug("%s: pdev->dev.of_node=%p\n", __func__, pdev->dev.of_node);
-#ifdef CONFIG_OF_DEVICE
- of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
-#endif
- data = dev_get_platdata(&pdev->dev);
- pr_debug("%p %s\n", data, data);
- if (!irq)
- irq = platform_get_irq(pdev, 0);
- r = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (r && !port)
- port = r->start;
-
- if (r && !port_size)
- port_size = resource_size(r);
isr_counter = 0;
/*
* This drivers without UART can be sill used
@@ -625,11 +504,6 @@ static __devinit int ldt_probe(struct platform_device *pdev)
goto exit;
}
mod_timer(&ldt_timer, jiffies + HZ / 10);
- thread = kthread_run(ldt_thread, NULL, "%s", KBUILD_MODNAME);
- if (IS_ERR(thread)) {
- ret = PTR_ERR(thread);
- goto exit;
- }
debugfs = debugfs_create_file(KBUILD_MODNAME, S_IRUGO, NULL, NULL, &ldt_fops);
if (IS_ERR(debugfs)) {
ret = PTR_ERR(debugfs);
@@ -646,67 +520,12 @@ static __devinit int ldt_probe(struct platform_device *pdev)
exit:
pr_debug("%s: ret=%d\n", __func__, ret);
if (ret < 0)
- ldt_cleanup(pdev);
+ ldt_cleanup();
return ret;
}
-static int __devexit ldt_remove(struct platform_device *pdev)
-{
- dev_dbg(&pdev->dev, "%s detaching device\n", __func__);
- ldt_cleanup(pdev);
- return 0;
-}
-
-/*
- * Following code requires platform_device (ldt_plat_dev.*) to work
- */
-
-#ifdef CONFIG_PM
-
-static int ldt_suspend(struct device *dev)
-{
- return 0;
-}
-
-static int ldt_resume(struct device *dev)
-{
- return 0;
-}
-
-static const struct dev_pm_ops ldt_pm = {
- .suspend = ldt_suspend,
- .resume = ldt_resume,
-};
-
-#define ldt_pm_ops (&ldt_pm)
-#else
-#define ldt_pm_ops NULL
-#endif
-
-/*
- * template for OF FDT ID
- * (Open Firmware Flat Device Tree)
- */
-
-static const struct of_device_id ldt_of_match[] = {
- {.compatible = "linux-driver-template",},
- {},
-};
-
-MODULE_DEVICE_TABLE(of, ldt_of_match);
-
-static struct platform_driver ldt_driver = {
- .driver = {
- .name = "ldt_device_name",
- .owner = THIS_MODULE,
- .pm = ldt_pm_ops,
- .of_match_table = of_match_ptr(ldt_of_match),
- },
- .probe = ldt_probe,
- .remove = __devexit_p(ldt_remove),
-};
-
-module_platform_driver(ldt_driver);
+module_init(ldt_init);
+module_exit(ldt_cleanup);
MODULE_DESCRIPTION("LDT - Linux Driver Template");
MODULE_AUTHOR("Constantine Shulyupin <const@makelinux.net>");
View
93 ldt_plat_drv.c
@@ -6,21 +6,53 @@
* Dual BSD/GPL License
*
* platform_driver template driver
+ * Power Management (dev_pm_ops)
+ * Device Tree (of_device_id)
*
*/
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_irq.h>
#include "tracing.h"
+static int irq;
+static int port;
+static int port_size;
+
static __devinit int ldt_plat_probe(struct platform_device *pdev)
{
char *data = NULL;
struct resource *r;
_entry:
- if (pdev)
+ dev_dbg(&pdev->dev, "%s\n", __func__);
data = pdev->dev.platform_data;
+ irq = platform_get_irq(pdev, 0);
r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ pr_debug("%s: pdev->dev.of_node = %p\n", __func__, pdev->dev.of_node);
+#ifdef CONFIG_OF_DEVICE
+ if (pdev->dev.of_node) {
+ const __be32 * p;
+ int property;
+ of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ p = of_get_property(pdev->dev.of_node, "property", NULL);
+ if (p)
+ property = be32_to_cpu(*p);
+ }
+#endif
+ //struct ldt_data *drvdata = platform_get_drvdata(pdev);
+ //platform_set_drvdata(pdev, drvdata);
+
+ data = dev_get_platdata(&pdev->dev);
+ pr_debug("%p %s\n", data, data);
+ r = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ port = r->start;
+ port_size = resource_size(r);
+
return 0;
}
@@ -30,37 +62,54 @@ static int __devexit ldt_plat_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver ldt_plat_driver = {
- .driver.name = "ldt_device_name",
- .driver.owner = THIS_MODULE,
- .probe = ldt_plat_probe,
- .remove = __devexit_p(ldt_plat_remove),
-};
-
-#ifdef module_platform_driver
-module_platform_driver(ldt_plat_driver);
-#else
/*
- * for releases before v3.1-12 without macro module_platform_driver
+ * template for OF FDT ID
+ * (Open Firmware Flat Device Tree)
*/
-static int ldt_plat_drv_init(void)
+
+static const struct of_device_id ldt_of_match[] = {
+ {.compatible = "linux-driver-template",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, ldt_of_match);
+
+#ifdef CONFIG_PM
+
+static int ldt_suspend(struct device *dev)
{
- int ret = 0;
-_entry:
- ret = platform_driver_register(&ldt_plat_driver);
- return ret;
+ return 0;
}
-static void ldt_plat_drv_exit(void)
+static int ldt_resume(struct device *dev)
{
-_entry:
- platform_driver_unregister(&ldt_plat_driver);
+ return 0;
}
-module_init(ldt_plat_drv_init);
-module_exit(ldt_plat_drv_exit);
+static const struct dev_pm_ops ldt_pm = {
+ .suspend = ldt_suspend,
+ .resume = ldt_resume,
+};
+
+#define ldt_pm_ops (&ldt_pm)
+#else
+#define ldt_pm_ops NULL
#endif
+static struct platform_driver ldt_plat_driver = {
+ .driver = {
+ .name = "ldt_device_name",
+ .owner = THIS_MODULE,
+ .pm = ldt_pm_ops,
+ .of_match_table = of_match_ptr(ldt_of_match),
+ },
+ .probe = ldt_plat_probe,
+ .remove = __devexit_p(ldt_plat_remove),
+
+};
+
+module_platform_driver(ldt_plat_driver);
+
MODULE_DESCRIPTION("LDT - Linux Driver Template: platform_driver template");
MODULE_AUTHOR("Constantine Shulyupin <const@makelinux.net>");
MODULE_LICENSE("Dual BSD/GPL");
View
7 ldt_plat_test
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+sudo insmod ./ldt_plat_drv.ko
+sudo insmod ./ldt_plat_dev.ko
+dmesg
+sudo rmmod ldt_plat_dev ldt_plat_drv
+
Please sign in to comment.
Something went wrong with that request. Please try again.