aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.27/ts72xx/0015-TS-72xx-MAX197-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.27/ts72xx/0015-TS-72xx-MAX197-support.patch')
-rw-r--r--recipes/linux/linux-2.6.27/ts72xx/0015-TS-72xx-MAX197-support.patch365
1 files changed, 365 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.27/ts72xx/0015-TS-72xx-MAX197-support.patch b/recipes/linux/linux-2.6.27/ts72xx/0015-TS-72xx-MAX197-support.patch
new file mode 100644
index 0000000000..0469920a59
--- /dev/null
+++ b/recipes/linux/linux-2.6.27/ts72xx/0015-TS-72xx-MAX197-support.patch
@@ -0,0 +1,365 @@
+From 7220a7235e7b6722fb7dc6e8f599a20bac224760 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sun, 4 Jan 2009 01:32:39 +0100
+Subject: [PATCH] TS-72xx MAX197 support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/include/mach/ts72xx.h | 8 +
+ arch/arm/mach-ep93xx/ts72xx.c | 27 ++++
+ drivers/misc/Kconfig | 21 +++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/ts72xx_max197.c | 235 ++++++++++++++++++++++++++++
+ 5 files changed, 292 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/misc/ts72xx_max197.c
+
+diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+index bb67506..28372df 100644
+--- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
++++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+@@ -87,6 +87,14 @@
+ #define TS72XX_WATCHDOG_FEED_PHYS_BASE 0x23c00000
+ #define TS72XX_WATCHDOG_FEED_SIZE 0x00001000
+
++#define TS72XX_JUMPERS_MAX197_VIRT_BASE 0xfebf2000
++#define TS72XX_JUMPERS_MAX197_PHYS_BASE 0x10800000
++#define TS72XX_JUMPERS_MAX197_SIZE 0x00001000
++
++#define TS72XX_MAX197_SAMPLE_VIRT_BASE 0xfebf1000
++#define TS72XX_MAX197_SAMPLE_PHYS_BASE 0x10f00000
++#define TS72XX_MAX197_SAMPLE_SIZE 0x00001000
++
+ #ifndef __ASSEMBLY__
+ #include <asm/io.h>
+
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index a9d3939..ea3deeb 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -205,6 +205,29 @@ static struct platform_device ts72xx_watchdog_device = {
+ .resource = ts72xx_watchdog_resources,
+ };
+
++static struct resource ts72xx_max197_resources[] = {
++ [0] = { /* sample/control register */
++ .start = TS72XX_MAX197_SAMPLE_PHYS_BASE,
++ .end = TS72XX_MAX197_SAMPLE_PHYS_BASE + TS72XX_MAX197_SAMPLE_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = { /* busy bit */
++ .start = TS72XX_JUMPERS_MAX197_PHYS_BASE,
++ .end = TS72XX_JUMPERS_MAX197_PHYS_BASE + TS72XX_JUMPERS_MAX197_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ts72xx_max197_device = {
++ .name = "ts72xx-max197",
++ .id = -1,
++ .dev = {
++ .platform_data = NULL,
++ },
++ .num_resources = ARRAY_SIZE(ts72xx_max197_resources),
++ .resource = ts72xx_max197_resources,
++};
++
+ static void __init ts72xx_init_machine(void)
+ {
+ ep93xx_init_devices();
+@@ -220,6 +243,10 @@ static void __init ts72xx_init_machine(void)
+ (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+ platform_device_register(&ts72xx_eth_device);
+ platform_device_register(&ts72xx_watchdog_device);
++
++ if (is_max197_installed()) {
++ platform_device_register(&ts72xx_max197_device);
++ }
+ }
+
+ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index a726f3b..4c696c6 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -475,4 +475,25 @@ config SGI_GRU_DEBUG
+ This option enables addition debugging code for the SGI GRU driver. If
+ you are unsure, say N.
+
++config TS72XX_MAX197
++ tristate "TS-72xx MAX197 support"
++ depends on ARCH_EP93XX && MACH_TS72XX && SYSFS
++ help
++ Say Y here if to include support for the MAX197 A/D converter
++ optionally included on Technologic Systems SBCs.
++ Default acquisition range is [0..5V].
++
++ To compile this driver as a module, choose M here: the
++ module will be called ts72xx_max197.
++
++if TS72XX_MAX197
++
++config TS72XX_MAX197_AVERAGE
++ bool "Average measurement"
++ help
++ Say Y here to enable making average measurement. Default is 1.
++ See /sys/module/ts72xx_max197/parameters/average file.
++
++endif # TS72XX_MAX197
++
+ endif # MISC_DEVICES
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index c6c13f6..d97326f 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -30,3 +30,4 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
+ obj-$(CONFIG_SGI_XP) += sgi-xp/
+ obj-$(CONFIG_SGI_GRU) += sgi-gru/
+ obj-$(CONFIG_HP_ILO) += hpilo.o
++obj-$(CONFIG_TS72XX_MAX197) += ts72xx_max197.o
+diff --git a/drivers/misc/ts72xx_max197.c b/drivers/misc/ts72xx_max197.c
+new file mode 100644
+index 0000000..f989de6
+--- /dev/null
++++ b/drivers/misc/ts72xx_max197.c
+@@ -0,0 +1,235 @@
++/*
++ * TS-72XX max197 driver for Technologic Systems boards.
++ *
++ * Voltage conversion is taken from adc_logger from Jim Jackson.
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.com>
++ *
++ * 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 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <asm/io.h>
++
++#define DRV_VERSION "0.2"
++#define PFX "ts72xx_max197: "
++
++#define MAX197_RANGE_5_5 1 // [- 5V + 5V]
++#define MAX197_RANGE_10_10 3 // [-10V +10V]
++#define MAX197_RANGE_0_5 0 // [ 0V + 5V]
++#define MAX197_RANGE_0_10 2 // [ 0V +10V]
++
++#define MAX197_RESET_CHANNEL_CONF(x) (~(3 << (2*(x))))
++#define MAX197_SET_CHANNEL_CONF(x, range) ((range) << (2*(x)))
++#define MAX197_GET_CHANNEL_CONF(x, conf) (((conf) >> (2*(x))) & 3)
++
++struct max197_config
++{
++ void __iomem *control_and_data_register;
++ void __iomem *busy_bit_register;
++ unsigned int channels; // two bits per channels
++};
++
++static struct max197_config conf;
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++static ushort average = 1;
++#endif
++
++static ssize_t max197_acquire(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ int range, n;
++ signed short val;
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++ int i, total;
++#endif
++
++ n = attr->attr.name[2] - 0x31;
++ range = MAX197_GET_CHANNEL_CONF(n, conf.channels);
++
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++ val = 0; total = 0;
++ for (i = 0; i < average; i++) {
++#endif
++
++ __raw_writeb(((range << 3) | n | 0x40) & 0xFF,
++ conf.control_and_data_register);
++ while (__raw_readb(conf.busy_bit_register) & 0x80);
++ val = __raw_readw(conf.control_and_data_register);
++
++ //printk(PFX "%hd/%hd: 0x%04X\n", i+1, average, val);
++
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++ total += val;
++ }
++ total /= average;
++ val = (signed short)total;
++#endif
++
++ /* We want three digit precision */
++ switch (range) {
++ case MAX197_RANGE_0_5:
++ val = ((val * 50000/4096)+5)/10;
++ break;
++ case MAX197_RANGE_5_5:
++ case MAX197_RANGE_0_10:
++ val = ((val * 100000/4096)+5)/10;
++ break;
++ case MAX197_RANGE_10_10:
++ val = ((val * 200000/4096)+5)/10;
++ break;
++ }
++
++ return sprintf(buf, "%d.%03d\n", val/1000, abs(val%1000));
++}
++
++static ssize_t max197_configure(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t len)
++{
++ int n = attr->attr.name[2] - 0x31;
++
++ long val = simple_strtol(buf, NULL, 10);
++ switch (val) {
++ case 10:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_10);
++ break;
++ case 5:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_5);
++ break;
++ case -10:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_10_10);
++ break;
++ case -5:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_5_5);
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return len;
++}
++
++static DEVICE_ATTR(ch1, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch2, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch3, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch4, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch5, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch6, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch7, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch8, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++
++static struct attribute *max197_attributes[] = {
++ &dev_attr_ch1.attr,
++ &dev_attr_ch2.attr,
++ &dev_attr_ch3.attr,
++ &dev_attr_ch4.attr,
++ &dev_attr_ch5.attr,
++ &dev_attr_ch6.attr,
++ &dev_attr_ch7.attr,
++ &dev_attr_ch8.attr,
++ NULL
++};
++
++static struct attribute_group max197_group = {
++ .attrs = max197_attributes,
++ //.name = "channels",
++};
++
++static __devinit int ts72xx_max197_probe(struct platform_device *pdev)
++{
++ int err = 0;
++ struct resource *r_data, *r_busy;
++
++ r_data = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ r_busy = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++
++ if (!r_data || !r_busy) {
++ dev_err(&pdev->dev, "missing resource(s)\n");
++ return -EINVAL;
++ }
++
++ conf.control_and_data_register = ioremap(r_data->start, r_data->end - r_data->start + 1);
++ if (!conf.control_and_data_register) {
++ err = -ENODEV;
++ goto exit;
++ }
++
++ conf.busy_bit_register = ioremap(r_busy->start, r_busy->end - r_busy->start + 1);
++ if (!conf.busy_bit_register) {
++ err = -ENODEV;
++ goto exit_unmap1;
++ }
++
++ conf.channels =
++ MAX197_SET_CHANNEL_CONF(0, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(1, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(2, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(3, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(4, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(5, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(6, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(7, MAX197_RANGE_0_5);
++
++ /* Register sysfs hooks */
++ if ((err = sysfs_create_group(&pdev->dev.kobj, &max197_group)))
++ goto exit_unmap2;
++
++ printk(PFX "TS-72xx max197 driver, v%s\n", DRV_VERSION);
++ return 0;
++
++exit_unmap2:
++ iounmap(conf.busy_bit_register);
++exit_unmap1:
++ iounmap(conf.control_and_data_register);
++exit:
++ return err;
++}
++
++static int __devexit ts72xx_max197_remove(struct platform_device *pdev)
++{
++ sysfs_remove_group(&pdev->dev.kobj, &max197_group);
++ iounmap(conf.busy_bit_register);
++ iounmap(conf.control_and_data_register);
++ return 0;
++}
++
++static struct platform_driver ts72xx_max197_platform_driver = {
++ .probe = ts72xx_max197_probe,
++ .remove = __devexit_p(ts72xx_max197_remove),
++ .driver = {
++ .name = "ts72xx-max197",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ts72xx_max197_init(void)
++{
++ return platform_driver_register(&ts72xx_max197_platform_driver);
++}
++
++static void __exit ts72xx_max197_exit(void)
++{
++ platform_driver_unregister(&ts72xx_max197_platform_driver);
++}
++
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++module_param(average, ushort, S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(average, "Allow average measurement (default=1)");
++#endif
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TS-72xx max197 driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++module_init(ts72xx_max197_init);
++module_exit(ts72xx_max197_exit);
+--
+1.6.0.4
+