12838c07fSSimon Glass /*
22838c07fSSimon Glass * Copyright (C) 2014 NVIDIA Corporation
32838c07fSSimon Glass *
42838c07fSSimon Glass * SPDX-License-Identifier: GPL-2.0+
52838c07fSSimon Glass */
62838c07fSSimon Glass
72838c07fSSimon Glass #define pr_fmt(fmt) "as3722: " fmt
82838c07fSSimon Glass
92838c07fSSimon Glass #include <common.h>
102838c07fSSimon Glass #include <dm.h>
112838c07fSSimon Glass #include <errno.h>
122838c07fSSimon Glass #include <fdtdec.h>
132838c07fSSimon Glass #include <i2c.h>
14e3f44f5cSSimon Glass #include <dm/lists.h>
152838c07fSSimon Glass #include <power/as3722.h>
16e3f44f5cSSimon Glass #include <power/pmic.h>
172838c07fSSimon Glass
18e3f44f5cSSimon Glass #define AS3722_NUM_OF_REGS 0x92
192838c07fSSimon Glass
as3722_read(struct udevice * dev,uint reg,uint8_t * buff,int len)20e3f44f5cSSimon Glass static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
212838c07fSSimon Glass {
22e3f44f5cSSimon Glass int ret;
232838c07fSSimon Glass
24e3f44f5cSSimon Glass ret = dm_i2c_read(dev, reg, buff, len);
25e3f44f5cSSimon Glass if (ret < 0)
26e3f44f5cSSimon Glass return ret;
272838c07fSSimon Glass
282838c07fSSimon Glass return 0;
292838c07fSSimon Glass }
302838c07fSSimon Glass
as3722_write(struct udevice * dev,uint reg,const uint8_t * buff,int len)31e3f44f5cSSimon Glass static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
32e3f44f5cSSimon Glass int len)
332838c07fSSimon Glass {
34e3f44f5cSSimon Glass int ret;
352838c07fSSimon Glass
36e3f44f5cSSimon Glass ret = dm_i2c_write(dev, reg, buff, len);
37e3f44f5cSSimon Glass if (ret < 0)
38e3f44f5cSSimon Glass return ret;
392838c07fSSimon Glass
402838c07fSSimon Glass return 0;
412838c07fSSimon Glass }
422838c07fSSimon Glass
as3722_read_id(struct udevice * dev,uint * idp,uint * revisionp)43e3f44f5cSSimon Glass static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp)
442838c07fSSimon Glass {
45e3f44f5cSSimon Glass int ret;
462838c07fSSimon Glass
47e3f44f5cSSimon Glass ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
48e3f44f5cSSimon Glass if (ret < 0) {
49*90aa625cSMasahiro Yamada pr_err("failed to read ID1 register: %d", ret);
50e3f44f5cSSimon Glass return ret;
512838c07fSSimon Glass }
52e3f44f5cSSimon Glass *idp = ret;
532838c07fSSimon Glass
54e3f44f5cSSimon Glass ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
55e3f44f5cSSimon Glass if (ret < 0) {
56*90aa625cSMasahiro Yamada pr_err("failed to read ID2 register: %d", ret);
57e3f44f5cSSimon Glass return ret;
582838c07fSSimon Glass }
59e3f44f5cSSimon Glass *revisionp = ret;
602838c07fSSimon Glass
612838c07fSSimon Glass return 0;
622838c07fSSimon Glass }
632838c07fSSimon Glass
64e3f44f5cSSimon Glass /* TODO(treding@nvidia.com): Add proper regulator support to avoid this */
as3722_sd_set_voltage(struct udevice * dev,unsigned int sd,u8 value)65e3f44f5cSSimon Glass int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value)
662838c07fSSimon Glass {
67e3f44f5cSSimon Glass int ret;
682838c07fSSimon Glass
692838c07fSSimon Glass if (sd > 6)
702838c07fSSimon Glass return -EINVAL;
712838c07fSSimon Glass
72e3f44f5cSSimon Glass ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
73e3f44f5cSSimon Glass if (ret < 0) {
74*90aa625cSMasahiro Yamada pr_err("failed to write SD%u voltage register: %d", sd, ret);
75e3f44f5cSSimon Glass return ret;
762838c07fSSimon Glass }
772838c07fSSimon Glass
782838c07fSSimon Glass return 0;
792838c07fSSimon Glass }
802838c07fSSimon Glass
as3722_ldo_set_voltage(struct udevice * dev,unsigned int ldo,u8 value)81e3f44f5cSSimon Glass int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value)
822838c07fSSimon Glass {
83e3f44f5cSSimon Glass int ret;
842838c07fSSimon Glass
852838c07fSSimon Glass if (ldo > 11)
862838c07fSSimon Glass return -EINVAL;
872838c07fSSimon Glass
88e3f44f5cSSimon Glass ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
89e3f44f5cSSimon Glass if (ret < 0) {
90*90aa625cSMasahiro Yamada pr_err("failed to write LDO%u voltage register: %d", ldo,
91e3f44f5cSSimon Glass ret);
92e3f44f5cSSimon Glass return ret;
932838c07fSSimon Glass }
942838c07fSSimon Glass
952838c07fSSimon Glass return 0;
962838c07fSSimon Glass }
972838c07fSSimon Glass
as3722_probe(struct udevice * dev)98e3f44f5cSSimon Glass static int as3722_probe(struct udevice *dev)
992838c07fSSimon Glass {
100e3f44f5cSSimon Glass uint id, revision;
101e3f44f5cSSimon Glass int ret;
1022838c07fSSimon Glass
103e3f44f5cSSimon Glass ret = as3722_read_id(dev, &id, &revision);
104e3f44f5cSSimon Glass if (ret < 0) {
105*90aa625cSMasahiro Yamada pr_err("failed to read ID: %d", ret);
106e3f44f5cSSimon Glass return ret;
1072838c07fSSimon Glass }
1082838c07fSSimon Glass
1092838c07fSSimon Glass if (id != AS3722_DEVICE_ID) {
110*90aa625cSMasahiro Yamada pr_err("unknown device");
1112838c07fSSimon Glass return -ENOENT;
1122838c07fSSimon Glass }
1132838c07fSSimon Glass
114e3f44f5cSSimon Glass debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
1152838c07fSSimon Glass
1162838c07fSSimon Glass return 0;
1172838c07fSSimon Glass }
118e3f44f5cSSimon Glass
119e3f44f5cSSimon Glass #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
120e3f44f5cSSimon Glass static const struct pmic_child_info pmic_children_info[] = {
121e3f44f5cSSimon Glass { .prefix = "sd", .driver = "as3722_stepdown"},
122e3f44f5cSSimon Glass { .prefix = "ldo", .driver = "as3722_ldo"},
123e3f44f5cSSimon Glass { },
124e3f44f5cSSimon Glass };
125e3f44f5cSSimon Glass
as3722_bind(struct udevice * dev)126e3f44f5cSSimon Glass static int as3722_bind(struct udevice *dev)
127e3f44f5cSSimon Glass {
128e3f44f5cSSimon Glass struct udevice *gpio_dev;
129e3f44f5cSSimon Glass ofnode regulators_node;
130e3f44f5cSSimon Glass int children;
131e3f44f5cSSimon Glass int ret;
132e3f44f5cSSimon Glass
133e3f44f5cSSimon Glass regulators_node = dev_read_subnode(dev, "regulators");
134e3f44f5cSSimon Glass if (!ofnode_valid(regulators_node)) {
135e3f44f5cSSimon Glass debug("%s: %s regulators subnode not found\n", __func__,
136e3f44f5cSSimon Glass dev->name);
137e3f44f5cSSimon Glass return -ENXIO;
138e3f44f5cSSimon Glass }
139e3f44f5cSSimon Glass
140e3f44f5cSSimon Glass children = pmic_bind_children(dev, regulators_node, pmic_children_info);
141e3f44f5cSSimon Glass if (!children)
142e3f44f5cSSimon Glass debug("%s: %s - no child found\n", __func__, dev->name);
143e3f44f5cSSimon Glass ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev);
144e3f44f5cSSimon Glass if (ret) {
145e3f44f5cSSimon Glass debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret);
146e3f44f5cSSimon Glass return ret;
147e3f44f5cSSimon Glass }
148e3f44f5cSSimon Glass
149e3f44f5cSSimon Glass return 0;
150e3f44f5cSSimon Glass }
151e3f44f5cSSimon Glass #endif
152e3f44f5cSSimon Glass
as3722_reg_count(struct udevice * dev)153e3f44f5cSSimon Glass static int as3722_reg_count(struct udevice *dev)
154e3f44f5cSSimon Glass {
155e3f44f5cSSimon Glass return AS3722_NUM_OF_REGS;
156e3f44f5cSSimon Glass }
157e3f44f5cSSimon Glass
158e3f44f5cSSimon Glass static struct dm_pmic_ops as3722_ops = {
159e3f44f5cSSimon Glass .reg_count = as3722_reg_count,
160e3f44f5cSSimon Glass .read = as3722_read,
161e3f44f5cSSimon Glass .write = as3722_write,
162e3f44f5cSSimon Glass };
163e3f44f5cSSimon Glass
164e3f44f5cSSimon Glass static const struct udevice_id as3722_ids[] = {
165e3f44f5cSSimon Glass { .compatible = "ams,as3722" },
166e3f44f5cSSimon Glass { }
167e3f44f5cSSimon Glass };
168e3f44f5cSSimon Glass
169e3f44f5cSSimon Glass U_BOOT_DRIVER(pmic_as3722) = {
170e3f44f5cSSimon Glass .name = "as3722_pmic",
171e3f44f5cSSimon Glass .id = UCLASS_PMIC,
172e3f44f5cSSimon Glass .of_match = as3722_ids,
173e3f44f5cSSimon Glass #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
174e3f44f5cSSimon Glass .bind = as3722_bind,
175e3f44f5cSSimon Glass #endif
176e3f44f5cSSimon Glass .probe = as3722_probe,
177e3f44f5cSSimon Glass .ops = &as3722_ops,
178e3f44f5cSSimon Glass };
179