diff options
Diffstat (limited to 'drivers/hwmon/adcxx.c')
| -rw-r--r-- | drivers/hwmon/adcxx.c | 153 |
1 files changed, 36 insertions, 117 deletions
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c index 242294db3db..04c08c2f79b 100644 --- a/drivers/hwmon/adcxx.c +++ b/drivers/hwmon/adcxx.c @@ -37,12 +37,14 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/device.h> #include <linux/err.h> #include <linux/sysfs.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/mutex.h> +#include <linux/mod_devicetable.h> #include <linux/spi/spi.h> #define DRVNAME "adcxx" @@ -60,19 +62,24 @@ static ssize_t adcxx_read(struct device *dev, { struct spi_device *spi = to_spi_device(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adcxx *adc = dev_get_drvdata(&spi->dev); - u8 tx_buf[2] = { attr->index << 3 }; /* other bits are don't care */ + struct adcxx *adc = spi_get_drvdata(spi); + u8 tx_buf[2]; u8 rx_buf[2]; int status; - int value; + u32 value; if (mutex_lock_interruptible(&adc->lock)) return -ERESTARTSYS; - status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), - rx_buf, sizeof(rx_buf)); + if (adc->channels == 1) { + status = spi_read(spi, rx_buf, sizeof(rx_buf)); + } else { + tx_buf[0] = attr->index << 3; /* other bits are don't care */ + status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), + rx_buf, sizeof(rx_buf)); + } if (status < 0) { - dev_warn(dev, "spi_write_then_read failed with status %d\n", + dev_warn(dev, "SPI synch. transfer failed with status %d\n", status); goto out; } @@ -98,7 +105,7 @@ static ssize_t adcxx_show_max(struct device *dev, struct device_attribute *devattr, char *buf) { struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); u32 reference; if (mutex_lock_interruptible(&adc->lock)) @@ -115,10 +122,10 @@ static ssize_t adcxx_set_max(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); unsigned long value; - if (strict_strtoul(buf, 10, &value)) + if (kstrtoul(buf, 10, &value)) return -EINVAL; if (mutex_lock_interruptible(&adc->lock)) @@ -134,10 +141,7 @@ static ssize_t adcxx_set_max(struct device *dev, static ssize_t adcxx_show_name(struct device *dev, struct device_attribute *devattr, char *buf) { - struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = dev_get_drvdata(&spi->dev); - - return sprintf(buf, "adcxx%ds\n", adc->channels); + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); } static struct sensor_device_attribute ad_input[] = { @@ -157,13 +161,14 @@ static struct sensor_device_attribute ad_input[] = { /*----------------------------------------------------------------------*/ -static int __devinit adcxx_probe(struct spi_device *spi, int channels) +static int adcxx_probe(struct spi_device *spi) { + int channels = spi_get_device_id(spi)->driver_data; struct adcxx *adc; int status; int i; - adc = kzalloc(sizeof *adc, GFP_KERNEL); + adc = devm_kzalloc(&spi->dev, sizeof(*adc), GFP_KERNEL); if (!adc) return -ENOMEM; @@ -174,7 +179,7 @@ static int __devinit adcxx_probe(struct spi_device *spi, int channels) mutex_lock(&adc->lock); - dev_set_drvdata(&spi->dev, adc); + spi_set_drvdata(spi, adc); for (i = 0; i < 3 + adc->channels; i++) { status = device_create_file(&spi->dev, &ad_input[i].dev_attr); @@ -198,35 +203,13 @@ out_err: for (i--; i >= 0; i--) device_remove_file(&spi->dev, &ad_input[i].dev_attr); - dev_set_drvdata(&spi->dev, NULL); mutex_unlock(&adc->lock); - kfree(adc); return status; } -static int __devinit adcxx1s_probe(struct spi_device *spi) -{ - return adcxx_probe(spi, 1); -} - -static int __devinit adcxx2s_probe(struct spi_device *spi) -{ - return adcxx_probe(spi, 2); -} - -static int __devinit adcxx4s_probe(struct spi_device *spi) -{ - return adcxx_probe(spi, 4); -} - -static int __devinit adcxx8s_probe(struct spi_device *spi) -{ - return adcxx_probe(spi, 8); -} - -static int __devexit adcxx_remove(struct spi_device *spi) +static int adcxx_remove(struct spi_device *spi) { - struct adcxx *adc = dev_get_drvdata(&spi->dev); + struct adcxx *adc = spi_get_drvdata(spi); int i; mutex_lock(&adc->lock); @@ -234,96 +217,32 @@ static int __devexit adcxx_remove(struct spi_device *spi) for (i = 0; i < 3 + adc->channels; i++) device_remove_file(&spi->dev, &ad_input[i].dev_attr); - dev_set_drvdata(&spi->dev, NULL); mutex_unlock(&adc->lock); - kfree(adc); return 0; } -static struct spi_driver adcxx1s_driver = { - .driver = { - .name = "adcxx1s", - .owner = THIS_MODULE, - }, - .probe = adcxx1s_probe, - .remove = __devexit_p(adcxx_remove), +static const struct spi_device_id adcxx_ids[] = { + { "adcxx1s", 1 }, + { "adcxx2s", 2 }, + { "adcxx4s", 4 }, + { "adcxx8s", 8 }, + { }, }; +MODULE_DEVICE_TABLE(spi, adcxx_ids); -static struct spi_driver adcxx2s_driver = { +static struct spi_driver adcxx_driver = { .driver = { - .name = "adcxx2s", + .name = "adcxx", .owner = THIS_MODULE, }, - .probe = adcxx2s_probe, - .remove = __devexit_p(adcxx_remove), + .id_table = adcxx_ids, + .probe = adcxx_probe, + .remove = adcxx_remove, }; -static struct spi_driver adcxx4s_driver = { - .driver = { - .name = "adcxx4s", - .owner = THIS_MODULE, - }, - .probe = adcxx4s_probe, - .remove = __devexit_p(adcxx_remove), -}; - -static struct spi_driver adcxx8s_driver = { - .driver = { - .name = "adcxx8s", - .owner = THIS_MODULE, - }, - .probe = adcxx8s_probe, - .remove = __devexit_p(adcxx_remove), -}; - -static int __init init_adcxx(void) -{ - int status; - status = spi_register_driver(&adcxx1s_driver); - if (status) - goto reg_1_failed; - - status = spi_register_driver(&adcxx2s_driver); - if (status) - goto reg_2_failed; - - status = spi_register_driver(&adcxx4s_driver); - if (status) - goto reg_4_failed; - - status = spi_register_driver(&adcxx8s_driver); - if (status) - goto reg_8_failed; - - return status; - -reg_8_failed: - spi_unregister_driver(&adcxx4s_driver); -reg_4_failed: - spi_unregister_driver(&adcxx2s_driver); -reg_2_failed: - spi_unregister_driver(&adcxx1s_driver); -reg_1_failed: - return status; -} - -static void __exit exit_adcxx(void) -{ - spi_unregister_driver(&adcxx1s_driver); - spi_unregister_driver(&adcxx2s_driver); - spi_unregister_driver(&adcxx4s_driver); - spi_unregister_driver(&adcxx8s_driver); -} - -module_init(init_adcxx); -module_exit(exit_adcxx); +module_spi_driver(adcxx_driver); MODULE_AUTHOR("Marc Pignat"); MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver"); MODULE_LICENSE("GPL"); - -MODULE_ALIAS("adcxx1s"); -MODULE_ALIAS("adcxx2s"); -MODULE_ALIAS("adcxx4s"); -MODULE_ALIAS("adcxx8s"); |
