blob: 59c65702863c2714966fd7bb0abf31550dd3126d [file] [log] [blame]
Martin Fuzzey483880c2020-01-14 15:56:16 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Flowbird
4 * Martin Fuzzey <martin.fuzzey@flowbird.group>
5 */
6
Martin Fuzzey483880c2020-01-14 15:56:16 +00007#include <fdtdec.h>
8#include <errno.h>
9#include <dm.h>
Fabio Estevam52612182024-09-17 10:55:50 -030010#include <dm/device-internal.h>
11#include <dm/device_compat.h>
12#include <dm/lists.h>
Martin Fuzzey483880c2020-01-14 15:56:16 +000013#include <i2c.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060014#include <log.h>
Simon Glass1e94b462023-09-14 18:21:46 -060015#include <linux/printk.h>
Martin Fuzzey483880c2020-01-14 15:56:16 +000016#include <power/pmic.h>
17#include <power/regulator.h>
18#include <power/da9063_pmic.h>
19
20static const struct pmic_child_info pmic_children_info[] = {
21 { .prefix = "ldo", .driver = DA9063_LDO_DRIVER },
22 { .prefix = "b", .driver = DA9063_BUCK_DRIVER },
23 { },
24};
25
26/*
27 * The register map is non contiguous and attempts to read in the holes fail.
28 * But "pmic dump" tries to dump the full register map.
29 * So define the holes here so we can fix that.
30 */
31struct da9063_reg_hole {
32 u16 first;
33 u16 last;
34};
35
36static const struct da9063_reg_hole da9063_reg_holes[] = {
37 DA9063_REG_HOLE_1,
38 DA9063_REG_HOLE_2,
39 DA9063_REG_HOLE_3,
40 /* These aren't readable. I can't see why from the datasheet but
41 * attempts to read fail and the kernel marks them unreadable too,
42 */
43 {DA9063_REG_OTP_COUNT, DA9063_REG_OTP_DATA},
44};
45
46static int da9063_reg_count(struct udevice *dev)
47{
48 return DA9063_NUM_OF_REGS;
49}
50
51static bool da9063_reg_valid(uint reg)
52{
53 int i;
54
55 for (i = 0; i < ARRAY_SIZE(da9063_reg_holes); i++) {
56 const struct da9063_reg_hole *hole = &da9063_reg_holes[i];
57
58 if (reg >= hole->first && reg <= hole->last)
59 return false;
60 }
61
62 return true;
63}
64
65static int da9063_write(struct udevice *dev, uint reg, const uint8_t *buff,
66 int len)
67{
68 if (dm_i2c_write(dev, reg, buff, len)) {
69 pr_err("write error to device: %p register: %#x!", dev, reg);
70 return -EIO;
71 }
72
73 return 0;
74}
75
76static int da9063_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
77{
78 if (!da9063_reg_valid(reg))
79 return -ENODATA;
80
81 if (dm_i2c_read(dev, reg, buff, len)) {
82 pr_err("read error from device: %p register: %#x!", dev, reg);
83 return -EIO;
84 }
85
86 return 0;
87}
88
89static int da9063_bind(struct udevice *dev)
90{
91 ofnode regulators_node;
Fabio Estevam52612182024-09-17 10:55:50 -030092 struct driver *drv;
Martin Fuzzey483880c2020-01-14 15:56:16 +000093 int children;
94
95 regulators_node = dev_read_subnode(dev, "regulators");
96 if (!ofnode_valid(regulators_node)) {
97 debug("%s: %s regulators subnode not found!", __func__,
98 dev->name);
99 return -ENXIO;
100 }
101
102 debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
103
104 children = pmic_bind_children(dev, regulators_node, pmic_children_info);
105 if (!children)
106 debug("%s: %s - no child found\n", __func__, dev->name);
107
Fabio Estevam52612182024-09-17 10:55:50 -0300108 drv = lists_driver_lookup_name("da9063-wdt");
109 if (!drv)
110 return 0;
111
112 return device_bind_with_driver_data(dev, drv, "da9063-wdt", dev->driver_data,
113 dev_ofnode(dev), &dev);
Martin Fuzzey483880c2020-01-14 15:56:16 +0000114}
115
116static int da9063_probe(struct udevice *dev)
117{
118 return i2c_set_chip_addr_offset_mask(dev, 0x1);
119}
120
121static struct dm_pmic_ops da9063_ops = {
122 .reg_count = da9063_reg_count,
123 .read = da9063_read,
124 .write = da9063_write,
125};
126
127static const struct udevice_id da9063_ids[] = {
128 { .compatible = "dlg,da9063" },
129 { }
130};
131
132U_BOOT_DRIVER(pmic_da9063) = {
133 .name = "da9063_pmic",
134 .id = UCLASS_PMIC,
135 .of_match = da9063_ids,
136 .bind = da9063_bind,
137 .probe = da9063_probe,
138 .ops = &da9063_ops,
139};