Commit | Line | Data |
---|---|---|
61d1eb02 SS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * mpq7932.c - hwmon with optional regulator driver for mps mpq7932 | |
4 | * Copyright 2022 Monolithic Power Systems, Inc | |
5 | * | |
6 | * Author: Saravanan Sekar <saravanan@linumiz.com> | |
7 | */ | |
8 | ||
9 | #include <linux/bits.h> | |
10 | #include <linux/err.h> | |
11 | #include <linux/i2c.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/kernel.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/of_device.h> | |
16 | #include <linux/pmbus.h> | |
17 | #include "pmbus.h" | |
18 | ||
19 | #define MPQ7932_BUCK_UV_MIN 206250 | |
20 | #define MPQ7932_UV_STEP 6250 | |
21 | #define MPQ7932_N_VOLTAGES 256 | |
22 | #define MPQ7932_VOUT_MAX 0xFF | |
23 | #define MPQ7932_NUM_PAGES 6 | |
24 | ||
25 | #define MPQ7932_TON_DELAY 0x60 | |
26 | #define MPQ7932_VOUT_STARTUP_SLEW 0xA3 | |
27 | #define MPQ7932_VOUT_SHUTDOWN_SLEW 0xA5 | |
28 | #define MPQ7932_VOUT_SLEW_MASK GENMASK(1, 0) | |
29 | #define MPQ7932_TON_DELAY_MASK GENMASK(4, 0) | |
30 | ||
31 | struct mpq7932_data { | |
32 | struct pmbus_driver_info info; | |
33 | struct pmbus_platform_data pdata; | |
34 | }; | |
35 | ||
36 | #if IS_ENABLED(CONFIG_SENSORS_MPQ7932_REGULATOR) | |
37 | static struct regulator_desc mpq7932_regulators_desc[] = { | |
38 | PMBUS_REGULATOR_STEP("buck", 0, MPQ7932_N_VOLTAGES, | |
39 | MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), | |
40 | PMBUS_REGULATOR_STEP("buck", 1, MPQ7932_N_VOLTAGES, | |
41 | MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), | |
42 | PMBUS_REGULATOR_STEP("buck", 2, MPQ7932_N_VOLTAGES, | |
43 | MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), | |
44 | PMBUS_REGULATOR_STEP("buck", 3, MPQ7932_N_VOLTAGES, | |
45 | MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), | |
46 | PMBUS_REGULATOR_STEP("buck", 4, MPQ7932_N_VOLTAGES, | |
47 | MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), | |
48 | PMBUS_REGULATOR_STEP("buck", 5, MPQ7932_N_VOLTAGES, | |
49 | MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), | |
50 | }; | |
51 | #endif | |
52 | ||
53 | static int mpq7932_write_word_data(struct i2c_client *client, int page, int reg, | |
54 | u16 word) | |
55 | { | |
56 | switch (reg) { | |
57 | /* | |
58 | * chip supports only byte access for VOUT_COMMAND otherwise | |
59 | * access results -EREMOTEIO | |
60 | */ | |
61 | case PMBUS_VOUT_COMMAND: | |
62 | return pmbus_write_byte_data(client, page, reg, word & 0xFF); | |
63 | ||
64 | default: | |
65 | return -ENODATA; | |
66 | } | |
67 | } | |
68 | ||
69 | static int mpq7932_read_word_data(struct i2c_client *client, int page, | |
70 | int phase, int reg) | |
71 | { | |
72 | switch (reg) { | |
73 | /* | |
74 | * chip supports neither (PMBUS_VOUT_MARGIN_HIGH, PMBUS_VOUT_MARGIN_LOW) | |
75 | * nor (PMBUS_MFR_VOUT_MIN, PMBUS_MFR_VOUT_MAX). As a result set voltage | |
76 | * fails due to error in pmbus_regulator_get_low_margin, so faked. | |
77 | */ | |
78 | case PMBUS_MFR_VOUT_MIN: | |
79 | return 0; | |
80 | ||
81 | case PMBUS_MFR_VOUT_MAX: | |
82 | return MPQ7932_VOUT_MAX; | |
83 | ||
84 | /* | |
85 | * chip supports only byte access for VOUT_COMMAND otherwise | |
86 | * access results in -EREMOTEIO | |
87 | */ | |
88 | case PMBUS_READ_VOUT: | |
89 | return pmbus_read_byte_data(client, page, PMBUS_VOUT_COMMAND); | |
90 | ||
91 | default: | |
92 | return -ENODATA; | |
93 | } | |
94 | } | |
95 | ||
96 | static int mpq7932_probe(struct i2c_client *client) | |
97 | { | |
98 | struct mpq7932_data *data; | |
99 | struct pmbus_driver_info *info; | |
100 | struct device *dev = &client->dev; | |
101 | int i; | |
102 | ||
103 | data = devm_kzalloc(dev, sizeof(struct mpq7932_data), GFP_KERNEL); | |
104 | if (!data) | |
105 | return -ENOMEM; | |
106 | ||
107 | info = &data->info; | |
108 | info->pages = MPQ7932_NUM_PAGES; | |
109 | info->format[PSC_VOLTAGE_OUT] = direct; | |
110 | info->m[PSC_VOLTAGE_OUT] = 160; | |
111 | info->b[PSC_VOLTAGE_OUT] = -33; | |
112 | for (i = 0; i < info->pages; i++) { | |
113 | info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | |
114 | | PMBUS_HAVE_STATUS_TEMP; | |
115 | } | |
116 | ||
117 | #if IS_ENABLED(CONFIG_SENSORS_MPQ7932_REGULATOR) | |
118 | info->num_regulators = ARRAY_SIZE(mpq7932_regulators_desc); | |
119 | info->reg_desc = mpq7932_regulators_desc; | |
120 | #endif | |
121 | ||
122 | info->read_word_data = mpq7932_read_word_data; | |
123 | info->write_word_data = mpq7932_write_word_data; | |
124 | ||
125 | data->pdata.flags = PMBUS_NO_CAPABILITY; | |
126 | dev->platform_data = &data->pdata; | |
127 | ||
128 | return pmbus_do_probe(client, info); | |
129 | } | |
130 | ||
131 | static const struct of_device_id mpq7932_of_match[] = { | |
132 | { .compatible = "mps,mpq7932"}, | |
133 | {}, | |
134 | }; | |
135 | MODULE_DEVICE_TABLE(of, mpq7932_of_match); | |
136 | ||
137 | static const struct i2c_device_id mpq7932_id[] = { | |
138 | { "mpq7932", }, | |
139 | { }, | |
140 | }; | |
141 | MODULE_DEVICE_TABLE(i2c, mpq7932_id); | |
142 | ||
143 | static struct i2c_driver mpq7932_regulator_driver = { | |
144 | .driver = { | |
145 | .name = "mpq7932", | |
146 | .of_match_table = mpq7932_of_match, | |
147 | }, | |
148 | .probe_new = mpq7932_probe, | |
149 | .id_table = mpq7932_id, | |
150 | }; | |
151 | module_i2c_driver(mpq7932_regulator_driver); | |
152 | ||
153 | MODULE_AUTHOR("Saravanan Sekar <saravanan@linumiz.com>"); | |
154 | MODULE_DESCRIPTION("MPQ7932 PMIC regulator driver"); | |
155 | MODULE_LICENSE("GPL"); | |
156 | MODULE_IMPORT_NS(PMBUS); |