aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.34/ts72xx/0013-ts72xx_max197.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.34/ts72xx/0013-ts72xx_max197.patch')
-rw-r--r--recipes/linux/linux-2.6.34/ts72xx/0013-ts72xx_max197.patch347
1 files changed, 347 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.34/ts72xx/0013-ts72xx_max197.patch b/recipes/linux/linux-2.6.34/ts72xx/0013-ts72xx_max197.patch
new file mode 100644
index 0000000000..86f52a3fbb
--- /dev/null
+++ b/recipes/linux/linux-2.6.34/ts72xx/0013-ts72xx_max197.patch
@@ -0,0 +1,347 @@
+From 93aa4fc5d32534422e80bbb7d1929f533c4ce65f Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sat, 19 Jun 2010 15:49:34 +0200
+Subject: [PATCH 13/18] ts72xx_max197
+
+---
+ arch/arm/mach-ep93xx/ts72xx.c | 30 +++++
+ drivers/misc/Kconfig | 21 ++++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/ts72xx_max197.c | 235 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 287 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/misc/ts72xx_max197.c
+
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index a46b370..ba27d9d 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -227,6 +227,32 @@ static struct platform_device ts72xx_wdt_device = {
+ };
+
+ /*************************************************************************
++ * MAX197 (8 * 12-bit A/D converter) option
++ *************************************************************************/
++static struct resource ts72xx_max197_resources[] = {
++ [0] = { /* sample/control register */
++ .start = TS72XX_MAX197_SAMPLE_PHYS_BASE,
++ .end = TS72XX_MAX197_SAMPLE_PHYS_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = { /* busy bit */
++ .start = TS72XX_JUMPERS_MAX197_PHYS_BASE,
++ .end = TS72XX_JUMPERS_MAX197_PHYS_BASE + SZ_4K - 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,
++};
++
++/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+ static struct ep93xx_eth_data ts72xx_eth_data = {
+@@ -260,6 +286,10 @@ static void __init ts72xx_init_machine(void)
+ ts72xx_i2c_board_info,
+ ARRAY_SIZE(ts72xx_i2c_board_info));
+
++ if (is_max197_installed()) {
++ platform_device_register(&ts72xx_max197_device);
++ }
++
+ /* PWM1 is DIO_6 on TS-72xx header */
+ ep93xx_register_pwm(0, 1);
+ }
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 0d0d625..45c4be8 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -332,4 +332,25 @@ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+ source "drivers/misc/iwmc3200top/Kconfig"
+
++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 7b6f7ee..388f636 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -23,6 +23,7 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
+ obj-$(CONFIG_ISL29003) += isl29003.o
+ obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
+ obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
++obj-$(CONFIG_TS72XX_MAX197) += ts72xx_max197.o
+ obj-$(CONFIG_DS1682) += ds1682.o
+ obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
+ obj-$(CONFIG_C2PORT) += c2port/
+diff --git a/drivers/misc/ts72xx_max197.c b/drivers/misc/ts72xx_max197.c
+new file mode 100644
+index 0000000..4121ae5
+--- /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.%03ld\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.7.1
+