xref: /openbmc/u-boot/arch/arm/mach-sunxi/pmic_bus.c (revision d94604d5)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2e6e505b9SAlexander Graf /*
3e6e505b9SAlexander Graf  * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
4e6e505b9SAlexander Graf  *
5e6e505b9SAlexander Graf  * Sunxi PMIC bus access helpers
6e6e505b9SAlexander Graf  *
7e6e505b9SAlexander Graf  * The axp152 & axp209 use an i2c bus, the axp221 uses the p2wi bus and the
8e6e505b9SAlexander Graf  * axp223 uses the rsb bus, these functions abstract this.
9e6e505b9SAlexander Graf  */
10e6e505b9SAlexander Graf 
11e6e505b9SAlexander Graf #include <common.h>
12e6e505b9SAlexander Graf #include <asm/arch/p2wi.h>
13e6e505b9SAlexander Graf #include <asm/arch/rsb.h>
14e6e505b9SAlexander Graf #include <i2c.h>
15e6e505b9SAlexander Graf #include <asm/arch/pmic_bus.h>
16e6e505b9SAlexander Graf 
17e6e505b9SAlexander Graf #define AXP152_I2C_ADDR			0x30
18e6e505b9SAlexander Graf 
19e6e505b9SAlexander Graf #define AXP209_I2C_ADDR			0x34
20e6e505b9SAlexander Graf 
21e6e505b9SAlexander Graf #define AXP221_CHIP_ADDR		0x68
22e6e505b9SAlexander Graf #define AXP221_CTRL_ADDR		0x3e
23e6e505b9SAlexander Graf #define AXP221_INIT_DATA		0x3e
24e6e505b9SAlexander Graf 
25e6e505b9SAlexander Graf /* AXP818 device and runtime addresses are same as AXP223 */
26e6e505b9SAlexander Graf #define AXP223_DEVICE_ADDR		0x3a3
27e6e505b9SAlexander Graf #define AXP223_RUNTIME_ADDR		0x2d
28e6e505b9SAlexander Graf 
pmic_bus_init(void)29e6e505b9SAlexander Graf int pmic_bus_init(void)
30e6e505b9SAlexander Graf {
31e6e505b9SAlexander Graf 	/* This cannot be 0 because it is used in SPL before BSS is ready */
32e6e505b9SAlexander Graf 	static int needs_init = 1;
33e6e505b9SAlexander Graf 	__maybe_unused int ret;
34e6e505b9SAlexander Graf 
35e6e505b9SAlexander Graf 	if (!needs_init)
36e6e505b9SAlexander Graf 		return 0;
37e6e505b9SAlexander Graf 
38795857dfSChen-Yu Tsai #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
39e6e505b9SAlexander Graf # ifdef CONFIG_MACH_SUN6I
40e6e505b9SAlexander Graf 	p2wi_init();
41e6e505b9SAlexander Graf 	ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
42e6e505b9SAlexander Graf 				       AXP221_INIT_DATA);
43409677ecSChen-Yu Tsai # elif defined CONFIG_MACH_SUN8I_R40
44409677ecSChen-Yu Tsai 	/* Nothing. R40 uses the AXP221s in I2C mode */
45409677ecSChen-Yu Tsai 	ret = 0;
46e6e505b9SAlexander Graf # else
47e6e505b9SAlexander Graf 	ret = rsb_init();
48e6e505b9SAlexander Graf 	if (ret)
49e6e505b9SAlexander Graf 		return ret;
50e6e505b9SAlexander Graf 
51e6e505b9SAlexander Graf 	ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
52e6e505b9SAlexander Graf # endif
53e6e505b9SAlexander Graf 	if (ret)
54e6e505b9SAlexander Graf 		return ret;
55e6e505b9SAlexander Graf #endif
56e6e505b9SAlexander Graf 
57e6e505b9SAlexander Graf 	needs_init = 0;
58e6e505b9SAlexander Graf 	return 0;
59e6e505b9SAlexander Graf }
60e6e505b9SAlexander Graf 
pmic_bus_read(u8 reg,u8 * data)61e6e505b9SAlexander Graf int pmic_bus_read(u8 reg, u8 *data)
62e6e505b9SAlexander Graf {
63e6e505b9SAlexander Graf #ifdef CONFIG_AXP152_POWER
64e6e505b9SAlexander Graf 	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
65e6e505b9SAlexander Graf #elif defined CONFIG_AXP209_POWER
66e6e505b9SAlexander Graf 	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
67795857dfSChen-Yu Tsai #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
68e6e505b9SAlexander Graf # ifdef CONFIG_MACH_SUN6I
69e6e505b9SAlexander Graf 	return p2wi_read(reg, data);
70409677ecSChen-Yu Tsai # elif defined CONFIG_MACH_SUN8I_R40
71409677ecSChen-Yu Tsai 	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
72e6e505b9SAlexander Graf # else
73e6e505b9SAlexander Graf 	return rsb_read(AXP223_RUNTIME_ADDR, reg, data);
74e6e505b9SAlexander Graf # endif
75e6e505b9SAlexander Graf #endif
76e6e505b9SAlexander Graf }
77e6e505b9SAlexander Graf 
pmic_bus_write(u8 reg,u8 data)78e6e505b9SAlexander Graf int pmic_bus_write(u8 reg, u8 data)
79e6e505b9SAlexander Graf {
80e6e505b9SAlexander Graf #ifdef CONFIG_AXP152_POWER
81e6e505b9SAlexander Graf 	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
82e6e505b9SAlexander Graf #elif defined CONFIG_AXP209_POWER
83e6e505b9SAlexander Graf 	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
84795857dfSChen-Yu Tsai #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
85e6e505b9SAlexander Graf # ifdef CONFIG_MACH_SUN6I
86e6e505b9SAlexander Graf 	return p2wi_write(reg, data);
87409677ecSChen-Yu Tsai # elif defined CONFIG_MACH_SUN8I_R40
88409677ecSChen-Yu Tsai 	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
89e6e505b9SAlexander Graf # else
90e6e505b9SAlexander Graf 	return rsb_write(AXP223_RUNTIME_ADDR, reg, data);
91e6e505b9SAlexander Graf # endif
92e6e505b9SAlexander Graf #endif
93e6e505b9SAlexander Graf }
94e6e505b9SAlexander Graf 
pmic_bus_setbits(u8 reg,u8 bits)95e6e505b9SAlexander Graf int pmic_bus_setbits(u8 reg, u8 bits)
96e6e505b9SAlexander Graf {
97e6e505b9SAlexander Graf 	int ret;
98e6e505b9SAlexander Graf 	u8 val;
99e6e505b9SAlexander Graf 
100e6e505b9SAlexander Graf 	ret = pmic_bus_read(reg, &val);
101e6e505b9SAlexander Graf 	if (ret)
102e6e505b9SAlexander Graf 		return ret;
103e6e505b9SAlexander Graf 
104*c970e895SOlliver Schinagl 	if ((val & bits) == bits)
105*c970e895SOlliver Schinagl 		return 0;
106*c970e895SOlliver Schinagl 
107e6e505b9SAlexander Graf 	val |= bits;
108e6e505b9SAlexander Graf 	return pmic_bus_write(reg, val);
109e6e505b9SAlexander Graf }
110e6e505b9SAlexander Graf 
pmic_bus_clrbits(u8 reg,u8 bits)111e6e505b9SAlexander Graf int pmic_bus_clrbits(u8 reg, u8 bits)
112e6e505b9SAlexander Graf {
113e6e505b9SAlexander Graf 	int ret;
114e6e505b9SAlexander Graf 	u8 val;
115e6e505b9SAlexander Graf 
116e6e505b9SAlexander Graf 	ret = pmic_bus_read(reg, &val);
117e6e505b9SAlexander Graf 	if (ret)
118e6e505b9SAlexander Graf 		return ret;
119e6e505b9SAlexander Graf 
120*c970e895SOlliver Schinagl 	if (!(val & bits))
121*c970e895SOlliver Schinagl 		return 0;
122*c970e895SOlliver Schinagl 
123e6e505b9SAlexander Graf 	val &= ~bits;
124e6e505b9SAlexander Graf 	return pmic_bus_write(reg, val);
125e6e505b9SAlexander Graf }
126