xref: /linux/drivers/media/dvb-frontends/cxd2880/cxd2880_spi_device.c (revision c13aca79ff3c4af5fd31a5b2743a90eba6e36a26)
1*4e67e6cbSYasunari Takiguchi // SPDX-License-Identifier: GPL-2.0
2*4e67e6cbSYasunari Takiguchi /*
3*4e67e6cbSYasunari Takiguchi  * cxd2880_spi_device.c
4*4e67e6cbSYasunari Takiguchi  * Sony CXD2880 DVB-T2/T tuner + demodulator driver
5*4e67e6cbSYasunari Takiguchi  * SPI access functions
6*4e67e6cbSYasunari Takiguchi  *
7*4e67e6cbSYasunari Takiguchi  * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
8*4e67e6cbSYasunari Takiguchi  */
9*4e67e6cbSYasunari Takiguchi 
10*4e67e6cbSYasunari Takiguchi #include <linux/spi/spi.h>
11*4e67e6cbSYasunari Takiguchi 
12*4e67e6cbSYasunari Takiguchi #include "cxd2880_spi_device.h"
13*4e67e6cbSYasunari Takiguchi 
cxd2880_spi_device_write(struct cxd2880_spi * spi,const u8 * data,u32 size)14*4e67e6cbSYasunari Takiguchi static int cxd2880_spi_device_write(struct cxd2880_spi *spi,
15*4e67e6cbSYasunari Takiguchi 				    const u8 *data, u32 size)
16*4e67e6cbSYasunari Takiguchi {
17*4e67e6cbSYasunari Takiguchi 	struct cxd2880_spi_device *spi_device = NULL;
18*4e67e6cbSYasunari Takiguchi 	struct spi_message msg;
19*4e67e6cbSYasunari Takiguchi 	struct spi_transfer tx;
20*4e67e6cbSYasunari Takiguchi 	int result = 0;
21*4e67e6cbSYasunari Takiguchi 
22*4e67e6cbSYasunari Takiguchi 	if (!spi || !spi->user || !data || size == 0)
23*4e67e6cbSYasunari Takiguchi 		return -EINVAL;
24*4e67e6cbSYasunari Takiguchi 
25*4e67e6cbSYasunari Takiguchi 	spi_device = spi->user;
26*4e67e6cbSYasunari Takiguchi 
27*4e67e6cbSYasunari Takiguchi 	memset(&tx, 0, sizeof(tx));
28*4e67e6cbSYasunari Takiguchi 	tx.tx_buf = data;
29*4e67e6cbSYasunari Takiguchi 	tx.len = size;
30*4e67e6cbSYasunari Takiguchi 
31*4e67e6cbSYasunari Takiguchi 	spi_message_init(&msg);
32*4e67e6cbSYasunari Takiguchi 	spi_message_add_tail(&tx, &msg);
33*4e67e6cbSYasunari Takiguchi 	result = spi_sync(spi_device->spi, &msg);
34*4e67e6cbSYasunari Takiguchi 
35*4e67e6cbSYasunari Takiguchi 	if (result < 0)
36*4e67e6cbSYasunari Takiguchi 		return -EIO;
37*4e67e6cbSYasunari Takiguchi 
38*4e67e6cbSYasunari Takiguchi 	return 0;
39*4e67e6cbSYasunari Takiguchi }
40*4e67e6cbSYasunari Takiguchi 
cxd2880_spi_device_write_read(struct cxd2880_spi * spi,const u8 * tx_data,u32 tx_size,u8 * rx_data,u32 rx_size)41*4e67e6cbSYasunari Takiguchi static int cxd2880_spi_device_write_read(struct cxd2880_spi *spi,
42*4e67e6cbSYasunari Takiguchi 					 const u8 *tx_data,
43*4e67e6cbSYasunari Takiguchi 					 u32 tx_size,
44*4e67e6cbSYasunari Takiguchi 					 u8 *rx_data,
45*4e67e6cbSYasunari Takiguchi 					 u32 rx_size)
46*4e67e6cbSYasunari Takiguchi {
47*4e67e6cbSYasunari Takiguchi 	struct cxd2880_spi_device *spi_device = NULL;
48*4e67e6cbSYasunari Takiguchi 	int result = 0;
49*4e67e6cbSYasunari Takiguchi 
50*4e67e6cbSYasunari Takiguchi 	if (!spi || !spi->user || !tx_data ||
51*4e67e6cbSYasunari Takiguchi 	    !tx_size || !rx_data || !rx_size)
52*4e67e6cbSYasunari Takiguchi 		return -EINVAL;
53*4e67e6cbSYasunari Takiguchi 
54*4e67e6cbSYasunari Takiguchi 	spi_device = spi->user;
55*4e67e6cbSYasunari Takiguchi 
56*4e67e6cbSYasunari Takiguchi 	result = spi_write_then_read(spi_device->spi, tx_data,
57*4e67e6cbSYasunari Takiguchi 				     tx_size, rx_data, rx_size);
58*4e67e6cbSYasunari Takiguchi 	if (result < 0)
59*4e67e6cbSYasunari Takiguchi 		return -EIO;
60*4e67e6cbSYasunari Takiguchi 
61*4e67e6cbSYasunari Takiguchi 	return 0;
62*4e67e6cbSYasunari Takiguchi }
63*4e67e6cbSYasunari Takiguchi 
64*4e67e6cbSYasunari Takiguchi int
cxd2880_spi_device_initialize(struct cxd2880_spi_device * spi_device,enum cxd2880_spi_mode mode,u32 speed_hz)65*4e67e6cbSYasunari Takiguchi cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device,
66*4e67e6cbSYasunari Takiguchi 			      enum cxd2880_spi_mode mode,
67*4e67e6cbSYasunari Takiguchi 			      u32 speed_hz)
68*4e67e6cbSYasunari Takiguchi {
69*4e67e6cbSYasunari Takiguchi 	int result = 0;
70*4e67e6cbSYasunari Takiguchi 	struct spi_device *spi = spi_device->spi;
71*4e67e6cbSYasunari Takiguchi 
72*4e67e6cbSYasunari Takiguchi 	switch (mode) {
73*4e67e6cbSYasunari Takiguchi 	case CXD2880_SPI_MODE_0:
74*4e67e6cbSYasunari Takiguchi 		spi->mode = SPI_MODE_0;
75*4e67e6cbSYasunari Takiguchi 		break;
76*4e67e6cbSYasunari Takiguchi 	case CXD2880_SPI_MODE_1:
77*4e67e6cbSYasunari Takiguchi 		spi->mode = SPI_MODE_1;
78*4e67e6cbSYasunari Takiguchi 		break;
79*4e67e6cbSYasunari Takiguchi 	case CXD2880_SPI_MODE_2:
80*4e67e6cbSYasunari Takiguchi 		spi->mode = SPI_MODE_2;
81*4e67e6cbSYasunari Takiguchi 		break;
82*4e67e6cbSYasunari Takiguchi 	case CXD2880_SPI_MODE_3:
83*4e67e6cbSYasunari Takiguchi 		spi->mode = SPI_MODE_3;
84*4e67e6cbSYasunari Takiguchi 		break;
85*4e67e6cbSYasunari Takiguchi 	default:
86*4e67e6cbSYasunari Takiguchi 		return -EINVAL;
87*4e67e6cbSYasunari Takiguchi 	}
88*4e67e6cbSYasunari Takiguchi 
89*4e67e6cbSYasunari Takiguchi 	spi->max_speed_hz = speed_hz;
90*4e67e6cbSYasunari Takiguchi 	spi->bits_per_word = 8;
91*4e67e6cbSYasunari Takiguchi 	result = spi_setup(spi);
92*4e67e6cbSYasunari Takiguchi 	if (result != 0) {
93*4e67e6cbSYasunari Takiguchi 		pr_err("spi_setup failed %d\n", result);
94*4e67e6cbSYasunari Takiguchi 		return -EINVAL;
95*4e67e6cbSYasunari Takiguchi 	}
96*4e67e6cbSYasunari Takiguchi 
97*4e67e6cbSYasunari Takiguchi 	return 0;
98*4e67e6cbSYasunari Takiguchi }
99*4e67e6cbSYasunari Takiguchi 
cxd2880_spi_device_create_spi(struct cxd2880_spi * spi,struct cxd2880_spi_device * spi_device)100*4e67e6cbSYasunari Takiguchi int cxd2880_spi_device_create_spi(struct cxd2880_spi *spi,
101*4e67e6cbSYasunari Takiguchi 				  struct cxd2880_spi_device *spi_device)
102*4e67e6cbSYasunari Takiguchi {
103*4e67e6cbSYasunari Takiguchi 	if (!spi || !spi_device)
104*4e67e6cbSYasunari Takiguchi 		return -EINVAL;
105*4e67e6cbSYasunari Takiguchi 
106*4e67e6cbSYasunari Takiguchi 	spi->read = NULL;
107*4e67e6cbSYasunari Takiguchi 	spi->write = cxd2880_spi_device_write;
108*4e67e6cbSYasunari Takiguchi 	spi->write_read = cxd2880_spi_device_write_read;
109*4e67e6cbSYasunari Takiguchi 	spi->flags = 0;
110*4e67e6cbSYasunari Takiguchi 	spi->user = spi_device;
111*4e67e6cbSYasunari Takiguchi 
112*4e67e6cbSYasunari Takiguchi 	return 0;
113*4e67e6cbSYasunari Takiguchi }
114