linux/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * cxd2880_spi_device.c
   4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
   5 * SPI access functions
   6 *
   7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
   8 */
   9
  10#include <linux/spi/spi.h>
  11
  12#include "cxd2880_spi_device.h"
  13
  14static int cxd2880_spi_device_write(struct cxd2880_spi *spi,
  15                                    const u8 *data, u32 size)
  16{
  17        struct cxd2880_spi_device *spi_device = NULL;
  18        struct spi_message msg;
  19        struct spi_transfer tx;
  20        int result = 0;
  21
  22        if (!spi || !spi->user || !data || size == 0)
  23                return -EINVAL;
  24
  25        spi_device = spi->user;
  26
  27        memset(&tx, 0, sizeof(tx));
  28        tx.tx_buf = data;
  29        tx.len = size;
  30
  31        spi_message_init(&msg);
  32        spi_message_add_tail(&tx, &msg);
  33        result = spi_sync(spi_device->spi, &msg);
  34
  35        if (result < 0)
  36                return -EIO;
  37
  38        return 0;
  39}
  40
  41static int cxd2880_spi_device_write_read(struct cxd2880_spi *spi,
  42                                         const u8 *tx_data,
  43                                         u32 tx_size,
  44                                         u8 *rx_data,
  45                                         u32 rx_size)
  46{
  47        struct cxd2880_spi_device *spi_device = NULL;
  48        int result = 0;
  49
  50        if (!spi || !spi->user || !tx_data ||
  51            !tx_size || !rx_data || !rx_size)
  52                return -EINVAL;
  53
  54        spi_device = spi->user;
  55
  56        result = spi_write_then_read(spi_device->spi, tx_data,
  57                                     tx_size, rx_data, rx_size);
  58        if (result < 0)
  59                return -EIO;
  60
  61        return 0;
  62}
  63
  64int
  65cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device,
  66                              enum cxd2880_spi_mode mode,
  67                              u32 speed_hz)
  68{
  69        int result = 0;
  70        struct spi_device *spi = spi_device->spi;
  71
  72        switch (mode) {
  73        case CXD2880_SPI_MODE_0:
  74                spi->mode = SPI_MODE_0;
  75                break;
  76        case CXD2880_SPI_MODE_1:
  77                spi->mode = SPI_MODE_1;
  78                break;
  79        case CXD2880_SPI_MODE_2:
  80                spi->mode = SPI_MODE_2;
  81                break;
  82        case CXD2880_SPI_MODE_3:
  83                spi->mode = SPI_MODE_3;
  84                break;
  85        default:
  86                return -EINVAL;
  87        }
  88
  89        spi->max_speed_hz = speed_hz;
  90        spi->bits_per_word = 8;
  91        result = spi_setup(spi);
  92        if (result != 0) {
  93                pr_err("spi_setup failed %d\n", result);
  94                return -EINVAL;
  95        }
  96
  97        return 0;
  98}
  99
 100int cxd2880_spi_device_create_spi(struct cxd2880_spi *spi,
 101                                  struct cxd2880_spi_device *spi_device)
 102{
 103        if (!spi || !spi_device)
 104                return -EINVAL;
 105
 106        spi->read = NULL;
 107        spi->write = cxd2880_spi_device_write;
 108        spi->write_read = cxd2880_spi_device_write_read;
 109        spi->flags = 0;
 110        spi->user = spi_device;
 111
 112        return 0;
 113}
 114