GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
config DM_PMIC
|
||||
bool "Enable Driver Model for PMIC drivers (UCLASS_PMIC)"
|
||||
depends on DM
|
||||
---help---
|
||||
This config enables the driver-model PMIC support.
|
||||
UCLASS_PMIC - designed to provide an I/O interface for PMIC devices.
|
||||
For the multi-function PMIC devices, this can be used as parent I/O
|
||||
device for each IC's interface. Then, each children uses its parent
|
||||
for read/write. For detailed description, please refer to the files:
|
||||
- 'drivers/power/pmic/pmic-uclass.c'
|
||||
- 'include/power/pmic.h'
|
||||
|
||||
config PMIC_CHILDREN
|
||||
bool "Allow child devices for PMICs"
|
||||
depends on DM_PMIC
|
||||
default y
|
||||
---help---
|
||||
This allows PMICs to support child devices (such as regulators) in
|
||||
SPL. This adds quite a bit of code so if you are not using this
|
||||
feature you can turn it off. Most likely you should turn it on for
|
||||
U-Boot proper.
|
||||
|
||||
config SPL_PMIC_CHILDREN
|
||||
bool "Allow child devices for PMICs in SPL"
|
||||
depends on DM_PMIC
|
||||
default y
|
||||
---help---
|
||||
This allows PMICs to support child devices (such as regulators) in
|
||||
SPL. This adds quite a bit of code so if you are not using this
|
||||
feature you can turn it off. In this case you may need a 'back door'
|
||||
to call your regulator code (e.g. see rk8xx.c for direct functions
|
||||
for use in SPL).
|
||||
|
||||
config PMIC_ACT8846
|
||||
bool "Enable support for the active-semi 8846 PMIC"
|
||||
depends on DM_PMIC && DM_I2C
|
||||
---help---
|
||||
This PMIC includes 4 DC/DC step-down buck regulators and 8 low-dropout
|
||||
regulators (LDOs). It also provides some GPIO, reset and battery
|
||||
functions. It uses an I2C interface and is designed for use with
|
||||
tablets and smartphones.
|
||||
|
||||
config PMIC_AS3722
|
||||
bool "Enable support for the Austria Micro Systems (AMS) AS7322 PMIC"
|
||||
help
|
||||
The AS3722 includes 7 DC/DC buck convertors, 11 low-noise LDOs, a
|
||||
real-time clock, GPIOs, ADC and a few other features. It uses an I2C
|
||||
interface and is designs to cover most of the power managementment
|
||||
required for a tablets or laptop.
|
||||
|
||||
config DM_PMIC_BD71837
|
||||
bool "Enable Driver Model for PMIC BD71837"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
This config enables implementation of driver-model pmic uclass features
|
||||
for PMIC BD71837. The driver implements read/write operations.
|
||||
|
||||
config SPL_DM_PMIC_BD71837
|
||||
bool "Enable Driver Model for PMIC BD71837 in SPL stage"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
This config enables implementation of driver-model pmic uclass
|
||||
features for PMIC BD71837. The driver implements read/write
|
||||
operations.
|
||||
|
||||
config DM_PMIC_FAN53555
|
||||
bool "Enable support for OnSemi FAN53555"
|
||||
depends on DM_PMIC && DM_REGULATOR && DM_I2C
|
||||
select DM_REGULATOR_FAN53555
|
||||
help
|
||||
This config enables implementation of driver-model PMIC
|
||||
uclass features for the FAN53555 regulator. The FAN53555 is
|
||||
a (family of) single-output regulators that supports
|
||||
transitioning between two different output voltages based on
|
||||
an voltage selection pin.
|
||||
|
||||
The driver implements read/write operations for use with the FAN53555
|
||||
regulator driver and binds the regulator driver to its node.
|
||||
|
||||
config DM_PMIC_PFUZE100
|
||||
bool "Enable Driver Model for PMIC PFUZE100"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
This config enables implementation of driver-model pmic uclass features
|
||||
for PMIC PFUZE100. The driver implements read/write operations.
|
||||
|
||||
config DM_PMIC_MAX77686
|
||||
bool "Enable Driver Model for PMIC MAX77686"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
This config enables implementation of driver-model pmic uclass features
|
||||
for PMIC MAX77686. The driver implements read/write operations.
|
||||
|
||||
config DM_PMIC_MAX8998
|
||||
bool "Enable Driver Model for PMIC MAX8998"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
This config enables implementation of driver-model pmic uclass features
|
||||
for PMIC MAX8998. The driver implements read/write operations.
|
||||
|
||||
config DM_PMIC_MC34708
|
||||
bool "Enable Driver Model for PMIC MC34708"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
This config enables implementation of driver-model pmic uclass features
|
||||
for PMIC MC34708. The driver implements read/write operations.
|
||||
|
||||
config PMIC_MAX8997
|
||||
bool "Enable Driver Model for PMIC MAX8997"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
This config enables implementation of driver-model pmic uclass features
|
||||
for PMIC MAX8997. The driver implements read/write operations.
|
||||
This is a Power Management IC with RTC, Fuel Gauge, MUIC control on Chip.
|
||||
- 21x LDOs
|
||||
- 12x GPIOs
|
||||
- Haptic Motor driver
|
||||
- RTC with two alarms
|
||||
- Fueal Gauge and One backup battery charger
|
||||
- MUIC
|
||||
- Others
|
||||
|
||||
config PMIC_PM8916
|
||||
bool "Enable Driver Model for Qualcomm PM8916 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The PM8916 is a PMIC connected to one (or several) processors
|
||||
with SPMI bus. It has 2 slaves with several peripherals:
|
||||
- 18x LDO
|
||||
- 4x GPIO
|
||||
- Power and Reset buttons
|
||||
- Watchdog
|
||||
- RTC
|
||||
- Vibrator drivers
|
||||
- Others
|
||||
|
||||
Driver binding info: doc/device-tree-bindings/pmic/pm8916.txt
|
||||
|
||||
config PMIC_RK8XX
|
||||
bool "Enable support for Rockchip PMIC RK8XX"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The Rockchip RK808 PMIC provides four buck DC-DC convertors, 8 LDOs,
|
||||
an RTC and two low Rds (resistance (drain to source)) switches. It is
|
||||
accessed via an I2C interface. The device is used with Rockchip SoCs.
|
||||
This driver implements register read/write operations.
|
||||
|
||||
config PMIC_S2MPS11
|
||||
bool "Enable Driver Model for PMIC Samsung S2MPS11"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The Samsung S2MPS11 PMIC provides:
|
||||
- 38 adjustable LDO regulators
|
||||
- 9 High-Efficiency Buck Converters
|
||||
- 1 BuckBoost Converter
|
||||
- RTC with two alarms
|
||||
- Backup battery charger
|
||||
- I2C Configuration Interface
|
||||
This driver provides access to I/O interface only.
|
||||
Binding info: doc/device-tree-bindings/pmic/s2mps11.txt
|
||||
|
||||
config DM_PMIC_SANDBOX
|
||||
bool "Enable Driver Model for emulated Sandbox PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
Enable the driver for Sandbox PMIC emulation. The emulated PMIC device
|
||||
depends on two drivers:
|
||||
- sandbox PMIC I/O driver - implements dm pmic operations
|
||||
- sandbox PMIC i2c emul driver - emulates the PMIC's I2C transmission
|
||||
|
||||
A detailed information can be found in header: '<power/sandbox_pmic.h>'
|
||||
|
||||
The Sandbox PMIC info:
|
||||
* I/O interface:
|
||||
- I2C chip address: 0x40
|
||||
- first register address: 0x0
|
||||
- register count: 0x10
|
||||
* Adjustable outputs:
|
||||
- 2x LDO
|
||||
- 2x BUCK
|
||||
- Each, with a different operating conditions (header).
|
||||
* Reset values:
|
||||
- set by i2c emul driver's probe() (defaults in header)
|
||||
|
||||
Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt
|
||||
|
||||
config PMIC_S5M8767
|
||||
bool "Enable Driver Model for the Samsung S5M8767 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The S5M8767 PMIC provides a large array of LDOs and BUCKs for use
|
||||
as a SoC power controller. It also provides 32KHz clock outputs. This
|
||||
driver provides basic register access and sets up the attached
|
||||
regulators if regulator support is enabled.
|
||||
|
||||
config PMIC_RN5T567
|
||||
bool "Enable driver for Ricoh RN5T567 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The RN5T567 is a PMIC with 4 step-down DC/DC converters, 5 LDO
|
||||
regulators Real-Time Clock and 4 GPIOs. This driver provides
|
||||
register access only.
|
||||
|
||||
config PMIC_TPS65090
|
||||
bool "Enable driver for Texas Instruments TPS65090 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The TPS65090 is a PMIC containing several LDOs, DC to DC convertors,
|
||||
FETs and a battery charger. This driver provides register access
|
||||
only, and you can enable the regulator/charger drivers separately if
|
||||
required.
|
||||
|
||||
config PMIC_PALMAS
|
||||
bool "Enable driver for Texas Instruments PALMAS PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The PALMAS is a PMIC containing several LDOs, SMPS.
|
||||
This driver binds the pmic children.
|
||||
|
||||
config PMIC_LP873X
|
||||
bool "Enable driver for Texas Instruments LP873X PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The LP873X is a PMIC containing couple of LDOs and couple of SMPS.
|
||||
This driver binds the pmic children.
|
||||
|
||||
config PMIC_LP87565
|
||||
bool "Enable driver for Texas Instruments LP87565 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The LP87565 is a PMIC containing a bunch of SMPS.
|
||||
This driver binds the pmic children.
|
||||
|
||||
config POWER_MC34VR500
|
||||
bool "Enable driver for Freescale MC34VR500 PMIC"
|
||||
---help---
|
||||
The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
|
||||
SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
|
||||
via an I2C interface.
|
||||
|
||||
config DM_PMIC_TPS65910
|
||||
bool "Enable driver for Texas Instruments TPS65910 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The TPS65910 is a PMIC containing 3 buck DC-DC converters, one boost
|
||||
DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
|
||||
pmic children.
|
||||
|
||||
config PMIC_STPMIC1
|
||||
bool "Enable support for STMicroelectronics STPMIC1 PMIC"
|
||||
depends on DM_PMIC && DM_I2C
|
||||
select SYSRESET_CMD_POWEROFF if CMD_POWEROFF && !ARM_PSCI_FW
|
||||
---help---
|
||||
The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
|
||||
It is accessed via an I2C interface. The device is used with STM32MP1
|
||||
SoCs. This driver implements register read/write operations.
|
||||
|
||||
config SPL_PMIC_PALMAS
|
||||
bool "Enable driver for Texas Instruments PALMAS PMIC"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
The PALMAS is a PMIC containing several LDOs, SMPS.
|
||||
This driver binds the pmic children in SPL.
|
||||
|
||||
config SPL_PMIC_LP873X
|
||||
bool "Enable driver for Texas Instruments LP873X PMIC"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
The LP873X is a PMIC containing couple of LDOs and couple of SMPS.
|
||||
This driver binds the pmic children in SPL.
|
||||
|
||||
config SPL_PMIC_LP87565
|
||||
bool "Enable driver for Texas Instruments LP87565 PMIC"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
The LP87565 is a PMIC containing a bunch of SMPS.
|
||||
This driver binds the pmic children in SPL.
|
||||
|
||||
config PMIC_TPS65941
|
||||
bool "Enable driver for Texas Instruments TPS65941 PMIC"
|
||||
depends on DM_PMIC
|
||||
help
|
||||
The TPS65941 is a PMIC containing a bunch of SMPS & LDOs.
|
||||
This driver binds the pmic children.
|
||||
@@ -0,0 +1,42 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2012 Samsung Electronics
|
||||
# Lukasz Majewski <l.majewski@samsung.com>
|
||||
|
||||
obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
|
||||
obj-$(CONFIG_DM_PMIC_FAN53555) += fan53555.o
|
||||
obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
|
||||
obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
|
||||
obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
|
||||
obj-$(CONFIG_$(SPL_)DM_PMIC_BD71837) += bd71837.o
|
||||
obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
|
||||
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
|
||||
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
|
||||
obj-$(CONFIG_PMIC_ACT8846) += act8846.o
|
||||
obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
|
||||
obj-$(CONFIG_PMIC_MAX8997) += max8997.o
|
||||
obj-$(CONFIG_PMIC_PM8916) += pm8916.o
|
||||
obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o
|
||||
obj-$(CONFIG_PMIC_RN5T567) += rn5t567.o
|
||||
obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
|
||||
obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
|
||||
obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
|
||||
obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
|
||||
|
||||
obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
|
||||
obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
|
||||
obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
|
||||
obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
|
||||
obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
|
||||
obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
|
||||
obj-$(CONFIG_POWER_PFUZE3000) += pmic_pfuze3000.o
|
||||
obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
|
||||
obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o
|
||||
obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
|
||||
obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o
|
||||
obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o
|
||||
obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o
|
||||
obj-$(CONFIG_PMIC_TPS65941) += tps65941.o
|
||||
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <power/act8846_pmic.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "REG", .driver = "act8846_reg"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int act8846_reg_count(struct udevice *dev)
|
||||
{
|
||||
return ACT8846_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int act8846_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
debug("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int act8846_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
debug("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int act8846_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops act8846_ops = {
|
||||
.reg_count = act8846_reg_count,
|
||||
.read = act8846_read,
|
||||
.write = act8846_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id act8846_ids[] = {
|
||||
{ .compatible = "active-semi,act8846" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_act8846) = {
|
||||
.name = "act8846 pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = act8846_ids,
|
||||
.bind = act8846_bind,
|
||||
.ops = &act8846_ops,
|
||||
};
|
||||
@@ -0,0 +1,177 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014 NVIDIA Corporation
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "as3722: " fmt
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <i2c.h>
|
||||
#include <dm/lists.h>
|
||||
#include <power/as3722.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
#define AS3722_NUM_OF_REGS 0x92
|
||||
|
||||
static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to read ID1 register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
*idp = ret;
|
||||
|
||||
ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to read ID2 register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
*revisionp = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(treding@nvidia.com): Add proper regulator support to avoid this */
|
||||
int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (sd > 6)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to write SD%u voltage register: %d\n", sd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ldo > 11)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to write LDO%u voltage register: %d\n", ldo,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as3722_probe(struct udevice *dev)
|
||||
{
|
||||
uint id, revision;
|
||||
int ret;
|
||||
|
||||
ret = as3722_read_id(dev, &id, &revision);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to read ID: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (id != AS3722_DEVICE_ID) {
|
||||
pr_err("unknown device\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "sd", .driver = "as3722_stepdown"},
|
||||
{ .prefix = "ldo", .driver = "as3722_ldo"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int as3722_bind(struct udevice *dev)
|
||||
{
|
||||
struct udevice *gpio_dev;
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
int ret;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev);
|
||||
if (ret) {
|
||||
debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int as3722_reg_count(struct udevice *dev)
|
||||
{
|
||||
return AS3722_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops as3722_ops = {
|
||||
.reg_count = as3722_reg_count,
|
||||
.read = as3722_read,
|
||||
.write = as3722_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id as3722_ids[] = {
|
||||
{ .compatible = "ams,as3722" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_as3722) = {
|
||||
.name = "as3722_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = as3722_ids,
|
||||
#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
|
||||
.bind = as3722_bind,
|
||||
#endif
|
||||
.probe = as3722_probe,
|
||||
.ops = &as3722_ops,
|
||||
};
|
||||
@@ -0,0 +1,120 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014 NVIDIA Corporation
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <power/as3722.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
#define NUM_GPIOS 8
|
||||
|
||||
int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
|
||||
unsigned long flags)
|
||||
{
|
||||
u8 value = 0;
|
||||
int err;
|
||||
|
||||
if (flags & AS3722_GPIO_OUTPUT_VDDH)
|
||||
value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
|
||||
|
||||
if (flags & AS3722_GPIO_INVERT)
|
||||
value |= AS3722_GPIO_CONTROL_INVERT;
|
||||
|
||||
err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
|
||||
if (err) {
|
||||
pr_err("failed to configure GPIO#%u: %d\n", gpio, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as3722_gpio_set_value(struct udevice *dev, unsigned int gpio,
|
||||
int level)
|
||||
{
|
||||
struct udevice *pmic = dev_get_parent(dev);
|
||||
const char *l;
|
||||
u8 value;
|
||||
int err;
|
||||
|
||||
if (gpio >= NUM_GPIOS)
|
||||
return -EINVAL;
|
||||
|
||||
err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
|
||||
if (err < 0) {
|
||||
pr_err("failed to read GPIO signal out register: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
value = err;
|
||||
|
||||
if (level == 0) {
|
||||
value &= ~(1 << gpio);
|
||||
l = "low";
|
||||
} else {
|
||||
value |= 1 << gpio;
|
||||
l = "high";
|
||||
}
|
||||
|
||||
err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
|
||||
if (err) {
|
||||
pr_err("failed to set GPIO#%u %s: %d\n", gpio, l, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int as3722_gpio_direction_output(struct udevice *dev, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
struct udevice *pmic = dev_get_parent(dev);
|
||||
int err;
|
||||
|
||||
if (gpio > 7)
|
||||
return -EINVAL;
|
||||
|
||||
if (value == 0)
|
||||
value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
|
||||
else
|
||||
value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
|
||||
|
||||
err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
|
||||
if (err) {
|
||||
pr_err("failed to configure GPIO#%u as output: %d\n", gpio,
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = as3722_gpio_set_value(pmic, gpio, value);
|
||||
if (err < 0) {
|
||||
pr_err("failed to set GPIO#%u high: %d\n", gpio, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as3722_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
|
||||
uc_priv->gpio_count = NUM_GPIOS;
|
||||
uc_priv->bank_name = "as3722_";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops gpio_as3722_ops = {
|
||||
.direction_output = as3722_gpio_direction_output,
|
||||
.set_value = as3722_gpio_set_value,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(gpio_as3722) = {
|
||||
.name = "gpio_as3722",
|
||||
.id = UCLASS_GPIO,
|
||||
.ops = &gpio_as3722_ops,
|
||||
.probe = as3722_gpio_probe,
|
||||
};
|
||||
@@ -0,0 +1,109 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2018 NXP
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/bd71837.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
/* buck */
|
||||
{ .prefix = "b", .driver = BD718XX_REGULATOR_DRIVER},
|
||||
/* ldo */
|
||||
{ .prefix = "l", .driver = BD718XX_REGULATOR_DRIVER},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int bd71837_reg_count(struct udevice *dev)
|
||||
{
|
||||
return BD718XX_MAX_REGISTER - 1;
|
||||
}
|
||||
|
||||
static int bd71837_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd71837_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd71837_bind(struct udevice *dev)
|
||||
{
|
||||
int children;
|
||||
ofnode regulators_node;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd718x7_probe(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
uint8_t mask = BD718XX_REGLOCK_PWRSEQ | BD718XX_REGLOCK_VREG;
|
||||
|
||||
/* Unlock the PMIC regulator control before probing the children */
|
||||
ret = pmic_clrsetbits(dev, BD718XX_REGLOCK, mask, 0);
|
||||
if (ret) {
|
||||
debug("%s: %s Failed to unlock regulator control\n", __func__,
|
||||
dev->name);
|
||||
return ret;
|
||||
}
|
||||
debug("%s: '%s' - BD718x7 PMIC registers unlocked\n", __func__,
|
||||
dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops bd71837_ops = {
|
||||
.reg_count = bd71837_reg_count,
|
||||
.read = bd71837_read,
|
||||
.write = bd71837_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id bd71837_ids[] = {
|
||||
{ .compatible = "rohm,bd71837", .data = ROHM_CHIP_TYPE_BD71837, },
|
||||
{ .compatible = "rohm,bd71847", .data = ROHM_CHIP_TYPE_BD71847, },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_bd71837) = {
|
||||
.name = "bd71837 pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = bd71837_ids,
|
||||
.bind = bd71837_bind,
|
||||
.probe = bd718x7_probe,
|
||||
.ops = &bd71837_ops,
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) 2018 Theobroma Systems Design und Consulting GmbH
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <i2c.h>
|
||||
#include <power/fan53555.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
static int pmic_fan53555_reg_count(struct udevice *dev)
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
static int pmic_fan53555_read(struct udevice *dev, uint reg,
|
||||
u8 *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("%s: read error for register: %#x!", dev->name, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmic_fan53555_write(struct udevice *dev, uint reg,
|
||||
const u8 *buff, int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("%s: write error for register: %#x!", dev->name, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmic_fan53555_bind(struct udevice *dev)
|
||||
{
|
||||
/*
|
||||
* The FAN53555 has only a single regulator and therefore doesn't
|
||||
* have a subnode. So we have to rebind a child device (the one
|
||||
* regulator) here.
|
||||
*/
|
||||
|
||||
const char *regulator_driver_name = "fan53555_regulator";
|
||||
struct udevice *child;
|
||||
struct driver *drv;
|
||||
|
||||
debug("%s\n", __func__);
|
||||
|
||||
drv = lists_driver_lookup_name(regulator_driver_name);
|
||||
if (!drv) {
|
||||
dev_err(dev, "no driver '%s'\n", regulator_driver_name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return device_bind_with_driver_data(dev, drv, "SW", dev->driver_data,
|
||||
dev_ofnode(dev), &child);
|
||||
};
|
||||
|
||||
static struct dm_pmic_ops pmic_fan53555_ops = {
|
||||
.reg_count = pmic_fan53555_reg_count,
|
||||
.read = pmic_fan53555_read,
|
||||
.write = pmic_fan53555_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id pmic_fan53555_match[] = {
|
||||
{ .compatible = "fcs,fan53555", .data = FAN53555_VENDOR_FAIRCHILD, },
|
||||
{ .compatible = "silergy,syr827", .data = FAN53555_VENDOR_SILERGY, },
|
||||
{ .compatible = "silergy,syr828", .data = FAN53555_VENDOR_SILERGY, },
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_fan53555) = {
|
||||
.name = "pmic_fan53555",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = pmic_fan53555_match,
|
||||
.bind = pmic_fan53555_bind,
|
||||
.ops = &pmic_fan53555_ops,
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/sandbox_pmic.h>
|
||||
|
||||
/**
|
||||
* struct sandbox_i2c_pmic_plat_data - platform data for the PMIC
|
||||
*
|
||||
* @rw_reg: PMICs register of the chip I/O transaction
|
||||
* @reg: PMICs registers array
|
||||
*/
|
||||
struct sandbox_i2c_pmic_plat_data {
|
||||
u8 rw_reg, rw_idx;
|
||||
u8 reg_count;
|
||||
u8 trans_len;
|
||||
u8 buf_size;
|
||||
u8 *reg;
|
||||
};
|
||||
|
||||
static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
|
||||
uchar *buffer, int len)
|
||||
{
|
||||
struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
|
||||
|
||||
if (plat->rw_idx + len > plat->buf_size) {
|
||||
pr_err("Request exceeds PMIC register range! Max register: %#x",
|
||||
plat->reg_count);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
debug("Read PMIC: %#x at register: %#x idx: %#x count: %d\n",
|
||||
(unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
|
||||
|
||||
memcpy(buffer, plat->reg + plat->rw_idx, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
|
||||
uchar *buffer, int len,
|
||||
bool next_is_read)
|
||||
{
|
||||
struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
|
||||
|
||||
/* Probe only */
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
/* Set PMIC register for I/O */
|
||||
plat->rw_reg = *buffer;
|
||||
plat->rw_idx = plat->rw_reg * plat->trans_len;
|
||||
|
||||
debug("Write PMIC: %#x at register: %#x idx: %#x count: %d\n",
|
||||
(unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
|
||||
|
||||
/* For read operation, set (write) only chip reg */
|
||||
if (next_is_read)
|
||||
return 0;
|
||||
|
||||
buffer++;
|
||||
len--;
|
||||
|
||||
if (plat->rw_idx + len > plat->buf_size) {
|
||||
pr_err("Request exceeds PMIC register range! Max register: %#x",
|
||||
plat->reg_count);
|
||||
}
|
||||
|
||||
memcpy(plat->reg + plat->rw_idx, buffer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_i2c_pmic_xfer(struct udevice *emul, struct i2c_msg *msg,
|
||||
int nmsgs)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
for (; nmsgs > 0; nmsgs--, msg++) {
|
||||
bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
ret = sandbox_i2c_pmic_read_data(emul, msg->addr,
|
||||
msg->buf, msg->len);
|
||||
} else {
|
||||
ret = sandbox_i2c_pmic_write_data(emul, msg->addr,
|
||||
msg->buf, msg->len,
|
||||
next_is_read);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sandbox_i2c_pmic_ofdata_to_platdata(struct udevice *emul)
|
||||
{
|
||||
struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
|
||||
struct udevice *pmic_dev = i2c_emul_get_device(emul);
|
||||
struct uc_pmic_priv *priv = dev_get_uclass_priv(pmic_dev);
|
||||
const u8 *reg_defaults;
|
||||
|
||||
debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
|
||||
plat->reg_count = pmic_reg_count(pmic_dev);
|
||||
plat->trans_len = priv->trans_len;
|
||||
plat->buf_size = plat->reg_count * plat->trans_len;
|
||||
|
||||
plat->reg = calloc(1, plat->buf_size);
|
||||
if (!plat->reg) {
|
||||
debug("Canot allocate memory (%d B) for PMIC I2C emulation!\n",
|
||||
plat->buf_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
|
||||
plat->buf_size);
|
||||
|
||||
if (!reg_defaults) {
|
||||
pr_err("Property \"reg-defaults\" not found for device: %s!",
|
||||
emul->name);
|
||||
free(plat->reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(plat->reg, reg_defaults, plat->buf_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dm_i2c_ops sandbox_i2c_pmic_emul_ops = {
|
||||
.xfer = sandbox_i2c_pmic_xfer,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_i2c_pmic_ids[] = {
|
||||
{ .compatible = "sandbox,i2c-pmic" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_i2c_pmic_emul) = {
|
||||
.name = "sandbox_i2c_pmic_emul",
|
||||
.id = UCLASS_I2C_EMUL,
|
||||
.of_match = sandbox_i2c_pmic_ids,
|
||||
.ofdata_to_platdata = sandbox_i2c_pmic_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct sandbox_i2c_pmic_plat_data),
|
||||
.ops = &sandbox_i2c_pmic_emul_ops,
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
|
||||
* Keerthy <j-keerthy@ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/lp873x.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "ldo", .driver = LP873X_LDO_DRIVER },
|
||||
{ .prefix = "buck", .driver = LP873X_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int lp873x_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp873x_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp873x_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
printf("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops lp873x_ops = {
|
||||
.read = lp873x_read,
|
||||
.write = lp873x_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id lp873x_ids[] = {
|
||||
{ .compatible = "ti,lp8732", .data = LP8732 },
|
||||
{ .compatible = "ti,lp8733" , .data = LP8733 },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_lp873x) = {
|
||||
.name = "lp873x_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = lp873x_ids,
|
||||
.bind = lp873x_bind,
|
||||
.ops = &lp873x_ops,
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2017 Texas Instruments Incorporated, <www.ti.com>
|
||||
* Keerthy <j-keerthy@ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/lp87565.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "buck", .driver = LP87565_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int lp87565_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lp87565_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lp87565_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
printf("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops lp87565_ops = {
|
||||
.read = lp87565_read,
|
||||
.write = lp87565_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id lp87565_ids[] = {
|
||||
{ .compatible = "ti,lp87565", .data = LP87565 },
|
||||
{ .compatible = "ti,lp87565-q1", .data = LP87565_Q1 },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_lp87565) = {
|
||||
.name = "lp87565_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = lp87565_ids,
|
||||
.bind = lp87565_bind,
|
||||
.ops = &lp87565_ops,
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/max77686_pmic.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "LDO", .driver = MAX77686_LDO_DRIVER },
|
||||
{ .prefix = "BUCK", .driver = MAX77686_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int max77686_reg_count(struct udevice *dev)
|
||||
{
|
||||
return MAX77686_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int max77686_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77686_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77686_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "voltage-regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops max77686_ops = {
|
||||
.reg_count = max77686_reg_count,
|
||||
.read = max77686_read,
|
||||
.write = max77686_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id max77686_ids[] = {
|
||||
{ .compatible = "maxim,max77686" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_max77686) = {
|
||||
.name = "max77686_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = max77686_ids,
|
||||
.bind = max77686_bind,
|
||||
.ops = &max77686_ops,
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2016 Samsung Electronics
|
||||
* Jaehoon Chung <jh80.chung@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max8997_pmic.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int max8997_reg_count(struct udevice *dev)
|
||||
{
|
||||
return PMIC_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int max8997_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max8997_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops max8997_ops = {
|
||||
.reg_count = max8997_reg_count,
|
||||
.read = max8997_read,
|
||||
.write = max8997_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id max8997_ids[] = {
|
||||
{ .compatible = "maxim,max8997" },
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_max8997) = {
|
||||
.name = "max8997_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = max8997_ids,
|
||||
.ops = &max8997_ops,
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2016 Samsung Electronics
|
||||
* Jaehoon Chung <jh80.chung@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max8998_pmic.h>
|
||||
|
||||
static int max8998_reg_count(struct udevice *dev)
|
||||
{
|
||||
return PMIC_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int max8998_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max8998_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops max8998_ops = {
|
||||
.reg_count = max8998_reg_count,
|
||||
.read = max8998_read,
|
||||
.write = max8998_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id max8998_ids[] = {
|
||||
{ .compatible = "maxim,max8998" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_max8998) = {
|
||||
.name = "max8998_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = max8998_ids,
|
||||
.ops = &max8998_ops,
|
||||
};
|
||||
@@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018
|
||||
* Lukasz Majewski, DENX Software Engineering, lukma@denx.de
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fsl_pmic.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int mc34708_reg_count(struct udevice *dev)
|
||||
{
|
||||
return PMIC_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int mc34708_write(struct udevice *dev, uint reg, const u8 *buff,
|
||||
int len)
|
||||
{
|
||||
u8 buf[3] = { 0 };
|
||||
int ret;
|
||||
|
||||
if (len != MC34708_TRANSFER_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The MC34708 sends data with big endian format, hence we need to
|
||||
* perform manual byte swap.
|
||||
*/
|
||||
buf[0] = buff[2];
|
||||
buf[1] = buff[1];
|
||||
buf[2] = buff[0];
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buf, len);
|
||||
if (ret)
|
||||
printf("write error to device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mc34708_read(struct udevice *dev, uint reg, u8 *buff, int len)
|
||||
{
|
||||
u8 buf[3] = { 0 };
|
||||
int ret;
|
||||
|
||||
if (len != MC34708_TRANSFER_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buf, len);
|
||||
if (ret)
|
||||
printf("read error from device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
buff[0] = buf[2];
|
||||
buff[1] = buf[1];
|
||||
buff[2] = buf[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mc34708_probe(struct udevice *dev)
|
||||
{
|
||||
struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
|
||||
|
||||
priv->trans_len = MC34708_TRANSFER_SIZE;
|
||||
|
||||
/*
|
||||
* Handle PMIC Errata 37: APS mode not fully functional,
|
||||
* use explicit PWM or PFM instead
|
||||
*/
|
||||
pmic_clrsetbits(dev, MC34708_REG_SW12_OPMODE,
|
||||
MC34708_SW1AMODE_MASK | MC34708_SW2MODE_MASK,
|
||||
SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 14u));
|
||||
|
||||
pmic_clrsetbits(dev, MC34708_REG_SW345_OPMODE,
|
||||
MC34708_SW3MODE_MASK | MC34708_SW4AMODE_MASK |
|
||||
MC34708_SW4BMODE_MASK | MC34708_SW5MODE_MASK,
|
||||
SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 6u) |
|
||||
(SW_MODE_PWMPWM << 12u) | (SW_MODE_PWMPWM << 18u));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops mc34708_ops = {
|
||||
.reg_count = mc34708_reg_count,
|
||||
.read = mc34708_read,
|
||||
.write = mc34708_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id mc34708_ids[] = {
|
||||
{ .compatible = "fsl,mc34708" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_mc34708) = {
|
||||
.name = "mc34708_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = mc34708_ids,
|
||||
.probe = mc34708_probe,
|
||||
.ops = &mc34708_ops,
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Lukasz Majewski <l.majewski@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/power_chrg.h>
|
||||
#include <power/max8997_muic.h>
|
||||
#include <i2c.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int power_chrg_get_type(struct pmic *p)
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned char charge_type, charger;
|
||||
|
||||
if (pmic_probe(p))
|
||||
return CHARGER_NO;
|
||||
|
||||
pmic_reg_read(p, MAX8997_MUIC_STATUS2, &val);
|
||||
charge_type = val & MAX8997_MUIC_CHG_MASK;
|
||||
|
||||
switch (charge_type) {
|
||||
case MAX8997_MUIC_CHG_NO:
|
||||
charger = CHARGER_NO;
|
||||
break;
|
||||
case MAX8997_MUIC_CHG_USB:
|
||||
case MAX8997_MUIC_CHG_USB_D:
|
||||
charger = CHARGER_USB;
|
||||
break;
|
||||
case MAX8997_MUIC_CHG_TA:
|
||||
case MAX8997_MUIC_CHG_TA_1A:
|
||||
charger = CHARGER_TA;
|
||||
break;
|
||||
case MAX8997_MUIC_CHG_TA_500:
|
||||
charger = CHARGER_TA_500;
|
||||
break;
|
||||
default:
|
||||
charger = CHARGER_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return charger;
|
||||
}
|
||||
|
||||
static struct power_chrg power_chrg_muic_ops = {
|
||||
.chrg_type = power_chrg_get_type,
|
||||
};
|
||||
|
||||
int power_muic_init(unsigned int bus)
|
||||
{
|
||||
static const char name[] = "MAX8997_MUIC";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
debug("Board Micro USB Interface Controller init\n");
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = MUIC_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = MAX8997_MUIC_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
p->chrg = &power_chrg_muic_ops;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
|
||||
* Keerthy <j-keerthy@ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/palmas.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "ldo", .driver = PALMAS_LDO_DRIVER },
|
||||
{ .prefix = "smps", .driver = PALMAS_SMPS_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int palmas_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int palmas_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int palmas_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode pmic_node = ofnode_null(), regulators_node;
|
||||
ofnode subnode;
|
||||
int children;
|
||||
|
||||
dev_for_each_subnode(subnode, dev) {
|
||||
const char *name;
|
||||
char *temp;
|
||||
|
||||
name = ofnode_get_name(subnode);
|
||||
temp = strstr(name, "pmic");
|
||||
if (temp) {
|
||||
pmic_node = subnode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ofnode_valid(pmic_node)) {
|
||||
debug("%s: %s pmic subnode not found!\n", __func__, dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
regulators_node = ofnode_find_subnode(pmic_node, "regulators");
|
||||
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s reg subnode not found!\n", __func__, dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops palmas_ops = {
|
||||
.read = palmas_read,
|
||||
.write = palmas_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id palmas_ids[] = {
|
||||
{ .compatible = "ti,tps659038", .data = TPS659038 },
|
||||
{ .compatible = "ti,tps65917" , .data = TPS65917 },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_palmas) = {
|
||||
.name = "palmas_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = palmas_ids,
|
||||
.bind = palmas_bind,
|
||||
.ops = &palmas_ops,
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc
|
||||
* Peng Fan <Peng.Fan@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/pfuze100_pmic.h>
|
||||
#include <power/pfuze3000_pmic.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
/* sw[x], swbst */
|
||||
{ .prefix = "s", .driver = PFUZE100_REGULATOR_DRIVER },
|
||||
/* vgen[x], vsnvs, vcc, v33, vcc_sd */
|
||||
{ .prefix = "v", .driver = PFUZE100_REGULATOR_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int pfuze100_reg_count(struct udevice *dev)
|
||||
{
|
||||
return dev->driver_data == PFUZE3000 ? PFUZE3000_NUM_OF_REGS : PFUZE100_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pfuze100_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops pfuze100_ops = {
|
||||
.reg_count = pfuze100_reg_count,
|
||||
.read = pfuze100_read,
|
||||
.write = pfuze100_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id pfuze100_ids[] = {
|
||||
{ .compatible = "fsl,pfuze100", .data = PFUZE100, },
|
||||
{ .compatible = "fsl,pfuze200", .data = PFUZE200, },
|
||||
{ .compatible = "fsl,pfuze3000", .data = PFUZE3000, },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_pfuze100) = {
|
||||
.name = "pfuze100 pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = pfuze100_ids,
|
||||
.bind = pfuze100_bind,
|
||||
.ops = &pfuze100_ops,
|
||||
};
|
||||
@@ -0,0 +1,86 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Qualcomm pm8916 pmic driver
|
||||
*
|
||||
* (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <power/pmic.h>
|
||||
#include <spmi/spmi.h>
|
||||
|
||||
#define PID_SHIFT 8
|
||||
#define PID_MASK (0xFF << PID_SHIFT)
|
||||
#define REG_MASK 0xFF
|
||||
|
||||
struct pm8916_priv {
|
||||
uint32_t usid; /* Slave ID on SPMI bus */
|
||||
};
|
||||
|
||||
static int pm8916_reg_count(struct udevice *dev)
|
||||
{
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
static int pm8916_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
struct pm8916_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (len != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return spmi_reg_write(dev->parent, priv->usid,
|
||||
(reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK,
|
||||
*buff);
|
||||
}
|
||||
|
||||
static int pm8916_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
struct pm8916_priv *priv = dev_get_priv(dev);
|
||||
int val;
|
||||
|
||||
if (len != 1)
|
||||
return -EINVAL;
|
||||
|
||||
val = spmi_reg_read(dev->parent, priv->usid,
|
||||
(reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK);
|
||||
|
||||
if (val < 0)
|
||||
return val;
|
||||
*buff = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops pm8916_ops = {
|
||||
.reg_count = pm8916_reg_count,
|
||||
.read = pm8916_read,
|
||||
.write = pm8916_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id pm8916_ids[] = {
|
||||
{ .compatible = "qcom,spmi-pmic" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int pm8916_probe(struct udevice *dev)
|
||||
{
|
||||
struct pm8916_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->usid = dev_read_addr(dev);
|
||||
|
||||
if (priv->usid == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(pmic_pm8916) = {
|
||||
.name = "pmic_pm8916",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = pm8916_ids,
|
||||
.bind = dm_scan_fdt_dev,
|
||||
.probe = pm8916_probe,
|
||||
.ops = &pm8916_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct pm8916_priv),
|
||||
};
|
||||
@@ -0,0 +1,199 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <vsprintf.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <power/pmic.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
|
||||
int pmic_bind_children(struct udevice *pmic, ofnode parent,
|
||||
const struct pmic_child_info *child_info)
|
||||
{
|
||||
const struct pmic_child_info *info;
|
||||
struct driver *drv;
|
||||
struct udevice *child;
|
||||
const char *node_name;
|
||||
const char *reg_name;
|
||||
int bind_count = 0;
|
||||
ofnode node;
|
||||
int prefix_len;
|
||||
int ret;
|
||||
|
||||
debug("%s for '%s' at node offset: %d\n", __func__, pmic->name,
|
||||
dev_of_offset(pmic));
|
||||
|
||||
ofnode_for_each_subnode(node, parent) {
|
||||
node_name = ofnode_get_name(node);
|
||||
|
||||
debug("* Found child node: '%s'\n", node_name);
|
||||
|
||||
child = NULL;
|
||||
for (info = child_info; info->prefix && info->driver; info++) {
|
||||
debug(" - compatible prefix: '%s'\n", info->prefix);
|
||||
|
||||
prefix_len = strlen(info->prefix);
|
||||
if (strncmp(info->prefix, node_name, prefix_len)) {
|
||||
reg_name = ofnode_read_string(node,
|
||||
"regulator-name");
|
||||
if (!reg_name)
|
||||
continue;
|
||||
if (strncmp(info->prefix, reg_name, prefix_len))
|
||||
continue;
|
||||
}
|
||||
|
||||
drv = lists_driver_lookup_name(info->driver);
|
||||
if (!drv) {
|
||||
debug(" - driver: '%s' not found!\n",
|
||||
info->driver);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug(" - found child driver: '%s'\n", drv->name);
|
||||
|
||||
ret = device_bind_with_driver_data(pmic, drv, node_name,
|
||||
0, node, &child);
|
||||
if (ret) {
|
||||
debug(" - child binding error: %d\n", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug(" - bound child device: '%s'\n", child->name);
|
||||
|
||||
child->driver_data = trailing_strtol(node_name);
|
||||
|
||||
debug(" - set 'child->driver_data': %lu\n",
|
||||
child->driver_data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (child)
|
||||
bind_count++;
|
||||
else
|
||||
debug(" - compatible prefix not found\n");
|
||||
}
|
||||
|
||||
debug("Bound: %d children for PMIC: '%s'\n", bind_count, pmic->name);
|
||||
return bind_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
int pmic_get(const char *name, struct udevice **devp)
|
||||
{
|
||||
return uclass_get_device_by_name(UCLASS_PMIC, name, devp);
|
||||
}
|
||||
|
||||
int pmic_reg_count(struct udevice *dev)
|
||||
{
|
||||
const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
|
||||
|
||||
if (!ops || !ops->reg_count)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->reg_count(dev);
|
||||
}
|
||||
|
||||
int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len)
|
||||
{
|
||||
const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
|
||||
|
||||
if (!buffer)
|
||||
return -EFAULT;
|
||||
|
||||
if (!ops || !ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->read(dev, reg, buffer, len);
|
||||
}
|
||||
|
||||
int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
|
||||
{
|
||||
const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
|
||||
|
||||
if (!buffer)
|
||||
return -EFAULT;
|
||||
|
||||
if (!ops || !ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->write(dev, reg, buffer, len);
|
||||
}
|
||||
|
||||
int pmic_reg_read(struct udevice *dev, uint reg)
|
||||
{
|
||||
struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
if (priv->trans_len < 1 || priv->trans_len > sizeof(val)) {
|
||||
debug("Wrong transmission size [%d]\n", priv->trans_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("%s: reg=%x priv->trans_len:%d", __func__, reg, priv->trans_len);
|
||||
ret = pmic_read(dev, reg, (uint8_t *)&val, priv->trans_len);
|
||||
debug(", value=%x, ret=%d\n", val, ret);
|
||||
|
||||
return ret ? ret : val;
|
||||
}
|
||||
|
||||
int pmic_reg_write(struct udevice *dev, uint reg, uint value)
|
||||
{
|
||||
struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
|
||||
int ret;
|
||||
|
||||
if (priv->trans_len < 1 || priv->trans_len > sizeof(value)) {
|
||||
debug("Wrong transmission size [%d]\n", priv->trans_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("%s: reg=%x, value=%x priv->trans_len:%d", __func__, reg, value,
|
||||
priv->trans_len);
|
||||
ret = pmic_write(dev, reg, (uint8_t *)&value, priv->trans_len);
|
||||
debug(", ret=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
|
||||
{
|
||||
struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
if (priv->trans_len < 1 || priv->trans_len > sizeof(val)) {
|
||||
debug("Wrong transmission size [%d]\n", priv->trans_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pmic_read(dev, reg, (uint8_t *)&val, priv->trans_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = (val & ~clr) | set;
|
||||
return pmic_write(dev, reg, (uint8_t *)&val, priv->trans_len);
|
||||
}
|
||||
|
||||
static int pmic_pre_probe(struct udevice *dev)
|
||||
{
|
||||
struct uc_pmic_priv *pmic_priv = dev_get_uclass_priv(dev);
|
||||
|
||||
pmic_priv->trans_len = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(pmic) = {
|
||||
.id = UCLASS_PMIC,
|
||||
.name = "pmic",
|
||||
.pre_probe = pmic_pre_probe,
|
||||
.per_device_auto_alloc_size = sizeof(struct uc_pmic_priv),
|
||||
};
|
||||
@@ -0,0 +1,132 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Linaro
|
||||
* Peter Griffin <peter.griffin@linaro.org>
|
||||
*/
|
||||
#include <asm/io.h>
|
||||
#include <common.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max8997_muic.h>
|
||||
#include <power/hi6553_pmic.h>
|
||||
#include <errno.h>
|
||||
|
||||
u8 *pmussi_base;
|
||||
|
||||
uint8_t hi6553_readb(u32 offset)
|
||||
{
|
||||
return readb(pmussi_base + (offset << 2));
|
||||
}
|
||||
|
||||
void hi6553_writeb(u32 offset, uint8_t value)
|
||||
{
|
||||
writeb(value, pmussi_base + (offset << 2));
|
||||
}
|
||||
|
||||
int pmic_reg_write(struct pmic *p, u32 reg, u32 val)
|
||||
{
|
||||
if (check_reg(p, reg))
|
||||
return -EINVAL;
|
||||
|
||||
hi6553_writeb(reg, (uint8_t)val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pmic_reg_read(struct pmic *p, u32 reg, u32 *val)
|
||||
{
|
||||
if (check_reg(p, reg))
|
||||
return -EINVAL;
|
||||
|
||||
*val = (u32)hi6553_readb(reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hi6553_init(void)
|
||||
{
|
||||
int data;
|
||||
|
||||
hi6553_writeb(HI6553_PERI_EN_MARK, 0x1e);
|
||||
hi6553_writeb(HI6553_NP_REG_ADJ1, 0);
|
||||
data = HI6553_DISABLE6_XO_CLK_CONN | HI6553_DISABLE6_XO_CLK_NFC |
|
||||
HI6553_DISABLE6_XO_CLK_RF1 | HI6553_DISABLE6_XO_CLK_RF2;
|
||||
hi6553_writeb(HI6553_DISABLE6_XO_CLK, data);
|
||||
|
||||
/* configure BUCK0 & BUCK1 */
|
||||
hi6553_writeb(HI6553_BUCK01_CTRL2, 0x5e);
|
||||
hi6553_writeb(HI6553_BUCK0_CTRL7, 0x10);
|
||||
hi6553_writeb(HI6553_BUCK1_CTRL7, 0x10);
|
||||
hi6553_writeb(HI6553_BUCK0_CTRL5, 0x1e);
|
||||
hi6553_writeb(HI6553_BUCK1_CTRL5, 0x1e);
|
||||
hi6553_writeb(HI6553_BUCK0_CTRL1, 0xfc);
|
||||
hi6553_writeb(HI6553_BUCK1_CTRL1, 0xfc);
|
||||
|
||||
/* configure BUCK2 */
|
||||
hi6553_writeb(HI6553_BUCK2_REG1, 0x4f);
|
||||
hi6553_writeb(HI6553_BUCK2_REG5, 0x99);
|
||||
hi6553_writeb(HI6553_BUCK2_REG6, 0x45);
|
||||
mdelay(1);
|
||||
hi6553_writeb(HI6553_VSET_BUCK2_ADJ, 0x22);
|
||||
mdelay(1);
|
||||
|
||||
/* configure BUCK3 */
|
||||
hi6553_writeb(HI6553_BUCK3_REG3, 0x02);
|
||||
hi6553_writeb(HI6553_BUCK3_REG5, 0x99);
|
||||
hi6553_writeb(HI6553_BUCK3_REG6, 0x41);
|
||||
hi6553_writeb(HI6553_VSET_BUCK3_ADJ, 0x02);
|
||||
mdelay(1);
|
||||
|
||||
/* configure BUCK4 */
|
||||
hi6553_writeb(HI6553_BUCK4_REG2, 0x9a);
|
||||
hi6553_writeb(HI6553_BUCK4_REG5, 0x99);
|
||||
hi6553_writeb(HI6553_BUCK4_REG6, 0x45);
|
||||
|
||||
/* configure LDO20 */
|
||||
hi6553_writeb(HI6553_LDO20_REG_ADJ, 0x50);
|
||||
|
||||
hi6553_writeb(HI6553_NP_REG_CHG, 0x0f);
|
||||
hi6553_writeb(HI6553_CLK_TOP0, 0x06);
|
||||
hi6553_writeb(HI6553_CLK_TOP3, 0xc0);
|
||||
hi6553_writeb(HI6553_CLK_TOP4, 0x00);
|
||||
|
||||
/* configure LDO7 & LDO10 for SD slot */
|
||||
data = hi6553_readb(HI6553_LDO7_REG_ADJ);
|
||||
data = (data & 0xf8) | 0x2;
|
||||
hi6553_writeb(HI6553_LDO7_REG_ADJ, data);
|
||||
mdelay(5);
|
||||
/* enable LDO7 */
|
||||
hi6553_writeb(HI6553_ENABLE2_LDO1_8, 1 << 6);
|
||||
mdelay(5);
|
||||
data = hi6553_readb(HI6553_LDO10_REG_ADJ);
|
||||
data = (data & 0xf8) | 0x5;
|
||||
hi6553_writeb(HI6553_LDO10_REG_ADJ, data);
|
||||
mdelay(5);
|
||||
/* enable LDO10 */
|
||||
hi6553_writeb(HI6553_ENABLE3_LDO9_16, 1 << 1);
|
||||
mdelay(5);
|
||||
|
||||
/* select 32.764KHz */
|
||||
hi6553_writeb(HI6553_CLK19M2_600_586_EN, 0x01);
|
||||
}
|
||||
|
||||
int power_hi6553_init(u8 *base)
|
||||
{
|
||||
static const char name[] = "HI6553 PMIC";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_NONE;
|
||||
p->number_of_regs = 44;
|
||||
pmussi_base = base;
|
||||
|
||||
hi6553_init();
|
||||
|
||||
puts("HI6553 PMIC init\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014 Gateworks Corporation
|
||||
* Tim Harvey <tharvey@gateworks.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/ltc3676_pmic.h>
|
||||
|
||||
int power_ltc3676_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "LTC3676_PMIC";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = LTC3676_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = CONFIG_POWER_LTC3676_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc.
|
||||
* Fabio Estevam <fabio.estevam@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max77696_pmic.h>
|
||||
|
||||
int power_max77696_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "MAX77696";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = PMIC_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = CONFIG_POWER_MAX77696_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Lukasz Majewski <l.majewski@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max8997_pmic.h>
|
||||
#include <i2c.h>
|
||||
#include <errno.h>
|
||||
|
||||
unsigned char max8997_reg_ldo(int uV)
|
||||
{
|
||||
unsigned char ret;
|
||||
if (uV <= 800000)
|
||||
return 0;
|
||||
if (uV >= 3950000)
|
||||
return MAX8997_LDO_MAX_VAL;
|
||||
ret = (uV - 800000) / 50000;
|
||||
if (ret > MAX8997_LDO_MAX_VAL) {
|
||||
printf("MAX8997 LDO SETTING ERROR (%duV) -> %u\n", uV, ret);
|
||||
ret = MAX8997_LDO_MAX_VAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmic_charger_state(struct pmic *p, int state, int current)
|
||||
{
|
||||
unsigned char fc;
|
||||
u32 val = 0;
|
||||
|
||||
if (pmic_probe(p))
|
||||
return -ENODEV;
|
||||
|
||||
if (state == PMIC_CHARGER_DISABLE) {
|
||||
puts("Disable the charger.\n");
|
||||
pmic_reg_read(p, MAX8997_REG_MBCCTRL2, &val);
|
||||
val &= ~(MBCHOSTEN | VCHGR_FC);
|
||||
pmic_reg_write(p, MAX8997_REG_MBCCTRL2, val);
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (current < CHARGER_MIN_CURRENT || current > CHARGER_MAX_CURRENT) {
|
||||
printf("%s: Wrong charge current: %d [mA]\n",
|
||||
__func__, current);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fc = (current - CHARGER_MIN_CURRENT) / CHARGER_CURRENT_RESOLUTION;
|
||||
fc = fc & 0xf; /* up to 950 mA */
|
||||
|
||||
printf("Enable the charger @ %d [mA]\n", fc * CHARGER_CURRENT_RESOLUTION
|
||||
+ CHARGER_MIN_CURRENT);
|
||||
|
||||
val = fc | MBCICHFCSET;
|
||||
pmic_reg_write(p, MAX8997_REG_MBCCTRL4, val);
|
||||
|
||||
pmic_reg_read(p, MAX8997_REG_MBCCTRL2, &val);
|
||||
val = MBCHOSTEN | VCHGR_FC; /* enable charger & fast charge */
|
||||
pmic_reg_write(p, MAX8997_REG_MBCCTRL2, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmic_charger_bat_present(struct pmic *p)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (pmic_probe(p))
|
||||
return -ENODEV;
|
||||
|
||||
pmic_reg_read(p, MAX8997_REG_STATUS4, &val);
|
||||
|
||||
return !(val & DETBAT);
|
||||
}
|
||||
|
||||
static struct power_chrg power_chrg_pmic_ops = {
|
||||
.chrg_bat_present = pmic_charger_bat_present,
|
||||
.chrg_state = pmic_charger_state,
|
||||
};
|
||||
|
||||
int pmic_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "MAX8997_PMIC";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
debug("Board PMIC init\n");
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = PMIC_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = MAX8997_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
p->chrg = &power_chrg_pmic_ops;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2011 Samsung Electronics
|
||||
* Lukasz Majewski <l.majewski@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max8998_pmic.h>
|
||||
#include <errno.h>
|
||||
|
||||
int pmic_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "MAX8998_PMIC";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
puts("Board PMIC init\n");
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = PMIC_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = MAX8998_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2016 Freescale Semiconductor, Inc.
|
||||
* Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/mc34vr500_pmic.h>
|
||||
|
||||
int power_mc34vr500_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "MC34VR500";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = MC34VR500_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = MC34VR500_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014 Gateworks Corporation
|
||||
* Tim Harvey <tharvey@gateworks.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/pfuze100_pmic.h>
|
||||
|
||||
int power_pfuze100_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "PFUZE100";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = PFUZE100_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = CONFIG_POWER_PFUZE100_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc.
|
||||
* Peng Fan <Peng.Fan@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/pfuze3000_pmic.h>
|
||||
|
||||
int power_pfuze3000_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "PFUZE3000";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = PFUZE3000_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = CONFIG_POWER_PFUZE3000_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2014 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Author: Felipe Balbi <balbi@ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <linux/errno.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/tps62362.h>
|
||||
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct udevice *tps62362_dev __attribute__((section(".data"))) = NULL;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tps62362_voltage_update() - Function to change a voltage level, as this
|
||||
* is a multi-step process.
|
||||
* @reg: Register address to write to
|
||||
* @volt_sel: Voltage register value to write
|
||||
* @return: 0 on success, 1 on failure
|
||||
*/
|
||||
int tps62362_voltage_update(unsigned char reg, unsigned char volt_sel)
|
||||
{
|
||||
if (reg > TPS62362_NUM_REGS)
|
||||
return 1;
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
return i2c_write(TPS62362_I2C_ADDR, reg, 1, &volt_sel, 1);
|
||||
#else
|
||||
if (!tps62362_dev)
|
||||
return -ENODEV;
|
||||
return dm_i2c_reg_write(tps62362_dev, reg, volt_sel);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
int power_tps62362_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "TPS62362";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = TPS62362_NUM_REGS;
|
||||
p->hw.i2c.addr = TPS62362_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int power_tps62362_init(unsigned char bus)
|
||||
{
|
||||
struct udevice *dev = NULL;
|
||||
int rc;
|
||||
|
||||
rc = i2c_get_chip_for_busnum(bus, TPS62362_I2C_ADDR, 1, &dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
tps62362_dev = dev;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2011-2013
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <power/tps65217.h>
|
||||
|
||||
struct udevice *tps65217_dev __attribute__((section(".data"))) = NULL;
|
||||
|
||||
/**
|
||||
* tps65217_reg_read() - Generic function that can read a TPS65217 register
|
||||
* @src_reg: Source register address
|
||||
* @src_val: Address of destination variable
|
||||
* @return: 0 for success, not 0 on failure.
|
||||
*/
|
||||
int tps65217_reg_read(uchar src_reg, uchar *src_val)
|
||||
{
|
||||
#ifndef CONFIG_DM_I2C
|
||||
return i2c_read(TPS65217_CHIP_PM, src_reg, 1, src_val, 1);
|
||||
#else
|
||||
return dm_i2c_read(tps65217_dev, src_reg, src_val, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* tps65217_reg_write() - Generic function that can write a TPS65217 PMIC
|
||||
* register or bit field regardless of protection
|
||||
* level.
|
||||
*
|
||||
* @prot_level: Register password protection. Use
|
||||
* TPS65217_PROT_LEVEL_NONE,
|
||||
* TPS65217_PROT_LEVEL_1 or TPS65217_PROT_LEVEL_2
|
||||
* @dest_reg: Register address to write.
|
||||
* @dest_val: Value to write.
|
||||
* @mask: Bit mask (8 bits) to be applied. Function will only
|
||||
* change bits that are set in the bit mask.
|
||||
*
|
||||
* @return: 0 for success, not 0 on failure, as per the i2c API
|
||||
*/
|
||||
int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
|
||||
uchar mask)
|
||||
{
|
||||
uchar read_val;
|
||||
uchar xor_reg;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If we are affecting only a bit field, read dest_reg and apply the
|
||||
* mask
|
||||
*/
|
||||
if (mask != TPS65217_MASK_ALL_BITS) {
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(TPS65217_CHIP_PM, dest_reg, 1, &read_val, 1);
|
||||
#else
|
||||
ret = dm_i2c_read(tps65217_dev, dest_reg, &read_val, 1);
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
read_val &= (~mask);
|
||||
read_val |= (dest_val & mask);
|
||||
dest_val = read_val;
|
||||
}
|
||||
|
||||
if (prot_level > 0) {
|
||||
xor_reg = dest_reg ^ TPS65217_PASSWORD_UNLOCK;
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
|
||||
&xor_reg, 1);
|
||||
#else
|
||||
ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
|
||||
&xor_reg, 1);
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
|
||||
#else
|
||||
ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (prot_level == TPS65217_PROT_LEVEL_2) {
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
|
||||
&xor_reg, 1);
|
||||
#else
|
||||
ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
|
||||
&xor_reg, 1);
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
|
||||
#else
|
||||
ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tps65217_voltage_update() - Function to change a voltage level, as this
|
||||
* is a multi-step process.
|
||||
* @dc_cntrl_reg: DC voltage control register to change.
|
||||
* @volt_sel: New value for the voltage register
|
||||
* @return: 0 for success, not 0 on failure.
|
||||
*/
|
||||
int tps65217_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
|
||||
{
|
||||
if ((dc_cntrl_reg != TPS65217_DEFDCDC1) &&
|
||||
(dc_cntrl_reg != TPS65217_DEFDCDC2) &&
|
||||
(dc_cntrl_reg != TPS65217_DEFDCDC3))
|
||||
return 1;
|
||||
|
||||
/* set voltage level */
|
||||
if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
|
||||
TPS65217_MASK_ALL_BITS))
|
||||
return 1;
|
||||
|
||||
/* set GO bit to initiate voltage transition */
|
||||
if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, TPS65217_DEFSLEW,
|
||||
TPS65217_DCDC_GO, TPS65217_DCDC_GO))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int power_tps65217_init(unsigned char bus)
|
||||
{
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct udevice *dev = NULL;
|
||||
int rc;
|
||||
|
||||
rc = i2c_get_chip_for_busnum(bus, TPS65217_CHIP_PM, 1, &dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
tps65217_dev = dev;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2011-2013
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <linux/errno.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/tps65218.h>
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
|
||||
{
|
||||
uchar read_val;
|
||||
int ret;
|
||||
|
||||
ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*dest_val = read_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tps65218_reg_write() - Generic function that can write a TPS65218 PMIC
|
||||
* register or bit field regardless of protection
|
||||
* level.
|
||||
*
|
||||
* @prot_level: Register password protection. Use
|
||||
* TPS65218_PROT_LEVEL_NONE,
|
||||
* TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2
|
||||
* @dest_reg: Register address to write.
|
||||
* @dest_val: Value to write.
|
||||
* @mask: Bit mask (8 bits) to be applied. Function will only
|
||||
* change bits that are set in the bit mask.
|
||||
*
|
||||
* @return: 0 for success, not 0 on failure, as per the i2c API
|
||||
*/
|
||||
int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
|
||||
uchar mask)
|
||||
{
|
||||
uchar read_val;
|
||||
uchar xor_reg;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If we are affecting only a bit field, read dest_reg and apply the
|
||||
* mask
|
||||
*/
|
||||
if (mask != TPS65218_MASK_ALL_BITS) {
|
||||
ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
read_val &= (~mask);
|
||||
read_val |= (dest_val & mask);
|
||||
dest_val = read_val;
|
||||
}
|
||||
|
||||
if (prot_level > 0) {
|
||||
xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
|
||||
ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
|
||||
&xor_reg, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (prot_level == TPS65218_PROT_LEVEL_2) {
|
||||
ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
|
||||
&xor_reg, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
struct udevice *tps65218_dev __attribute__((section(".data"))) = NULL;
|
||||
|
||||
int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
|
||||
{
|
||||
uchar read_val;
|
||||
int ret;
|
||||
|
||||
if (!tps65218_dev)
|
||||
return -ENODEV;
|
||||
|
||||
ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*dest_val = read_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
|
||||
uchar mask)
|
||||
{
|
||||
uchar read_val;
|
||||
uchar xor_reg;
|
||||
int ret;
|
||||
|
||||
if (!tps65218_dev)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* If we are affecting only a bit field, read dest_reg and apply the
|
||||
* mask
|
||||
*/
|
||||
if (mask != TPS65218_MASK_ALL_BITS) {
|
||||
ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
read_val &= (~mask);
|
||||
read_val |= (dest_val & mask);
|
||||
dest_val = read_val;
|
||||
}
|
||||
|
||||
if (prot_level > 0) {
|
||||
xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
|
||||
ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
|
||||
1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (prot_level == TPS65218_PROT_LEVEL_2) {
|
||||
ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
|
||||
1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tps65218_voltage_update() - Function to change a voltage level, as this
|
||||
* is a multi-step process.
|
||||
* @dc_cntrl_reg: DC voltage control register to change.
|
||||
* @volt_sel: New value for the voltage register
|
||||
* @return: 0 for success, not 0 on failure.
|
||||
*/
|
||||
int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
|
||||
{
|
||||
if ((dc_cntrl_reg != TPS65218_DCDC1) &&
|
||||
(dc_cntrl_reg != TPS65218_DCDC2) &&
|
||||
(dc_cntrl_reg != TPS65218_DCDC3))
|
||||
return 1;
|
||||
|
||||
/* set voltage level */
|
||||
if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
|
||||
TPS65218_DCDC_VSEL_MASK))
|
||||
return 1;
|
||||
|
||||
/* set GO bit to initiate voltage transition */
|
||||
if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
|
||||
TPS65218_DCDC_GO, TPS65218_DCDC_GO))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit.
|
||||
*
|
||||
* @return: 0 on success, -EBADE if the sequence was broken
|
||||
*/
|
||||
int tps65218_toggle_fseal(void)
|
||||
{
|
||||
if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
|
||||
0xb1, TPS65218_MASK_ALL_BITS))
|
||||
return -EBADE;
|
||||
|
||||
if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
|
||||
0xfe, TPS65218_MASK_ALL_BITS))
|
||||
return -EBADE;
|
||||
|
||||
if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
|
||||
0xa3, TPS65218_MASK_ALL_BITS))
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1.
|
||||
*
|
||||
* The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be
|
||||
* toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch
|
||||
* its value is locked and can only be reset by powering off the PMIC entirely.
|
||||
*
|
||||
* @return: 0 on success, -EBADE if the sequence was broken
|
||||
*/
|
||||
int tps65218_lock_fseal(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
if (tps65218_toggle_fseal())
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
int power_tps65218_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = "TPS65218_PMIC";
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
printf("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = PMIC_I2C;
|
||||
p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS;
|
||||
p->hw.i2c.addr = TPS65218_CHIP_PM;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int power_tps65218_init(unsigned char bus)
|
||||
{
|
||||
struct udevice *dev = NULL;
|
||||
int rc;
|
||||
|
||||
rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
tps65218_dev = dev;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2011-2013
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <power/tps65910.h>
|
||||
|
||||
struct udevice *tps65910_dev __attribute__((section(".data"))) = NULL;
|
||||
|
||||
static inline int tps65910_read_reg(int addr, uchar *buf)
|
||||
{
|
||||
#ifndef CONFIG_DM_I2C
|
||||
return i2c_read(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1);
|
||||
#else
|
||||
int rc;
|
||||
|
||||
rc = dm_i2c_reg_read(tps65910_dev, addr);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
*buf = (uchar)rc;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int tps65910_write_reg(int addr, uchar *buf)
|
||||
{
|
||||
#ifndef CONFIG_DM_I2C
|
||||
return i2c_write(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1);
|
||||
#else
|
||||
return dm_i2c_reg_write(tps65910_dev, addr, *buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
int power_tps65910_init(unsigned char bus)
|
||||
{
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct udevice *dev = NULL;
|
||||
int rc;
|
||||
|
||||
rc = i2c_get_chip_for_busnum(bus, TPS65910_CTRL_I2C_ADDR, 1, &dev);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
tps65910_dev = dev;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tps65910_set_i2c_control() - Set the TPS65910 to be controlled via the I2C
|
||||
* interface.
|
||||
* @return: 0 on success, not 0 on failure
|
||||
*/
|
||||
int tps65910_set_i2c_control(void)
|
||||
{
|
||||
int ret;
|
||||
uchar buf;
|
||||
|
||||
/* VDD1/2 voltage selection register access by control i/f */
|
||||
ret = tps65910_read_reg(TPS65910_DEVCTRL_REG, &buf);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf |= TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C;
|
||||
|
||||
return tps65910_write_reg(TPS65910_DEVCTRL_REG, &buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* tps65910_voltage_update() - Voltage switching for MPU frequency switching.
|
||||
* @module: mpu - 0, core - 1
|
||||
* @vddx_op_vol_sel: vdd voltage to set
|
||||
* @return: 0 on success, not 0 on failure
|
||||
*/
|
||||
int tps65910_voltage_update(unsigned int module, unsigned char vddx_op_vol_sel)
|
||||
{
|
||||
uchar buf;
|
||||
unsigned int reg_offset;
|
||||
int ret;
|
||||
|
||||
if (module == MPU)
|
||||
reg_offset = TPS65910_VDD1_OP_REG;
|
||||
else
|
||||
reg_offset = TPS65910_VDD2_OP_REG;
|
||||
|
||||
/* Select VDDx OP */
|
||||
ret = tps65910_read_reg(reg_offset, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf &= ~TPS65910_OP_REG_CMD_MASK;
|
||||
|
||||
ret = tps65910_write_reg(reg_offset, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure VDDx OP Voltage */
|
||||
ret = tps65910_read_reg(reg_offset, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf &= ~TPS65910_OP_REG_SEL_MASK;
|
||||
buf |= vddx_op_vol_sel;
|
||||
|
||||
ret = tps65910_write_reg(reg_offset, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tps65910_read_reg(reg_offset, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((buf & TPS65910_OP_REG_SEL_MASK) != vddx_op_vol_sel)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/tps65910_pmic.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "ldo_", .driver = TPS65910_LDO_DRIVER },
|
||||
{ .prefix = "buck_", .driver = TPS65910_BUCK_DRIVER },
|
||||
{ .prefix = "boost_", .driver = TPS65910_BOOST_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int pmic_tps65910_reg_count(struct udevice *dev)
|
||||
{
|
||||
return TPS65910_NUM_REGS;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_write(struct udevice *dev, uint reg, const u8 *buffer,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buffer, len);
|
||||
if (ret)
|
||||
pr_err("%s write error on register %02x\n", dev->name, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buffer, len);
|
||||
if (ret)
|
||||
pr_err("%s read error on register %02x\n", dev->name, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s regulators subnode not found\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s has no children (regulators)\n", dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_probe(struct udevice *dev)
|
||||
{
|
||||
/* use I2C control interface instead of I2C smartreflex interface to
|
||||
* access smartrefelex registers VDD1_OP_REG, VDD1_SR_REG, VDD2_OP_REG
|
||||
* and VDD2_SR_REG
|
||||
*/
|
||||
return pmic_clrsetbits(dev, TPS65910_REG_DEVICE_CTRL, 0,
|
||||
TPS65910_I2C_SEL_MASK);
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops pmic_tps65910_ops = {
|
||||
.reg_count = pmic_tps65910_reg_count,
|
||||
.read = pmic_tps65910_read,
|
||||
.write = pmic_tps65910_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id pmic_tps65910_match[] = {
|
||||
{ .compatible = "ti,tps65910" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_tps65910) = {
|
||||
.name = "pmic_tps65910",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = pmic_tps65910_match,
|
||||
.bind = pmic_tps65910_bind,
|
||||
.probe = pmic_tps65910_probe,
|
||||
.ops = &pmic_tps65910_ops,
|
||||
};
|
||||
@@ -0,0 +1,195 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <power/rk8xx_pmic.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
static struct reg_data rk817_init_reg[] = {
|
||||
/* enable the under-voltage protection,
|
||||
* the under-voltage protection will shutdown the LDO3 and reset the PMIC
|
||||
*/
|
||||
{ RK817_BUCK4_CMIN, 0x60, 0x60},
|
||||
};
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
|
||||
{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
|
||||
{ .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int rk8xx_reg_count(struct udevice *dev)
|
||||
{
|
||||
return RK808_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret) {
|
||||
debug("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret) {
|
||||
debug("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
|
||||
static int rk8xx_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rk8xx_probe(struct udevice *dev)
|
||||
{
|
||||
struct rk8xx_priv *priv = dev_get_priv(dev);
|
||||
struct reg_data *init_data = NULL;
|
||||
int init_data_num = 0;
|
||||
int ret = 0, i, show_variant;
|
||||
u8 msb, lsb, id_msb, id_lsb;
|
||||
u8 on_source = 0, off_source = 0;
|
||||
u8 power_en0, power_en1, power_en2, power_en3;
|
||||
u8 value;
|
||||
|
||||
/* read Chip variant */
|
||||
if (device_is_compatible(dev, "rockchip,rk817") ||
|
||||
device_is_compatible(dev, "rockchip,rk809")) {
|
||||
id_msb = RK817_ID_MSB;
|
||||
id_lsb = RK817_ID_LSB;
|
||||
} else {
|
||||
id_msb = ID_MSB;
|
||||
id_lsb = ID_LSB;
|
||||
}
|
||||
|
||||
ret = rk8xx_read(dev, id_msb, &msb, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = rk8xx_read(dev, id_lsb, &lsb, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
|
||||
show_variant = priv->variant;
|
||||
switch (priv->variant) {
|
||||
case RK808_ID:
|
||||
show_variant = 0x808; /* RK808 hardware ID is 0 */
|
||||
break;
|
||||
case RK805_ID:
|
||||
case RK816_ID:
|
||||
case RK818_ID:
|
||||
on_source = RK8XX_ON_SOURCE;
|
||||
off_source = RK8XX_OFF_SOURCE;
|
||||
break;
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
on_source = RK817_ON_SOURCE;
|
||||
off_source = RK817_OFF_SOURCE;
|
||||
init_data = rk817_init_reg;
|
||||
init_data_num = ARRAY_SIZE(rk817_init_reg);
|
||||
power_en0 = pmic_reg_read(dev, RK817_POWER_EN0);
|
||||
power_en1 = pmic_reg_read(dev, RK817_POWER_EN1);
|
||||
power_en2 = pmic_reg_read(dev, RK817_POWER_EN2);
|
||||
power_en3 = pmic_reg_read(dev, RK817_POWER_EN3);
|
||||
|
||||
value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
|
||||
pmic_reg_write(dev, RK817_POWER_EN_SAVE0, value);
|
||||
value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
|
||||
pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown PMIC: RK%x!!\n", priv->variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < init_data_num; i++) {
|
||||
ret = pmic_clrsetbits(dev,
|
||||
init_data[i].reg,
|
||||
init_data[i].mask,
|
||||
init_data[i].val);
|
||||
if (ret < 0) {
|
||||
printf("%s: i2c set reg 0x%x failed, ret=%d\n",
|
||||
__func__, init_data[i].reg, ret);
|
||||
}
|
||||
|
||||
debug("%s: reg[0x%x] = 0x%x\n", __func__, init_data[i].reg,
|
||||
pmic_reg_read(dev, init_data[i].reg));
|
||||
}
|
||||
|
||||
printf("PMIC: RK%x ", show_variant);
|
||||
|
||||
if (on_source && off_source)
|
||||
printf("(on=0x%02x, off=0x%02x)",
|
||||
pmic_reg_read(dev, on_source),
|
||||
pmic_reg_read(dev, off_source));
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops rk8xx_ops = {
|
||||
.reg_count = rk8xx_reg_count,
|
||||
.read = rk8xx_read,
|
||||
.write = rk8xx_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id rk8xx_ids[] = {
|
||||
{ .compatible = "rockchip,rk805" },
|
||||
{ .compatible = "rockchip,rk808" },
|
||||
{ .compatible = "rockchip,rk809" },
|
||||
{ .compatible = "rockchip,rk816" },
|
||||
{ .compatible = "rockchip,rk817" },
|
||||
{ .compatible = "rockchip,rk818" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_rk8xx) = {
|
||||
.name = "rk8xx pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = rk8xx_ids,
|
||||
#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
|
||||
.bind = rk8xx_bind,
|
||||
#endif
|
||||
.priv_auto_alloc_size = sizeof(struct rk8xx_priv),
|
||||
.probe = rk8xx_probe,
|
||||
.ops = &rk8xx_ops,
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2016 Toradex AG
|
||||
* Stefan Agner <stefan.agner@toradex.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <power/rn5t567_pmic.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
static int rn5t567_reg_count(struct udevice *dev)
|
||||
{
|
||||
return RN5T567_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int rn5t567_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret) {
|
||||
debug("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rn5t567_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret) {
|
||||
debug("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops rn5t567_ops = {
|
||||
.reg_count = rn5t567_reg_count,
|
||||
.read = rn5t567_read,
|
||||
.write = rn5t567_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id rn5t567_ids[] = {
|
||||
{ .compatible = "ricoh,rn5t567" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_rn5t567) = {
|
||||
.name = "rn5t567 pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = rn5t567_ids,
|
||||
.ops = &rn5t567_ops,
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/s2mps11.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = S2MPS11_OF_LDO_PREFIX, .driver = S2MPS11_LDO_DRIVER },
|
||||
{ .prefix = S2MPS11_OF_BUCK_PREFIX, .driver = S2MPS11_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int s2mps11_reg_count(struct udevice *dev)
|
||||
{
|
||||
return S2MPS11_REG_COUNT;
|
||||
}
|
||||
|
||||
static int s2mps11_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s2mps11_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s2mps11_probe(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "voltage-regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops s2mps11_ops = {
|
||||
.reg_count = s2mps11_reg_count,
|
||||
.read = s2mps11_read,
|
||||
.write = s2mps11_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id s2mps11_ids[] = {
|
||||
{ .compatible = "samsung,s2mps11-pmic" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_s2mps11) = {
|
||||
.name = "s2mps11_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = s2mps11_ids,
|
||||
.ops = &s2mps11_ops,
|
||||
.probe = s2mps11_probe,
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/s5m8767.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "LDO", .driver = S5M8767_LDO_DRIVER },
|
||||
{ .prefix = "BUCK", .driver = S5M8767_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int s5m8767_reg_count(struct udevice *dev)
|
||||
{
|
||||
return S5M8767_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int s5m8767_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s5m8767_enable_32khz_cp(struct udevice *dev)
|
||||
{
|
||||
return pmic_clrsetbits(dev, S5M8767_EN32KHZ_CP, 0, 1 << 1);
|
||||
}
|
||||
|
||||
static int s5m8767_bind(struct udevice *dev)
|
||||
{
|
||||
int children;
|
||||
ofnode node;
|
||||
|
||||
node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops s5m8767_ops = {
|
||||
.reg_count = s5m8767_reg_count,
|
||||
.read = s5m8767_read,
|
||||
.write = s5m8767_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id s5m8767_ids[] = {
|
||||
{ .compatible = "samsung,s5m8767-pmic" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_s5m8767) = {
|
||||
.name = "s5m8767_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = s5m8767_ids,
|
||||
.bind = s5m8767_bind,
|
||||
.ops = &s5m8767_ops,
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/sandbox_pmic.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = SANDBOX_OF_LDO_PREFIX, .driver = SANDBOX_LDO_DRIVER },
|
||||
{ .prefix = SANDBOX_OF_BUCK_PREFIX, .driver = SANDBOX_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int sandbox_pmic_reg_count(struct udevice *dev)
|
||||
{
|
||||
return SANDBOX_PMIC_REG_COUNT;
|
||||
}
|
||||
|
||||
static int sandbox_pmic_write(struct udevice *dev, uint reg,
|
||||
const uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_pmic_read(struct udevice *dev, uint reg,
|
||||
uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_pmic_bind(struct udevice *dev)
|
||||
{
|
||||
if (!pmic_bind_children(dev, dev_ofnode(dev), pmic_children_info))
|
||||
pr_err("%s:%d PMIC: %s - no child found!", __func__, __LINE__,
|
||||
dev->name);
|
||||
|
||||
/* Always return success for this device - allows for PMIC I/O */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops sandbox_pmic_ops = {
|
||||
.reg_count = sandbox_pmic_reg_count,
|
||||
.read = sandbox_pmic_read,
|
||||
.write = sandbox_pmic_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_pmic_ids[] = {
|
||||
{ .compatible = "sandbox,pmic" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_pmic) = {
|
||||
.name = "sandbox_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = sandbox_pmic_ids,
|
||||
.bind = sandbox_pmic_bind,
|
||||
.ops = &sandbox_pmic_ops,
|
||||
};
|
||||
@@ -0,0 +1,268 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <misc.h>
|
||||
#include <sysreset.h>
|
||||
#include <time.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/lists.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/stpmic1.h>
|
||||
|
||||
#define STPMIC1_NUM_OF_REGS 0x100
|
||||
|
||||
#define STPMIC1_NVM_SIZE 8
|
||||
#define STPMIC1_NVM_POLL_TIMEOUT 100000
|
||||
#define STPMIC1_NVM_START_ADDRESS 0xf8
|
||||
|
||||
enum pmic_nvm_op {
|
||||
SHADOW_READ,
|
||||
SHADOW_WRITE,
|
||||
NVM_READ,
|
||||
NVM_WRITE,
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_REGULATOR)
|
||||
static const struct pmic_child_info stpmic1_children_info[] = {
|
||||
{ .prefix = "ldo", .driver = "stpmic1_ldo" },
|
||||
{ .prefix = "buck", .driver = "stpmic1_buck" },
|
||||
{ .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
|
||||
{ .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
|
||||
{ .prefix = "boost", .driver = "stpmic1_boost" },
|
||||
{ },
|
||||
};
|
||||
#endif /* DM_REGULATOR */
|
||||
|
||||
static int stpmic1_reg_count(struct udevice *dev)
|
||||
{
|
||||
return STPMIC1_NUM_OF_REGS;
|
||||
}
|
||||
|
||||
static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buff, len);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: failed to write register %#x :%d",
|
||||
__func__, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: failed to read register %#x : %d",
|
||||
__func__, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stpmic1_bind(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
#if CONFIG_IS_ENABLED(DM_REGULATOR)
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
dev_dbg(dev, "regulators subnode not found!");
|
||||
return -ENXIO;
|
||||
}
|
||||
dev_dbg(dev, "found regulators subnode\n");
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node,
|
||||
stpmic1_children_info);
|
||||
if (!children)
|
||||
dev_dbg(dev, "no child found\n");
|
||||
#endif /* DM_REGULATOR */
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
|
||||
ret = device_bind_driver(dev, "stpmic1-nvm",
|
||||
"stpmic1-nvm", NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(SYSRESET))
|
||||
return device_bind_driver(dev, "stpmic1-sysreset",
|
||||
"stpmic1-sysreset", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops stpmic1_ops = {
|
||||
.reg_count = stpmic1_reg_count,
|
||||
.read = stpmic1_read,
|
||||
.write = stpmic1_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id stpmic1_ids[] = {
|
||||
{ .compatible = "st,stpmic1" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_stpmic1) = {
|
||||
.name = "stpmic1_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = stpmic1_ids,
|
||||
.bind = stpmic1_bind,
|
||||
.ops = &stpmic1_ops,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static int stpmic1_nvm_rw(struct udevice *dev, u8 addr, u8 *buf, int buf_len,
|
||||
enum pmic_nvm_op op)
|
||||
{
|
||||
unsigned long timeout;
|
||||
u8 cmd = STPMIC1_NVM_CMD_READ;
|
||||
int ret, len = buf_len;
|
||||
|
||||
if (addr < STPMIC1_NVM_START_ADDRESS)
|
||||
return -EACCES;
|
||||
if (addr + buf_len > STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE)
|
||||
len = STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE - addr;
|
||||
|
||||
if (op == SHADOW_READ) {
|
||||
ret = pmic_read(dev, addr, buf, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return len;
|
||||
}
|
||||
|
||||
if (op == SHADOW_WRITE) {
|
||||
ret = pmic_write(dev, addr, buf, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return len;
|
||||
}
|
||||
|
||||
if (op == NVM_WRITE) {
|
||||
cmd = STPMIC1_NVM_CMD_PROGRAM;
|
||||
|
||||
ret = pmic_write(dev, addr, buf, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pmic_reg_read(dev, STPMIC1_NVM_CR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = pmic_reg_write(dev, STPMIC1_NVM_CR, ret | cmd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
timeout = timer_get_us() + STPMIC1_NVM_POLL_TIMEOUT;
|
||||
for (;;) {
|
||||
ret = pmic_reg_read(dev, STPMIC1_NVM_SR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(ret & STPMIC1_NVM_BUSY))
|
||||
break;
|
||||
|
||||
if (time_after(timer_get_us(), timeout))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret & STPMIC1_NVM_BUSY)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (op == NVM_READ) {
|
||||
ret = pmic_read(dev, addr, buf, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int stpmic1_nvm_read(struct udevice *dev, int offset,
|
||||
void *buf, int size)
|
||||
{
|
||||
enum pmic_nvm_op op = NVM_READ;
|
||||
|
||||
if (offset < 0) {
|
||||
op = SHADOW_READ;
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
return stpmic1_nvm_rw(dev->parent, offset, buf, size, op);
|
||||
}
|
||||
|
||||
static int stpmic1_nvm_write(struct udevice *dev, int offset,
|
||||
const void *buf, int size)
|
||||
{
|
||||
enum pmic_nvm_op op = NVM_WRITE;
|
||||
|
||||
if (offset < 0) {
|
||||
op = SHADOW_WRITE;
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
return stpmic1_nvm_rw(dev->parent, offset, (void *)buf, size, op);
|
||||
}
|
||||
|
||||
static const struct misc_ops stpmic1_nvm_ops = {
|
||||
.read = stpmic1_nvm_read,
|
||||
.write = stpmic1_nvm_write,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_nvm) = {
|
||||
.name = "stpmic1-nvm",
|
||||
.id = UCLASS_MISC,
|
||||
.ops = &stpmic1_nvm_ops,
|
||||
};
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
#ifdef CONFIG_SYSRESET
|
||||
static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct udevice *pmic_dev = dev->parent;
|
||||
int ret;
|
||||
|
||||
if (type != SYSRESET_POWER && type != SYSRESET_POWER_OFF)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret |= STPMIC1_SWOFF;
|
||||
ret &= ~STPMIC1_RREQ_EN;
|
||||
/* request Power Cycle */
|
||||
if (type == SYSRESET_POWER)
|
||||
ret |= STPMIC1_RREQ_EN;
|
||||
|
||||
ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static struct sysreset_ops stpmic1_sysreset_ops = {
|
||||
.request = stpmic1_sysreset_request,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(stpmic1_sysreset) = {
|
||||
.name = "stpmic1-sysreset",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.ops = &stpmic1_sysreset_ops,
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/tps65090.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "fet", .driver = TPS65090_FET_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int tps65090_reg_count(struct udevice *dev)
|
||||
{
|
||||
return TPS65090_NUM_REGS;
|
||||
}
|
||||
|
||||
static int tps65090_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65090_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buff, len);
|
||||
if (ret) {
|
||||
pr_err("read error %d from device: %p register: %#x!\n", ret,
|
||||
dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65090_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops tps65090_ops = {
|
||||
.reg_count = tps65090_reg_count,
|
||||
.read = tps65090_read,
|
||||
.write = tps65090_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id tps65090_ids[] = {
|
||||
{ .compatible = "ti,tps65090" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_tps65090) = {
|
||||
.name = "tps65090 pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = tps65090_ids,
|
||||
.bind = tps65090_bind,
|
||||
.ops = &tps65090_ops,
|
||||
};
|
||||
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2019 Texas Instruments Incorporated, <www.ti.com>
|
||||
* Keerthy <j-keerthy@ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/tps65941.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "ldo", .driver = TPS65941_LDO_DRIVER },
|
||||
{ .prefix = "buck", .driver = TPS65941_BUCK_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int tps65941_write(struct udevice *dev, uint reg, const uint8_t *buff,
|
||||
int len)
|
||||
{
|
||||
if (dm_i2c_write(dev, reg, buff, len)) {
|
||||
pr_err("write error to device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65941_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
|
||||
{
|
||||
if (dm_i2c_read(dev, reg, buff, len)) {
|
||||
pr_err("read error from device: %p register: %#x!\n", dev, reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65941_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s: %s regulators subnode not found!\n", __func__,
|
||||
dev->name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
printf("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops tps65941_ops = {
|
||||
.read = tps65941_read,
|
||||
.write = tps65941_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id tps65941_ids[] = {
|
||||
{ .compatible = "ti,tps659411", .data = TPS659411 },
|
||||
{ .compatible = "ti,tps659413", .data = TPS659413 },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_tps65941) = {
|
||||
.name = "tps65941_pmic",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = tps65941_ids,
|
||||
.bind = tps65941_bind,
|
||||
.ops = &tps65941_ops,
|
||||
};
|
||||
Reference in New Issue
Block a user