blob: 7bb266b882215588096185f90ec45dd4b2ef3f19 [file] [log] [blame]
Icenowy Zheng7508bef2018-07-21 20:41:12 +08001/*
Samuel Hollandf95b3682019-10-20 15:12:20 -05002 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
Icenowy Zheng7508bef2018-07-21 20:41:12 +08003 * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
Icenowy Zheng8d769822018-07-22 21:30:14 +08008#include <errno.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +08009#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
11#include <arch_helpers.h>
12#include <common/debug.h>
13#include <drivers/delay_timer.h>
14#include <drivers/mentor/mi2cv.h>
15#include <lib/mmio.h>
16
Andre Przywara67537762018-10-14 22:13:53 +010017#include <sunxi_def.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +080018#include <sunxi_mmap.h>
Andre Przywara456208a2018-10-14 12:02:02 +010019#include <sunxi_private.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +080020
21#define AXP805_ADDR 0x36
22#define AXP805_ID 0x03
23
Samuel Hollandf95b3682019-10-20 15:12:20 -050024static enum pmic_type {
25 UNKNOWN,
Icenowy Zheng8d769822018-07-22 21:30:14 +080026 AXP805,
Samuel Hollandf95b3682019-10-20 15:12:20 -050027} pmic;
Icenowy Zheng8d769822018-07-22 21:30:14 +080028
Icenowy Zheng8d769822018-07-22 21:30:14 +080029int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val)
30{
31 int ret;
32
33 ret = i2c_write(chip, 0, 0, &reg, 1);
Samuel Hollandf39fd862019-10-20 15:28:14 -050034 if (ret == 0)
35 ret = i2c_read(chip, 0, 0, val, 1);
Icenowy Zheng8d769822018-07-22 21:30:14 +080036 if (ret)
Samuel Hollandf39fd862019-10-20 15:28:14 -050037 ERROR("PMIC: Cannot read AXP805 register %02x\n", reg);
Icenowy Zheng8d769822018-07-22 21:30:14 +080038
Samuel Hollandf39fd862019-10-20 15:28:14 -050039 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080040}
41
42int axp_i2c_write(uint8_t chip, uint8_t reg, uint8_t val)
43{
Samuel Hollandf39fd862019-10-20 15:28:14 -050044 int ret;
45
46 ret = i2c_write(chip, reg, 1, &val, 1);
47 if (ret)
48 ERROR("PMIC: Cannot write AXP805 register %02x\n", reg);
49
50 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080051}
52
53static int axp805_probe(void)
54{
55 int ret;
56 uint8_t val;
57
Samuel Hollandf39fd862019-10-20 15:28:14 -050058 /* Switch the AXP805 to master/single-PMIC mode. */
Icenowy Zheng8d769822018-07-22 21:30:14 +080059 ret = axp_i2c_write(AXP805_ADDR, 0xff, 0x0);
Samuel Hollandf39fd862019-10-20 15:28:14 -050060 if (ret)
61 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080062
63 ret = axp_i2c_read(AXP805_ADDR, AXP805_ID, &val);
Samuel Hollandf39fd862019-10-20 15:28:14 -050064 if (ret)
65 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080066
Samuel Hollandf39fd862019-10-20 15:28:14 -050067 val &= 0xcf;
68 if (val != 0x40) {
69 ERROR("PMIC: Found unknown PMIC %02x\n", val);
Icenowy Zheng8d769822018-07-22 21:30:14 +080070 return -EINVAL;
71 }
72
73 return 0;
74}
Icenowy Zheng7508bef2018-07-21 20:41:12 +080075
Andre Przywara4e4b1e62018-09-08 19:18:37 +010076int sunxi_pmic_setup(uint16_t socid, const void *fdt)
Icenowy Zheng7508bef2018-07-21 20:41:12 +080077{
Icenowy Zheng8d769822018-07-22 21:30:14 +080078 int ret;
79
Samuel Hollandf39fd862019-10-20 15:28:14 -050080 INFO("PMIC: Probing AXP805 on I2C\n");
81
82 ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
83 if (ret)
84 return ret;
85
Andre Przywara67537762018-10-14 22:13:53 +010086 /* initialise mi2cv driver */
87 i2c_init((void *)SUNXI_R_I2C_BASE);
Icenowy Zheng8d769822018-07-22 21:30:14 +080088
Icenowy Zheng8d769822018-07-22 21:30:14 +080089 ret = axp805_probe();
90 if (ret)
Samuel Hollandf95b3682019-10-20 15:12:20 -050091 return ret;
92
93 pmic = AXP805;
Icenowy Zheng7508bef2018-07-21 20:41:12 +080094
95 return 0;
96}
Icenowy Zhengbd57eb52018-07-22 21:52:50 +080097
Samuel Hollandfa4d9352019-10-20 15:06:57 -050098void sunxi_power_down(void)
Icenowy Zhengbd57eb52018-07-22 21:52:50 +080099{
100 uint8_t val;
101
102 switch (pmic) {
103 case AXP805:
Andre Przywara67537762018-10-14 22:13:53 +0100104 /* Re-initialise after rich OS might have used it. */
105 sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
106 /* initialise mi2cv driver */
107 i2c_init((void *)SUNXI_R_I2C_BASE);
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800108 axp_i2c_read(AXP805_ADDR, 0x32, &val);
Andre Przywaraaffb9322018-09-09 00:38:58 +0100109 axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80);
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800110 break;
111 default:
112 break;
113 }
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800114}