From patchwork Wed Dec 10 05:25:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 419400 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 1B2181400DE for ; Wed, 10 Dec 2014 16:26:04 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 81C3A4B6AD; Wed, 10 Dec 2014 06:26:00 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7YIY4BQP8diw; Wed, 10 Dec 2014 06:26:00 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CC8D24B6B2; Wed, 10 Dec 2014 06:25:55 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7F3834B6AD for ; Wed, 10 Dec 2014 06:25:45 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id o0n5IiphJR8d for ; Wed, 10 Dec 2014 06:25:45 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-ie0-f201.google.com (mail-ie0-f201.google.com [209.85.223.201]) by theia.denx.de (Postfix) with ESMTPS id 2C6A74B695 for ; Wed, 10 Dec 2014 06:25:40 +0100 (CET) Received: by mail-ie0-f201.google.com with SMTP id rp18so269531iec.2 for ; Tue, 09 Dec 2014 21:25:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mwa4t7IWqcKD4r1pULyTxiBboLviojJwBNli41EHrBI=; b=e57f+abjxgohlk/InSoyPJKXDUqg6arxxCheg6dKno/WbrpfV63p7Nh5a9d0yUPzRc Byw9P0BSC8U9DzeQBfn2QmlSN24VKLAx4IbtiCo7Ev2YfYxel1kR5RlQDg+nF6U8IcDP 5MR0cBWXWzf4TZXzdSgAlHpanGzYwAaIJ+9EmbnqcSxtUDIR/ka/X+Arn5QJbWy+mh9e h0HkCn7B2pQki2Ne5PMhjtKFLGTFrT2Et0FYh8IYR89b5kvmUE7YJqaGVB/23egjwpsE LQ9YTMT5xOYuoqdbz5r9agmUC7vMDnedrg+2o9s8ARBDyJhkyMc2BSfeZ7lgl6s+4cX6 dHxw== X-Gm-Message-State: ALoCoQnBLf/ohedkdUKiumODoYbHHwu+fHN1OUsK3AMGErwzuFm1nkv3uuUYq5HwIHrM3nqL4W8O X-Received: by 10.43.126.9 with SMTP id gu9mr6193365icc.11.1418189139381; Tue, 09 Dec 2014 21:25:39 -0800 (PST) Received: from corpmail-nozzle1-1.hot.corp.google.com ([100.108.1.104]) by gmr-mx.google.com with ESMTPS id 26si113327yhj.7.2014.12.09.21.25.39 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Dec 2014 21:25:39 -0800 (PST) Received: from kaki.bld.corp.google.com ([172.29.216.32]) by corpmail-nozzle1-1.hot.corp.google.com with ESMTP id tW3F1Wmp.1; Tue, 09 Dec 2014 21:25:39 -0800 Received: by kaki.bld.corp.google.com (Postfix, from userid 121222) id B37F8220873; Tue, 9 Dec 2014 22:25:38 -0700 (MST) From: Simon Glass To: U-Boot Mailing List Date: Tue, 9 Dec 2014 22:25:05 -0700 Message-Id: <1418189127-27407-2-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1418189127-27407-1-git-send-email-sjg@chromium.org> References: <1418189127-27407-1-git-send-email-sjg@chromium.org> Cc: Thierry Reding Subject: [U-Boot] [PATCH v4 01/23] power: Add AMS AS3722 PMIC support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Thierry Reding The AS3722 provides a number of DC/DC converters and LDOs as well as 8 GPIOs. Signed-off-by: Thierry Reding Signed-off-by: Simon Glass --- Changes in v4: - Use const unsigned for bus and address Changes in v3: - Use driver model for the PMIC drivers/power/Makefile | 1 + drivers/power/as3722.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++++ include/fdtdec.h | 1 + include/power/as3722.h | 27 +++++ lib/fdtdec.c | 1 + 5 files changed, 294 insertions(+) create mode 100644 drivers/power/as3722.c create mode 100644 include/power/as3722.h diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 04bd996..2145652 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -5,6 +5,7 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_AS3722_POWER) += as3722.o obj-$(CONFIG_AXP152_POWER) += axp152.o obj-$(CONFIG_AXP209_POWER) += axp209.o obj-$(CONFIG_AXP221_POWER) += axp221.o diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c new file mode 100644 index 0000000..4c6de79 --- /dev/null +++ b/drivers/power/as3722.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2014 NVIDIA Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#define pr_fmt(fmt) "as3722: " fmt + +#include +#include +#include +#include +#include + +#include + +#define AS3722_SD_VOLTAGE(n) (0x00 + (n)) +#define AS3722_GPIO_CONTROL(n) (0x08 + (n)) +#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0) +#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0) +#define AS3722_GPIO_CONTROL_INVERT (1 << 7) +#define AS3722_LDO_VOLTAGE(n) (0x10 + (n)) +#define AS3722_GPIO_SIGNAL_OUT 0x20 +#define AS3722_SD_CONTROL 0x4d +#define AS3722_LDO_CONTROL 0x4e +#define AS3722_ASIC_ID1 0x90 +#define AS3722_DEVICE_ID 0x0c +#define AS3722_ASIC_ID2 0x91 + +static int as3722_read(struct udevice *pmic, u8 reg, u8 *value) +{ + int err; + + err = i2c_read(pmic, reg, value, 1); + if (err < 0) + return err; + + return 0; +} + +static int as3722_write(struct udevice *pmic, u8 reg, u8 value) +{ + int err; + + err = i2c_write(pmic, reg, &value, 1); + if (err < 0) + return err; + + return 0; +} + +static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision) +{ + int err; + + err = as3722_read(pmic, AS3722_ASIC_ID1, id); + if (err) { + error("failed to read ID1 register: %d", err); + return err; + } + + err = as3722_read(pmic, AS3722_ASIC_ID2, revision); + if (err) { + error("failed to read ID2 register: %d", err); + return err; + } + + return 0; +} + +int as3722_sd_enable(struct udevice *pmic, unsigned int sd) +{ + u8 value; + int err; + + if (sd > 6) + return -EINVAL; + + err = as3722_read(pmic, AS3722_SD_CONTROL, &value); + if (err) { + error("failed to read SD control register: %d", err); + return err; + } + + value |= 1 << sd; + + err = as3722_write(pmic, AS3722_SD_CONTROL, value); + if (err < 0) { + error("failed to write SD control register: %d", err); + return err; + } + + return 0; +} + +int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value) +{ + int err; + + if (sd > 6) + return -EINVAL; + + err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value); + if (err < 0) { + error("failed to write SD%u voltage register: %d", sd, err); + return err; + } + + return 0; +} + +int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo) +{ + u8 value; + int err; + + if (ldo > 11) + return -EINVAL; + + err = as3722_read(pmic, AS3722_LDO_CONTROL, &value); + if (err) { + error("failed to read LDO control register: %d", err); + return err; + } + + value |= 1 << ldo; + + err = as3722_write(pmic, AS3722_LDO_CONTROL, value); + if (err < 0) { + error("failed to write LDO control register: %d", err); + return err; + } + + return 0; +} + +int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value) +{ + int err; + + if (ldo > 11) + return -EINVAL; + + err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value); + if (err < 0) { + error("failed to write LDO%u voltage register: %d", ldo, + err); + return err; + } + + return 0; +} + +int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, + unsigned long flags) +{ + u8 value = 0; + int err; + + if (flags & AS3722_GPIO_OUTPUT_VDDH) + value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; + + if (flags & AS3722_GPIO_INVERT) + value |= AS3722_GPIO_CONTROL_INVERT; + + err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); + if (err) { + error("failed to configure GPIO#%u: %d", gpio, err); + return err; + } + + return 0; +} + +static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio, + unsigned int level) +{ + const char *l; + u8 value; + int err; + + if (gpio > 7) + return -EINVAL; + + err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value); + if (err < 0) { + error("failed to read GPIO signal out register: %d", err); + return err; + } + + if (level == 0) { + value &= ~(1 << gpio); + l = "low"; + } else { + value |= 1 << gpio; + l = "high"; + } + + err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value); + if (err) { + error("failed to set GPIO#%u %s: %d", gpio, l, err); + return err; + } + + return 0; +} + +int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio, + unsigned int level) +{ + u8 value; + int err; + + if (gpio > 7) + return -EINVAL; + + if (level == 0) + value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; + else + value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; + + err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); + if (err) { + error("failed to configure GPIO#%u as output: %d", gpio, err); + return err; + } + + err = as3722_gpio_set(pmic, gpio, level); + if (err < 0) { + error("failed to set GPIO#%u high: %d", gpio, err); + return err; + } + + return 0; +} + +int as3722_init(struct udevice **devp) +{ + struct udevice *pmic; + u8 id, revision; + const unsigned int bus = 0; + const unsigned int address = 0x40; + int err; + + err = i2c_get_chip_for_busnum(bus, address, &pmic); + if (err) + return err; + err = as3722_read_id(pmic, &id, &revision); + if (err < 0) { + error("failed to read ID: %d", err); + return err; + } + + if (id != AS3722_DEVICE_ID) { + error("unknown device"); + return -ENOENT; + } + + debug("AS3722 revision %#x found on I2C bus %u, address %#x\n", + revision, bus, address); + *devp = pmic; + + return 0; +} diff --git a/include/fdtdec.h b/include/fdtdec.h index d2b665c..cc2dc5c 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -123,6 +123,7 @@ enum fdt_compat_id { COMPAT_INTEL_PANTHERPOINT_AHCI, /* Intel Pantherpoint AHCI */ COMPAT_INTEL_MODEL_206AX, /* Intel Model 206AX CPU */ COMPAT_INTEL_GMA, /* Intel Graphics Media Accelerator */ + COMPAT_AMS_AS3722, /* AMS AS3722 PMIC */ COMPAT_COUNT, }; diff --git a/include/power/as3722.h b/include/power/as3722.h new file mode 100644 index 0000000..aa966d2 --- /dev/null +++ b/include/power/as3722.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014 NVIDIA Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __POWER_AS3722_H__ +#define __POWER_AS3722_H__ + +#include + +#define AS3722_GPIO_OUTPUT_VDDH (1 << 0) +#define AS3722_GPIO_INVERT (1 << 1) + +struct udevice; + +int as3722_init(struct udevice **devp); +int as3722_sd_enable(struct udevice *pmic, unsigned int sd); +int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value); +int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo); +int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value); +int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, + unsigned long flags); +int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio, + unsigned int level); + +#endif /* __POWER_AS3722_H__ */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 9d86dba..9a4d470 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -78,6 +78,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"), COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"), COMPAT(INTEL_GMA, "intel,gma"), + COMPAT(AMS_AS3722, "ams,as3722"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id)