18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * cxd2880_spi_device.c 48c2ecf20Sopenharmony_ci * Sony CXD2880 DVB-T2/T tuner + demodulator driver 58c2ecf20Sopenharmony_ci * SPI access functions 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "cxd2880_spi_device.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic int cxd2880_spi_device_write(struct cxd2880_spi *spi, 158c2ecf20Sopenharmony_ci const u8 *data, u32 size) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct cxd2880_spi_device *spi_device = NULL; 188c2ecf20Sopenharmony_ci struct spi_message msg; 198c2ecf20Sopenharmony_ci struct spi_transfer tx; 208c2ecf20Sopenharmony_ci int result = 0; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci if (!spi || !spi->user || !data || size == 0) 238c2ecf20Sopenharmony_ci return -EINVAL; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci spi_device = spi->user; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci memset(&tx, 0, sizeof(tx)); 288c2ecf20Sopenharmony_ci tx.tx_buf = data; 298c2ecf20Sopenharmony_ci tx.len = size; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci spi_message_init(&msg); 328c2ecf20Sopenharmony_ci spi_message_add_tail(&tx, &msg); 338c2ecf20Sopenharmony_ci result = spi_sync(spi_device->spi, &msg); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (result < 0) 368c2ecf20Sopenharmony_ci return -EIO; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic int cxd2880_spi_device_write_read(struct cxd2880_spi *spi, 428c2ecf20Sopenharmony_ci const u8 *tx_data, 438c2ecf20Sopenharmony_ci u32 tx_size, 448c2ecf20Sopenharmony_ci u8 *rx_data, 458c2ecf20Sopenharmony_ci u32 rx_size) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci struct cxd2880_spi_device *spi_device = NULL; 488c2ecf20Sopenharmony_ci int result = 0; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (!spi || !spi->user || !tx_data || 518c2ecf20Sopenharmony_ci !tx_size || !rx_data || !rx_size) 528c2ecf20Sopenharmony_ci return -EINVAL; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci spi_device = spi->user; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci result = spi_write_then_read(spi_device->spi, tx_data, 578c2ecf20Sopenharmony_ci tx_size, rx_data, rx_size); 588c2ecf20Sopenharmony_ci if (result < 0) 598c2ecf20Sopenharmony_ci return -EIO; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciint 658c2ecf20Sopenharmony_cicxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device, 668c2ecf20Sopenharmony_ci enum cxd2880_spi_mode mode, 678c2ecf20Sopenharmony_ci u32 speed_hz) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci int result = 0; 708c2ecf20Sopenharmony_ci struct spi_device *spi = spi_device->spi; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci switch (mode) { 738c2ecf20Sopenharmony_ci case CXD2880_SPI_MODE_0: 748c2ecf20Sopenharmony_ci spi->mode = SPI_MODE_0; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci case CXD2880_SPI_MODE_1: 778c2ecf20Sopenharmony_ci spi->mode = SPI_MODE_1; 788c2ecf20Sopenharmony_ci break; 798c2ecf20Sopenharmony_ci case CXD2880_SPI_MODE_2: 808c2ecf20Sopenharmony_ci spi->mode = SPI_MODE_2; 818c2ecf20Sopenharmony_ci break; 828c2ecf20Sopenharmony_ci case CXD2880_SPI_MODE_3: 838c2ecf20Sopenharmony_ci spi->mode = SPI_MODE_3; 848c2ecf20Sopenharmony_ci break; 858c2ecf20Sopenharmony_ci default: 868c2ecf20Sopenharmony_ci return -EINVAL; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci spi->max_speed_hz = speed_hz; 908c2ecf20Sopenharmony_ci spi->bits_per_word = 8; 918c2ecf20Sopenharmony_ci result = spi_setup(spi); 928c2ecf20Sopenharmony_ci if (result != 0) { 938c2ecf20Sopenharmony_ci pr_err("spi_setup failed %d\n", result); 948c2ecf20Sopenharmony_ci return -EINVAL; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return 0; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciint cxd2880_spi_device_create_spi(struct cxd2880_spi *spi, 1018c2ecf20Sopenharmony_ci struct cxd2880_spi_device *spi_device) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci if (!spi || !spi_device) 1048c2ecf20Sopenharmony_ci return -EINVAL; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci spi->read = NULL; 1078c2ecf20Sopenharmony_ci spi->write = cxd2880_spi_device_write; 1088c2ecf20Sopenharmony_ci spi->write_read = cxd2880_spi_device_write_read; 1098c2ecf20Sopenharmony_ci spi->flags = 0; 1108c2ecf20Sopenharmony_ci spi->user = spi_device; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci} 114