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, ®Data, 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, ®Data, 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