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 14 static 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 41 static 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 64 int 65 cxd2880_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 100 int 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