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