1 /*
2 * Copyright (c) 2022 HPMicro
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
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include "device_resource_if.h"
19 #include "hdf_device_desc.h"
20 #include "osal_sem.h"
21 #include "osal_mem.h"
22 #include "hdf_log.h"
23 #include "spi_if.h"
24 #include "spi_core.h"
25 #include "hpm_common.h"
26 #include "hpm_spi_drv.h"
27 #include <los_interrupt.h>
28
29 #define HDF_LOG_TAG HPMICRO_SPI_HDF
30
31
32 struct HPMSpiDevice {
33 uint32_t id;
34 uint32_t base;
35 uint32_t clkFreq;
36 struct SpiCfg cfg;
37 };
38
39 spi_control_config_t control_config = {0};
40
HpmSpiConfig(struct SpiCntlr * cntlr)41 static void HpmSpiConfig(struct SpiCntlr *cntlr)
42 {
43 struct HPMSpiDevice *hpmSpiDev = (struct HPMSpiDevice *)cntlr->priv;
44 SPI_Type *base = (SPI_Type *)hpmSpiDev->base;
45 struct SpiCfg *cfg = &hpmSpiDev->cfg;
46 spi_timing_config_t timing_config = {0};
47 spi_format_config_t format_config = {0};
48
49 spi_master_get_default_timing_config(&timing_config);
50 spi_master_get_default_format_config(&format_config);
51
52 format_config.common_config.data_len_in_bits = 8;
53 format_config.common_config.mode = spi_master_mode;
54
55 if (cfg->mode & SPI_CLK_POLARITY) {
56 format_config.common_config.cpol = spi_sclk_high_idle;
57 } else {
58 format_config.common_config.cpol = spi_sclk_low_idle;
59 }
60
61 if (cfg->mode & SPI_CLK_PHASE) {
62 format_config.common_config.cpha = spi_sclk_sampling_even_clk_edges;
63 } else {
64 format_config.common_config.cpha = spi_sclk_sampling_odd_clk_edges;
65 }
66
67 if (cfg->mode & SPI_MODE_LSBFE) {
68 format_config.common_config.lsb = 1;
69 } else {
70 format_config.common_config.lsb = 0;
71 }
72
73 timing_config.master_config.clk_src_freq_in_hz = hpmSpiDev->clkFreq;
74 timing_config.master_config.sclk_freq_in_hz = cfg->maxSpeedHz;
75
76 spi_master_timing_init(base, &timing_config);
77 spi_format_init(base, &format_config);
78 }
79
80
HpmSpiGetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)81 static int32_t HpmSpiGetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
82 {
83 struct HPMSpiDevice *hpmSpiDev = (struct HPMSpiDevice *)cntlr->priv;
84 *cfg = hpmSpiDev->cfg;
85
86 return 0;
87 }
88
HpmSpiSetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)89 static int32_t HpmSpiSetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
90 {
91 struct HPMSpiDevice *hpmSpiDev = (struct HPMSpiDevice *)cntlr->priv;
92 hpmSpiDev->cfg = *cfg;
93
94 HpmSpiConfig(cntlr);
95 return 0;
96 }
97
HpmSpiTransfer(struct SpiCntlr * cntlr,struct SpiMsg * msg,uint32_t count)98 static int32_t HpmSpiTransfer(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count)
99 {
100 int ret;
101 struct HPMSpiDevice *hpmSpiDev = (struct HPMSpiDevice *)cntlr->priv;
102 SPI_Type *base = (SPI_Type *)hpmSpiDev->base;
103
104 spi_control_config_t config;
105 spi_master_get_default_control_config(&config);
106
107 config.master_config.cmd_enable = control_config.master_config.cmd_enable; /* cmd phase control for master */
108 config.master_config.addr_enable = control_config.master_config.addr_enable; /* address phase control for master */
109 config.slave_config.slave_data_only = control_config.slave_config.slave_data_only;
110 config.common_config.trans_mode = control_config.common_config.trans_mode;
111
112 uint32_t rLen;
113 uint32_t wLen;
114
115 for (int i = 0; i < count; i++) {
116 if (msg[i].wbuf && msg[i].rbuf) {
117 config.common_config.trans_mode = spi_trans_write_read_together;
118 rLen = msg[i].len;
119 wLen = msg[i].len;
120
121 } else if (msg[i].wbuf && !msg[i].rbuf) {
122 config.common_config.trans_mode = spi_trans_write_only;
123 rLen = 0;
124 wLen = msg[i].len;
125 } else if (!msg[i].wbuf && msg[i].rbuf) {
126 config.common_config.trans_mode = spi_trans_read_only;
127 rLen = msg[i].len;
128 wLen = 0;
129 } else {
130 return -1;
131 }
132
133 ret = spi_transfer(base, &config, NULL, NULL,
134 msg[i].wbuf, wLen, msg[i].rbuf, rLen);
135 if (ret != status_success) {
136 return -1;
137 }
138 }
139
140 return 0;
141 }
142
HpmSpiOpen(struct SpiCntlr * cntlr)143 static int32_t HpmSpiOpen(struct SpiCntlr *cntlr)
144 {
145 return 0;
146 }
147
HpmSpiClose(struct SpiCntlr * cntlr)148 static int32_t HpmSpiClose(struct SpiCntlr *cntlr)
149 {
150 return 0;
151 }
152
153 static struct SpiCntlrMethod spiCntlrMethod = {
154 .GetCfg = HpmSpiGetCfg,
155 .SetCfg = HpmSpiSetCfg,
156 .Transfer = HpmSpiTransfer,
157 .Open = HpmSpiOpen,
158 .Close = HpmSpiClose,
159 };
160
161
SpiDriverBind(struct HdfDeviceObject * device)162 static int32_t SpiDriverBind(struct HdfDeviceObject *device)
163 {
164 int32_t ret = HDF_SUCCESS;
165
166 struct SpiCntlr *cntlr = SpiCntlrCreate(device);
167 if (cntlr == NULL) {
168 ret = HDF_FAILURE;
169 HDF_LOGE("Bind: SpiCntlrCreate null\n");
170 return ret;
171 }
172
173 HDF_LOGI("Bind: successed\n");
174 return ret;
175 }
176
SpiDriverInit(struct HdfDeviceObject * device)177 static int32_t SpiDriverInit(struct HdfDeviceObject *device)
178 {
179 int32_t ret = HDF_SUCCESS;
180
181 struct SpiCntlr *cntlr = SpiCntlrFromDevice(device);
182 if (cntlr == NULL) {
183 ret = HDF_FAILURE;
184 HDF_LOGE("Init: SpiCntlrFromDevice null\n");
185 return ret;
186 }
187
188 struct HPMSpiDevice *hpmSpiDev = (struct HPMSpiDevice *)OsalMemCalloc(
189 sizeof(struct HPMSpiDevice));
190 if (hpmSpiDev == NULL) {
191 ret = HDF_ERR_MALLOC_FAIL;
192 HDF_LOGE("Init: HPMSpiDevice malloc Failed!!!\n");
193 goto ERROR1;
194 }
195
196 struct DeviceResourceIface *dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
197 if (dri == NULL) {
198 ret = HDF_FAILURE;
199 HDF_LOGE("Init: get DeviceResourceIface Failed!!!\n");
200 goto ERROR2;
201 }
202
203 dri->GetUint32(device->property, "id", &hpmSpiDev->id, 0);
204 dri->GetUint32(device->property, "base", &hpmSpiDev->base, 0);
205 dri->GetUint32(device->property, "clk_freq", &hpmSpiDev->clkFreq, 0);
206 HDF_LOGI("Init: hpmSpiDev->id: %u\n", hpmSpiDev->id);
207 HDF_LOGI("Init: hpmSpiDev->base: 0x%X\n", hpmSpiDev->base);
208 HDF_LOGI("Init: hpmSpiDev->clkFreq: %u\n", hpmSpiDev->clkFreq);
209
210 cntlr->busNum = hpmSpiDev->id;
211 cntlr->priv = hpmSpiDev;
212 cntlr->method = &spiCntlrMethod;
213
214 return ret;
215
216 ERROR2:
217 OsalMemFree(hpmSpiDev);
218 ERROR1:
219 return ret;
220 }
221
SpiDriverRelease(struct HdfDeviceObject * device)222 static void SpiDriverRelease(struct HdfDeviceObject *device)
223 {
224 if (device == NULL) {
225 return;
226 }
227
228 struct SpiCntlr *cntlr = SpiCntlrFromDevice(device);
229 if (cntlr == NULL) {
230 HDF_LOGE("Release: SpiCntlrFromDevice null\n");
231 return;
232 }
233
234 struct HPMSpiDevice *hpmSpiDev = (struct HPMSpiDevice *)cntlr->priv;
235
236 if (hpmSpiDev) {
237 OsalMemFree(hpmSpiDev);
238 }
239
240 SpiCntlrDestroy(cntlr);
241
242 HDF_LOGI("Release");
243 return;
244 }
245
246
247 struct HdfDriverEntry g_spiDriverEntry = {
248 .moduleVersion = 1,
249 .moduleName = "HPMICRO_SPI_MODULE_HDF",
250 .Bind = SpiDriverBind,
251 .Init = SpiDriverInit,
252 .Release = SpiDriverRelease,
253 };
254
255 HDF_INIT(g_spiDriverEntry);