bos0614_mmi: added features

Added the following features:

  1) BOS0614 registers dump sysfs
  2) reading device tree and applying default config
     in case of power cut

Change-Id: I53f1b7069ea4d74aa8b02ac525765951fe29bcce
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1889879
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Ling Jin <lingjin@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2021-03-01 19:11:17 -06:00 • committed by Konstantin Makariev
commit dc86c37e42
9 changed files with 384 additions and 4374 deletions

View file

@ -21,6 +21,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#define pr_fmt(fmt) "bos0614: %s: " fmt, __func__
#define DEBUG
//#undef DEBUG
#include <linux/init.h>
#include <linux/module.h>
@ -34,62 +38,12 @@
#include "libs/dk-core/src/bsp/drivers/i2c/i2c.h"
#include "libs/dk-core/src/bsp/drivers/haptic/bos0614Driver.h"
enum {
PARAM_UCHAR8 = 1,
PARAM_INT16,
PARAM_UINT16,
PARAM_INT32,
PARAM_UINT32
};
typedef struct {
int tid;
void *data_ptr;
} ParamsLst;
#define PARAM_ADD(t, v) {\
params[numP].tid = t;\
params[numP].data_ptr = v;\
numP++;\
}
static int process_params(ParamsLst *params, int numP, const char *buffer)
{
char *arg, *buf, *p;
int n, err;
buf = kstrdup(buffer, GFP_KERNEL);
for (n = 0; n < numP && p && *p; n++, params++) {
arg = strsep(&p, " ");
if (!arg || !*arg)
break;
switch (params->tid) {
case PARAM_UCHAR8:
err = kstrtou8(arg, 0, params->data_ptr);
break;
case PARAM_INT16:
err = kstrtos16(arg, 0, params->data_ptr);
break;
case PARAM_UINT16:
err = kstrtou16(arg, 0, params->data_ptr);
break;
case PARAM_INT32:
err = kstrtoint(arg, 0, params->data_ptr);
break;
case PARAM_UINT32:
err = kstrtouint(arg, 0, params->data_ptr);
break;
}
if (err) {
n = err;
break;
}
}
kfree(buf);
return n;
}
#ifdef DEBUG
#undef pr_debug
#define pr_debug pr_err
#undef dev_dbg
#define dev_dbg dev_info
#endif
typedef struct
{
@ -132,6 +86,40 @@ static ssize_t getChipId(struct device *dev,
static DEVICE_ATTR(chip_id, 0440, getChipId, NULL);
static ssize_t getRegsDump(struct device *dev,
struct device_attribute *attr, char *buf)
{
Context *ctx = dev_get_drvdata(dev);
ssize_t blen = 0;
(void) attr;
if (ctx != NULL)
{
mutex_lock(&ctx->lock);
if (ctx->hapticDriver != NULL)
{
bool res;
u16 r, rval;
/* dump first 42 registers */
for (r = 0; r < ADDRESS_BOS0614_BIST_REG; r++) {
rval = 0x2bad;
res = ctx->hapticDriver->getRegister(ctx->hapticDriver, r, &rval);
blen += snprintf(buf + blen, PAGE_SIZE - blen,
"%02X: 0x%02X 0x%02X\n", r,
(rval & 0xFF00) >> 8,
(rval & 0x00FF));
}
}
mutex_unlock(&ctx->lock);
}
return blen;
}
static DEVICE_ATTR(regs, 0440, getRegsDump, NULL);
static bool hasError(BOSError *errors, size_t length, BOSError errorType)
{
size_t index;
@ -161,18 +149,19 @@ static ssize_t getIcErrors(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver = ctx->hapticDriver;
size_t nbrErros;
BOSError *errors;
errors = kzalloc(sizeof(BOSError) * BOSERROR_Length, GFP_KERNEL);
if (!errors)
return res;
mutex_lock(&ctx->lock);
errors = kzalloc(sizeof(BOSError) * BOSERROR_Length, GFP_KERNEL);
nbrErros = driver->getError(driver, errors, BOSERROR_Length);
if (errors != NULL)
{
HapticDriver *driver = ctx->hapticDriver;
size_t nbrErros = driver->getError(driver, errors, BOSERROR_Length);
res = snprintf(buf, PAGE_SIZE, "SC: %d UVLO: %d IDAC: %d MAX_POWER: %d OVT: %d OVV: %d\n",
res = snprintf(buf, PAGE_SIZE, "SC: %d UVLO: %d IDAC: %d MAX_POWER: %d OVT: %d OVV: %d\n",
hasError(errors, nbrErros, BOSERROR_SHORT_CIRCUIT),
hasError(errors, nbrErros, BOSERROR_UVLO),
hasError(errors, nbrErros, BOSERROR_IDAC),
@ -180,9 +169,7 @@ static ssize_t getIcErrors(struct device *dev,
hasError(errors, nbrErros, BOSERROR_OVT),
hasError(errors, nbrErros, BOSERROR_OVV));
kfree(errors);
}
kfree(errors);
mutex_unlock(&ctx->lock);
}
@ -202,6 +189,7 @@ static ssize_t setSynthWaveform(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver = ctx->hapticDriver;
WaveformId id = 0;
uint8_t startSliceId = 0;
size_t nbrOfSlices = 0;
@ -209,7 +197,7 @@ static ssize_t setSynthWaveform(struct device *dev,
uint8_t outputChannel = 0;
size_t paramLength = 0;
int numP = 0;
ParamsLst params[5];
ParamsLst params[SET_WAVEFORM_PARAM_LENGTH];
PARAM_ADD(PARAM_UCHAR8, &id);
PARAM_ADD(PARAM_UCHAR8, &startSliceId);
@ -217,27 +205,20 @@ static ssize_t setSynthWaveform(struct device *dev,
PARAM_ADD(PARAM_UINT16, &cycle);
PARAM_ADD(PARAM_UCHAR8, &outputChannel);
mutex_lock(&ctx->lock);
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
mutex_unlock(&ctx->lock);
if (paramLength != SET_WAVEFORM_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%hh %hi %zi %hi %hi", &id, &startSliceId,
// &nbrOfSlices, &cycle, &outputChannel);
dev_dbg(ctx->dev,
"[Set Synth Waveform] Waveform Id: %d Start Slice Id: %d Nbr Of Slices: %zu Cycle: %d Output Channel: %d\n",
id, startSliceId, nbrOfSlices, cycle, outputChannel);
if (paramLength == SET_WAVEFORM_PARAM_LENGTH)
{
HapticDriver *driver = ctx->hapticDriver;
mutex_lock(&ctx->lock);
if (driver->synthSetWaveform(driver, id, startSliceId, nbrOfSlices, cycle, outputChannel))
{
res = count;
}
if (driver->synthSetWaveform(driver, id, startSliceId, nbrOfSlices, cycle, outputChannel))
{
res = count;
}
mutex_unlock(&ctx->lock);
@ -258,35 +239,31 @@ static ssize_t setSynthSlice(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver;
HapticDriver *driver = ctx->hapticDriver;
SynthSlice slice;
uint8_t outputChannel = 0;
size_t paramLength = 0;
int numP = 0;
ParamsLst params[4];
ParamsLst params[SET_SLICE_PARAM_LENGTH];
PARAM_ADD(PARAM_UINT32, &slice.sliceId);
PARAM_ADD(PARAM_INT32, &slice.mVAmp);
PARAM_ADD(PARAM_UINT32, &slice.mHzFreq);
PARAM_ADD(PARAM_UINT32, &slice.cycle);
PARAM_ADD(PARAM_UCHAR8, &outputChannel);
mutex_lock(&ctx->lock);
driver = ctx->hapticDriver;
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
mutex_unlock(&ctx->lock);
if (paramLength != SET_SLICE_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%d %d %d %d %d", &slice.sliceId, &slice.mVAmp,
// &slice.mHzFreq, &slice.cycle, &outputChannel);
dev_dbg(ctx->dev,
"[Set Slice] Slice Id: %d Amplitude: %d mV Frequency: %d milliHertz Cycle: %d Output Channel: %d\n",
slice.sliceId, slice.mVAmp, slice.mHzFreq, slice.cycle, outputChannel);
if (paramLength == SET_SLICE_PARAM_LENGTH &&
driver->synthSetSlice(driver, (const SynthSlice *) &slice, outputChannel))
mutex_lock(&ctx->lock);
if (driver->synthSetSlice(driver, (const SynthSlice *) &slice, outputChannel))
{
res = count;
}
@ -310,26 +287,24 @@ static ssize_t synthPlay(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver;
HapticDriver *driver = ctx->hapticDriver;
WaveformId start = 0;
WaveformId stop = 0;
size_t paramLength = 0;
int numP = 0;
ParamsLst params[2];
ParamsLst params[SYNTH_PLAY_PARAM_LENGTH];
PARAM_ADD(PARAM_UCHAR8, &start);
PARAM_ADD(PARAM_UCHAR8, &stop);
driver = ctx->hapticDriver;
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
mutex_unlock(&ctx->lock);
if (paramLength != SYNTH_PLAY_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%hi %hi", &start, &stop);
if (paramLength == SYNTH_PLAY_PARAM_LENGTH && driver->wfsPlay(driver, start, stop))
mutex_lock(&ctx->lock);
if (driver->wfsPlay(driver, start, stop))
{
res = count;
}
@ -352,27 +327,25 @@ static ssize_t setOutput(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver;
HapticDriver *driver = ctx->hapticDriver;
int outputState = 0;
size_t paramLength = 0;
bool bOutputState = outputState > 0 ? true : false;
bool bOutputState;
int numP = 0;
ParamsLst params[1];
ParamsLst params[CTRL_OUTPUT_PARAM_LENGTH];
PARAM_ADD(PARAM_INT32, &outputState);
mutex_lock(&ctx->lock);
driver = ctx->hapticDriver;
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
mutex_unlock(&ctx->lock);
if (paramLength != CTRL_OUTPUT_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%d", &outputState);
if (paramLength == CTRL_OUTPUT_PARAM_LENGTH &&
driver->ctrlOutput(driver, bOutputState))
bOutputState = outputState > 0 ? true : false;
mutex_lock(&ctx->lock);
if (driver->ctrlOutput(driver, bOutputState))
{
dev_dbg(ctx->dev,
"[Set Output] State: %d \n", bOutputState);
@ -440,37 +413,33 @@ static ssize_t setSensingConfig(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver;
HapticDriver *driver = ctx->hapticDriver;
SensingConfig config;
ChannelId channelId = 0;
size_t paramLength = 0;
const char *directionS = getSensingDirection(config.direction);
const char *modeS = getSensingDetectionMode(config.mode);
const char *directionS;
const char *modeS;
int numP = 0;
ParamsLst params[6];
ParamsLst params[SENSING_CONFIG_PARAM_LENGTH];
PARAM_ADD(PARAM_UCHAR8, &channelId);
PARAM_ADD(PARAM_UCHAR8, &config.mode);
PARAM_ADD(PARAM_UCHAR8, &config.direction);
PARAM_ADD(PARAM_UINT16, &config.debounceUs);
PARAM_ADD(PARAM_UINT16, &config.thresholdMv);
PARAM_ADD(PARAM_INT16, &config.thresholdMv);
PARAM_ADD(PARAM_UCHAR8, &config.stabilisationMs);
mutex_lock(&ctx->lock);
driver = ctx->hapticDriver;
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
mutex_unlock(&ctx->lock);
if (paramLength != SENSING_CONFIG_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%hhu %d %d %hd %hd %s", &channelId, &config.mode,
// &config.direction, &config.debounceUs,
// &config.thresholdMv, &config.stabilisationMs);
if (paramLength == SENSING_CONFIG_PARAM_LENGTH &&
directionS != NULL &&
modeS != NULL &&
directionS = getSensingDirection(config.direction);
modeS = getSensingDetectionMode(config.mode);
mutex_lock(&ctx->lock);
if (directionS != NULL && modeS != NULL &&
driver->configSensing(driver, channelId, config) &&
ctx->hapticDriver->configGPO(ctx->hapticDriver, channelId, GPO_ButtonState))
{
@ -499,32 +468,29 @@ static ssize_t setSensingAutoPlay(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver;
HapticDriver *driver = ctx->hapticDriver;
ChannelId channelId = 0;
WaveformId id = 0;
SensingDirection direction = 0;
size_t paramLength = 0;
const char *directionS;
int numP = 0;
ParamsLst params[3];
ParamsLst params[SENSING_AUTO_FEEDBACK_PARAM_LENGTH];
PARAM_ADD(PARAM_UCHAR8, &channelId);
PARAM_ADD(PARAM_UCHAR8, &id);
PARAM_ADD(PARAM_UCHAR8, &direction);
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
if (paramLength != SENSING_AUTO_FEEDBACK_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%d %d %d", &channelId, &id, &direction);
directionS = getSensingDirection(direction);
mutex_lock(&ctx->lock);
driver = ctx->hapticDriver;
if (paramLength == SENSING_AUTO_FEEDBACK_PARAM_LENGTH &&
directionS != NULL &&
if (directionS != NULL &&
driver->sensingAutoPlayWave(driver, channelId, id, direction))
{
dev_dbg(ctx->dev, "[Set Sensing Automatic Feedback] Channel #: %d Waveform #: %d Direction: %s", channelId,
@ -551,29 +517,27 @@ static ssize_t stopSensing(struct device *dev,
if (ctx != NULL && ctx->hapticDriver != NULL)
{
HapticDriver *driver;
HapticDriver *driver = ctx->hapticDriver;
ChannelId channelId = 0;
SensingDirection direction = 0;
const char *directionS;
size_t paramLength = 0;
int numP = 0;
ParamsLst params[2];
ParamsLst params[STOP_SENSING_PARAM_LENGTH];
PARAM_ADD(PARAM_UCHAR8, &channelId);
PARAM_ADD(PARAM_UCHAR8, &direction);
paramLength = process_params(params, numP, buf);
if (paramLength < 0) {
if (paramLength != STOP_SENSING_PARAM_LENGTH) {
return (ssize_t)paramLength;
}
//paramLength = sscanf(buf, "%d %d", &channelId, &direction);
directionS = getSensingDirection(direction);
mutex_lock(&ctx->lock);
driver = ctx->hapticDriver;
if (paramLength == STOP_SENSING_PARAM_LENGTH &&
directionS != NULL &&
if (directionS != NULL &&
driver->stopSensing(driver, channelId, direction))
{
dev_dbg(ctx->dev, "[Remove Sensing Profile] Channel #: %d Direction: %s", channelId, directionS);
@ -592,6 +556,7 @@ static DEVICE_ATTR(sensing_stop, 0220, NULL, stopSensing);
static struct attribute *bosDriverAttrs[] = {
&dev_attr_chip_id.attr,
&dev_attr_regs.attr,
&dev_attr_set_waveform.attr,
&dev_attr_set_slice.attr,
&dev_attr_synth_play.attr,
@ -666,6 +631,8 @@ static int bosDriverI2cProbe(struct i2c_client *client,
resource.i2c = ctx->i2c;
ctx->hapticDriver = bos0614DriverI2cInit(resource);
pr_debug("i2c: %p, driver: %p\n", ctx->i2c, ctx->hapticDriver);
if (ctx->i2c == NULL || ctx->hapticDriver == NULL)
{
dev_err(&client->dev, "Failed to instantiate BOS0614 driver\n");
@ -757,13 +724,13 @@ static struct i2c_driver bosDriverI2c = {
#ifdef CONFIG_OF
static int __init bosDriver_init(void)
{
pr_info("%s: loading driver\n", __func__);
pr_debug("loading driver\n");
return i2c_add_driver(&bosDriverI2c);
}
static void __exit bosDriver_exit(void)
{
pr_info("%s: removing driver\n", __func__);
pr_debug("removing driver\n");
i2c_del_driver(&bosDriverI2c);
}

View file

@ -21,6 +21,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#define pr_fmt(fmt) "bos0614: %s: " fmt, __func__
#define DEBUG
//#undef DEBUG
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@ -28,6 +33,13 @@
#include "i2cLinux.h"
#ifdef DEBUG
#undef pr_debug
#define pr_debug pr_err
#undef dev_dbg
#define dev_dbg dev_err
#endif
typedef struct
{
I2c driver;
@ -39,6 +51,124 @@ static void initDriverFct(Context *ctx);
#define NBR_CHAR_PER_BYTE (5)
#define ESCAPE_CHAR (1)
int process_params(ParamsLst *params, int numP, const char *buffer)
{
char *arg, *buf, *p;
int n, err;
unsigned int value;
p = buf = kstrdup(buffer, GFP_KERNEL);
for (n = 0; n < numP && p && *p; n++, params++) {
arg = strsep(&p, " ");
if (!arg || !*arg)
break;
pr_debug("arg=[%s] rest=[%s]\n", arg, p);
switch (params->tid) {
case PARAM_UCHAR8:
err = kstrtou8(arg, 0, params->data_ptr);
value = (unsigned int)*(unsigned char *)params->data_ptr;
break;
case PARAM_INT16:
err = kstrtos16(arg, 0, params->data_ptr);
value = (unsigned int)*(short *)params->data_ptr;
break;
case PARAM_UINT16:
err = kstrtou16(arg, 0, params->data_ptr);
value = (unsigned int)*(unsigned short *)params->data_ptr;
break;
case PARAM_INT32:
err = kstrtoint(arg, 0, params->data_ptr);
value = (unsigned int)*(int *)params->data_ptr;
break;
case PARAM_UINT32:
err = kstrtouint(arg, 0, params->data_ptr);
value = *(unsigned int *)params->data_ptr;
break;
}
if (err) {
n = err;
break;
} else
pr_debug("[%d]=%u\n", n, value);
}
kfree(buf);
pr_debug("processed %d input parameters\n", n);
return n;
}
#if 0
static int readRegsConfig(Context *ctx, struct device_node *parent, const char *suffix)
{
Bos0614RegisterStruct *config = getAllRegsPtr();
struct device_node *node;
char node_name[64];
u32 *temp, length = 0;
int npairs, i, index, ret = -EIO;
scnprintf(node_name, 63, "config-%s", suffix);
node = of_find_node_by_name(parent, node_name);
if (!node)
return -ENODEV;
if (!of_find_property(node, "config-data", &length)) {
dev_err(&ctx->client->dev, "(config-%s) prop config-data not found\n", suffix);
goto out;
}
npairs = length / 2;
dev_info(&ctx->client->dev, "(config-%s) array size %d\n", suffix, npairs);
temp = kzalloc(length, GFP_KERNEL);
if (!temp)
goto out;
ret = of_property_read_u32_array(node, "config-data", temp, sizeof(u32) * npairs * 2);
if (ret) {
dev_err(&ctx->client->dev, "error reading config-data (config-%s)\n", suffix);
goto release_mem;
}
for (i = 0; i < npairs; i++) {
index =(uint16_t)*temp++;
config[index].value = (uint16_t)*temp++;
dev_info(&ctx->client->dev, "[%d] addr=0x%02x, val=0x%04x\n",
i, config[index].addr, config[index].value);
}
release_mem:
kfree(temp);
out:
of_node_put(node);
return ret;
}
static int readDevTree(Context *ctx)
{
int ret, verno;
struct device_node *np = ctx->client->dev.of_node;
struct device_node *config_np;
config_np = of_find_node_by_name(np, "configs");
if (!config_np) {
dev_info(&ctx->client->dev, "does not support configs\n");
return 0;
}
if (!of_property_read_u32(config_np, "config-ver", &verno))
dev_info(&ctx->client->dev, "dt config Rev.%u\n", verno);
ret = readRegsConfig(ctx, config_np, "default");
if (ret > 0)
dev_info(&ctx->client->dev, "has default config\n");
of_node_put(config_np);
return 0;
}
#endif
static void logBuffer(const char *message, const void *data, size_t length)
{
size_t bufferLength = length * NBR_CHAR_PER_BYTE + ESCAPE_CHAR;
@ -57,15 +187,13 @@ static void logBuffer(const char *message, const void *data, size_t length)
ptr += sprintf(ptr, index < (length - 1) ? "0x%02x " : "0x%02x", _data[index]);
}
//printk("%s length: %zu [%s]\n", message, length, buf, bufferLength, ptr, end);
printk("%s length: %zu [%s]\n", message, length, buf);
pr_debug("%s length: %zu [%s]\n", message, length, buf);
kfree(buf);
}
}
/*
* Private Section
*/
@ -142,16 +270,20 @@ I2c *i2cBoreasLinuxInit(struct i2c_client *client)
{
Context *ctx = kzalloc(sizeof(Context), GFP_KERNEL);
printk("[PF-Debug] I2C Client %p", client);
if (ctx != NULL)
{
ctx->client = client;
initDriverFct(ctx);
driver = &ctx->driver;
#if 0
if (ctx->client->dev.of_node)
readDevTree(ctx);
#endif
}
}
pr_debug("I2C client: %p, driver: %p\n", client, driver);
return driver;
}

View file

@ -25,8 +25,31 @@
#ifndef BOREAS_HAPTIC_DRIVER_LINUX_I2CLINUX_H
#define BOREAS_HAPTIC_DRIVER_LINUX_I2CLINUX_H
#include <linux/device.h>
#include <linux/i2c.h>
#include "libs/dk-core/src/bsp/drivers/i2c/i2c.h"
#include "libs/dk-core/src/bsp/drivers/haptic/bos0614Driver.h"
enum {
PARAM_UCHAR8 = 1,
PARAM_INT16,
PARAM_UINT16,
PARAM_INT32,
PARAM_UINT32
};
typedef struct {
int tid;
void *data_ptr;
} ParamsLst;
#define PARAM_ADD(t, v) {\
params[numP].tid = t;\
params[numP].data_ptr = v;\
numP++;\
}
int process_params(ParamsLst *params, int numP, const char *buffer);
I2c *i2cBoreasLinuxInit(struct i2c_client *client);

View file

@ -1,21 +0,0 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text
*.txt text
*.xsd text
*.pdsc text
*.svd text
*.bat text
# Declare files that will always have CRLF line endings on checkout.
*.uvproj text eol=crlf
*.uvproj text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.a filter=lfs diff=lfs merge=lfs -text
*.lib filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
CMSIS/Utilities/Linux-gcc-*/* filter=lfs diff=lfs merge=lfs -text

View file

@ -1,10 +0,0 @@
*.breadcrumb
*.junit
**/__pycache__
Local_Release/
CMSIS/Documentation/
CMSIS/RTOS2/RTX/Library/ARM/MDK/RTX_CM.uvguix.*
CMSIS/CoreValidation/Tests/build
CMSIS/CoreValidation/Tests/bootloader/build
*.uvguix.*
*.uvmpw.uvgui.*

View file

@ -1,50 +0,0 @@
pdsc: ARM.CMSIS.pdsc
preproc:
- clean: CMSIS/Documentation/(Core,Core_A,DAP,Driver,DSP,NN,General,Pack,RTOS,RTOS2,SVD,Zone)
- doxygen: CMSIS/DoxyGen/Core/core.dxy
- doxygen: CMSIS/DoxyGen/Core_A/core_A.dxy
- doxygen: CMSIS/DoxyGen/DAP/dap.dxy
- doxygen: CMSIS/DoxyGen/Driver/Driver.dxy
- doxygen: CMSIS/DoxyGen/DSP/dsp.dxy
- doxygen: CMSIS/DoxyGen/General/general.dxy
- doxygen: CMSIS/DoxyGen/NN/nn.dxy
- doxygen: CMSIS/DoxyGen/Pack/Pack.dxy
- doxygen: CMSIS/DoxyGen/RTOS/rtos.dxy
- doxygen: CMSIS/DoxyGen/RTOS2/rtos.dxy
- doxygen: CMSIS/DoxyGen/SVD/svd.dxy
- doxygen: CMSIS/DoxyGen/Zone/zone.dxy
glob:
- LICENSE.txt
- Device/**/*
- CMSIS/Core/Include/**/*
- CMSIS/Core/Include/**/*: CMSIS/Include/
- CMSIS/Core/Template/**/*
- CMSIS/Core_A/**/*
- CMSIS/DAP/**/*
- CMSIS/Driver/**/*
- CMSIS/DSP/Include/**/*
- CMSIS/DSP/Source/**/*
- CMSIS/DSP/Projects/**/*
- CMSIS/DSP/Examples/**/*
- CMSIS/DSP/Include/**/*: CMSIS/Include/
- CMSIS/DSP/Lib/**/*
- CMSIS/NN/**/*
- CMSIS/Pack/**/*
- CMSIS/RTOS/**/*
- CMSIS/RTOS2/**/*
- CMSIS/Utilities/ARM_Example.*: CMSIS/SVD/ARM_Example.
- CMSIS/Utilities/CMSIS-SVD.xsd
- CMSIS/Utilities/PACK.xsd
- CMSIS/Utilities/PackIndex.xsd
- CMSIS/Utilities/Win32/**/*
- CMSIS/Utilities/Linux-gcc-4.4.4/**/*
- CMSIS/Utilities/Linux-gcc-4.8.3/**/*
- CMSIS/Documentation/**/*
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/Core/html/search/search.css
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/Core_A/html/search/search.css
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/Driver/html/search/search.css
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/Pack/html/search/search.css
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/DSP/html/search/search.css
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/DAP/html/search/search.css
- CMSIS/DoxyGen/Doxygen_Templates/search.css: CMSIS/Documentation/NN/html/search/search.css
- CMSIS/DoxyGen/Zone/genmodel/**/*: CMSIS/Documentation/Zone/genmodel/

View file

@ -23,6 +23,9 @@
//
#define pr_fmt(fmt) "bos0614: %s: " fmt, __func__
#define DEBUG
//#undef DEBUG
#include <linux/string.h>
#include <linux/slab.h>
@ -31,8 +34,15 @@
#include "bsp/boards/boreasTime.h"
#include "bsp/drivers/i2c/i2c.h"
#include "bsp/drivers/haptic/bos0614Driver.h"
#include "bsp/drivers/haptic/bos0614Register.h"
#include "bsp/drivers/haptic/bos0614Driver.h"
#ifdef DEBUG
#undef pr_debug
#define pr_debug pr_info
#undef dev_dbg
#define dev_dbg dev_info
#endif
#define BOS0614_CHIP_ID (0x0D)
#define BOS0614_I2C_ADDRESS (0x2c)
@ -182,6 +192,7 @@ static bool resetSoftware(Context *ctx)
{
bool res;
pr_debug("enter\n");
ctx->reg.CONFIG_0614.bit.RST = 0x1;
res = writeReg(ctx, &ctx->reg.CONFIG_0614.reg);
@ -622,6 +633,8 @@ static bool validateIcWorking(Context *ctx)
res = res && readRegister(ctx, &ctx->reg.CONFIG_0614.reg);
res = res && ctx->reg.CONFIG_0614.bit.PLAY == bos0614SamplingRate_512Ksps;
pr_debug("ic is%s working!!!\n", res ? "" : " NOT");
return res;
}
@ -1780,78 +1793,85 @@ static BOS0614_REGS bOS0614Regs =
.REG47_0614.reg.generic.addr = ADDRESS_BOS0614_REG47_REG,
};
static uint8_t regAddrToRead[] = {ADDRESS_BOS0614_REFERENCE_REG,
ADDRESS_BOS0614_IC_STATUS_REG,
ADDRESS_BOS0614_READ_REG,
ADDRESS_BOS0614_GPIOX_REG,
ADDRESS_BOS0614_TC_REG,
ADDRESS_BOS0614_CONFIG_REG,
ADDRESS_BOS0614_SENSECONFIG_REG,
ADDRESS_BOS0614_SENSE0_REG,
ADDRESS_BOS0614_SENSE0P_REG,
ADDRESS_BOS0614_SENSE0R_REG,
ADDRESS_BOS0614_SENSE0S_REG,
ADDRESS_BOS0614_SENSE1_REG,
ADDRESS_BOS0614_SENSE1P_REG,
ADDRESS_BOS0614_SENSE1R_REG,
ADDRESS_BOS0614_SENSE1S_REG,
ADDRESS_BOS0614_SENSE2_REG,
ADDRESS_BOS0614_SENSE2P_REG,
ADDRESS_BOS0614_SENSE2R_REG,
ADDRESS_BOS0614_SENSE2S_REG,
ADDRESS_BOS0614_SENSE3_REG,
ADDRESS_BOS0614_SENSE3P_REG,
ADDRESS_BOS0614_SENSE3R_REG,
ADDRESS_BOS0614_SENSE3S_REG,
ADDRESS_BOS0614_SENSESTATUS_REG,
ADDRESS_BOS0614_SENSEDATA0_REG,
ADDRESS_BOS0614_SENSEDATA1_REG,
ADDRESS_BOS0614_SENSEDATA2_REG,
ADDRESS_BOS0614_SENSEDATA3_REG,
ADDRESS_BOS0614_SENSERAW0_REG,
ADDRESS_BOS0614_SENSERAW1_REG,
ADDRESS_BOS0614_SENSERAW2_REG,
ADDRESS_BOS0614_SENSERAW3_REG,
ADDRESS_BOS0614_KPA_REG,
ADDRESS_BOS0614_KP_KI_REG,
ADDRESS_BOS0614_DEADTIME_REG,
ADDRESS_BOS0614_PARCAP_REG,
ADDRESS_BOS0614_SUP_RISE_REG,
ADDRESS_BOS0614_TRIM_REG,
ADDRESS_BOS0614_CHIP_ID_REG,
ADDRESS_BOS0614_VFEEDBACK_REG,
ADDRESS_BOS0614_FIFO_STATE_REG,
ADDRESS_BOS0614_AUTO_STATE_REG,
ADDRESS_BOS0614_BIST_REG,
ADDRESS_BOS0614_BISTRES_REG,
ADDRESS_BOS0614_DEBUG_REG,
ADDRESS_BOS0614_THRESH_REG,
ADDRESS_BOS0614_REG38_REG,
ADDRESS_BOS0614_REG39_REG,
ADDRESS_BOS0614_CALIB_DATA_REG,
ADDRESS_BOS0614_REG3B_REG,
ADDRESS_BOS0614_REG3C_REG,
ADDRESS_BOS0614_REG3D_REG,
ADDRESS_BOS0614_REG3E_REG,
ADDRESS_BOS0614_REG3F_REG,
ADDRESS_BOS0614_REG40_REG,
ADDRESS_BOS0614_REG41_REG,
ADDRESS_BOS0614_REG42_REG,
ADDRESS_BOS0614_REG43_REG,
ADDRESS_BOS0614_REG44_REG,
ADDRESS_BOS0614_REG45_REG,
ADDRESS_BOS0614_REG46_REG,
ADDRESS_BOS0614_REG47_REG};
static Bos0614RegisterStruct regToRead[] = {
{.addr = ADDRESS_BOS0614_REFERENCE_REG,},
{.addr = ADDRESS_BOS0614_IC_STATUS_REG,},
{.addr = ADDRESS_BOS0614_READ_REG,},
{.addr = ADDRESS_BOS0614_GPIOX_REG,},
{.addr = ADDRESS_BOS0614_TC_REG,},
{.addr = ADDRESS_BOS0614_CONFIG_REG,},
{.addr = ADDRESS_BOS0614_SENSECONFIG_REG,},
{.addr = ADDRESS_BOS0614_SENSE0_REG,},
{.addr = ADDRESS_BOS0614_SENSE0P_REG,},
{.addr = ADDRESS_BOS0614_SENSE0R_REG,},
{.addr = ADDRESS_BOS0614_SENSE0S_REG,},
{.addr = ADDRESS_BOS0614_SENSE1_REG,},
{.addr = ADDRESS_BOS0614_SENSE1P_REG,},
{.addr = ADDRESS_BOS0614_SENSE1R_REG,},
{.addr = ADDRESS_BOS0614_SENSE1S_REG,},
{.addr = ADDRESS_BOS0614_SENSE2_REG,},
{.addr = ADDRESS_BOS0614_SENSE2P_REG,},
{.addr = ADDRESS_BOS0614_SENSE2R_REG,},
{.addr = ADDRESS_BOS0614_SENSE2S_REG,},
{.addr = ADDRESS_BOS0614_SENSE3_REG,},
{.addr = ADDRESS_BOS0614_SENSE3P_REG,},
{.addr = ADDRESS_BOS0614_SENSE3R_REG,},
{.addr = ADDRESS_BOS0614_SENSE3S_REG,},
{.addr = ADDRESS_BOS0614_SENSESTATUS_REG,},
{.addr = ADDRESS_BOS0614_SENSEDATA0_REG,},
{.addr = ADDRESS_BOS0614_SENSEDATA1_REG,},
{.addr = ADDRESS_BOS0614_SENSEDATA2_REG,},
{.addr = ADDRESS_BOS0614_SENSEDATA3_REG,},
{.addr = ADDRESS_BOS0614_SENSERAW0_REG,},
{.addr = ADDRESS_BOS0614_SENSERAW1_REG,},
{.addr = ADDRESS_BOS0614_SENSERAW2_REG,},
{.addr = ADDRESS_BOS0614_SENSERAW3_REG,},
{.addr = ADDRESS_BOS0614_KPA_REG,},
{.addr = ADDRESS_BOS0614_KP_KI_REG,},
{.addr = ADDRESS_BOS0614_DEADTIME_REG,},
{.addr = ADDRESS_BOS0614_PARCAP_REG,},
{.addr = ADDRESS_BOS0614_SUP_RISE_REG,},
{.addr = ADDRESS_BOS0614_TRIM_REG,},
{.addr = ADDRESS_BOS0614_CHIP_ID_REG,},
{.addr = ADDRESS_BOS0614_VFEEDBACK_REG,},
{.addr = ADDRESS_BOS0614_FIFO_STATE_REG,},
{.addr = ADDRESS_BOS0614_AUTO_STATE_REG,},
{.addr = ADDRESS_BOS0614_BIST_REG,},
{.addr = ADDRESS_BOS0614_BISTRES_REG,},
{.addr = ADDRESS_BOS0614_DEBUG_REG,},
{.addr = ADDRESS_BOS0614_THRESH_REG,},
{.addr = ADDRESS_BOS0614_REG38_REG,},
{.addr = ADDRESS_BOS0614_REG39_REG,},
{.addr = ADDRESS_BOS0614_CALIB_DATA_REG,},
{.addr = ADDRESS_BOS0614_REG3B_REG,},
{.addr = ADDRESS_BOS0614_REG3C_REG,},
{.addr = ADDRESS_BOS0614_REG3D_REG,},
{.addr = ADDRESS_BOS0614_REG3E_REG,},
{.addr = ADDRESS_BOS0614_REG3F_REG,},
{.addr = ADDRESS_BOS0614_REG40_REG,},
{.addr = ADDRESS_BOS0614_REG41_REG,},
{.addr = ADDRESS_BOS0614_REG42_REG,},
{.addr = ADDRESS_BOS0614_REG43_REG,},
{.addr = ADDRESS_BOS0614_REG44_REG,},
{.addr = ADDRESS_BOS0614_REG45_REG,},
{.addr = ADDRESS_BOS0614_REG46_REG,},
{.addr = ADDRESS_BOS0614_REG47_REG,},
};
Bos0614RegisterStruct *getAllRegsPtr(void)
{
return regToRead;
}
static bool readAllRegister(Context *ctx)
{
uint32_t index;
bool res = true;
for (index = 0; index < DATA_ARRAY_LENGTH(regAddrToRead) && res; index++)
for (index = 0; index < DATA_ARRAY_LENGTH(regToRead) && res; index++)
{
uint16_t dummy;
res = bos0614GetRegister(&ctx->hDriver, regAddrToRead[index], &dummy);
res = bos0614GetRegister(&ctx->hDriver, regToRead[index].addr, &dummy);
}
return res;
@ -1861,10 +1881,22 @@ static bool setDefaultConfig(Context *ctx)
{
bool res = true;
//Reset configuration of the register;
pr_debug("enter\n");
//No need to copy registers again here!!!
memcpy(&ctx->reg, &bOS0614Regs, sizeof(bOS0614Regs));
//Why do we need to do a dummy read???
res = readAllRegister(ctx);
//bosDriverI2cProbe calls i2cBoreasLinuxInit
// i2cBoreasLinuxInit calls readDeviceTree
// readDeviceTree populates regToRead with default configuration
//
//Read SENSECONFIG to determine whether power cut occurred
//and necessary to apply default config provided in device tree
res = readRegister(ctx, &ctx->reg.SENSECONFIG_0614.reg);
res = res && ctx->reg.SENSECONFIG_0614.reg.generic.value == regToRead[ADDRESS_BOS0614_SENSECONFIG_REG].value;
ctx->reg.SENSECONFIG_0614.bit.CH0 = BOS0614_DISABLE;
ctx->reg.SENSECONFIG_0614.bit.CH1 = BOS0614_DISABLE;
ctx->reg.SENSECONFIG_0614.bit.CH2 = BOS0614_DISABLE;
@ -1875,12 +1907,21 @@ static bool setDefaultConfig(Context *ctx)
ctx->reg.SENSECONFIG_0614.reg.generic.addr,
ctx->reg.SENSECONFIG_0614.reg.generic.value);
// Bos0614Register *reg[] = {&ctx->reg.SENSECONFIG_0614.reg};
// for (uint32_t index = 0; index < DATA_ARRAY_LENGTH(reg); index++)
// {
// res = res && ctx->hDriver.setRegister(&ctx->hDriver, reg[index]->generic.addr,
// reg[index]->generic.value);
// }
//This happens when SENSECONFIG register value from IC
//won't match config from device tree
if (res == false)
{
uint32_t index;
res = true;
for (index = 0; index < DATA_ARRAY_LENGTH(regToRead); index++)
{
if (regToRead[index].value != 0)
res = res && ctx->hDriver.setRegister(&ctx->hDriver,
regToRead[index].addr,
regToRead[index].value);
}
}
return res;
}

View file

@ -45,5 +45,6 @@ HapticDriver *bos0614DriverI2cInit(Bos0614Resource resources);
HapticDriver *bos0614DriverSpiInit(Spi *spi, Gpio *gpioA, Gpio *gpioD);
Bos0614RegisterStruct *getAllRegsPtr(void);
#endif //DKCORE_BOS0614DRIVER_H