diff options
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.patch | 365 |
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 + |