mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 17:10:11 +00:00
3f6e4ec7c3
All devices based on ST-Ericsson Ux500 use a PMIC similar to AB8500 (Analog Baseband). There is AB8500, AB8505, AB9540 and AB8540 although in practice only AB8500 and AB8505 are relevant since the platforms with AB9540 and AB8540 were cancelled and never used in production. In general, the AB8500 PMIC uses I2C as control interface, where the different register banks are represented as separate I2C devices. However, in practice AB8500 is always connected to a special I2C bus on the DB8500 SoC that is controlled by the power/reset/clock management unit (PRCMU) firmware. Add a simple driver that allows reading/writing registers of the AB8500 PMIC. The driver directly accesses registers from the PRCMU parent device (represented by syscon in U-Boot). Abstracting it further (e.g. with the i2c uclass) would not provide any advantage because the PRCMU I2C bus is always just connected to AB8500 and vice-versa. The ab8500.h header is mostly taken as-is from Linux (with some minor adjustments) to allow using similar code in both Linux and U-Boot. Cc: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Stephan Gerhold <stephan@gerhold.net> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
125 lines
3.6 KiB
C
125 lines
3.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Based on include/linux/mfd/abx500/ab8500.h from Linux
|
|
* Copyright (C) ST-Ericsson SA 2010
|
|
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
|
*/
|
|
|
|
#ifndef _PMIC_AB8500_H_
|
|
#define _PMIC_AB8500_H_
|
|
|
|
/*
|
|
* AB IC versions
|
|
*
|
|
* AB8500_VERSION_AB8500 should be 0xFF but will never be read as need a
|
|
* non-supported multi-byte I2C access via PRCMU. Set to 0x00 to ease the
|
|
* print of version string.
|
|
*/
|
|
enum ab8500_version {
|
|
AB8500_VERSION_AB8500 = 0x0,
|
|
AB8500_VERSION_AB8505 = 0x1,
|
|
AB8500_VERSION_AB9540 = 0x2,
|
|
AB8500_VERSION_AB8540 = 0x4,
|
|
AB8500_VERSION_UNDEFINED,
|
|
};
|
|
|
|
/* AB8500 CIDs*/
|
|
#define AB8500_CUTEARLY 0x00
|
|
#define AB8500_CUT1P0 0x10
|
|
#define AB8500_CUT1P1 0x11
|
|
#define AB8500_CUT1P2 0x12 /* Only valid for AB8540 */
|
|
#define AB8500_CUT2P0 0x20
|
|
#define AB8500_CUT3P0 0x30
|
|
#define AB8500_CUT3P3 0x33
|
|
|
|
/*
|
|
* AB8500 bank addresses
|
|
*/
|
|
#define AB8500_BANK(bank, reg) (((bank) << 8) | (reg))
|
|
#define AB8500_M_FSM_RANK(reg) AB8500_BANK(0x0, reg)
|
|
#define AB8500_SYS_CTRL1_BLOCK(reg) AB8500_BANK(0x1, reg)
|
|
#define AB8500_SYS_CTRL2_BLOCK(reg) AB8500_BANK(0x2, reg)
|
|
#define AB8500_REGU_CTRL1(reg) AB8500_BANK(0x3, reg)
|
|
#define AB8500_REGU_CTRL2(reg) AB8500_BANK(0x4, reg)
|
|
#define AB8500_USB(reg) AB8500_BANK(0x5, reg)
|
|
#define AB8500_TVOUT(reg) AB8500_BANK(0x6, reg)
|
|
#define AB8500_DBI(reg) AB8500_BANK(0x7, reg)
|
|
#define AB8500_ECI_AV_ACC(reg) AB8500_BANK(0x8, reg)
|
|
#define AB8500_RESERVED(reg) AB8500_BANK(0x9, reg)
|
|
#define AB8500_GPADC(reg) AB8500_BANK(0xA, reg)
|
|
#define AB8500_CHARGER(reg) AB8500_BANK(0xB, reg)
|
|
#define AB8500_GAS_GAUGE(reg) AB8500_BANK(0xC, reg)
|
|
#define AB8500_AUDIO(reg) AB8500_BANK(0xD, reg)
|
|
#define AB8500_INTERRUPT(reg) AB8500_BANK(0xE, reg)
|
|
#define AB8500_RTC(reg) AB8500_BANK(0xF, reg)
|
|
#define AB8500_GPIO(reg) AB8500_BANK(0x10, reg)
|
|
#define AB8500_MISC(reg) AB8500_BANK(0x10, reg)
|
|
#define AB8500_DEVELOPMENT(reg) AB8500_BANK(0x11, reg)
|
|
#define AB8500_DEBUG(reg) AB8500_BANK(0x12, reg)
|
|
#define AB8500_PROD_TEST(reg) AB8500_BANK(0x13, reg)
|
|
#define AB8500_STE_TEST(reg) AB8500_BANK(0x14, reg)
|
|
#define AB8500_OTP_EMUL(reg) AB8500_BANK(0x15, reg)
|
|
|
|
#define AB8500_NUM_BANKS 0x16
|
|
#define AB8500_NUM_REGISTERS AB8500_BANK(AB8500_NUM_BANKS, 0)
|
|
|
|
struct ab8500 {
|
|
enum ab8500_version version;
|
|
u8 chip_id;
|
|
};
|
|
|
|
static inline int is_ab8500(struct ab8500 *ab)
|
|
{
|
|
return ab->version == AB8500_VERSION_AB8500;
|
|
}
|
|
|
|
static inline int is_ab8505(struct ab8500 *ab)
|
|
{
|
|
return ab->version == AB8500_VERSION_AB8505;
|
|
}
|
|
|
|
/* exclude also ab8505, ab9540... */
|
|
static inline int is_ab8500_1p0_or_earlier(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P0));
|
|
}
|
|
|
|
/* exclude also ab8505, ab9540... */
|
|
static inline int is_ab8500_1p1_or_earlier(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P1));
|
|
}
|
|
|
|
/* exclude also ab8505, ab9540... */
|
|
static inline int is_ab8500_2p0_or_earlier(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT2P0));
|
|
}
|
|
|
|
static inline int is_ab8500_3p3_or_earlier(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT3P3));
|
|
}
|
|
|
|
/* exclude also ab8505, ab9540... */
|
|
static inline int is_ab8500_2p0(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
|
|
}
|
|
|
|
static inline int is_ab8505_1p0_or_earlier(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8505(ab) && (ab->chip_id <= AB8500_CUT1P0));
|
|
}
|
|
|
|
static inline int is_ab8505_2p0(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8505(ab) && (ab->chip_id == AB8500_CUT2P0));
|
|
}
|
|
|
|
static inline int is_ab8505_2p0_earlier(struct ab8500 *ab)
|
|
{
|
|
return (is_ab8505(ab) && (ab->chip_id < AB8500_CUT2P0));
|
|
}
|
|
|
|
#endif
|