linux/drivers/media/dvb-frontends/cxd2880/cxd2880_devio_spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * cxd2880_devio_spi.c
   4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
   5 * I/O interface via SPI
   6 *
   7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
   8 */
   9
  10#include "cxd2880_devio_spi.h"
  11
  12#define BURST_WRITE_MAX 128
  13
  14static int cxd2880_io_spi_read_reg(struct cxd2880_io *io,
  15                                   enum cxd2880_io_tgt tgt,
  16                                   u8 sub_address, u8 *data,
  17                                   u32 size)
  18{
  19        int ret = 0;
  20        struct cxd2880_spi *spi = NULL;
  21        u8 send_data[6];
  22        u8 *read_data_top = data;
  23
  24        if (!io || !io->if_object || !data)
  25                return -EINVAL;
  26
  27        if (sub_address + size > 0x100)
  28                return -EINVAL;
  29
  30        spi = io->if_object;
  31
  32        if (tgt == CXD2880_IO_TGT_SYS)
  33                send_data[0] = 0x0b;
  34        else
  35                send_data[0] = 0x0a;
  36
  37        send_data[3] = 0;
  38        send_data[4] = 0;
  39        send_data[5] = 0;
  40
  41        while (size > 0) {
  42                send_data[1] = sub_address;
  43                if (size > 255)
  44                        send_data[2] = 255;
  45                else
  46                        send_data[2] = size;
  47
  48                ret =
  49                    spi->write_read(spi, send_data, sizeof(send_data),
  50                                    read_data_top, send_data[2]);
  51                if (ret)
  52                        return ret;
  53
  54                sub_address += send_data[2];
  55                read_data_top += send_data[2];
  56                size -= send_data[2];
  57        }
  58
  59        return ret;
  60}
  61
  62static int cxd2880_io_spi_write_reg(struct cxd2880_io *io,
  63                                    enum cxd2880_io_tgt tgt,
  64                                    u8 sub_address,
  65                                    const u8 *data, u32 size)
  66{
  67        int ret = 0;
  68        struct cxd2880_spi *spi = NULL;
  69        u8 send_data[BURST_WRITE_MAX + 4];
  70        const u8 *write_data_top = data;
  71
  72        if (!io || !io->if_object || !data)
  73                return -EINVAL;
  74
  75        if (size > BURST_WRITE_MAX)
  76                return -EINVAL;
  77
  78        if (sub_address + size > 0x100)
  79                return -EINVAL;
  80
  81        spi = io->if_object;
  82
  83        if (tgt == CXD2880_IO_TGT_SYS)
  84                send_data[0] = 0x0f;
  85        else
  86                send_data[0] = 0x0e;
  87
  88        while (size > 0) {
  89                send_data[1] = sub_address;
  90                if (size > 255)
  91                        send_data[2] = 255;
  92                else
  93                        send_data[2] = size;
  94
  95                memcpy(&send_data[3], write_data_top, send_data[2]);
  96
  97                if (tgt == CXD2880_IO_TGT_SYS) {
  98                        send_data[3 + send_data[2]] = 0x00;
  99                        ret = spi->write(spi, send_data, send_data[2] + 4);
 100                } else {
 101                        ret = spi->write(spi, send_data, send_data[2] + 3);
 102                }
 103                if (ret)
 104                        return ret;
 105
 106                sub_address += send_data[2];
 107                write_data_top += send_data[2];
 108                size -= send_data[2];
 109        }
 110
 111        return ret;
 112}
 113
 114int cxd2880_io_spi_create(struct cxd2880_io *io,
 115                          struct cxd2880_spi *spi, u8 slave_select)
 116{
 117        if (!io || !spi)
 118                return -EINVAL;
 119
 120        io->read_regs = cxd2880_io_spi_read_reg;
 121        io->write_regs = cxd2880_io_spi_write_reg;
 122        io->write_reg = cxd2880_io_common_write_one_reg;
 123        io->if_object = spi;
 124        io->i2c_address_sys = 0;
 125        io->i2c_address_demod = 0;
 126        io->slave_select = slave_select;
 127
 128        return 0;
 129}
 130