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