• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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