/* * linux/drivers/industrialio/adc/max1363.c * Copyright (C) 2008 Jonathan Cameron * * based on linux/drivers/i2c/chips/max123x * Copyright (C) 2002-2004 Stefan Eletzhofer * * based on linux/drivers/acron/char/pcf8583.c * Copyright (C) 2000 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * max1363.c * * Partial support for max1363 and similar chips. * * Not currently implemented. * * - Monitor interrrupt generation. * - Control of internal reference. * - Sysfs scan interface currently assumes unipolar mode. */ #include #include #include #include #include #include #include #include #include #include #include #include "../iio.h" #include "../sysfs.h" #include "max1363.h" /* Available scan modes. * Awkwardly the associated enum is in the header so it is available to * the ring buffer code. */ static const struct max1363_mode max1363_mode_table[] = { MAX1363_MODE_SINGLE(0), MAX1363_MODE_SINGLE(1), MAX1363_MODE_SINGLE(2), MAX1363_MODE_SINGLE(3), MAX1363_MODE_SINGLE(4), MAX1363_MODE_SINGLE(5), MAX1363_MODE_SINGLE(6), MAX1363_MODE_SINGLE(7), MAX1363_MODE_SINGLE(8), MAX1363_MODE_SINGLE(9), MAX1363_MODE_SINGLE(10), MAX1363_MODE_SINGLE(11), MAX1363_MODE_SINGLE_TIMES_8(0), MAX1363_MODE_SINGLE_TIMES_8(1), MAX1363_MODE_SINGLE_TIMES_8(2), MAX1363_MODE_SINGLE_TIMES_8(3), MAX1363_MODE_SINGLE_TIMES_8(4), MAX1363_MODE_SINGLE_TIMES_8(5), MAX1363_MODE_SINGLE_TIMES_8(6), MAX1363_MODE_SINGLE_TIMES_8(7), MAX1363_MODE_SINGLE_TIMES_8(8), MAX1363_MODE_SINGLE_TIMES_8(9), MAX1363_MODE_SINGLE_TIMES_8(10), MAX1363_MODE_SINGLE_TIMES_8(11), MAX1363_MODE_SCAN_TO_CHANNEL(1), MAX1363_MODE_SCAN_TO_CHANNEL(2), MAX1363_MODE_SCAN_TO_CHANNEL(3), MAX1363_MODE_SCAN_TO_CHANNEL(4), MAX1363_MODE_SCAN_TO_CHANNEL(5), MAX1363_MODE_SCAN_TO_CHANNEL(6), MAX1363_MODE_SCAN_TO_CHANNEL(7), MAX1363_MODE_SCAN_TO_CHANNEL(8), MAX1363_MODE_SCAN_TO_CHANNEL(9), MAX1363_MODE_SCAN_TO_CHANNEL(10), MAX1363_MODE_SCAN_TO_CHANNEL(11), MAX1363_MODE_DIFF_SINGLE(0, 1), MAX1363_MODE_DIFF_SINGLE(2, 3), MAX1363_MODE_DIFF_SINGLE(4, 5), MAX1363_MODE_DIFF_SINGLE(6, 7), MAX1363_MODE_DIFF_SINGLE(8, 9), MAX1363_MODE_DIFF_SINGLE(10, 11), MAX1363_MODE_DIFF_SINGLE(1, 0), MAX1363_MODE_DIFF_SINGLE(3, 2), MAX1363_MODE_DIFF_SINGLE(5, 4), MAX1363_MODE_DIFF_SINGLE(7, 6), MAX1363_MODE_DIFF_SINGLE(9, 8), MAX1363_MODE_DIFF_SINGLE(11, 10), MAX1363_MODE_DIFF_SINGLE_TIMES_8(0, 1), MAX1363_MODE_DIFF_SINGLE_TIMES_8(2, 3), MAX1363_MODE_DIFF_SINGLE_TIMES_8(4, 5), MAX1363_MODE_DIFF_SINGLE_TIMES_8(6, 7), MAX1363_MODE_DIFF_SINGLE_TIMES_8(8, 9), MAX1363_MODE_DIFF_SINGLE_TIMES_8(10, 11), MAX1363_MODE_DIFF_SINGLE_TIMES_8(1, 0), MAX1363_MODE_DIFF_SINGLE_TIMES_8(3, 2), MAX1363_MODE_DIFF_SINGLE_TIMES_8(5, 4), MAX1363_MODE_DIFF_SINGLE_TIMES_8(7, 6), MAX1363_MODE_DIFF_SINGLE_TIMES_8(9, 8), MAX1363_MODE_DIFF_SINGLE_TIMES_8(11, 10), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...2-3, 2, 2), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...4-5, 4, 3), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...6-7, 6, 4), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...8-9, 8, 5), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(0-1...10-11, 10, 6), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...3-2, 3, 2), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...5-4, 5, 3), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...7-6, 7, 4), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...9-8, 9, 5), MAX1363_MODE_DIFF_SCAN_TO_CHANNEL_NAMED(1-0...11-10, 11, 6), MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3), MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7), MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8), MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9), MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10), MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11), MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(6-7...8-9, 8, 2), MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(6-7...10-11, 10, 3), MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(7-6...9-8, 9, 2), MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL_NAMED(7-6...11-10, 11, 3), }; /* Applies to max1363 */ static const enum max1363_modes max1363_mode_list[] = { _s0, _s1, _s2, _s3, se0, se1, se2, se3, s0to1, s0to2, s0to3, d0m1, d2m3, d1m0, d3m2, de0m1, de2m3, de1m0, de3m2, d0m1to2m3, d1m0to3m2, }; /* Appies to max1236, max1237 */ static const enum max1363_modes max1236_mode_list[] = { _s0, _s1, _s2, _s3, se0, se1, se2, se3, s0to1, s0to2, s0to3, d0m1, d2m3, d1m0, d3m2, de0m1, de2m3, de1m0, de3m2, d0m1to2m3, d1m0to3m2, s2to3, }; /* Applies to max1238, max1239 */ static const enum max1363_modes max1238_mode_list[] = { _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, se0, se1, se2, se3, se4, se5, se6, se7, se8, se9, se10, se11, s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7, s0to8, s0to9, s0to10, s0to11, d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, de0m1, de2m3, de4m5, de6m7, de8m9, de10m11, de1m0, de3m2, de5m4, de7m6, de9m8, de11m10, d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11, d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10, s6to7, s6to8, s6to9, s6to10, s6to11, s6m7to8m9, s6m7to10m11, s7m6to9m8, s7m6to11m10, }; enum { max1361, max1362, max1363, max1364, max1136, max1137, max1138, max1139, max1236, max1237, max1238, max1239, }; /* max1363 and max1368 tested - rest from data sheet */ static const struct max1363_chip_info max1363_chip_info_tbl[] = { { .name = "max1361", .num_inputs = 4, .monitor_mode = 1, .mode_list = max1363_mode_list, .num_modes = ARRAY_SIZE(max1363_mode_list), .default_mode = s0to3, }, { .name = "max1362", .num_inputs = 4, .monitor_mode = 1, .mode_list = max1363_mode_list, .num_modes = ARRAY_SIZE(max1363_mode_list), .default_mode = s0to3, }, { .name = "max1363", .num_inputs = 4, .monitor_mode = 1, .mode_list = max1363_mode_list, .num_modes = ARRAY_SIZE(max1363_mode_list), .default_mode = s0to3, }, { .name = "max1364", .num_inputs = 4, .monitor_mode = 1, .mode_list = max1363_mode_list, .num_modes = ARRAY_SIZE(max1363_mode_list), .default_mode = s0to3, }, { .name = "max1136", .num_inputs = 4, .int_vref_mv = 4096, .mode_list = max1236_mode_list, .num_modes = ARRAY_SIZE(max1236_mode_list), .default_mode = s0to3, }, { .name = "max1137", .num_inputs = 4, .int_vref_mv = 2048, .mode_list = max1236_mode_list, .num_modes = ARRAY_SIZE(max1236_mode_list), .default_mode = s0to3, }, { .name = "max1138", .num_inputs = 12, .int_vref_mv = 4096, .mode_list = max1238_mode_list, .num_modes = ARRAY_SIZE(max1238_mode_list), .default_mode = s0to11, }, { .name = "max1139", .num_inputs = 12, .int_vref_mv = 2048, .mode_list = max1238_mode_list, .num_modes = ARRAY_SIZE(max1238_mode_list), .default_mode = s0to11, }, { .name = "max1236", .num_inputs = 4, .int_vref_mv = 4096, .mode_list = max1236_mode_list, .num_modes = ARRAY_SIZE(max1236_mode_list), .default_mode = s0to3, }, { .name = "max1237", .num_inputs = 4, .int_vref_mv = 2048, .mode_list = max1236_mode_list, .num_modes = ARRAY_SIZE(max1236_mode_list), .default_mode = s0to3, }, { .name = "max1238", .num_inputs = 12, .int_vref_mv = 4096, .mode_list = max1238_mode_list, .num_modes = ARRAY_SIZE(max1238_mode_list), .default_mode = s0to11, }, { .name = "max1239", .num_inputs = 12, .int_vref_mv = 2048, .mode_list = max1238_mode_list, .num_modes = ARRAY_SIZE(max1238_mode_list), .default_mode = s0to11, }, }; static int max1363_write_basic_config(struct i2c_client *client, unsigned char d1, unsigned char d2) { int ret; u8 *tx_buf = kmalloc(2 , GFP_KERNEL); if (!tx_buf) return -ENOMEM; tx_buf[0] = d1; tx_buf[1] = d2; ret = i2c_master_send(client, tx_buf, 2); kfree(tx_buf); return (ret > 0) ? 0 : ret; } static int max1363_set_scan_mode(struct max1363_state *st) { st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK | MAX1363_SCAN_MASK | MAX1363_SE_DE_MASK); st->configbyte |= st->current_mode->conf; return max1363_write_basic_config(st->client, st->setupbyte, st->configbyte); } static int max1363_initial_setup(struct max1363_state *st) { st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD | MAX1363_SETUP_POWER_UP_INT_REF | MAX1363_SETUP_INT_CLOCK | MAX1363_SETUP_UNIPOLAR | MAX1363_SETUP_NORESET; /* Set scan mode writes the config anyway so wait until then*/ st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte); st->current_mode = &max1363_mode_table[st->chip_info->default_mode]; st->configbyte = MAX1363_CONFIG_BYTE(st->configbyte); return max1363_set_scan_mode(st); } static ssize_t max1363_show_av_scan_modes(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct max1363_state *st = dev_info->dev_data; int i, len = 0; for (i = 0; i < st->chip_info->num_modes; i++) len += sprintf(buf + len, "%s ", max1363_mode_table[st->chip_info ->mode_list[i]].name); len += sprintf(buf + len, "\n"); return len; } /* The dev here is the sysfs related one, not the underlying i2c one */ static ssize_t max1363_scan_direct(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct max1363_state *st = dev_info->dev_data; int len = 0, ret, i; struct i2c_client *client = st->client; char *rxbuf; if (st->current_mode->numvals == 0) return 0; rxbuf = kmalloc(st->current_mode->numvals*2, GFP_KERNEL); if (rxbuf == NULL) return -ENOMEM; /* Interpretation depends on whether these are signed or not!*/ /* Assume not for now */ ret = i2c_master_recv(client, rxbuf, st->current_mode->numvals*2); if (ret < 0) return ret; for (i = 0; i < st->current_mode->numvals; i++) len += sprintf(buf+len, "%d ", ((int)(rxbuf[i*2+0]&0x0F) << 8) + ((int)(rxbuf[i*2+1]))); kfree(rxbuf); len += sprintf(buf + len, "\n"); return len; } static ssize_t max1363_scan(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); int ret; mutex_lock(&dev_info->mlock); if (dev_info->currentmode == INDIO_RING_TRIGGERED) ret = max1363_scan_from_ring(dev, attr, buf); else ret = max1363_scan_direct(dev, attr, buf); mutex_unlock(&dev_info->mlock); return ret; } /* Cannot query the device, so use local copy of state */ static ssize_t max1363_show_scan_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct max1363_state *st = dev_info->dev_data; return sprintf(buf, "%s\n", st->current_mode->name); } static const struct max1363_mode *__max1363_find_mode_in_ci(const struct max1363_chip_info *info, const char *buf) { int i; for (i = 0; i < info->num_modes; i++) if (strcmp(max1363_mode_table[info->mode_list[i]].name, buf) == 0) return &max1363_mode_table[info->mode_list[i]]; return NULL; } static ssize_t max1363_store_scan_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct max1363_state *st = dev_info->dev_data; const struct max1363_mode *new_mode; int ret; mutex_lock(&dev_info->mlock); new_mode = NULL; /* Avoid state changes if a ring buffer is enabled */ if (!iio_ring_enabled(dev_info)) { new_mode = __max1363_find_mode_in_ci(st->chip_info, buf); if (!new_mode) { ret = -EINVAL; goto error_ret; } st->current_mode = new_mode; ret = max1363_set_scan_mode(st); if (ret) goto error_ret; } else { ret = -EBUSY; goto error_ret; } mutex_unlock(&dev_info->mlock); return len; error_ret: mutex_unlock(&dev_info->mlock); return ret; } IIO_DEV_ATTR_AVAIL_SCAN_MODES(max1363_show_av_scan_modes); IIO_DEV_ATTR_SCAN_MODE(S_IRUGO | S_IWUSR, max1363_show_scan_mode, max1363_store_scan_mode); IIO_DEV_ATTR_SCAN(max1363_scan); static ssize_t max1363_show_name(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct max1363_state *st = dev_info->dev_data; return sprintf(buf, "%s\n", st->chip_info->name); } IIO_DEVICE_ATTR(name, S_IRUGO, max1363_show_name, NULL, 0); /*name export */ static struct attribute *max1363_attributes[] = { &iio_dev_attr_available_scan_modes.dev_attr.attr, &iio_dev_attr_scan_mode.dev_attr.attr, &iio_dev_attr_scan.dev_attr.attr, &iio_dev_attr_name.dev_attr.attr, NULL, }; static const struct attribute_group max1363_attribute_group = { .attrs = max1363_attributes, }; static int __devinit max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret, i, regdone = 0; struct max1363_state *st = kzalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) { ret = -ENOMEM; goto error_ret; } /* this is only used for device removal purposes */ i2c_set_clientdata(client, st); atomic_set(&st->protect_ring, 0); /* Find the chip model specific data */ for (i = 0; i < ARRAY_SIZE(max1363_chip_info_tbl); i++) if (!strcmp(max1363_chip_info_tbl[i].name, id->name)) { st->chip_info = &max1363_chip_info_tbl[i]; break; }; /* Unsupported chip */ if (!st->chip_info) { dev_err(&client->dev, "%s is not supported\n", id->name); ret = -ENODEV; goto error_free_st; } st->reg = regulator_get(&client->dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) goto error_put_reg; } st->client = client; st->indio_dev = iio_allocate_device(); if (st->indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; } /* Estabilish that the iio_dev is a child of the i2c device */ st->indio_dev->dev.parent = &client->dev; st->indio_dev->attrs = &max1363_attribute_group; st->indio_dev->dev_data = (void *)(st); st->indio_dev->driver_module = THIS_MODULE; st->indio_dev->modes = INDIO_DIRECT_MODE; ret = max1363_initial_setup(st); if (ret) goto error_free_device; ret = max1363_register_ring_funcs_and_init(st->indio_dev); if (ret) goto error_free_device; ret = iio_device_register(st->indio_dev); if (ret) goto error_cleanup_ring; regdone = 1; ret = max1363_initialize_ring(st->indio_dev->ring); if (ret) goto error_cleanup_ring; return 0; error_cleanup_ring: max1363_ring_cleanup(st->indio_dev); error_free_device: if (!regdone) iio_free_device(st->indio_dev); else iio_device_unregister(st->indio_dev); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); error_free_st: kfree(st); error_ret: return ret; } static int max1363_remove(struct i2c_client *client) { struct max1363_state *st = i2c_get_clientdata(client); struct iio_dev *indio_dev = st->indio_dev; max1363_uninitialize_ring(indio_dev->ring); max1363_ring_cleanup(indio_dev); iio_device_unregister(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); } kfree(st); return 0; } static const struct i2c_device_id max1363_id[] = { { "max1361", max1361 }, { "max1362", max1362 }, { "max1363", max1363 }, { "max1364", max1364 }, { "max1136", max1136 }, { "max1137", max1137 }, { "max1138", max1138 }, { "max1139", max1139 }, { "max1236", max1236 }, { "max1237", max1237 }, { "max1238", max1238 }, { "max1239", max1239 }, {} }; MODULE_DEVICE_TABLE(i2c, max1363_id); static struct i2c_driver max1363_driver = { .driver = { .name = "max1363", }, .probe = max1363_probe, .remove = max1363_remove, .id_table = max1363_id, }; static __init int max1363_init(void) { return i2c_add_driver(&max1363_driver); } static __exit void max1363_exit(void) { i2c_del_driver(&max1363_driver); } MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Maxim 1363 ADC"); MODULE_LICENSE("GPL v2"); module_init(max1363_init); module_exit(max1363_exit);