allwinner: H6: Factor out I2C platform setup
In the H6 platform code there is a routine to do the platform initialisation of the R_I2C controller. We will need a very similar setup routine to initialise the RSB controller on the A64. Move this code to sunxi_common.c and generalise it to support all SoCs and also to cover the related RSB bus. Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
parent
103f19f055
commit
d5ddf67a66
|
@ -19,5 +19,6 @@ void sunxi_security_setup(void);
|
|||
|
||||
uint16_t sunxi_read_soc_id(void);
|
||||
void sunxi_set_gpio_out(char port, int pin, bool level_high);
|
||||
int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb);
|
||||
|
||||
#endif /* SUNXI_PRIVATE_H */
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <mmio.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
|
@ -100,3 +102,58 @@ void sunxi_set_gpio_out(char port, int pin, bool level_high)
|
|||
0x7 << ((pin % 8) * 4),
|
||||
0x1 << ((pin % 8) * 4));
|
||||
}
|
||||
|
||||
int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb)
|
||||
{
|
||||
uint32_t pin_func = 0x77;
|
||||
uint32_t device_bit;
|
||||
unsigned int reset_offset = 0xb0;
|
||||
|
||||
switch (socid) {
|
||||
case SUNXI_SOC_H5:
|
||||
if (use_rsb)
|
||||
return -ENODEV;
|
||||
pin_func = 0x22;
|
||||
device_bit = BIT(6);
|
||||
break;
|
||||
case SUNXI_SOC_H6:
|
||||
if (use_rsb)
|
||||
return -ENODEV;
|
||||
pin_func = 0x33;
|
||||
device_bit = BIT(16);
|
||||
reset_offset = 0x19c;
|
||||
break;
|
||||
case SUNXI_SOC_A64:
|
||||
pin_func = use_rsb ? 0x22 : 0x33;
|
||||
device_bit = use_rsb ? BIT(3) : BIT(6);
|
||||
break;
|
||||
default:
|
||||
INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* un-gate R_PIO clock */
|
||||
if (socid != SUNXI_SOC_H6)
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0));
|
||||
|
||||
/* switch pins PL0 and PL1 to the desired function */
|
||||
mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func);
|
||||
|
||||
/* level 2 drive strength */
|
||||
mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU);
|
||||
|
||||
/* set both pins to pull-up */
|
||||
mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U);
|
||||
|
||||
/* assert, then de-assert reset of I2C/RSB controller */
|
||||
mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
|
||||
|
||||
/* un-gate clock */
|
||||
if (socid != SUNXI_SOC_H6)
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
|
||||
else
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <mmio.h>
|
||||
#include <mentor/mi2cv.h>
|
||||
#include <string.h>
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
|
@ -25,36 +26,6 @@ enum pmic_type {
|
|||
|
||||
enum pmic_type pmic;
|
||||
|
||||
static int sunxi_init_r_i2c(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* switch pins PL0 and PL1 to I2C */
|
||||
reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x00);
|
||||
mmio_write_32(SUNXI_R_PIO_BASE + 0x00, (reg & ~0xff) | 0x33);
|
||||
|
||||
/* level 2 drive strength */
|
||||
reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x14);
|
||||
mmio_write_32(SUNXI_R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa);
|
||||
|
||||
/* set both ports to pull-up */
|
||||
reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x1c);
|
||||
mmio_write_32(SUNXI_R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5);
|
||||
|
||||
/* assert & de-assert reset of R_I2C */
|
||||
reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c);
|
||||
mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg & ~BIT(16));
|
||||
mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16));
|
||||
|
||||
/* un-gate R_I2C clock */
|
||||
mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16) | BIT(0));
|
||||
|
||||
/* call mi2cv driver */
|
||||
i2c_init((void *)SUNXI_R_I2C_BASE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val)
|
||||
{
|
||||
int ret;
|
||||
|
@ -101,7 +72,9 @@ int sunxi_pmic_setup(uint16_t socid)
|
|||
{
|
||||
int ret;
|
||||
|
||||
sunxi_init_r_i2c();
|
||||
sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
|
||||
/* initialise mi2cv driver */
|
||||
i2c_init((void *)SUNXI_R_I2C_BASE);
|
||||
|
||||
NOTICE("PMIC: Probing AXP805\n");
|
||||
pmic = AXP805;
|
||||
|
@ -121,7 +94,10 @@ void __dead2 sunxi_power_down(void)
|
|||
|
||||
switch (pmic) {
|
||||
case AXP805:
|
||||
sunxi_init_r_i2c();
|
||||
/* Re-initialise after rich OS might have used it. */
|
||||
sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
|
||||
/* initialise mi2cv driver */
|
||||
i2c_init((void *)SUNXI_R_I2C_BASE);
|
||||
axp_i2c_read(AXP805_ADDR, 0x32, &val);
|
||||
axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue