rhode: rhode 4G camera ldo config[2/3]

Rhode 4G wl2868c ldo bringup

modify camera ldo file

Change-Id: Id1b37b1ca39dc14862ca32fa8aa22c5c636df6ed
Signed-off-by: luozhq15 <luozhq15@motorola.com>
Reviewed-on: https://gerrit.mot.com/2106490
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: XiaoFeng Wang <wangxf32@lenovo.com>
Reviewed-by: Zhichao Chen <chenzc2@motorola.com>
Reviewed-by: Xingyun Fu <fuxy7@motorola.com>
Reviewed-by: Guobin Zhang <zhanggb@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
luozhq15 2021-11-03 17:53:29 +08:00
commit 85578616c0
5 changed files with 453 additions and 0 deletions

View file

@ -0,0 +1,9 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := wl2868c.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -0,0 +1,5 @@
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
wl2868c-objs += wl2868c-regulator.o
obj-m += wl2868c.o

View file

@ -0,0 +1,10 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

View file

@ -0,0 +1,382 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* wl2868c, Multi-Output Regulators
* Copyright (C) 2019 Motorola Mobility LLC,
*
* Author: ChengLong, Motorola Mobility LLC,
*/
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include "wl2868c-regulator.h"
//static int ldo_chipid = -1;
enum slg51000_regulators {
wl2868c_REGULATOR_LDO1 = 0,
wl2868c_REGULATOR_LDO2,
wl2868c_REGULATOR_LDO3,
wl2868c_REGULATOR_LDO4,
wl2868c_REGULATOR_LDO5,
wl2868c_REGULATOR_LDO6,
wl2868c_REGULATOR_LDO7,
wl2868c_MAX_REGULATORS,
};
struct wl2868c {
struct device *dev;
struct regmap *regmap;
struct regulator_desc *rdesc[wl2868c_MAX_REGULATORS];
struct regulator_dev *rdev[wl2868c_MAX_REGULATORS];
// int chip_irq;
int chip_cs_pin;
};
struct wl2868c_evt_sta {
unsigned int sreg;
};
static const struct wl2868c_evt_sta wl2868c_status_reg = { wl2868c_LDO_EN };
static const struct regmap_range wl2868c_writeable_ranges[] = {
regmap_reg_range(wl2868c_CURRENT_LIMITSEL, wl2868c_SEQ_STATUS),
/* Do not let useless register writeable */
// regmap_reg_range(wl2868c_CURRENT_LIMITSEL, wl2868c_CURRENT_LIMITSEL),
// regmap_reg_range(wl2868c_LDO1_VOUT, wl2868c_LDO7_VOUT),
// regmap_reg_range(wl2868c_LDO_EN, wl2868c_LDO_EN),
};
static const struct regmap_range wl2868c_readable_ranges[] = {
regmap_reg_range(wl2868c_CHIP_REV, wl2868c_SEQ_STATUS),
};
static const struct regmap_range wl2868c_volatile_ranges[] = {
regmap_reg_range(wl2868c_CURRENT_LIMITSEL, wl2868c_SEQ_STATUS),
};
static const struct regmap_access_table wl2868c_writeable_table = {
.yes_ranges = wl2868c_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(wl2868c_writeable_ranges),
};
static const struct regmap_access_table wl2868c_readable_table = {
.yes_ranges = wl2868c_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(wl2868c_readable_ranges),
};
static const struct regmap_access_table wl2868c_volatile_table = {
.yes_ranges = wl2868c_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(wl2868c_volatile_ranges),
};
static const struct regmap_config wl2868c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x0F,
.wr_table = &wl2868c_writeable_table,
.rd_table = &wl2868c_readable_table,
.volatile_table = &wl2868c_volatile_table,
};
static int wl2868c_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
{
struct wl2868c *chip = rdev_get_drvdata(rdev);
uint8_t reg_dump[wl2868c_REG_NUM];
uint8_t reg_idx;
unsigned int val = 0;
dev_err(chip->dev, "************ start dump wl2868c register ************\n");
dev_err(chip->dev, "register 0x00: chip version\n");
dev_err(chip->dev, "register 0x01: LDO CL\n");
dev_err(chip->dev, "register 0x03~0x09: LDO1~LDO7 OUT Voltage\n");
dev_err(chip->dev, "register 0x0e: Bit[6:0] LDO7~LDO1 EN\n");
for (reg_idx = 0; reg_idx < wl2868c_REG_NUM; reg_idx++) {
regmap_read(chip->regmap, reg_idx, &val);
reg_dump[reg_idx] = val;
dev_err(chip->dev, "Reg[0x%02x] = 0x%x", reg_idx, reg_dump[reg_idx]);
}
dev_err(chip->dev, "************ end dump wl2868c register ************\n");
if (flags != NULL) {
*flags = 0;
}
return 0;
}
static int wl2868c_get_status(struct regulator_dev *rdev)
{
struct wl2868c *chip = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int status = 0;
ret = regulator_is_enabled_regmap(rdev);
if (ret < 0) {
dev_err(chip->dev, "Failed to read enable register(%d)\n",
ret);
return ret;
}
if (!ret)
return REGULATOR_STATUS_OFF;
wl2868c_get_error_flags(rdev, NULL);
ret = regmap_read(chip->regmap, wl2868c_status_reg.sreg, &status);
if (ret < 0) {
dev_err(chip->dev, "Failed to read status register(%d)\n",
ret);
return ret;
}
if (status & (0x01ul << id)) {
return REGULATOR_STATUS_ON;
} else {
return REGULATOR_STATUS_OFF;
}
}
static const struct regulator_ops wl2868c_regl_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_status = wl2868c_get_status,
.get_error_flags = wl2868c_get_error_flags,
};
static int wl2868c_of_parse_cb(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *config)
{
int ena_gpio;
ena_gpio = of_get_named_gpio(np, "enable-gpios", 0);
if (gpio_is_valid(ena_gpio))
config->ena_gpiod = gpio_to_desc(ena_gpio);
return 0;
}
#define wl2868c_REGL_DESC(_id, _name, _s_name, _min, _step) \
[wl2868c_REGULATOR_##_id] = { \
.name = #_name, \
.supply_name = _s_name, \
.id = wl2868c_REGULATOR_##_id, \
.of_match = of_match_ptr(#_name), \
.of_parse_cb = wl2868c_of_parse_cb, \
.ops = &wl2868c_regl_ops, \
.regulators_node = of_match_ptr("regulators"), \
.n_voltages = 256, \
.min_uV = _min, \
.uV_step = _step, \
.linear_min_sel = 0, \
.vsel_mask = wl2868c_VSEL_MASK, \
.vsel_reg = wl2868c_##_id##_VSEL, \
.enable_reg = wl2868c_LDO_EN, \
.enable_mask = BIT(wl2868c_REGULATOR_##_id)|0x80, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
static struct regulator_desc wl2868c_regls_desc[wl2868c_MAX_REGULATORS] = {
wl2868c_REGL_DESC(LDO1, ldo1, "vin1", 496000, 8000),
wl2868c_REGL_DESC(LDO2, ldo2, "vin1", 496000, 8000),
wl2868c_REGL_DESC(LDO3, ldo3, "vin2", 1504000, 8000),
wl2868c_REGL_DESC(LDO4, ldo4, "vin2", 1504000, 8000),
wl2868c_REGL_DESC(LDO5, ldo5, "vin2", 1504000, 8000),
wl2868c_REGL_DESC(LDO6, ldo6, "vin2", 1504000, 8000),
wl2868c_REGL_DESC(LDO7, ldo7, "vin2", 1504000, 8000),
};
static int wl2868c_regulator_init(struct wl2868c *chip)
{
struct regulator_config config = { };
struct regulator_desc *rdesc;
u8 vsel_range[1];
int id, ret = 0;
const unsigned int ldo_regs[wl2868c_MAX_REGULATORS] = {
wl2868c_LDO1_VOUT,
wl2868c_LDO2_VOUT,
wl2868c_LDO3_VOUT,
wl2868c_LDO4_VOUT,
wl2868c_LDO5_VOUT,
wl2868c_LDO6_VOUT,
wl2868c_LDO7_VOUT,
};
const unsigned int initial_voltage[wl2868c_MAX_REGULATORS] = {
0x24,//LDO1 1.05V
0x30,//LDO2 1.2V
0x80,//LDO3 2.8V
0x80,//LDO4 2.8V
0x80,//LDO5 2.8V
0x30,//LDO6 1.8V
0x30,//LDO7 1.8V
};
/*Disable all ldo output by default*/
ret = regmap_write(chip->regmap, wl2868c_LDO_EN, 0);
if (ret < 0) {
dev_err(chip->dev,
"Disable all LDO output failed!!!\n");
return ret;
}
for (id = 0; id < wl2868c_MAX_REGULATORS; id++) {
chip->rdesc[id] = &wl2868c_regls_desc[id];
rdesc = chip->rdesc[id];
config.regmap = chip->regmap;
config.dev = chip->dev;
config.driver_data = chip;
ret = regmap_bulk_read(chip->regmap, ldo_regs[id],
vsel_range, 1);
pr_err("wl2868c_regulator_init: LDO%d, default value:0x%x", (id+1), vsel_range[0]);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read the ldo register\n");
return ret;
}
ret = regmap_write(chip->regmap, ldo_regs[id], initial_voltage[id]);
if (ret < 0) {
dev_err(chip->dev,
"Failed to write inital voltage register\n");
return ret;
}
pr_err("wl2868c_regulator_init: LDO%d, initial value:0x%x", (id+1), initial_voltage[id]);
chip->rdev[id] = devm_regulator_register(chip->dev, rdesc,
&config);
if (IS_ERR(chip->rdev[id])) {
ret = PTR_ERR(chip->rdev[id]);
dev_err(chip->dev,
"Failed to register regulator(%s):%d\n",
chip->rdesc[id]->name, ret);
return ret;
}
}
return 0;
}
static int wl2868c_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct wl2868c *chip;
int error, cs_gpio, ret;
#if 0//del by zhangle
unsigned int status = 0;
ldo_chipid = regmap_read(chip->regmap, wl2868c_CHIP_REV, &status);
if (ldo_chipid != 0x82)
{
dev_info(chip->dev, "wl2868c_i2c addr error:%d\n", ldo_chipid);
return -ENOMEM;
}
#endif
chip = devm_kzalloc(dev, sizeof(struct wl2868c), GFP_KERNEL);
if (!chip) {
dev_err(chip->dev, "wl2868c_i2c_probe Memory error...\n");
return -ENOMEM;
}
dev_info(chip->dev, "wl2868c_i2c_probe Enter...\n");
cs_gpio = of_get_named_gpio(dev->of_node, "semi,cs-gpios", 0);
if (cs_gpio > 0) {
if (!gpio_is_valid(cs_gpio)) {
dev_err(dev, "Invalid chip select pin\n");
return -EPERM;
}
ret = devm_gpio_request_one(dev, cs_gpio, GPIOF_OUT_INIT_HIGH,
"wl2868c_cs_pin");
if (ret) {
dev_err(dev, "GPIO(%d) request failed(%d)\n",
cs_gpio, ret);
return ret;
}
chip->chip_cs_pin = cs_gpio;
}
dev_info(chip->dev, "wl2868c_i2c_probe cs_gpio:%d...\n", cs_gpio);
mdelay(10);
i2c_set_clientdata(client, chip);
chip->dev = dev;
chip->regmap = devm_regmap_init_i2c(client, &wl2868c_regmap_config);
if (IS_ERR(chip->regmap)) {
error = PTR_ERR(chip->regmap);
dev_err(dev, "Failed to allocate register map: %d\n",
error);
return error;
}
{
int chip_rev = 0;
ret = regmap_bulk_read(chip->regmap, 0x00, &chip_rev, 1);
printk("wl2868c chip rev: %02x\n", chip_rev);
}
ret = wl2868c_regulator_init(chip);
if (ret < 0) {
dev_err(chip->dev, "Failed to init regulator(%d)\n", ret);
return ret;
}
dev_info(chip->dev, "wl2868c_i2c_probe Exit...\n");
return ret;
}
static int wl2868c_i2c_remove(struct i2c_client *client)
{
struct wl2868c *chip = i2c_get_clientdata(client);
struct gpio_desc *desc;
int ret = 0;
if (chip->chip_cs_pin > 0) {
desc = gpio_to_desc(chip->chip_cs_pin);
ret = gpiod_direction_output_raw(desc, GPIOF_INIT_LOW);
}
return ret;
}
static const struct i2c_device_id wl2868c_i2c_id[] = {
{"wl2868c", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, wl2868c_i2c_id);
static struct i2c_driver wl2868c_regulator_driver = {
.driver = {
.name = "wl2868c-regulator",
},
.probe = wl2868c_i2c_probe,
.remove = wl2868c_i2c_remove,
.id_table = wl2868c_i2c_id,
};
module_i2c_driver(wl2868c_regulator_driver);
MODULE_AUTHOR("ChengLong <chengl1@motorola.com>");
MODULE_DESCRIPTION("wl2868c regulator driver");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* wl2868c, Multi-Output Regulators
* Copyright (C) 2019 Motorola Mobility LLC,
*
* Author: ChengLong, Motorola Mobility LLC,
*/
#ifndef __wl2868c_REGISTERS_H__
#define __wl2868c_REGISTERS_H__
/* Registers */
#define wl2868c_REG_NUM (wl2868c_SEQ_STATUS - wl2868c_CHIP_REV + 1)
#define wl2868c_CHIP_REV 0x00
#define wl2868c_CURRENT_LIMITSEL 0x01
#define wl2868c_DISCHARGE_RESISTORS 0x02
#define wl2868c_LDO1_VOUT 0x03
#define wl2868c_LDO2_VOUT 0x04
#define wl2868c_LDO3_VOUT 0x05
#define wl2868c_LDO4_VOUT 0x06
#define wl2868c_LDO5_VOUT 0x07
#define wl2868c_LDO6_VOUT 0x08
#define wl2868c_LDO7_VOUT 0x09
#define wl2868c_LDO1_LDO2_SEQ 0x0a
#define wl2868c_LDO3_LDO4_SEQ 0x0b
#define wl2868c_LDO5_LDO6_SEQ 0x0c
#define wl2868c_LDO7_SEQ 0x0d
#define wl2868c_LDO_EN 0x0e
#define wl2868c_SEQ_STATUS 0x0f
/* wl2868c_LDO1_VSEL ~ wl2868c_LDO7_VSEL =
* 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
*/
#define wl2868c_LDO1_VSEL wl2868c_LDO1_VOUT
#define wl2868c_LDO2_VSEL wl2868c_LDO2_VOUT
#define wl2868c_LDO3_VSEL wl2868c_LDO3_VOUT
#define wl2868c_LDO4_VSEL wl2868c_LDO4_VOUT
#define wl2868c_LDO5_VSEL wl2868c_LDO5_VOUT
#define wl2868c_LDO6_VSEL wl2868c_LDO6_VOUT
#define wl2868c_LDO7_VSEL wl2868c_LDO7_VOUT
#define wl2868c_VSEL_SHIFT 0
#define wl2868c_VSEL_MASK (0xff << 0)
#endif /* __wl2868c_REGISTERS_H__ */