1 /*
2 * Copyright (c) 2024 Vogl Electronic GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT mps_mpm54304
8
9 #include <errno.h>
10
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/drivers/regulator.h>
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(mps_mpm54304, CONFIG_REGULATOR_LOG_LEVEL);
16
17 #define MPM54304_REG_EN 0x0CU
18 #define MPM54304_REG_VENDOR_ID 0x13U
19
20 #define MPM54304_BUCK1_EN_MASK BIT(7)
21 #define MPM54304_BUCK2_EN_MASK BIT(6)
22 #define MPM54304_BUCK3_EN_MASK BIT(5)
23 #define MPM54304_BUCK4_EN_MASK BIT(4)
24
25 struct regulator_mpm54304_config {
26 struct regulator_common_config common;
27 struct i2c_dt_spec bus;
28 uint8_t enable_mask;
29 };
30
31 struct regulator_mpm54304_data {
32 struct regulator_common_data common;
33 };
34
regulator_mpm54304_enable(const struct device * dev)35 static int regulator_mpm54304_enable(const struct device *dev)
36 {
37 const struct regulator_mpm54304_config *config = dev->config;
38
39 return i2c_reg_update_byte_dt(&config->bus, MPM54304_REG_EN, config->enable_mask,
40 config->enable_mask);
41 }
42
regulator_mpm54304_disable(const struct device * dev)43 static int regulator_mpm54304_disable(const struct device *dev)
44 {
45 const struct regulator_mpm54304_config *config = dev->config;
46
47 return i2c_reg_update_byte_dt(&config->bus, MPM54304_REG_EN, config->enable_mask, 0x00);
48 }
49
regulator_mpm54304_init(const struct device * dev)50 static int regulator_mpm54304_init(const struct device *dev)
51 {
52 const struct regulator_mpm54304_config *config = dev->config;
53 uint8_t value;
54
55 if (!i2c_is_ready_dt(&config->bus)) {
56 LOG_ERR("I2C bus %s not ready", config->bus.bus->name);
57 return -ENODEV;
58 }
59
60 /* dummy read needed for chip to function properly */
61 (void)i2c_reg_read_byte_dt(&config->bus, MPM54304_REG_VENDOR_ID, &value);
62 LOG_DBG("vendor id: 0x%x", value >> 4);
63
64 return 0;
65 }
66
67 static DEVICE_API(regulator, mpm54304_api) = {
68 .enable = regulator_mpm54304_enable,
69 .disable = regulator_mpm54304_disable,
70 };
71
72 #define REGULATOR_MPM54304_DEFINE(node_id, id, child_name) \
73 static const struct regulator_mpm54304_config regulator_mpm54304_config_##id = { \
74 .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \
75 .bus = I2C_DT_SPEC_GET(DT_PARENT(node_id)), \
76 .enable_mask = MPM54304_##child_name##_EN_MASK, \
77 }; \
78 \
79 static struct regulator_mpm54304_data regulator_mpm54304_data_##id; \
80 DEVICE_DT_DEFINE(node_id, regulator_mpm54304_init, NULL, ®ulator_mpm54304_data_##id, \
81 ®ulator_mpm54304_config_##id, POST_KERNEL, \
82 CONFIG_REGULATOR_MPM54304_INIT_PRIORITY, &mpm54304_api);
83
84 #define REGULATOR_MPM54304_DEFINE_COND(inst, child, child_name) \
85 IF_ENABLED( \
86 DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \
87 (REGULATOR_MPM54304_DEFINE(DT_INST_CHILD(inst, child), child##inst, child_name)))
88
89 #define REGULATOR_MPM54304_DEFINE_ALL(inst) \
90 REGULATOR_MPM54304_DEFINE_COND(inst, buck1, BUCK1) \
91 REGULATOR_MPM54304_DEFINE_COND(inst, buck2, BUCK2) \
92 REGULATOR_MPM54304_DEFINE_COND(inst, buck3, BUCK3) \
93 REGULATOR_MPM54304_DEFINE_COND(inst, buck4, BUCK4)
94
95 DT_INST_FOREACH_STATUS_OKAY(REGULATOR_MPM54304_DEFINE_ALL)
96