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.dm"
14 #define DBG_LVL DBG_INFO
15 #include <rtdbg.h>
16
17 #ifdef RT_USING_OFW
ofw_parse_delay(struct rt_ofw_node * np,struct rt_spi_delay * delay,const char * prop)18 static void ofw_parse_delay(struct rt_ofw_node *np, struct rt_spi_delay *delay,
19 const char *prop)
20 {
21 rt_uint32_t value;
22
23 if (!rt_ofw_prop_read_u32(np, prop, &value))
24 {
25 if (value > RT_UINT16_MAX)
26 {
27 delay->value = RT_DIV_ROUND_UP(value, 1000);
28 delay->unit = RT_SPI_DELAY_UNIT_USECS;
29 }
30 else
31 {
32 delay->value = value;
33 delay->unit = RT_SPI_DELAY_UNIT_NSECS;
34 }
35 }
36 }
37
spi_device_ofw_parse(struct rt_spi_device * spi_dev)38 rt_err_t spi_device_ofw_parse(struct rt_spi_device *spi_dev)
39 {
40 rt_err_t err;
41 rt_uint32_t value, cs[RT_SPI_CS_CNT_MAX];
42 struct rt_spi_bus *spi_bus = spi_dev->bus;
43 struct rt_ofw_node *np = spi_dev->parent.ofw_node;
44 struct rt_spi_configuration *conf = &spi_dev->config;
45
46 if (rt_ofw_prop_read_bool(np, "spi-cpha"))
47 {
48 conf->mode |= RT_SPI_CPHA;
49 }
50 if (rt_ofw_prop_read_bool(np, "spi-cpol"))
51 {
52 conf->mode |= RT_SPI_CPOL;
53 }
54 if (rt_ofw_prop_read_bool(np, "spi-3wire"))
55 {
56 conf->mode |= RT_SPI_3WIRE;
57 }
58 if (rt_ofw_prop_read_bool(np, "spi-lsb-first"))
59 {
60 conf->mode |= RT_SPI_LSB;
61 }
62 if (rt_ofw_prop_read_bool(np, "spi-cs-high"))
63 {
64 conf->mode |= RT_SPI_CS_HIGH;
65 }
66
67 value = 1;
68 rt_ofw_prop_read_u32(np, "spi-tx-bus-width", &value);
69 conf->data_width_tx = value;
70
71 value = 1;
72 rt_ofw_prop_read_u32(np, "spi-rx-bus-width", &value);
73 conf->data_width_rx = value;
74
75 if (spi_bus->slave)
76 {
77 if (!rt_ofw_node_tag_equ(np, "slave"))
78 {
79 LOG_E("Invalid SPI device = %s", rt_ofw_node_full_name(np));
80
81 return -RT_EINVAL;
82 }
83
84 return RT_EOK;
85 }
86
87 value = rt_ofw_prop_read_u32_array_index(np, "reg", 0, RT_SPI_CS_CNT_MAX, cs);
88
89 if ((rt_int32_t)value < 0)
90 {
91 err = (rt_err_t)value;
92 LOG_E("Find 'reg' failed");
93
94 return err;
95 }
96
97 for (int i = 0; i < value; ++i)
98 {
99 spi_dev->chip_select[i] = cs[i];
100 }
101
102 if (!rt_ofw_prop_read_u32(np, "spi-max-frequency", &value))
103 {
104 conf->max_hz = value;
105 }
106
107 ofw_parse_delay(np, &spi_dev->cs_setup, "spi-cs-setup-delay-ns");
108 ofw_parse_delay(np, &spi_dev->cs_hold, "spi-cs-hold-delay-ns");
109 ofw_parse_delay(np, &spi_dev->cs_inactive, "spi-cs-inactive-delay-ns");
110
111 return RT_EOK;
112 }
113 #endif /* RT_USING_OFW */
114