183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2453c5a92SJacob Chen /*
3453c5a92SJacob Chen * Copyright (C) 2015 Google, Inc
4453c5a92SJacob Chen * Written by Simon Glass <sjg@chromium.org>
5453c5a92SJacob Chen */
6453c5a92SJacob Chen
7453c5a92SJacob Chen #include <common.h>
8453c5a92SJacob Chen #include <dm.h>
9453c5a92SJacob Chen #include <errno.h>
10453c5a92SJacob Chen #include <power/rk8xx_pmic.h>
11453c5a92SJacob Chen #include <power/pmic.h>
12453c5a92SJacob Chen
13453c5a92SJacob Chen static const struct pmic_child_info pmic_children_info[] = {
14453c5a92SJacob Chen { .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
15453c5a92SJacob Chen { .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
16453c5a92SJacob Chen { .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
17453c5a92SJacob Chen { },
18453c5a92SJacob Chen };
19453c5a92SJacob Chen
rk8xx_reg_count(struct udevice * dev)20453c5a92SJacob Chen static int rk8xx_reg_count(struct udevice *dev)
21453c5a92SJacob Chen {
22453c5a92SJacob Chen return RK808_NUM_OF_REGS;
23453c5a92SJacob Chen }
24453c5a92SJacob Chen
rk8xx_write(struct udevice * dev,uint reg,const uint8_t * buff,int len)25453c5a92SJacob Chen static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
26453c5a92SJacob Chen int len)
27453c5a92SJacob Chen {
28453c5a92SJacob Chen int ret;
29453c5a92SJacob Chen
30453c5a92SJacob Chen ret = dm_i2c_write(dev, reg, buff, len);
31453c5a92SJacob Chen if (ret) {
32*c83c436dSSimon Glass debug("write error to device: %p register: %#x!\n", dev, reg);
33453c5a92SJacob Chen return ret;
34453c5a92SJacob Chen }
35453c5a92SJacob Chen
36453c5a92SJacob Chen return 0;
37453c5a92SJacob Chen }
38453c5a92SJacob Chen
rk8xx_read(struct udevice * dev,uint reg,uint8_t * buff,int len)39453c5a92SJacob Chen static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
40453c5a92SJacob Chen {
41453c5a92SJacob Chen int ret;
42453c5a92SJacob Chen
43453c5a92SJacob Chen ret = dm_i2c_read(dev, reg, buff, len);
44453c5a92SJacob Chen if (ret) {
45*c83c436dSSimon Glass debug("read error from device: %p register: %#x!\n", dev, reg);
46453c5a92SJacob Chen return ret;
47453c5a92SJacob Chen }
48453c5a92SJacob Chen
49453c5a92SJacob Chen return 0;
50453c5a92SJacob Chen }
51453c5a92SJacob Chen
52453c5a92SJacob Chen #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
rk8xx_bind(struct udevice * dev)53453c5a92SJacob Chen static int rk8xx_bind(struct udevice *dev)
54453c5a92SJacob Chen {
557a869e6cSSimon Glass ofnode regulators_node;
56453c5a92SJacob Chen int children;
57453c5a92SJacob Chen
587a869e6cSSimon Glass regulators_node = dev_read_subnode(dev, "regulators");
597a869e6cSSimon Glass if (!ofnode_valid(regulators_node)) {
60*c83c436dSSimon Glass debug("%s: %s regulators subnode not found!\n", __func__,
61453c5a92SJacob Chen dev->name);
62453c5a92SJacob Chen return -ENXIO;
63453c5a92SJacob Chen }
64453c5a92SJacob Chen
65453c5a92SJacob Chen debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
66453c5a92SJacob Chen
67453c5a92SJacob Chen children = pmic_bind_children(dev, regulators_node, pmic_children_info);
68453c5a92SJacob Chen if (!children)
69453c5a92SJacob Chen debug("%s: %s - no child found\n", __func__, dev->name);
70453c5a92SJacob Chen
71453c5a92SJacob Chen /* Always return success for this device */
72453c5a92SJacob Chen return 0;
73453c5a92SJacob Chen }
74453c5a92SJacob Chen #endif
75453c5a92SJacob Chen
rk8xx_probe(struct udevice * dev)76453c5a92SJacob Chen static int rk8xx_probe(struct udevice *dev)
77453c5a92SJacob Chen {
78453c5a92SJacob Chen struct rk8xx_priv *priv = dev_get_priv(dev);
79453c5a92SJacob Chen uint8_t msb, lsb;
80453c5a92SJacob Chen
81453c5a92SJacob Chen /* read Chip variant */
82453c5a92SJacob Chen rk8xx_read(dev, ID_MSB, &msb, 1);
83453c5a92SJacob Chen rk8xx_read(dev, ID_LSB, &lsb, 1);
84453c5a92SJacob Chen
85453c5a92SJacob Chen priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
86453c5a92SJacob Chen
87453c5a92SJacob Chen return 0;
88453c5a92SJacob Chen }
89453c5a92SJacob Chen
90453c5a92SJacob Chen static struct dm_pmic_ops rk8xx_ops = {
91453c5a92SJacob Chen .reg_count = rk8xx_reg_count,
92453c5a92SJacob Chen .read = rk8xx_read,
93453c5a92SJacob Chen .write = rk8xx_write,
94453c5a92SJacob Chen };
95453c5a92SJacob Chen
96453c5a92SJacob Chen static const struct udevice_id rk8xx_ids[] = {
97453c5a92SJacob Chen { .compatible = "rockchip,rk808" },
98453c5a92SJacob Chen { .compatible = "rockchip,rk818" },
99453c5a92SJacob Chen { }
100453c5a92SJacob Chen };
101453c5a92SJacob Chen
102453c5a92SJacob Chen U_BOOT_DRIVER(pmic_rk8xx) = {
103453c5a92SJacob Chen .name = "rk8xx pmic",
104453c5a92SJacob Chen .id = UCLASS_PMIC,
105453c5a92SJacob Chen .of_match = rk8xx_ids,
106453c5a92SJacob Chen #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
107453c5a92SJacob Chen .bind = rk8xx_bind,
108453c5a92SJacob Chen #endif
1097c1fb0a7SKever Yang .priv_auto_alloc_size = sizeof(struct rk8xx_priv),
110453c5a92SJacob Chen .probe = rk8xx_probe,
111453c5a92SJacob Chen .ops = &rk8xx_ops,
112453c5a92SJacob Chen };
113