diff options
-rw-r--r-- | plat/sun50iw1p1/plat_pm.c | 4 | ||||
-rw-r--r-- | plat/sun50iw1p1/sunxi_power.c | 518 | ||||
-rw-r--r-- | plat/sun50iw1p1/sunxi_power.h | 83 | ||||
-rw-r--r-- | plat/sun50iw1p1/sunxi_private.h | 6 |
4 files changed, 567 insertions, 44 deletions
diff --git a/plat/sun50iw1p1/plat_pm.c b/plat/sun50iw1p1/plat_pm.c index ec26248..922e497 100644 --- a/plat/sun50iw1p1/plat_pm.c +++ b/plat/sun50iw1p1/plat_pm.c @@ -254,7 +254,9 @@ static int32_t sunxi_affinst_suspend_finish(uint64_t mpidr, ******************************************************************************/ static void __dead2 sunxi_system_off(void) { - sunxi_pmic_write(0x32, sunxi_pmic_read(0x32) | 0x80); + uint8_t val; + sunxi_pmic_read(0x32, &val); + sunxi_pmic_write(0x32, val | 0x80); ERROR("PSCI system shutdown: still alive ...\n"); wfi(); diff --git a/plat/sun50iw1p1/sunxi_power.c b/plat/sun50iw1p1/sunxi_power.c index 827f0d5..5a7668d 100644 --- a/plat/sun50iw1p1/sunxi_power.c +++ b/plat/sun50iw1p1/sunxi_power.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (C) 2017, Theobroma Systems. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -35,69 +36,509 @@ #include "sunxi_def.h" #include "sunxi_private.h" +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#define BIT(n) (1U << (n)) + +/* RSB-RT address of the AXP803 */ #define PMIC_RSB_RT_ADDR 0x2d -int sunxi_pmic_read(uint8_t reg) +#define DVM_FINISHED_BIT BIT(7) + +struct regulator_details { + enum axp803_regulator regulator; + + /* + * For two-step regulators: + * mvolt_low-mvolt_mid: mvolt_step1 / step + * mvolt_mid+mvolt_step2-mvolt_high: mvolt_step2 / step + * + * For one-step regulators (set mvolt_mid and mvolt_step2 to 0): + * mvolt_low-mvolt_high: mvolt_step1 / step + */ + uint32_t mvolt_low; + uint32_t mvolt_mid; + uint32_t mvolt_high; + uint32_t mvolt_step1; + uint32_t mvolt_step2; + uint32_t voltage_control_reg; + int dvm; /* DVM used or not */ + uint32_t onoff_control_reg; + uint8_t onoff_control_bit; +}; + +static struct regulator_details regulator_details[] = { + { + .regulator = AXP803_DLDO1, + .mvolt_low = 700, + .mvolt_high = 3300, + .mvolt_step1 = 100, + .voltage_control_reg = 0x15, + .onoff_control_reg = 0x12, + .onoff_control_bit = 3, + }, { + .regulator = AXP803_DLDO2, + .mvolt_low = 700, + .mvolt_mid = 3400, + .mvolt_high = 4200, + .mvolt_step1 = 100, + .mvolt_step2 = 200, + .voltage_control_reg = 0x16, + .onoff_control_reg = 0x12, + .onoff_control_bit = 4, + }, { + .regulator = AXP803_DLDO3, + .mvolt_low = 700, + .mvolt_high = 3300, + .mvolt_step1 = 100, + .voltage_control_reg = 0x15, + .onoff_control_reg = 0x12, + .onoff_control_bit = 5, + }, { + .regulator = AXP803_DLDO4, + .mvolt_low = 700, + .mvolt_high = 3300, + .mvolt_step1 = 100, + .voltage_control_reg = 0x18, + .onoff_control_reg = 0x12, + .onoff_control_bit = 6, + }, { + .regulator = AXP803_ELDO1, + .mvolt_low = 700, + .mvolt_high = 1900, + .mvolt_step1 = 50, + .voltage_control_reg = 0x19, + .onoff_control_reg = 0x12, + .onoff_control_bit = 0, + }, { + .regulator = AXP803_ELDO2, + .mvolt_low = 700, + .mvolt_high = 1900, + .mvolt_step1 = 50, + .voltage_control_reg = 0x1a, + .onoff_control_reg = 0x12, + .onoff_control_bit = 1, + }, { + .regulator = AXP803_ELDO3, + .mvolt_low = 700, + .mvolt_high = 1900, + .mvolt_step1 = 50, + .voltage_control_reg = 0x1b, + .onoff_control_reg = 0x12, + .onoff_control_bit = 2, + }, { + .regulator = AXP803_FLDO1, + .mvolt_low = 700, + .mvolt_high = 1450, + .mvolt_step1 = 50, + .voltage_control_reg = 0x1c, + .onoff_control_reg = 0x13, + .onoff_control_bit = 2, + }, { + .regulator = AXP803_FLDO2, + .mvolt_low = 700, + .mvolt_high = 1450, + .mvolt_step1 = 50, + .voltage_control_reg = 0x1d, + .onoff_control_reg = 0x13, + .onoff_control_bit = 3, + }, { + .regulator = AXP803_DCDC1, + .mvolt_low = 1600, + .mvolt_high = 3400, + .mvolt_step1 = 100, + .voltage_control_reg = 0x20, + .onoff_control_reg = 0x10, + .onoff_control_bit = 0, + }, { + .regulator = AXP803_DCDC2, + .mvolt_low = 500, + .mvolt_mid = 1200, + .mvolt_high = 1300, + .mvolt_step1 = 10, + .mvolt_step2 = 20, + .voltage_control_reg = 0x21, + .dvm = 1, + .onoff_control_reg = 0x10, + .onoff_control_bit = 1, + }, { + .regulator = AXP803_DCDC3, + .mvolt_low = 500, + .mvolt_mid = 1200, + .mvolt_high = 1300, + .mvolt_step1 = 10, + .mvolt_step2 = 20, + .voltage_control_reg = 0x22, + .dvm = 1, + .onoff_control_reg = 0x10, + .onoff_control_bit = 2, + }, { + .regulator = AXP803_DCDC4, + .mvolt_low = 500, + .mvolt_mid = 1200, + .mvolt_high = 1300, + .mvolt_step1 = 10, + .mvolt_step2 = 20, + .voltage_control_reg = 0x23, + .dvm = 1, + .onoff_control_reg = 0x10, + .onoff_control_bit = 3, + }, { + .regulator = AXP803_DCDC5, + .mvolt_low = 800, + .mvolt_mid = 1120, + .mvolt_high = 1840, + .mvolt_step1 = 10, + .mvolt_step2 = 20, + .voltage_control_reg = 0x24, + .dvm = 1, + .onoff_control_reg = 0x10, + .onoff_control_bit = 4, + }, { + .regulator = AXP803_DCDC6, + .mvolt_low = 600, + .mvolt_mid = 1100, + .mvolt_high = 1520, + .mvolt_step1 = 10, + .mvolt_step2 = 20, + .voltage_control_reg = 0x25, + .dvm = 1, + .onoff_control_reg = 0x10, + .onoff_control_bit = 5, + }, { + .regulator = AXP803_ALDO1, + .mvolt_low = 700, + .mvolt_high = 3300, + .mvolt_step1 = 100, + .voltage_control_reg = 0x28, + .onoff_control_reg = 0x13, + .onoff_control_bit = 5, + }, { + .regulator = AXP803_ALDO2, + .mvolt_low = 700, + .mvolt_high = 3300, + .mvolt_step1 = 100, + .voltage_control_reg = 0x29, + .onoff_control_reg = 0x13, + .onoff_control_bit = 6, + }, { + .regulator = AXP803_ALDO3, + .mvolt_low = 700, + .mvolt_high = 3300, + .mvolt_step1 = 100, + .voltage_control_reg = 0x2a, + .onoff_control_reg = 0x13, + .onoff_control_bit = 7, + } +}; + +static struct regulator_details* get_regulator_details(enum axp803_regulator r) { - uint32_t val; + size_t i; + + for (i = 0; i < ARRAY_SIZE(regulator_details); i++) { + struct regulator_details *rd = ®ulator_details[i]; + + if (rd->regulator == r) + return rd; + } + return NULL; +} + +int sunxi_pmic_read(uint8_t reg, uint8_t *val) +{ + uint32_t v; int ret; - ret = rsb_read(PMIC_RSB_RT_ADDR, reg, &val, 1); + ret = rsb_read(PMIC_RSB_RT_ADDR, reg, &v, 1); if (ret) return ret; + + *val = v; + + VERBOSE("PMIC read @0x%x: 0x%x\n", reg, *val); + + return 0; +} + +int sunxi_pmic_write(uint8_t reg, uint8_t val) +{ + VERBOSE("PMIC write @0x%x: 0x%x\n", reg, val); + return rsb_write(PMIC_RSB_RT_ADDR, reg, val, 1); +} + +static int sunxi_pmic_set_bit_val(uint8_t reg, uint8_t bit, uint32_t v) +{ + uint8_t old_val, new_val; + int ret; + + ret = sunxi_pmic_read(reg, &old_val); + if (ret < 0) + return ret; + + if (v) + new_val = old_val | BIT(bit); + else + new_val = old_val & (~BIT(bit)); + + if (old_val != new_val) + ret = sunxi_pmic_write(reg, new_val); + else + ret = 0; + + return ret; +} + +int sunxi_pmic_set_bit(uint8_t reg, uint8_t bit) +{ + return sunxi_pmic_set_bit_val(reg, bit, 1); +} + +int sunxi_pmic_clear_bit(uint8_t reg, uint8_t bit) +{ + return sunxi_pmic_set_bit_val(reg, bit, 0); +} + +static uint8_t mvolt_to_val(struct regulator_details *rd, uint32_t mvolt) +{ + uint8_t val; + + if (mvolt < rd->mvolt_low) + mvolt = rd->mvolt_low; + + if (mvolt > rd->mvolt_high) + mvolt = rd->mvolt_high; + + if (rd->mvolt_mid != 0 && mvolt > rd->mvolt_mid) { + val = (rd->mvolt_mid - rd->mvolt_low) / rd->mvolt_step1; + val += (mvolt - rd->mvolt_mid) / rd->mvolt_step2; + } else + val = (mvolt - rd->mvolt_low) / rd->mvolt_step1; + return val; } -int sunxi_pmic_write(uint8_t reg, uint8_t value) +static uint32_t val_to_mvolt(struct regulator_details *rd, uint8_t val) { - return rsb_write(PMIC_RSB_RT_ADDR, reg, value, 1); + uint32_t step1_max = rd->mvolt_mid / rd->mvolt_step1; + uint32_t mvolt; + + if (rd->mvolt_mid != 0 && val > step1_max) { + mvolt = rd->mvolt_mid; + mvolt += (val - step1_max) * rd->mvolt_step2; + } else + mvolt = rd->mvolt_low + val * rd->mvolt_step1; + + return mvolt; } -/* Setup the PMIC: DCDC1 to 3.3V, enable DC1SW and DLDO4 */ -static int pmic_setup(void) +int sunxi_pmic_set_voltage(enum axp803_regulator r, uint32_t mvolt) { int ret; + struct regulator_details *rd; + + rd = get_regulator_details(r); + if (!rd) { + ERROR("Unknown regulator!\n"); + return -1; + } + + /* Get the register value */ + uint8_t val = mvolt_to_val(rd, mvolt); + + /* Set voltage control to desired voltage */ + ret = sunxi_pmic_write(rd->voltage_control_reg, val); + if (ret < 0) { + ERROR("Failed to set voltage of regulator %d to %u mV!\n", + r, mvolt); + return ret; + } - ret = sunxi_pmic_read(0x20); - if (ret != 0x0e && ret != 0x11) { - int voltage = (ret & 0x1f) * 10 + 16; + if (rd->dvm) { + /* Wait until the finished flag is set */ + do { + ret = sunxi_pmic_read(rd->voltage_control_reg, &val); + if (ret < 0) { + ERROR("Failed to read DVM finished flag (%d)!\n", ret); + return ret; + } + } while (!(val & DVM_FINISHED_BIT)); + } + + return 0; +} - NOTICE("PMIC: DCDC1 voltage is an unexpected %d.%dV\n", - voltage / 10, voltage % 10); +int sunxi_pmic_get_voltage(enum axp803_regulator r, uint32_t *mvolt) +{ + int ret; + uint8_t val; + struct regulator_details *rd; + + rd = get_regulator_details(r); + if (!rd) { + ERROR("Unknown regulator!\n"); return -1; } - if (ret != 0x11) { - /* Set DCDC1 voltage to 3.3 Volts */ - ret = sunxi_pmic_write(0x20, 0x11); - if (ret < 0) { - NOTICE("PMIC: error %d writing DCDC1 voltage\n", ret); - return -2; - } + /* Get the register value */ + ret = sunxi_pmic_read(rd->voltage_control_reg, &val); + if (ret < 0) { + ERROR("Failed to read voltage control register (%d)!\n", ret); + return ret; } - ret = sunxi_pmic_read(0x12); - if ((ret & 0x3f) != 0x01) { - NOTICE("PMIC: Output power control 2 is an unexpected 0x%x\n", - ret); - return -3; + /* Remove DVM bit */ + val &= ~DVM_FINISHED_BIT; + + /* Get the mvolt value */ + *mvolt = val_to_mvolt(rd, val); + + return 0; +} + +int sunxi_pmic_set_enable(enum axp803_regulator r, uint32_t enable) +{ + int ret; + struct regulator_details *rd; + + rd = get_regulator_details(r); + if (!rd) { + ERROR("Unknown regulator!\n"); + return -1; + } + + ret = sunxi_pmic_set_bit_val(rd->onoff_control_reg, + rd->onoff_control_bit, enable); + if (ret < 0) { + ERROR("Failed to set enable bit of regulator (%d)!\n", ret); + return ret; + } + + return 0; +} + +int sunxi_pmic_get_enable(enum axp803_regulator r, uint32_t *enable) +{ + int ret; + uint8_t val; + struct regulator_details *rd; + + rd = get_regulator_details(r); + if (!rd) { + ERROR("Unknown regulator!\n"); + return -1; } - if ((ret & 0xc1) != 0xc1) { - /* Enable DC1SW to power PHY and DLDO4 for WiFi */ - ret = sunxi_pmic_write(0x12, ret | 0xc0); - if (ret < 0) { - NOTICE("PMIC: error %d enabling DC1SW/DLDO4\n", ret); - return -4; + ret = sunxi_pmic_read(rd->onoff_control_reg, &val); + if (ret < 0) { + ERROR("Failed to read onoff control register (%d)!\n", ret); + return ret; + } + + *enable = (val & BIT(rd->onoff_control_bit)) ? 1 : 0; + + return 0; +} + +int sunxi_pmic_run_tasks(struct pmic_task *tasks, size_t tasks_num) +{ + size_t i; + + for (i = 0; i < tasks_num; i++) { + VERBOSE("Running PMIC task %zu\n", i); + struct pmic_task *t = &tasks[i]; + if (t->t == PMIC_SET_VOLTAGE) { + int ret = sunxi_pmic_set_voltage(t->r, t->val); + if (ret) { + ERROR("Could run set-voltage task #%zu!", i); + return -1; + } + } else if (t->t == PMIC_SET_ENABLE) { + int ret = sunxi_pmic_set_enable(t->r, t->val); + if (ret) { + ERROR("Could run set-enable task #%zu!", i); + return -1; + } + } else { + ERROR("Could run unknown task #%zu!", i); + return -1; } } - ret = sunxi_pmic_read(0x10); - sunxi_pmic_write(0x10, ret | (1 << 3)); + return 0; +} - sunxi_pmic_write(0x23, 0x46); /* DCDC4 = ETH PHY = 1.2V */ - sunxi_pmic_write(0x24, 0x2c); /* DCDC5 = DDR3L voltage = 1.36V */ - // sunxi_pmic_write(0x24, 0xb3); /* DCDC5 = DDR RAM voltage = 1.5V */ +static int pmic_setup(void) +{ + int ret; + + /* + * (Verified) default values of AXP803 (see table 9-29): + * DCDC1: 3V0 on -> 3V3 + * DCDC2: 1V1 on -> 1V04 + * DCDC3: 1V1 on -> (dual-phase) + * DCDC4: 1V1 off -> 1V2 on + * DCDC5: 1V5 on -> 1V36 + * DCDC6: 1V1 on + * ALDO1: 3V3 off -> on + * ALDO2: 1V8 on -> 3V3 on + * ALDO3: 3V0 on -> 3V3 + * ELDO1: 1V8 on + * ELDO2: 0V7 off + * ELDO3: 0V7 off + * DLDO1: 3V3 off + * DLDO2: 2V9 off + * DLDO3: 2V9 off + * DLDO4: 3V3 off + * FLDO1: 1V2 off -> on + * FLDO2: 1V1 on + * + * DC1SW: off -> on + * DCDC2/3 dual-phase: off -> on + * DCDC5/6 dual-phase: off + */ + + /* Turn on DC1SW (part of DCDC1) */ + ret = sunxi_pmic_set_bit(0x12, 7); + if (ret < 0) { + ERROR("Could not turn on DC1SW\n"); + return -1; + } + + /* Set DCDC2 and DCDC3 to dual-phase mode */ + ret = sunxi_pmic_set_bit(0x14, 6); + if (ret < 0) { + ERROR("Could not enable dual-phase for DCDC2/3\n"); + return -1; + } + + struct pmic_task tasks[] = { + /* Set DCDC1 to 3V3 */ + { .t = PMIC_SET_VOLTAGE, .r = AXP803_DCDC1, .val = 3300 }, + /* Set DCDC2/3 to 1V04 */ + { .t = PMIC_SET_VOLTAGE, .r = AXP803_DCDC2, .val = 1040 }, + /* Set DCDC4 (ETH PHY) to 1V2 */ + { .t = PMIC_SET_VOLTAGE, .r = AXP803_DCDC4, .val = 1200 }, + /* Enable DCDC4 */ + { .t = PMIC_SET_ENABLE, .r = AXP803_DCDC4, .val = 1 }, + /* Set DCDC5 (DDR3L) to 1V36 */ + { .t = PMIC_SET_VOLTAGE, .r = AXP803_DCDC5, .val = 1360 }, + /* Enable ALDO1 */ + { .t = PMIC_SET_ENABLE, .r = AXP803_ALDO1, .val = 1 }, + /* Set ALDO2 to 3V3 */ + { .t = PMIC_SET_VOLTAGE, .r = AXP803_ALDO2, .val = 3300 }, + /* Enable ALDO2 */ + { .t = PMIC_SET_ENABLE, .r = AXP803_ALDO2, .val = 1 }, + /* Set ALDO3 to 3V3 */ + { .t = PMIC_SET_VOLTAGE, .r = AXP803_ALDO3, .val = 3300 }, + /* Enable FLDO1 */ + { .t = PMIC_SET_ENABLE, .r = AXP803_FLDO1, .val = 1 }, + }; + + ret = sunxi_pmic_run_tasks(tasks, ARRAY_SIZE(tasks)); + if (ret < 0) { + ERROR("Could not run PMIC tasks\n"); + return -1; + } return 0; } @@ -108,19 +549,20 @@ static int pmic_setup(void) int sunxi_pmic_setup(void) { int ret; + uint8_t val; NOTICE("Configuring AXP PMIC\n"); /* Test PMIC communication */ - ret = sunxi_pmic_read(0x03); + ret = sunxi_pmic_read(0x03, &val); if (ret < 0) { ERROR("PMIC: error %d reading PMIC IC type register\n", ret); return -2; } /* Check IC type number equals 0b01xx00001 */ - if ((ret & 0xcf) != 0x41) { - ERROR("PMIC: unknown PMIC IC type 0x%x\n", ret); + if ((val & 0xcf) != 0x41) { + ERROR("PMIC: unknown PMIC IC type 0x%x\n", val); return -3; } diff --git a/plat/sun50iw1p1/sunxi_power.h b/plat/sun50iw1p1/sunxi_power.h new file mode 100644 index 0000000..566c59c --- /dev/null +++ b/plat/sun50iw1p1/sunxi_power.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017, Theobroma Systems. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SUNXI_POWER_H__ +#define __SUNXI_POWER_H__ + +#include <bl_common.h> +#include <platform_def.h> + +int sunxi_pmic_setup(void); + +/* Register-level access */ +int sunxi_pmic_read(uint8_t address, uint8_t *value); +int sunxi_pmic_write(uint8_t address, uint8_t value); +int sunxi_pmic_set_bit(uint8_t address, uint8_t bit); +int sunxi_pmic_clear_bit(uint8_t address, uint8_t bit); + +/* Regulator-level access */ +enum axp803_regulator { + AXP803_DLDO1, + AXP803_DLDO2, + AXP803_DLDO3, + AXP803_DLDO4, + AXP803_ELDO1, + AXP803_ELDO2, + AXP803_ELDO3, + AXP803_FLDO1, + AXP803_FLDO2, + AXP803_DCDC1, + AXP803_DCDC2, + AXP803_DCDC3, + AXP803_DCDC4, + AXP803_DCDC5, + AXP803_DCDC6, + AXP803_ALDO1, + AXP803_ALDO2, + AXP803_ALDO3, +}; +int sunxi_pmic_set_voltage(enum axp803_regulator r, uint32_t mvolt); +int sunxi_pmic_get_voltage(enum axp803_regulator r, uint32_t *mvolt); +int sunxi_pmic_set_enable(enum axp803_regulator r, uint32_t enable); +int sunxi_pmic_get_enable(enum axp803_regulator r, uint32_t *enable); + +/* Task-level access */ +enum pmic_task_type { + PMIC_SET_VOLTAGE, + PMIC_SET_ENABLE, +}; +struct pmic_task { + enum pmic_task_type t; + enum axp803_regulator r; + uint32_t val; /* mvolt or enable */ +}; +int sunxi_pmic_run_tasks(struct pmic_task *tasks, size_t tasks_num); + +#endif /* __SUNXI_POWER_H__ */ diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h index 34e36d8..4093f55 100644 --- a/plat/sun50iw1p1/sunxi_private.h +++ b/plat/sun50iw1p1/sunxi_private.h @@ -33,6 +33,7 @@ #include <bl_common.h> #include <platform_def.h> +#include "sunxi_power.h" /******************************************************************************* * Forward declarations @@ -72,11 +73,6 @@ int rsb_read(uint8_t rt_addr, uint8_t addr, uint32_t *val, size_t size); int rsb_write(uint8_t rt_addr, uint8_t addr, uint32_t val, size_t size); int sunxi_rsb_init(void); -/* Declarations for sunxi_power.c */ -int sunxi_pmic_setup(void); -int sunxi_pmic_read(uint8_t address); -int sunxi_pmic_write(uint8_t address, uint8_t value); - void udelay(unsigned int delay); int sunxi_setup_clocks(uint16_t socid); void sun50i_set_cpu_pll(unsigned int freq_mhz); |