blob: 54adcbf50f5515ade7af71612bf7608cb462360e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Thierry Reding09c0cf22014-12-09 22:25:05 -07002/*
3 * Copyright (C) 2014 NVIDIA Corporation
Thierry Reding09c0cf22014-12-09 22:25:05 -07004 */
5
6#define pr_fmt(fmt) "as3722: " fmt
7
8#include <common.h>
9#include <dm.h>
10#include <errno.h>
11#include <fdtdec.h>
12#include <i2c.h>
Simon Glassb3d2ed32017-07-25 08:30:12 -060013#include <dm/lists.h>
Thierry Reding09c0cf22014-12-09 22:25:05 -070014#include <power/as3722.h>
Simon Glassb3d2ed32017-07-25 08:30:12 -060015#include <power/pmic.h>
Thierry Reding09c0cf22014-12-09 22:25:05 -070016
Simon Glassb3d2ed32017-07-25 08:30:12 -060017#define AS3722_NUM_OF_REGS 0x92
Thierry Reding09c0cf22014-12-09 22:25:05 -070018
Simon Glassb3d2ed32017-07-25 08:30:12 -060019static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
Thierry Reding09c0cf22014-12-09 22:25:05 -070020{
Simon Glassb3d2ed32017-07-25 08:30:12 -060021 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070022
Simon Glassb3d2ed32017-07-25 08:30:12 -060023 ret = dm_i2c_read(dev, reg, buff, len);
24 if (ret < 0)
25 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070026
27 return 0;
28}
29
Simon Glassb3d2ed32017-07-25 08:30:12 -060030static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
31 int len)
Thierry Reding09c0cf22014-12-09 22:25:05 -070032{
Simon Glassb3d2ed32017-07-25 08:30:12 -060033 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070034
Simon Glassb3d2ed32017-07-25 08:30:12 -060035 ret = dm_i2c_write(dev, reg, buff, len);
36 if (ret < 0)
37 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070038
39 return 0;
40}
41
Simon Glassb3d2ed32017-07-25 08:30:12 -060042static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp)
Thierry Reding09c0cf22014-12-09 22:25:05 -070043{
Simon Glassb3d2ed32017-07-25 08:30:12 -060044 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070045
Simon Glassb3d2ed32017-07-25 08:30:12 -060046 ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
47 if (ret < 0) {
Simon Glass73126ac2018-11-18 08:14:28 -070048 pr_err("failed to read ID1 register: %d\n", ret);
Simon Glassb3d2ed32017-07-25 08:30:12 -060049 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070050 }
Simon Glassb3d2ed32017-07-25 08:30:12 -060051 *idp = ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070052
Simon Glassb3d2ed32017-07-25 08:30:12 -060053 ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
54 if (ret < 0) {
Simon Glass73126ac2018-11-18 08:14:28 -070055 pr_err("failed to read ID2 register: %d\n", ret);
Simon Glassb3d2ed32017-07-25 08:30:12 -060056 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070057 }
Simon Glassb3d2ed32017-07-25 08:30:12 -060058 *revisionp = ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070059
60 return 0;
61}
62
Simon Glassb3d2ed32017-07-25 08:30:12 -060063/* TODO(treding@nvidia.com): Add proper regulator support to avoid this */
64int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value)
Thierry Reding09c0cf22014-12-09 22:25:05 -070065{
Simon Glassb3d2ed32017-07-25 08:30:12 -060066 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070067
68 if (sd > 6)
69 return -EINVAL;
70
Simon Glassb3d2ed32017-07-25 08:30:12 -060071 ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
72 if (ret < 0) {
Simon Glass73126ac2018-11-18 08:14:28 -070073 pr_err("failed to write SD%u voltage register: %d\n", sd, ret);
Simon Glassb3d2ed32017-07-25 08:30:12 -060074 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070075 }
76
77 return 0;
78}
79
Simon Glassb3d2ed32017-07-25 08:30:12 -060080int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value)
Thierry Reding09c0cf22014-12-09 22:25:05 -070081{
Simon Glassb3d2ed32017-07-25 08:30:12 -060082 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070083
84 if (ldo > 11)
85 return -EINVAL;
86
Simon Glassb3d2ed32017-07-25 08:30:12 -060087 ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
88 if (ret < 0) {
Simon Glass73126ac2018-11-18 08:14:28 -070089 pr_err("failed to write LDO%u voltage register: %d\n", ldo,
90 ret);
Simon Glassb3d2ed32017-07-25 08:30:12 -060091 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -070092 }
93
94 return 0;
95}
96
Simon Glassb3d2ed32017-07-25 08:30:12 -060097static int as3722_probe(struct udevice *dev)
Thierry Reding09c0cf22014-12-09 22:25:05 -070098{
Simon Glassb3d2ed32017-07-25 08:30:12 -060099 uint id, revision;
100 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -0700101
Simon Glassb3d2ed32017-07-25 08:30:12 -0600102 ret = as3722_read_id(dev, &id, &revision);
103 if (ret < 0) {
Simon Glass73126ac2018-11-18 08:14:28 -0700104 pr_err("failed to read ID: %d\n", ret);
Simon Glassb3d2ed32017-07-25 08:30:12 -0600105 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -0700106 }
107
Simon Glassb3d2ed32017-07-25 08:30:12 -0600108 if (id != AS3722_DEVICE_ID) {
Simon Glass73126ac2018-11-18 08:14:28 -0700109 pr_err("unknown device\n");
Simon Glassb3d2ed32017-07-25 08:30:12 -0600110 return -ENOENT;
Thierry Reding09c0cf22014-12-09 22:25:05 -0700111 }
112
Simon Glassb3d2ed32017-07-25 08:30:12 -0600113 debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
Thierry Reding09c0cf22014-12-09 22:25:05 -0700114
115 return 0;
116}
117
Simon Glassb3d2ed32017-07-25 08:30:12 -0600118#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
119static const struct pmic_child_info pmic_children_info[] = {
120 { .prefix = "sd", .driver = "as3722_stepdown"},
121 { .prefix = "ldo", .driver = "as3722_ldo"},
122 { },
123};
Thierry Reding09c0cf22014-12-09 22:25:05 -0700124
Simon Glassb3d2ed32017-07-25 08:30:12 -0600125static int as3722_bind(struct udevice *dev)
126{
127 struct udevice *gpio_dev;
128 ofnode regulators_node;
129 int children;
130 int ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -0700131
Simon Glassb3d2ed32017-07-25 08:30:12 -0600132 regulators_node = dev_read_subnode(dev, "regulators");
133 if (!ofnode_valid(regulators_node)) {
134 debug("%s: %s regulators subnode not found\n", __func__,
135 dev->name);
136 return -ENXIO;
Thierry Reding09c0cf22014-12-09 22:25:05 -0700137 }
138
Simon Glassb3d2ed32017-07-25 08:30:12 -0600139 children = pmic_bind_children(dev, regulators_node, pmic_children_info);
140 if (!children)
141 debug("%s: %s - no child found\n", __func__, dev->name);
142 ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev);
143 if (ret) {
144 debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret);
145 return ret;
Thierry Reding09c0cf22014-12-09 22:25:05 -0700146 }
147
148 return 0;
149}
Simon Glassb3d2ed32017-07-25 08:30:12 -0600150#endif
Thierry Reding09c0cf22014-12-09 22:25:05 -0700151
Simon Glassb3d2ed32017-07-25 08:30:12 -0600152static int as3722_reg_count(struct udevice *dev)
Simon Glass053da132015-04-14 21:03:26 -0600153{
Simon Glassb3d2ed32017-07-25 08:30:12 -0600154 return AS3722_NUM_OF_REGS;
Simon Glass053da132015-04-14 21:03:26 -0600155}
156
Simon Glassb3d2ed32017-07-25 08:30:12 -0600157static struct dm_pmic_ops as3722_ops = {
158 .reg_count = as3722_reg_count,
159 .read = as3722_read,
160 .write = as3722_write,
161};
Thierry Reding09c0cf22014-12-09 22:25:05 -0700162
Simon Glassb3d2ed32017-07-25 08:30:12 -0600163static const struct udevice_id as3722_ids[] = {
164 { .compatible = "ams,as3722" },
165 { }
166};
Thierry Reding09c0cf22014-12-09 22:25:05 -0700167
Simon Glassb3d2ed32017-07-25 08:30:12 -0600168U_BOOT_DRIVER(pmic_as3722) = {
169 .name = "as3722_pmic",
170 .id = UCLASS_PMIC,
171 .of_match = as3722_ids,
172#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
173 .bind = as3722_bind,
174#endif
175 .probe = as3722_probe,
176 .ops = &as3722_ops,
177};