blob: 3c86eb20ab439d904690bea978ca1d7977d11df1 [file] [log] [blame]
Andre Przywara5e8af842024-05-13 22:55:07 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * AXP PMIC SPL driver
4 * (C) Copyright 2024 Arm Ltd.
5 */
6
7#include <errno.h>
8#include <linux/types.h>
9#include <asm/arch/pmic_bus.h>
10#include <axp_pmic.h>
11
12struct axp_reg_desc_spl {
13 u8 enable_reg;
14 u8 enable_mask;
15 u8 volt_reg;
16 u8 volt_mask;
17 u16 min_mV;
18 u16 max_mV;
19 u8 step_mV;
20 u8 split;
21};
22
23#define NA 0xff
24
25#if defined(CONFIG_AXP717_POWER) /* AXP717 */
26
27static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
28 { 0x80, BIT(0), 0x83, 0x7f, 500, 1540, 10, 70 },
29 { 0x80, BIT(1), 0x84, 0x7f, 500, 1540, 10, 70 },
30 { 0x80, BIT(2), 0x85, 0x7f, 500, 1840, 10, 70 },
31};
32
33#define AXP_CHIP_VERSION 0x0
34#define AXP_CHIP_VERSION_MASK 0x0
35#define AXP_CHIP_ID 0x0
36#define AXP_SHUTDOWN_REG 0x27
37#define AXP_SHUTDOWN_MASK BIT(0)
38
Andre Przywara670c0322024-05-14 00:46:59 +010039#elif defined(CONFIG_AXP313_POWER) /* AXP313 */
40
41static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
42 { 0x10, BIT(0), 0x13, 0x7f, 500, 1540, 10, 70 },
43 { 0x10, BIT(1), 0x14, 0x7f, 500, 1540, 10, 70 },
44 { 0x10, BIT(2), 0x15, 0x7f, 500, 1840, 10, 70 },
45};
46
47#define AXP_CHIP_VERSION 0x3
48#define AXP_CHIP_VERSION_MASK 0xc8
49#define AXP_CHIP_ID 0x48
50#define AXP_SHUTDOWN_REG 0x1a
51#define AXP_SHUTDOWN_MASK BIT(7)
52
Andre Przywaraf5a75322024-05-14 00:47:09 +010053#elif defined(CONFIG_AXP305_POWER) /* AXP305 */
54
55static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
56 { 0x10, BIT(0), 0x12, 0x7f, 600, 1520, 10, 50 },
57 { 0x10, BIT(1), 0x13, 0x1f, 1000, 2550, 50, NA },
58 { 0x10, BIT(2), 0x14, 0x7f, 600, 1520, 10, 50 },
59 { 0x10, BIT(3), 0x15, 0x3f, 600, 1500, 20, NA },
60 { 0x10, BIT(4), 0x16, 0x1f, 1100, 3400, 100, NA },
61};
62
63#define AXP_CHIP_VERSION 0x3
64#define AXP_CHIP_VERSION_MASK 0xcf
65#define AXP_CHIP_ID 0x40
66#define AXP_SHUTDOWN_REG 0x32
67#define AXP_SHUTDOWN_MASK BIT(7)
68
Andre Przywara5e8af842024-05-13 22:55:07 +010069#else
70
71 #error "Please define the regulator registers in axp_spl_regulators[]."
72
73#endif
74
75static u8 axp_mvolt_to_cfg(int mvolt, const struct axp_reg_desc_spl *reg)
76{
77 if (mvolt < reg->min_mV)
78 mvolt = reg->min_mV;
79 else if (mvolt > reg->max_mV)
80 mvolt = reg->max_mV;
81
82 mvolt -= reg->min_mV;
83
84 /* voltage in the first range ? */
85 if (mvolt <= reg->split * reg->step_mV)
86 return mvolt / reg->step_mV;
87
88 mvolt -= reg->split * reg->step_mV;
89
90 return reg->split + mvolt / (reg->step_mV * 2);
91}
92
93static int axp_set_dcdc(int dcdc_num, unsigned int mvolt)
94{
95 const struct axp_reg_desc_spl *reg;
96 int ret;
97
98 if (dcdc_num < 1 || dcdc_num > ARRAY_SIZE(axp_spl_dcdc_regulators))
99 return -EINVAL;
100
101 reg = &axp_spl_dcdc_regulators[dcdc_num - 1];
102
103 if (mvolt == 0)
104 return pmic_bus_clrbits(reg->enable_reg, reg->enable_mask);
105
106 ret = pmic_bus_write(reg->volt_reg, axp_mvolt_to_cfg(mvolt, reg));
107 if (ret)
108 return ret;
109
110 return pmic_bus_setbits(reg->enable_reg, reg->enable_mask);
111}
112
113int axp_set_dcdc1(unsigned int mvolt)
114{
115 return axp_set_dcdc(1, mvolt);
116}
117
118int axp_set_dcdc2(unsigned int mvolt)
119{
120 return axp_set_dcdc(2, mvolt);
121}
122
123int axp_set_dcdc3(unsigned int mvolt)
124{
125 return axp_set_dcdc(3, mvolt);
126}
127
128int axp_set_dcdc4(unsigned int mvolt)
129{
130 return axp_set_dcdc(4, mvolt);
131}
132
133int axp_set_dcdc5(unsigned int mvolt)
134{
135 return axp_set_dcdc(5, mvolt);
136}
137
138int axp_init(void)
139{
140 int ret = pmic_bus_init();
141
142 if (ret)
143 return ret;
144
145 if (AXP_CHIP_VERSION_MASK) {
146 u8 axp_chip_id;
147
148 ret = pmic_bus_read(AXP_CHIP_VERSION, &axp_chip_id);
149 if (ret)
150 return ret;
151
152 if ((axp_chip_id & AXP_CHIP_VERSION_MASK) != AXP_CHIP_ID) {
153 debug("unknown PMIC: 0x%x\n", axp_chip_id);
154 return -EINVAL;
155 }
156 }
157
158 return 0;
159}
160
161#if !CONFIG_IS_ENABLED(ARM_PSCI_FW) && !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
162int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
163{
164 pmic_bus_setbits(AXP_SHUTDOWN_REG, AXP_SHUTDOWN_MASK);
165
166 /* infinite loop during shutdown */
167 while (1)
168 ;
169
170 /* not reached */
171 return 0;
172}
173#endif