155b951e7SEric Miao /* 255b951e7SEric Miao * max1111.c - +2.7V, Low-Power, Multichannel, Serial 8-bit ADCs 355b951e7SEric Miao * 455b951e7SEric Miao * Based on arch/arm/mach-pxa/corgi_ssp.c 555b951e7SEric Miao * 655b951e7SEric Miao * Copyright (C) 2004-2005 Richard Purdie 755b951e7SEric Miao * 855b951e7SEric Miao * Copyright (C) 2008 Marvell International Ltd. 955b951e7SEric Miao * Eric Miao <eric.miao@marvell.com> 1055b951e7SEric Miao * 1155b951e7SEric Miao * This program is free software; you can redistribute it and/or modify 1255b951e7SEric Miao * it under the terms of the GNU General Public License version 2 as 1355b951e7SEric Miao * publishhed by the Free Software Foundation. 1455b951e7SEric Miao */ 1555b951e7SEric Miao 1655b951e7SEric Miao #include <linux/module.h> 1755b951e7SEric Miao #include <linux/kernel.h> 1855b951e7SEric Miao #include <linux/init.h> 1955b951e7SEric Miao #include <linux/err.h> 2055b951e7SEric Miao #include <linux/hwmon.h> 2155b951e7SEric Miao #include <linux/hwmon-sysfs.h> 2255b951e7SEric Miao #include <linux/spi/spi.h> 235a0e3ad6STejun Heo #include <linux/slab.h> 2455b951e7SEric Miao 2555b951e7SEric Miao #define MAX1111_TX_BUF_SIZE 1 2655b951e7SEric Miao #define MAX1111_RX_BUF_SIZE 2 2755b951e7SEric Miao 2855b951e7SEric Miao /* MAX1111 Commands */ 2955b951e7SEric Miao #define MAX1111_CTRL_PD0 (1u << 0) 3055b951e7SEric Miao #define MAX1111_CTRL_PD1 (1u << 1) 3155b951e7SEric Miao #define MAX1111_CTRL_SGL (1u << 2) 3255b951e7SEric Miao #define MAX1111_CTRL_UNI (1u << 3) 3355b951e7SEric Miao #define MAX1111_CTRL_SEL_SH (5) /* NOTE: bit 4 is ignored */ 3455b951e7SEric Miao #define MAX1111_CTRL_STR (1u << 7) 3555b951e7SEric Miao 3655b951e7SEric Miao struct max1111_data { 3755b951e7SEric Miao struct spi_device *spi; 3855b951e7SEric Miao struct device *hwmon_dev; 3955b951e7SEric Miao struct spi_message msg; 4055b951e7SEric Miao struct spi_transfer xfer[2]; 41d737c09cSJean Delvare uint8_t tx_buf[MAX1111_TX_BUF_SIZE]; 42d737c09cSJean Delvare uint8_t rx_buf[MAX1111_RX_BUF_SIZE]; 43d3f684f2SPavel Herrmann struct mutex drvdata_lock; 44d3f684f2SPavel Herrmann /* protect msg, xfer and buffers from multiple access */ 4555b951e7SEric Miao }; 4655b951e7SEric Miao 4755b951e7SEric Miao static int max1111_read(struct device *dev, int channel) 4855b951e7SEric Miao { 4955b951e7SEric Miao struct max1111_data *data = dev_get_drvdata(dev); 5055b951e7SEric Miao uint8_t v1, v2; 5155b951e7SEric Miao int err; 5255b951e7SEric Miao 53d3f684f2SPavel Herrmann /* writing to drvdata struct is not thread safe, wait on mutex */ 54d3f684f2SPavel Herrmann mutex_lock(&data->drvdata_lock); 55d3f684f2SPavel Herrmann 5655b951e7SEric Miao data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) | 5755b951e7SEric Miao MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | 5855b951e7SEric Miao MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR; 5955b951e7SEric Miao 6055b951e7SEric Miao err = spi_sync(data->spi, &data->msg); 6155b951e7SEric Miao if (err < 0) { 6255b951e7SEric Miao dev_err(dev, "spi_sync failed with %d\n", err); 63d3f684f2SPavel Herrmann mutex_unlock(&data->drvdata_lock); 6455b951e7SEric Miao return err; 6555b951e7SEric Miao } 6655b951e7SEric Miao 6755b951e7SEric Miao v1 = data->rx_buf[0]; 6855b951e7SEric Miao v2 = data->rx_buf[1]; 6955b951e7SEric Miao 70d3f684f2SPavel Herrmann mutex_unlock(&data->drvdata_lock); 71d3f684f2SPavel Herrmann 7255b951e7SEric Miao if ((v1 & 0xc0) || (v2 & 0x3f)) 7355b951e7SEric Miao return -EINVAL; 7455b951e7SEric Miao 7555b951e7SEric Miao return (v1 << 2) | (v2 >> 6); 7655b951e7SEric Miao } 7755b951e7SEric Miao 78f16177c2SEric Miao #ifdef CONFIG_SHARPSL_PM 79f16177c2SEric Miao static struct max1111_data *the_max1111; 80f16177c2SEric Miao 81f16177c2SEric Miao int max1111_read_channel(int channel) 82f16177c2SEric Miao { 83f16177c2SEric Miao return max1111_read(&the_max1111->spi->dev, channel); 84f16177c2SEric Miao } 85f16177c2SEric Miao EXPORT_SYMBOL(max1111_read_channel); 86f16177c2SEric Miao #endif 87f16177c2SEric Miao 8855b951e7SEric Miao /* 8955b951e7SEric Miao * NOTE: SPI devices do not have a default 'name' attribute, which is 9055b951e7SEric Miao * likely to be used by hwmon applications to distinguish between 9155b951e7SEric Miao * different devices, explicitly add a name attribute here. 9255b951e7SEric Miao */ 9355b951e7SEric Miao static ssize_t show_name(struct device *dev, 9455b951e7SEric Miao struct device_attribute *attr, char *buf) 9555b951e7SEric Miao { 9655b951e7SEric Miao return sprintf(buf, "max1111\n"); 9755b951e7SEric Miao } 9855b951e7SEric Miao 9955b951e7SEric Miao static ssize_t show_adc(struct device *dev, 10055b951e7SEric Miao struct device_attribute *attr, char *buf) 10155b951e7SEric Miao { 10255b951e7SEric Miao int channel = to_sensor_dev_attr(attr)->index; 10355b951e7SEric Miao int ret; 10455b951e7SEric Miao 10555b951e7SEric Miao ret = max1111_read(dev, channel); 10655b951e7SEric Miao if (ret < 0) 10755b951e7SEric Miao return ret; 10855b951e7SEric Miao 109*012f3b91SEric Miao /* assume the reference voltage to be 2.048V, with an 8-bit sample, 110*012f3b91SEric Miao * the LSB weight is 8mV 111*012f3b91SEric Miao */ 112*012f3b91SEric Miao return sprintf(buf, "%d\n", ret * 8); 11355b951e7SEric Miao } 11455b951e7SEric Miao 11555b951e7SEric Miao #define MAX1111_ADC_ATTR(_id) \ 116*012f3b91SEric Miao SENSOR_DEVICE_ATTR(in##_id##_input, S_IRUGO, show_adc, NULL, _id) 11755b951e7SEric Miao 11855b951e7SEric Miao static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 11955b951e7SEric Miao static MAX1111_ADC_ATTR(0); 12055b951e7SEric Miao static MAX1111_ADC_ATTR(1); 12155b951e7SEric Miao static MAX1111_ADC_ATTR(2); 12255b951e7SEric Miao static MAX1111_ADC_ATTR(3); 12355b951e7SEric Miao 12455b951e7SEric Miao static struct attribute *max1111_attributes[] = { 12555b951e7SEric Miao &dev_attr_name.attr, 126*012f3b91SEric Miao &sensor_dev_attr_in0_input.dev_attr.attr, 127*012f3b91SEric Miao &sensor_dev_attr_in1_input.dev_attr.attr, 128*012f3b91SEric Miao &sensor_dev_attr_in2_input.dev_attr.attr, 129*012f3b91SEric Miao &sensor_dev_attr_in3_input.dev_attr.attr, 13055b951e7SEric Miao NULL, 13155b951e7SEric Miao }; 13255b951e7SEric Miao 13355b951e7SEric Miao static const struct attribute_group max1111_attr_group = { 13455b951e7SEric Miao .attrs = max1111_attributes, 13555b951e7SEric Miao }; 13655b951e7SEric Miao 137d737c09cSJean Delvare static int __devinit setup_transfer(struct max1111_data *data) 13855b951e7SEric Miao { 13955b951e7SEric Miao struct spi_message *m; 14055b951e7SEric Miao struct spi_transfer *x; 14155b951e7SEric Miao 14255b951e7SEric Miao m = &data->msg; 14355b951e7SEric Miao x = &data->xfer[0]; 14455b951e7SEric Miao 14555b951e7SEric Miao spi_message_init(m); 14655b951e7SEric Miao 14755b951e7SEric Miao x->tx_buf = &data->tx_buf[0]; 148d737c09cSJean Delvare x->len = MAX1111_TX_BUF_SIZE; 14955b951e7SEric Miao spi_message_add_tail(x, m); 15055b951e7SEric Miao 15155b951e7SEric Miao x++; 15255b951e7SEric Miao x->rx_buf = &data->rx_buf[0]; 153d737c09cSJean Delvare x->len = MAX1111_RX_BUF_SIZE; 15455b951e7SEric Miao spi_message_add_tail(x, m); 15555b951e7SEric Miao 15655b951e7SEric Miao return 0; 15755b951e7SEric Miao } 15855b951e7SEric Miao 15955b951e7SEric Miao static int __devinit max1111_probe(struct spi_device *spi) 16055b951e7SEric Miao { 16155b951e7SEric Miao struct max1111_data *data; 16255b951e7SEric Miao int err; 16355b951e7SEric Miao 16455b951e7SEric Miao spi->bits_per_word = 8; 16555b951e7SEric Miao spi->mode = SPI_MODE_0; 16655b951e7SEric Miao err = spi_setup(spi); 16755b951e7SEric Miao if (err < 0) 16855b951e7SEric Miao return err; 16955b951e7SEric Miao 17055b951e7SEric Miao data = kzalloc(sizeof(struct max1111_data), GFP_KERNEL); 17155b951e7SEric Miao if (data == NULL) { 17255b951e7SEric Miao dev_err(&spi->dev, "failed to allocate memory\n"); 17355b951e7SEric Miao return -ENOMEM; 17455b951e7SEric Miao } 17555b951e7SEric Miao 17655b951e7SEric Miao err = setup_transfer(data); 17755b951e7SEric Miao if (err) 17855b951e7SEric Miao goto err_free_data; 17955b951e7SEric Miao 180d3f684f2SPavel Herrmann mutex_init(&data->drvdata_lock); 181d3f684f2SPavel Herrmann 18255b951e7SEric Miao data->spi = spi; 18355b951e7SEric Miao spi_set_drvdata(spi, data); 18455b951e7SEric Miao 18555b951e7SEric Miao err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group); 18655b951e7SEric Miao if (err) { 18755b951e7SEric Miao dev_err(&spi->dev, "failed to create attribute group\n"); 188d737c09cSJean Delvare goto err_free_data; 18955b951e7SEric Miao } 19055b951e7SEric Miao 19155b951e7SEric Miao data->hwmon_dev = hwmon_device_register(&spi->dev); 19255b951e7SEric Miao if (IS_ERR(data->hwmon_dev)) { 19355b951e7SEric Miao dev_err(&spi->dev, "failed to create hwmon device\n"); 19455b951e7SEric Miao err = PTR_ERR(data->hwmon_dev); 19555b951e7SEric Miao goto err_remove; 19655b951e7SEric Miao } 19755b951e7SEric Miao 198f16177c2SEric Miao #ifdef CONFIG_SHARPSL_PM 199f16177c2SEric Miao the_max1111 = data; 200f16177c2SEric Miao #endif 20155b951e7SEric Miao return 0; 20255b951e7SEric Miao 20355b951e7SEric Miao err_remove: 20455b951e7SEric Miao sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); 20555b951e7SEric Miao err_free_data: 20655b951e7SEric Miao kfree(data); 20755b951e7SEric Miao return err; 20855b951e7SEric Miao } 20955b951e7SEric Miao 21055b951e7SEric Miao static int __devexit max1111_remove(struct spi_device *spi) 21155b951e7SEric Miao { 21255b951e7SEric Miao struct max1111_data *data = spi_get_drvdata(spi); 21355b951e7SEric Miao 21455b951e7SEric Miao hwmon_device_unregister(data->hwmon_dev); 21555b951e7SEric Miao sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); 216d3f684f2SPavel Herrmann mutex_destroy(&data->drvdata_lock); 21755b951e7SEric Miao kfree(data); 21855b951e7SEric Miao return 0; 21955b951e7SEric Miao } 22055b951e7SEric Miao 22155b951e7SEric Miao static struct spi_driver max1111_driver = { 22255b951e7SEric Miao .driver = { 22355b951e7SEric Miao .name = "max1111", 22455b951e7SEric Miao .owner = THIS_MODULE, 22555b951e7SEric Miao }, 22655b951e7SEric Miao .probe = max1111_probe, 22755b951e7SEric Miao .remove = __devexit_p(max1111_remove), 22855b951e7SEric Miao }; 22955b951e7SEric Miao 23055b951e7SEric Miao static int __init max1111_init(void) 23155b951e7SEric Miao { 23255b951e7SEric Miao return spi_register_driver(&max1111_driver); 23355b951e7SEric Miao } 23455b951e7SEric Miao module_init(max1111_init); 23555b951e7SEric Miao 23655b951e7SEric Miao static void __exit max1111_exit(void) 23755b951e7SEric Miao { 23855b951e7SEric Miao spi_unregister_driver(&max1111_driver); 23955b951e7SEric Miao } 24055b951e7SEric Miao module_exit(max1111_exit); 24155b951e7SEric Miao 24255b951e7SEric Miao MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); 24355b951e7SEric Miao MODULE_DESCRIPTION("MAX1111 ADC Driver"); 24455b951e7SEric Miao MODULE_LICENSE("GPL"); 245e0626e38SAnton Vorontsov MODULE_ALIAS("spi:max1111"); 246