1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "icu_hal.h"
16 #include "clock_driver.h"
17 #include "power_hal.h"
18 #include "spi_hal.h"
19 #include "spi_ll.h"
20 #include <driver/hal/hal_spi_types.h>
21 #include "sys_hal.h"
22
23 #define CONFIG_SPI_MAX_BAUD_RATE ((120000000 >> 1) / (1 + 1)) /**< 30M */
24
25 #if 0
26 static icu_hal_t s_icu_hal = {
27 .hw = (icu_hw_t *)ICU_LL_REG_BASE(),
28 };
29 #endif
30
31 /* spi_clk(more than 1M) support list when source_clk = XTAL_26M
32 * sort the numbers from largest to smallest, otherwize binary_search will not work
33 */
34 static const uint32_t s_spi_clk_list[] = {
35 26000000, /**< DIV1 */
36 13000000, /**< DIV2 */
37 6500000, /**< DIV4 */
38 5200000, /**< DIV5 */
39 3250000, /**< DIV8 */
40 2600000, /**< DIV10 */
41 2000000, /**< DIV13 */
42 1625000, /**< DIV16 */
43 1300000, /**< DIV20 */
44 1040000, /**< DIV25 */
45 1000000, /**< DIV26 */
46 };
47
binary_search(const uint32_t * array,uint32_t size,uint32_t target)48 static int binary_search(const uint32_t *array, uint32_t size, uint32_t target)
49 {
50 uint32_t left = 0;
51 uint32_t right = size - 1;
52 uint32_t mid = (left + right) / 2;
53
54 while (left <= right && mid < size) {
55 mid = (left + right) / 2;
56 if (array[mid] == target) {
57 return mid;
58 }
59 if (target > array[mid]) {
60 right = mid - 1;
61 } else {
62 left = mid + 1;
63 }
64 }
65 return BK_FAIL;
66 }
67
spi_hal_init(spi_hal_t * hal)68 bk_err_t spi_hal_init(spi_hal_t *hal)
69 {
70 hal->hw = (spi_hw_t *)SPI_LL_REG_BASE(hal->id);
71 spi_ll_init(hal->hw);
72 return BK_OK;
73 }
74
75 /* 1. bit_width, clk_rate, cpol, cpha, master/slave, 4line, int_level=0, rxovf_en=1, txudf_en=1
76 * 2. if 4 wire mode, enable sla_release_int_en, clear slv_release_int
77 * 3. set rx_callback, tx_need_write_callback, tx_finish_callback
78 * 4. enable spi, bit[23] spi_en
79 */
spi_hal_configure(spi_hal_t * hal,const spi_config_t * config)80 bk_err_t spi_hal_configure(spi_hal_t *hal, const spi_config_t *config)
81 {
82 spi_ll_enable_tx_underflow_int(hal->hw);
83 spi_ll_enable_rx_overflow_int(hal->hw);
84 spi_ll_disable_tx_fifo_int(hal->hw);
85 spi_ll_enable_rx_fifo_int(hal->hw);
86
87 spi_hal_set_baud_rate(hal, config->baud_rate);
88
89 spi_ll_set_bit_width(hal->hw, config->bit_width);
90 spi_ll_set_first_bit(hal->hw, config->bit_order);
91 spi_ll_set_cpol(hal->hw, config->polarity);
92 spi_ll_set_cpha(hal->hw, config->phase);
93 if (config->role == SPI_ROLE_SLAVE) {
94 spi_ll_set_role_slave(hal->hw);
95 } else {
96 spi_ll_set_role_master(hal->hw);
97 }
98 spi_ll_set_wire_mode(hal->hw, config->wire_mode);
99 if (config->wire_mode == SPI_4WIRE_MODE) {
100 spi_ll_enable_slave_release_int(hal->hw);
101 } else {
102 spi_ll_disable_slave_release_int(hal->hw);
103 }
104 spi_ll_enable_tx_finish_int(hal->hw);
105 spi_ll_enable_rx_finish_int(hal->hw);
106 spi_ll_clear_int_status(hal->hw);
107
108 return BK_OK;
109 }
110
spi_hal_start_common(spi_hal_t * hal)111 bk_err_t spi_hal_start_common(spi_hal_t *hal)
112 {
113 spi_ll_enable(hal->hw);
114 return BK_OK;
115 }
116
spi_hal_stop_common(spi_hal_t * hal)117 bk_err_t spi_hal_stop_common(spi_hal_t *hal)
118 {
119 spi_ll_disable(hal->hw);
120 return BK_OK;
121 }
122
123 /* 1) src_clk=dco, div = ((dco_clk/2) / spi_clk) - 1
124 * 2) src_clk=xtal_26M, div = xtal_26m / spi_clk - 1
125 */
spi_hal_set_baud_rate(spi_hal_t * hal,uint32_t baud_rate)126 bk_err_t spi_hal_set_baud_rate(spi_hal_t *hal, uint32_t baud_rate)
127 {
128 uint32_t src_clk = 0;
129 uint32_t spi_clk = baud_rate;
130 uint32_t clk_div = 0;
131
132 if (baud_rate > CONFIG_SPI_MAX_BAUD_RATE) {
133 HAL_LOGW("baud_rate(%d) not support, spi support max baud_rate:%d\r\n", baud_rate, CONFIG_SPI_MAX_BAUD_RATE);
134 spi_clk = CONFIG_SPI_MAX_BAUD_RATE;
135 }
136
137 if (binary_search(s_spi_clk_list, ARRAY_SIZE(s_spi_clk_list), baud_rate) >= 0) {
138 HAL_LOGI("spi select src_clk xtal\r\n");
139 src_clk = CONFIG_XTAL_FREQ;
140 #if (CONFIG_SYSTEM_CTRL)
141 sys_hal_spi_select_clock(hal->id, SPI_CLK_XTAL);
142 #else
143 clk_set_spi_clk_26m(hal->id);
144 #endif
145 clk_div = (src_clk / spi_clk - 1) & SPI_F_CLK_DIV_M;
146 } else {
147 #if (CONFIG_SYSTEM_CTRL)
148 //APLL is for i2s
149 HAL_LOGI("spi select src_clk xtal\r\n");
150 src_clk = CONFIG_XTAL_FREQ;
151 sys_hal_spi_select_clock(hal->id, SPI_CLK_XTAL);
152 clk_div = ((src_clk / spi_clk) - 1) & SPI_F_CLK_DIV_M;
153 #else
154 HAL_LOGI("spi select src_clk dco\r\n");
155 src_clk = CONFIG_DCO_FREQ >> 1; /* The spi clock is derived from the dco clock divided by 2 */
156 clk_set_spi_clk_dco(hal->id);
157 clk_div = (src_clk / spi_clk) & SPI_F_CLK_DIV_M;
158 #endif
159 }
160
161 spi_ll_set_clk_div(hal->hw, clk_div);
162
163 return BK_OK;
164 }
165
spi_hal_read_byte(spi_hal_t * hal,uint8_t * data)166 bk_err_t spi_hal_read_byte(spi_hal_t *hal, uint8_t *data)
167 {
168 if (spi_ll_is_rx_fifo_rd_ready(hal->hw)) {
169 *data = spi_ll_read_byte(hal->hw);
170 return BK_OK;
171 }
172 return BK_ERR_SPI_FIFO_RD_NOT_READY;
173 }
174
175