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