// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for LM70EVAL-LLP board for the LM70 sensor * * Copyright (C) 2006 Kaiwan N Billimoria <[email protected]> */ #define pr_fmt(fmt) … #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/parport.h> #include <linux/sysfs.h> #include <linux/workqueue.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> /* * The LM70 communicates with a host processor using a 3-wire variant of * the SPI/Microwire bus interface. This driver specifically supports an * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel * port to bitbang an SPI-parport bridge. Accordingly, this is an SPI * host controller driver. The hwmon/lm70 driver is a "SPI protocol * driver", layered on top of this one and usable without the lm70llp. * * Datasheet and Schematic: * The LM70 is a temperature sensor chip from National Semiconductor; its * datasheet is available at https://www.ti.com/lit/gpn/lm70 * The schematic for this particular board (the LM70EVAL-LLP) is * available (on page 4) here: * https://download.datasheets.com/pdfs/documentation/nat/kit&board/lm70llpevalmanual.pdf * * Also see Documentation/spi/spi-lm70llp.rst. The SPI<->parport code here is * (heavily) based on spi-butterfly by David Brownell. * * The LM70 LLP connects to the PC parallel port in the following manner: * * Parallel LM70 LLP * Port Direction JP2 Header * ----------- --------- ------------ * D0 2 - - * D1 3 --> V+ 5 * D2 4 --> V+ 5 * D3 5 --> V+ 5 * D4 6 --> V+ 5 * D5 7 --> nCS 8 * D6 8 --> SCLK 3 * D7 9 --> SI/O 5 * GND 25 - GND 7 * Select 13 <-- SI/O 1 * * Note that parport pin 13 actually gets inverted by the transistor * arrangement which lets either the parport or the LM70 drive the * SI/SO signal (see the schematic for details). */ #define DRVNAME … #define lm70_INIT … #define SIO … #define nCS … #define SCLK … /*-------------------------------------------------------------------------*/ struct spi_lm70llp { … }; /* REVISIT : ugly global ; provides "exclusive open" facility */ static struct spi_lm70llp *lm70llp; /*-------------------------------------------------------------------*/ static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi) { … } /*---------------------- LM70 LLP eval board-specific inlines follow */ /* NOTE: we don't actually need to reread the output values, since they'll * still be what we wrote before. Plus, going through parport builds in * a ~1ms/operation delay; these SPI transfers could easily be faster. */ static inline void deassertCS(struct spi_lm70llp *pp) { … } static inline void assertCS(struct spi_lm70llp *pp) { … } static inline void clkHigh(struct spi_lm70llp *pp) { … } static inline void clkLow(struct spi_lm70llp *pp) { … } /*------------------------- SPI-LM70-specific inlines ----------------------*/ static inline void spidelay(unsigned d) { … } static inline void setsck(struct spi_device *s, int is_on) { … } static inline void setmosi(struct spi_device *s, int is_on) { … } /* * getmiso: * Why do we return 0 when the SIO line is high and vice-versa? * The fact is, the lm70 eval board from NS (which this driver drives), * is wired in just such a way : when the lm70's SIO goes high, a transistor * switches it to low reflecting this on the parport (pin 13), and vice-versa. */ static inline int getmiso(struct spi_device *s) { … } /*--------------------------------------------------------------------*/ #include "spi-bitbang-txrx.h" static void lm70_chipselect(struct spi_device *spi, int value) { … } /* * Our actual bitbanger routine. */ static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { … } static void spi_lm70llp_attach(struct parport *p) { … } static void spi_lm70llp_detach(struct parport *p) { … } static struct parport_driver spi_lm70llp_drv = …; module_parport_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;