Linux-libre 5.4.49-gnu
[librecmc/linux-libre.git] / drivers / media / dvb-frontends / cxd2880 / cxd2880_spi_device.c
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 }