130 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * cxd2880_devio_spi.c4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver5 * I/O interface via SPI6 *7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation8 */9 10#include "cxd2880_devio_spi.h"11 12#define BURST_WRITE_MAX 12813 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 else35 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 else46 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 else86 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 else93 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