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