Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * lm70.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * The LM70 is a temperature sensor chip from National Semiconductor (NS).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * The LM70 communicates with a host processor via an SPI/Microwire Bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * interface. The complete datasheet is available at National's website
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * here:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * http://www.national.com/pf/LM/LM70.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define DRVNAME		"lm70"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define LM70_CHIP_LM70		0	/* original NS LM70 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define LM70_CHIP_TMP121	1	/* TI TMP121/TMP123 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define LM70_CHIP_LM71		2	/* NS LM71 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define LM70_CHIP_LM74		3	/* NS LM74 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define LM70_CHIP_TMP122	4	/* TI TMP122/TMP124 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) struct lm70 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	struct spi_device *spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	unsigned int chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* sysfs hook function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static ssize_t temp1_input_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 				struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	struct lm70 *p_lm70 = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct spi_device *spi = p_lm70->spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	int status, val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	u8 rxbuf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	s16 raw = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (mutex_lock_interruptible(&p_lm70->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	 * spi_read() requires a DMA-safe buffer; so we use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	 * spi_write_then_read(), transmitting 0 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		dev_warn(dev, "spi_write_then_read failed with status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 			 status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	raw = (rxbuf[0] << 8) + rxbuf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	dev_dbg(dev, "rxbuf[0] : 0x%02x rxbuf[1] : 0x%02x raw=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		rxbuf[0], rxbuf[1], raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 * LM70:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	 * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	 * complement value. Only the MSB 11 bits (1 sign + 10 temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	 * bits) are meaningful; the LSB 5 bits are to be discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	 * See the datasheet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	 * Further, each bit represents 0.25 degrees Celsius; so, multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	 * by 0.25. Also multiply by 1000 to represent in millidegrees
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	 * Celsius.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 * So it's equivalent to multiplying by 0.25 * 1000 = 250.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	 * LM74 and TMP121/TMP122/TMP123/TMP124:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	 * 13 bits of 2's complement data, discard LSB 3 bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	 * resolution 0.0625 degrees celsius.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 * LM71:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 * 14 bits of 2's complement data, discard LSB 2 bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 * resolution 0.0312 degrees celsius.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	switch (p_lm70->chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	case LM70_CHIP_LM70:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		val = ((int)raw / 32) * 250;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	case LM70_CHIP_TMP121:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	case LM70_CHIP_TMP122:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	case LM70_CHIP_LM74:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		val = ((int)raw / 8) * 625 / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	case LM70_CHIP_LM71:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		val = ((int)raw / 4) * 3125 / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	mutex_unlock(&p_lm70->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static DEVICE_ATTR_RO(temp1_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static struct attribute *lm70_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	&dev_attr_temp1_input.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ATTRIBUTE_GROUPS(lm70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*----------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static const struct of_device_id lm70_of_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		.compatible = "ti,lm70",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		.data = (void *) LM70_CHIP_LM70,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		.compatible = "ti,tmp121",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		.data = (void *) LM70_CHIP_TMP121,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		.compatible = "ti,tmp122",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		.data = (void *) LM70_CHIP_TMP122,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		.compatible = "ti,lm71",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		.data = (void *) LM70_CHIP_LM71,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		.compatible = "ti,lm74",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		.data = (void *) LM70_CHIP_LM74,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) MODULE_DEVICE_TABLE(of, lm70_of_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int lm70_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	struct lm70 *p_lm70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	int chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (dev_fwnode(&spi->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		chip = (int)(uintptr_t)device_get_match_data(&spi->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		chip = spi_get_device_id(spi)->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	/* signaling is SPI_MODE_0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (spi->mode & (SPI_CPOL | SPI_CPHA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	/* NOTE:  we assume 8-bit words, and convert to 16 bits manually */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	p_lm70 = devm_kzalloc(&spi->dev, sizeof(*p_lm70), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	if (!p_lm70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	mutex_init(&p_lm70->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	p_lm70->chip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	p_lm70->spi = spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	hwmon_dev = devm_hwmon_device_register_with_groups(&spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 							   spi->modalias,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 							   p_lm70, lm70_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	return PTR_ERR_OR_ZERO(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static const struct spi_device_id lm70_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	{ "lm70",   LM70_CHIP_LM70 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	{ "tmp121", LM70_CHIP_TMP121 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	{ "tmp122", LM70_CHIP_TMP122 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	{ "lm71",   LM70_CHIP_LM71 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	{ "lm74",   LM70_CHIP_LM74 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) MODULE_DEVICE_TABLE(spi, lm70_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static struct spi_driver lm70_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		.name	= "lm70",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		.of_match_table	= of_match_ptr(lm70_of_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	.id_table = lm70_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	.probe	= lm70_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) module_spi_driver(lm70_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) MODULE_AUTHOR("Kaiwan N Billimoria");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) MODULE_DESCRIPTION("NS LM70 and compatibles Linux driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) MODULE_LICENSE("GPL");