174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2e1a8e913SKaiwan N Billimoria /* 3e1a8e913SKaiwan N Billimoria * lm70.c 4e1a8e913SKaiwan N Billimoria * 5e1a8e913SKaiwan N Billimoria * The LM70 is a temperature sensor chip from National Semiconductor (NS). 6e1a8e913SKaiwan N Billimoria * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com> 7e1a8e913SKaiwan N Billimoria * 8e1a8e913SKaiwan N Billimoria * The LM70 communicates with a host processor via an SPI/Microwire Bus 9e1a8e913SKaiwan N Billimoria * interface. The complete datasheet is available at National's website 10e1a8e913SKaiwan N Billimoria * here: 11e1a8e913SKaiwan N Billimoria * http://www.national.com/pf/LM/LM70.html 12e1a8e913SKaiwan N Billimoria */ 13e1a8e913SKaiwan N Billimoria 145713017eSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 155713017eSJoe Perches 16e1a8e913SKaiwan N Billimoria #include <linux/init.h> 17e1a8e913SKaiwan N Billimoria #include <linux/module.h> 18e1a8e913SKaiwan N Billimoria #include <linux/kernel.h> 19e1a8e913SKaiwan N Billimoria #include <linux/device.h> 20e1a8e913SKaiwan N Billimoria #include <linux/err.h> 21e1a8e913SKaiwan N Billimoria #include <linux/sysfs.h> 22e1a8e913SKaiwan N Billimoria #include <linux/hwmon.h> 234bfe6604SMatthias Kaehlcke #include <linux/mutex.h> 248cec03eeSAnton Vorontsov #include <linux/mod_devicetable.h> 25ac61c8aaSGuenter Roeck #include <linux/of.h> 266e09d755SStephen Boyd #include <linux/property.h> 27e1a8e913SKaiwan N Billimoria #include <linux/spi/spi.h> 285a0e3ad6STejun Heo #include <linux/slab.h> 29e1a8e913SKaiwan N Billimoria 30e1a8e913SKaiwan N Billimoria #define DRVNAME "lm70" 31e1a8e913SKaiwan N Billimoria 32c8ac32e4SManuel Lauss #define LM70_CHIP_LM70 0 /* original NS LM70 */ 33c8ac32e4SManuel Lauss #define LM70_CHIP_TMP121 1 /* TI TMP121/TMP123 */ 34a86e94dcSChristophe Leroy #define LM70_CHIP_LM71 2 /* NS LM71 */ 35a86e94dcSChristophe Leroy #define LM70_CHIP_LM74 3 /* NS LM74 */ 3668f0c8c9SFlorian Fainelli #define LM70_CHIP_TMP122 4 /* TI TMP122/TMP124 */ 37c8ac32e4SManuel Lauss 38e1a8e913SKaiwan N Billimoria struct lm70 { 39aa9bcddaSGuenter Roeck struct spi_device *spi; 404bfe6604SMatthias Kaehlcke struct mutex lock; 41c8ac32e4SManuel Lauss unsigned int chip; 42e1a8e913SKaiwan N Billimoria }; 43e1a8e913SKaiwan N Billimoria 44e1a8e913SKaiwan N Billimoria /* sysfs hook function */ 4589cb4af8SJulia Lawall static ssize_t temp1_input_show(struct device *dev, 46e1a8e913SKaiwan N Billimoria struct device_attribute *attr, char *buf) 47e1a8e913SKaiwan N Billimoria { 48aa9bcddaSGuenter Roeck struct lm70 *p_lm70 = dev_get_drvdata(dev); 49aa9bcddaSGuenter Roeck struct spi_device *spi = p_lm70->spi; 50c8ac32e4SManuel Lauss int status, val = 0; 51e1a8e913SKaiwan N Billimoria u8 rxbuf[2]; 52e1a8e913SKaiwan N Billimoria s16 raw = 0; 53e1a8e913SKaiwan N Billimoria 544bfe6604SMatthias Kaehlcke if (mutex_lock_interruptible(&p_lm70->lock)) 55e1a8e913SKaiwan N Billimoria return -ERESTARTSYS; 56e1a8e913SKaiwan N Billimoria 57e1a8e913SKaiwan N Billimoria /* 58e1a8e913SKaiwan N Billimoria * spi_read() requires a DMA-safe buffer; so we use 59e1a8e913SKaiwan N Billimoria * spi_write_then_read(), transmitting 0 bytes. 60e1a8e913SKaiwan N Billimoria */ 61e1a8e913SKaiwan N Billimoria status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2); 62e1a8e913SKaiwan N Billimoria if (status < 0) { 63e8295146SFlorian Fainelli dev_warn(dev, "spi_write_then_read failed with status %d\n", 64e8295146SFlorian Fainelli status); 65e1a8e913SKaiwan N Billimoria goto out; 66e1a8e913SKaiwan N Billimoria } 672b730051SKaiwan N Billimoria raw = (rxbuf[0] << 8) + rxbuf[1]; 682b730051SKaiwan N Billimoria dev_dbg(dev, "rxbuf[0] : 0x%02x rxbuf[1] : 0x%02x raw=0x%04x\n", 692b730051SKaiwan N Billimoria rxbuf[0], rxbuf[1], raw); 70e1a8e913SKaiwan N Billimoria 71e1a8e913SKaiwan N Billimoria /* 72c8ac32e4SManuel Lauss * LM70: 73e1a8e913SKaiwan N Billimoria * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's 74e1a8e913SKaiwan N Billimoria * complement value. Only the MSB 11 bits (1 sign + 10 temperature 75e1a8e913SKaiwan N Billimoria * bits) are meaningful; the LSB 5 bits are to be discarded. 76e1a8e913SKaiwan N Billimoria * See the datasheet. 77e1a8e913SKaiwan N Billimoria * 78e1a8e913SKaiwan N Billimoria * Further, each bit represents 0.25 degrees Celsius; so, multiply 79e1a8e913SKaiwan N Billimoria * by 0.25. Also multiply by 1000 to represent in millidegrees 80e1a8e913SKaiwan N Billimoria * Celsius. 81e1a8e913SKaiwan N Billimoria * So it's equivalent to multiplying by 0.25 * 1000 = 250. 82c8ac32e4SManuel Lauss * 8368f0c8c9SFlorian Fainelli * LM74 and TMP121/TMP122/TMP123/TMP124: 84c8ac32e4SManuel Lauss * 13 bits of 2's complement data, discard LSB 3 bits, 85c8ac32e4SManuel Lauss * resolution 0.0625 degrees celsius. 86a86e94dcSChristophe Leroy * 87a86e94dcSChristophe Leroy * LM71: 88a86e94dcSChristophe Leroy * 14 bits of 2's complement data, discard LSB 2 bits, 89a86e94dcSChristophe Leroy * resolution 0.0312 degrees celsius. 90e1a8e913SKaiwan N Billimoria */ 91c8ac32e4SManuel Lauss switch (p_lm70->chip) { 92c8ac32e4SManuel Lauss case LM70_CHIP_LM70: 93e1a8e913SKaiwan N Billimoria val = ((int)raw / 32) * 250; 94c8ac32e4SManuel Lauss break; 95c8ac32e4SManuel Lauss 96c8ac32e4SManuel Lauss case LM70_CHIP_TMP121: 9768f0c8c9SFlorian Fainelli case LM70_CHIP_TMP122: 98a86e94dcSChristophe Leroy case LM70_CHIP_LM74: 99c8ac32e4SManuel Lauss val = ((int)raw / 8) * 625 / 10; 100c8ac32e4SManuel Lauss break; 101a86e94dcSChristophe Leroy 102a86e94dcSChristophe Leroy case LM70_CHIP_LM71: 103a86e94dcSChristophe Leroy val = ((int)raw / 4) * 3125 / 100; 104a86e94dcSChristophe Leroy break; 105c8ac32e4SManuel Lauss } 106c8ac32e4SManuel Lauss 10767f921d1SJean Delvare status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ 108e1a8e913SKaiwan N Billimoria out: 1094bfe6604SMatthias Kaehlcke mutex_unlock(&p_lm70->lock); 110e1a8e913SKaiwan N Billimoria return status; 111e1a8e913SKaiwan N Billimoria } 112e1a8e913SKaiwan N Billimoria 11389cb4af8SJulia Lawall static DEVICE_ATTR_RO(temp1_input); 114e1a8e913SKaiwan N Billimoria 115aa9bcddaSGuenter Roeck static struct attribute *lm70_attrs[] = { 116aa9bcddaSGuenter Roeck &dev_attr_temp1_input.attr, 117aa9bcddaSGuenter Roeck NULL 118aa9bcddaSGuenter Roeck }; 11967f921d1SJean Delvare 120aa9bcddaSGuenter Roeck ATTRIBUTE_GROUPS(lm70); 12167f921d1SJean Delvare 122e1a8e913SKaiwan N Billimoria /*----------------------------------------------------------------------*/ 123e1a8e913SKaiwan N Billimoria 124a1dc86ebSRabin Vincent #ifdef CONFIG_OF 125a1dc86ebSRabin Vincent static const struct of_device_id lm70_of_ids[] = { 126a1dc86ebSRabin Vincent { 127a1dc86ebSRabin Vincent .compatible = "ti,lm70", 128a1dc86ebSRabin Vincent .data = (void *) LM70_CHIP_LM70, 129a1dc86ebSRabin Vincent }, 130a1dc86ebSRabin Vincent { 131a1dc86ebSRabin Vincent .compatible = "ti,tmp121", 132a1dc86ebSRabin Vincent .data = (void *) LM70_CHIP_TMP121, 133a1dc86ebSRabin Vincent }, 134a1dc86ebSRabin Vincent { 13568f0c8c9SFlorian Fainelli .compatible = "ti,tmp122", 13668f0c8c9SFlorian Fainelli .data = (void *) LM70_CHIP_TMP122, 13768f0c8c9SFlorian Fainelli }, 13868f0c8c9SFlorian Fainelli { 139a1dc86ebSRabin Vincent .compatible = "ti,lm71", 140a1dc86ebSRabin Vincent .data = (void *) LM70_CHIP_LM71, 141a1dc86ebSRabin Vincent }, 142a1dc86ebSRabin Vincent { 143a1dc86ebSRabin Vincent .compatible = "ti,lm74", 144a1dc86ebSRabin Vincent .data = (void *) LM70_CHIP_LM74, 145a1dc86ebSRabin Vincent }, 146a1dc86ebSRabin Vincent {}, 147a1dc86ebSRabin Vincent }; 148a1dc86ebSRabin Vincent MODULE_DEVICE_TABLE(of, lm70_of_ids); 149a1dc86ebSRabin Vincent #endif 150a1dc86ebSRabin Vincent 1516c931ae1SBill Pemberton static int lm70_probe(struct spi_device *spi) 152e1a8e913SKaiwan N Billimoria { 153aa9bcddaSGuenter Roeck struct device *hwmon_dev; 154e1a8e913SKaiwan N Billimoria struct lm70 *p_lm70; 155a1dc86ebSRabin Vincent int chip; 156a1dc86ebSRabin Vincent 1576e09d755SStephen Boyd if (dev_fwnode(&spi->dev)) 1586e09d755SStephen Boyd chip = (int)(uintptr_t)device_get_match_data(&spi->dev); 159a1dc86ebSRabin Vincent else 160a1dc86ebSRabin Vincent chip = spi_get_device_id(spi)->driver_data; 1616e09d755SStephen Boyd 162e1a8e913SKaiwan N Billimoria 163a86e94dcSChristophe Leroy /* signaling is SPI_MODE_0 */ 164*ba9c5fc3SAndy Shevchenko if ((spi->mode & SPI_MODE_X_MASK) != SPI_MODE_0) 1658cec03eeSAnton Vorontsov return -EINVAL; 1668cec03eeSAnton Vorontsov 1672b730051SKaiwan N Billimoria /* NOTE: we assume 8-bit words, and convert to 16 bits manually */ 1682b730051SKaiwan N Billimoria 16933ed6d4aSGuenter Roeck p_lm70 = devm_kzalloc(&spi->dev, sizeof(*p_lm70), GFP_KERNEL); 170e1a8e913SKaiwan N Billimoria if (!p_lm70) 171e1a8e913SKaiwan N Billimoria return -ENOMEM; 172e1a8e913SKaiwan N Billimoria 1734bfe6604SMatthias Kaehlcke mutex_init(&p_lm70->lock); 174c8ac32e4SManuel Lauss p_lm70->chip = chip; 175aa9bcddaSGuenter Roeck p_lm70->spi = spi; 176e1a8e913SKaiwan N Billimoria 177aa9bcddaSGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(&spi->dev, 178aa9bcddaSGuenter Roeck spi->modalias, 179aa9bcddaSGuenter Roeck p_lm70, lm70_groups); 180aa9bcddaSGuenter Roeck return PTR_ERR_OR_ZERO(hwmon_dev); 181e200c14fSGuenter Roeck } 182e200c14fSGuenter Roeck 1838cec03eeSAnton Vorontsov static const struct spi_device_id lm70_ids[] = { 1848cec03eeSAnton Vorontsov { "lm70", LM70_CHIP_LM70 }, 1858cec03eeSAnton Vorontsov { "tmp121", LM70_CHIP_TMP121 }, 18668f0c8c9SFlorian Fainelli { "tmp122", LM70_CHIP_TMP122 }, 187a86e94dcSChristophe Leroy { "lm71", LM70_CHIP_LM71 }, 188a86e94dcSChristophe Leroy { "lm74", LM70_CHIP_LM74 }, 1898cec03eeSAnton Vorontsov { }, 190c8ac32e4SManuel Lauss }; 1918cec03eeSAnton Vorontsov MODULE_DEVICE_TABLE(spi, lm70_ids); 192c8ac32e4SManuel Lauss 193e1a8e913SKaiwan N Billimoria static struct spi_driver lm70_driver = { 194e1a8e913SKaiwan N Billimoria .driver = { 195e1a8e913SKaiwan N Billimoria .name = "lm70", 196a1dc86ebSRabin Vincent .of_match_table = of_match_ptr(lm70_of_ids), 197e1a8e913SKaiwan N Billimoria }, 1988cec03eeSAnton Vorontsov .id_table = lm70_ids, 199e1a8e913SKaiwan N Billimoria .probe = lm70_probe, 200e1a8e913SKaiwan N Billimoria }; 201e1a8e913SKaiwan N Billimoria 20291efffe2SAxel Lin module_spi_driver(lm70_driver); 203e1a8e913SKaiwan N Billimoria 204e1a8e913SKaiwan N Billimoria MODULE_AUTHOR("Kaiwan N Billimoria"); 205a86e94dcSChristophe Leroy MODULE_DESCRIPTION("NS LM70 and compatibles Linux driver"); 206e1a8e913SKaiwan N Billimoria MODULE_LICENSE("GPL"); 207