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