Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge series "Add support for voltage regulator on ChromeOS EC." from Pi-Hsun Shih <pihsun@chromium.org>:

Add support for controlling voltage regulator that is connected and
controlled by ChromeOS EC. Kernel controls these regulators through
newly added EC host commands.

Changes from v5:
* Move new host command to a separate patch.
* Use devm_regulator_register.
* Address review comments.

Changes from v4:
* Change compatible name from regulator-cros-ec to cros-ec-regulator.

Changes from v3:
* Fix dt bindings file name.
* Remove check around CONFIG_OF in driver.
* Add new host commands to cros_ec_trace.
* Address review comments.

Changes from v2:
* Add 'depends on OF' to Kconfig.
* Add Kconfig description about compiling as module.

Changes from v1:
* Change compatible string to google,regulator-cros-ec.
* Use reg property in device tree.
* Change license for dt binding according to checkpatch.pl.
* Address comments on code styles.

Pi-Hsun Shih (3):
dt-bindings: regulator: Add DT binding for cros-ec-regulator
platform/chrome: cros_ec: Add command for regulator control.
regulator: Add driver for cros-ec-regulator

.../regulator/google,cros-ec-regulator.yaml | 51 ++++
drivers/platform/chrome/cros_ec_trace.c | 5 +
drivers/regulator/Kconfig | 10 +
drivers/regulator/Makefile | 1 +
drivers/regulator/cros-ec-regulator.c | 257 ++++++++++++++++++
.../linux/platform_data/cros_ec_commands.h | 82 ++++++
6 files changed, 406 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml
create mode 100644 drivers/regulator/cros-ec-regulator.c

base-commit: b791d1bdf9212d944d749a5c7ff6febdba241771
--
2.27.0.290.gba653c62da-goog

+406
+51
Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/regulator/google,cros-ec-regulator.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ChromeOS EC controlled voltage regulators 8 + 9 + maintainers: 10 + - Pi-Hsun Shih <pihsun@chromium.org> 11 + 12 + description: 13 + Any property defined as part of the core regulator binding, defined in 14 + regulator.yaml, can also be used. 15 + 16 + allOf: 17 + - $ref: "regulator.yaml#" 18 + 19 + properties: 20 + compatible: 21 + const: google,cros-ec-regulator 22 + 23 + reg: 24 + maxItems: 1 25 + description: Identifier for the voltage regulator to ChromeOS EC. 26 + 27 + required: 28 + - compatible 29 + - reg 30 + 31 + examples: 32 + - | 33 + spi0 { 34 + #address-cells = <1>; 35 + #size-cells = <0>; 36 + 37 + cros_ec: ec@0 { 38 + compatible = "google,cros-ec-spi"; 39 + reg = <0>; 40 + #address-cells = <1>; 41 + #size-cells = <0>; 42 + 43 + regulator@0 { 44 + compatible = "google,cros-ec-regulator"; 45 + regulator-min-microvolt = <1800000>; 46 + regulator-max-microvolt = <3300000>; 47 + reg = <0>; 48 + }; 49 + }; 50 + }; 51 + ...
+5
drivers/platform/chrome/cros_ec_trace.c
··· 161 161 TRACE_SYMBOL(EC_CMD_ADC_READ), \ 162 162 TRACE_SYMBOL(EC_CMD_ROLLBACK_INFO), \ 163 163 TRACE_SYMBOL(EC_CMD_AP_RESET), \ 164 + TRACE_SYMBOL(EC_CMD_REGULATOR_GET_INFO), \ 165 + TRACE_SYMBOL(EC_CMD_REGULATOR_ENABLE), \ 166 + TRACE_SYMBOL(EC_CMD_REGULATOR_IS_ENABLED), \ 167 + TRACE_SYMBOL(EC_CMD_REGULATOR_SET_VOLTAGE), \ 168 + TRACE_SYMBOL(EC_CMD_REGULATOR_GET_VOLTAGE), \ 164 169 TRACE_SYMBOL(EC_CMD_CR51_BASE), \ 165 170 TRACE_SYMBOL(EC_CMD_CR51_LAST), \ 166 171 TRACE_SYMBOL(EC_CMD_FP_PASSTHRU), \
+10
drivers/regulator/Kconfig
··· 238 238 Say y here for CPCAP regulator found on some Motorola phones 239 239 and tablets such as Droid 4. 240 240 241 + config REGULATOR_CROS_EC 242 + tristate "ChromeOS EC regulators" 243 + depends on CROS_EC && OF 244 + help 245 + This driver supports voltage regulators that is connected to ChromeOS 246 + EC and controlled through EC host commands. 247 + 248 + This driver can also be built as a module. If so, the module 249 + will be called cros-ec-regulator. 250 + 241 251 config REGULATOR_DA903X 242 252 tristate "Dialog Semiconductor DA9030/DA9034 regulators" 243 253 depends on PMIC_DA903X
+1
drivers/regulator/Makefile
··· 13 13 obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o 14 14 obj-$(CONFIG_REGULATOR_88PM800) += 88pm800-regulator.o 15 15 obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o 16 + obj-$(CONFIG_REGULATOR_CROS_EC) += cros-ec-regulator.o 16 17 obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o 17 18 obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o 18 19 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
+257
drivers/regulator/cros-ec-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright 2020 Google LLC. 4 + 5 + #include <linux/module.h> 6 + #include <linux/of.h> 7 + #include <linux/platform_data/cros_ec_proto.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/regulator/driver.h> 10 + #include <linux/regulator/machine.h> 11 + #include <linux/regulator/of_regulator.h> 12 + #include <linux/slab.h> 13 + 14 + struct cros_ec_regulator_data { 15 + struct regulator_desc desc; 16 + struct regulator_dev *dev; 17 + struct cros_ec_device *ec_dev; 18 + 19 + u32 index; 20 + 21 + u16 *voltages_mV; 22 + u16 num_voltages; 23 + }; 24 + 25 + static int cros_ec_cmd(struct cros_ec_device *ec, u32 version, u32 command, 26 + void *outdata, u32 outsize, void *indata, u32 insize) 27 + { 28 + struct cros_ec_command *msg; 29 + int ret; 30 + 31 + msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL); 32 + if (!msg) 33 + return -ENOMEM; 34 + 35 + msg->version = version; 36 + msg->command = command; 37 + msg->outsize = outsize; 38 + msg->insize = insize; 39 + 40 + if (outdata && outsize > 0) 41 + memcpy(msg->data, outdata, outsize); 42 + 43 + ret = cros_ec_cmd_xfer_status(ec, msg); 44 + if (ret < 0) 45 + goto cleanup; 46 + 47 + if (insize) 48 + memcpy(indata, msg->data, insize); 49 + 50 + cleanup: 51 + kfree(msg); 52 + return ret; 53 + } 54 + 55 + static int cros_ec_regulator_enable(struct regulator_dev *dev) 56 + { 57 + struct cros_ec_regulator_data *data = rdev_get_drvdata(dev); 58 + struct ec_params_regulator_enable cmd = { 59 + .index = data->index, 60 + .enable = 1, 61 + }; 62 + 63 + return cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_ENABLE, &cmd, 64 + sizeof(cmd), NULL, 0); 65 + } 66 + 67 + static int cros_ec_regulator_disable(struct regulator_dev *dev) 68 + { 69 + struct cros_ec_regulator_data *data = rdev_get_drvdata(dev); 70 + struct ec_params_regulator_enable cmd = { 71 + .index = data->index, 72 + .enable = 0, 73 + }; 74 + 75 + return cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_ENABLE, &cmd, 76 + sizeof(cmd), NULL, 0); 77 + } 78 + 79 + static int cros_ec_regulator_is_enabled(struct regulator_dev *dev) 80 + { 81 + struct cros_ec_regulator_data *data = rdev_get_drvdata(dev); 82 + struct ec_params_regulator_is_enabled cmd = { 83 + .index = data->index, 84 + }; 85 + struct ec_response_regulator_is_enabled resp; 86 + int ret; 87 + 88 + ret = cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_IS_ENABLED, &cmd, 89 + sizeof(cmd), &resp, sizeof(resp)); 90 + if (ret < 0) 91 + return ret; 92 + return resp.enabled; 93 + } 94 + 95 + static int cros_ec_regulator_list_voltage(struct regulator_dev *dev, 96 + unsigned int selector) 97 + { 98 + struct cros_ec_regulator_data *data = rdev_get_drvdata(dev); 99 + 100 + if (selector >= data->num_voltages) 101 + return -EINVAL; 102 + 103 + return data->voltages_mV[selector] * 1000; 104 + } 105 + 106 + static int cros_ec_regulator_get_voltage(struct regulator_dev *dev) 107 + { 108 + struct cros_ec_regulator_data *data = rdev_get_drvdata(dev); 109 + struct ec_params_regulator_get_voltage cmd = { 110 + .index = data->index, 111 + }; 112 + struct ec_response_regulator_get_voltage resp; 113 + int ret; 114 + 115 + ret = cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_GET_VOLTAGE, &cmd, 116 + sizeof(cmd), &resp, sizeof(resp)); 117 + if (ret < 0) 118 + return ret; 119 + return resp.voltage_mv * 1000; 120 + } 121 + 122 + static int cros_ec_regulator_set_voltage(struct regulator_dev *dev, int min_uV, 123 + int max_uV, unsigned int *selector) 124 + { 125 + struct cros_ec_regulator_data *data = rdev_get_drvdata(dev); 126 + int min_mV = DIV_ROUND_UP(min_uV, 1000); 127 + int max_mV = max_uV / 1000; 128 + struct ec_params_regulator_set_voltage cmd = { 129 + .index = data->index, 130 + .min_mv = min_mV, 131 + .max_mv = max_mV, 132 + }; 133 + 134 + /* 135 + * This can happen when the given range [min_uV, max_uV] doesn't 136 + * contain any voltage that can be represented exactly in mV. 137 + */ 138 + if (min_mV > max_mV) 139 + return -EINVAL; 140 + 141 + return cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_SET_VOLTAGE, &cmd, 142 + sizeof(cmd), NULL, 0); 143 + } 144 + 145 + static struct regulator_ops cros_ec_regulator_voltage_ops = { 146 + .enable = cros_ec_regulator_enable, 147 + .disable = cros_ec_regulator_disable, 148 + .is_enabled = cros_ec_regulator_is_enabled, 149 + .list_voltage = cros_ec_regulator_list_voltage, 150 + .get_voltage = cros_ec_regulator_get_voltage, 151 + .set_voltage = cros_ec_regulator_set_voltage, 152 + }; 153 + 154 + static int cros_ec_regulator_init_info(struct device *dev, 155 + struct cros_ec_regulator_data *data) 156 + { 157 + struct ec_params_regulator_get_info cmd = { 158 + .index = data->index, 159 + }; 160 + struct ec_response_regulator_get_info resp; 161 + int ret; 162 + 163 + ret = cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_GET_INFO, &cmd, 164 + sizeof(cmd), &resp, sizeof(resp)); 165 + if (ret < 0) 166 + return ret; 167 + 168 + data->num_voltages = 169 + min_t(u16, ARRAY_SIZE(resp.voltages_mv), resp.num_voltages); 170 + data->voltages_mV = 171 + devm_kmemdup(dev, resp.voltages_mv, 172 + sizeof(u16) * data->num_voltages, GFP_KERNEL); 173 + data->desc.n_voltages = data->num_voltages; 174 + 175 + /* Make sure the returned name is always a valid string */ 176 + resp.name[ARRAY_SIZE(resp.name) - 1] = '\0'; 177 + data->desc.name = devm_kstrdup(dev, resp.name, GFP_KERNEL); 178 + if (!data->desc.name) 179 + return -ENOMEM; 180 + 181 + return 0; 182 + } 183 + 184 + static int cros_ec_regulator_probe(struct platform_device *pdev) 185 + { 186 + struct device *dev = &pdev->dev; 187 + struct device_node *np = dev->of_node; 188 + struct cros_ec_regulator_data *drvdata; 189 + struct regulator_init_data *init_data; 190 + struct regulator_config cfg = {}; 191 + struct regulator_desc *desc; 192 + int ret; 193 + 194 + drvdata = devm_kzalloc( 195 + &pdev->dev, sizeof(struct cros_ec_regulator_data), GFP_KERNEL); 196 + if (!drvdata) 197 + return -ENOMEM; 198 + 199 + drvdata->ec_dev = dev_get_drvdata(dev->parent); 200 + desc = &drvdata->desc; 201 + 202 + init_data = of_get_regulator_init_data(dev, np, desc); 203 + if (!init_data) 204 + return -EINVAL; 205 + 206 + ret = of_property_read_u32(np, "reg", &drvdata->index); 207 + if (ret < 0) 208 + return ret; 209 + 210 + desc->owner = THIS_MODULE; 211 + desc->type = REGULATOR_VOLTAGE; 212 + desc->ops = &cros_ec_regulator_voltage_ops; 213 + 214 + ret = cros_ec_regulator_init_info(dev, drvdata); 215 + if (ret < 0) 216 + return ret; 217 + 218 + cfg.dev = &pdev->dev; 219 + cfg.init_data = init_data; 220 + cfg.driver_data = drvdata; 221 + cfg.of_node = np; 222 + 223 + drvdata->dev = devm_regulator_register(dev, &drvdata->desc, &cfg); 224 + if (IS_ERR(drvdata->dev)) { 225 + ret = PTR_ERR(drvdata->dev); 226 + dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); 227 + goto free_name; 228 + } 229 + 230 + platform_set_drvdata(pdev, drvdata); 231 + 232 + return 0; 233 + 234 + free_name: 235 + kfree(desc->name); 236 + return ret; 237 + } 238 + 239 + static const struct of_device_id regulator_cros_ec_of_match[] = { 240 + { .compatible = "google,cros-ec-regulator", }, 241 + {} 242 + }; 243 + MODULE_DEVICE_TABLE(of, regulator_cros_ec_of_match); 244 + 245 + static struct platform_driver cros_ec_regulator_driver = { 246 + .probe = cros_ec_regulator_probe, 247 + .driver = { 248 + .name = "cros-ec-regulator", 249 + .of_match_table = regulator_cros_ec_of_match, 250 + }, 251 + }; 252 + 253 + module_platform_driver(cros_ec_regulator_driver); 254 + 255 + MODULE_LICENSE("GPL v2"); 256 + MODULE_DESCRIPTION("ChromeOS EC controlled regulator"); 257 + MODULE_AUTHOR("Pi-Hsun Shih <pihsun@chromium.org>");
+82
include/linux/platform_data/cros_ec_commands.h
··· 5431 5431 #define EC_CMD_AP_RESET 0x0125 5432 5432 5433 5433 /*****************************************************************************/ 5434 + /* Voltage regulator controls */ 5435 + 5436 + /* 5437 + * Get basic info of voltage regulator for given index. 5438 + * 5439 + * Returns the regulator name and supported voltage list in mV. 5440 + */ 5441 + #define EC_CMD_REGULATOR_GET_INFO 0x012B 5442 + 5443 + /* Maximum length of regulator name */ 5444 + #define EC_REGULATOR_NAME_MAX_LEN 16 5445 + 5446 + /* Maximum length of the supported voltage list. */ 5447 + #define EC_REGULATOR_VOLTAGE_MAX_COUNT 16 5448 + 5449 + struct ec_params_regulator_get_info { 5450 + uint32_t index; 5451 + } __ec_align4; 5452 + 5453 + struct ec_response_regulator_get_info { 5454 + char name[EC_REGULATOR_NAME_MAX_LEN]; 5455 + uint16_t num_voltages; 5456 + uint16_t voltages_mv[EC_REGULATOR_VOLTAGE_MAX_COUNT]; 5457 + } __ec_align1; 5458 + 5459 + /* 5460 + * Configure the regulator as enabled / disabled. 5461 + */ 5462 + #define EC_CMD_REGULATOR_ENABLE 0x012C 5463 + 5464 + struct ec_params_regulator_enable { 5465 + uint32_t index; 5466 + uint8_t enable; 5467 + } __ec_align4; 5468 + 5469 + /* 5470 + * Query if the regulator is enabled. 5471 + * 5472 + * Returns 1 if the regulator is enabled, 0 if not. 5473 + */ 5474 + #define EC_CMD_REGULATOR_IS_ENABLED 0x012D 5475 + 5476 + struct ec_params_regulator_is_enabled { 5477 + uint32_t index; 5478 + } __ec_align4; 5479 + 5480 + struct ec_response_regulator_is_enabled { 5481 + uint8_t enabled; 5482 + } __ec_align1; 5483 + 5484 + /* 5485 + * Set voltage for the voltage regulator within the range specified. 5486 + * 5487 + * The driver should select the voltage in range closest to min_mv. 5488 + * 5489 + * Also note that this might be called before the regulator is enabled, and the 5490 + * setting should be in effect after the regulator is enabled. 5491 + */ 5492 + #define EC_CMD_REGULATOR_SET_VOLTAGE 0x012E 5493 + 5494 + struct ec_params_regulator_set_voltage { 5495 + uint32_t index; 5496 + uint32_t min_mv; 5497 + uint32_t max_mv; 5498 + } __ec_align4; 5499 + 5500 + /* 5501 + * Get the currently configured voltage for the voltage regulator. 5502 + * 5503 + * Note that this might be called before the regulator is enabled. 5504 + */ 5505 + #define EC_CMD_REGULATOR_GET_VOLTAGE 0x012F 5506 + 5507 + struct ec_params_regulator_get_voltage { 5508 + uint32_t index; 5509 + } __ec_align4; 5510 + 5511 + struct ec_response_regulator_get_voltage { 5512 + uint32_t voltage_mv; 5513 + } __ec_align4; 5514 + 5515 + /*****************************************************************************/ 5434 5516 /* The command range 0x200-0x2FF is reserved for Rotor. */ 5435 5517 5436 5518 /*****************************************************************************/