1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 */
9
10 #include <rtthread.h>
11 #include "drivers/dev_spi.h"
12
13 #define DBG_TAG "spi.dev"
14 #define DBG_LVL DBG_INFO
15 #include <rtdbg.h>
16
17 #ifdef RT_USING_DM
18 #include "dev_spi_dm.h"
19 #endif
20
21 /* SPI bus device interface, compatible with RT-Thread 0.3.x/1.0.x */
_spi_bus_device_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)22 static rt_ssize_t _spi_bus_device_read(rt_device_t dev,
23 rt_off_t pos,
24 void *buffer,
25 rt_size_t size)
26 {
27 struct rt_spi_bus *bus;
28
29 bus = (struct rt_spi_bus *)dev;
30 RT_ASSERT(bus != RT_NULL);
31 RT_ASSERT(bus->owner != RT_NULL);
32
33 return rt_spi_transfer(bus->owner, RT_NULL, buffer, size);
34 }
35
_spi_bus_device_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)36 static rt_ssize_t _spi_bus_device_write(rt_device_t dev,
37 rt_off_t pos,
38 const void *buffer,
39 rt_size_t size)
40 {
41 struct rt_spi_bus *bus;
42
43 bus = (struct rt_spi_bus *)dev;
44 RT_ASSERT(bus != RT_NULL);
45 RT_ASSERT(bus->owner != RT_NULL);
46
47 return rt_spi_transfer(bus->owner, buffer, RT_NULL, size);
48 }
49
50 #ifdef RT_USING_DEVICE_OPS
51 const static struct rt_device_ops spi_bus_ops =
52 {
53 RT_NULL,
54 RT_NULL,
55 RT_NULL,
56 _spi_bus_device_read,
57 _spi_bus_device_write,
58 RT_NULL
59 };
60 #endif
61
rt_spi_bus_device_init(struct rt_spi_bus * bus,const char * name)62 rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name)
63 {
64 struct rt_device *device;
65 RT_ASSERT(bus != RT_NULL);
66
67 device = &bus->parent;
68
69 /* set device type */
70 device->type = RT_Device_Class_SPIBUS;
71 /* initialize device interface */
72 #ifdef RT_USING_DEVICE_OPS
73 device->ops = &spi_bus_ops;
74 #else
75 device->init = RT_NULL;
76 device->open = RT_NULL;
77 device->close = RT_NULL;
78 device->read = _spi_bus_device_read;
79 device->write = _spi_bus_device_write;
80 device->control = RT_NULL;
81 #endif
82
83 /* register to device manager */
84 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
85 }
86
87 /* SPI Dev device interface, compatible with RT-Thread 0.3.x/1.0.x */
_spidev_device_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)88 static rt_ssize_t _spidev_device_read(rt_device_t dev,
89 rt_off_t pos,
90 void *buffer,
91 rt_size_t size)
92 {
93 struct rt_spi_device *device;
94
95 device = (struct rt_spi_device *)dev;
96 RT_ASSERT(device != RT_NULL);
97 RT_ASSERT(device->bus != RT_NULL);
98
99 return rt_spi_transfer(device, RT_NULL, buffer, size);
100 }
101
_spidev_device_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)102 static rt_ssize_t _spidev_device_write(rt_device_t dev,
103 rt_off_t pos,
104 const void *buffer,
105 rt_size_t size)
106 {
107 struct rt_spi_device *device;
108
109 device = (struct rt_spi_device *)dev;
110 RT_ASSERT(device != RT_NULL);
111 RT_ASSERT(device->bus != RT_NULL);
112
113 return rt_spi_transfer(device, buffer, RT_NULL, size);
114 }
115
_spidev_device_control(rt_device_t dev,int cmd,void * args)116 static rt_err_t _spidev_device_control(rt_device_t dev,
117 int cmd,
118 void *args)
119 {
120 switch (cmd)
121 {
122 case 0: /* set device */
123 break;
124 case 1:
125 break;
126 }
127
128 return RT_EOK;
129 }
130
131 #ifdef RT_USING_DEVICE_OPS
132 const static struct rt_device_ops spi_device_ops =
133 {
134 RT_NULL,
135 RT_NULL,
136 RT_NULL,
137 _spidev_device_read,
138 _spidev_device_write,
139 _spidev_device_control
140 };
141 #endif
142
rt_spidev_device_init(struct rt_spi_device * dev,const char * name)143 rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
144 {
145 struct rt_device *device;
146 RT_ASSERT(dev != RT_NULL);
147
148 device = &(dev->parent);
149
150 /* set device type */
151 device->type = RT_Device_Class_SPIDevice;
152 #ifdef RT_USING_DEVICE_OPS
153 device->ops = &spi_device_ops;
154 #else
155 device->init = RT_NULL;
156 device->open = RT_NULL;
157 device->close = RT_NULL;
158 device->read = _spidev_device_read;
159 device->write = _spidev_device_write;
160 device->control = _spidev_device_control;
161 #endif
162
163 /* register to device manager */
164 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
165 }
166
167 #ifdef RT_USING_DM
spidev_probe(struct rt_spi_device * spi_dev)168 static rt_err_t spidev_probe(struct rt_spi_device *spi_dev)
169 {
170 const char *bus_name;
171 struct rt_device *dev = &spi_dev->parent;
172
173 if (spi_dev->parent.ofw_node)
174 {
175 if (rt_dm_dev_prop_index_of_string(dev, "compatible", "spidev") >= 0)
176 {
177 LOG_E("spidev is not supported in OFW");
178
179 return -RT_EINVAL;
180 }
181 }
182
183 bus_name = rt_dm_dev_get_name(&spi_dev->bus->parent);
184 rt_dm_dev_set_name(dev, "%s_%d", bus_name, spi_dev->chip_select[0]);
185
186 return RT_EOK;
187 }
188
189 static const struct rt_spi_device_id spidev_ids[] =
190 {
191 { .name = "dh2228fv" },
192 { .name = "ltc2488" },
193 { .name = "sx1301" },
194 { .name = "bk4" },
195 { .name = "dhcom-board" },
196 { .name = "m53cpld" },
197 { .name = "spi-petra" },
198 { .name = "spi-authenta" },
199 { .name = "em3581" },
200 { .name = "si3210" },
201 { /* sentinel */ },
202 };
203
204 static const struct rt_ofw_node_id spidev_ofw_ids[] =
205 {
206 { .compatible = "cisco,spi-petra" },
207 { .compatible = "dh,dhcom-board" },
208 { .compatible = "lineartechnology,ltc2488" },
209 { .compatible = "lwn,bk4" },
210 { .compatible = "menlo,m53cpld" },
211 { .compatible = "micron,spi-authenta" },
212 { .compatible = "rohm,dh2228fv" },
213 { .compatible = "semtech,sx1301" },
214 { .compatible = "silabs,em3581" },
215 { .compatible = "silabs,si3210" },
216 { .compatible = "rockchip,spidev" },
217 { /* sentinel */ },
218 };
219
220 static struct rt_spi_driver spidev_driver =
221 {
222 .ids = spidev_ids,
223 .ofw_ids = spidev_ofw_ids,
224
225 .probe = spidev_probe,
226 };
227 RT_SPI_DRIVER_EXPORT(spidev_driver);
228 #endif /* RT_USING_DM */
229