linux/drivers/staging/iio/addac/adt7316-spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * API bus driver for ADT7316/7/8 ADT7516/7/9 digital temperature
   4 * sensor, ADC and DAC
   5 *
   6 * Copyright 2010 Analog Devices Inc.
   7 */
   8
   9#include <linux/device.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/interrupt.h>
  13#include <linux/spi/spi.h>
  14
  15#include "adt7316.h"
  16
  17#define ADT7316_SPI_MAX_FREQ_HZ         5000000
  18#define ADT7316_SPI_CMD_READ            0x91
  19#define ADT7316_SPI_CMD_WRITE           0x90
  20
  21/*
  22 * adt7316 register access by SPI
  23 */
  24
  25static int adt7316_spi_multi_read(void *client, u8 reg, u8 count, u8 *data)
  26{
  27        struct spi_device *spi_dev = client;
  28        u8 cmd[2];
  29        int ret;
  30
  31        if (count > ADT7316_REG_MAX_ADDR)
  32                count = ADT7316_REG_MAX_ADDR;
  33
  34        cmd[0] = ADT7316_SPI_CMD_WRITE;
  35        cmd[1] = reg;
  36
  37        ret = spi_write(spi_dev, cmd, 2);
  38        if (ret < 0) {
  39                dev_err(&spi_dev->dev, "SPI fail to select reg\n");
  40                return ret;
  41        }
  42
  43        cmd[0] = ADT7316_SPI_CMD_READ;
  44
  45        ret = spi_write_then_read(spi_dev, cmd, 1, data, count);
  46        if (ret < 0) {
  47                dev_err(&spi_dev->dev, "SPI read data error\n");
  48                return ret;
  49        }
  50
  51        return 0;
  52}
  53
  54static int adt7316_spi_multi_write(void *client, u8 reg, u8 count, u8 *data)
  55{
  56        struct spi_device *spi_dev = client;
  57        u8 buf[ADT7316_REG_MAX_ADDR + 2];
  58        int i, ret;
  59
  60        if (count > ADT7316_REG_MAX_ADDR)
  61                count = ADT7316_REG_MAX_ADDR;
  62
  63        buf[0] = ADT7316_SPI_CMD_WRITE;
  64        buf[1] = reg;
  65        for (i = 0; i < count; i++)
  66                buf[i + 2] = data[i];
  67
  68        ret = spi_write(spi_dev, buf, count + 2);
  69        if (ret < 0) {
  70                dev_err(&spi_dev->dev, "SPI write error\n");
  71                return ret;
  72        }
  73
  74        return ret;
  75}
  76
  77static int adt7316_spi_read(void *client, u8 reg, u8 *data)
  78{
  79        return adt7316_spi_multi_read(client, reg, 1, data);
  80}
  81
  82static int adt7316_spi_write(void *client, u8 reg, u8 val)
  83{
  84        return adt7316_spi_multi_write(client, reg, 1, &val);
  85}
  86
  87/*
  88 * device probe and remove
  89 */
  90
  91static int adt7316_spi_probe(struct spi_device *spi_dev)
  92{
  93        struct adt7316_bus bus = {
  94                .client = spi_dev,
  95                .irq = spi_dev->irq,
  96                .read = adt7316_spi_read,
  97                .write = adt7316_spi_write,
  98                .multi_read = adt7316_spi_multi_read,
  99                .multi_write = adt7316_spi_multi_write,
 100        };
 101
 102        /* don't exceed max specified SPI CLK frequency */
 103        if (spi_dev->max_speed_hz > ADT7316_SPI_MAX_FREQ_HZ) {
 104                dev_err(&spi_dev->dev, "SPI CLK %d Hz?\n",
 105                        spi_dev->max_speed_hz);
 106                return -EINVAL;
 107        }
 108
 109        /* switch from default I2C protocol to SPI protocol */
 110        adt7316_spi_write(spi_dev, 0, 0);
 111        adt7316_spi_write(spi_dev, 0, 0);
 112        adt7316_spi_write(spi_dev, 0, 0);
 113
 114        return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias);
 115}
 116
 117static const struct spi_device_id adt7316_spi_id[] = {
 118        { "adt7316", 0 },
 119        { "adt7317", 0 },
 120        { "adt7318", 0 },
 121        { "adt7516", 0 },
 122        { "adt7517", 0 },
 123        { "adt7519", 0 },
 124        { }
 125};
 126
 127MODULE_DEVICE_TABLE(spi, adt7316_spi_id);
 128
 129static const struct of_device_id adt7316_of_spi_match[] = {
 130        { .compatible = "adi,adt7316" },
 131        { .compatible = "adi,adt7317" },
 132        { .compatible = "adi,adt7318" },
 133        { .compatible = "adi,adt7516" },
 134        { .compatible = "adi,adt7517" },
 135        { .compatible = "adi,adt7519" },
 136        { }
 137};
 138
 139MODULE_DEVICE_TABLE(of, adt7316_of_spi_match);
 140
 141static struct spi_driver adt7316_driver = {
 142        .driver = {
 143                .name = "adt7316",
 144                .of_match_table = adt7316_of_spi_match,
 145                .pm = ADT7316_PM_OPS,
 146        },
 147        .probe = adt7316_spi_probe,
 148        .id_table = adt7316_spi_id,
 149};
 150module_spi_driver(adt7316_driver);
 151
 152MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
 153MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and ADT7516/7/9 digital temperature sensor, ADC and DAC");
 154MODULE_LICENSE("GPL v2");
 155