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]; 41*d737c09cSJean Delvare uint8_t tx_buf[MAX1111_TX_BUF_SIZE]; 42*d737c09cSJean 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 10955b951e7SEric Miao return sprintf(buf, "%d\n", ret); 11055b951e7SEric Miao } 11155b951e7SEric Miao 11255b951e7SEric Miao #define MAX1111_ADC_ATTR(_id) \ 11355b951e7SEric Miao SENSOR_DEVICE_ATTR(adc##_id##_in, S_IRUGO, show_adc, NULL, _id) 11455b951e7SEric Miao 11555b951e7SEric Miao static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 11655b951e7SEric Miao static MAX1111_ADC_ATTR(0); 11755b951e7SEric Miao static MAX1111_ADC_ATTR(1); 11855b951e7SEric Miao static MAX1111_ADC_ATTR(2); 11955b951e7SEric Miao static MAX1111_ADC_ATTR(3); 12055b951e7SEric Miao 12155b951e7SEric Miao static struct attribute *max1111_attributes[] = { 12255b951e7SEric Miao &dev_attr_name.attr, 12355b951e7SEric Miao &sensor_dev_attr_adc0_in.dev_attr.attr, 12455b951e7SEric Miao &sensor_dev_attr_adc1_in.dev_attr.attr, 12555b951e7SEric Miao &sensor_dev_attr_adc2_in.dev_attr.attr, 12655b951e7SEric Miao &sensor_dev_attr_adc3_in.dev_attr.attr, 12755b951e7SEric Miao NULL, 12855b951e7SEric Miao }; 12955b951e7SEric Miao 13055b951e7SEric Miao static const struct attribute_group max1111_attr_group = { 13155b951e7SEric Miao .attrs = max1111_attributes, 13255b951e7SEric Miao }; 13355b951e7SEric Miao 134*d737c09cSJean Delvare static int __devinit setup_transfer(struct max1111_data *data) 13555b951e7SEric Miao { 13655b951e7SEric Miao struct spi_message *m; 13755b951e7SEric Miao struct spi_transfer *x; 13855b951e7SEric Miao 13955b951e7SEric Miao m = &data->msg; 14055b951e7SEric Miao x = &data->xfer[0]; 14155b951e7SEric Miao 14255b951e7SEric Miao spi_message_init(m); 14355b951e7SEric Miao 14455b951e7SEric Miao x->tx_buf = &data->tx_buf[0]; 145*d737c09cSJean Delvare x->len = MAX1111_TX_BUF_SIZE; 14655b951e7SEric Miao spi_message_add_tail(x, m); 14755b951e7SEric Miao 14855b951e7SEric Miao x++; 14955b951e7SEric Miao x->rx_buf = &data->rx_buf[0]; 150*d737c09cSJean Delvare x->len = MAX1111_RX_BUF_SIZE; 15155b951e7SEric Miao spi_message_add_tail(x, m); 15255b951e7SEric Miao 15355b951e7SEric Miao return 0; 15455b951e7SEric Miao } 15555b951e7SEric Miao 15655b951e7SEric Miao static int __devinit max1111_probe(struct spi_device *spi) 15755b951e7SEric Miao { 15855b951e7SEric Miao struct max1111_data *data; 15955b951e7SEric Miao int err; 16055b951e7SEric Miao 16155b951e7SEric Miao spi->bits_per_word = 8; 16255b951e7SEric Miao spi->mode = SPI_MODE_0; 16355b951e7SEric Miao err = spi_setup(spi); 16455b951e7SEric Miao if (err < 0) 16555b951e7SEric Miao return err; 16655b951e7SEric Miao 16755b951e7SEric Miao data = kzalloc(sizeof(struct max1111_data), GFP_KERNEL); 16855b951e7SEric Miao if (data == NULL) { 16955b951e7SEric Miao dev_err(&spi->dev, "failed to allocate memory\n"); 17055b951e7SEric Miao return -ENOMEM; 17155b951e7SEric Miao } 17255b951e7SEric Miao 17355b951e7SEric Miao err = setup_transfer(data); 17455b951e7SEric Miao if (err) 17555b951e7SEric Miao goto err_free_data; 17655b951e7SEric Miao 177d3f684f2SPavel Herrmann mutex_init(&data->drvdata_lock); 178d3f684f2SPavel Herrmann 17955b951e7SEric Miao data->spi = spi; 18055b951e7SEric Miao spi_set_drvdata(spi, data); 18155b951e7SEric Miao 18255b951e7SEric Miao err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group); 18355b951e7SEric Miao if (err) { 18455b951e7SEric Miao dev_err(&spi->dev, "failed to create attribute group\n"); 185*d737c09cSJean Delvare goto err_free_data; 18655b951e7SEric Miao } 18755b951e7SEric Miao 18855b951e7SEric Miao data->hwmon_dev = hwmon_device_register(&spi->dev); 18955b951e7SEric Miao if (IS_ERR(data->hwmon_dev)) { 19055b951e7SEric Miao dev_err(&spi->dev, "failed to create hwmon device\n"); 19155b951e7SEric Miao err = PTR_ERR(data->hwmon_dev); 19255b951e7SEric Miao goto err_remove; 19355b951e7SEric Miao } 19455b951e7SEric Miao 195f16177c2SEric Miao #ifdef CONFIG_SHARPSL_PM 196f16177c2SEric Miao the_max1111 = data; 197f16177c2SEric Miao #endif 19855b951e7SEric Miao return 0; 19955b951e7SEric Miao 20055b951e7SEric Miao err_remove: 20155b951e7SEric Miao sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); 20255b951e7SEric Miao err_free_data: 20355b951e7SEric Miao kfree(data); 20455b951e7SEric Miao return err; 20555b951e7SEric Miao } 20655b951e7SEric Miao 20755b951e7SEric Miao static int __devexit max1111_remove(struct spi_device *spi) 20855b951e7SEric Miao { 20955b951e7SEric Miao struct max1111_data *data = spi_get_drvdata(spi); 21055b951e7SEric Miao 21155b951e7SEric Miao hwmon_device_unregister(data->hwmon_dev); 21255b951e7SEric Miao sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); 213d3f684f2SPavel Herrmann mutex_destroy(&data->drvdata_lock); 21455b951e7SEric Miao kfree(data); 21555b951e7SEric Miao return 0; 21655b951e7SEric Miao } 21755b951e7SEric Miao 21855b951e7SEric Miao static struct spi_driver max1111_driver = { 21955b951e7SEric Miao .driver = { 22055b951e7SEric Miao .name = "max1111", 22155b951e7SEric Miao .owner = THIS_MODULE, 22255b951e7SEric Miao }, 22355b951e7SEric Miao .probe = max1111_probe, 22455b951e7SEric Miao .remove = __devexit_p(max1111_remove), 22555b951e7SEric Miao }; 22655b951e7SEric Miao 22755b951e7SEric Miao static int __init max1111_init(void) 22855b951e7SEric Miao { 22955b951e7SEric Miao return spi_register_driver(&max1111_driver); 23055b951e7SEric Miao } 23155b951e7SEric Miao module_init(max1111_init); 23255b951e7SEric Miao 23355b951e7SEric Miao static void __exit max1111_exit(void) 23455b951e7SEric Miao { 23555b951e7SEric Miao spi_unregister_driver(&max1111_driver); 23655b951e7SEric Miao } 23755b951e7SEric Miao module_exit(max1111_exit); 23855b951e7SEric Miao 23955b951e7SEric Miao MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); 24055b951e7SEric Miao MODULE_DESCRIPTION("MAX1111 ADC Driver"); 24155b951e7SEric Miao MODULE_LICENSE("GPL"); 242e0626e38SAnton Vorontsov MODULE_ALIAS("spi:max1111"); 243