blob: e99ece8fb0838d1adecf174d5a1b2b3eae8f0eb9 [file] [log] [blame]
Ye Lic3ee9092019-10-15 02:15:18 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2019 NXP
4 */
5
6#include <common.h>
7#include <fdtdec.h>
8#include <errno.h>
9#include <dm.h>
Frieder Schrempfccf51fb2022-06-27 13:00:58 +020010#include <dm/device_compat.h>
Ye Lic3ee9092019-10-15 02:15:18 -070011#include <i2c.h>
Frieder Schrempfccf51fb2022-06-27 13:00:58 +020012#include <linux/err.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Frieder Schrempfccf51fb2022-06-27 13:00:58 +020015#include <asm-generic/gpio.h>
Ye Lic3ee9092019-10-15 02:15:18 -070016#include <power/pmic.h>
17#include <power/regulator.h>
18#include <power/pca9450.h>
19
20DECLARE_GLOBAL_DATA_PTR;
21
22static const struct pmic_child_info pmic_children_info[] = {
23 /* buck */
24 { .prefix = "b", .driver = PCA9450_REGULATOR_DRIVER},
Marek Vasut1d6dd082022-05-20 05:10:16 +020025 { .prefix = "B", .driver = PCA9450_REGULATOR_DRIVER},
Ye Lic3ee9092019-10-15 02:15:18 -070026 /* ldo */
27 { .prefix = "l", .driver = PCA9450_REGULATOR_DRIVER},
Marek Vasut1d6dd082022-05-20 05:10:16 +020028 { .prefix = "L", .driver = PCA9450_REGULATOR_DRIVER},
Ye Lic3ee9092019-10-15 02:15:18 -070029 { },
30};
31
Frieder Schrempfccf51fb2022-06-27 13:00:58 +020032struct pca9450_priv {
33 struct gpio_desc *sd_vsel_gpio;
34};
35
Ye Lic3ee9092019-10-15 02:15:18 -070036static int pca9450_reg_count(struct udevice *dev)
37{
38 return PCA9450_REG_NUM;
39}
40
41static int pca9450_write(struct udevice *dev, uint reg, const uint8_t *buff,
42 int len)
43{
44 if (dm_i2c_write(dev, reg, buff, len)) {
45 pr_err("write error to device: %p register: %#x!", dev, reg);
46 return -EIO;
47 }
48
49 return 0;
50}
51
52static int pca9450_read(struct udevice *dev, uint reg, uint8_t *buff,
53 int len)
54{
55 if (dm_i2c_read(dev, reg, buff, len)) {
56 pr_err("read error from device: %p register: %#x!", dev, reg);
57 return -EIO;
58 }
59
60 return 0;
61}
62
63static int pca9450_bind(struct udevice *dev)
64{
65 int children;
66 ofnode regulators_node;
67
68 regulators_node = dev_read_subnode(dev, "regulators");
69 if (!ofnode_valid(regulators_node)) {
70 debug("%s: %s regulators subnode not found!", __func__,
71 dev->name);
72 return -ENXIO;
73 }
74
75 debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
76
77 children = pmic_bind_children(dev, regulators_node,
78 pmic_children_info);
79 if (!children)
80 debug("%s: %s - no child found\n", __func__, dev->name);
81
82 /* Always return success for this device */
83 return 0;
84}
85
Frieder Schrempfccf51fb2022-06-27 13:00:58 +020086static int pca9450_probe(struct udevice *dev)
87{
88 struct pca9450_priv *priv = dev_get_priv(dev);
Marek Vasut14fc02a2022-12-09 20:35:46 +010089 unsigned int reset_ctrl;
Frieder Schrempfccf51fb2022-06-27 13:00:58 +020090 int ret = 0;
91
92 if (CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(DM_REGULATOR_PCA9450)) {
93 priv->sd_vsel_gpio = devm_gpiod_get_optional(dev, "sd-vsel",
94 GPIOD_IS_OUT |
95 GPIOD_IS_OUT_ACTIVE);
96 if (IS_ERR(priv->sd_vsel_gpio)) {
97 ret = PTR_ERR(priv->sd_vsel_gpio);
98 dev_err(dev, "Failed to request SD_VSEL GPIO: %d\n", ret);
Marek Vasut14fc02a2022-12-09 20:35:46 +010099 if (ret)
100 return ret;
Frieder Schrempfccf51fb2022-06-27 13:00:58 +0200101 }
102 }
103
Marek Vasut14fc02a2022-12-09 20:35:46 +0100104 if (ofnode_read_bool(dev_ofnode(dev), "nxp,wdog_b-warm-reset"))
105 reset_ctrl = PCA9450_PMIC_RESET_WDOG_B_CFG_WARM;
106 else
107 reset_ctrl = PCA9450_PMIC_RESET_WDOG_B_CFG_COLD_LDO12;
108
109 return pmic_clrsetbits(dev, PCA9450_RESET_CTRL,
110 PCA9450_PMIC_RESET_WDOG_B_CFG_MASK, reset_ctrl);
Frieder Schrempfccf51fb2022-06-27 13:00:58 +0200111}
112
Ye Lic3ee9092019-10-15 02:15:18 -0700113static struct dm_pmic_ops pca9450_ops = {
114 .reg_count = pca9450_reg_count,
115 .read = pca9450_read,
116 .write = pca9450_write,
117};
118
119static const struct udevice_id pca9450_ids[] = {
Marek Vasut5d9b83d2022-05-20 05:10:17 +0200120 { .compatible = "nxp,pca9450a", .data = NXP_CHIP_TYPE_PCA9450A, },
121 { .compatible = "nxp,pca9450b", .data = NXP_CHIP_TYPE_PCA9450BC, },
122 { .compatible = "nxp,pca9450c", .data = NXP_CHIP_TYPE_PCA9450BC, },
Ye Lib2ced042023-02-03 18:24:36 +0800123 { .compatible = "nxp,pca9451a", .data = NXP_CHIP_TYPE_PCA9451A, },
Ye Lic3ee9092019-10-15 02:15:18 -0700124 { }
125};
126
127U_BOOT_DRIVER(pmic_pca9450) = {
128 .name = "pca9450 pmic",
129 .id = UCLASS_PMIC,
130 .of_match = pca9450_ids,
131 .bind = pca9450_bind,
Frieder Schrempfccf51fb2022-06-27 13:00:58 +0200132 .probe = pca9450_probe,
Ye Lic3ee9092019-10-15 02:15:18 -0700133 .ops = &pca9450_ops,
Frieder Schrempfccf51fb2022-06-27 13:00:58 +0200134 .priv_auto = sizeof(struct pca9450_priv),
Ye Lic3ee9092019-10-15 02:15:18 -0700135};