[Armadeus-commitlog] armadeus branch, master, updated. armadeus-5.0-15-ga4e3b8b
Brought to you by:
sszy
|
From: Fabien M <fa...@us...> - 2012-09-10 10:18:57
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "armadeus".
The branch, master has been updated
via a4e3b8b667285d64a0f7b35f6a851e8f095829ad (commit)
via 149aeaf86dfceab2b943dfde43b791391e514a47 (commit)
from 4768bc75d3e477c6d6cffd1d022a736cc6ff9244 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a4e3b8b667285d64a0f7b35f6a851e8f095829ad
Author: Kevin JOLY <jol...@gm...>
Date: Tue Sep 4 18:50:48 2012 +0200
Add pod_servo driver to virtual_components
Signed-off-by: Fabien Marteau <fab...@ar...>
commit 149aeaf86dfceab2b943dfde43b791391e514a47
Author: Kevin JOLY <jol...@gm...>
Date: Tue Sep 4 18:48:28 2012 +0200
Add pod_pwm driver to virtual_components
Signed-off-by: Fabien Marteau <fab...@ar...>
-----------------------------------------------------------------------
Summary of changes:
.../linux/modules/fpga/virtual_components/Kconfig | 2 +
.../linux/modules/fpga/virtual_components/Makefile | 2 +-
.../fpga/virtual_components/pod_pwm/.test.c.swp | Bin 0 -> 12288 bytes
.../fpga/virtual_components/pod_pwm/Kconfig | 8 +
.../fpga/virtual_components/pod_pwm/Makefile | 3 +
.../fpga/virtual_components/pod_pwm/pod_pwm.c | 368 ++++++++++++++++++++
.../fpga/virtual_components/pod_pwm/pod_pwm.h} | 24 +-
.../fpga/virtual_components/pod_servo/Kconfig | 8 +
.../fpga/virtual_components/pod_servo/Makefile | 3 +
.../fpga/virtual_components/pod_servo/pod_servo.c | 305 ++++++++++++++++
.../fpga/virtual_components/pod_servo/pod_servo.h} | 24 +-
11 files changed, 712 insertions(+), 35 deletions(-)
create mode 100644 target/linux/modules/fpga/virtual_components/pod_pwm/.test.c.swp
create mode 100644 target/linux/modules/fpga/virtual_components/pod_pwm/Kconfig
create mode 100644 target/linux/modules/fpga/virtual_components/pod_pwm/Makefile
create mode 100644 target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.c
copy target/linux/{debug/imxregs/definitions.h => modules/fpga/virtual_components/pod_pwm/pod_pwm.h} (68%)
create mode 100644 target/linux/modules/fpga/virtual_components/pod_servo/Kconfig
create mode 100644 target/linux/modules/fpga/virtual_components/pod_servo/Makefile
create mode 100644 target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.c
copy target/linux/{debug/imxregs/definitions.h => modules/fpga/virtual_components/pod_servo/pod_servo.h} (68%)
diff --git a/target/linux/modules/fpga/virtual_components/Kconfig b/target/linux/modules/fpga/virtual_components/Kconfig
index c976c69..a3e63e8 100644
--- a/target/linux/modules/fpga/virtual_components/Kconfig
+++ b/target/linux/modules/fpga/virtual_components/Kconfig
@@ -10,4 +10,6 @@ source "drivers/armadeus/fpga/virtual_components/irq_mngr/Kconfig"
source "drivers/armadeus/fpga/virtual_components/button/Kconfig"
source "drivers/armadeus/fpga/virtual_components/led/Kconfig"
source "drivers/armadeus/fpga/virtual_components/pod_gpio/Kconfig"
+source "drivers/armadeus/fpga/virtual_components/pod_pwm/Kconfig"
+source "drivers/armadeus/fpga/virtual_components/pod_servo/Kconfig"
source "drivers/armadeus/fpga/virtual_components/sploader/Kconfig"
diff --git a/target/linux/modules/fpga/virtual_components/Makefile b/target/linux/modules/fpga/virtual_components/Makefile
index 71d24a9..8060879 100644
--- a/target/linux/modules/fpga/virtual_components/Makefile
+++ b/target/linux/modules/fpga/virtual_components/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ARMADEUS_FPGA_VIRTUAL_COMPONENTS) += button/ irq_mngr/ led/ pod_gpio/ sploader/
+obj-$(CONFIG_ARMADEUS_FPGA_VIRTUAL_COMPONENTS) += button/ irq_mngr/ led/ pod_gpio/ sploader/ pod_pwm/ pod_servo/
diff --git a/target/linux/modules/fpga/virtual_components/pod_pwm/.test.c.swp b/target/linux/modules/fpga/virtual_components/pod_pwm/.test.c.swp
new file mode 100644
index 0000000..d7f225b
Binary files /dev/null and b/target/linux/modules/fpga/virtual_components/pod_pwm/.test.c.swp differ
diff --git a/target/linux/modules/fpga/virtual_components/pod_pwm/Kconfig b/target/linux/modules/fpga/virtual_components/pod_pwm/Kconfig
new file mode 100644
index 0000000..bf00c2c
--- /dev/null
+++ b/target/linux/modules/fpga/virtual_components/pod_pwm/Kconfig
@@ -0,0 +1,8 @@
+
+config ARMADEUS_FPGA_VIRTUAL_COMPONENTS_PWM
+ tristate "pod_pwm"
+ default n
+ depends on ARMADEUS_FPGA_VIRTUAL_COMPONENTS
+ ---help---
+ Armadeus driver for virtual pod_pwm component.
+ kernel >= 2.6.38 is required
diff --git a/target/linux/modules/fpga/virtual_components/pod_pwm/Makefile b/target/linux/modules/fpga/virtual_components/pod_pwm/Makefile
new file mode 100644
index 0000000..890a4a8
--- /dev/null
+++ b/target/linux/modules/fpga/virtual_components/pod_pwm/Makefile
@@ -0,0 +1,3 @@
+# Makefile for pod_pwm driver
+
+obj-$(CONFIG_ARMADEUS_FPGA_VIRTUAL_COMPONENTS_PWM) += pod_pwm.o
diff --git a/target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.c b/target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.c
new file mode 100644
index 0000000..291bcab
--- /dev/null
+++ b/target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.c
@@ -0,0 +1,368 @@
+/*
+ * Linux kernel driver for the POD component pod_pwm
+ *
+ * (C) Copyright 2012 - EIRBOT <eirbot.enseirb.fr>
+ * Author: Kevin JOLY jol...@gm...
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pod_pwm.h"
+
+/* POD_PWM Registers*/
+#define REG_PWM_ID 0x00
+#define REG_T_ON 0x02
+#define REG_DIV 0x04
+
+#define DEFAULT_CLOCK_SOURCE_FREQUENCY 100000000
+
+struct class *class_pwm;
+
+struct pod_pwm_device {
+ int angle;
+ void __iomem *membase;
+ struct device *dev;
+ int gMajor;
+ unsigned long clock_source;
+};
+
+const struct file_operations pwm_fops = {
+ /* TODO */
+};
+
+/* Low level access */
+static u16 read_reg(const struct pod_pwm_device *pwm, u16 reg)
+{
+ return ioread16(pwm->membase + reg);
+}
+
+void write_reg(const struct pod_pwm_device *pwm, u16 reg, u16 value)
+{
+ iowrite16(value, pwm->membase + reg);
+}
+
+unsigned int get_duty(const struct pod_pwm_device *pwm)
+{
+ u16 t_on;
+ u16 div;
+
+ t_on = read_reg(pwm, REG_T_ON);
+ div = read_reg(pwm, REG_DIV);
+
+ if (div < 1)
+ return 0;
+
+ return (t_on*1000)/div;
+}
+
+/* Attributes */
+
+static ssize_t pwm_show_duty(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%d\n", get_duty(pwm));
+}
+
+static ssize_t pwm_store_duty(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int err;
+ u16 div;
+ u16 duty;
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(dev));
+
+ err = kstrtouint(buf, 10, (unsigned int *)(&duty));
+
+ if (err) {
+ dev_err(dev, "kstrtol failed with error code %d.\n", err);
+ return size;
+ }
+
+ if (duty < 0)
+ duty = 0;
+ if (duty > 1000)
+ duty = 1000;
+
+ div = read_reg(pwm, REG_DIV);
+ write_reg(pwm, REG_T_ON, (div * duty)/1000);
+
+ return size;
+}
+
+static ssize_t pwm_show_frequency(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u16 div;
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(dev));
+
+ div = read_reg(pwm, REG_DIV);
+ if (div <= 0)
+ return pwm->clock_source;
+
+ return sprintf(buf, "%ld\n", pwm->clock_source/div);
+}
+
+static ssize_t pwm_store_frequency(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u16 div;
+ int err;
+ unsigned int duty;
+ unsigned long freq;
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(dev));
+
+ err = kstrtol(buf, 10, &freq);
+
+ if (err) {
+ dev_err(dev, "kstrtol failed with error code %d.\n", err);
+ return size;
+ }
+
+ if ((freq > pwm->clock_source) || (freq < pwm->clock_source/65635)) {
+ dev_err(dev, "Invalid pwm frequency %ld.\n", freq);
+ return size;
+ }
+
+ duty = get_duty(pwm);
+ div = pwm->clock_source / freq;
+
+ write_reg(pwm, REG_DIV, div);
+ write_reg(pwm, REG_T_ON, (div * duty)/1000);
+
+ return size;
+}
+
+static ssize_t pwm_show_clock_source(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%ld\n", pwm->clock_source);
+}
+
+static ssize_t pwm_store_clock_source(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int err;
+ long freq;
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(dev));
+
+ err = kstrtol(buf, 10, &freq);
+
+ if (err) {
+ dev_err(dev, "kstrtol failed with error code %d.\n", err);
+ return size;
+ }
+
+ if (freq < 1)
+ return 0;
+
+ pwm->clock_source = freq;
+
+ return size;
+}
+
+/* dev_attr_duty /class/pwm/pwmX/duty */
+static DEVICE_ATTR(duty, S_IWUSR | S_IRUGO, pwm_show_duty, pwm_store_duty);
+/* dev_attr_frequency /sys/class/pwm/pwmX/frequency */
+static DEVICE_ATTR(frequency, S_IWUSR | S_IRUGO, pwm_show_frequency,
+ pwm_store_frequency);
+/* dev_attr_clock_source /sys/class/pwm/pwmX/clock_source */
+static DEVICE_ATTR(clock_source, S_IWUSR | S_IRUGO, pwm_show_clock_source,
+ pwm_store_clock_source);
+
+void init_pwm(struct pod_pwm_device *pwm)
+{
+ pwm->clock_source = DEFAULT_CLOCK_SOURCE_FREQUENCY;
+ pwm->gMajor = 0;
+}
+
+static int pod_pwm_drv_probe(struct platform_device *pdev)
+{
+ struct resource *resource_memory;
+ struct pod_pwm_device *pwm;
+ int err;
+ u16 id;
+
+ resource_memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!resource_memory) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "Device pod_pwm not found\n");
+ goto exit_error;
+ }
+
+ if (!request_mem_region(resource_memory->start,
+ resource_size(resource_memory), DRIVER_NAME)) {
+ dev_err(&pdev->dev, "Can't request memory region %x to %x\n",
+ resource_memory->start,
+ resource_memory->start + resource_memory->end);
+ err = -ENOMEM;
+ goto exit_error;
+ }
+
+ pwm = kmalloc(sizeof(struct pod_pwm_device), GFP_KERNEL);
+
+ if (!pwm) {
+ err = -ENOMEM;
+ goto exit_release_mem;
+ }
+ pwm->membase = ioremap(resource_memory->start,
+ resource_memory->end - resource_memory->start + 1);
+ if (!pwm) {
+ err = -ENOMEM;
+ goto exit_kfree;
+ }
+
+ id = read_reg(pwm, REG_PWM_ID);
+
+ if (pdev->id != id) {
+ dev_err(&pdev->dev,
+ "Driver id %d doesn't match with the device id %d\n",
+ pdev->id, id);
+ err = -ENODEV;
+ goto exit_iounmap;
+ }
+
+ init_pwm(pwm);
+
+ err = register_chrdev(pwm->gMajor, DRIVER_NAME, &pwm_fops);
+ if (err < 0) {
+ dev_err(&pdev->dev, "unable to register char driver.\n");
+ goto exit_iounmap;
+ }
+
+ if (!pwm->gMajor)
+ pwm->gMajor = err;
+
+ pwm->dev = device_create(class_pwm, NULL, MKDEV(pwm->gMajor, pdev->id),
+ NULL, "pwm%i", pdev->id);
+
+ if (IS_ERR(pwm->dev)) {
+ err = PTR_ERR(pwm->dev);
+ dev_err(&pdev->dev, "can't create device\n");
+ goto error_device_destroy;
+ }
+
+ err = device_create_file(pwm->dev, &dev_attr_duty);
+ if (err) {
+ dev_err(&pdev->dev,
+ "can't create device attribute \"duty\".\n");
+ goto error_device_destroy;
+ }
+
+ err = device_create_file(pwm->dev, &dev_attr_frequency);
+ if (err) {
+ dev_err(&pdev->dev,
+ "can't create device attribute \"frequency\".\n");
+ goto error_device_destroy;
+ }
+
+ err = device_create_file(pwm->dev, &dev_attr_clock_source);
+
+ if (err) {
+ dev_err(&pdev->dev,
+ "can't create device attribute \"clock_source\".\n");
+ goto error_device_destroy;
+ }
+
+ dev_set_drvdata(&pdev->dev, pwm);
+ dev_set_drvdata(pwm->dev, pwm);
+
+ dev_info(&pdev->dev, "pod_pwm:%d Succesfully probed", id);
+
+ return 0;
+
+error_device_destroy:
+ device_destroy(class_pwm, MKDEV(pwm->gMajor, pdev->id));
+ unregister_chrdev(pwm->gMajor, DRIVER_NAME);
+exit_iounmap:
+ iounmap(pwm->membase);
+exit_kfree:
+ kfree(pwm);
+exit_release_mem:
+ release_mem_region(resource_memory->start,
+ resource_size(resource_memory));
+exit_error:
+ return err;
+}
+
+static int pod_pwm_drv_remove(struct platform_device *pdev)
+{
+ struct pod_pwm_device *pwm =
+ (struct pod_pwm_device *)(dev_get_drvdata(&pdev->dev));
+ struct resource *resource_memory =
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ device_remove_file(pwm->dev, &dev_attr_duty);
+ device_remove_file(pwm->dev, &dev_attr_frequency);
+ device_remove_file(pwm->dev, &dev_attr_clock_source);
+
+ device_destroy(class_pwm, MKDEV(pwm->gMajor, pdev->id));
+ unregister_chrdev(pwm->gMajor, DRIVER_NAME);
+
+ if (pwm->membase > 0)
+ iounmap(pwm->membase);
+
+ kfree(pwm);
+ release_mem_region(resource_memory->start,
+ resource_size(resource_memory));
+
+ return 0;
+}
+
+static struct platform_driver pod_pwm_driver = {
+ .probe = pod_pwm_drv_probe,
+ .remove = pod_pwm_drv_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+},
+};
+
+static int __init pod_pwm_init(void)
+{
+ class_pwm = class_create(THIS_MODULE, "pod_pwm");
+ if (IS_ERR(class_pwm))
+ return PTR_ERR(class_pwm);
+
+ return platform_driver_register(&pod_pwm_driver);
+}
+
+static void __exit pod_pwm_exit(void)
+{
+ platform_driver_unregister(&pod_pwm_driver);
+ class_destroy(class_pwm);
+}
+
+module_init(pod_pwm_init);
+module_exit(pod_pwm_exit);
+
+MODULE_AUTHOR("Kevin JOLY, inspired by i.MX PWM driver");
+MODULE_DESCRIPTION("POD pwm driver");
+MODULE_LICENSE("GPL");
diff --git a/target/linux/debug/imxregs/definitions.h b/target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.h
similarity index 68%
copy from target/linux/debug/imxregs/definitions.h
copy to target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.h
index ee71db3..aa5fca3 100644
--- a/target/linux/debug/imxregs/definitions.h
+++ b/target/linux/modules/fpga/virtual_components/pod_pwm/pod_pwm.h
@@ -1,8 +1,8 @@
/*
- * definitions.h - imxregs common definitions
+ * Linux kernel driver for the POD component pod_pwm
*
- * Copyright (C) 2008 armadeus systems
- * Author: Julien Boibessot
+ * (C) Copyright 2012 - EIRBOT <eirbot.enseirb.fr>
+ * Author: Kevin JOLY jol...@gm...
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,20 +17,10 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
+#ifndef LINUX_POD_PWM
+#define LINUX_POD_PWM
-typedef unsigned int u32;
-
-struct reg_info {
- char *name;
- u32 addr;
- int shift;
- u32 mask;
- char type;
- char *desc;
-};
+#define DRIVER_NAME "pod_pwm"
-// Size of mmapping:
-#define MAP_SIZE 4096
-#define MAP_MASK ( MAP_SIZE - 1 )
+#endif
diff --git a/target/linux/modules/fpga/virtual_components/pod_servo/Kconfig b/target/linux/modules/fpga/virtual_components/pod_servo/Kconfig
new file mode 100644
index 0000000..eaeb370
--- /dev/null
+++ b/target/linux/modules/fpga/virtual_components/pod_servo/Kconfig
@@ -0,0 +1,8 @@
+
+config ARMADEUS_FPGA_VIRTUAL_COMPONENTS_SERVO
+ tristate "pod_servo"
+ default n
+ depends on ARMADEUS_FPGA_VIRTUAL_COMPONENTS
+ ---help---
+ Armadeus driver for virtual pod_servo component.
+ kernel >= 2.6.38 is required
diff --git a/target/linux/modules/fpga/virtual_components/pod_servo/Makefile b/target/linux/modules/fpga/virtual_components/pod_servo/Makefile
new file mode 100644
index 0000000..35d9c2a
--- /dev/null
+++ b/target/linux/modules/fpga/virtual_components/pod_servo/Makefile
@@ -0,0 +1,3 @@
+# Makefile for pod_pwm driver
+
+obj-$(CONFIG_ARMADEUS_FPGA_VIRTUAL_COMPONENTS_PWM) += pod_servo.o
diff --git a/target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.c b/target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.c
new file mode 100644
index 0000000..d62e78f
--- /dev/null
+++ b/target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.c
@@ -0,0 +1,305 @@
+/*
+ * Linux kernel driver for the POD component pod_servo
+ *
+ * (C) Copyright 2012 - EIRBOT <eirbot.enseirb.fr>
+ * Author: Kevin JOLY jol...@gm...
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pod_servo.h"
+
+/* POD_SERVO Registers*/
+#define REG_SERVO_ID 0x00
+#define REG_ANGLE 0x02
+
+#define DEFAULT_CLOCK_SOURCE_FREQUENCY 100000000
+
+struct class *class_servo;
+
+struct pod_servo_device {
+ int angle;
+ void __iomem *membase;
+ struct device *dev;
+ int gMajor;
+ unsigned long clock_source;
+};
+
+const struct file_operations servo_fops = {
+ /* TODO */
+};
+
+/* Low level access */
+static u16 read_reg(const struct pod_servo_device *servo, u16 reg)
+{
+ return ioread16(servo->membase + reg);
+}
+
+void write_reg(const struct pod_servo_device *servo, u16 reg, u16 value)
+{
+ iowrite16(value, servo->membase + reg);
+}
+
+unsigned int get_angle(const struct pod_servo_device *servo)
+{
+ u16 angle;
+
+ angle = read_reg(servo, REG_ANGLE);
+
+ return (angle*180)/1000;
+}
+
+/* Attributes */
+
+static ssize_t servo_show_angle(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pod_servo_device *servo =
+ (struct pod_servo_device *)(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%d\n", get_angle(servo));
+}
+
+static ssize_t servo_store_angle(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int err;
+ u16 angle;
+ struct pod_servo_device *servo =
+ (struct pod_servo_device *)(dev_get_drvdata(dev));
+
+ err = kstrtouint(buf, 10, (unsigned int *)(&angle));
+
+ if (err) {
+ dev_err(dev, "kstrtol failed with error code %d.\n", err);
+ return size;
+ }
+
+ if (angle < 0)
+ angle = 0;
+ if (angle > 180)
+ angle = 1000;
+
+ write_reg(servo, REG_ANGLE, (angle*1000)/180);
+
+ return size;
+}
+
+static ssize_t servo_show_clock_source(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pod_servo_device *servo =
+ (struct pod_servo_device *)(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%ld\n", servo->clock_source);
+}
+
+static ssize_t servo_store_clock_source(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int err;
+ long freq;
+ struct pod_servo_device *servo =
+ (struct pod_servo_device *)(dev_get_drvdata(dev));
+
+ err = kstrtol(buf, 10, &freq);
+
+ if (err) {
+ dev_err(dev, "kstrtol failed with error code %d.\n", err);
+ return size;
+ }
+
+ if (freq < 1)
+ return 0;
+
+ servo->clock_source = freq;
+
+ return size;
+}
+
+/* dev_attr_angle /class/servo/servoX/angle */
+static DEVICE_ATTR(angle, S_IWUSR | S_IRUGO, servo_show_angle,
+ servo_store_angle);
+/* dev_attr_clock_source /sys/class/servo/servoX/clock_source */
+static DEVICE_ATTR(clock_source, S_IWUSR | S_IRUGO, servo_show_clock_source,
+ servo_store_clock_source);
+
+void init_servo(struct pod_servo_device *servo)
+{
+ servo->clock_source = DEFAULT_CLOCK_SOURCE_FREQUENCY;
+ servo->gMajor = 0;
+}
+
+static int pod_servo_drv_probe(struct platform_device *pdev)
+{
+ struct resource *resource_memory;
+ struct pod_servo_device *servo;
+ int err;
+ u16 id;
+
+ resource_memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!resource_memory) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "Device pod_servo not found\n");
+ goto exit_error;
+ }
+
+ if (!request_mem_region(resource_memory->start,
+ resource_size(resource_memory), DRIVER_NAME)) {
+ dev_err(&pdev->dev, "Can't request memory region %x to %x\n",
+ resource_memory->start,
+ resource_memory->start + resource_memory->end);
+ err = -ENOMEM;
+ goto exit_error;
+ }
+
+ servo = kmalloc(sizeof(struct pod_servo_device), GFP_KERNEL);
+
+ if (!servo) {
+ err = -ENOMEM;
+ goto exit_release_mem;
+ }
+ servo->membase = ioremap(resource_memory->start,
+ resource_memory->end - resource_memory->start + 1);
+ if (!servo) {
+ err = -ENOMEM;
+ goto exit_kfree;
+ }
+
+ id = read_reg(servo, REG_SERVO_ID);
+
+ if (pdev->id != id) {
+ dev_err(&pdev->dev,
+ "Driver id %d doesn't match with the device id %d\n",
+ pdev->id, id);
+ err = -ENODEV;
+ goto exit_iounmap;
+ }
+
+ init_servo(servo);
+
+ err = register_chrdev(servo->gMajor, DRIVER_NAME, &servo_fops);
+ if (err < 0) {
+ dev_err(&pdev->dev, "unable to register char driver.\n");
+ goto exit_iounmap;
+ }
+
+ if (!servo->gMajor)
+ servo->gMajor = err;
+
+ servo->dev = device_create(class_servo, NULL, MKDEV(servo->gMajor, pdev->id),
+ NULL, "servo%i", pdev->id);
+
+ if (IS_ERR(servo->dev)) {
+ err = PTR_ERR(servo->dev);
+ dev_err(&pdev->dev, "can't create device\n");
+ goto error_device_destroy;
+ }
+
+ err = device_create_file(servo->dev, &dev_attr_angle);
+ if (err) {
+ dev_err(&pdev->dev,
+ "can't create device attribute \"angle\".\n");
+ goto error_device_destroy;
+ }
+
+ err = device_create_file(servo->dev, &dev_attr_clock_source);
+
+ if (err) {
+ dev_err(&pdev->dev,
+ "can't create device attribute \"clock_source\".\n");
+ goto error_device_destroy;
+ }
+
+ dev_set_drvdata(&pdev->dev, servo);
+ dev_set_drvdata(servo->dev, servo);
+
+ dev_info(&pdev->dev, "pod_servo:%d Succesfully probed", id);
+
+ return 0;
+
+error_device_destroy:
+ device_destroy(class_servo, MKDEV(servo->gMajor, pdev->id));
+ unregister_chrdev(servo->gMajor, DRIVER_NAME);
+exit_iounmap:
+ iounmap(servo->membase);
+exit_kfree:
+ kfree(servo);
+exit_release_mem:
+ release_mem_region(resource_memory->start,
+ resource_size(resource_memory));
+exit_error:
+ return err;
+}
+
+static int pod_servo_drv_remove(struct platform_device *pdev)
+{
+ struct pod_servo_device *servo =
+ (struct pod_servo_device *)(dev_get_drvdata(&pdev->dev));
+ struct resource *resource_memory =
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ device_remove_file(servo->dev, &dev_attr_angle);
+ device_remove_file(servo->dev, &dev_attr_clock_source);
+
+ device_destroy(class_servo, MKDEV(servo->gMajor, pdev->id));
+ unregister_chrdev(servo->gMajor, DRIVER_NAME);
+
+ if (servo->membase > 0)
+ iounmap(servo->membase);
+
+ kfree(servo);
+ release_mem_region(resource_memory->start,
+ resource_size(resource_memory));
+
+ return 0;
+}
+
+static struct platform_driver pod_servo_driver = {
+ .probe = pod_servo_drv_probe,
+ .remove = pod_servo_drv_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+},
+};
+
+static int __init pod_servo_init(void)
+{
+ class_servo = class_create(THIS_MODULE, "pod_servo");
+ if (IS_ERR(class_servo))
+ return PTR_ERR(class_servo);
+
+ return platform_driver_register(&pod_servo_driver);
+}
+
+static void __exit pod_servo_exit(void)
+{
+ platform_driver_unregister(&pod_servo_driver);
+ class_destroy(class_servo);
+}
+
+module_init(pod_servo_init);
+module_exit(pod_servo_exit);
+
+MODULE_AUTHOR("Kevin JOLY, inspired by i.MX PWM driver");
+MODULE_DESCRIPTION("POD servo driver");
+MODULE_LICENSE("GPL");
diff --git a/target/linux/debug/imxregs/definitions.h b/target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.h
similarity index 68%
copy from target/linux/debug/imxregs/definitions.h
copy to target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.h
index ee71db3..69729df 100644
--- a/target/linux/debug/imxregs/definitions.h
+++ b/target/linux/modules/fpga/virtual_components/pod_servo/pod_servo.h
@@ -1,8 +1,8 @@
/*
- * definitions.h - imxregs common definitions
+ * Linux kernel driver for the POD component pod_servo
*
- * Copyright (C) 2008 armadeus systems
- * Author: Julien Boibessot
+ * (C) Copyright 2012 - EIRBOT <eirbot.enseirb.fr>
+ * Author: Kevin JOLY jol...@gm...
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,20 +17,10 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
+#ifndef LINUX_POD_SERVO
+#define LINUX_POD_SERVO
-typedef unsigned int u32;
-
-struct reg_info {
- char *name;
- u32 addr;
- int shift;
- u32 mask;
- char type;
- char *desc;
-};
+#define DRIVER_NAME "pod_servo"
-// Size of mmapping:
-#define MAP_SIZE 4096
-#define MAP_MASK ( MAP_SIZE - 1 )
+#endif
hooks/post-receive
--
armadeus
|