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

Merge branches 'ib-mfd-x86-usb-watchdog-5.8', 'ib-mfd-power-rtc-5.8', 'ib-mfd-iio-power-5.8' and 'ib-mfd-hwmon-5.8' into ibs-for-mfd-merged

+2963 -62
+8
Documentation/ABI/testing/sysfs-class-power-mp2629
··· 1 + What: /sys/class/power_supply/mp2629_battery/batt_impedance_compen 2 + Date: April 2020 3 + KernelVersion: 5.7 4 + Description: 5 + Represents a battery impedance compensation to accelerate charging. 6 + 7 + Access: Read, Write 8 + Valid values: Represented in milli-ohms. Valid range is [0, 140].
+196
Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/gateworks-gsc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Gateworks System Controller 8 + 9 + description: | 10 + The Gateworks System Controller (GSC) is a device present across various 11 + Gateworks product families that provides a set of system related features 12 + such as the following (refer to the board hardware user manuals to see what 13 + features are present) 14 + - Watchdog Timer 15 + - GPIO 16 + - Pushbutton controller 17 + - Hardware monitor with ADC's for temperature and voltage rails and 18 + fan controller 19 + 20 + maintainers: 21 + - Tim Harvey <tharvey@gateworks.com> 22 + - Robert Jones <rjones@gateworks.com> 23 + 24 + properties: 25 + $nodename: 26 + pattern: "gsc@[0-9a-f]{1,2}" 27 + compatible: 28 + const: gw,gsc 29 + 30 + reg: 31 + description: I2C device address 32 + maxItems: 1 33 + 34 + interrupts: 35 + maxItems: 1 36 + 37 + interrupt-controller: true 38 + 39 + "#interrupt-cells": 40 + const: 1 41 + 42 + "#address-cells": 43 + const: 1 44 + 45 + "#size-cells": 46 + const: 0 47 + 48 + adc: 49 + type: object 50 + description: Optional hardware monitoring module 51 + 52 + properties: 53 + compatible: 54 + const: gw,gsc-adc 55 + 56 + "#address-cells": 57 + const: 1 58 + 59 + "#size-cells": 60 + const: 0 61 + 62 + patternProperties: 63 + "^channel@[0-9]+$": 64 + type: object 65 + description: | 66 + Properties for a single ADC which can report cooked values 67 + (i.e. temperature sensor based on thermister), raw values 68 + (i.e. voltage rail with a pre-scaling resistor divider). 69 + 70 + properties: 71 + reg: 72 + description: Register of the ADC 73 + maxItems: 1 74 + 75 + label: 76 + description: Name of the ADC input 77 + 78 + gw,mode: 79 + description: | 80 + conversion mode: 81 + 0 - temperature, in C*10 82 + 1 - pre-scaled voltage value 83 + 2 - scaled voltage based on an optional resistor divider 84 + and optional offset 85 + $ref: /schemas/types.yaml#/definitions/uint32 86 + enum: [0, 1, 2] 87 + 88 + gw,voltage-divider-ohms: 89 + description: Values of resistors for divider on raw ADC input 90 + maxItems: 2 91 + items: 92 + minimum: 1000 93 + maximum: 1000000 94 + 95 + gw,voltage-offset-microvolt: 96 + description: | 97 + A positive voltage offset to apply to a raw ADC 98 + (i.e. to compensate for a diode drop). 99 + minimum: 0 100 + maximum: 1000000 101 + 102 + required: 103 + - gw,mode 104 + - reg 105 + - label 106 + 107 + required: 108 + - compatible 109 + - "#address-cells" 110 + - "#size-cells" 111 + 112 + patternProperties: 113 + "^fan-controller@[0-9a-f]+$": 114 + type: object 115 + description: Optional fan controller 116 + 117 + properties: 118 + compatible: 119 + const: gw,gsc-fan 120 + 121 + "#address-cells": 122 + const: 1 123 + 124 + "#size-cells": 125 + const: 0 126 + 127 + reg: 128 + description: The fan controller base address 129 + maxItems: 1 130 + 131 + required: 132 + - compatible 133 + - reg 134 + - "#address-cells" 135 + - "#size-cells" 136 + 137 + required: 138 + - compatible 139 + - reg 140 + - interrupts 141 + - interrupt-controller 142 + - "#interrupt-cells" 143 + - "#address-cells" 144 + - "#size-cells" 145 + 146 + examples: 147 + - | 148 + #include <dt-bindings/gpio/gpio.h> 149 + i2c { 150 + #address-cells = <1>; 151 + #size-cells = <0>; 152 + 153 + gsc@20 { 154 + compatible = "gw,gsc"; 155 + reg = <0x20>; 156 + interrupt-parent = <&gpio1>; 157 + interrupts = <4 GPIO_ACTIVE_LOW>; 158 + interrupt-controller; 159 + #interrupt-cells = <1>; 160 + #address-cells = <1>; 161 + #size-cells = <0>; 162 + 163 + adc { 164 + compatible = "gw,gsc-adc"; 165 + #address-cells = <1>; 166 + #size-cells = <0>; 167 + 168 + channel@0 { /* A0: Board Temperature */ 169 + reg = <0x00>; 170 + label = "temp"; 171 + gw,mode = <0>; 172 + }; 173 + 174 + channel@2 { /* A1: Input Voltage (raw ADC) */ 175 + reg = <0x02>; 176 + label = "vdd_vin"; 177 + gw,mode = <1>; 178 + gw,voltage-divider-ohms = <22100 1000>; 179 + gw,voltage-offset-microvolt = <800000>; 180 + }; 181 + 182 + channel@b { /* A2: Battery voltage */ 183 + reg = <0x0b>; 184 + label = "vdd_bat"; 185 + gw,mode = <1>; 186 + }; 187 + }; 188 + 189 + fan-controller@2c { 190 + #address-cells = <1>; 191 + #size-cells = <0>; 192 + compatible = "gw,gsc-fan"; 193 + reg = <0x2c>; 194 + }; 195 + }; 196 + };
+62
Documentation/devicetree/bindings/mfd/mps,mp2629.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/mps,mp2629.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MP2629 Battery Charger PMIC from Monolithic Power System. 8 + 9 + maintainers: 10 + - Saravanan Sekar <sravanhome@gmail.com> 11 + 12 + description: | 13 + MP2629 is a PMIC providing battery charging and power supply for smartphones, 14 + wireless camera and portable devices. Chip is controlled over I2C. 15 + 16 + The battery charge management device handles battery charger controller and 17 + ADC IIO device for battery, system voltage 18 + 19 + properties: 20 + compatible: 21 + const: mps,mp2629 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + interrupts: 27 + maxItems: 1 28 + 29 + interrupt-controller: true 30 + 31 + "#interrupt-cells": 32 + const: 2 33 + description: 34 + The first cell is the IRQ number, the second cell is the trigger type. 35 + 36 + required: 37 + - compatible 38 + - reg 39 + - interrupts 40 + - interrupt-controller 41 + - "#interrupt-cells" 42 + 43 + additionalProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/interrupt-controller/irq.h> 48 + #include <dt-bindings/input/linux-event-codes.h> 49 + i2c { 50 + #address-cells = <1>; 51 + #size-cells = <0>; 52 + 53 + pmic@4b { 54 + compatible = "mps,mp2629"; 55 + reg = <0x4b>; 56 + 57 + interrupt-controller; 58 + interrupt-parent = <&gpio2>; 59 + #interrupt-cells = <2>; 60 + interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; 61 + }; 62 + };
+10 -4
Documentation/devicetree/bindings/mfd/mt6397.txt
··· 18 18 This document describes the binding for MFD device and its sub module. 19 19 20 20 Required properties: 21 - compatible: "mediatek,mt6397" or "mediatek,mt6323" 21 + compatible: 22 + "mediatek,mt6323" for PMIC MT6323 23 + "mediatek,mt6358" for PMIC MT6358 24 + "mediatek,mt6397" for PMIC MT6397 22 25 23 26 Optional subnodes: 24 27 25 28 - rtc 26 29 Required properties: Should be one of follows 27 30 - compatible: "mediatek,mt6323-rtc" 31 + - compatible: "mediatek,mt6358-rtc" 28 32 - compatible: "mediatek,mt6397-rtc" 29 33 For details, see ../rtc/rtc-mt6397.txt 30 34 - regulators 31 35 Required properties: 32 - - compatible: "mediatek,mt6397-regulator" 33 - see ../regulator/mt6397-regulator.txt 34 36 - compatible: "mediatek,mt6323-regulator" 35 37 see ../regulator/mt6323-regulator.txt 38 + - compatible: "mediatek,mt6358-regulator" 39 + see ../regulator/mt6358-regulator.txt 40 + - compatible: "mediatek,mt6397-regulator" 41 + see ../regulator/mt6397-regulator.txt 36 42 - codec 37 43 Required properties: 38 - - compatible: "mediatek,mt6397-codec" 44 + - compatible: "mediatek,mt6397-codec" or "mediatek,mt6358-sound" 39 45 - clk 40 46 Required properties: 41 47 - compatible: "mediatek,mt6397-clk"
+53
Documentation/hwmon/gsc-hwmon.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Kernel driver gsc-hwmon 4 + ======================= 5 + 6 + Supported chips: Gateworks GSC 7 + Datasheet: http://trac.gateworks.com/wiki/gsc 8 + Author: Tim Harvey <tharvey@gateworks.com> 9 + 10 + Description: 11 + ------------ 12 + 13 + This driver supports hardware monitoring for the temperature sensor, 14 + various ADC's connected to the GSC, and optional FAN controller available 15 + on some boards. 16 + 17 + 18 + Voltage Monitoring 19 + ------------------ 20 + 21 + The voltage inputs are scaled either internally or by the driver depending 22 + on the GSC version and firmware. The values returned by the driver do not need 23 + further scaling. The voltage input labels provide the voltage rail name: 24 + 25 + inX_input Measured voltage (mV). 26 + inX_label Name of voltage rail. 27 + 28 + 29 + Temperature Monitoring 30 + ---------------------- 31 + 32 + Temperatures are measured with 12-bit or 10-bit resolution and are scaled 33 + either internally or by the driver depending on the GSC version and firmware. 34 + The values returned by the driver reflect millidegree Celcius: 35 + 36 + tempX_input Measured temperature. 37 + tempX_label Name of temperature input. 38 + 39 + 40 + PWM Output Control 41 + ------------------ 42 + 43 + The GSC features 1 PWM output that operates in automatic mode where the 44 + PWM value will be scalled depending on 6 temperature boundaries. 45 + The tempeature boundaries are read-write and in millidegree Celcius and the 46 + read-only PWM values range from 0 (off) to 255 (full speed). 47 + Fan speed will be set to minimum (off) when the temperature sensor reads 48 + less than pwm1_auto_point1_temp and maximum when the temperature sensor 49 + equals or exceeds pwm1_auto_point6_temp. 50 + 51 + pwm1_auto_point[1-6]_pwm PWM value. 52 + pwm1_auto_point[1-6]_temp Temperature boundary. 53 +
+1
Documentation/hwmon/index.rst
··· 60 60 ftsteutates 61 61 g760a 62 62 g762 63 + gsc-hwmon 63 64 gl518sm 64 65 hih6130 65 66 ibmaem
+16
MAINTAINERS
··· 7028 7028 F: tools/perf/bench/futex* 7029 7029 F: tools/testing/selftests/futex/ 7030 7030 7031 + GATEWORKS SYSTEM CONTROLLER (GSC) DRIVER 7032 + M: Tim Harvey <tharvey@gateworks.com> 7033 + M: Robert Jones <rjones@gateworks.com> 7034 + S: Maintained 7035 + F: Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml 7036 + F: drivers/mfd/gateworks-gsc.c 7037 + F: include/linux/mfd/gsc.h 7038 + F: Documentation/hwmon/gsc-hwmon.rst 7039 + F: drivers/hwmon/gsc-hwmon.c 7040 + F: include/linux/platform_data/gsc_hwmon.h 7041 + 7031 7042 GASKET DRIVER FRAMEWORK 7032 7043 M: Rob Springer <rspringer@google.com> 7033 7044 M: Todd Poynor <toddpoynor@google.com> ··· 11393 11382 MONOLITHIC POWER SYSTEM PMIC DRIVER 11394 11383 M: Saravanan Sekar <sravanhome@gmail.com> 11395 11384 S: Maintained 11385 + F: Documentation/devicetree/bindings/mfd/mps,mp2629.yaml 11396 11386 F: Documentation/devicetree/bindings/regulator/mps,mp*.yaml 11387 + F: drivers/iio/adc/mp2629_adc.c 11388 + F: drivers/mfd/mp2629.c 11389 + F: drivers/power/supply/mp2629_charger.c 11397 11390 F: drivers/regulator/mp5416.c 11398 11391 F: drivers/regulator/mpq7920.c 11399 11392 F: drivers/regulator/mpq7920.h 11393 + F: include/linux/mfd/mp2629.h 11400 11394 11401 11395 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER 11402 11396 S: Orphan
+9
drivers/hwmon/Kconfig
··· 523 523 This driver can also be built as a module. If so, the module 524 524 will be called f75375s. 525 525 526 + config SENSORS_GSC 527 + tristate "Gateworks System Controller ADC" 528 + depends on MFD_GATEWORKS_GSC 529 + help 530 + Support for the Gateworks System Controller A/D converters. 531 + 532 + To compile this driver as a module, choose M here: 533 + the module will be called gsc-hwmon. 534 + 526 535 config SENSORS_MC13783_ADC 527 536 tristate "Freescale MC13783/MC13892 ADC" 528 537 depends on MFD_MC13XXX
+1
drivers/hwmon/Makefile
··· 74 74 obj-$(CONFIG_SENSORS_G762) += g762.o 75 75 obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o 76 76 obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o 77 + obj-$(CONFIG_SENSORS_GSC) += gsc-hwmon.o 77 78 obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o 78 79 obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o 79 80 obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
+390
drivers/hwmon/gsc-hwmon.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Driver for Gateworks System Controller Hardware Monitor module 4 + * 5 + * Copyright (C) 2020 Gateworks Corporation 6 + */ 7 + #include <linux/hwmon.h> 8 + #include <linux/hwmon-sysfs.h> 9 + #include <linux/mfd/gsc.h> 10 + #include <linux/module.h> 11 + #include <linux/of.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/regmap.h> 14 + #include <linux/slab.h> 15 + 16 + #include <linux/platform_data/gsc_hwmon.h> 17 + 18 + #define GSC_HWMON_MAX_TEMP_CH 16 19 + #define GSC_HWMON_MAX_IN_CH 16 20 + 21 + #define GSC_HWMON_RESOLUTION 12 22 + #define GSC_HWMON_VREF 2500 23 + 24 + struct gsc_hwmon_data { 25 + struct gsc_dev *gsc; 26 + struct gsc_hwmon_platform_data *pdata; 27 + struct regmap *regmap; 28 + const struct gsc_hwmon_channel *temp_ch[GSC_HWMON_MAX_TEMP_CH]; 29 + const struct gsc_hwmon_channel *in_ch[GSC_HWMON_MAX_IN_CH]; 30 + u32 temp_config[GSC_HWMON_MAX_TEMP_CH + 1]; 31 + u32 in_config[GSC_HWMON_MAX_IN_CH + 1]; 32 + struct hwmon_channel_info temp_info; 33 + struct hwmon_channel_info in_info; 34 + const struct hwmon_channel_info *info[3]; 35 + struct hwmon_chip_info chip; 36 + }; 37 + 38 + static struct regmap_bus gsc_hwmon_regmap_bus = { 39 + .reg_read = gsc_read, 40 + .reg_write = gsc_write, 41 + }; 42 + 43 + static const struct regmap_config gsc_hwmon_regmap_config = { 44 + .reg_bits = 8, 45 + .val_bits = 8, 46 + .cache_type = REGCACHE_NONE, 47 + }; 48 + 49 + static ssize_t pwm_auto_point_temp_show(struct device *dev, 50 + struct device_attribute *devattr, 51 + char *buf) 52 + { 53 + struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev); 54 + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 55 + u8 reg = hwmon->pdata->fan_base + (2 * attr->index); 56 + u8 regs[2]; 57 + int ret; 58 + 59 + ret = regmap_bulk_read(hwmon->regmap, reg, regs, 2); 60 + if (ret) 61 + return ret; 62 + 63 + ret = regs[0] | regs[1] << 8; 64 + return sprintf(buf, "%d\n", ret * 10); 65 + } 66 + 67 + static ssize_t pwm_auto_point_temp_store(struct device *dev, 68 + struct device_attribute *devattr, 69 + const char *buf, size_t count) 70 + { 71 + struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev); 72 + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 73 + u8 reg = hwmon->pdata->fan_base + (2 * attr->index); 74 + u8 regs[2]; 75 + long temp; 76 + int err; 77 + 78 + if (kstrtol(buf, 10, &temp)) 79 + return -EINVAL; 80 + 81 + temp = clamp_val(temp, 0, 10000); 82 + temp = DIV_ROUND_CLOSEST(temp, 10); 83 + 84 + regs[0] = temp & 0xff; 85 + regs[1] = (temp >> 8) & 0xff; 86 + err = regmap_bulk_write(hwmon->regmap, reg, regs, 2); 87 + if (err) 88 + return err; 89 + 90 + return count; 91 + } 92 + 93 + static ssize_t pwm_auto_point_pwm_show(struct device *dev, 94 + struct device_attribute *devattr, 95 + char *buf) 96 + { 97 + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 98 + 99 + return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100); 100 + } 101 + 102 + static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0); 103 + static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, pwm_auto_point_temp, 0); 104 + 105 + static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point2_pwm, pwm_auto_point_pwm, 1); 106 + static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp, pwm_auto_point_temp, 1); 107 + 108 + static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point3_pwm, pwm_auto_point_pwm, 2); 109 + static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp, pwm_auto_point_temp, 2); 110 + 111 + static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point4_pwm, pwm_auto_point_pwm, 3); 112 + static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp, pwm_auto_point_temp, 3); 113 + 114 + static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point5_pwm, pwm_auto_point_pwm, 4); 115 + static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point5_temp, pwm_auto_point_temp, 4); 116 + 117 + static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point6_pwm, pwm_auto_point_pwm, 5); 118 + static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point6_temp, pwm_auto_point_temp, 5); 119 + 120 + static struct attribute *gsc_hwmon_attributes[] = { 121 + &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, 122 + &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, 123 + &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, 124 + &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, 125 + &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, 126 + &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, 127 + &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, 128 + &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, 129 + &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr, 130 + &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr, 131 + &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr, 132 + &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr, 133 + NULL 134 + }; 135 + 136 + static const struct attribute_group gsc_hwmon_group = { 137 + .attrs = gsc_hwmon_attributes, 138 + }; 139 + __ATTRIBUTE_GROUPS(gsc_hwmon); 140 + 141 + static int 142 + gsc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, 143 + int channel, long *val) 144 + { 145 + struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev); 146 + const struct gsc_hwmon_channel *ch; 147 + int sz, ret; 148 + long tmp; 149 + u8 buf[3]; 150 + 151 + switch (type) { 152 + case hwmon_in: 153 + ch = hwmon->in_ch[channel]; 154 + break; 155 + case hwmon_temp: 156 + ch = hwmon->temp_ch[channel]; 157 + break; 158 + default: 159 + return -EOPNOTSUPP; 160 + } 161 + 162 + sz = (ch->mode == mode_voltage) ? 3 : 2; 163 + ret = regmap_bulk_read(hwmon->regmap, ch->reg, buf, sz); 164 + if (ret) 165 + return ret; 166 + 167 + tmp = 0; 168 + while (sz-- > 0) 169 + tmp |= (buf[sz] << (8 * sz)); 170 + 171 + switch (ch->mode) { 172 + case mode_temperature: 173 + if (tmp > 0x8000) 174 + tmp -= 0xffff; 175 + break; 176 + case mode_voltage_raw: 177 + tmp = clamp_val(tmp, 0, BIT(GSC_HWMON_RESOLUTION)); 178 + /* scale based on ref voltage and ADC resolution */ 179 + tmp *= GSC_HWMON_VREF; 180 + tmp >>= GSC_HWMON_RESOLUTION; 181 + /* scale based on optional voltage divider */ 182 + if (ch->vdiv[0] && ch->vdiv[1]) { 183 + tmp *= (ch->vdiv[0] + ch->vdiv[1]); 184 + tmp /= ch->vdiv[1]; 185 + } 186 + /* adjust by uV offset */ 187 + tmp += ch->mvoffset; 188 + break; 189 + case mode_voltage: 190 + /* no adjustment needed */ 191 + break; 192 + } 193 + 194 + *val = tmp; 195 + 196 + return 0; 197 + } 198 + 199 + static int 200 + gsc_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, 201 + u32 attr, int channel, const char **buf) 202 + { 203 + struct gsc_hwmon_data *hwmon = dev_get_drvdata(dev); 204 + 205 + switch (type) { 206 + case hwmon_in: 207 + *buf = hwmon->in_ch[channel]->name; 208 + break; 209 + case hwmon_temp: 210 + *buf = hwmon->temp_ch[channel]->name; 211 + break; 212 + default: 213 + return -ENOTSUPP; 214 + } 215 + 216 + return 0; 217 + } 218 + 219 + static umode_t 220 + gsc_hwmon_is_visible(const void *_data, enum hwmon_sensor_types type, u32 attr, 221 + int ch) 222 + { 223 + return 0444; 224 + } 225 + 226 + static const struct hwmon_ops gsc_hwmon_ops = { 227 + .is_visible = gsc_hwmon_is_visible, 228 + .read = gsc_hwmon_read, 229 + .read_string = gsc_hwmon_read_string, 230 + }; 231 + 232 + static struct gsc_hwmon_platform_data * 233 + gsc_hwmon_get_devtree_pdata(struct device *dev) 234 + { 235 + struct gsc_hwmon_platform_data *pdata; 236 + struct gsc_hwmon_channel *ch; 237 + struct fwnode_handle *child; 238 + struct device_node *fan; 239 + int nchannels; 240 + 241 + nchannels = device_get_child_node_count(dev); 242 + if (nchannels == 0) 243 + return ERR_PTR(-ENODEV); 244 + 245 + pdata = devm_kzalloc(dev, 246 + sizeof(*pdata) + nchannels * sizeof(*ch), 247 + GFP_KERNEL); 248 + if (!pdata) 249 + return ERR_PTR(-ENOMEM); 250 + ch = (struct gsc_hwmon_channel *)(pdata + 1); 251 + pdata->channels = ch; 252 + pdata->nchannels = nchannels; 253 + 254 + /* fan controller base address */ 255 + fan = of_find_compatible_node(dev->parent->of_node, NULL, "gw,gsc-fan"); 256 + if (fan && of_property_read_u32(fan, "reg", &pdata->fan_base)) { 257 + dev_err(dev, "fan node without base\n"); 258 + return ERR_PTR(-EINVAL); 259 + } 260 + 261 + /* allocate structures for channels and count instances of each type */ 262 + device_for_each_child_node(dev, child) { 263 + if (fwnode_property_read_string(child, "label", &ch->name)) { 264 + dev_err(dev, "channel without label\n"); 265 + fwnode_handle_put(child); 266 + return ERR_PTR(-EINVAL); 267 + } 268 + if (fwnode_property_read_u32(child, "reg", &ch->reg)) { 269 + dev_err(dev, "channel without reg\n"); 270 + fwnode_handle_put(child); 271 + return ERR_PTR(-EINVAL); 272 + } 273 + if (fwnode_property_read_u32(child, "gw,mode", &ch->mode)) { 274 + dev_err(dev, "channel without mode\n"); 275 + fwnode_handle_put(child); 276 + return ERR_PTR(-EINVAL); 277 + } 278 + if (ch->mode > mode_max) { 279 + dev_err(dev, "invalid channel mode\n"); 280 + fwnode_handle_put(child); 281 + return ERR_PTR(-EINVAL); 282 + } 283 + 284 + if (!fwnode_property_read_u32(child, 285 + "gw,voltage-offset-microvolt", 286 + &ch->mvoffset)) 287 + ch->mvoffset /= 1000; 288 + fwnode_property_read_u32_array(child, 289 + "gw,voltage-divider-ohms", 290 + ch->vdiv, ARRAY_SIZE(ch->vdiv)); 291 + ch++; 292 + } 293 + 294 + return pdata; 295 + } 296 + 297 + static int gsc_hwmon_probe(struct platform_device *pdev) 298 + { 299 + struct gsc_dev *gsc = dev_get_drvdata(pdev->dev.parent); 300 + struct device *dev = &pdev->dev; 301 + struct device *hwmon_dev; 302 + struct gsc_hwmon_platform_data *pdata = dev_get_platdata(dev); 303 + struct gsc_hwmon_data *hwmon; 304 + const struct attribute_group **groups; 305 + int i, i_in, i_temp; 306 + 307 + if (!pdata) { 308 + pdata = gsc_hwmon_get_devtree_pdata(dev); 309 + if (IS_ERR(pdata)) 310 + return PTR_ERR(pdata); 311 + } 312 + 313 + hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL); 314 + if (!hwmon) 315 + return -ENOMEM; 316 + hwmon->gsc = gsc; 317 + hwmon->pdata = pdata; 318 + 319 + hwmon->regmap = devm_regmap_init(dev, &gsc_hwmon_regmap_bus, 320 + gsc->i2c_hwmon, 321 + &gsc_hwmon_regmap_config); 322 + if (IS_ERR(hwmon->regmap)) 323 + return PTR_ERR(hwmon->regmap); 324 + 325 + for (i = 0, i_in = 0, i_temp = 0; i < hwmon->pdata->nchannels; i++) { 326 + const struct gsc_hwmon_channel *ch = &pdata->channels[i]; 327 + 328 + switch (ch->mode) { 329 + case mode_temperature: 330 + if (i_temp == GSC_HWMON_MAX_TEMP_CH) { 331 + dev_err(gsc->dev, "too many temp channels\n"); 332 + return -EINVAL; 333 + } 334 + hwmon->temp_ch[i_temp] = ch; 335 + hwmon->temp_config[i_temp] = HWMON_T_INPUT | 336 + HWMON_T_LABEL; 337 + i_temp++; 338 + break; 339 + case mode_voltage: 340 + case mode_voltage_raw: 341 + if (i_in == GSC_HWMON_MAX_IN_CH) { 342 + dev_err(gsc->dev, "too many input channels\n"); 343 + return -EINVAL; 344 + } 345 + hwmon->in_ch[i_in] = ch; 346 + hwmon->in_config[i_in] = 347 + HWMON_I_INPUT | HWMON_I_LABEL; 348 + i_in++; 349 + break; 350 + default: 351 + dev_err(gsc->dev, "invalid mode: %d\n", ch->mode); 352 + return -EINVAL; 353 + } 354 + } 355 + 356 + /* setup config structures */ 357 + hwmon->chip.ops = &gsc_hwmon_ops; 358 + hwmon->chip.info = hwmon->info; 359 + hwmon->info[0] = &hwmon->temp_info; 360 + hwmon->info[1] = &hwmon->in_info; 361 + hwmon->temp_info.type = hwmon_temp; 362 + hwmon->temp_info.config = hwmon->temp_config; 363 + hwmon->in_info.type = hwmon_in; 364 + hwmon->in_info.config = hwmon->in_config; 365 + 366 + groups = pdata->fan_base ? gsc_hwmon_groups : NULL; 367 + hwmon_dev = devm_hwmon_device_register_with_info(dev, 368 + KBUILD_MODNAME, hwmon, 369 + &hwmon->chip, groups); 370 + return PTR_ERR_OR_ZERO(hwmon_dev); 371 + } 372 + 373 + static const struct of_device_id gsc_hwmon_of_match[] = { 374 + { .compatible = "gw,gsc-adc", }, 375 + {} 376 + }; 377 + 378 + static struct platform_driver gsc_hwmon_driver = { 379 + .driver = { 380 + .name = "gsc-hwmon", 381 + .of_match_table = gsc_hwmon_of_match, 382 + }, 383 + .probe = gsc_hwmon_probe, 384 + }; 385 + 386 + module_platform_driver(gsc_hwmon_driver); 387 + 388 + MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>"); 389 + MODULE_DESCRIPTION("GSC hardware monitor driver"); 390 + MODULE_LICENSE("GPL v2");
+10
drivers/iio/adc/Kconfig
··· 692 692 To compile this driver as a module, choose M here: the 693 693 module will be called meson_saradc. 694 694 695 + config MP2629_ADC 696 + tristate "Monolithic MP2629 ADC driver" 697 + depends on MFD_MP2629 698 + help 699 + Say yes to have support for battery charger IC MP2629 ADC device 700 + accessed over I2C. 701 + 702 + This driver provides ADC conversion of system, input power supply 703 + and battery voltage & current information. 704 + 695 705 config NAU7802 696 706 tristate "Nuvoton NAU7802 ADC driver" 697 707 depends on I2C
+1
drivers/iio/adc/Makefile
··· 65 65 obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o 66 66 obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o 67 67 obj-$(CONFIG_MESON_SARADC) += meson_saradc.o 68 + obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o 68 69 obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o 69 70 obj-$(CONFIG_NAU7802) += nau7802.o 70 71 obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
+208
drivers/iio/adc/mp2629_adc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * MP2629 Driver for ADC 4 + * 5 + * Copyright 2020 Monolithic Power Systems, Inc 6 + * 7 + * Author: Saravanan Sekar <sravanhome@gmail.com> 8 + */ 9 + 10 + #include <linux/iio/driver.h> 11 + #include <linux/iio/iio.h> 12 + #include <linux/iio/machine.h> 13 + #include <linux/mfd/mp2629.h> 14 + #include <linux/module.h> 15 + #include <linux/mutex.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/regmap.h> 18 + 19 + #define MP2629_REG_ADC_CTRL 0x03 20 + #define MP2629_REG_BATT_VOLT 0x0e 21 + #define MP2629_REG_SYSTEM_VOLT 0x0f 22 + #define MP2629_REG_INPUT_VOLT 0x11 23 + #define MP2629_REG_BATT_CURRENT 0x12 24 + #define MP2629_REG_INPUT_CURRENT 0x13 25 + 26 + #define MP2629_ADC_START BIT(7) 27 + #define MP2629_ADC_CONTINUOUS BIT(6) 28 + 29 + #define MP2629_MAP(_mp, _mpc) IIO_MAP(#_mp, "mp2629_charger", "mp2629-"_mpc) 30 + 31 + #define MP2629_ADC_CHAN(_ch, _type) { \ 32 + .type = _type, \ 33 + .indexed = 1, \ 34 + .datasheet_name = #_ch, \ 35 + .channel = MP2629_ ## _ch, \ 36 + .address = MP2629_REG_ ## _ch, \ 37 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 38 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 39 + } 40 + 41 + struct mp2629_adc { 42 + struct regmap *regmap; 43 + struct device *dev; 44 + }; 45 + 46 + static struct iio_chan_spec mp2629_channels[] = { 47 + MP2629_ADC_CHAN(BATT_VOLT, IIO_VOLTAGE), 48 + MP2629_ADC_CHAN(SYSTEM_VOLT, IIO_VOLTAGE), 49 + MP2629_ADC_CHAN(INPUT_VOLT, IIO_VOLTAGE), 50 + MP2629_ADC_CHAN(BATT_CURRENT, IIO_CURRENT), 51 + MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT) 52 + }; 53 + 54 + static struct iio_map mp2629_adc_maps[] = { 55 + MP2629_MAP(BATT_VOLT, "batt-volt"), 56 + MP2629_MAP(SYSTEM_VOLT, "system-volt"), 57 + MP2629_MAP(INPUT_VOLT, "input-volt"), 58 + MP2629_MAP(BATT_CURRENT, "batt-current"), 59 + MP2629_MAP(INPUT_CURRENT, "input-current") 60 + }; 61 + 62 + static int mp2629_read_raw(struct iio_dev *indio_dev, 63 + struct iio_chan_spec const *chan, 64 + int *val, int *val2, long mask) 65 + { 66 + struct mp2629_adc *info = iio_priv(indio_dev); 67 + unsigned int rval; 68 + int ret; 69 + 70 + switch (mask) { 71 + case IIO_CHAN_INFO_RAW: 72 + ret = regmap_read(info->regmap, chan->address, &rval); 73 + if (ret) 74 + return ret; 75 + 76 + if (chan->address == MP2629_INPUT_VOLT) 77 + rval &= GENMASK(6, 0); 78 + *val = rval; 79 + return IIO_VAL_INT; 80 + 81 + case IIO_CHAN_INFO_SCALE: 82 + switch (chan->channel) { 83 + case MP2629_BATT_VOLT: 84 + case MP2629_SYSTEM_VOLT: 85 + *val = 20; 86 + return IIO_VAL_INT; 87 + 88 + case MP2629_INPUT_VOLT: 89 + *val = 60; 90 + return IIO_VAL_INT; 91 + 92 + case MP2629_BATT_CURRENT: 93 + *val = 175; 94 + *val2 = 10; 95 + return IIO_VAL_FRACTIONAL; 96 + 97 + case MP2629_INPUT_CURRENT: 98 + *val = 133; 99 + *val2 = 10; 100 + return IIO_VAL_FRACTIONAL; 101 + 102 + default: 103 + return -EINVAL; 104 + } 105 + 106 + default: 107 + return -EINVAL; 108 + } 109 + } 110 + 111 + static const struct iio_info mp2629_adc_info = { 112 + .read_raw = &mp2629_read_raw, 113 + }; 114 + 115 + static int mp2629_adc_probe(struct platform_device *pdev) 116 + { 117 + struct device *dev = &pdev->dev; 118 + struct mp2629_data *ddata = dev_get_drvdata(dev->parent); 119 + struct mp2629_adc *info; 120 + struct iio_dev *indio_dev; 121 + int ret; 122 + 123 + indio_dev = devm_iio_device_alloc(dev, sizeof(*info)); 124 + if (!indio_dev) 125 + return -ENOMEM; 126 + 127 + info = iio_priv(indio_dev); 128 + info->regmap = ddata->regmap; 129 + info->dev = dev; 130 + platform_set_drvdata(pdev, indio_dev); 131 + 132 + ret = regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, 133 + MP2629_ADC_START | MP2629_ADC_CONTINUOUS, 134 + MP2629_ADC_START | MP2629_ADC_CONTINUOUS); 135 + if (ret) { 136 + dev_err(dev, "adc enable fail: %d\n", ret); 137 + return ret; 138 + } 139 + 140 + ret = iio_map_array_register(indio_dev, mp2629_adc_maps); 141 + if (ret) { 142 + dev_err(dev, "IIO maps register fail: %d\n", ret); 143 + goto fail_disable; 144 + } 145 + 146 + indio_dev->name = "mp2629-adc"; 147 + indio_dev->dev.parent = dev; 148 + indio_dev->channels = mp2629_channels; 149 + indio_dev->num_channels = ARRAY_SIZE(mp2629_channels); 150 + indio_dev->modes = INDIO_DIRECT_MODE; 151 + indio_dev->info = &mp2629_adc_info; 152 + 153 + ret = iio_device_register(indio_dev); 154 + if (ret) { 155 + dev_err(dev, "IIO device register fail: %d\n", ret); 156 + goto fail_map_unregister; 157 + } 158 + 159 + return 0; 160 + 161 + fail_map_unregister: 162 + iio_map_array_unregister(indio_dev); 163 + 164 + fail_disable: 165 + regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, 166 + MP2629_ADC_CONTINUOUS, 0); 167 + regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, 168 + MP2629_ADC_START, 0); 169 + 170 + return ret; 171 + } 172 + 173 + static int mp2629_adc_remove(struct platform_device *pdev) 174 + { 175 + struct iio_dev *indio_dev = platform_get_drvdata(pdev); 176 + struct mp2629_adc *info = iio_priv(indio_dev); 177 + 178 + iio_device_unregister(indio_dev); 179 + 180 + iio_map_array_unregister(indio_dev); 181 + 182 + regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, 183 + MP2629_ADC_CONTINUOUS, 0); 184 + regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL, 185 + MP2629_ADC_START, 0); 186 + 187 + return 0; 188 + } 189 + 190 + static const struct of_device_id mp2629_adc_of_match[] = { 191 + { .compatible = "mps,mp2629_adc"}, 192 + {} 193 + }; 194 + MODULE_DEVICE_TABLE(of, mp2629_adc_of_match); 195 + 196 + static struct platform_driver mp2629_adc_driver = { 197 + .driver = { 198 + .name = "mp2629_adc", 199 + .of_match_table = mp2629_adc_of_match, 200 + }, 201 + .probe = mp2629_adc_probe, 202 + .remove = mp2629_adc_remove, 203 + }; 204 + module_platform_driver(mp2629_adc_driver); 205 + 206 + MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>"); 207 + MODULE_DESCRIPTION("MP2629 ADC driver"); 208 + MODULE_LICENSE("GPL");
+24
drivers/mfd/Kconfig
··· 407 407 Select this option to enable support for Samsung Exynos Low Power 408 408 Audio Subsystem. 409 409 410 + config MFD_GATEWORKS_GSC 411 + tristate "Gateworks System Controller" 412 + depends on (I2C && OF) 413 + select MFD_CORE 414 + select REGMAP_I2C 415 + select REGMAP_IRQ 416 + help 417 + Enable support for the Gateworks System Controller (GSC) found 418 + on Gateworks Single Board Computers supporting system functions 419 + such as push-button monitor, multiple ADC's for voltage and 420 + temperature monitoring, fan controller and watchdog monitor. 421 + This driver provides common support for accessing the device. 422 + Additional drivers must be enabled in order to use the 423 + functionality of the device. 424 + 410 425 config MFD_MC13XXX 411 426 tristate 412 427 depends on (SPI_MASTER || I2C) ··· 448 433 select MFD_MC13XXX 449 434 help 450 435 Select this if your MC13xxx is connected via an I2C bus. 436 + 437 + config MFD_MP2629 438 + tristate "Monolithic Power Systems MP2629 ADC and Battery charger" 439 + depends on I2C 440 + select REGMAP_I2C 441 + help 442 + Select this option to enable support for Monolithic Power Systems 443 + battery charger. This provides ADC, thermal and battery charger power 444 + management functions. 451 445 452 446 config MFD_MXS_LRADC 453 447 tristate "Freescale i.MX23/i.MX28 LRADC"
+4 -1
drivers/mfd/Makefile
··· 15 15 obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o 16 16 obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o 17 17 obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o 18 + obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o 18 19 19 20 obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o 20 21 obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o ··· 171 170 obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o 172 171 obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o 173 172 173 + obj-$(CONFIG_MFD_MP2629) += mp2629.o 174 + 174 175 pcf50633-objs := pcf50633-core.o pcf50633-irq.o 175 176 obj-$(CONFIG_MFD_PCF50633) += pcf50633.o 176 177 obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o ··· 243 240 obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o 244 241 obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o 245 242 obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o 246 - mt6397-objs := mt6397-core.o mt6397-irq.o 243 + mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o 247 244 obj-$(CONFIG_MFD_MT6397) += mt6397.o 248 245 obj-$(CONFIG_INTEL_SOC_PMIC_MRFLD) += intel_soc_pmic_mrfld.o 249 246
+277
drivers/mfd/gateworks-gsc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * The Gateworks System Controller (GSC) is a multi-function 4 + * device designed for use in Gateworks Single Board Computers. 5 + * The control interface is I2C, with an interrupt. The device supports 6 + * system functions such as push-button monitoring, multiple ADC's for 7 + * voltage and temperature monitoring, fan controller and watchdog monitor. 8 + * 9 + * Copyright (C) 2020 Gateworks Corporation 10 + */ 11 + 12 + #include <linux/device.h> 13 + #include <linux/i2c.h> 14 + #include <linux/interrupt.h> 15 + #include <linux/mfd/gsc.h> 16 + #include <linux/module.h> 17 + #include <linux/mutex.h> 18 + #include <linux/of.h> 19 + #include <linux/of_platform.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/regmap.h> 22 + 23 + #include <asm/unaligned.h> 24 + 25 + /* 26 + * The GSC suffers from an errata where occasionally during 27 + * ADC cycles the chip can NAK I2C transactions. To ensure we have reliable 28 + * register access we place retries around register access. 29 + */ 30 + #define I2C_RETRIES 3 31 + 32 + int gsc_write(void *context, unsigned int reg, unsigned int val) 33 + { 34 + struct i2c_client *client = context; 35 + int retry, ret; 36 + 37 + for (retry = 0; retry < I2C_RETRIES; retry++) { 38 + ret = i2c_smbus_write_byte_data(client, reg, val); 39 + /* 40 + * -EAGAIN returned when the i2c host controller is busy 41 + * -EIO returned when i2c device is busy 42 + */ 43 + if (ret != -EAGAIN && ret != -EIO) 44 + break; 45 + } 46 + 47 + return 0; 48 + } 49 + EXPORT_SYMBOL_GPL(gsc_write); 50 + 51 + int gsc_read(void *context, unsigned int reg, unsigned int *val) 52 + { 53 + struct i2c_client *client = context; 54 + int retry, ret; 55 + 56 + for (retry = 0; retry < I2C_RETRIES; retry++) { 57 + ret = i2c_smbus_read_byte_data(client, reg); 58 + /* 59 + * -EAGAIN returned when the i2c host controller is busy 60 + * -EIO returned when i2c device is busy 61 + */ 62 + if (ret != -EAGAIN && ret != -EIO) 63 + break; 64 + } 65 + *val = ret & 0xff; 66 + 67 + return 0; 68 + } 69 + EXPORT_SYMBOL_GPL(gsc_read); 70 + 71 + /* 72 + * gsc_powerdown - API to use GSC to power down board for a specific time 73 + * 74 + * secs - number of seconds to remain powered off 75 + */ 76 + static int gsc_powerdown(struct gsc_dev *gsc, unsigned long secs) 77 + { 78 + int ret; 79 + unsigned char regs[4]; 80 + 81 + dev_info(&gsc->i2c->dev, "GSC powerdown for %ld seconds\n", 82 + secs); 83 + 84 + put_unaligned_le32(secs, regs); 85 + ret = regmap_bulk_write(gsc->regmap, GSC_TIME_ADD, regs, 4); 86 + if (ret) 87 + return ret; 88 + 89 + ret = regmap_update_bits(gsc->regmap, GSC_CTRL_1, 90 + BIT(GSC_CTRL_1_SLEEP_ADD), 91 + BIT(GSC_CTRL_1_SLEEP_ADD)); 92 + if (ret) 93 + return ret; 94 + 95 + ret = regmap_update_bits(gsc->regmap, GSC_CTRL_1, 96 + BIT(GSC_CTRL_1_SLEEP_ACTIVATE) | 97 + BIT(GSC_CTRL_1_SLEEP_ENABLE), 98 + BIT(GSC_CTRL_1_SLEEP_ACTIVATE) | 99 + BIT(GSC_CTRL_1_SLEEP_ENABLE)); 100 + 101 + 102 + return ret; 103 + } 104 + 105 + static ssize_t gsc_show(struct device *dev, struct device_attribute *attr, 106 + char *buf) 107 + { 108 + struct gsc_dev *gsc = dev_get_drvdata(dev); 109 + const char *name = attr->attr.name; 110 + int rz = 0; 111 + 112 + if (strcasecmp(name, "fw_version") == 0) 113 + rz = sprintf(buf, "%d\n", gsc->fwver); 114 + else if (strcasecmp(name, "fw_crc") == 0) 115 + rz = sprintf(buf, "0x%04x\n", gsc->fwcrc); 116 + else 117 + dev_err(dev, "invalid command: '%s'\n", name); 118 + 119 + return rz; 120 + } 121 + 122 + static ssize_t gsc_store(struct device *dev, struct device_attribute *attr, 123 + const char *buf, size_t count) 124 + { 125 + struct gsc_dev *gsc = dev_get_drvdata(dev); 126 + const char *name = attr->attr.name; 127 + long value; 128 + 129 + if (strcasecmp(name, "powerdown") == 0) { 130 + if (kstrtol(buf, 0, &value) == 0) 131 + gsc_powerdown(gsc, value); 132 + } else { 133 + dev_err(dev, "invalid command: '%s\n", name); 134 + } 135 + 136 + return count; 137 + } 138 + 139 + static struct device_attribute attr_fwver = 140 + __ATTR(fw_version, 0440, gsc_show, NULL); 141 + static struct device_attribute attr_fwcrc = 142 + __ATTR(fw_crc, 0440, gsc_show, NULL); 143 + static struct device_attribute attr_pwrdown = 144 + __ATTR(powerdown, 0220, NULL, gsc_store); 145 + 146 + static struct attribute *gsc_attrs[] = { 147 + &attr_fwver.attr, 148 + &attr_fwcrc.attr, 149 + &attr_pwrdown.attr, 150 + NULL, 151 + }; 152 + 153 + static struct attribute_group attr_group = { 154 + .attrs = gsc_attrs, 155 + }; 156 + 157 + static const struct of_device_id gsc_of_match[] = { 158 + { .compatible = "gw,gsc", }, 159 + { } 160 + }; 161 + MODULE_DEVICE_TABLE(of, gsc_of_match); 162 + 163 + static struct regmap_bus gsc_regmap_bus = { 164 + .reg_read = gsc_read, 165 + .reg_write = gsc_write, 166 + }; 167 + 168 + static const struct regmap_config gsc_regmap_config = { 169 + .reg_bits = 8, 170 + .val_bits = 8, 171 + .cache_type = REGCACHE_NONE, 172 + .max_register = GSC_WP, 173 + }; 174 + 175 + static const struct regmap_irq gsc_irqs[] = { 176 + REGMAP_IRQ_REG(GSC_IRQ_PB, 0, BIT(GSC_IRQ_PB)), 177 + REGMAP_IRQ_REG(GSC_IRQ_KEY_ERASED, 0, BIT(GSC_IRQ_KEY_ERASED)), 178 + REGMAP_IRQ_REG(GSC_IRQ_EEPROM_WP, 0, BIT(GSC_IRQ_EEPROM_WP)), 179 + REGMAP_IRQ_REG(GSC_IRQ_RESV, 0, BIT(GSC_IRQ_RESV)), 180 + REGMAP_IRQ_REG(GSC_IRQ_GPIO, 0, BIT(GSC_IRQ_GPIO)), 181 + REGMAP_IRQ_REG(GSC_IRQ_TAMPER, 0, BIT(GSC_IRQ_TAMPER)), 182 + REGMAP_IRQ_REG(GSC_IRQ_WDT_TIMEOUT, 0, BIT(GSC_IRQ_WDT_TIMEOUT)), 183 + REGMAP_IRQ_REG(GSC_IRQ_SWITCH_HOLD, 0, BIT(GSC_IRQ_SWITCH_HOLD)), 184 + }; 185 + 186 + static const struct regmap_irq_chip gsc_irq_chip = { 187 + .name = "gateworks-gsc", 188 + .irqs = gsc_irqs, 189 + .num_irqs = ARRAY_SIZE(gsc_irqs), 190 + .num_regs = 1, 191 + .status_base = GSC_IRQ_STATUS, 192 + .mask_base = GSC_IRQ_ENABLE, 193 + .mask_invert = true, 194 + .ack_base = GSC_IRQ_STATUS, 195 + .ack_invert = true, 196 + }; 197 + 198 + static int gsc_probe(struct i2c_client *client) 199 + { 200 + struct device *dev = &client->dev; 201 + struct gsc_dev *gsc; 202 + struct regmap_irq_chip_data *irq_data; 203 + int ret; 204 + unsigned int reg; 205 + 206 + gsc = devm_kzalloc(dev, sizeof(*gsc), GFP_KERNEL); 207 + if (!gsc) 208 + return -ENOMEM; 209 + 210 + gsc->dev = &client->dev; 211 + gsc->i2c = client; 212 + i2c_set_clientdata(client, gsc); 213 + 214 + gsc->regmap = devm_regmap_init(dev, &gsc_regmap_bus, client, 215 + &gsc_regmap_config); 216 + if (IS_ERR(gsc->regmap)) 217 + return PTR_ERR(gsc->regmap); 218 + 219 + if (regmap_read(gsc->regmap, GSC_FW_VER, &reg)) 220 + return -EIO; 221 + gsc->fwver = reg; 222 + 223 + regmap_read(gsc->regmap, GSC_FW_CRC, &reg); 224 + gsc->fwcrc = reg; 225 + regmap_read(gsc->regmap, GSC_FW_CRC + 1, &reg); 226 + gsc->fwcrc |= reg << 8; 227 + 228 + gsc->i2c_hwmon = devm_i2c_new_dummy_device(dev, client->adapter, 229 + GSC_HWMON); 230 + if (IS_ERR(gsc->i2c_hwmon)) { 231 + dev_err(dev, "Failed to allocate I2C device for HWMON\n"); 232 + return PTR_ERR(gsc->i2c_hwmon); 233 + } 234 + 235 + ret = devm_regmap_add_irq_chip(dev, gsc->regmap, client->irq, 236 + IRQF_ONESHOT | IRQF_SHARED | 237 + IRQF_TRIGGER_FALLING, 0, 238 + &gsc_irq_chip, &irq_data); 239 + if (ret) 240 + return ret; 241 + 242 + dev_info(dev, "Gateworks System Controller v%d: fw 0x%04x\n", 243 + gsc->fwver, gsc->fwcrc); 244 + 245 + ret = sysfs_create_group(&dev->kobj, &attr_group); 246 + if (ret) 247 + dev_err(dev, "failed to create sysfs attrs\n"); 248 + 249 + ret = devm_of_platform_populate(dev); 250 + if (ret) { 251 + sysfs_remove_group(&dev->kobj, &attr_group); 252 + return ret; 253 + } 254 + 255 + return 0; 256 + } 257 + 258 + static int gsc_remove(struct i2c_client *client) 259 + { 260 + sysfs_remove_group(&client->dev.kobj, &attr_group); 261 + 262 + return 0; 263 + } 264 + 265 + static struct i2c_driver gsc_driver = { 266 + .driver = { 267 + .name = "gateworks-gsc", 268 + .of_match_table = gsc_of_match, 269 + }, 270 + .probe_new = gsc_probe, 271 + .remove = gsc_remove, 272 + }; 273 + module_i2c_driver(gsc_driver); 274 + 275 + MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>"); 276 + MODULE_DESCRIPTION("I2C Core interface for GSC"); 277 + MODULE_LICENSE("GPL v2");
+79
drivers/mfd/mp2629.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * MP2629 parent driver for ADC and battery charger 4 + * 5 + * Copyright 2020 Monolithic Power Systems, Inc 6 + * 7 + * Author: Saravanan Sekar <sravanhome@gmail.com> 8 + */ 9 + 10 + #include <linux/i2c.h> 11 + #include <linux/kernel.h> 12 + #include <linux/mfd/core.h> 13 + #include <linux/mfd/mp2629.h> 14 + #include <linux/module.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/regmap.h> 17 + #include <linux/slab.h> 18 + 19 + static const struct mfd_cell mp2629_cell[] = { 20 + { 21 + .name = "mp2629_adc", 22 + .of_compatible = "mps,mp2629_adc", 23 + }, 24 + { 25 + .name = "mp2629_charger", 26 + .of_compatible = "mps,mp2629_charger", 27 + } 28 + }; 29 + 30 + static const struct regmap_config mp2629_regmap_config = { 31 + .reg_bits = 8, 32 + .val_bits = 8, 33 + .max_register = 0x17, 34 + }; 35 + 36 + static int mp2629_probe(struct i2c_client *client) 37 + { 38 + struct mp2629_data *ddata; 39 + int ret; 40 + 41 + ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL); 42 + if (!ddata) 43 + return -ENOMEM; 44 + 45 + ddata->dev = &client->dev; 46 + i2c_set_clientdata(client, ddata); 47 + 48 + ddata->regmap = devm_regmap_init_i2c(client, &mp2629_regmap_config); 49 + if (IS_ERR(ddata->regmap)) { 50 + dev_err(ddata->dev, "Failed to allocate regmap\n"); 51 + return PTR_ERR(ddata->regmap); 52 + } 53 + 54 + ret = devm_mfd_add_devices(ddata->dev, PLATFORM_DEVID_AUTO, mp2629_cell, 55 + ARRAY_SIZE(mp2629_cell), NULL, 0, NULL); 56 + if (ret) 57 + dev_err(ddata->dev, "Failed to register sub-devices %d\n", ret); 58 + 59 + return ret; 60 + } 61 + 62 + static const struct of_device_id mp2629_of_match[] = { 63 + { .compatible = "mps,mp2629"}, 64 + { } 65 + }; 66 + MODULE_DEVICE_TABLE(of, mp2629_of_match); 67 + 68 + static struct i2c_driver mp2629_driver = { 69 + .driver = { 70 + .name = "mp2629", 71 + .of_match_table = mp2629_of_match, 72 + }, 73 + .probe_new = mp2629_probe, 74 + }; 75 + module_i2c_driver(mp2629_driver); 76 + 77 + MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>"); 78 + MODULE_DESCRIPTION("MP2629 Battery charger parent driver"); 79 + MODULE_LICENSE("GPL");
+235
drivers/mfd/mt6358-irq.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Copyright (c) 2020 MediaTek Inc. 4 + 5 + #include <linux/interrupt.h> 6 + #include <linux/mfd/mt6358/core.h> 7 + #include <linux/mfd/mt6358/registers.h> 8 + #include <linux/mfd/mt6397/core.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/of_device.h> 12 + #include <linux/of_irq.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/regmap.h> 15 + 16 + static struct irq_top_t mt6358_ints[] = { 17 + MT6358_TOP_GEN(BUCK), 18 + MT6358_TOP_GEN(LDO), 19 + MT6358_TOP_GEN(PSC), 20 + MT6358_TOP_GEN(SCK), 21 + MT6358_TOP_GEN(BM), 22 + MT6358_TOP_GEN(HK), 23 + MT6358_TOP_GEN(AUD), 24 + MT6358_TOP_GEN(MISC), 25 + }; 26 + 27 + static void pmic_irq_enable(struct irq_data *data) 28 + { 29 + unsigned int hwirq = irqd_to_hwirq(data); 30 + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); 31 + struct pmic_irq_data *irqd = chip->irq_data; 32 + 33 + irqd->enable_hwirq[hwirq] = true; 34 + } 35 + 36 + static void pmic_irq_disable(struct irq_data *data) 37 + { 38 + unsigned int hwirq = irqd_to_hwirq(data); 39 + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); 40 + struct pmic_irq_data *irqd = chip->irq_data; 41 + 42 + irqd->enable_hwirq[hwirq] = false; 43 + } 44 + 45 + static void pmic_irq_lock(struct irq_data *data) 46 + { 47 + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); 48 + 49 + mutex_lock(&chip->irqlock); 50 + } 51 + 52 + static void pmic_irq_sync_unlock(struct irq_data *data) 53 + { 54 + unsigned int i, top_gp, gp_offset, en_reg, int_regs, shift; 55 + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); 56 + struct pmic_irq_data *irqd = chip->irq_data; 57 + 58 + for (i = 0; i < irqd->num_pmic_irqs; i++) { 59 + if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i]) 60 + continue; 61 + 62 + /* Find out the IRQ group */ 63 + top_gp = 0; 64 + while ((top_gp + 1) < irqd->num_top && 65 + i >= mt6358_ints[top_gp + 1].hwirq_base) 66 + top_gp++; 67 + 68 + /* Find the IRQ registers */ 69 + gp_offset = i - mt6358_ints[top_gp].hwirq_base; 70 + int_regs = gp_offset / MT6358_REG_WIDTH; 71 + shift = gp_offset % MT6358_REG_WIDTH; 72 + en_reg = mt6358_ints[top_gp].en_reg + 73 + (mt6358_ints[top_gp].en_reg_shift * int_regs); 74 + 75 + regmap_update_bits(chip->regmap, en_reg, BIT(shift), 76 + irqd->enable_hwirq[i] << shift); 77 + 78 + irqd->cache_hwirq[i] = irqd->enable_hwirq[i]; 79 + } 80 + mutex_unlock(&chip->irqlock); 81 + } 82 + 83 + static struct irq_chip mt6358_irq_chip = { 84 + .name = "mt6358-irq", 85 + .flags = IRQCHIP_SKIP_SET_WAKE, 86 + .irq_enable = pmic_irq_enable, 87 + .irq_disable = pmic_irq_disable, 88 + .irq_bus_lock = pmic_irq_lock, 89 + .irq_bus_sync_unlock = pmic_irq_sync_unlock, 90 + }; 91 + 92 + static void mt6358_irq_sp_handler(struct mt6397_chip *chip, 93 + unsigned int top_gp) 94 + { 95 + unsigned int irq_status, sta_reg, status; 96 + unsigned int hwirq, virq; 97 + int i, j, ret; 98 + 99 + for (i = 0; i < mt6358_ints[top_gp].num_int_regs; i++) { 100 + sta_reg = mt6358_ints[top_gp].sta_reg + 101 + mt6358_ints[top_gp].sta_reg_shift * i; 102 + 103 + ret = regmap_read(chip->regmap, sta_reg, &irq_status); 104 + if (ret) { 105 + dev_err(chip->dev, 106 + "Failed to read IRQ status, ret=%d\n", ret); 107 + return; 108 + } 109 + 110 + if (!irq_status) 111 + continue; 112 + 113 + status = irq_status; 114 + do { 115 + j = __ffs(status); 116 + 117 + hwirq = mt6358_ints[top_gp].hwirq_base + 118 + MT6358_REG_WIDTH * i + j; 119 + 120 + virq = irq_find_mapping(chip->irq_domain, hwirq); 121 + if (virq) 122 + handle_nested_irq(virq); 123 + 124 + status &= ~BIT(j); 125 + } while (status); 126 + 127 + regmap_write(chip->regmap, sta_reg, irq_status); 128 + } 129 + } 130 + 131 + static irqreturn_t mt6358_irq_handler(int irq, void *data) 132 + { 133 + struct mt6397_chip *chip = data; 134 + struct pmic_irq_data *mt6358_irq_data = chip->irq_data; 135 + unsigned int bit, i, top_irq_status = 0; 136 + int ret; 137 + 138 + ret = regmap_read(chip->regmap, 139 + mt6358_irq_data->top_int_status_reg, 140 + &top_irq_status); 141 + if (ret) { 142 + dev_err(chip->dev, 143 + "Failed to read status from the device, ret=%d\n", ret); 144 + return IRQ_NONE; 145 + } 146 + 147 + for (i = 0; i < mt6358_irq_data->num_top; i++) { 148 + bit = BIT(mt6358_ints[i].top_offset); 149 + if (top_irq_status & bit) { 150 + mt6358_irq_sp_handler(chip, i); 151 + top_irq_status &= ~bit; 152 + if (!top_irq_status) 153 + break; 154 + } 155 + } 156 + 157 + return IRQ_HANDLED; 158 + } 159 + 160 + static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq, 161 + irq_hw_number_t hw) 162 + { 163 + struct mt6397_chip *mt6397 = d->host_data; 164 + 165 + irq_set_chip_data(irq, mt6397); 166 + irq_set_chip_and_handler(irq, &mt6358_irq_chip, handle_level_irq); 167 + irq_set_nested_thread(irq, 1); 168 + irq_set_noprobe(irq); 169 + 170 + return 0; 171 + } 172 + 173 + static const struct irq_domain_ops mt6358_irq_domain_ops = { 174 + .map = pmic_irq_domain_map, 175 + .xlate = irq_domain_xlate_twocell, 176 + }; 177 + 178 + int mt6358_irq_init(struct mt6397_chip *chip) 179 + { 180 + int i, j, ret; 181 + struct pmic_irq_data *irqd; 182 + 183 + irqd = devm_kzalloc(chip->dev, sizeof(*irqd), GFP_KERNEL); 184 + if (!irqd) 185 + return -ENOMEM; 186 + 187 + chip->irq_data = irqd; 188 + 189 + mutex_init(&chip->irqlock); 190 + irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0; 191 + irqd->num_pmic_irqs = MT6358_IRQ_NR; 192 + irqd->num_top = ARRAY_SIZE(mt6358_ints); 193 + 194 + irqd->enable_hwirq = devm_kcalloc(chip->dev, 195 + irqd->num_pmic_irqs, 196 + sizeof(*irqd->enable_hwirq), 197 + GFP_KERNEL); 198 + if (!irqd->enable_hwirq) 199 + return -ENOMEM; 200 + 201 + irqd->cache_hwirq = devm_kcalloc(chip->dev, 202 + irqd->num_pmic_irqs, 203 + sizeof(*irqd->cache_hwirq), 204 + GFP_KERNEL); 205 + if (!irqd->cache_hwirq) 206 + return -ENOMEM; 207 + 208 + /* Disable all interrupts for initializing */ 209 + for (i = 0; i < irqd->num_top; i++) { 210 + for (j = 0; j < mt6358_ints[i].num_int_regs; j++) 211 + regmap_write(chip->regmap, 212 + mt6358_ints[i].en_reg + 213 + mt6358_ints[i].en_reg_shift * j, 0); 214 + } 215 + 216 + chip->irq_domain = irq_domain_add_linear(chip->dev->of_node, 217 + irqd->num_pmic_irqs, 218 + &mt6358_irq_domain_ops, chip); 219 + if (!chip->irq_domain) { 220 + dev_err(chip->dev, "Could not create IRQ domain\n"); 221 + return -ENODEV; 222 + } 223 + 224 + ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL, 225 + mt6358_irq_handler, IRQF_ONESHOT, 226 + mt6358_irq_chip.name, chip); 227 + if (ret) { 228 + dev_err(chip->dev, "Failed to register IRQ=%d, ret=%d\n", 229 + chip->irq, ret); 230 + return ret; 231 + } 232 + 233 + enable_irq_wake(chip->irq); 234 + return ret; 235 + }
+50 -51
drivers/mfd/mt6397-core.c
··· 12 12 #include <linux/regmap.h> 13 13 #include <linux/mfd/core.h> 14 14 #include <linux/mfd/mt6323/core.h> 15 + #include <linux/mfd/mt6358/core.h> 15 16 #include <linux/mfd/mt6397/core.h> 16 17 #include <linux/mfd/mt6323/registers.h> 18 + #include <linux/mfd/mt6358/registers.h> 17 19 #include <linux/mfd/mt6397/registers.h> 18 20 19 21 #define MT6323_RTC_BASE 0x8000 20 22 #define MT6323_RTC_SIZE 0x40 23 + 24 + #define MT6358_RTC_BASE 0x0588 25 + #define MT6358_RTC_SIZE 0x3c 21 26 22 27 #define MT6397_RTC_BASE 0xe000 23 28 #define MT6397_RTC_SIZE 0x3e ··· 33 28 static const struct resource mt6323_rtc_resources[] = { 34 29 DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE), 35 30 DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC), 31 + }; 32 + 33 + static const struct resource mt6358_rtc_resources[] = { 34 + DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE), 35 + DEFINE_RES_IRQ(MT6358_IRQ_RTC), 36 36 }; 37 37 38 38 static const struct resource mt6397_rtc_resources[] = { ··· 84 74 }, 85 75 }; 86 76 77 + static const struct mfd_cell mt6358_devs[] = { 78 + { 79 + .name = "mt6358-regulator", 80 + .of_compatible = "mediatek,mt6358-regulator" 81 + }, { 82 + .name = "mt6358-rtc", 83 + .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 84 + .resources = mt6358_rtc_resources, 85 + .of_compatible = "mediatek,mt6358-rtc", 86 + }, { 87 + .name = "mt6358-sound", 88 + .of_compatible = "mediatek,mt6358-sound" 89 + }, 90 + }; 91 + 87 92 static const struct mfd_cell mt6397_devs[] = { 88 93 { 89 94 .name = "mt6397-rtc", ··· 125 100 } 126 101 }; 127 102 128 - #ifdef CONFIG_PM_SLEEP 129 - static int mt6397_irq_suspend(struct device *dev) 130 - { 131 - struct mt6397_chip *chip = dev_get_drvdata(dev); 132 - 133 - regmap_write(chip->regmap, chip->int_con[0], chip->wake_mask[0]); 134 - regmap_write(chip->regmap, chip->int_con[1], chip->wake_mask[1]); 135 - 136 - enable_irq_wake(chip->irq); 137 - 138 - return 0; 139 - } 140 - 141 - static int mt6397_irq_resume(struct device *dev) 142 - { 143 - struct mt6397_chip *chip = dev_get_drvdata(dev); 144 - 145 - regmap_write(chip->regmap, chip->int_con[0], chip->irq_masks_cur[0]); 146 - regmap_write(chip->regmap, chip->int_con[1], chip->irq_masks_cur[1]); 147 - 148 - disable_irq_wake(chip->irq); 149 - 150 - return 0; 151 - } 152 - #endif 153 - 154 - static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend, 155 - mt6397_irq_resume); 156 - 157 103 struct chip_data { 158 104 u32 cid_addr; 159 105 u32 cid_shift; 106 + const struct mfd_cell *cells; 107 + int cell_size; 108 + int (*irq_init)(struct mt6397_chip *chip); 160 109 }; 161 110 162 111 static const struct chip_data mt6323_core = { 163 112 .cid_addr = MT6323_CID, 164 113 .cid_shift = 0, 114 + .cells = mt6323_devs, 115 + .cell_size = ARRAY_SIZE(mt6323_devs), 116 + .irq_init = mt6397_irq_init, 117 + }; 118 + 119 + static const struct chip_data mt6358_core = { 120 + .cid_addr = MT6358_SWCID, 121 + .cid_shift = 8, 122 + .cells = mt6358_devs, 123 + .cell_size = ARRAY_SIZE(mt6358_devs), 124 + .irq_init = mt6358_irq_init, 165 125 }; 166 126 167 127 static const struct chip_data mt6397_core = { 168 128 .cid_addr = MT6397_CID, 169 129 .cid_shift = 0, 130 + .cells = mt6397_devs, 131 + .cell_size = ARRAY_SIZE(mt6397_devs), 132 + .irq_init = mt6397_irq_init, 170 133 }; 171 134 172 135 static int mt6397_probe(struct platform_device *pdev) 173 136 { 174 137 int ret; 175 - unsigned int id; 138 + unsigned int id = 0; 176 139 struct mt6397_chip *pmic; 177 140 const struct chip_data *pmic_core; 178 141 ··· 196 183 if (pmic->irq <= 0) 197 184 return pmic->irq; 198 185 199 - ret = mt6397_irq_init(pmic); 186 + ret = pmic_core->irq_init(pmic); 200 187 if (ret) 201 188 return ret; 202 189 203 - switch (pmic->chip_id) { 204 - case MT6323_CHIP_ID: 205 - ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 206 - mt6323_devs, ARRAY_SIZE(mt6323_devs), 207 - NULL, 0, pmic->irq_domain); 208 - break; 209 - 210 - case MT6391_CHIP_ID: 211 - case MT6397_CHIP_ID: 212 - ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 213 - mt6397_devs, ARRAY_SIZE(mt6397_devs), 214 - NULL, 0, pmic->irq_domain); 215 - break; 216 - 217 - default: 218 - dev_err(&pdev->dev, "unsupported chip: %d\n", pmic->chip_id); 219 - return -ENODEV; 220 - } 221 - 190 + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 191 + pmic_core->cells, pmic_core->cell_size, 192 + NULL, 0, pmic->irq_domain); 222 193 if (ret) { 223 194 irq_domain_remove(pmic->irq_domain); 224 195 dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); ··· 215 218 { 216 219 .compatible = "mediatek,mt6323", 217 220 .data = &mt6323_core, 221 + }, { 222 + .compatible = "mediatek,mt6358", 223 + .data = &mt6358_core, 218 224 }, { 219 225 .compatible = "mediatek,mt6397", 220 226 .data = &mt6397_core, ··· 238 238 .driver = { 239 239 .name = "mt6397", 240 240 .of_match_table = of_match_ptr(mt6397_of_match), 241 - .pm = &mt6397_pm_ops, 242 241 }, 243 242 .id_table = mt6397_id, 244 243 };
+34 -1
drivers/mfd/mt6397-irq.c
··· 9 9 #include <linux/of_irq.h> 10 10 #include <linux/platform_device.h> 11 11 #include <linux/regmap.h> 12 + #include <linux/suspend.h> 12 13 #include <linux/mfd/mt6323/core.h> 13 14 #include <linux/mfd/mt6323/registers.h> 14 15 #include <linux/mfd/mt6397/core.h> ··· 82 81 static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg, 83 82 int irqbase) 84 83 { 85 - unsigned int status; 84 + unsigned int status = 0; 86 85 int i, irq, ret; 87 86 88 87 ret = regmap_read(mt6397->regmap, reg, &status); ··· 129 128 .map = mt6397_irq_domain_map, 130 129 }; 131 130 131 + static int mt6397_irq_pm_notifier(struct notifier_block *notifier, 132 + unsigned long pm_event, void *unused) 133 + { 134 + struct mt6397_chip *chip = 135 + container_of(notifier, struct mt6397_chip, pm_nb); 136 + 137 + switch (pm_event) { 138 + case PM_SUSPEND_PREPARE: 139 + regmap_write(chip->regmap, 140 + chip->int_con[0], chip->wake_mask[0]); 141 + regmap_write(chip->regmap, 142 + chip->int_con[1], chip->wake_mask[1]); 143 + enable_irq_wake(chip->irq); 144 + break; 145 + 146 + case PM_POST_SUSPEND: 147 + regmap_write(chip->regmap, 148 + chip->int_con[0], chip->irq_masks_cur[0]); 149 + regmap_write(chip->regmap, 150 + chip->int_con[1], chip->irq_masks_cur[1]); 151 + disable_irq_wake(chip->irq); 152 + break; 153 + 154 + default: 155 + break; 156 + } 157 + 158 + return NOTIFY_DONE; 159 + } 160 + 132 161 int mt6397_irq_init(struct mt6397_chip *chip) 133 162 { 134 163 int ret; ··· 190 159 regmap_write(chip->regmap, chip->int_con[0], 0x0); 191 160 regmap_write(chip->regmap, chip->int_con[1], 0x0); 192 161 162 + chip->pm_nb.notifier_call = mt6397_irq_pm_notifier; 193 163 chip->irq_domain = irq_domain_add_linear(chip->dev->of_node, 194 164 MT6397_IRQ_NR, 195 165 &mt6397_irq_domain_ops, ··· 209 177 return ret; 210 178 } 211 179 180 + register_pm_notifier(&chip->pm_nb); 212 181 return 0; 213 182 }
+1 -1
drivers/power/reset/mt6323-poweroff.c
··· 30 30 int ret; 31 31 32 32 regmap_write(pwrc->regmap, pwrc->base + RTC_BBPU, RTC_BBPU_KEY); 33 - regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR, 1); 33 + regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR_MT6323, 1); 34 34 35 35 ret = regmap_read_poll_timeout(pwrc->regmap, 36 36 pwrc->base + RTC_BBPU, val,
+10
drivers/power/supply/Kconfig
··· 541 541 Say Y to enable support for the battery charger control sysfs and 542 542 platform data of MAX8998/LP3974 PMICs. 543 543 544 + config CHARGER_MP2629 545 + tristate "Monolithic power system MP2629 Battery charger" 546 + depends on MFD_MP2629 547 + depends on MP2629_ADC 548 + depends on IIO 549 + help 550 + Select this option to enable support for Monolithic power system 551 + Battery charger. This driver provides Battery charger power management 552 + functions on the systems. 553 + 544 554 config CHARGER_QCOM_SMBB 545 555 tristate "Qualcomm Switch-Mode Battery Charger and Boost" 546 556 depends on MFD_SPMI_PMIC || COMPILE_TEST
+1
drivers/power/supply/Makefile
··· 75 75 obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o 76 76 obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o 77 77 obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o 78 + obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o 78 79 obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o 79 80 obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o 80 81 obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o
+669
drivers/power/supply/mp2629_charger.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * MP2629 battery charger driver 4 + * 5 + * Copyright 2020 Monolithic Power Systems, Inc 6 + * 7 + * Author: Saravanan Sekar <sravanhome@gmail.com> 8 + */ 9 + 10 + #include <linux/bits.h> 11 + #include <linux/iio/consumer.h> 12 + #include <linux/iio/types.h> 13 + #include <linux/interrupt.h> 14 + #include <linux/mfd/mp2629.h> 15 + #include <linux/module.h> 16 + #include <linux/mod_devicetable.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/power_supply.h> 19 + #include <linux/regmap.h> 20 + 21 + #define MP2629_REG_INPUT_ILIM 0x00 22 + #define MP2629_REG_INPUT_VLIM 0x01 23 + #define MP2629_REG_CHARGE_CTRL 0x04 24 + #define MP2629_REG_CHARGE_ILIM 0x05 25 + #define MP2629_REG_PRECHARGE 0x06 26 + #define MP2629_REG_TERM_CURRENT 0x06 27 + #define MP2629_REG_CHARGE_VLIM 0x07 28 + #define MP2629_REG_TIMER_CTRL 0x08 29 + #define MP2629_REG_IMPEDANCE_COMP 0x09 30 + #define MP2629_REG_INTERRUPT 0x0b 31 + #define MP2629_REG_STATUS 0x0c 32 + #define MP2629_REG_FAULT 0x0d 33 + 34 + #define MP2629_MASK_INPUT_TYPE GENMASK(7, 5) 35 + #define MP2629_MASK_CHARGE_TYPE GENMASK(4, 3) 36 + #define MP2629_MASK_CHARGE_CTRL GENMASK(5, 4) 37 + #define MP2629_MASK_WDOG_CTRL GENMASK(5, 4) 38 + #define MP2629_MASK_IMPEDANCE GENMASK(7, 4) 39 + 40 + #define MP2629_INPUTSOURCE_CHANGE GENMASK(7, 5) 41 + #define MP2629_CHARGING_CHANGE GENMASK(4, 3) 42 + #define MP2629_FAULT_BATTERY BIT(3) 43 + #define MP2629_FAULT_THERMAL BIT(4) 44 + #define MP2629_FAULT_INPUT BIT(5) 45 + #define MP2629_FAULT_OTG BIT(6) 46 + 47 + #define MP2629_MAX_BATT_CAPACITY 100 48 + 49 + #define MP2629_PROPS(_idx, _min, _max, _step) \ 50 + [_idx] = { \ 51 + .min = _min, \ 52 + .max = _max, \ 53 + .step = _step, \ 54 + } 55 + 56 + enum mp2629_source_type { 57 + MP2629_SOURCE_TYPE_NO_INPUT, 58 + MP2629_SOURCE_TYPE_NON_STD, 59 + MP2629_SOURCE_TYPE_SDP, 60 + MP2629_SOURCE_TYPE_CDP, 61 + MP2629_SOURCE_TYPE_DCP, 62 + MP2629_SOURCE_TYPE_OTG = 7, 63 + }; 64 + 65 + enum mp2629_field { 66 + INPUT_ILIM, 67 + INPUT_VLIM, 68 + CHARGE_ILIM, 69 + CHARGE_VLIM, 70 + PRECHARGE, 71 + TERM_CURRENT, 72 + MP2629_MAX_FIELD 73 + }; 74 + 75 + struct mp2629_charger { 76 + struct device *dev; 77 + int status; 78 + int fault; 79 + 80 + struct regmap *regmap; 81 + struct regmap_field *regmap_fields[MP2629_MAX_FIELD]; 82 + struct mutex lock; 83 + struct power_supply *usb; 84 + struct power_supply *battery; 85 + struct iio_channel *iiochan[MP2629_ADC_CHAN_END]; 86 + }; 87 + 88 + struct mp2629_prop { 89 + int reg; 90 + int mask; 91 + int min; 92 + int max; 93 + int step; 94 + int shift; 95 + }; 96 + 97 + static enum power_supply_usb_type mp2629_usb_types[] = { 98 + POWER_SUPPLY_USB_TYPE_SDP, 99 + POWER_SUPPLY_USB_TYPE_DCP, 100 + POWER_SUPPLY_USB_TYPE_CDP, 101 + POWER_SUPPLY_USB_TYPE_PD_DRP, 102 + POWER_SUPPLY_USB_TYPE_UNKNOWN 103 + }; 104 + 105 + static enum power_supply_property mp2629_charger_usb_props[] = { 106 + POWER_SUPPLY_PROP_ONLINE, 107 + POWER_SUPPLY_PROP_USB_TYPE, 108 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 109 + POWER_SUPPLY_PROP_CURRENT_NOW, 110 + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 111 + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, 112 + }; 113 + 114 + static enum power_supply_property mp2629_charger_bat_props[] = { 115 + POWER_SUPPLY_PROP_STATUS, 116 + POWER_SUPPLY_PROP_HEALTH, 117 + POWER_SUPPLY_PROP_CHARGE_TYPE, 118 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 119 + POWER_SUPPLY_PROP_CURRENT_NOW, 120 + POWER_SUPPLY_PROP_CAPACITY, 121 + POWER_SUPPLY_PROP_PRECHARGE_CURRENT, 122 + POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 123 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 124 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 125 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 126 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 127 + }; 128 + 129 + static struct mp2629_prop props[] = { 130 + MP2629_PROPS(INPUT_ILIM, 100000, 3250000, 50000), 131 + MP2629_PROPS(INPUT_VLIM, 3800000, 5300000, 100000), 132 + MP2629_PROPS(CHARGE_ILIM, 320000, 4520000, 40000), 133 + MP2629_PROPS(CHARGE_VLIM, 3400000, 4670000, 10000), 134 + MP2629_PROPS(PRECHARGE, 120000, 720000, 40000), 135 + MP2629_PROPS(TERM_CURRENT, 80000, 680000, 40000), 136 + }; 137 + 138 + static const struct reg_field mp2629_reg_fields[] = { 139 + [INPUT_ILIM] = REG_FIELD(MP2629_REG_INPUT_ILIM, 0, 5), 140 + [INPUT_VLIM] = REG_FIELD(MP2629_REG_INPUT_VLIM, 0, 3), 141 + [CHARGE_ILIM] = REG_FIELD(MP2629_REG_CHARGE_ILIM, 0, 6), 142 + [CHARGE_VLIM] = REG_FIELD(MP2629_REG_CHARGE_VLIM, 1, 7), 143 + [PRECHARGE] = REG_FIELD(MP2629_REG_PRECHARGE, 4, 7), 144 + [TERM_CURRENT] = REG_FIELD(MP2629_REG_TERM_CURRENT, 0, 3), 145 + }; 146 + 147 + static char *adc_chan_name[] = { 148 + "mp2629-batt-volt", 149 + "mp2629-system-volt", 150 + "mp2629-input-volt", 151 + "mp2629-batt-current", 152 + "mp2629-input-current", 153 + }; 154 + 155 + static int mp2629_read_adc(struct mp2629_charger *charger, 156 + enum mp2629_adc_chan ch, 157 + union power_supply_propval *val) 158 + { 159 + int ret; 160 + int chval; 161 + 162 + ret = iio_read_channel_processed(charger->iiochan[ch], &chval); 163 + if (ret) 164 + return ret; 165 + 166 + val->intval = chval * 1000; 167 + 168 + return 0; 169 + } 170 + 171 + static int mp2629_get_prop(struct mp2629_charger *charger, 172 + enum mp2629_field fld, 173 + union power_supply_propval *val) 174 + { 175 + int ret; 176 + unsigned int rval; 177 + 178 + ret = regmap_field_read(charger->regmap_fields[fld], &rval); 179 + if (ret) 180 + return ret; 181 + 182 + val->intval = rval * props[fld].step + props[fld].min; 183 + 184 + return 0; 185 + } 186 + 187 + static int mp2629_set_prop(struct mp2629_charger *charger, 188 + enum mp2629_field fld, 189 + const union power_supply_propval *val) 190 + { 191 + unsigned int rval; 192 + 193 + if (val->intval < props[fld].min || val->intval > props[fld].max) 194 + return -EINVAL; 195 + 196 + rval = (val->intval - props[fld].min) / props[fld].step; 197 + return regmap_field_write(charger->regmap_fields[fld], rval); 198 + } 199 + 200 + static int mp2629_get_battery_capacity(struct mp2629_charger *charger, 201 + union power_supply_propval *val) 202 + { 203 + union power_supply_propval vnow, vlim; 204 + int ret; 205 + 206 + ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, &vnow); 207 + if (ret) 208 + return ret; 209 + 210 + ret = mp2629_get_prop(charger, CHARGE_VLIM, &vlim); 211 + if (ret) 212 + return ret; 213 + 214 + val->intval = (vnow.intval * 100) / vlim.intval; 215 + val->intval = min(val->intval, MP2629_MAX_BATT_CAPACITY); 216 + 217 + return 0; 218 + } 219 + 220 + static int mp2629_charger_battery_get_prop(struct power_supply *psy, 221 + enum power_supply_property psp, 222 + union power_supply_propval *val) 223 + { 224 + struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 225 + unsigned int rval; 226 + int ret = 0; 227 + 228 + switch (psp) { 229 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 230 + ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, val); 231 + break; 232 + 233 + case POWER_SUPPLY_PROP_CURRENT_NOW: 234 + ret = mp2629_read_adc(charger, MP2629_BATT_CURRENT, val); 235 + break; 236 + 237 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 238 + val->intval = 4520000; 239 + break; 240 + 241 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 242 + val->intval = 4670000; 243 + break; 244 + 245 + case POWER_SUPPLY_PROP_CAPACITY: 246 + ret = mp2629_get_battery_capacity(charger, val); 247 + break; 248 + 249 + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 250 + ret = mp2629_get_prop(charger, TERM_CURRENT, val); 251 + break; 252 + 253 + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 254 + ret = mp2629_get_prop(charger, PRECHARGE, val); 255 + break; 256 + 257 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 258 + ret = mp2629_get_prop(charger, CHARGE_VLIM, val); 259 + break; 260 + 261 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 262 + ret = mp2629_get_prop(charger, CHARGE_ILIM, val); 263 + break; 264 + 265 + case POWER_SUPPLY_PROP_HEALTH: 266 + if (!charger->fault) 267 + val->intval = POWER_SUPPLY_HEALTH_GOOD; 268 + if (MP2629_FAULT_BATTERY & charger->fault) 269 + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 270 + else if (MP2629_FAULT_THERMAL & charger->fault) 271 + val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 272 + else if (MP2629_FAULT_INPUT & charger->fault) 273 + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 274 + break; 275 + 276 + case POWER_SUPPLY_PROP_STATUS: 277 + ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 278 + if (ret) 279 + break; 280 + 281 + rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3; 282 + switch (rval) { 283 + case 0x00: 284 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 285 + break; 286 + case 0x01: 287 + case 0x10: 288 + val->intval = POWER_SUPPLY_STATUS_CHARGING; 289 + break; 290 + case 0x11: 291 + val->intval = POWER_SUPPLY_STATUS_FULL; 292 + } 293 + break; 294 + 295 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 296 + ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 297 + if (ret) 298 + break; 299 + 300 + rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3; 301 + switch (rval) { 302 + case 0x00: 303 + val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 304 + break; 305 + case 0x01: 306 + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 307 + break; 308 + case 0x10: 309 + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 310 + break; 311 + default: 312 + val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; 313 + } 314 + break; 315 + 316 + default: 317 + return -EINVAL; 318 + } 319 + 320 + return ret; 321 + } 322 + 323 + static int mp2629_charger_battery_set_prop(struct power_supply *psy, 324 + enum power_supply_property psp, 325 + const union power_supply_propval *val) 326 + { 327 + struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 328 + 329 + switch (psp) { 330 + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 331 + return mp2629_set_prop(charger, TERM_CURRENT, val); 332 + 333 + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 334 + return mp2629_set_prop(charger, PRECHARGE, val); 335 + 336 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 337 + return mp2629_set_prop(charger, CHARGE_VLIM, val); 338 + 339 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 340 + return mp2629_set_prop(charger, CHARGE_ILIM, val); 341 + 342 + default: 343 + return -EINVAL; 344 + } 345 + } 346 + 347 + static int mp2629_charger_usb_get_prop(struct power_supply *psy, 348 + enum power_supply_property psp, 349 + union power_supply_propval *val) 350 + { 351 + struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 352 + unsigned int rval; 353 + int ret; 354 + 355 + switch (psp) { 356 + case POWER_SUPPLY_PROP_ONLINE: 357 + ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 358 + if (ret) 359 + break; 360 + 361 + val->intval = !!(rval & MP2629_MASK_INPUT_TYPE); 362 + break; 363 + 364 + case POWER_SUPPLY_PROP_USB_TYPE: 365 + ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 366 + if (ret) 367 + break; 368 + 369 + rval = (rval & MP2629_MASK_INPUT_TYPE) >> 5; 370 + switch (rval) { 371 + case MP2629_SOURCE_TYPE_SDP: 372 + val->intval = POWER_SUPPLY_USB_TYPE_SDP; 373 + break; 374 + case MP2629_SOURCE_TYPE_CDP: 375 + val->intval = POWER_SUPPLY_USB_TYPE_CDP; 376 + break; 377 + case MP2629_SOURCE_TYPE_DCP: 378 + val->intval = POWER_SUPPLY_USB_TYPE_DCP; 379 + break; 380 + case MP2629_SOURCE_TYPE_OTG: 381 + val->intval = POWER_SUPPLY_USB_TYPE_PD_DRP; 382 + break; 383 + default: 384 + val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN; 385 + break; 386 + } 387 + break; 388 + 389 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 390 + ret = mp2629_read_adc(charger, MP2629_INPUT_VOLT, val); 391 + break; 392 + 393 + case POWER_SUPPLY_PROP_CURRENT_NOW: 394 + ret = mp2629_read_adc(charger, MP2629_INPUT_CURRENT, val); 395 + break; 396 + 397 + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 398 + ret = mp2629_get_prop(charger, INPUT_VLIM, val); 399 + break; 400 + 401 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 402 + ret = mp2629_get_prop(charger, INPUT_ILIM, val); 403 + break; 404 + 405 + default: 406 + return -EINVAL; 407 + } 408 + 409 + return ret; 410 + } 411 + 412 + static int mp2629_charger_usb_set_prop(struct power_supply *psy, 413 + enum power_supply_property psp, 414 + const union power_supply_propval *val) 415 + { 416 + struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 417 + 418 + switch (psp) { 419 + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 420 + return mp2629_set_prop(charger, INPUT_VLIM, val); 421 + 422 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 423 + return mp2629_set_prop(charger, INPUT_ILIM, val); 424 + 425 + default: 426 + return -EINVAL; 427 + } 428 + } 429 + 430 + static int mp2629_charger_battery_prop_writeable(struct power_supply *psy, 431 + enum power_supply_property psp) 432 + { 433 + return (psp == POWER_SUPPLY_PROP_PRECHARGE_CURRENT) || 434 + (psp == POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT) || 435 + (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT) || 436 + (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE); 437 + } 438 + 439 + static int mp2629_charger_usb_prop_writeable(struct power_supply *psy, 440 + enum power_supply_property psp) 441 + { 442 + return (psp == POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT) || 443 + (psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT); 444 + } 445 + 446 + static irqreturn_t mp2629_irq_handler(int irq, void *dev_id) 447 + { 448 + struct mp2629_charger *charger = dev_id; 449 + unsigned int rval; 450 + int ret; 451 + 452 + mutex_lock(&charger->lock); 453 + 454 + ret = regmap_read(charger->regmap, MP2629_REG_FAULT, &rval); 455 + if (ret) 456 + goto unlock; 457 + 458 + if (rval) { 459 + charger->fault = rval; 460 + if (MP2629_FAULT_BATTERY & rval) 461 + dev_err(charger->dev, "Battery fault OVP\n"); 462 + else if (MP2629_FAULT_THERMAL & rval) 463 + dev_err(charger->dev, "Thermal shutdown fault\n"); 464 + else if (MP2629_FAULT_INPUT & rval) 465 + dev_err(charger->dev, "no input or input OVP\n"); 466 + else if (MP2629_FAULT_OTG & rval) 467 + dev_err(charger->dev, "VIN overloaded\n"); 468 + 469 + goto unlock; 470 + } 471 + 472 + ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 473 + if (ret) 474 + goto unlock; 475 + 476 + if (rval & MP2629_INPUTSOURCE_CHANGE) 477 + power_supply_changed(charger->usb); 478 + else if (rval & MP2629_CHARGING_CHANGE) 479 + power_supply_changed(charger->battery); 480 + 481 + unlock: 482 + mutex_unlock(&charger->lock); 483 + 484 + return IRQ_HANDLED; 485 + } 486 + 487 + static const struct power_supply_desc mp2629_usb_desc = { 488 + .name = "mp2629_usb", 489 + .type = POWER_SUPPLY_TYPE_USB, 490 + .usb_types = mp2629_usb_types, 491 + .num_usb_types = ARRAY_SIZE(mp2629_usb_types), 492 + .properties = mp2629_charger_usb_props, 493 + .num_properties = ARRAY_SIZE(mp2629_charger_usb_props), 494 + .get_property = mp2629_charger_usb_get_prop, 495 + .set_property = mp2629_charger_usb_set_prop, 496 + .property_is_writeable = mp2629_charger_usb_prop_writeable, 497 + }; 498 + 499 + static const struct power_supply_desc mp2629_battery_desc = { 500 + .name = "mp2629_battery", 501 + .type = POWER_SUPPLY_TYPE_BATTERY, 502 + .properties = mp2629_charger_bat_props, 503 + .num_properties = ARRAY_SIZE(mp2629_charger_bat_props), 504 + .get_property = mp2629_charger_battery_get_prop, 505 + .set_property = mp2629_charger_battery_set_prop, 506 + .property_is_writeable = mp2629_charger_battery_prop_writeable, 507 + }; 508 + 509 + static ssize_t batt_impedance_compensation_show(struct device *dev, 510 + struct device_attribute *attr, 511 + char *buf) 512 + { 513 + struct mp2629_charger *charger = dev_get_drvdata(dev->parent); 514 + unsigned int rval; 515 + int ret; 516 + 517 + ret = regmap_read(charger->regmap, MP2629_REG_IMPEDANCE_COMP, &rval); 518 + if (ret) 519 + return ret; 520 + 521 + rval = (rval >> 4) * 10; 522 + return sprintf(buf, "%d mohm\n", rval); 523 + } 524 + 525 + static ssize_t batt_impedance_compensation_store(struct device *dev, 526 + struct device_attribute *attr, 527 + const char *buf, 528 + size_t count) 529 + { 530 + struct mp2629_charger *charger = dev_get_drvdata(dev->parent); 531 + unsigned int val; 532 + int ret; 533 + 534 + ret = kstrtouint(buf, 10, &val); 535 + if (ret) 536 + return ret; 537 + 538 + if (val > 140) 539 + return -ERANGE; 540 + 541 + /* multiples of 10 mohm so round off */ 542 + val = val / 10; 543 + ret = regmap_update_bits(charger->regmap, MP2629_REG_IMPEDANCE_COMP, 544 + MP2629_MASK_IMPEDANCE, val << 4); 545 + if (ret) 546 + return ret; 547 + 548 + return count; 549 + } 550 + 551 + static DEVICE_ATTR_RW(batt_impedance_compensation); 552 + 553 + static struct attribute *mp2629_charger_sysfs_attrs[] = { 554 + &dev_attr_batt_impedance_compensation.attr, 555 + NULL 556 + }; 557 + ATTRIBUTE_GROUPS(mp2629_charger_sysfs); 558 + 559 + static void mp2629_charger_disable(void *data) 560 + { 561 + struct mp2629_charger *charger = data; 562 + 563 + regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL, 564 + MP2629_MASK_CHARGE_CTRL, 0); 565 + } 566 + 567 + static int mp2629_charger_probe(struct platform_device *pdev) 568 + { 569 + struct device *dev = &pdev->dev; 570 + struct mp2629_data *ddata = dev_get_drvdata(dev->parent); 571 + struct mp2629_charger *charger; 572 + struct power_supply_config psy_cfg = {}; 573 + int ret, i, irq; 574 + 575 + charger = devm_kzalloc(dev, sizeof(*charger), GFP_KERNEL); 576 + if (!charger) 577 + return -ENOMEM; 578 + 579 + charger->regmap = ddata->regmap; 580 + charger->dev = dev; 581 + platform_set_drvdata(pdev, charger); 582 + 583 + irq = platform_get_irq_optional(to_platform_device(dev->parent), 0); 584 + if (irq < 0) { 585 + dev_err(dev, "get irq fail: %d\n", irq); 586 + return irq; 587 + } 588 + 589 + for (i = 0; i < MP2629_MAX_FIELD; i++) { 590 + charger->regmap_fields[i] = devm_regmap_field_alloc(dev, 591 + charger->regmap, mp2629_reg_fields[i]); 592 + if (IS_ERR(charger->regmap_fields[i])) { 593 + dev_err(dev, "regmap field alloc fail %d\n", i); 594 + return PTR_ERR(charger->regmap_fields[i]); 595 + } 596 + } 597 + 598 + for (i = 0; i < MP2629_ADC_CHAN_END; i++) { 599 + charger->iiochan[i] = devm_iio_channel_get(dev, 600 + adc_chan_name[i]); 601 + if (IS_ERR(charger->iiochan[i])) { 602 + dev_err(dev, "iio chan get %s err\n", adc_chan_name[i]); 603 + return PTR_ERR(charger->iiochan[i]); 604 + } 605 + } 606 + 607 + ret = devm_add_action_or_reset(dev, mp2629_charger_disable, charger); 608 + if (ret) 609 + return ret; 610 + 611 + charger->usb = devm_power_supply_register(dev, &mp2629_usb_desc, NULL); 612 + if (IS_ERR(charger->usb)) { 613 + dev_err(dev, "power supply register usb failed\n"); 614 + return PTR_ERR(charger->usb); 615 + } 616 + 617 + psy_cfg.drv_data = charger; 618 + psy_cfg.attr_grp = mp2629_charger_sysfs_groups; 619 + charger->battery = devm_power_supply_register(dev, 620 + &mp2629_battery_desc, &psy_cfg); 621 + if (IS_ERR(charger->battery)) { 622 + dev_err(dev, "power supply register battery failed\n"); 623 + return PTR_ERR(charger->battery); 624 + } 625 + 626 + ret = regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL, 627 + MP2629_MASK_CHARGE_CTRL, BIT(4)); 628 + if (ret) { 629 + dev_err(dev, "enable charge fail: %d\n", ret); 630 + return ret; 631 + } 632 + 633 + regmap_update_bits(charger->regmap, MP2629_REG_TIMER_CTRL, 634 + MP2629_MASK_WDOG_CTRL, 0); 635 + 636 + mutex_init(&charger->lock); 637 + 638 + ret = devm_request_threaded_irq(dev, irq, NULL, mp2629_irq_handler, 639 + IRQF_ONESHOT | IRQF_TRIGGER_RISING, 640 + "mp2629-charger", charger); 641 + if (ret) { 642 + dev_err(dev, "failed to request gpio IRQ\n"); 643 + return ret; 644 + } 645 + 646 + regmap_update_bits(charger->regmap, MP2629_REG_INTERRUPT, 647 + GENMASK(6, 5), BIT(6) | BIT(5)); 648 + 649 + return 0; 650 + } 651 + 652 + static const struct of_device_id mp2629_charger_of_match[] = { 653 + { .compatible = "mps,mp2629_charger"}, 654 + {} 655 + }; 656 + MODULE_DEVICE_TABLE(of, mp2629_charger_of_match); 657 + 658 + static struct platform_driver mp2629_charger_driver = { 659 + .driver = { 660 + .name = "mp2629_charger", 661 + .of_match_table = mp2629_charger_of_match, 662 + }, 663 + .probe = mp2629_charger_probe, 664 + }; 665 + module_platform_driver(mp2629_charger_driver); 666 + 667 + MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>"); 668 + MODULE_DESCRIPTION("MP2629 Charger driver"); 669 + MODULE_LICENSE("GPL");
+15 -3
drivers/rtc/rtc-mt6397.c
··· 9 9 #include <linux/mfd/mt6397/core.h> 10 10 #include <linux/module.h> 11 11 #include <linux/mutex.h> 12 + #include <linux/of_device.h> 12 13 #include <linux/platform_device.h> 13 14 #include <linux/regmap.h> 14 15 #include <linux/rtc.h> ··· 21 20 int ret; 22 21 u32 data; 23 22 24 - ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_WRTGR, 1); 23 + ret = regmap_write(rtc->regmap, rtc->addr_base + rtc->data->wrtgr, 1); 25 24 if (ret < 0) 26 25 return ret; 27 26 ··· 270 269 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 271 270 rtc->addr_base = res->start; 272 271 272 + rtc->data = of_device_get_match_data(&pdev->dev); 273 + 273 274 rtc->irq = platform_get_irq(pdev, 0); 274 275 if (rtc->irq < 0) 275 276 return rtc->irq; ··· 328 325 static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend, 329 326 mt6397_rtc_resume); 330 327 328 + static const struct mtk_rtc_data mt6358_rtc_data = { 329 + .wrtgr = RTC_WRTGR_MT6358, 330 + }; 331 + 332 + static const struct mtk_rtc_data mt6397_rtc_data = { 333 + .wrtgr = RTC_WRTGR_MT6397, 334 + }; 335 + 331 336 static const struct of_device_id mt6397_rtc_of_match[] = { 332 - { .compatible = "mediatek,mt6323-rtc", }, 333 - { .compatible = "mediatek,mt6397-rtc", }, 337 + { .compatible = "mediatek,mt6323-rtc", .data = &mt6397_rtc_data }, 338 + { .compatible = "mediatek,mt6358-rtc", .data = &mt6358_rtc_data }, 339 + { .compatible = "mediatek,mt6397-rtc", .data = &mt6397_rtc_data }, 334 340 { } 335 341 }; 336 342 MODULE_DEVICE_TABLE(of, mt6397_rtc_of_match);
+76
include/linux/mfd/gsc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 3 + * Copyright (C) 2020 Gateworks Corporation 4 + */ 5 + #ifndef __LINUX_MFD_GSC_H_ 6 + #define __LINUX_MFD_GSC_H_ 7 + 8 + #include <linux/regmap.h> 9 + 10 + /* Device Addresses */ 11 + #define GSC_MISC 0x20 12 + #define GSC_UPDATE 0x21 13 + #define GSC_GPIO 0x23 14 + #define GSC_HWMON 0x29 15 + #define GSC_EEPROM0 0x50 16 + #define GSC_EEPROM1 0x51 17 + #define GSC_EEPROM2 0x52 18 + #define GSC_EEPROM3 0x53 19 + #define GSC_RTC 0x68 20 + 21 + /* Register offsets */ 22 + enum { 23 + GSC_CTRL_0 = 0x00, 24 + GSC_CTRL_1 = 0x01, 25 + GSC_TIME = 0x02, 26 + GSC_TIME_ADD = 0x06, 27 + GSC_IRQ_STATUS = 0x0A, 28 + GSC_IRQ_ENABLE = 0x0B, 29 + GSC_FW_CRC = 0x0C, 30 + GSC_FW_VER = 0x0E, 31 + GSC_WP = 0x0F, 32 + }; 33 + 34 + /* Bit definitions */ 35 + #define GSC_CTRL_0_PB_HARD_RESET 0 36 + #define GSC_CTRL_0_PB_CLEAR_SECURE_KEY 1 37 + #define GSC_CTRL_0_PB_SOFT_POWER_DOWN 2 38 + #define GSC_CTRL_0_PB_BOOT_ALTERNATE 3 39 + #define GSC_CTRL_0_PERFORM_CRC 4 40 + #define GSC_CTRL_0_TAMPER_DETECT 5 41 + #define GSC_CTRL_0_SWITCH_HOLD 6 42 + 43 + #define GSC_CTRL_1_SLEEP_ENABLE 0 44 + #define GSC_CTRL_1_SLEEP_ACTIVATE 1 45 + #define GSC_CTRL_1_SLEEP_ADD 2 46 + #define GSC_CTRL_1_SLEEP_NOWAKEPB 3 47 + #define GSC_CTRL_1_WDT_TIME 4 48 + #define GSC_CTRL_1_WDT_ENABLE 5 49 + #define GSC_CTRL_1_SWITCH_BOOT_ENABLE 6 50 + #define GSC_CTRL_1_SWITCH_BOOT_CLEAR 7 51 + 52 + #define GSC_IRQ_PB 0 53 + #define GSC_IRQ_KEY_ERASED 1 54 + #define GSC_IRQ_EEPROM_WP 2 55 + #define GSC_IRQ_RESV 3 56 + #define GSC_IRQ_GPIO 4 57 + #define GSC_IRQ_TAMPER 5 58 + #define GSC_IRQ_WDT_TIMEOUT 6 59 + #define GSC_IRQ_SWITCH_HOLD 7 60 + 61 + int gsc_read(void *context, unsigned int reg, unsigned int *val); 62 + int gsc_write(void *context, unsigned int reg, unsigned int val); 63 + 64 + struct gsc_dev { 65 + struct device *dev; 66 + 67 + struct i2c_client *i2c; /* 0x20: interrupt controller, WDT */ 68 + struct i2c_client *i2c_hwmon; /* 0x29: hwmon, fan controller */ 69 + 70 + struct regmap *regmap; 71 + 72 + unsigned int fwver; 73 + unsigned short fwcrc; 74 + }; 75 + 76 + #endif /* __LINUX_MFD_GSC_H_ */
+26
include/linux/mfd/mp2629.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright 2020 Monolithic Power Systems, Inc 4 + */ 5 + 6 + #ifndef __MP2629_H__ 7 + #define __MP2629_H__ 8 + 9 + #include <linux/device.h> 10 + #include <linux/regmap.h> 11 + 12 + struct mp2629_data { 13 + struct device *dev; 14 + struct regmap *regmap; 15 + }; 16 + 17 + enum mp2629_adc_chan { 18 + MP2629_BATT_VOLT, 19 + MP2629_SYSTEM_VOLT, 20 + MP2629_INPUT_VOLT, 21 + MP2629_BATT_CURRENT, 22 + MP2629_INPUT_CURRENT, 23 + MP2629_ADC_CHAN_END 24 + }; 25 + 26 + #endif
+158
include/linux/mfd/mt6358/core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2020 MediaTek Inc. 4 + */ 5 + 6 + #ifndef __MFD_MT6358_CORE_H__ 7 + #define __MFD_MT6358_CORE_H__ 8 + 9 + #define MT6358_REG_WIDTH 16 10 + 11 + struct irq_top_t { 12 + int hwirq_base; 13 + unsigned int num_int_regs; 14 + unsigned int num_int_bits; 15 + unsigned int en_reg; 16 + unsigned int en_reg_shift; 17 + unsigned int sta_reg; 18 + unsigned int sta_reg_shift; 19 + unsigned int top_offset; 20 + }; 21 + 22 + struct pmic_irq_data { 23 + unsigned int num_top; 24 + unsigned int num_pmic_irqs; 25 + unsigned short top_int_status_reg; 26 + bool *enable_hwirq; 27 + bool *cache_hwirq; 28 + }; 29 + 30 + enum mt6358_irq_top_status_shift { 31 + MT6358_BUCK_TOP = 0, 32 + MT6358_LDO_TOP, 33 + MT6358_PSC_TOP, 34 + MT6358_SCK_TOP, 35 + MT6358_BM_TOP, 36 + MT6358_HK_TOP, 37 + MT6358_AUD_TOP, 38 + MT6358_MISC_TOP, 39 + }; 40 + 41 + enum mt6358_irq_numbers { 42 + MT6358_IRQ_VPROC11_OC = 0, 43 + MT6358_IRQ_VPROC12_OC, 44 + MT6358_IRQ_VCORE_OC, 45 + MT6358_IRQ_VGPU_OC, 46 + MT6358_IRQ_VMODEM_OC, 47 + MT6358_IRQ_VDRAM1_OC, 48 + MT6358_IRQ_VS1_OC, 49 + MT6358_IRQ_VS2_OC, 50 + MT6358_IRQ_VPA_OC, 51 + MT6358_IRQ_VCORE_PREOC, 52 + MT6358_IRQ_VFE28_OC = 16, 53 + MT6358_IRQ_VXO22_OC, 54 + MT6358_IRQ_VRF18_OC, 55 + MT6358_IRQ_VRF12_OC, 56 + MT6358_IRQ_VEFUSE_OC, 57 + MT6358_IRQ_VCN33_OC, 58 + MT6358_IRQ_VCN28_OC, 59 + MT6358_IRQ_VCN18_OC, 60 + MT6358_IRQ_VCAMA1_OC, 61 + MT6358_IRQ_VCAMA2_OC, 62 + MT6358_IRQ_VCAMD_OC, 63 + MT6358_IRQ_VCAMIO_OC, 64 + MT6358_IRQ_VLDO28_OC, 65 + MT6358_IRQ_VA12_OC, 66 + MT6358_IRQ_VAUX18_OC, 67 + MT6358_IRQ_VAUD28_OC, 68 + MT6358_IRQ_VIO28_OC, 69 + MT6358_IRQ_VIO18_OC, 70 + MT6358_IRQ_VSRAM_PROC11_OC, 71 + MT6358_IRQ_VSRAM_PROC12_OC, 72 + MT6358_IRQ_VSRAM_OTHERS_OC, 73 + MT6358_IRQ_VSRAM_GPU_OC, 74 + MT6358_IRQ_VDRAM2_OC, 75 + MT6358_IRQ_VMC_OC, 76 + MT6358_IRQ_VMCH_OC, 77 + MT6358_IRQ_VEMC_OC, 78 + MT6358_IRQ_VSIM1_OC, 79 + MT6358_IRQ_VSIM2_OC, 80 + MT6358_IRQ_VIBR_OC, 81 + MT6358_IRQ_VUSB_OC, 82 + MT6358_IRQ_VBIF28_OC, 83 + MT6358_IRQ_PWRKEY = 48, 84 + MT6358_IRQ_HOMEKEY, 85 + MT6358_IRQ_PWRKEY_R, 86 + MT6358_IRQ_HOMEKEY_R, 87 + MT6358_IRQ_NI_LBAT_INT, 88 + MT6358_IRQ_CHRDET, 89 + MT6358_IRQ_CHRDET_EDGE, 90 + MT6358_IRQ_VCDT_HV_DET, 91 + MT6358_IRQ_RTC = 64, 92 + MT6358_IRQ_FG_BAT0_H = 80, 93 + MT6358_IRQ_FG_BAT0_L, 94 + MT6358_IRQ_FG_CUR_H, 95 + MT6358_IRQ_FG_CUR_L, 96 + MT6358_IRQ_FG_ZCV, 97 + MT6358_IRQ_FG_BAT1_H, 98 + MT6358_IRQ_FG_BAT1_L, 99 + MT6358_IRQ_FG_N_CHARGE_L, 100 + MT6358_IRQ_FG_IAVG_H, 101 + MT6358_IRQ_FG_IAVG_L, 102 + MT6358_IRQ_FG_TIME_H, 103 + MT6358_IRQ_FG_DISCHARGE, 104 + MT6358_IRQ_FG_CHARGE, 105 + MT6358_IRQ_BATON_LV = 96, 106 + MT6358_IRQ_BATON_HT, 107 + MT6358_IRQ_BATON_BAT_IN, 108 + MT6358_IRQ_BATON_BAT_OUT, 109 + MT6358_IRQ_BIF, 110 + MT6358_IRQ_BAT_H = 112, 111 + MT6358_IRQ_BAT_L, 112 + MT6358_IRQ_BAT2_H, 113 + MT6358_IRQ_BAT2_L, 114 + MT6358_IRQ_BAT_TEMP_H, 115 + MT6358_IRQ_BAT_TEMP_L, 116 + MT6358_IRQ_AUXADC_IMP, 117 + MT6358_IRQ_NAG_C_DLTV, 118 + MT6358_IRQ_AUDIO = 128, 119 + MT6358_IRQ_ACCDET = 133, 120 + MT6358_IRQ_ACCDET_EINT0, 121 + MT6358_IRQ_ACCDET_EINT1, 122 + MT6358_IRQ_SPI_CMD_ALERT = 144, 123 + MT6358_IRQ_NR, 124 + }; 125 + 126 + #define MT6358_IRQ_BUCK_BASE MT6358_IRQ_VPROC11_OC 127 + #define MT6358_IRQ_LDO_BASE MT6358_IRQ_VFE28_OC 128 + #define MT6358_IRQ_PSC_BASE MT6358_IRQ_PWRKEY 129 + #define MT6358_IRQ_SCK_BASE MT6358_IRQ_RTC 130 + #define MT6358_IRQ_BM_BASE MT6358_IRQ_FG_BAT0_H 131 + #define MT6358_IRQ_HK_BASE MT6358_IRQ_BAT_H 132 + #define MT6358_IRQ_AUD_BASE MT6358_IRQ_AUDIO 133 + #define MT6358_IRQ_MISC_BASE MT6358_IRQ_SPI_CMD_ALERT 134 + 135 + #define MT6358_IRQ_BUCK_BITS (MT6358_IRQ_VCORE_PREOC - MT6358_IRQ_BUCK_BASE + 1) 136 + #define MT6358_IRQ_LDO_BITS (MT6358_IRQ_VBIF28_OC - MT6358_IRQ_LDO_BASE + 1) 137 + #define MT6358_IRQ_PSC_BITS (MT6358_IRQ_VCDT_HV_DET - MT6358_IRQ_PSC_BASE + 1) 138 + #define MT6358_IRQ_SCK_BITS (MT6358_IRQ_RTC - MT6358_IRQ_SCK_BASE + 1) 139 + #define MT6358_IRQ_BM_BITS (MT6358_IRQ_BIF - MT6358_IRQ_BM_BASE + 1) 140 + #define MT6358_IRQ_HK_BITS (MT6358_IRQ_NAG_C_DLTV - MT6358_IRQ_HK_BASE + 1) 141 + #define MT6358_IRQ_AUD_BITS (MT6358_IRQ_ACCDET_EINT1 - MT6358_IRQ_AUD_BASE + 1) 142 + #define MT6358_IRQ_MISC_BITS \ 143 + (MT6358_IRQ_SPI_CMD_ALERT - MT6358_IRQ_MISC_BASE + 1) 144 + 145 + #define MT6358_TOP_GEN(sp) \ 146 + { \ 147 + .hwirq_base = MT6358_IRQ_##sp##_BASE, \ 148 + .num_int_regs = \ 149 + ((MT6358_IRQ_##sp##_BITS - 1) / MT6358_REG_WIDTH) + 1, \ 150 + .num_int_bits = MT6358_IRQ_##sp##_BITS, \ 151 + .en_reg = MT6358_##sp##_TOP_INT_CON0, \ 152 + .en_reg_shift = 0x6, \ 153 + .sta_reg = MT6358_##sp##_TOP_INT_STATUS0, \ 154 + .sta_reg_shift = 0x2, \ 155 + .top_offset = MT6358_##sp##_TOP, \ 156 + } 157 + 158 + #endif /* __MFD_MT6358_CORE_H__ */
+282
include/linux/mfd/mt6358/registers.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2020 MediaTek Inc. 4 + */ 5 + 6 + #ifndef __MFD_MT6358_REGISTERS_H__ 7 + #define __MFD_MT6358_REGISTERS_H__ 8 + 9 + /* PMIC Registers */ 10 + #define MT6358_SWCID 0xa 11 + #define MT6358_MISC_TOP_INT_CON0 0x188 12 + #define MT6358_MISC_TOP_INT_STATUS0 0x194 13 + #define MT6358_TOP_INT_STATUS0 0x19e 14 + #define MT6358_SCK_TOP_INT_CON0 0x52e 15 + #define MT6358_SCK_TOP_INT_STATUS0 0x53a 16 + #define MT6358_EOSC_CALI_CON0 0x540 17 + #define MT6358_EOSC_CALI_CON1 0x542 18 + #define MT6358_RTC_MIX_CON0 0x544 19 + #define MT6358_RTC_MIX_CON1 0x546 20 + #define MT6358_RTC_MIX_CON2 0x548 21 + #define MT6358_RTC_DSN_ID 0x580 22 + #define MT6358_RTC_DSN_REV0 0x582 23 + #define MT6358_RTC_DBI 0x584 24 + #define MT6358_RTC_DXI 0x586 25 + #define MT6358_RTC_BBPU 0x588 26 + #define MT6358_RTC_IRQ_STA 0x58a 27 + #define MT6358_RTC_IRQ_EN 0x58c 28 + #define MT6358_RTC_CII_EN 0x58e 29 + #define MT6358_RTC_AL_MASK 0x590 30 + #define MT6358_RTC_TC_SEC 0x592 31 + #define MT6358_RTC_TC_MIN 0x594 32 + #define MT6358_RTC_TC_HOU 0x596 33 + #define MT6358_RTC_TC_DOM 0x598 34 + #define MT6358_RTC_TC_DOW 0x59a 35 + #define MT6358_RTC_TC_MTH 0x59c 36 + #define MT6358_RTC_TC_YEA 0x59e 37 + #define MT6358_RTC_AL_SEC 0x5a0 38 + #define MT6358_RTC_AL_MIN 0x5a2 39 + #define MT6358_RTC_AL_HOU 0x5a4 40 + #define MT6358_RTC_AL_DOM 0x5a6 41 + #define MT6358_RTC_AL_DOW 0x5a8 42 + #define MT6358_RTC_AL_MTH 0x5aa 43 + #define MT6358_RTC_AL_YEA 0x5ac 44 + #define MT6358_RTC_OSC32CON 0x5ae 45 + #define MT6358_RTC_POWERKEY1 0x5b0 46 + #define MT6358_RTC_POWERKEY2 0x5b2 47 + #define MT6358_RTC_PDN1 0x5b4 48 + #define MT6358_RTC_PDN2 0x5b6 49 + #define MT6358_RTC_SPAR0 0x5b8 50 + #define MT6358_RTC_SPAR1 0x5ba 51 + #define MT6358_RTC_PROT 0x5bc 52 + #define MT6358_RTC_DIFF 0x5be 53 + #define MT6358_RTC_CALI 0x5c0 54 + #define MT6358_RTC_WRTGR 0x5c2 55 + #define MT6358_RTC_CON 0x5c4 56 + #define MT6358_RTC_SEC_CTRL 0x5c6 57 + #define MT6358_RTC_INT_CNT 0x5c8 58 + #define MT6358_RTC_SEC_DAT0 0x5ca 59 + #define MT6358_RTC_SEC_DAT1 0x5cc 60 + #define MT6358_RTC_SEC_DAT2 0x5ce 61 + #define MT6358_RTC_SEC_DSN_ID 0x600 62 + #define MT6358_RTC_SEC_DSN_REV0 0x602 63 + #define MT6358_RTC_SEC_DBI 0x604 64 + #define MT6358_RTC_SEC_DXI 0x606 65 + #define MT6358_RTC_TC_SEC_SEC 0x608 66 + #define MT6358_RTC_TC_MIN_SEC 0x60a 67 + #define MT6358_RTC_TC_HOU_SEC 0x60c 68 + #define MT6358_RTC_TC_DOM_SEC 0x60e 69 + #define MT6358_RTC_TC_DOW_SEC 0x610 70 + #define MT6358_RTC_TC_MTH_SEC 0x612 71 + #define MT6358_RTC_TC_YEA_SEC 0x614 72 + #define MT6358_RTC_SEC_CK_PDN 0x616 73 + #define MT6358_RTC_SEC_WRTGR 0x618 74 + #define MT6358_PSC_TOP_INT_CON0 0x910 75 + #define MT6358_PSC_TOP_INT_STATUS0 0x91c 76 + #define MT6358_BM_TOP_INT_CON0 0xc32 77 + #define MT6358_BM_TOP_INT_CON1 0xc38 78 + #define MT6358_BM_TOP_INT_STATUS0 0xc4a 79 + #define MT6358_BM_TOP_INT_STATUS1 0xc4c 80 + #define MT6358_HK_TOP_INT_CON0 0xf92 81 + #define MT6358_HK_TOP_INT_STATUS0 0xf9e 82 + #define MT6358_BUCK_TOP_INT_CON0 0x1318 83 + #define MT6358_BUCK_TOP_INT_STATUS0 0x1324 84 + #define MT6358_BUCK_VPROC11_CON0 0x1388 85 + #define MT6358_BUCK_VPROC11_DBG0 0x139e 86 + #define MT6358_BUCK_VPROC11_DBG1 0x13a0 87 + #define MT6358_BUCK_VPROC11_ELR0 0x13a6 88 + #define MT6358_BUCK_VPROC12_CON0 0x1408 89 + #define MT6358_BUCK_VPROC12_DBG0 0x141e 90 + #define MT6358_BUCK_VPROC12_DBG1 0x1420 91 + #define MT6358_BUCK_VPROC12_ELR0 0x1426 92 + #define MT6358_BUCK_VCORE_CON0 0x1488 93 + #define MT6358_BUCK_VCORE_DBG0 0x149e 94 + #define MT6358_BUCK_VCORE_DBG1 0x14a0 95 + #define MT6358_BUCK_VCORE_ELR0 0x14aa 96 + #define MT6358_BUCK_VGPU_CON0 0x1508 97 + #define MT6358_BUCK_VGPU_DBG0 0x151e 98 + #define MT6358_BUCK_VGPU_DBG1 0x1520 99 + #define MT6358_BUCK_VGPU_ELR0 0x1526 100 + #define MT6358_BUCK_VMODEM_CON0 0x1588 101 + #define MT6358_BUCK_VMODEM_DBG0 0x159e 102 + #define MT6358_BUCK_VMODEM_DBG1 0x15a0 103 + #define MT6358_BUCK_VMODEM_ELR0 0x15a6 104 + #define MT6358_BUCK_VDRAM1_CON0 0x1608 105 + #define MT6358_BUCK_VDRAM1_DBG0 0x161e 106 + #define MT6358_BUCK_VDRAM1_DBG1 0x1620 107 + #define MT6358_BUCK_VDRAM1_ELR0 0x1626 108 + #define MT6358_BUCK_VS1_CON0 0x1688 109 + #define MT6358_BUCK_VS1_DBG0 0x169e 110 + #define MT6358_BUCK_VS1_DBG1 0x16a0 111 + #define MT6358_BUCK_VS1_ELR0 0x16ae 112 + #define MT6358_BUCK_VS2_CON0 0x1708 113 + #define MT6358_BUCK_VS2_DBG0 0x171e 114 + #define MT6358_BUCK_VS2_DBG1 0x1720 115 + #define MT6358_BUCK_VS2_ELR0 0x172e 116 + #define MT6358_BUCK_VPA_CON0 0x1788 117 + #define MT6358_BUCK_VPA_CON1 0x178a 118 + #define MT6358_BUCK_VPA_ELR0 MT6358_BUCK_VPA_CON1 119 + #define MT6358_BUCK_VPA_DBG0 0x1792 120 + #define MT6358_BUCK_VPA_DBG1 0x1794 121 + #define MT6358_VPROC_ANA_CON0 0x180c 122 + #define MT6358_VCORE_VGPU_ANA_CON0 0x1828 123 + #define MT6358_VMODEM_ANA_CON0 0x1888 124 + #define MT6358_VDRAM1_ANA_CON0 0x1896 125 + #define MT6358_VS1_ANA_CON0 0x18a2 126 + #define MT6358_VS2_ANA_CON0 0x18ae 127 + #define MT6358_VPA_ANA_CON0 0x18ba 128 + #define MT6358_LDO_TOP_INT_CON0 0x1a50 129 + #define MT6358_LDO_TOP_INT_CON1 0x1a56 130 + #define MT6358_LDO_TOP_INT_STATUS0 0x1a68 131 + #define MT6358_LDO_TOP_INT_STATUS1 0x1a6a 132 + #define MT6358_LDO_VXO22_CON0 0x1a88 133 + #define MT6358_LDO_VXO22_CON1 0x1a96 134 + #define MT6358_LDO_VA12_CON0 0x1a9c 135 + #define MT6358_LDO_VA12_CON1 0x1aaa 136 + #define MT6358_LDO_VAUX18_CON0 0x1ab0 137 + #define MT6358_LDO_VAUX18_CON1 0x1abe 138 + #define MT6358_LDO_VAUD28_CON0 0x1ac4 139 + #define MT6358_LDO_VAUD28_CON1 0x1ad2 140 + #define MT6358_LDO_VIO28_CON0 0x1ad8 141 + #define MT6358_LDO_VIO28_CON1 0x1ae6 142 + #define MT6358_LDO_VIO18_CON0 0x1aec 143 + #define MT6358_LDO_VIO18_CON1 0x1afa 144 + #define MT6358_LDO_VDRAM2_CON0 0x1b08 145 + #define MT6358_LDO_VDRAM2_CON1 0x1b16 146 + #define MT6358_LDO_VEMC_CON0 0x1b1c 147 + #define MT6358_LDO_VEMC_CON1 0x1b2a 148 + #define MT6358_LDO_VUSB_CON0_0 0x1b30 149 + #define MT6358_LDO_VUSB_CON1 0x1b40 150 + #define MT6358_LDO_VSRAM_PROC11_CON0 0x1b46 151 + #define MT6358_LDO_VSRAM_PROC11_DBG0 0x1b60 152 + #define MT6358_LDO_VSRAM_PROC11_DBG1 0x1b62 153 + #define MT6358_LDO_VSRAM_PROC11_TRACKING_CON0 0x1b64 154 + #define MT6358_LDO_VSRAM_PROC11_TRACKING_CON1 0x1b66 155 + #define MT6358_LDO_VSRAM_PROC11_TRACKING_CON2 0x1b68 156 + #define MT6358_LDO_VSRAM_PROC11_TRACKING_CON3 0x1b6a 157 + #define MT6358_LDO_VSRAM_PROC12_TRACKING_CON0 0x1b6c 158 + #define MT6358_LDO_VSRAM_PROC12_TRACKING_CON1 0x1b6e 159 + #define MT6358_LDO_VSRAM_PROC12_TRACKING_CON2 0x1b70 160 + #define MT6358_LDO_VSRAM_PROC12_TRACKING_CON3 0x1b72 161 + #define MT6358_LDO_VSRAM_WAKEUP_CON0 0x1b74 162 + #define MT6358_LDO_GON1_ELR_NUM 0x1b76 163 + #define MT6358_LDO_VDRAM2_ELR0 0x1b78 164 + #define MT6358_LDO_VSRAM_PROC12_CON0 0x1b88 165 + #define MT6358_LDO_VSRAM_PROC12_DBG0 0x1ba2 166 + #define MT6358_LDO_VSRAM_PROC12_DBG1 0x1ba4 167 + #define MT6358_LDO_VSRAM_OTHERS_CON0 0x1ba6 168 + #define MT6358_LDO_VSRAM_OTHERS_DBG0 0x1bc0 169 + #define MT6358_LDO_VSRAM_OTHERS_DBG1 0x1bc2 170 + #define MT6358_LDO_VSRAM_GPU_CON0 0x1bc8 171 + #define MT6358_LDO_VSRAM_GPU_DBG0 0x1be2 172 + #define MT6358_LDO_VSRAM_GPU_DBG1 0x1be4 173 + #define MT6358_LDO_VSRAM_CON0 0x1bee 174 + #define MT6358_LDO_VSRAM_CON1 0x1bf0 175 + #define MT6358_LDO_VSRAM_CON2 0x1bf2 176 + #define MT6358_LDO_VSRAM_CON3 0x1bf4 177 + #define MT6358_LDO_VFE28_CON0 0x1c08 178 + #define MT6358_LDO_VFE28_CON1 0x1c16 179 + #define MT6358_LDO_VFE28_CON2 0x1c18 180 + #define MT6358_LDO_VFE28_CON3 0x1c1a 181 + #define MT6358_LDO_VRF18_CON0 0x1c1c 182 + #define MT6358_LDO_VRF18_CON1 0x1c2a 183 + #define MT6358_LDO_VRF18_CON2 0x1c2c 184 + #define MT6358_LDO_VRF18_CON3 0x1c2e 185 + #define MT6358_LDO_VRF12_CON0 0x1c30 186 + #define MT6358_LDO_VRF12_CON1 0x1c3e 187 + #define MT6358_LDO_VRF12_CON2 0x1c40 188 + #define MT6358_LDO_VRF12_CON3 0x1c42 189 + #define MT6358_LDO_VEFUSE_CON0 0x1c44 190 + #define MT6358_LDO_VEFUSE_CON1 0x1c52 191 + #define MT6358_LDO_VEFUSE_CON2 0x1c54 192 + #define MT6358_LDO_VEFUSE_CON3 0x1c56 193 + #define MT6358_LDO_VCN18_CON0 0x1c58 194 + #define MT6358_LDO_VCN18_CON1 0x1c66 195 + #define MT6358_LDO_VCN18_CON2 0x1c68 196 + #define MT6358_LDO_VCN18_CON3 0x1c6a 197 + #define MT6358_LDO_VCAMA1_CON0 0x1c6c 198 + #define MT6358_LDO_VCAMA1_CON1 0x1c7a 199 + #define MT6358_LDO_VCAMA1_CON2 0x1c7c 200 + #define MT6358_LDO_VCAMA1_CON3 0x1c7e 201 + #define MT6358_LDO_VCAMA2_CON0 0x1c88 202 + #define MT6358_LDO_VCAMA2_CON1 0x1c96 203 + #define MT6358_LDO_VCAMA2_CON2 0x1c98 204 + #define MT6358_LDO_VCAMA2_CON3 0x1c9a 205 + #define MT6358_LDO_VCAMD_CON0 0x1c9c 206 + #define MT6358_LDO_VCAMD_CON1 0x1caa 207 + #define MT6358_LDO_VCAMD_CON2 0x1cac 208 + #define MT6358_LDO_VCAMD_CON3 0x1cae 209 + #define MT6358_LDO_VCAMIO_CON0 0x1cb0 210 + #define MT6358_LDO_VCAMIO_CON1 0x1cbe 211 + #define MT6358_LDO_VCAMIO_CON2 0x1cc0 212 + #define MT6358_LDO_VCAMIO_CON3 0x1cc2 213 + #define MT6358_LDO_VMC_CON0 0x1cc4 214 + #define MT6358_LDO_VMC_CON1 0x1cd2 215 + #define MT6358_LDO_VMC_CON2 0x1cd4 216 + #define MT6358_LDO_VMC_CON3 0x1cd6 217 + #define MT6358_LDO_VMCH_CON0 0x1cd8 218 + #define MT6358_LDO_VMCH_CON1 0x1ce6 219 + #define MT6358_LDO_VMCH_CON2 0x1ce8 220 + #define MT6358_LDO_VMCH_CON3 0x1cea 221 + #define MT6358_LDO_VIBR_CON0 0x1d08 222 + #define MT6358_LDO_VIBR_CON1 0x1d16 223 + #define MT6358_LDO_VIBR_CON2 0x1d18 224 + #define MT6358_LDO_VIBR_CON3 0x1d1a 225 + #define MT6358_LDO_VCN33_CON0_0 0x1d1c 226 + #define MT6358_LDO_VCN33_CON0_1 0x1d2a 227 + #define MT6358_LDO_VCN33_CON1 0x1d2c 228 + #define MT6358_LDO_VCN33_BT_CON1 MT6358_LDO_VCN33_CON1 229 + #define MT6358_LDO_VCN33_WIFI_CON1 MT6358_LDO_VCN33_CON1 230 + #define MT6358_LDO_VCN33_CON2 0x1d2e 231 + #define MT6358_LDO_VCN33_CON3 0x1d30 232 + #define MT6358_LDO_VLDO28_CON0_0 0x1d32 233 + #define MT6358_LDO_VLDO28_CON0_1 0x1d40 234 + #define MT6358_LDO_VLDO28_CON1 0x1d42 235 + #define MT6358_LDO_VLDO28_CON2 0x1d44 236 + #define MT6358_LDO_VLDO28_CON3 0x1d46 237 + #define MT6358_LDO_VSIM1_CON0 0x1d48 238 + #define MT6358_LDO_VSIM1_CON1 0x1d56 239 + #define MT6358_LDO_VSIM1_CON2 0x1d58 240 + #define MT6358_LDO_VSIM1_CON3 0x1d5a 241 + #define MT6358_LDO_VSIM2_CON0 0x1d5c 242 + #define MT6358_LDO_VSIM2_CON1 0x1d6a 243 + #define MT6358_LDO_VSIM2_CON2 0x1d6c 244 + #define MT6358_LDO_VSIM2_CON3 0x1d6e 245 + #define MT6358_LDO_VCN28_CON0 0x1d88 246 + #define MT6358_LDO_VCN28_CON1 0x1d96 247 + #define MT6358_LDO_VCN28_CON2 0x1d98 248 + #define MT6358_LDO_VCN28_CON3 0x1d9a 249 + #define MT6358_VRTC28_CON0 0x1d9c 250 + #define MT6358_LDO_VBIF28_CON0 0x1d9e 251 + #define MT6358_LDO_VBIF28_CON1 0x1dac 252 + #define MT6358_LDO_VBIF28_CON2 0x1dae 253 + #define MT6358_LDO_VBIF28_CON3 0x1db0 254 + #define MT6358_VCAMA1_ANA_CON0 0x1e08 255 + #define MT6358_VCAMA2_ANA_CON0 0x1e0c 256 + #define MT6358_VCN33_ANA_CON0 0x1e28 257 + #define MT6358_VSIM1_ANA_CON0 0x1e2c 258 + #define MT6358_VSIM2_ANA_CON0 0x1e30 259 + #define MT6358_VUSB_ANA_CON0 0x1e34 260 + #define MT6358_VEMC_ANA_CON0 0x1e38 261 + #define MT6358_VLDO28_ANA_CON0 0x1e3c 262 + #define MT6358_VIO28_ANA_CON0 0x1e40 263 + #define MT6358_VIBR_ANA_CON0 0x1e44 264 + #define MT6358_VMCH_ANA_CON0 0x1e48 265 + #define MT6358_VMC_ANA_CON0 0x1e4c 266 + #define MT6358_VRF18_ANA_CON0 0x1e88 267 + #define MT6358_VCN18_ANA_CON0 0x1e8c 268 + #define MT6358_VCAMIO_ANA_CON0 0x1e90 269 + #define MT6358_VIO18_ANA_CON0 0x1e94 270 + #define MT6358_VEFUSE_ANA_CON0 0x1e98 271 + #define MT6358_VRF12_ANA_CON0 0x1e9c 272 + #define MT6358_VSRAM_PROC11_ANA_CON0 0x1ea0 273 + #define MT6358_VSRAM_PROC12_ANA_CON0 0x1ea4 274 + #define MT6358_VSRAM_OTHERS_ANA_CON0 0x1ea6 275 + #define MT6358_VSRAM_GPU_ANA_CON0 0x1ea8 276 + #define MT6358_VDRAM2_ANA_CON0 0x1eaa 277 + #define MT6358_VCAMD_ANA_CON0 0x1eae 278 + #define MT6358_VA12_ANA_CON0 0x1eb2 279 + #define MT6358_AUD_TOP_INT_CON0 0x2228 280 + #define MT6358_AUD_TOP_INT_STATUS0 0x2234 281 + 282 + #endif /* __MFD_MT6358_REGISTERS_H__ */
+5
include/linux/mfd/mt6397/core.h
··· 8 8 #define __MFD_MT6397_CORE_H__ 9 9 10 10 #include <linux/mutex.h> 11 + #include <linux/notifier.h> 11 12 12 13 enum chip_id { 13 14 MT6323_CHIP_ID = 0x23, 15 + MT6358_CHIP_ID = 0x58, 14 16 MT6391_CHIP_ID = 0x91, 15 17 MT6397_CHIP_ID = 0x97, 16 18 }; ··· 56 54 struct mt6397_chip { 57 55 struct device *dev; 58 56 struct regmap *regmap; 57 + struct notifier_block pm_nb; 59 58 int irq; 60 59 struct irq_domain *irq_domain; 61 60 struct mutex irqlock; ··· 66 63 u16 int_con[2]; 67 64 u16 int_status[2]; 68 65 u16 chip_id; 66 + void *irq_data; 69 67 }; 70 68 69 + int mt6358_irq_init(struct mt6397_chip *chip); 71 70 int mt6397_irq_init(struct mt6397_chip *chip); 72 71 73 72 #endif /* __MFD_MT6397_CORE_H__ */
+8 -1
include/linux/mfd/mt6397/rtc.h
··· 18 18 #define RTC_BBPU_CBUSY BIT(6) 19 19 #define RTC_BBPU_KEY (0x43 << 8) 20 20 21 - #define RTC_WRTGR 0x003c 21 + #define RTC_WRTGR_MT6358 0x003a 22 + #define RTC_WRTGR_MT6397 0x003c 23 + #define RTC_WRTGR_MT6323 RTC_WRTGR_MT6397 22 24 23 25 #define RTC_IRQ_STA 0x0002 24 26 #define RTC_IRQ_STA_AL BIT(0) ··· 67 65 #define MTK_RTC_POLL_DELAY_US 10 68 66 #define MTK_RTC_POLL_TIMEOUT (jiffies_to_usecs(HZ)) 69 67 68 + struct mtk_rtc_data { 69 + u32 wrtgr; 70 + }; 71 + 70 72 struct mt6397_rtc { 71 73 struct device *dev; 72 74 struct rtc_device *rtc_dev; ··· 80 74 struct regmap *regmap; 81 75 int irq; 82 76 u32 addr_base; 77 + const struct mtk_rtc_data *data; 83 78 }; 84 79 85 80 #endif /* _LINUX_MFD_MT6397_RTC_H_ */
+44
include/linux/platform_data/gsc_hwmon.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _GSC_HWMON_H 3 + #define _GSC_HWMON_H 4 + 5 + enum gsc_hwmon_mode { 6 + mode_temperature, 7 + mode_voltage, 8 + mode_voltage_raw, 9 + mode_max, 10 + }; 11 + 12 + /** 13 + * struct gsc_hwmon_channel - configuration parameters 14 + * @reg: I2C register offset 15 + * @mode: channel mode 16 + * @name: channel name 17 + * @mvoffset: voltage offset 18 + * @vdiv: voltage divider array (2 resistor values in milli-ohms) 19 + */ 20 + struct gsc_hwmon_channel { 21 + unsigned int reg; 22 + unsigned int mode; 23 + const char *name; 24 + unsigned int mvoffset; 25 + unsigned int vdiv[2]; 26 + }; 27 + 28 + /** 29 + * struct gsc_hwmon_platform_data - platform data for gsc_hwmon driver 30 + * @channels: pointer to array of gsc_hwmon_channel structures 31 + * describing channels 32 + * @nchannels: number of elements in @channels array 33 + * @vreference: voltage reference (mV) 34 + * @resolution: ADC bit resolution 35 + * @fan_base: register base for FAN controller 36 + */ 37 + struct gsc_hwmon_platform_data { 38 + const struct gsc_hwmon_channel *channels; 39 + int nchannels; 40 + unsigned int resolution; 41 + unsigned int vreference; 42 + unsigned int fan_base; 43 + }; 44 + #endif