feat: charge: initialize rx charger stwlc38 driver

CHAMPION-25

Signed-off-by: zhangguoliang <zhangguoliang3@xiaomi.com>
Change-Id: Ifa5732ae2160d4bc083f9aaf4e3beb34096b7770
This commit is contained in:
zhangguoliang 2021-09-14 07:41:31 +00:00 committed by zhangguoliang3
parent 7df6d25fc3
commit e6d84fccc9
6 changed files with 1040 additions and 0 deletions

View file

@ -383,6 +383,15 @@ config SC8551
---help---
The SC8551 are battery charger for lithium-ion batteries.
config STWLC38
bool "STWLC38 Battery charger support"
default n
select I2C
select I2C_STWLC38
depends on BATTERY_CHARGER
---help---
The STWLC38 are wireless rx for power supply.
config MCP73871
bool "Microchip MCP73871 Battery charger support"
default n
@ -420,6 +429,16 @@ config DEBUG_SC8551
endif # SC8551
if STWLC38
config DEBUG_STWLC38
bool "STWLC38 Debug Features"
default n
---help---
Enable STWLC38 wireless rx debug features.
endif # STWLC38
config BATTERY_GAUGE
bool "Battery Fuel Gauge support"
default n
@ -482,6 +501,10 @@ config I2C_SC8551
bool
default y if SC8551
config I2C_STWLC38
bool
default y if STWLC38
config I2C_MAX1704X
bool
default y if MAX1704X

View file

@ -103,6 +103,10 @@ ifeq ($(CONFIG_I2C_SC8551),y)
CSRCS += sc8551.c
endif
ifeq ($(CONFIG_I2C_STWLC38),y)
CSRCS += polaris.c
endif
# Add the BQ256XX I2C-based battery charger driver
ifeq ($(CONFIG_I2C_BQ25618),y)

778
drivers/power/polaris.c Normal file
View file

@ -0,0 +1,778 @@
/****************************************************************************
* drivers/power/polaris.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef __POLARIS_C
#define __POLARIS_C
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/config.h>
#include <assert.h>
#include <nuttx/kmalloc.h>
#include <nuttx/signal.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/power/battery_charger.h>
#include <nuttx/power/battery_ioctl.h>
#include "polaris.h"
#include "polaris_nvm.c"
#define PAGE_SIZE 256
#define NO_DEBUG
/* Debug ********************************************************************/
#ifdef CONFIG_DEBUG_STWLC38
# define baterr _err
# define batdbg _err
# define batinfo _err
#else
# define baterr _none
# define batdbg _none
# define batinfo _none
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
static int stwlc38_state(FAR struct battery_charger_dev_s *dev,
FAR int *status);
static int stwlc38_health(FAR struct battery_charger_dev_s *dev,
FAR int *health);
static int stwlc38_online(FAR struct battery_charger_dev_s *dev,
FAR bool *status);
static int stwlc38_voltage(FAR struct battery_charger_dev_s *dev,
int value);
static int stwlc38_current(FAR struct battery_charger_dev_s *dev,
int value);
static int stwlc38_input_current(FAR struct battery_charger_dev_s *dev,
int value);
static int stwlc38_operate(FAR struct battery_charger_dev_s *dev,
uintptr_t param);
static const struct battery_charger_operations_s g_stwlc38ops =
{
stwlc38_state,
stwlc38_health,
stwlc38_online,
stwlc38_voltage,
stwlc38_current,
stwlc38_input_current,
stwlc38_operate,
};
static int stwlc38_state(FAR struct battery_charger_dev_s *dev,
FAR int *status)
{
return ERROR;
}
static int stwlc38_health(FAR struct battery_charger_dev_s *dev,
FAR int *health)
{
return ERROR;
}
static int stwlc38_online(FAR struct battery_charger_dev_s *dev,
FAR bool *status)
{
return ERROR;
}
static int stwlc38_voltage(FAR struct battery_charger_dev_s *dev,
FAR int value)
{
return ERROR;
}
static int stwlc38_current(FAR struct battery_charger_dev_s *dev,
FAR int value)
{
return ERROR;
}
static int stwlc38_input_current(FAR struct battery_charger_dev_s *dev,
FAR int value)
{
return ERROR;
}
static int stwlc38_operate(FAR struct battery_charger_dev_s *dev,
uintptr_t param)
{
return ERROR;
}
struct stwlc38_dev_s
{
/* The common part of the battery driver visible to the upper-half driver */
FAR const struct battery_charger_operations_s *ops; /* Battery operations */
sem_t batsem; /* Enforce mutually exclusive access */
/* Data fields specific to the lower half STWLC38 driver follow */
FAR struct i2c_master_s *i2c; /* I2C interface */
uint8_t addr; /* I2C address */
uint32_t frequency; /* I2C frequency */
};
static uint8_t type_of_command[CMD_STR_LEN] =
{
0
};
static int number_parameters;
static int wlc_i2c_read(FAR struct stwlc38_dev_s *priv, uint8_t *cmd,
int cmd_length, uint8_t *read_data, int read_count)
{
struct i2c_msg_s msg[2];
int err;
FAR struct i2c_master_s *dev = priv->i2c;
#ifdef DEBUG
int i = 0;
#endif
msg[0].addr = priv->addr;
msg[0].buffer = cmd;
msg[0].length = cmd_length;
msg[0].flags = 0;
msg[1].addr = priv->addr;
msg[1].buffer = read_data;
msg[1].length = read_count;
msg[1].flags = I2C_M_READ;
if ((err = I2C_TRANSFER(dev, msg, 2)) < OK)
{
baterr("[WLC] i2c transfer failed! err: %d\n", err);
return err;
}
#ifdef DEBUG
batinfo("[WLC] WR-W: ");
for (i = 0; i < cmd_length; i++)
printk(KERN_CONT "%02X ", cmd[i]);
baterr("[WLC] WR-R: ");
for (i = 0; i < read_count; i++)
printk(KERN_CONT "%02X ", read_data[i]);
#endif
return OK;
}
static int wlc_i2c_write(FAR struct stwlc38_dev_s *priv,
uint8_t *cmd, int cmd_length)
{
struct i2c_msg_s msg[1];
int err;
FAR struct i2c_master_s *dev = priv->i2c;
#ifdef DEBUG
int i = 0;
#endif
msg[0].addr = priv->addr;
msg[0].buffer = cmd;
msg[0].length = cmd_length;
msg[0].flags = 0;
#ifdef DEBUG
batinfo("[WLC] W: ");
for (i = 0; i < cmd_length; i++)
printk(KERN_CONT "%02X ", cmd[i]);
#endif
if ((err = I2C_TRANSFER(dev, msg, 1)) < OK)
{
baterr("[WLC] i2c transfer failed! err: %d\n", err);
return err;
}
return OK;
}
static int hw_i2c_write(FAR struct stwlc38_dev_s *priv, uint32_t addr,
uint8_t *data, uint32_t data_length)
{
uint8_t *cmd;
memset(cmd, 0, (5 + data_length) * sizeof(uint8_t));
cmd[0] = OPCODE_WRITE;
cmd[1] = (uint8_t)((addr >> 24) & 0xff);
cmd[2] = (uint8_t)((addr >> 16) & 0xff);
cmd[3] = (uint8_t)((addr >> 8) & 0xff);
cmd[4] = (uint8_t)((addr >> 0) & 0xff);
memcpy(&cmd[5], data, data_length);
if ((wlc_i2c_write(priv, cmd, (5 + data_length))) < OK)
{
baterr("[WLC] Error in writing Hardware I2c!\n");
kmm_free(cmd);
return E_BUS_W;
}
kmm_free(cmd);
return OK;
}
static int fw_i2c_write(FAR struct stwlc38_dev_s *priv, uint16_t addr,
uint8_t *data, uint32_t data_length)
{
uint8_t *cmd;
memset(cmd, 0, (2 + data_length) * sizeof(uint8_t));
cmd[0] = (uint8_t)((addr >> 8) & 0xff);
cmd[1] = (uint8_t)((addr >> 0) & 0xff);
memcpy(&cmd[2], data, data_length);
if ((wlc_i2c_write(priv, cmd, (2 + data_length))) < OK)
{
baterr("[WLC] ERROR: in writing Hardware I2c!\n");
kmm_free(cmd);
return E_BUS_W;
}
kmm_free(cmd);
return OK;
}
static int hw_i2c_read(FAR struct stwlc38_dev_s *priv, uint32_t addr,
uint8_t *read_buff, int read_count)
{
uint8_t cmd[5];
cmd[0] = OPCODE_WRITE;
cmd[1] = (uint8_t)((addr >> 24) & 0xff);
cmd[2] = (uint8_t)((addr >> 16) & 0xff);
cmd[3] = (uint8_t)((addr >> 8) & 0xff);
cmd[4] = (uint8_t)((addr >> 0) & 0xff);
if ((wlc_i2c_read(priv, cmd, 5 , read_buff, read_count)) < OK)
{
baterr("[WLC] Error in writing Hardware I2c!\n");
return E_BUS_WR;
}
return OK;
}
static int fw_i2c_read(FAR struct stwlc38_dev_s *priv, uint16_t addr,
uint8_t *read_buff, int read_count)
{
uint8_t cmd[2];
cmd[0] = (uint8_t)((addr >> 8) & 0xff);
cmd[1] = (uint8_t)((addr >> 0) & 0xff);
if ((wlc_i2c_read(priv, cmd, 2, read_buff, read_count)) < OK)
{
baterr("[WLC] Error in writing Hardware I2c!\n");
return E_BUS_WR;
}
return OK;
}
char *print_hex(char *label, uint8_t *buff, int count, uint8_t *result)
{
int i;
int offset;
offset = strlen(label) + 1;
strlcpy(result, label, offset); /* +1 for terminator char */
for (i = 0; i < count; i++)
{
snprintf(&result[offset], 4, "%02X ", buff[i]);
/* this append automatically a null terminator char */
offset += 3;
}
return result;
}
static int get_polaris_chip_info(FAR struct stwlc38_dev_s *priv,
struct polaris_chip_info *info)
{
uint8_t read_buff[14];
memset(read_buff, 0, 14);
if (fw_i2c_read(priv, WLC_CHIPID_LOW_REG, read_buff, 14) < OK)
{
baterr("[WLC] Error while getting polaris_chip_info\n");
return E_BUS_R;
}
info->chip_id = (uint16_t)(read_buff[0] + (read_buff[1] << 8));
info->chip_revision = read_buff[2];
info->customer_id = read_buff[3];
info->project_id = (uint16_t)(read_buff[4] + (read_buff[5] << 8));
info->nvm_patch_id = (uint16_t)(read_buff[6] + (read_buff[7] << 8));
info->ram_patch_id = (uint16_t)(read_buff[8] + (read_buff[9] << 8));
info->config_id = (uint16_t)(read_buff[10] + (read_buff[11] << 8));
info->pe_id = (uint16_t)(read_buff[12] + (read_buff[13] << 8));
if (hw_i2c_read(priv, HWREG_HW_VER_ADDR, read_buff, 1) < OK)
{
baterr("[WLC] Error while getting polaris_chip_info\n");
return E_BUS_R;
}
info->cut_id = read_buff[0];
batinfo("[WLC] ChipID: %04X Chip Revision: %02X CustomerID: %02X \
RomID: %04X NVMPatchID: %04X RAMPatchID: %04X CFG: %04X \
PE: %04X\n", info->chip_id, info->chip_revision, \
info->customer_id, info->project_id, info->nvm_patch_id, \
info->ram_patch_id, info->config_id, info->pe_id);
return OK;
}
static int polaris_nvm_write_sector(FAR struct stwlc38_dev_s *priv,
const uint8_t *data,
int data_length,
int sector_index)
{
int err = 0;
int i = 0;
int timeout = 1;
uint8_t reg_value = (uint8_t)sector_index;
uint8_t write_buff[NVM_SECTOR_SIZE_BYTES];
batinfo("[WLC] writing sector %02X\n", sector_index);
if (data_length > NVM_SECTOR_SIZE_BYTES)
{
baterr("[WLC] sector data bigger than 256 bytes\n");
return E_INVALID_INPUT;
}
memset(write_buff, 0, NVM_SECTOR_SIZE_BYTES);
memcpy(write_buff, data, data_length);
err = fw_i2c_write(priv, FWREG_NVM_SECTOR_INDEX_ADDR, &reg_value, 1);
if (err != OK) return err;
reg_value = 0x10;
err = fw_i2c_write(priv, FWREG_SYS_CMD_ADDR, &reg_value, 1);
if (err != OK) return err;
err = fw_i2c_write(priv, FWREG_AUX_DATA_00, write_buff, data_length);
if (err != OK) return err;
reg_value = 0x04;
err = fw_i2c_write(priv, FWREG_SYS_CMD_ADDR, &reg_value, 1);
if (err != OK) return err;
for (i = 0; i < 20; i++)
{
sleep(1);
err = fw_i2c_read(priv, FWREG_SYS_CMD_ADDR, &reg_value, 1);
if (err != OK) return err;
if ((reg_value & 0x04) == 0)
{
timeout = 0;
break;
}
}
reg_value = 0x20;
if (fw_i2c_write(priv, FWREG_SYS_CMD_ADDR, &reg_value, 1) != OK)
baterr("[WLC] Error power down the NVM\n");
return timeout == 0 ? OK : E_TIMEOUT;
}
static int polaris_nvm_write_bulk(FAR struct stwlc38_dev_s *priv,
const uint8_t *data,
int data_length,
uint8_t sector_index)
{
int err = 0;
int remaining = data_length;
int to_write_now = 0;
int written_already = 0;
while (remaining > 0)
{
if (remaining > NVM_SECTOR_SIZE_BYTES)
to_write_now = NVM_SECTOR_SIZE_BYTES;
else
to_write_now = remaining;
err = polaris_nvm_write_sector(priv, data + written_already,
to_write_now, sector_index);
if (err != OK) return err;
remaining -= to_write_now;
written_already += to_write_now;
sector_index++;
}
return OK;
}
static int polaris_nvm_write(FAR struct stwlc38_dev_s *priv)
{
int err = 0;
uint8_t reg_value = 0;
/* check if OP MODE = DC POWER */
err = fw_i2c_read(priv, FWREG_OP_MODE_ADDR, &reg_value, 1);
if (err != OK) return err;
baterr("[WLC] OP MODE %02X\n", reg_value);
if (reg_value != FW_OP_MODE_SA)
{
baterr("[WLC] no DC power detected, nvm programming aborted\n");
return E_UNEXPECTED_OP_MODE;
}
/* FW system reset */
reg_value = 0x40;
if ((err = fw_i2c_write(priv, FWREG_SYS_CMD_ADDR, &reg_value, 1)) != OK)
return err;
sleep(AFTER_SYS_RESET_SLEEP_MS);
reg_value = 0xc5;
if ((err = fw_i2c_write(priv, FWREG_NVM_PWD_ADDR, &reg_value, 1)) != OK)
return err;
batinfo("[WLC] RRAM Programming.. \n");
err = polaris_nvm_write_bulk(priv, patch_data, NVM_PATCH_SIZE,
NVM_PATCH_START_SECTOR_INDEX);
if (err != OK) return err;
err = polaris_nvm_write_bulk(priv, cfg_data, NVM_CFG_SIZE,
NVM_CFG_START_SECTOR_INDEX);
if (err != OK) return err;
/* system reset */
reg_value = 0x01;
if ((err = hw_i2c_write(priv, HWREG_HW_SYS_RST_ADDR, &reg_value, 1)) != OK)
return err;
sleep(AFTER_SYS_RESET_SLEEP_MS);
return OK;
}
static ssize_t chip_info_show(FAR struct stwlc38_dev_s *priv, char *buf)
{
int error;
char temp[100];
uint8_t read_buff[4];
uint8_t cmd[2];
FAR struct i2c_master_s *dev = priv->i2c;
memset(read_buff, 0, 4);
memset(cmd, 0, 2);
cmd[0] = (WLC_CHIPID_LOW_REG & 0xff00) >> 8;
cmd[1] = (WLC_CHIPID_LOW_REG & 0xff);
batinfo("[WLC] Chip Id Command: %02X %02X\n", cmd[0], cmd[1]);
if (wlc_i2c_read(dev, cmd, 2, read_buff, 4) < OK)
{
baterr("[WLC] could not read the register\n");
error = snprintf(buf, PAGE_SIZE,
"CHIP INFO READ ERROR {%02X}\n", E_BUS_WR);
return error;
}
batinfo("[WLC] Chip Id : 0x%04X\n", (read_buff[0] | (read_buff[1] << 8)));
batinfo("[WLC] Chip Revision : 0x%02X\n", read_buff[2]);
error = snprintf(buf, PAGE_SIZE, "%s\n", print_hex("Chip Info: ",
read_buff, 3, temp));
return error;
}
static ssize_t nvm_program_show(FAR struct stwlc38_dev_s *priv, char *buf)
{
int err = 0;
FAR struct i2c_master_s *dev = priv->i2c;
int count = 0;
int config_id_mismatch = 0;
int patch_id_mismatch = 0;
struct polaris_chip_info chip_info;
batinfo("[WLC] NVM Programming started\n");
if (get_polaris_chip_info(priv, &chip_info) < OK)
{
baterr("[WLC] Error in reading polaris_chip_info\n");
err = E_BUS_R;
goto exit_0;
}
/* determine what has to be programmed depending on version ids */
batinfo("[WLC] Cut Id: %02X\n", chip_info.cut_id);
if (chip_info.cut_id != NVM_TARGET_CUT_ID)
{
batinfo("[WLC] HW cut id mismatch with Target cut id, \
NVM programming aborted\n");
err = E_UNEXPECTED_HW_REV;
goto exit_0;
}
if (chip_info.config_id != NVM_CFG_VERSION_ID)
{
batinfo("[WLC] Config ID mismatch - running|header: [%04X|%04X]\n", \
chip_info.config_id, NVM_CFG_VERSION_ID);
config_id_mismatch = 1;
}
if (chip_info.nvm_patch_id != NVM_PATCH_VERSION_ID)
{
batinfo("[WLC] Patch ID mismatch - running|header: [%04X|%04X]\n", \
chip_info.nvm_patch_id, NVM_PATCH_VERSION_ID);
patch_id_mismatch = 1;
}
if (config_id_mismatch == 0 && patch_id_mismatch == 0)
{
batinfo("[WLC] NVM programming is not required, \
both cfg and patch are up to date\n");
err = OK;
goto exit_0;
}
/**************************************************************************
* program both cfg and patch
* in case one of the two needs to be programmed
**************************************************************************/
if ((err = polaris_nvm_write(priv)) != OK)
{
err = E_NVM_WRITE;
baterr("[WLC] NVM programming failed\n");
goto exit_0;
}
batinfo("[WLC] NVM programming completed, \
now checking patch and cfg id\n");
if (get_polaris_chip_info(priv, &chip_info) < OK)
{
baterr("[WLC] Error in reading lyra_chip_info\n");
err = E_BUS_R;
goto exit_0;
}
if ((chip_info.config_id == NVM_CFG_VERSION_ID)
&& (chip_info.nvm_patch_id == NVM_PATCH_VERSION_ID))
{
batinfo("[WLC] NVM patch and cfg id is OK\n");
batinfo("[WLC] NVM Programming is successful\n");
}
else
{
err = E_NVM_DATA_MISMATCH;
if (chip_info.config_id != NVM_CFG_VERSION_ID)
baterr("[WLC] Config Id mismatch after NVM programming\n");
if (chip_info.nvm_patch_id != NVM_PATCH_VERSION_ID)
baterr("[WLC] Patch Id mismatch after NVM programming\n");
batinfo("[WLC] NVM Programming failed\n");
}
exit_0:
batinfo("[WLC] NVM programming exited\n");
count = snprintf(buf, PAGE_SIZE, "{ %08X }\n", err);
return count;
}
static ssize_t st_polaris_i2c_bridge_show(FAR struct stwlc38_dev_s *priv,
char *buf)
{
int err = 0;
FAR struct i2c_master_s *dev = priv->i2c;
uint8_t *read_buff = NULL;
uint8_t *all_strbuff = NULL;
int read_count = 0;
int i = 0;
int index = 0;
int size = (6 * 2) + 1;
if (number_parameters != 0)
{
switch (type_of_command[0])
{
case WRITE_READ_OPERATION:
{
if (number_parameters >= MIN_WR_BYTE_LENGTH)
{
read_count = ((type_of_command[number_parameters - 2] << 8)
| (type_of_command[number_parameters - 1]));
batinfo("[WLC] read Count is %d\n", read_count);
memset(read_buff, 0, read_count * sizeof(uint8_t));
if (read_buff == NULL)
{
err = E_MEMORY_ALLOC;
goto cleanup;
}
if (wlc_i2c_read(priv, type_of_command + 1,
(number_parameters - 3),
read_buff, read_count) < OK)
{
err = E_BUS_WR;
}
else
{
size += (read_count * sizeof(uint8_t)) * 2;
memset(all_strbuff, 0, size);
if (all_strbuff == NULL)
{
err = E_MEMORY_ALLOC;
goto cleanup;
}
err = OK;
snprintf(&all_strbuff[index], 11, "{ %08X", err);
index += 10;
for (i = 0; i < read_count; i++)
{
snprintf(&all_strbuff[index], 3, "%02X",
read_buff[i]);
index += 2;
}
snprintf(&all_strbuff[index], 3, " }");
index += 2;
err = snprintf(buf, PAGE_SIZE, "%s\n", all_strbuff);
number_parameters = 0;
kmm_free(read_buff);
kmm_free(all_strbuff);
return err;
}
}
else
{
baterr("[WLC] Invalid input for Write read operation\n");
err = E_INVALID_INPUT;
}
goto cleanup;
}
case WRITE_OPERATION:
{
if (number_parameters >= MIN_W_BYTE_LENGTH)
{
if (wlc_i2c_write(priv, type_of_command + 1,
(number_parameters - 1)) < OK)
{
err = E_BUS_W;
}
else
{
err = OK;
}
}
else
{
baterr("[WLC] Invalid input for Write operation\n");
err = E_INVALID_INPUT;
}
goto cleanup;
}
default:
{
baterr("[WLC] Invalid input for i2c bridge\n");
err = E_INVALID_INPUT;
goto cleanup;
}
}
}
else
{
err = E_INVALID_INPUT;
baterr("[WLC] Invalid input for write/write_read operation\n");
goto cleanup;
}
cleanup:
number_parameters = 0;
if (read_buff != NULL) kmm_free(read_buff);
err = snprintf(buf, PAGE_SIZE, "{ %08X }\n", err);
return err;
}
static ssize_t st_polaris_i2c_bridge_store(FAR struct stwlc38_dev_s *priv,
const char *buf, size_t count)
{
int n;
int temp;
char *p = (char *)buf;
number_parameters = 0;
for (n = 0; n < (count + 1) / 3; n++)
{
if (sscanf(p, "%02X ", &temp) == 1)
{
p += 3;
type_of_command[n] = (uint8_t)temp;
batinfo("[WLC] type_of_command[%d] = %02X\n",
n, type_of_command[n]);
number_parameters++;
}
}
batinfo("[WLC] Number of Parameters = %d\n", number_parameters);
return count;
}
FAR struct battery_charger_dev_s *
stwlc38_initialize(FAR struct i2c_master_s *i2c, uint8_t addr,
uint32_t frequency, int current)
{
FAR struct stwlc38_dev_s *priv;
char *buf;
int count;
/* Initialize the SC8551 device structure */
priv = kmm_zalloc(sizeof(struct stwlc38_dev_s));
if (priv)
{
/* Initialize the SC8551 device structure */
nxsem_init(&priv->batsem, 0, 1);
priv->ops = &g_stwlc38ops;
priv->i2c = i2c;
priv->addr = addr;
priv->frequency = frequency;
}
count = nvm_program_show(priv, buf);
return (FAR struct battery_charger_dev_s *)priv;
}
#endif /* __POLARIS_C */

89
drivers/power/polaris.h Normal file
View file

@ -0,0 +1,89 @@
/****************************************************************************
* drivers/power/polaris.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __POLARIS_H
#define __POLARIS_H
#define NVM_SECTOR_SIZE_BYTES 256 //128
#define NVM_PATCH_START_SECTOR_INDEX 0
#define NVM_CFG_START_SECTOR_INDEX 126 //93
#define I2C_CHUNK_SIZE 256 //128
#define AFTER_SYS_RESET_SLEEP_MS 50
/* FW register address */
#define FWREG_OP_MODE_ADDR 0x000E
#define FWREG_SYS_CMD_ADDR 0x0020
#define FWREG_NVM_SECTOR_INDEX_ADDR 0x0024
#define FWREG_AUX_DATA_00 0x0180
#define FWREG_NVM_PWD_ADDR 0x0022
/* SYSREG registers */
#define HWREG_HW_VER_ADDR 0x2001C002
#define HWREG_HW_SYS_RST_ADDR 0x2001F200
typedef enum
{
FW_OP_MODE_SA = 1,
FW_OP_MODE_RX = 2,
FW_OP_MODE_TX = 3
}fw_op_mode_t;
#define WRITE_READ_OPERATION 0x01
#define WRITE_OPERATION 0x02
#define OPCODE_WRITE 0xFA
#define MIN_WR_BYTE_LENGTH 5
#define MIN_W_BYTE_LENGTH 4
#define CMD_STR_LEN 1024
#define OK ((int)0x00000000)
#define E_BUS_R ((int)0x80000001)
#define E_BUS_W ((int)0x80000002)
#define E_BUS_WR ((int)0x80000003)
#define E_UNEXPECTED_OP_MODE ((int)0x80000004)
#define E_NVM_WRITE ((int)0x80000005)
#define E_INVALID_INPUT ((int)0x80000006)
#define E_MEMORY_ALLOC ((int)0x80000007)
#define E_UNEXPECTED_HW_REV ((int)0x80000008)
#define E_TIMEOUT ((int)0x80000009)
#define E_NVM_DATA_MISMATCH ((int)0x8000000A)
#define WLC_CHIPID_LOW_REG 0x0000
#define WLC_DRV_VERSION "1.0.0" /* driver version string format */
struct polaris_chip_info
{
uint16_t chip_id;
uint8_t chip_revision;
uint8_t customer_id;
uint16_t project_id;
uint16_t nvm_patch_id;
uint16_t ram_patch_id;
uint16_t config_id;
uint16_t pe_id;
uint8_t cut_id;
};
#endif /* __POLARIS_H */

108
drivers/power/polaris_nvm.c Normal file
View file

@ -0,0 +1,108 @@
/****************************************************************************
* drivers/power/polaris_nvm.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* The STWLC38 are Li-Ion Battery management
*
* This driver requires:
*
* CONFIG_BATTERY_CHARGER - Upper half battery driver support
* CONFIG_I2C - I2C support
* CONFIG_I2C_STWLC38 - And the driver must be explicitly selected.
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef NVM_DATA_H
#define NVM_DATA_H
#define NVM_TARGET_CUT_ID 1
#define NVM_CFG_SIZE 384
#define NVM_CFG_VERSION_ID 0x1001
#define NVM_PATCH_SIZE 8
#define NVM_PATCH_VERSION_ID 0x1000
/****************************************************************************
* Private Functions
****************************************************************************/
const uint8_t cfg_data[] =
{
0x01, 0x10, 0x00, 0x01, 0x77, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x44,
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x00, 0x03, 0x0d, 0x09, 0x06, 0x00, 0xff,
0x02, 0x19, 0x0f, 0x3d, 0x14, 0x0a, 0x32, 0x28,
0x7d, 0x64, 0x0a, 0x00, 0x82, 0x82, 0x82, 0x82,
0x41, 0x02, 0x02, 0x02, 0x02, 0xa5, 0x07, 0x06,
0x12, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x40,
0x23, 0x37, 0x2c, 0x42, 0x58, 0x6e, 0x84, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7d, 0xc8, 0x13, 0x0f, 0x0a, 0x05,
0x26, 0x3c, 0x4b, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x56, 0x5f, 0x85, 0x64,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x07, 0x19,
0x11, 0x00, 0x02, 0x00, 0x16, 0x11, 0x22, 0x33,
0x44, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x05, 0x1e, 0x00, 0x12, 0x04, 0x1e, 0x5d,
0x5d, 0x54, 0x80, 0x37, 0x9c, 0x14, 0x8e, 0x20,
0x08, 0x04, 0x43, 0x11, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf0, 0x28, 0x0e, 0x05,
0xd4, 0x00, 0xa8, 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00,
0x11, 0xc3, 0x05, 0x06, 0x09, 0x0d, 0x03, 0x1e,
0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9a, 0x85, 0x29, 0x37,
};
const uint8_t patch_data[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif

View file

@ -338,6 +338,44 @@ FAR struct battery_charger_dev_s *
uint32_t frequency, int current);
#endif
/****************************************************************************
* Name: stwlc38_initialize
*
* Description:
* Initialize the stwlc38 (wireless rx) charger driver and return
* an instance of the lower-half interface that may be used with
* battery_charger_register().
*
* This is for:
* STWLC38
*
* This driver requires:
*
* CONFIG_BATTERY_CHARGER - Upper half battery charger driver support
* CONFIG_I2C - I2C support
* CONFIG_I2C_STWLC38 - And the driver must be explicitly selected.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with
* the SC8551
* addr - The I2C address of the STWLC38 (Better be 0x61).
* frequency - The I2C frequency
* current - The input current our power-supply can offer to charger
*
* Returned Value:
* A pointer to the initialized battery driver instance. A NULL pointer
* is returned on a failure to initialize the STWLC38 lower half.
*
****************************************************************************/
#if defined(CONFIG_I2C) && defined(CONFIG_I2C_STWLC38)
struct i2c_master_s;
FAR struct battery_charger_dev_s *
stwlc38_initialize(FAR struct i2c_master_s *i2c, uint8_t addr,
uint32_t frequency, int current);
#endif
#undef EXTERN
#ifdef __cplusplus
}