1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-12-06 GuEe-GUI first version
9 */
10
11 #include "dev_spi_dm.h"
12
13 #define DBG_TAG "spi.bus"
14 #define DBG_LVL DBG_INFO
15 #include <rtdbg.h>
16
17 extern rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name);
18
19 static struct rt_bus spi_bus;
20
spi_bus_scan_devices(struct rt_spi_bus * bus)21 void spi_bus_scan_devices(struct rt_spi_bus *bus)
22 {
23 #ifdef RT_USING_OFW
24 if (bus->parent.ofw_node)
25 {
26 struct rt_ofw_node *np = bus->parent.ofw_node, *spi_dev_np;
27
28 rt_ofw_foreach_available_child_node(np, spi_dev_np)
29 {
30 struct rt_spi_device *spi_dev;
31
32 if (!rt_ofw_prop_read_bool(spi_dev_np, "compatible"))
33 {
34 continue;
35 }
36
37 if ((bus->mode & RT_SPI_BUS_MODE_SPI) == RT_SPI_BUS_MODE_SPI)
38 {
39 spi_dev = rt_calloc(1, sizeof(struct rt_spi_device));
40 }
41 else if ((bus->mode & RT_SPI_BUS_MODE_QSPI) == RT_SPI_BUS_MODE_QSPI)
42 {
43 spi_dev = rt_calloc(1, sizeof(struct rt_qspi_device));
44 }
45 else
46 {
47 LOG_E("Unknown bus mode = %x", bus->mode);
48 RT_ASSERT(0);
49 }
50
51 if (!spi_dev)
52 {
53 rt_ofw_node_put(spi_dev_np);
54 LOG_E("Not memory to create spi device: %s",
55 rt_ofw_node_full_name(spi_dev_np));
56
57 return;
58 }
59
60 spi_dev->parent.ofw_node = spi_dev_np;
61 spi_dev->parent.type = RT_Device_Class_Unknown;
62 spi_dev->name = rt_ofw_node_name(spi_dev_np);
63 spi_dev->bus = bus;
64
65 rt_dm_dev_set_name(&spi_dev->parent, rt_ofw_node_full_name(spi_dev_np));
66
67 if (spi_device_ofw_parse(spi_dev))
68 {
69 continue;
70 }
71
72 rt_spi_device_register(spi_dev);
73 }
74 }
75 #endif /* RT_USING_OFW */
76 }
77
rt_spi_driver_register(struct rt_spi_driver * driver)78 rt_err_t rt_spi_driver_register(struct rt_spi_driver *driver)
79 {
80 RT_ASSERT(driver != RT_NULL);
81
82 driver->parent.bus = &spi_bus;
83
84 return rt_driver_register(&driver->parent);
85 }
86
rt_spi_device_register(struct rt_spi_device * device)87 rt_err_t rt_spi_device_register(struct rt_spi_device *device)
88 {
89 RT_ASSERT(device != RT_NULL);
90
91 return rt_bus_add_device(&spi_bus, &device->parent);
92 }
93
spi_match(rt_driver_t drv,rt_device_t dev)94 static rt_bool_t spi_match(rt_driver_t drv, rt_device_t dev)
95 {
96 const struct rt_spi_device_id *id;
97 struct rt_spi_driver *driver = rt_container_of(drv, struct rt_spi_driver, parent);
98 struct rt_spi_device *device = rt_container_of(dev, struct rt_spi_device, parent);
99
100 if ((id = driver->ids))
101 {
102 for (; id->name[0]; ++id)
103 {
104 if (!rt_strcmp(id->name, device->name))
105 {
106 device->id = id;
107 device->ofw_id = RT_NULL;
108
109 return RT_TRUE;
110 }
111 }
112 }
113
114 #ifdef RT_USING_OFW
115 device->ofw_id = rt_ofw_node_match(device->parent.ofw_node, driver->ofw_ids);
116
117 if (device->ofw_id)
118 {
119 device->id = RT_NULL;
120
121 return RT_TRUE;
122 }
123 #endif
124
125 return RT_FALSE;
126 }
127
spi_probe(rt_device_t dev)128 static rt_err_t spi_probe(rt_device_t dev)
129 {
130 rt_err_t err;
131 struct rt_spi_bus *bus;
132 struct rt_spi_driver *driver = rt_container_of(dev->drv, struct rt_spi_driver, parent);
133 struct rt_spi_device *device = rt_container_of(dev, struct rt_spi_device, parent);
134
135 if (!device->bus)
136 {
137 return -RT_EINVAL;
138 }
139
140 err = driver->probe(device);
141
142 if (err)
143 {
144 return err;
145 }
146
147 bus = device->bus;
148
149 if (bus->cs_pins[0] >= 0)
150 {
151 device->cs_pin = bus->cs_pins[device->chip_select[0]];
152
153 rt_pin_mode(device->cs_pin, PIN_MODE_OUTPUT);
154 }
155 else
156 {
157 device->cs_pin = PIN_NONE;
158 }
159
160 /* Driver not register SPI device to system */
161 if (device->parent.type == RT_Device_Class_Unknown)
162 {
163 rt_spidev_device_init(device, rt_dm_dev_get_name(&device->parent));
164 }
165
166 return err;
167 }
168
spi_remove(rt_device_t dev)169 static rt_err_t spi_remove(rt_device_t dev)
170 {
171 struct rt_spi_driver *driver = rt_container_of(dev->drv, struct rt_spi_driver, parent);
172 struct rt_spi_device *device = rt_container_of(dev, struct rt_spi_device, parent);
173
174 if (driver && driver->remove)
175 {
176 driver->remove(device);
177 }
178 rt_free(device);
179
180 return RT_EOK;
181 }
182
spi_shutdown(rt_device_t dev)183 static rt_err_t spi_shutdown(rt_device_t dev)
184 {
185 struct rt_spi_driver *driver = rt_container_of(dev->drv, struct rt_spi_driver, parent);
186 struct rt_spi_device *device = rt_container_of(dev, struct rt_spi_device, parent);
187
188 if (driver && driver->shutdown)
189 {
190 driver->shutdown(device);
191 }
192 rt_free(device);
193
194 return RT_EOK;
195 }
196
197 static struct rt_bus spi_bus =
198 {
199 .name = "spi",
200 .match = spi_match,
201 .probe = spi_probe,
202 .remove = spi_remove,
203 .shutdown = spi_shutdown,
204 };
205
spi_bus_init(void)206 static int spi_bus_init(void)
207 {
208 rt_bus_register(&spi_bus);
209
210 return 0;
211 }
212 INIT_CORE_EXPORT(spi_bus_init);
213