1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022 Chipsea Technologies (Shenzhen) Corp., Ltd.
3094332d3Sopenharmony_ci *
4094332d3Sopenharmony_ci * HDF is dual licensed: you can use it either under the terms of
5094332d3Sopenharmony_ci * the GPL, or the BSD license, at your option.
6094332d3Sopenharmony_ci * See the LICENSE file in the root of this repository for complete details.
7094332d3Sopenharmony_ci */
8094332d3Sopenharmony_ci
9094332d3Sopenharmony_ci#include "ppg_cs1262_spi.h"
10094332d3Sopenharmony_ci#include "spi_if.h"
11094332d3Sopenharmony_ci
12094332d3Sopenharmony_ci#define HDF_LOG_TAG khdf_sensor_ppg_driver
13094332d3Sopenharmony_ci
14094332d3Sopenharmony_ci#define CS1262_HEAD_BUF_SINGLEREG_LEN 4
15094332d3Sopenharmony_ci#define CS1262_HEAD_BUF_FULL_LEN 6
16094332d3Sopenharmony_ci#define OFFSET_BITS_8 8
17094332d3Sopenharmony_ci#define OFFSET_BITS_2 2
18094332d3Sopenharmony_ci
19094332d3Sopenharmony_cistatic struct SensorBusCfg *g_busCfg = NULL;
20094332d3Sopenharmony_ci
21094332d3Sopenharmony_cistatic inline uint16_t ReverseEndianInt16(uint16_t data)
22094332d3Sopenharmony_ci{
23094332d3Sopenharmony_ci    return (((data & 0x00FF) << OFFSET_BITS_8) |
24094332d3Sopenharmony_ci            ((data & 0xFF00) >> OFFSET_BITS_8));
25094332d3Sopenharmony_ci}
26094332d3Sopenharmony_ci
27094332d3Sopenharmony_cistatic inline uint16_t Cs1262RegAddrConvert(uint16_t reg)
28094332d3Sopenharmony_ci{
29094332d3Sopenharmony_ci    /* CS1262 takes the register address from bit[2] to bit[15], bit[1~0] fixed as 00,
30094332d3Sopenharmony_ci     * so reg needs to be shifted left by 2 bits to convert it to the address format required by CS1262
31094332d3Sopenharmony_ci     */
32094332d3Sopenharmony_ci    return (reg << OFFSET_BITS_2) & 0x0FFC;
33094332d3Sopenharmony_ci}
34094332d3Sopenharmony_ci
35094332d3Sopenharmony_cistatic inline uint8_t Cs1262GetHighByteInt16(uint16_t data)
36094332d3Sopenharmony_ci{
37094332d3Sopenharmony_ci    return (data & 0xFF00) >> OFFSET_BITS_8;
38094332d3Sopenharmony_ci}
39094332d3Sopenharmony_ci
40094332d3Sopenharmony_cistatic inline uint8_t Cs1262GetLowByteInt16(uint16_t data)
41094332d3Sopenharmony_ci{
42094332d3Sopenharmony_ci    return data & 0x00FF;
43094332d3Sopenharmony_ci}
44094332d3Sopenharmony_ci
45094332d3Sopenharmony_civoid Cs1262ReleaseSpi(struct SensorBusCfg *busCfg)
46094332d3Sopenharmony_ci{
47094332d3Sopenharmony_ci    SpiClose(busCfg->spiCfg.handle);
48094332d3Sopenharmony_ci    busCfg->spiCfg.handle = NULL;
49094332d3Sopenharmony_ci    g_busCfg = NULL;
50094332d3Sopenharmony_ci}
51094332d3Sopenharmony_ci
52094332d3Sopenharmony_ciint32_t Cs1262InitSpi(struct SensorBusCfg *busCfg)
53094332d3Sopenharmony_ci{
54094332d3Sopenharmony_ci    int32_t ret;
55094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(busCfg, HDF_ERR_INVALID_PARAM);
56094332d3Sopenharmony_ci    struct SpiDevInfo spiDevinfo = {
57094332d3Sopenharmony_ci        .busNum = busCfg->spiCfg.busNum,
58094332d3Sopenharmony_ci        .csNum = busCfg->spiCfg.csNum,
59094332d3Sopenharmony_ci    };
60094332d3Sopenharmony_ci
61094332d3Sopenharmony_ci    HDF_LOGI("%s: SpiOpen busNum = %d, csNum = %d", __func__, spiDevinfo.busNum, spiDevinfo.csNum);
62094332d3Sopenharmony_ci
63094332d3Sopenharmony_ci    busCfg->spiCfg.handle = SpiOpen(&spiDevinfo);
64094332d3Sopenharmony_ci    if (busCfg->spiCfg.handle == NULL) {
65094332d3Sopenharmony_ci        HDF_LOGE("%s: SpiOpen failed", __func__);
66094332d3Sopenharmony_ci        return HDF_FAILURE;
67094332d3Sopenharmony_ci    }
68094332d3Sopenharmony_ci
69094332d3Sopenharmony_ci    HDF_LOGD("%s: SpiSetCfg: maxSpeedHz:%d, mode=%d, transferMode=%d, bitsPerWord=%d",
70094332d3Sopenharmony_ci        __func__, busCfg->spiCfg.spi.maxSpeedHz, busCfg->spiCfg.spi.mode,
71094332d3Sopenharmony_ci        busCfg->spiCfg.spi.transferMode, busCfg->spiCfg.spi.bitsPerWord);
72094332d3Sopenharmony_ci
73094332d3Sopenharmony_ci    ret = SpiSetCfg(busCfg->spiCfg.handle, &busCfg->spiCfg.spi);
74094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
75094332d3Sopenharmony_ci        HDF_LOGE("%s: SpiSetCfg failed", __func__);
76094332d3Sopenharmony_ci        SpiClose(busCfg->spiCfg.handle);
77094332d3Sopenharmony_ci        return ret;
78094332d3Sopenharmony_ci    }
79094332d3Sopenharmony_ci
80094332d3Sopenharmony_ci    g_busCfg = busCfg;
81094332d3Sopenharmony_ci    return HDF_SUCCESS;
82094332d3Sopenharmony_ci}
83094332d3Sopenharmony_ci
84094332d3Sopenharmony_ciint32_t Cs1262ReadFifoReg(Cs1262FifoVal *fifoBuf, uint16_t fifoLen)
85094332d3Sopenharmony_ci{
86094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(fifoBuf, HDF_ERR_INVALID_PARAM);
87094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
88094332d3Sopenharmony_ci
89094332d3Sopenharmony_ci    uint8_t headBuf[CS1262_HEAD_BUF_FULL_LEN] = {
90094332d3Sopenharmony_ci        CS1262_SPI_NOCHECK_CONTINUOUSREAD,
91094332d3Sopenharmony_ci        0,
92094332d3Sopenharmony_ci        Cs1262GetHighByteInt16(Cs1262RegAddrConvert(CS1262_FIFO_DATA_REG)),
93094332d3Sopenharmony_ci        Cs1262GetLowByteInt16(Cs1262RegAddrConvert(CS1262_FIFO_DATA_REG)),
94094332d3Sopenharmony_ci        Cs1262GetHighByteInt16(fifoLen - 1),
95094332d3Sopenharmony_ci        Cs1262GetLowByteInt16(fifoLen - 1),
96094332d3Sopenharmony_ci    };
97094332d3Sopenharmony_ci
98094332d3Sopenharmony_ci    struct SpiMsg msg[] = {
99094332d3Sopenharmony_ci        {
100094332d3Sopenharmony_ci            .wbuf = headBuf,
101094332d3Sopenharmony_ci            .rbuf = NULL,
102094332d3Sopenharmony_ci            .len = CS1262_HEAD_BUF_FULL_LEN,
103094332d3Sopenharmony_ci            .keepCs = 0,  // cs low
104094332d3Sopenharmony_ci            .delayUs = 0,
105094332d3Sopenharmony_ci            .speed = g_busCfg->spiCfg.spi.maxSpeedHz,
106094332d3Sopenharmony_ci        },
107094332d3Sopenharmony_ci        {
108094332d3Sopenharmony_ci            .wbuf = NULL,
109094332d3Sopenharmony_ci            .rbuf = (uint8_t *)fifoBuf,
110094332d3Sopenharmony_ci            .len = fifoLen * sizeof(Cs1262FifoVal),
111094332d3Sopenharmony_ci            .keepCs = 1,  // cs high
112094332d3Sopenharmony_ci            .delayUs = 0,
113094332d3Sopenharmony_ci            .speed = g_busCfg->spiCfg.spi.maxSpeedHz
114094332d3Sopenharmony_ci        }
115094332d3Sopenharmony_ci    };
116094332d3Sopenharmony_ci
117094332d3Sopenharmony_ci    if (SpiTransfer(g_busCfg->spiCfg.handle, msg, HDF_ARRAY_SIZE(msg)) != HDF_SUCCESS) {
118094332d3Sopenharmony_ci        HDF_LOGE("%s: Read Fifo data use spi failed", __func__);
119094332d3Sopenharmony_ci        return HDF_FAILURE;
120094332d3Sopenharmony_ci    }
121094332d3Sopenharmony_ci
122094332d3Sopenharmony_ci    return HDF_SUCCESS;
123094332d3Sopenharmony_ci}
124094332d3Sopenharmony_ci
125094332d3Sopenharmony_ciint32_t Cs1262ReadRegs(uint16_t regAddr, uint16_t *dataBuf, uint16_t dataLen)
126094332d3Sopenharmony_ci{
127094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(dataBuf, HDF_ERR_INVALID_PARAM);
128094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
129094332d3Sopenharmony_ci
130094332d3Sopenharmony_ci    uint8_t headBuf[CS1262_HEAD_BUF_FULL_LEN] = {
131094332d3Sopenharmony_ci        CS1262_SPI_NOCHECK_SINGLEREAD,
132094332d3Sopenharmony_ci        0,
133094332d3Sopenharmony_ci        Cs1262GetHighByteInt16(Cs1262RegAddrConvert(regAddr)),
134094332d3Sopenharmony_ci        Cs1262GetLowByteInt16(Cs1262RegAddrConvert(regAddr))
135094332d3Sopenharmony_ci    };
136094332d3Sopenharmony_ci    uint8_t bufLen = CS1262_HEAD_BUF_SINGLEREG_LEN;
137094332d3Sopenharmony_ci
138094332d3Sopenharmony_ci    if (dataLen > 1) {
139094332d3Sopenharmony_ci        headBuf[0] = CS1262_SPI_NOCHECK_CONTINUOUSREAD;
140094332d3Sopenharmony_ci        headBuf[bufLen++] = Cs1262GetHighByteInt16(dataLen - 1);
141094332d3Sopenharmony_ci        headBuf[bufLen++] = Cs1262GetLowByteInt16(dataLen - 1);
142094332d3Sopenharmony_ci    }
143094332d3Sopenharmony_ci
144094332d3Sopenharmony_ci    struct SpiMsg msg[] = {
145094332d3Sopenharmony_ci        {
146094332d3Sopenharmony_ci            .wbuf = headBuf,
147094332d3Sopenharmony_ci            .rbuf = NULL,
148094332d3Sopenharmony_ci            .len = bufLen,
149094332d3Sopenharmony_ci            .keepCs = 0,
150094332d3Sopenharmony_ci            .delayUs = 0,
151094332d3Sopenharmony_ci            .speed = g_busCfg->spiCfg.spi.maxSpeedHz
152094332d3Sopenharmony_ci        },
153094332d3Sopenharmony_ci        {
154094332d3Sopenharmony_ci            .wbuf = NULL,
155094332d3Sopenharmony_ci            .rbuf = (uint8_t *)dataBuf,
156094332d3Sopenharmony_ci            .len = dataLen * 2,  // 2 bytes reg
157094332d3Sopenharmony_ci            .keepCs = 1,  // 1 means enable
158094332d3Sopenharmony_ci            .delayUs = 0,
159094332d3Sopenharmony_ci            .speed = g_busCfg->spiCfg.spi.maxSpeedHz
160094332d3Sopenharmony_ci        }
161094332d3Sopenharmony_ci    };
162094332d3Sopenharmony_ci
163094332d3Sopenharmony_ci    if (SpiTransfer(g_busCfg->spiCfg.handle, msg, HDF_ARRAY_SIZE(msg)) != HDF_SUCCESS) {
164094332d3Sopenharmony_ci        HDF_LOGE("%s: Read data use spi failed", __func__);
165094332d3Sopenharmony_ci        return HDF_FAILURE;
166094332d3Sopenharmony_ci    }
167094332d3Sopenharmony_ci
168094332d3Sopenharmony_ci    for (uint16_t index = 0; index < dataLen; index++) {
169094332d3Sopenharmony_ci        *(dataBuf + index) = ReverseEndianInt16(*(dataBuf + index));
170094332d3Sopenharmony_ci    }
171094332d3Sopenharmony_ci
172094332d3Sopenharmony_ci    return HDF_SUCCESS;
173094332d3Sopenharmony_ci}
174094332d3Sopenharmony_ci
175094332d3Sopenharmony_ciint32_t Cs1262WriteRegs(uint16_t regAddr, uint16_t *dataBuf, uint16_t dataLen)
176094332d3Sopenharmony_ci{
177094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(dataBuf, HDF_ERR_INVALID_PARAM);
178094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
179094332d3Sopenharmony_ci
180094332d3Sopenharmony_ci    uint8_t headBuf[CS1262_HEAD_BUF_FULL_LEN] = {
181094332d3Sopenharmony_ci        CS1262_SPI_NOCHECK_SINGLEWRITE,
182094332d3Sopenharmony_ci        0,
183094332d3Sopenharmony_ci        Cs1262GetHighByteInt16(Cs1262RegAddrConvert(regAddr)),
184094332d3Sopenharmony_ci        Cs1262GetLowByteInt16(Cs1262RegAddrConvert(regAddr))
185094332d3Sopenharmony_ci    };
186094332d3Sopenharmony_ci    uint8_t bufLen = CS1262_HEAD_BUF_SINGLEREG_LEN;
187094332d3Sopenharmony_ci
188094332d3Sopenharmony_ci    if (dataLen > 1) {
189094332d3Sopenharmony_ci        headBuf[0] = CS1262_SPI_NOCHECK_CONTINUOUSWRITE;
190094332d3Sopenharmony_ci        headBuf[bufLen++] = Cs1262GetHighByteInt16(dataLen - 1);
191094332d3Sopenharmony_ci        headBuf[bufLen++] = Cs1262GetLowByteInt16(dataLen - 1);
192094332d3Sopenharmony_ci    }
193094332d3Sopenharmony_ci
194094332d3Sopenharmony_ci    for (uint16_t index = 0; index < dataLen; index++) {
195094332d3Sopenharmony_ci        *(dataBuf + index) = ReverseEndianInt16(*(dataBuf + index));
196094332d3Sopenharmony_ci    }
197094332d3Sopenharmony_ci
198094332d3Sopenharmony_ci    struct SpiMsg msg[] = {
199094332d3Sopenharmony_ci        {
200094332d3Sopenharmony_ci            .wbuf = headBuf,
201094332d3Sopenharmony_ci            .rbuf = NULL,
202094332d3Sopenharmony_ci            .len = bufLen,
203094332d3Sopenharmony_ci            .keepCs = 0,
204094332d3Sopenharmony_ci            .delayUs = 0,
205094332d3Sopenharmony_ci            .speed = g_busCfg->spiCfg.spi.maxSpeedHz
206094332d3Sopenharmony_ci        },
207094332d3Sopenharmony_ci        {
208094332d3Sopenharmony_ci            .wbuf = (uint8_t *)dataBuf,
209094332d3Sopenharmony_ci            .rbuf = NULL,
210094332d3Sopenharmony_ci            .len = dataLen * 2,  // 1 data has 2 bytes
211094332d3Sopenharmony_ci            .keepCs = 1,  // 1 means enable
212094332d3Sopenharmony_ci            .delayUs = 0,
213094332d3Sopenharmony_ci            .speed = g_busCfg->spiCfg.spi.maxSpeedHz
214094332d3Sopenharmony_ci        }
215094332d3Sopenharmony_ci    };
216094332d3Sopenharmony_ci
217094332d3Sopenharmony_ci    if (SpiTransfer(g_busCfg->spiCfg.handle, msg, HDF_ARRAY_SIZE(msg)) != HDF_SUCCESS) {
218094332d3Sopenharmony_ci        HDF_LOGE("%s: Write data use spi failed", __func__);
219094332d3Sopenharmony_ci        return HDF_FAILURE;
220094332d3Sopenharmony_ci    }
221094332d3Sopenharmony_ci
222094332d3Sopenharmony_ci    return HDF_SUCCESS;
223094332d3Sopenharmony_ci}
224094332d3Sopenharmony_ci
225094332d3Sopenharmony_ciinline int32_t Cs1262WriteReg(uint16_t regAddr, uint16_t data)
226094332d3Sopenharmony_ci{
227094332d3Sopenharmony_ci    return Cs1262WriteRegs(regAddr, &data, 1);
228094332d3Sopenharmony_ci}
229094332d3Sopenharmony_ci
230094332d3Sopenharmony_ciint32_t Cs1262WriteData(uint8_t *data, uint16_t dataLen)
231094332d3Sopenharmony_ci{
232094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
233094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
234094332d3Sopenharmony_ci    struct SpiMsg msg = {
235094332d3Sopenharmony_ci        .wbuf = data,
236094332d3Sopenharmony_ci        .rbuf = NULL,
237094332d3Sopenharmony_ci        .len = dataLen,
238094332d3Sopenharmony_ci        .keepCs = 1,  // 1 means enable
239094332d3Sopenharmony_ci        .delayUs = 0,
240094332d3Sopenharmony_ci        .speed = g_busCfg->spiCfg.spi.maxSpeedHz
241094332d3Sopenharmony_ci    };
242094332d3Sopenharmony_ci    return SpiTransfer(g_busCfg->spiCfg.handle, &msg, 1);
243094332d3Sopenharmony_ci}
244094332d3Sopenharmony_ci
245094332d3Sopenharmony_ciint32_t Cs1262WriteRegbit(uint16_t regAddr, uint16_t setbit, Cs1262BitStatus bitval)
246094332d3Sopenharmony_ci{
247094332d3Sopenharmony_ci    uint16_t regData = 0;
248094332d3Sopenharmony_ci
249094332d3Sopenharmony_ci    if (Cs1262ReadRegs(regAddr, &regData, 1) != HDF_SUCCESS) {
250094332d3Sopenharmony_ci        HDF_LOGE("%s: failed", __func__);
251094332d3Sopenharmony_ci        return HDF_FAILURE;
252094332d3Sopenharmony_ci    }
253094332d3Sopenharmony_ci
254094332d3Sopenharmony_ci    if (bitval == CS1262_REG_BIT_SET) {
255094332d3Sopenharmony_ci        regData |= (uint16_t)(1 << setbit);
256094332d3Sopenharmony_ci    } else {
257094332d3Sopenharmony_ci        regData &=  (uint16_t)(~(1 << setbit));
258094332d3Sopenharmony_ci    }
259094332d3Sopenharmony_ci
260094332d3Sopenharmony_ci    return Cs1262WriteRegs(regAddr, &regData, 1);
261094332d3Sopenharmony_ci}
262094332d3Sopenharmony_ci
263094332d3Sopenharmony_ciint32_t Cs1262WriteGroup(Cs1262RegGroup *regGroup, uint16_t groupLen)
264094332d3Sopenharmony_ci{
265094332d3Sopenharmony_ci    int32_t ret;
266094332d3Sopenharmony_ci
267094332d3Sopenharmony_ci    CHECK_NULL_PTR_RETURN_VALUE(regGroup, HDF_ERR_INVALID_PARAM);
268094332d3Sopenharmony_ci
269094332d3Sopenharmony_ci    for (uint16_t index = 0; index < groupLen; index++) {
270094332d3Sopenharmony_ci        if (regGroup[index].regLen == 1) {
271094332d3Sopenharmony_ci            ret = Cs1262WriteReg(regGroup[index].regAddr, regGroup[index].regVal);
272094332d3Sopenharmony_ci        } else {
273094332d3Sopenharmony_ci            ret = Cs1262WriteRegs(regGroup[index].regAddr, regGroup[index].regValGroup, regGroup[index].regLen);
274094332d3Sopenharmony_ci        }
275094332d3Sopenharmony_ci
276094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
277094332d3Sopenharmony_ci            HDF_LOGE("%s: failed, index = %u", __func__, index);
278094332d3Sopenharmony_ci            return HDF_FAILURE;
279094332d3Sopenharmony_ci        }
280094332d3Sopenharmony_ci    }
281094332d3Sopenharmony_ci
282094332d3Sopenharmony_ci    return HDF_SUCCESS;
283094332d3Sopenharmony_ci}
284