power: pmic: add driver for Dialog DA9063 PMIC
authorMartin Fuzzey <martin.fuzzey@flowbird.group>
Tue, 14 Jan 2020 15:56:16 +0000 (15:56 +0000)
committerTom Rini <trini@konsulko.com>
Tue, 28 Jan 2020 00:54:20 +0000 (19:54 -0500)
This adds the basic register access operations and child regulator
binding (if a regulator driver exists).

Robert Beckett: simplify accesses by using bottom bit of address as
offset overflow. This avoids the need to track which page we are on.
Add an option CONFIG_SPL_DM_PMIC_DA9063.

Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group>
Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/da9063.c [new file with mode: 0644]
include/power/da9063_pmic.h [new file with mode: 0644]

index df9372c239e3af05f2e6d4e2de952973b7679bf0..ef8bf49d49563be888a30f9fb6434ab22f56c377 100644 (file)
@@ -40,6 +40,20 @@ config PMIC_ACT8846
        functions. It uses an I2C interface and is designed for use with
        tablets and smartphones.
 
+config DM_PMIC_DA9063
+       bool "Enable Driver Model for the Dialog DA9063 PMIC"
+       depends on DM_PMIC
+       help
+         This config enables implementation of driver-model pmic uclass features
+         for PMIC DA9063. The driver implements read/write operations.
+
+config SPL_DM_PMIC_DA9063
+       bool "Enable Driver Model for the Dialog DA9063 PMIC in SPL"
+       depends on DM_PMIC && SPL
+       help
+         This config enables implementation of driver-model pmic uclass features
+         for PMIC DA9063. The driver implements read/write operations.
+
 config PMIC_AS3722
        bool "Enable support for the Austria Micro Systems (AMS) AS7322 PMIC"
        help
index 7b6cb0ee1bd2c7df81908e8386d530637ea465ec..9cd6c375c06ff980a5f89caa4a783bf6972564e0 100644 (file)
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
 obj-$(CONFIG_DM_PMIC_FAN53555) += fan53555.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_DA9063) += da9063.o
 obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
 obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
 obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
diff --git a/drivers/power/pmic/da9063.c b/drivers/power/pmic/da9063.c
new file mode 100644 (file)
index 0000000..abda7a5
--- /dev/null
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright (C) 2018 Flowbird
+ *  Martin Fuzzey  <martin.fuzzey@flowbird.group>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/da9063_pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+       { .prefix = "ldo", .driver = DA9063_LDO_DRIVER },
+       { .prefix = "b", .driver = DA9063_BUCK_DRIVER },
+       { },
+};
+
+/*
+ * The register map is non contiguous and attempts to read in the holes fail.
+ * But "pmic dump" tries to dump the full register map.
+ * So define the holes here so we can fix that.
+ */
+struct da9063_reg_hole {
+       u16     first;
+       u16     last;
+};
+
+static const struct da9063_reg_hole da9063_reg_holes[] = {
+       DA9063_REG_HOLE_1,
+       DA9063_REG_HOLE_2,
+       DA9063_REG_HOLE_3,
+       /* These aren't readable. I can't see why from the datasheet but
+        * attempts to read fail and the kernel marks them unreadable too,
+        */
+       {DA9063_REG_OTP_COUNT, DA9063_REG_OTP_DATA},
+};
+
+static int da9063_reg_count(struct udevice *dev)
+{
+       return DA9063_NUM_OF_REGS;
+}
+
+static bool da9063_reg_valid(uint reg)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(da9063_reg_holes); i++) {
+               const struct da9063_reg_hole *hole = &da9063_reg_holes[i];
+
+               if (reg >= hole->first && reg <= hole->last)
+                       return false;
+       }
+
+       return true;
+}
+
+static int da9063_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                       int len)
+{
+       if (dm_i2c_write(dev, reg, buff, len)) {
+               pr_err("write error to device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int da9063_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       if (!da9063_reg_valid(reg))
+               return -ENODATA;
+
+       if (dm_i2c_read(dev, reg, buff, len)) {
+               pr_err("read error from device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int da9063_bind(struct udevice *dev)
+{
+       ofnode regulators_node;
+       int children;
+
+       regulators_node = dev_read_subnode(dev, "regulators");
+       if (!ofnode_valid(regulators_node)) {
+               debug("%s: %s regulators subnode not found!", __func__,
+                     dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+       if (!children)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static int da9063_probe(struct udevice *dev)
+{
+       return i2c_set_chip_addr_offset_mask(dev, 0x1);
+}
+
+static struct dm_pmic_ops da9063_ops = {
+       .reg_count = da9063_reg_count,
+       .read = da9063_read,
+       .write = da9063_write,
+};
+
+static const struct udevice_id da9063_ids[] = {
+       { .compatible = "dlg,da9063" },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_da9063) = {
+       .name = "da9063_pmic",
+       .id = UCLASS_PMIC,
+       .of_match = da9063_ids,
+       .bind = da9063_bind,
+       .probe = da9063_probe,
+       .ops = &da9063_ops,
+};
diff --git a/include/power/da9063_pmic.h b/include/power/da9063_pmic.h
new file mode 100644 (file)
index 0000000..9b0f76c
--- /dev/null
@@ -0,0 +1,308 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  Copyright (C) 2018 Flowbird
+ *  Martin Fuzzey  <martin.fuzzey@flowbird.group>
+ */
+
+#ifndef __DA9063_PMIC_H_
+#define __DA9063_PMIC_H_
+
+/* Register definitions below taken from the kernel */
+
+/* Page selection I2C or SPI always in the beginning of any page. */
+/* Page 0 : I2C access 0x000 - 0x0FF   SPI access 0x000 - 0x07F */
+/* Page 1 :                            SPI access 0x080 - 0x0FF */
+/* Page 2 : I2C access 0x100 - 0x1FF   SPI access 0x100 - 0x17F */
+/* Page 3 :                            SPI access 0x180 - 0x1FF */
+#define        DA9063_REG_PAGE_CON             0x00
+
+/* System Control and Event Registers */
+#define        DA9063_REG_STATUS_A             0x01
+#define        DA9063_REG_STATUS_B             0x02
+#define        DA9063_REG_STATUS_C             0x03
+#define        DA9063_REG_STATUS_D             0x04
+#define        DA9063_REG_FAULT_LOG            0x05
+#define        DA9063_REG_EVENT_A              0x06
+#define        DA9063_REG_EVENT_B              0x07
+#define        DA9063_REG_EVENT_C              0x08
+#define        DA9063_REG_EVENT_D              0x09
+#define        DA9063_REG_IRQ_MASK_A           0x0A
+#define        DA9063_REG_IRQ_MASK_B           0x0B
+#define        DA9063_REG_IRQ_MASK_C           0x0C
+#define        DA9063_REG_IRQ_MASK_D           0x0D
+#define        DA9063_REG_CONTROL_A            0x0E
+#define        DA9063_REG_CONTROL_B            0x0F
+#define        DA9063_REG_CONTROL_C            0x10
+#define        DA9063_REG_CONTROL_D            0x11
+#define        DA9063_REG_CONTROL_E            0x12
+#define        DA9063_REG_CONTROL_F            0x13
+#define        DA9063_REG_PD_DIS               0x14
+
+/* GPIO Control Registers */
+#define        DA9063_REG_GPIO_0_1             0x15
+#define        DA9063_REG_GPIO_2_3             0x16
+#define        DA9063_REG_GPIO_4_5             0x17
+#define        DA9063_REG_GPIO_6_7             0x18
+#define        DA9063_REG_GPIO_8_9             0x19
+#define        DA9063_REG_GPIO_10_11           0x1A
+#define        DA9063_REG_GPIO_12_13           0x1B
+#define        DA9063_REG_GPIO_14_15           0x1C
+#define        DA9063_REG_GPIO_MODE0_7         0x1D
+#define        DA9063_REG_GPIO_MODE8_15        0x1E
+#define        DA9063_REG_SWITCH_CONT          0x1F
+
+/* Regulator Control Registers */
+#define        DA9063_REG_BCORE2_CONT          0x20
+#define        DA9063_REG_BCORE1_CONT          0x21
+#define        DA9063_REG_BPRO_CONT            0x22
+#define        DA9063_REG_BMEM_CONT            0x23
+#define        DA9063_REG_BIO_CONT             0x24
+#define        DA9063_REG_BPERI_CONT           0x25
+#define        DA9063_REG_LDO1_CONT            0x26
+#define        DA9063_REG_LDO2_CONT            0x27
+#define        DA9063_REG_LDO3_CONT            0x28
+#define        DA9063_REG_LDO4_CONT            0x29
+#define        DA9063_REG_LDO5_CONT            0x2A
+#define        DA9063_REG_LDO6_CONT            0x2B
+#define        DA9063_REG_LDO7_CONT            0x2C
+#define        DA9063_REG_LDO8_CONT            0x2D
+#define        DA9063_REG_LDO9_CONT            0x2E
+#define        DA9063_REG_LDO10_CONT           0x2F
+#define        DA9063_REG_LDO11_CONT           0x30
+#define        DA9063_REG_SUPPLIES             0x31
+#define        DA9063_REG_DVC_1                0x32
+#define        DA9063_REG_DVC_2                0x33
+
+/* GP-ADC Control Registers */
+#define        DA9063_REG_ADC_MAN              0x34
+#define        DA9063_REG_ADC_CONT             0x35
+#define        DA9063_REG_VSYS_MON             0x36
+#define        DA9063_REG_ADC_RES_L            0x37
+#define        DA9063_REG_ADC_RES_H            0x38
+#define        DA9063_REG_VSYS_RES             0x39
+#define        DA9063_REG_ADCIN1_RES           0x3A
+#define        DA9063_REG_ADCIN2_RES           0x3B
+#define        DA9063_REG_ADCIN3_RES           0x3C
+#define        DA9063_REG_MON_A8_RES           0x3D
+#define        DA9063_REG_MON_A9_RES           0x3E
+#define        DA9063_REG_MON_A10_RES          0x3F
+
+/* RTC Calendar and Alarm Registers */
+#define        DA9063_REG_COUNT_S              0x40
+#define        DA9063_REG_COUNT_MI             0x41
+#define        DA9063_REG_COUNT_H              0x42
+#define        DA9063_REG_COUNT_D              0x43
+#define        DA9063_REG_COUNT_MO             0x44
+#define        DA9063_REG_COUNT_Y              0x45
+
+#define        DA9063_AD_REG_ALARM_MI          0x46
+#define        DA9063_AD_REG_ALARM_H           0x47
+#define        DA9063_AD_REG_ALARM_D           0x48
+#define        DA9063_AD_REG_ALARM_MO          0x49
+#define        DA9063_AD_REG_ALARM_Y           0x4A
+#define        DA9063_AD_REG_SECOND_A          0x4B
+#define        DA9063_AD_REG_SECOND_B          0x4C
+#define        DA9063_AD_REG_SECOND_C          0x4D
+#define        DA9063_AD_REG_SECOND_D          0x4E
+
+#define        DA9063_BB_REG_ALARM_S           0x46
+#define        DA9063_BB_REG_ALARM_MI          0x47
+#define        DA9063_BB_REG_ALARM_H           0x48
+#define        DA9063_BB_REG_ALARM_D           0x49
+#define        DA9063_BB_REG_ALARM_MO          0x4A
+#define        DA9063_BB_REG_ALARM_Y           0x4B
+#define        DA9063_BB_REG_SECOND_A          0x4C
+#define        DA9063_BB_REG_SECOND_B          0x4D
+#define        DA9063_BB_REG_SECOND_C          0x4E
+#define        DA9063_BB_REG_SECOND_D          0x4F
+
+#define DA9063_REG_HOLE_1 {0x50, 0x7F}
+
+/* Sequencer Control Registers */
+#define        DA9063_REG_SEQ                  0x81
+#define        DA9063_REG_SEQ_TIMER            0x82
+#define        DA9063_REG_ID_2_1               0x83
+#define        DA9063_REG_ID_4_3               0x84
+#define        DA9063_REG_ID_6_5               0x85
+#define        DA9063_REG_ID_8_7               0x86
+#define        DA9063_REG_ID_10_9              0x87
+#define        DA9063_REG_ID_12_11             0x88
+#define        DA9063_REG_ID_14_13             0x89
+#define        DA9063_REG_ID_16_15             0x8A
+#define        DA9063_REG_ID_18_17             0x8B
+#define        DA9063_REG_ID_20_19             0x8C
+#define        DA9063_REG_ID_22_21             0x8D
+#define        DA9063_REG_ID_24_23             0x8E
+#define        DA9063_REG_ID_26_25             0x8F
+#define        DA9063_REG_ID_28_27             0x90
+#define        DA9063_REG_ID_30_29             0x91
+#define        DA9063_REG_ID_32_31             0x92
+#define        DA9063_REG_SEQ_A                0x95
+#define        DA9063_REG_SEQ_B                0x96
+#define        DA9063_REG_WAIT                 0x97
+#define        DA9063_REG_EN_32K               0x98
+#define        DA9063_REG_RESET                0x99
+
+/* Regulator Setting Registers */
+#define        DA9063_REG_BUCK_ILIM_A          0x9A
+#define        DA9063_REG_BUCK_ILIM_B          0x9B
+#define        DA9063_REG_BUCK_ILIM_C          0x9C
+#define        DA9063_REG_BCORE2_CFG           0x9D
+#define        DA9063_REG_BCORE1_CFG           0x9E
+#define        DA9063_REG_BPRO_CFG             0x9F
+#define        DA9063_REG_BIO_CFG              0xA0
+#define        DA9063_REG_BMEM_CFG             0xA1
+#define        DA9063_REG_BPERI_CFG            0xA2
+#define        DA9063_REG_VBCORE2_A            0xA3
+#define        DA9063_REG_VBCORE1_A            0xA4
+#define        DA9063_REG_VBPRO_A              0xA5
+#define        DA9063_REG_VBMEM_A              0xA6
+#define        DA9063_REG_VBIO_A               0xA7
+#define        DA9063_REG_VBPERI_A             0xA8
+#define        DA9063_REG_VLDO1_A              0xA9
+#define        DA9063_REG_VLDO2_A              0xAA
+#define        DA9063_REG_VLDO3_A              0xAB
+#define        DA9063_REG_VLDO4_A              0xAC
+#define        DA9063_REG_VLDO5_A              0xAD
+#define        DA9063_REG_VLDO6_A              0xAE
+#define        DA9063_REG_VLDO7_A              0xAF
+#define        DA9063_REG_VLDO8_A              0xB0
+#define        DA9063_REG_VLDO9_A              0xB1
+#define        DA9063_REG_VLDO10_A             0xB2
+#define        DA9063_REG_VLDO11_A             0xB3
+#define        DA9063_REG_VBCORE2_B            0xB4
+#define        DA9063_REG_VBCORE1_B            0xB5
+#define        DA9063_REG_VBPRO_B              0xB6
+#define        DA9063_REG_VBMEM_B              0xB7
+#define        DA9063_REG_VBIO_B               0xB8
+#define        DA9063_REG_VBPERI_B             0xB9
+#define        DA9063_REG_VLDO1_B              0xBA
+#define        DA9063_REG_VLDO2_B              0xBB
+#define        DA9063_REG_VLDO3_B              0xBC
+#define        DA9063_REG_VLDO4_B              0xBD
+#define        DA9063_REG_VLDO5_B              0xBE
+#define        DA9063_REG_VLDO6_B              0xBF
+#define        DA9063_REG_VLDO7_B              0xC0
+#define        DA9063_REG_VLDO8_B              0xC1
+#define        DA9063_REG_VLDO9_B              0xC2
+#define        DA9063_REG_VLDO10_B             0xC3
+#define        DA9063_REG_VLDO11_B             0xC4
+
+/* Backup Battery Charger Control Register */
+#define        DA9063_REG_BBAT_CONT            0xC5
+
+/* GPIO PWM (LED) */
+#define        DA9063_REG_GPO11_LED            0xC6
+#define        DA9063_REG_GPO14_LED            0xC7
+#define        DA9063_REG_GPO15_LED            0xC8
+
+/* GP-ADC Threshold Registers */
+#define        DA9063_REG_ADC_CFG              0xC9
+#define        DA9063_REG_AUTO1_HIGH           0xCA
+#define        DA9063_REG_AUTO1_LOW            0xCB
+#define        DA9063_REG_AUTO2_HIGH           0xCC
+#define        DA9063_REG_AUTO2_LOW            0xCD
+#define        DA9063_REG_AUTO3_HIGH           0xCE
+#define        DA9063_REG_AUTO3_LOW            0xCF
+
+#define DA9063_REG_HOLE_2 {0xD0, 0xFF}
+
+/* DA9063 Configuration registers */
+/* OTP */
+#define        DA9063_REG_OTP_COUNT            0x101
+#define        DA9063_REG_OTP_ADDR             0x102
+#define        DA9063_REG_OTP_DATA             0x103
+
+/* Customer Trim and Configuration */
+#define        DA9063_REG_T_OFFSET             0x104
+#define        DA9063_REG_INTERFACE            0x105
+#define        DA9063_REG_CONFIG_A             0x106
+#define        DA9063_REG_CONFIG_B             0x107
+#define        DA9063_REG_CONFIG_C             0x108
+#define        DA9063_REG_CONFIG_D             0x109
+#define        DA9063_REG_CONFIG_E             0x10A
+#define        DA9063_REG_CONFIG_F             0x10B
+#define        DA9063_REG_CONFIG_G             0x10C
+#define        DA9063_REG_CONFIG_H             0x10D
+#define        DA9063_REG_CONFIG_I             0x10E
+#define        DA9063_REG_CONFIG_J             0x10F
+#define        DA9063_REG_CONFIG_K             0x110
+#define        DA9063_REG_CONFIG_L             0x111
+
+#define        DA9063_AD_REG_MON_REG_1         0x112
+#define        DA9063_AD_REG_MON_REG_2         0x113
+#define        DA9063_AD_REG_MON_REG_3         0x114
+#define        DA9063_AD_REG_MON_REG_4         0x115
+#define        DA9063_AD_REG_MON_REG_5         0x116
+#define        DA9063_AD_REG_MON_REG_6         0x117
+#define        DA9063_AD_REG_TRIM_CLDR         0x118
+
+#define        DA9063_AD_REG_GP_ID_0           0x119
+#define        DA9063_AD_REG_GP_ID_1           0x11A
+#define        DA9063_AD_REG_GP_ID_2           0x11B
+#define        DA9063_AD_REG_GP_ID_3           0x11C
+#define        DA9063_AD_REG_GP_ID_4           0x11D
+#define        DA9063_AD_REG_GP_ID_5           0x11E
+#define        DA9063_AD_REG_GP_ID_6           0x11F
+#define        DA9063_AD_REG_GP_ID_7           0x120
+#define        DA9063_AD_REG_GP_ID_8           0x121
+#define        DA9063_AD_REG_GP_ID_9           0x122
+#define        DA9063_AD_REG_GP_ID_10          0x123
+#define        DA9063_AD_REG_GP_ID_11          0x124
+#define        DA9063_AD_REG_GP_ID_12          0x125
+#define        DA9063_AD_REG_GP_ID_13          0x126
+#define        DA9063_AD_REG_GP_ID_14          0x127
+#define        DA9063_AD_REG_GP_ID_15          0x128
+#define        DA9063_AD_REG_GP_ID_16          0x129
+#define        DA9063_AD_REG_GP_ID_17          0x12A
+#define        DA9063_AD_REG_GP_ID_18          0x12B
+#define        DA9063_AD_REG_GP_ID_19          0x12C
+
+#define        DA9063_BB_REG_CONFIG_M          0x112
+#define        DA9063_BB_REG_CONFIG_N          0x113
+
+#define        DA9063_BB_REG_MON_REG_1         0x114
+#define        DA9063_BB_REG_MON_REG_2         0x115
+#define        DA9063_BB_REG_MON_REG_3         0x116
+#define        DA9063_BB_REG_MON_REG_4         0x117
+#define        DA9063_BB_REG_MON_REG_5         0x11E
+#define        DA9063_BB_REG_MON_REG_6         0x11F
+#define        DA9063_BB_REG_TRIM_CLDR         0x120
+/* General Purpose Registers */
+#define        DA9063_BB_REG_GP_ID_0           0x121
+#define        DA9063_BB_REG_GP_ID_1           0x122
+#define        DA9063_BB_REG_GP_ID_2           0x123
+#define        DA9063_BB_REG_GP_ID_3           0x124
+#define        DA9063_BB_REG_GP_ID_4           0x125
+#define        DA9063_BB_REG_GP_ID_5           0x126
+#define        DA9063_BB_REG_GP_ID_6           0x127
+#define        DA9063_BB_REG_GP_ID_7           0x128
+#define        DA9063_BB_REG_GP_ID_8           0x129
+#define        DA9063_BB_REG_GP_ID_9           0x12A
+#define        DA9063_BB_REG_GP_ID_10          0x12B
+#define        DA9063_BB_REG_GP_ID_11          0x12C
+#define        DA9063_BB_REG_GP_ID_12          0x12D
+#define        DA9063_BB_REG_GP_ID_13          0x12E
+#define        DA9063_BB_REG_GP_ID_14          0x12F
+#define        DA9063_BB_REG_GP_ID_15          0x130
+#define        DA9063_BB_REG_GP_ID_16          0x131
+#define        DA9063_BB_REG_GP_ID_17          0x132
+#define        DA9063_BB_REG_GP_ID_18          0x133
+#define        DA9063_BB_REG_GP_ID_19          0x134
+
+/* 0x135 - 0x13f are readable, but not documented */
+#define DA9063_REG_HOLE_3 {0x140, 0x17F}
+
+/* Chip ID and variant */
+#define        DA9063_REG_CHIP_ID              0x181
+#define        DA9063_REG_CHIP_VARIANT         0x182
+#define DA9063_REG_CUSTOMER_ID         0x183
+#define DA9063_REG_CONFIG_ID           0x184
+
+#define DA9063_NUM_OF_REGS             (DA9063_REG_CONFIG_ID + 1)
+
+/* Drivers name */
+#define DA9063_LDO_DRIVER      "da9063_ldo"
+#define DA9063_BUCK_DRIVER     "da9063_buck"
+
+#endif