GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/allwinner/axp.h>
|
||||
|
||||
const uint8_t axp_chip_id = AXP803_CHIP_ID;
|
||||
const char *const axp_compatible = "x-powers,axp803";
|
||||
|
||||
#if SUNXI_SETUP_REGULATORS == 1
|
||||
const struct axp_regulator axp_regulators[] = {
|
||||
{"aldo1", 700, 3300, 100, NA, 0x28, 0x13, 5},
|
||||
{"dcdc1", 1600, 3400, 100, NA, 0x20, 0x10, 0},
|
||||
{"dcdc5", 800, 1840, 10, 32, 0x24, 0x10, 4},
|
||||
{"dcdc6", 600, 1520, 10, 50, 0x25, 0x10, 5},
|
||||
{"dldo1", 700, 3300, 100, NA, 0x15, 0x12, 3},
|
||||
{"dldo2", 700, 4200, 100, 27, 0x16, 0x12, 4},
|
||||
{"dldo3", 700, 3300, 100, NA, 0x17, 0x12, 5},
|
||||
{"dldo4", 700, 3300, 100, NA, 0x18, 0x12, 6},
|
||||
{"fldo1", 700, 1450, 50, NA, 0x1c, 0x13, 2},
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/allwinner/axp.h>
|
||||
|
||||
const uint8_t axp_chip_id = AXP805_CHIP_ID;
|
||||
const char *const axp_compatible = "x-powers,axp805";
|
||||
|
||||
#if SUNXI_SETUP_REGULATORS == 1
|
||||
/*
|
||||
* The "dcdcd" split changes the step size by a factor of 5, not 2;
|
||||
* disallow values above the split to maintain accuracy.
|
||||
*/
|
||||
const struct axp_regulator axp_regulators[] = {
|
||||
{"dcdca", 600, 1520, 10, 50, 0x12, 0x10, 0},
|
||||
{"dcdcb", 1000, 2550, 50, NA, 0x13, 0x10, 1},
|
||||
{"dcdcc", 600, 1520, 10, 50, 0x14, 0x10, 2},
|
||||
{"dcdcd", 600, 1500, 20, NA, 0x15, 0x10, 3},
|
||||
{"dcdce", 1100, 3400, 100, NA, 0x16, 0x10, 4},
|
||||
{"aldo1", 700, 3300, 100, NA, 0x17, 0x10, 5},
|
||||
{"aldo2", 700, 3300, 100, NA, 0x18, 0x10, 6},
|
||||
{"aldo3", 700, 3300, 100, NA, 0x19, 0x10, 7},
|
||||
{"bldo1", 700, 1900, 100, NA, 0x20, 0x11, 0},
|
||||
{"bldo2", 700, 1900, 100, NA, 0x21, 0x11, 1},
|
||||
{"bldo3", 700, 1900, 100, NA, 0x22, 0x11, 2},
|
||||
{"bldo4", 700, 1900, 100, NA, 0x23, 0x11, 3},
|
||||
{"cldo1", 700, 3300, 100, NA, 0x24, 0x11, 4},
|
||||
{"cldo2", 700, 4200, 100, 27, 0x25, 0x11, 5},
|
||||
{"cldo3", 700, 3300, 100, NA, 0x26, 0x11, 6},
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/allwinner/axp.h>
|
||||
|
||||
int axp_check_id(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = axp_read(0x03);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= 0xcf;
|
||||
if (ret != axp_chip_id) {
|
||||
ERROR("PMIC: Found unknown PMIC %02x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int axp_clrsetbits(uint8_t reg, uint8_t clr_mask, uint8_t set_mask)
|
||||
{
|
||||
uint8_t val;
|
||||
int ret;
|
||||
|
||||
ret = axp_read(reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = (ret & ~clr_mask) | set_mask;
|
||||
|
||||
return axp_write(reg, val);
|
||||
}
|
||||
|
||||
void axp_power_off(void)
|
||||
{
|
||||
/* Set "power disable control" bit */
|
||||
axp_setbits(0x32, BIT(7));
|
||||
}
|
||||
|
||||
#if SUNXI_SETUP_REGULATORS == 1
|
||||
/*
|
||||
* Retrieve the voltage from a given regulator DTB node.
|
||||
* Both the regulator-{min,max}-microvolt properties must be present and
|
||||
* have the same value. Return that value in millivolts.
|
||||
*/
|
||||
static int fdt_get_regulator_millivolt(const void *fdt, int node)
|
||||
{
|
||||
const fdt32_t *prop;
|
||||
uint32_t min_volt;
|
||||
|
||||
prop = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
|
||||
if (prop == NULL)
|
||||
return -EINVAL;
|
||||
min_volt = fdt32_to_cpu(*prop);
|
||||
|
||||
prop = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
|
||||
if (prop == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (fdt32_to_cpu(*prop) != min_volt)
|
||||
return -EINVAL;
|
||||
|
||||
return min_volt / 1000;
|
||||
}
|
||||
|
||||
static int setup_regulator(const void *fdt, int node,
|
||||
const struct axp_regulator *reg)
|
||||
{
|
||||
uint8_t val;
|
||||
int mvolt;
|
||||
|
||||
mvolt = fdt_get_regulator_millivolt(fdt, node);
|
||||
if (mvolt < reg->min_volt || mvolt > reg->max_volt)
|
||||
return -EINVAL;
|
||||
|
||||
val = (mvolt / reg->step) - (reg->min_volt / reg->step);
|
||||
if (val > reg->split)
|
||||
val = ((val - reg->split) / 2) + reg->split;
|
||||
|
||||
axp_write(reg->volt_reg, val);
|
||||
axp_setbits(reg->switch_reg, BIT(reg->switch_bit));
|
||||
|
||||
INFO("PMIC: %s voltage: %d.%03dV\n", reg->dt_name,
|
||||
mvolt / 1000, mvolt % 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_node_disabled(const void *fdt, int node)
|
||||
{
|
||||
const char *cell;
|
||||
cell = fdt_getprop(fdt, node, "status", NULL);
|
||||
if (cell == NULL) {
|
||||
return false;
|
||||
}
|
||||
return strcmp(cell, "okay") != 0;
|
||||
}
|
||||
|
||||
static bool should_enable_regulator(const void *fdt, int node)
|
||||
{
|
||||
if (is_node_disabled(fdt, node)) {
|
||||
return false;
|
||||
}
|
||||
if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) {
|
||||
return true;
|
||||
}
|
||||
if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool board_uses_usb0_host_mode(const void *fdt)
|
||||
{
|
||||
int node, length;
|
||||
const char *prop;
|
||||
|
||||
node = fdt_node_offset_by_compatible(fdt, -1,
|
||||
"allwinner,sun8i-a33-musb");
|
||||
if (node < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
prop = fdt_getprop(fdt, node, "dr_mode", &length);
|
||||
if (!prop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !strncmp(prop, "host", length);
|
||||
}
|
||||
|
||||
void axp_setup_regulators(const void *fdt)
|
||||
{
|
||||
int node;
|
||||
bool sw = false;
|
||||
|
||||
if (fdt == NULL)
|
||||
return;
|
||||
|
||||
/* locate the PMIC DT node, bail out if not found */
|
||||
node = fdt_node_offset_by_compatible(fdt, -1, axp_compatible);
|
||||
if (node < 0) {
|
||||
WARN("PMIC: No PMIC DT node, skipping setup\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This applies to AXP803 only. */
|
||||
if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL) &&
|
||||
board_uses_usb0_host_mode(fdt)) {
|
||||
axp_clrbits(0x8f, BIT(4));
|
||||
axp_setbits(0x30, BIT(2));
|
||||
INFO("PMIC: Enabling DRIVEVBUS\n");
|
||||
}
|
||||
|
||||
/* descend into the "regulators" subnode */
|
||||
node = fdt_subnode_offset(fdt, node, "regulators");
|
||||
if (node < 0) {
|
||||
WARN("PMIC: No regulators DT node, skipping setup\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* iterate over all regulators to find used ones */
|
||||
fdt_for_each_subnode(node, fdt, node) {
|
||||
const struct axp_regulator *reg;
|
||||
const char *name;
|
||||
int length;
|
||||
|
||||
/* We only care if it's always on or referenced. */
|
||||
if (!should_enable_regulator(fdt, node))
|
||||
continue;
|
||||
|
||||
name = fdt_get_name(fdt, node, &length);
|
||||
|
||||
/* Enable the switch last to avoid overheating. */
|
||||
if (!strncmp(name, "dc1sw", length) ||
|
||||
!strncmp(name, "sw", length)) {
|
||||
sw = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (reg = axp_regulators; reg->dt_name; reg++) {
|
||||
if (!strncmp(name, reg->dt_name, length)) {
|
||||
setup_regulator(fdt, node, reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* On the AXP803, if DLDO2 is enabled after DC1SW, the PMIC overheats
|
||||
* and shuts down. So always enable DC1SW as the very last regulator.
|
||||
*/
|
||||
if (sw) {
|
||||
INFO("PMIC: Enabling DC SW\n");
|
||||
if (axp_chip_id == AXP803_CHIP_ID)
|
||||
axp_setbits(0x12, BIT(7));
|
||||
if (axp_chip_id == AXP805_CHIP_ID)
|
||||
axp_setbits(0x11, BIT(7));
|
||||
}
|
||||
}
|
||||
#endif /* SUNXI_SETUP_REGULATORS */
|
||||
Reference in New Issue
Block a user