1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nordic_npm6001
7 
8 #include <errno.h>
9 
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/sys/util.h>
12 
13 /* nPM6001 registers */
14 #define NPM6001_BUCK3SELDAC      0x44U
15 #define NPM6001_BUCKMODEPADCONF  0x4EU
16 #define NPM6001_PADDRIVESTRENGTH 0x53U
17 
18 /* nPM6001 BUCKMODEPADCONF fields */
19 #define NPM6001_BUCKMODEPADCONF_BUCKMODE0PADTYPE_CMOS  BIT(0)
20 #define NPM6001_BUCKMODEPADCONF_BUCKMODE1PADTYPE_CMOS  BIT(1)
21 #define NPM6001_BUCKMODEPADCONF_BUCKMODE2PADTYPE_CMOS  BIT(2)
22 #define NPM6001_BUCKMODEPADCONF_BUCKMODE0PULLD_ENABLED BIT(4)
23 #define NPM6001_BUCKMODEPADCONF_BUCKMODE1PULLD_ENABLED BIT(5)
24 #define NPM6001_BUCKMODEPADCONF_BUCKMODE2PULLD_ENABLED BIT(6)
25 
26 /* nPM6001 PADDRIVESTRENGTH fields */
27 #define NPM6001_PADDRIVESTRENGTH_READY_HIGH BIT(2)
28 #define NPM6001_PADDRIVESTRENGTH_NINT_HIGH  BIT(3)
29 #define NPM6001_PADDRIVESTRENGTH_SDA_HIGH   BIT(5)
30 
31 struct mfd_npm6001_config {
32 	struct i2c_dt_spec i2c;
33 	uint8_t buck_pad_val;
34 	uint8_t pad_val;
35 };
36 
mfd_npm6001_init(const struct device * dev)37 static int mfd_npm6001_init(const struct device *dev)
38 {
39 	const struct mfd_npm6001_config *config = dev->config;
40 	int ret;
41 
42 	if (!i2c_is_ready_dt(&config->i2c)) {
43 		return -ENODEV;
44 	}
45 
46 	/* always select BUCK3 DAC (does not increase power consumption) */
47 	ret = i2c_reg_write_byte_dt(&config->i2c, NPM6001_BUCK3SELDAC, 1U);
48 	if (ret < 0) {
49 		return ret;
50 	}
51 
52 	/* configure pad properties */
53 	ret = i2c_reg_write_byte_dt(&config->i2c, NPM6001_BUCKMODEPADCONF, config->buck_pad_val);
54 	if (ret < 0) {
55 		return ret;
56 	}
57 
58 	ret = i2c_reg_write_byte_dt(&config->i2c, NPM6001_PADDRIVESTRENGTH, config->pad_val);
59 	if (ret < 0) {
60 		return ret;
61 	}
62 
63 	return 0;
64 }
65 
66 #define MFD_NPM6001_DEFINE(inst)                                                                   \
67 	static const struct mfd_npm6001_config config##inst = {                                    \
68 		.i2c = I2C_DT_SPEC_INST_GET(inst),                                                 \
69 		.buck_pad_val = ((DT_INST_ENUM_IDX(inst, nordic_buck_mode0_input_type) *           \
70 				  NPM6001_BUCKMODEPADCONF_BUCKMODE0PADTYPE_CMOS) |                 \
71 				 (DT_INST_ENUM_IDX(inst, nordic_buck_mode1_input_type) *           \
72 				  NPM6001_BUCKMODEPADCONF_BUCKMODE1PADTYPE_CMOS) |                 \
73 				 (DT_INST_ENUM_IDX(inst, nordic_buck_mode2_input_type) *           \
74 				  NPM6001_BUCKMODEPADCONF_BUCKMODE2PADTYPE_CMOS) |                 \
75 				 (DT_INST_PROP(inst, nordic_buck_mode0_pull_down) *                \
76 				  NPM6001_BUCKMODEPADCONF_BUCKMODE0PULLD_ENABLED) |                \
77 				 (DT_INST_PROP(inst, nordic_buck_mode1_pull_down) *                \
78 				  NPM6001_BUCKMODEPADCONF_BUCKMODE1PULLD_ENABLED) |                \
79 				 (DT_INST_PROP(inst, nordic_buck_mode2_pull_down) *                \
80 				  NPM6001_BUCKMODEPADCONF_BUCKMODE2PULLD_ENABLED)),                \
81 		.pad_val = ((DT_INST_PROP(inst, nordic_ready_high_drive) *                         \
82 			     NPM6001_PADDRIVESTRENGTH_READY_HIGH) |                                \
83 			    (DT_INST_PROP(inst, nordic_nint_high_drive) *                          \
84 			     NPM6001_PADDRIVESTRENGTH_NINT_HIGH) |                                 \
85 			    (DT_INST_PROP(inst, nordic_sda_high_drive) *                           \
86 			     NPM6001_PADDRIVESTRENGTH_SDA_HIGH)),                                  \
87 	};                                                                                         \
88                                                                                                    \
89 	DEVICE_DT_INST_DEFINE(inst, mfd_npm6001_init, NULL, NULL, &config##inst, POST_KERNEL,      \
90 			      CONFIG_MFD_INIT_PRIORITY, NULL);
91 
92 DT_INST_FOREACH_STATUS_OKAY(MFD_NPM6001_DEFINE)
93