blob: c962160307b1df7f53c5cad3dea88ee9b76cf547 [file] [log] [blame]
Tom Rini4549e782018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +01004 */
5
6#include <common.h>
7#include <dm.h>
8#include <errno.h>
9#include <i2c.h>
Patrick Delaunay8811583e2019-02-04 11:26:19 +010010#include <sysreset.h>
11#include <dm/device.h>
12#include <dm/lists.h>
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010013#include <power/pmic.h>
Patrick Delaunayd46c22b2019-02-04 11:26:16 +010014#include <power/stpmic1.h>
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010015
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010016#define STPMIC1_NUM_OF_REGS 0x100
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010017
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010018#if CONFIG_IS_ENABLED(DM_REGULATOR)
19static const struct pmic_child_info stpmic1_children_info[] = {
20 { .prefix = "ldo", .driver = "stpmic1_ldo" },
21 { .prefix = "buck", .driver = "stpmic1_buck" },
22 { .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
23 { .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
24 { .prefix = "boost", .driver = "stpmic1_boost" },
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020025 { },
26};
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010027#endif /* DM_REGULATOR */
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020028
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010029static int stpmic1_reg_count(struct udevice *dev)
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010030{
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010031 return STPMIC1_NUM_OF_REGS;
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010032}
33
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010034static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff,
35 int len)
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010036{
37 int ret;
38
39 ret = dm_i2c_write(dev, reg, buff, len);
40 if (ret)
41 dev_err(dev, "%s: failed to write register %#x :%d",
42 __func__, reg, ret);
43
44 return ret;
45}
46
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010047static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010048{
49 int ret;
50
51 ret = dm_i2c_read(dev, reg, buff, len);
52 if (ret)
53 dev_err(dev, "%s: failed to read register %#x : %d",
54 __func__, reg, ret);
55
56 return ret;
57}
58
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010059static int stpmic1_bind(struct udevice *dev)
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020060{
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010061#if CONFIG_IS_ENABLED(DM_REGULATOR)
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020062 ofnode regulators_node;
63 int children;
64
65 regulators_node = dev_read_subnode(dev, "regulators");
66 if (!ofnode_valid(regulators_node)) {
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010067 dev_dbg(dev, "regulators subnode not found!");
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020068 return -ENXIO;
69 }
70 dev_dbg(dev, "found regulators subnode\n");
71
72 children = pmic_bind_children(dev, regulators_node,
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010073 stpmic1_children_info);
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020074 if (!children)
75 dev_dbg(dev, "no child found\n");
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010076#endif /* DM_REGULATOR */
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020077
Patrick Delaunay8811583e2019-02-04 11:26:19 +010078 if (CONFIG_IS_ENABLED(SYSRESET))
79 return device_bind_driver(dev, "stpmic1-sysreset",
80 "stpmic1-sysreset", NULL);
81
Patrice Chotard1f0dfa12018-04-26 17:13:10 +020082 return 0;
83}
84
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010085static struct dm_pmic_ops stpmic1_ops = {
86 .reg_count = stpmic1_reg_count,
87 .read = stpmic1_read,
88 .write = stpmic1_write,
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010089};
90
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010091static const struct udevice_id stpmic1_ids[] = {
92 { .compatible = "st,stpmic1" },
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010093 { }
94};
95
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010096U_BOOT_DRIVER(pmic_stpmic1) = {
97 .name = "stpmic1_pmic",
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +010098 .id = UCLASS_PMIC,
Patrick Delaunay42f01aa2019-02-04 11:26:17 +010099 .of_match = stpmic1_ids,
100 .bind = stpmic1_bind,
101 .ops = &stpmic1_ops,
Patrick Delaunay5d0c74e2018-03-12 10:46:12 +0100102};
Patrick Delaunay8811583e2019-02-04 11:26:19 +0100103
104#ifdef CONFIG_SYSRESET
105static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
106{
107 struct udevice *pmic_dev;
108 int ret;
109
110 if (type != SYSRESET_POWER)
111 return -EPROTONOSUPPORT;
112
113 ret = uclass_get_device_by_driver(UCLASS_PMIC,
114 DM_GET_DRIVER(pmic_stpmic1),
115 &pmic_dev);
116
117 if (ret)
118 return -EOPNOTSUPP;
119
120 ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
121 if (ret < 0)
122 return ret;
123
124 ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR,
125 ret | STPMIC1_SWOFF | STPMIC1_RREQ_EN);
126 if (ret < 0)
127 return ret;
128
129 return -EINPROGRESS;
130}
131
132static struct sysreset_ops stpmic1_sysreset_ops = {
133 .request = stpmic1_sysreset_request,
134};
135
136U_BOOT_DRIVER(stpmic1_sysreset) = {
137 .name = "stpmic1-sysreset",
138 .id = UCLASS_SYSRESET,
139 .ops = &stpmic1_sysreset_ops,
140};
141#endif