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

Merge tag 'regulator-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
"The biggest set of changes in here is the addition of the Qualcomm
RPMH driver. As well as the regualtor driver itself being quite large
due to the usual involved Qualcomm regulator stuff there's also some
code shared with the arm-soc tree, a bus driver required to
communicate with the hardware that actually winds up being much larger
than the regulator driver itself and a LLCC driver that was part of
the same signed tag used with the arm-soc tree.

Other than that it's a fairly standard and quiet release, highlights
include:

- Addition of device links from regulator consumers to their
regulators, helping the core avoid dependency issues during
suspend.

- Support for the entertainingly innovative suspend implementation in
the BD9571MWV.

- Support for switch regulators on the PFUZE100, this required two
goes due to backwards compatibility issues with old DTs that were
discovered.

- Support for Freescale PFUZE3001 and SocioNext UniPhier.

- The aforementioned Qualcomm RPMH driver together with the driver
changes required to support it"

* tag 'regulator-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (52 commits)
regulator: add QCOM RPMh regulator driver
regulator: dt-bindings: add QCOM RPMh regulator bindings
regulator: samsung: Add SPDX license identifiers
regulator: maxim: Add SPDX license identifiers
regulator: bd71837: adobt MFD changes to regulator driver
regulator: tps65217: Fix NULL pointer dereference on probe
regulator: Add support for CPCAP regulators on Motorola Xoom devices.
regulator: Add sw2_sw4 voltage table to cpcap regulator.
regulator: bd9571mwv: Make symbol 'dev_attr_backup_mode' static
regulator: pfuze100: add support to en-/disable switch regulators
regulator: pfuze100: add optional disable switch-regulators binding
soc: qcom: rmtfs-mem: fix memleak in probe error paths
soc: qcom: llc-slice: Add missing MODULE_LICENSE()
drivers: qcom: rpmh: fix unwanted error check for get_tcs_of_type()
drivers: qcom: rpmh-rsc: fix the loop index check in get_req_from_tcs
firmware: qcom: scm: add a dummy qcom_scm_assign_mem()
drivers: qcom: rpmh-rsc: Check cmd_db_ready() to help children
drivers: qcom: rpmh-rsc: allow active requests from wake TCS
drivers: qcom: rpmh: add support for batch RPMH request
drivers: qcom: rpmh: allow requests to be sent asynchronously
...

+4186 -271
+27
Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator
··· 1 + What: /sys/bus/i2c/devices/.../bd9571mwv-regulator.*.auto/backup_mode 2 + Date: Jul 2018 3 + KernelVersion: 4.19 4 + Contact: Geert Uytterhoeven <geert+renesas@glider.be> 5 + Description: Read/write the current state of DDR Backup Mode, which controls 6 + if DDR power rails will be kept powered during system suspend. 7 + ("on"/"1" = enabled, "off"/"0" = disabled). 8 + Two types of power switches (or control signals) can be used: 9 + A. With a momentary power switch (or pulse signal), DDR 10 + Backup Mode is enabled by default when available, as the 11 + PMIC will be configured only during system suspend. 12 + B. With a toggle power switch (or level signal), the 13 + following steps must be followed exactly: 14 + 1. Configure PMIC for backup mode, to change the role of 15 + the accessory power switch from a power switch to a 16 + wake-up switch, 17 + 2. Switch accessory power switch off, to prepare for 18 + system suspend, which is a manual step not controlled 19 + by software, 20 + 3. Suspend system, 21 + 4. Switch accessory power switch on, to resume the 22 + system. 23 + DDR Backup Mode must be explicitly enabled by the user, 24 + to invoke step 1. 25 + See also Documentation/devicetree/bindings/mfd/bd9571mwv.txt. 26 + Users: User space applications for embedded boards equipped with a 27 + BD9571MWV PMIC.
+26
Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
··· 1 + == Introduction== 2 + 3 + LLCC (Last Level Cache Controller) provides last level of cache memory in SOC, 4 + that can be shared by multiple clients. Clients here are different cores in the 5 + SOC, the idea is to minimize the local caches at the clients and migrate to 6 + common pool of memory. Cache memory is divided into partitions called slices 7 + which are assigned to clients. Clients can query the slice details, activate 8 + and deactivate them. 9 + 10 + Properties: 11 + - compatible: 12 + Usage: required 13 + Value type: <string> 14 + Definition: must be "qcom,sdm845-llcc" 15 + 16 + - reg: 17 + Usage: required 18 + Value Type: <prop-encoded-array> 19 + Definition: Start address and the the size of the register region. 20 + 21 + Example: 22 + 23 + cache-controller@1100000 { 24 + compatible = "qcom,sdm845-llcc"; 25 + reg = <0x1100000 0x250000>; 26 + };
+1
Documentation/devicetree/bindings/regulator/cpcap-regulator.txt
··· 5 5 - "compatible" value one of: 6 6 "motorola,cpcap-regulator" 7 7 "motorola,mapphone-cpcap-regulator" 8 + "motorola,xoom-cpcap-regulator" 8 9 9 10 Required regulator properties: 10 11 - "regulator-name"
+85 -1
Documentation/devicetree/bindings/regulator/pfuze100.txt
··· 1 1 PFUZE100 family of regulators 2 2 3 3 Required properties: 4 - - compatible: "fsl,pfuze100", "fsl,pfuze200", "fsl,pfuze3000" 4 + - compatible: "fsl,pfuze100", "fsl,pfuze200", "fsl,pfuze3000", "fsl,pfuze3001" 5 5 - reg: I2C slave address 6 + 7 + Optional properties: 8 + - fsl,pfuze-support-disable-sw: Boolean, if present disable all unused switch 9 + regulators to save power consumption. Attention, ensure that all important 10 + regulators (e.g. DDR ref, DDR supply) has set the "regulator-always-on" 11 + property. If not present, the switched regualtors are always on and can't be 12 + disabled. This binding is a workaround to keep backward compatibility with 13 + old dtb's which rely on the fact that the switched regulators are always on 14 + and don't mark them explicit as "regulator-always-on". 6 15 7 16 Required child node: 8 17 - regulators: This is the list of child nodes that specify the regulator ··· 25 16 sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6,coin 26 17 --PFUZE3000 27 18 sw1a,sw1b,sw2,sw3,swbst,vsnvs,vrefddr,vldo1,vldo2,vccsd,v33,vldo3,vldo4 19 + --PFUZE3001 20 + sw1,sw2,sw3,vsnvs,vldo1,vldo2,vccsd,v33,vldo3,vldo4 28 21 29 22 Each regulator is defined using the standard binding for regulators. 30 23 ··· 299 288 vgen4_reg: v33 { 300 289 regulator-min-microvolt = <2850000>; 301 290 regulator-max-microvolt = <3300000>; 291 + }; 292 + 293 + vgen5_reg: vldo3 { 294 + regulator-min-microvolt = <1800000>; 295 + regulator-max-microvolt = <3300000>; 296 + regulator-always-on; 297 + }; 298 + 299 + vgen6_reg: vldo4 { 300 + regulator-min-microvolt = <1800000>; 301 + regulator-max-microvolt = <3300000>; 302 + regulator-always-on; 303 + }; 304 + }; 305 + }; 306 + 307 + Example 4: PFUZE 3001 308 + 309 + pfuze3001: pmic@8 { 310 + compatible = "fsl,pfuze3001"; 311 + reg = <0x08>; 312 + 313 + regulators { 314 + sw1_reg: sw1 { 315 + regulator-min-microvolt = <700000>; 316 + regulator-max-microvolt = <3300000>; 317 + regulator-boot-on; 318 + regulator-always-on; 319 + }; 320 + 321 + sw2_reg: sw2 { 322 + regulator-min-microvolt = <1500000>; 323 + regulator-max-microvolt = <3300000>; 324 + regulator-boot-on; 325 + regulator-always-on; 326 + }; 327 + 328 + sw3_reg: sw3 { 329 + regulator-min-microvolt = <900000>; 330 + regulator-max-microvolt = <1650000>; 331 + regulator-boot-on; 332 + regulator-always-on; 333 + }; 334 + 335 + snvs_reg: vsnvs { 336 + regulator-min-microvolt = <1000000>; 337 + regulator-max-microvolt = <3000000>; 338 + regulator-boot-on; 339 + regulator-always-on; 340 + }; 341 + 342 + vgen1_reg: vldo1 { 343 + regulator-min-microvolt = <1800000>; 344 + regulator-max-microvolt = <3300000>; 345 + regulator-always-on; 346 + }; 347 + 348 + vgen2_reg: vldo2 { 349 + regulator-min-microvolt = <800000>; 350 + regulator-max-microvolt = <1550000>; 351 + regulator-always-on; 352 + }; 353 + 354 + vgen3_reg: vccsd { 355 + regulator-min-microvolt = <2850000>; 356 + regulator-max-microvolt = <3300000>; 357 + regulator-always-on; 358 + }; 359 + 360 + vgen4_reg: v33 { 361 + regulator-min-microvolt = <2850000>; 362 + regulator-max-microvolt = <3300000>; 363 + regulator-always-on; 302 364 }; 303 365 304 366 vgen5_reg: vldo3 {
+160
Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
··· 1 + Qualcomm Technologies, Inc. RPMh Regulators 2 + 3 + rpmh-regulator devices support PMIC regulator management via the Voltage 4 + Regulator Manager (VRM) and Oscillator Buffer (XOB) RPMh accelerators. The APPS 5 + processor communicates with these hardware blocks via a Resource State 6 + Coordinator (RSC) using command packets. The VRM allows changing three 7 + parameters for a given regulator: enable state, output voltage, and operating 8 + mode. The XOB allows changing only a single parameter for a given regulator: 9 + its enable state. Despite its name, the XOB is capable of controlling the 10 + enable state of any PMIC peripheral. It is used for clock buffers, low-voltage 11 + switches, and LDO/SMPS regulators which have a fixed voltage and mode. 12 + 13 + ======================= 14 + Required Node Structure 15 + ======================= 16 + 17 + RPMh regulators must be described in two levels of device nodes. The first 18 + level describes the PMIC containing the regulators and must reside within an 19 + RPMh device node. The second level describes each regulator within the PMIC 20 + which is to be used on the board. Each of these regulators maps to a single 21 + RPMh resource. 22 + 23 + The names used for regulator nodes must match those supported by a given PMIC. 24 + Supported regulator node names: 25 + PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 26 + PMI8998: bob 27 + PM8005: smps1 - smps4 28 + 29 + ======================== 30 + First Level Nodes - PMIC 31 + ======================== 32 + 33 + - compatible 34 + Usage: required 35 + Value type: <string> 36 + Definition: Must be one of: "qcom,pm8998-rpmh-regulators", 37 + "qcom,pmi8998-rpmh-regulators" or 38 + "qcom,pm8005-rpmh-regulators". 39 + 40 + - qcom,pmic-id 41 + Usage: required 42 + Value type: <string> 43 + Definition: RPMh resource name suffix used for the regulators found on 44 + this PMIC. Typical values: "a", "b", "c", "d", "e", "f". 45 + 46 + - vdd-s1-supply 47 + - vdd-s2-supply 48 + - vdd-s3-supply 49 + - vdd-s4-supply 50 + Usage: optional (PM8998 and PM8005 only) 51 + Value type: <phandle> 52 + Definition: phandle of the parent supply regulator of one or more of the 53 + regulators for this PMIC. 54 + 55 + - vdd-s5-supply 56 + - vdd-s6-supply 57 + - vdd-s7-supply 58 + - vdd-s8-supply 59 + - vdd-s9-supply 60 + - vdd-s10-supply 61 + - vdd-s11-supply 62 + - vdd-s12-supply 63 + - vdd-s13-supply 64 + - vdd-l1-l27-supply 65 + - vdd-l2-l8-l17-supply 66 + - vdd-l3-l11-supply 67 + - vdd-l4-l5-supply 68 + - vdd-l6-supply 69 + - vdd-l7-l12-l14-l15-supply 70 + - vdd-l9-supply 71 + - vdd-l10-l23-l25-supply 72 + - vdd-l13-l19-l21-supply 73 + - vdd-l16-l28-supply 74 + - vdd-l18-l22-supply 75 + - vdd-l20-l24-supply 76 + - vdd-l26-supply 77 + - vin-lvs-1-2-supply 78 + Usage: optional (PM8998 only) 79 + Value type: <phandle> 80 + Definition: phandle of the parent supply regulator of one or more of the 81 + regulators for this PMIC. 82 + 83 + - vdd-bob-supply 84 + Usage: optional (PMI8998 only) 85 + Value type: <phandle> 86 + Definition: BOB regulator parent supply phandle 87 + 88 + =============================== 89 + Second Level Nodes - Regulators 90 + =============================== 91 + 92 + - qcom,always-wait-for-ack 93 + Usage: optional 94 + Value type: <empty> 95 + Definition: Boolean flag which indicates that the application processor 96 + must wait for an ACK or a NACK from RPMh for every request 97 + sent for this regulator including those which are for a 98 + strictly lower power state. 99 + 100 + Other properties defined in Documentation/devicetree/bindings/regulator.txt 101 + may also be used. regulator-initial-mode and regulator-allowed-modes may be 102 + specified for VRM regulators using mode values from 103 + include/dt-bindings/regulator/qcom,rpmh-regulator.h. regulator-allow-bypass 104 + may be specified for BOB type regulators managed via VRM. 105 + regulator-allow-set-load may be specified for LDO type regulators managed via 106 + VRM. 107 + 108 + ======== 109 + Examples 110 + ======== 111 + 112 + #include <dt-bindings/regulator/qcom,rpmh-regulator.h> 113 + 114 + &apps_rsc { 115 + pm8998-rpmh-regulators { 116 + compatible = "qcom,pm8998-rpmh-regulators"; 117 + qcom,pmic-id = "a"; 118 + 119 + vdd-l7-l12-l14-l15-supply = <&pm8998_s5>; 120 + 121 + smps2 { 122 + regulator-min-microvolt = <1100000>; 123 + regulator-max-microvolt = <1100000>; 124 + }; 125 + 126 + pm8998_s5: smps5 { 127 + regulator-min-microvolt = <1904000>; 128 + regulator-max-microvolt = <2040000>; 129 + }; 130 + 131 + ldo7 { 132 + regulator-min-microvolt = <1800000>; 133 + regulator-max-microvolt = <1800000>; 134 + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; 135 + regulator-allowed-modes = 136 + <RPMH_REGULATOR_MODE_LPM 137 + RPMH_REGULATOR_MODE_HPM>; 138 + regulator-allow-set-load; 139 + }; 140 + 141 + lvs1 { 142 + regulator-min-microvolt = <1800000>; 143 + regulator-max-microvolt = <1800000>; 144 + }; 145 + }; 146 + 147 + pmi8998-rpmh-regulators { 148 + compatible = "qcom,pmi8998-rpmh-regulators"; 149 + qcom,pmic-id = "b"; 150 + 151 + bob { 152 + regulator-min-microvolt = <3312000>; 153 + regulator-max-microvolt = <3600000>; 154 + regulator-allowed-modes = 155 + <RPMH_REGULATOR_MODE_AUTO 156 + RPMH_REGULATOR_MODE_HPM>; 157 + regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>; 158 + }; 159 + }; 160 + };
-8
Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt
··· 1 1 ROHM BD71837 Power Management Integrated Circuit (PMIC) regulator bindings 2 2 3 - BD71837MWV is a programmable Power Management 4 - IC (PMIC) for powering single-core, dual-core, and 5 - quad-core SoC’s such as NXP-i.MX 8M. It is optimized 6 - for low BOM cost and compact solution footprint. It 7 - integrates 8 Buck regulators and 7 LDO’s to provide all 8 - the power rails required by the SoC and the commonly 9 - used peripherals. 10 - 11 3 Required properties: 12 4 - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" 13 5
+57
Documentation/devicetree/bindings/regulator/uniphier-regulator.txt
··· 1 + Socionext UniPhier Regulator Controller 2 + 3 + This describes the devicetree bindings for regulator controller implemented 4 + on Socionext UniPhier SoCs. 5 + 6 + USB3 Controller 7 + --------------- 8 + 9 + This regulator controls VBUS and belongs to USB3 glue layer. Before using 10 + the regulator, it is necessary to control the clocks and resets to enable 11 + this layer. These clocks and resets should be described in each property. 12 + 13 + Required properties: 14 + - compatible: Should be 15 + "socionext,uniphier-pro4-usb3-regulator" - for Pro4 SoC 16 + "socionext,uniphier-pxs2-usb3-regulator" - for PXs2 SoC 17 + "socionext,uniphier-ld20-usb3-regulator" - for LD20 SoC 18 + "socionext,uniphier-pxs3-usb3-regulator" - for PXs3 SoC 19 + - reg: Specifies offset and length of the register set for the device. 20 + - clocks: A list of phandles to the clock gate for USB3 glue layer. 21 + According to the clock-names, appropriate clocks are required. 22 + - clock-names: Should contain 23 + "gio", "link" - for Pro4 SoC 24 + "link" - for others 25 + - resets: A list of phandles to the reset control for USB3 glue layer. 26 + According to the reset-names, appropriate resets are required. 27 + - reset-names: Should contain 28 + "gio", "link" - for Pro4 SoC 29 + "link" - for others 30 + 31 + See Documentation/devicetree/bindings/regulator/regulator.txt 32 + for more details about the regulator properties. 33 + 34 + Example: 35 + 36 + usb-glue@65b00000 { 37 + compatible = "socionext,uniphier-ld20-dwc3-glue", 38 + "simple-mfd"; 39 + #address-cells = <1>; 40 + #size-cells = <1>; 41 + ranges = <0 0x65b00000 0x400>; 42 + 43 + usb_vbus0: regulators@100 { 44 + compatible = "socionext,uniphier-ld20-usb3-regulator"; 45 + reg = <0x100 0x10>; 46 + clock-names = "link"; 47 + clocks = <&sys_clk 14>; 48 + reset-names = "link"; 49 + resets = <&sys_rst 14>; 50 + }; 51 + 52 + phy { 53 + ... 54 + phy-supply = <&usb_vbus0>; 55 + }; 56 + ... 57 + };
+137
Documentation/devicetree/bindings/soc/qcom/rpmh-rsc.txt
··· 1 + RPMH RSC: 2 + ------------ 3 + 4 + Resource Power Manager Hardened (RPMH) is the mechanism for communicating with 5 + the hardened resource accelerators on Qualcomm SoCs. Requests to the resources 6 + can be written to the Trigger Command Set (TCS) registers and using a (addr, 7 + val) pair and triggered. Messages in the TCS are then sent in sequence over an 8 + internal bus. 9 + 10 + The hardware block (Direct Resource Voter or DRV) is a part of the h/w entity 11 + (Resource State Coordinator a.k.a RSC) that can handle multiple sleep and 12 + active/wake resource requests. Multiple such DRVs can exist in a SoC and can 13 + be written to from Linux. The structure of each DRV follows the same template 14 + with a few variations that are captured by the properties here. 15 + 16 + A TCS may be triggered from Linux or triggered by the F/W after all the CPUs 17 + have powered off to facilitate idle power saving. TCS could be classified as - 18 + 19 + ACTIVE /* Triggered by Linux */ 20 + SLEEP /* Triggered by F/W */ 21 + WAKE /* Triggered by F/W */ 22 + CONTROL /* Triggered by F/W */ 23 + 24 + The order in which they are described in the DT, should match the hardware 25 + configuration. 26 + 27 + Requests can be made for the state of a resource, when the subsystem is active 28 + or idle. When all subsystems like Modem, GPU, CPU are idle, the resource state 29 + will be an aggregate of the sleep votes from each of those subsystems. Clients 30 + may request a sleep value for their shared resources in addition to the active 31 + mode requests. 32 + 33 + Properties: 34 + 35 + - compatible: 36 + Usage: required 37 + Value type: <string> 38 + Definition: Should be "qcom,rpmh-rsc". 39 + 40 + - reg: 41 + Usage: required 42 + Value type: <prop-encoded-array> 43 + Definition: The first register specifies the base address of the 44 + DRV(s). The number of DRVs in the dependent on the RSC. 45 + The tcs-offset specifies the start address of the 46 + TCS in the DRVs. 47 + 48 + - reg-names: 49 + Usage: required 50 + Value type: <string> 51 + Definition: Maps the register specified in the reg property. Must be 52 + "drv-0", "drv-1", "drv-2" etc and "tcs-offset". The 53 + 54 + - interrupts: 55 + Usage: required 56 + Value type: <prop-encoded-interrupt> 57 + Definition: The interrupt that trips when a message complete/response 58 + is received for this DRV from the accelerators. 59 + 60 + - qcom,drv-id: 61 + Usage: required 62 + Value type: <u32> 63 + Definition: The id of the DRV in the RSC block that will be used by 64 + this controller. 65 + 66 + - qcom,tcs-config: 67 + Usage: required 68 + Value type: <prop-encoded-array> 69 + Definition: The tuple defining the configuration of TCS. 70 + Must have 2 cells which describe each TCS type. 71 + <type number_of_tcs>. 72 + The order of the TCS must match the hardware 73 + configuration. 74 + - Cell #1 (TCS Type): TCS types to be specified - 75 + ACTIVE_TCS 76 + SLEEP_TCS 77 + WAKE_TCS 78 + CONTROL_TCS 79 + - Cell #2 (Number of TCS): <u32> 80 + 81 + - label: 82 + Usage: optional 83 + Value type: <string> 84 + Definition: Name for the RSC. The name would be used in trace logs. 85 + 86 + Drivers that want to use the RSC to communicate with RPMH must specify their 87 + bindings as child nodes of the RSC controllers they wish to communicate with. 88 + 89 + Example 1: 90 + 91 + For a TCS whose RSC base address is is 0x179C0000 and is at a DRV id of 2, the 92 + register offsets for DRV2 start at 0D00, the register calculations are like 93 + this - 94 + DRV0: 0x179C0000 95 + DRV2: 0x179C0000 + 0x10000 = 0x179D0000 96 + DRV2: 0x179C0000 + 0x10000 * 2 = 0x179E0000 97 + TCS-OFFSET: 0xD00 98 + 99 + apps_rsc: rsc@179c0000 { 100 + label = "apps_rsc"; 101 + compatible = "qcom,rpmh-rsc"; 102 + reg = <0x179c0000 0x10000>, 103 + <0x179d0000 0x10000>, 104 + <0x179e0000 0x10000>; 105 + reg-names = "drv-0", "drv-1", "drv-2"; 106 + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, 107 + <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, 108 + <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; 109 + qcom,tcs-offset = <0xd00>; 110 + qcom,drv-id = <2>; 111 + qcom,tcs-config = <ACTIVE_TCS 2>, 112 + <SLEEP_TCS 3>, 113 + <WAKE_TCS 3>, 114 + <CONTROL_TCS 1>; 115 + }; 116 + 117 + Example 2: 118 + 119 + For a TCS whose RSC base address is 0xAF20000 and is at DRV id of 0, the 120 + register offsets for DRV0 start at 01C00, the register calculations are like 121 + this - 122 + DRV0: 0xAF20000 123 + TCS-OFFSET: 0x1C00 124 + 125 + disp_rsc: rsc@af20000 { 126 + label = "disp_rsc"; 127 + compatible = "qcom,rpmh-rsc"; 128 + reg = <0xaf20000 0x10000>; 129 + reg-names = "drv-0"; 130 + interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>; 131 + qcom,tcs-offset = <0x1c00>; 132 + qcom,drv-id = <0>; 133 + qcom,tcs-config = <ACTIVE_TCS 0>, 134 + <SLEEP_TCS 1>, 135 + <WAKE_TCS 1>, 136 + <CONTROL_TCS 0>; 137 + };
+30
drivers/base/core.c
··· 372 372 } 373 373 EXPORT_SYMBOL_GPL(device_link_del); 374 374 375 + /** 376 + * device_link_remove - remove a link between two devices. 377 + * @consumer: Consumer end of the link. 378 + * @supplier: Supplier end of the link. 379 + * 380 + * The caller must ensure proper synchronization of this function with runtime 381 + * PM. 382 + */ 383 + void device_link_remove(void *consumer, struct device *supplier) 384 + { 385 + struct device_link *link; 386 + 387 + if (WARN_ON(consumer == supplier)) 388 + return; 389 + 390 + device_links_write_lock(); 391 + device_pm_lock(); 392 + 393 + list_for_each_entry(link, &supplier->links.consumers, s_node) { 394 + if (link->consumer == consumer) { 395 + kref_put(&link->kref, __device_link_del); 396 + break; 397 + } 398 + } 399 + 400 + device_pm_unlock(); 401 + device_links_write_unlock(); 402 + } 403 + EXPORT_SYMBOL_GPL(device_link_remove); 404 + 375 405 static void device_links_missing_supplier(struct device *dev) 376 406 { 377 407 struct device_link *link;
+21 -4
drivers/regulator/Kconfig
··· 180 180 BCM590xx PMUs. This will enable support for the software 181 181 controllable LDO/Switching regulators. 182 182 183 - config REGULATOR_BD71837 183 + config REGULATOR_BD718XX 184 184 tristate "ROHM BD71837 Power Regulator" 185 - depends on MFD_BD71837 185 + depends on MFD_ROHM_BD718XX 186 186 help 187 187 This driver supports voltage regulators on ROHM BD71837 PMIC. 188 188 This will enable support for the software controllable buck ··· 633 633 on PCF50633 634 634 635 635 config REGULATOR_PFUZE100 636 - tristate "Freescale PFUZE100/200/3000 regulator driver" 636 + tristate "Freescale PFUZE100/200/3000/3001 regulator driver" 637 637 depends on I2C 638 638 select REGMAP_I2C 639 639 help 640 640 Say y here to support the regulators found on the Freescale 641 - PFUZE100/200/3000 PMIC. 641 + PFUZE100/200/3000/3001 PMIC. 642 642 643 643 config REGULATOR_PV88060 644 644 tristate "Powerventure Semiconductor PV88060 regulator" ··· 681 681 Say M here if you want to include support for the regulators on the 682 682 Qualcomm RPM as a module. The module will be named 683 683 "qcom_rpm-regulator". 684 + 685 + config REGULATOR_QCOM_RPMH 686 + tristate "Qualcomm Technologies, Inc. RPMh regulator driver" 687 + depends on QCOM_RPMH || COMPILE_TEST 688 + help 689 + This driver supports control of PMIC regulators via the RPMh hardware 690 + block found on Qualcomm Technologies Inc. SoCs. RPMh regulator 691 + control allows for voting on regulator state between multiple 692 + processors within the SoC. 684 693 685 694 config REGULATOR_QCOM_SMD_RPM 686 695 tristate "Qualcomm SMD based RPM regulator driver" ··· 958 949 help 959 950 This driver supports the voltage regulators provided by 960 951 this family of companion chips. 952 + 953 + config REGULATOR_UNIPHIER 954 + tristate "UniPhier regulator driver" 955 + depends on ARCH_UNIPHIER || COMPILE_TEST 956 + depends on OF && MFD_SYSCON 957 + default ARCH_UNIPHIER 958 + help 959 + Support for regulators implemented on Socionext UniPhier SoCs. 961 960 962 961 config REGULATOR_VCTRL 963 962 tristate "Voltage controlled regulators"
+3 -1
drivers/regulator/Makefile
··· 27 27 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o 28 28 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o 29 29 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o 30 - obj-$(CONFIG_REGULATOR_BD71837) += bd71837-regulator.o 30 + obj-$(CONFIG_REGULATOR_BD718XX) += bd71837-regulator.o 31 31 obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o 32 32 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o 33 33 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o ··· 78 78 obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o 79 79 obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o 80 80 obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o 81 + obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o 81 82 obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o 82 83 obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o 83 84 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o ··· 119 118 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o 120 119 obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o 121 120 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o 121 + obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o 122 122 obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o 123 123 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o 124 124 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
+24 -3
drivers/regulator/arizona-ldo1.c
··· 36 36 37 37 struct regulator_consumer_supply supply; 38 38 struct regulator_init_data init_data; 39 + 40 + struct gpio_desc *ena_gpiod; 39 41 }; 40 42 41 43 static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, ··· 255 253 } 256 254 } 257 255 258 - /* We assume that high output = regulator off */ 259 - config.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, "wlf,ldoena", 260 - GPIOD_OUT_HIGH); 256 + /* We assume that high output = regulator off 257 + * Don't use devm, since we need to get against the parent device 258 + * so clean up would happen at the wrong time 259 + */ 260 + config.ena_gpiod = gpiod_get_optional(parent_dev, "wlf,ldoena", 261 + GPIOD_OUT_LOW); 261 262 if (IS_ERR(config.ena_gpiod)) 262 263 return PTR_ERR(config.ena_gpiod); 264 + 265 + ldo1->ena_gpiod = config.ena_gpiod; 263 266 264 267 if (pdata->init_data) 265 268 config.init_data = pdata->init_data; ··· 283 276 of_node_put(config.of_node); 284 277 285 278 if (IS_ERR(ldo1->regulator)) { 279 + if (config.ena_gpiod) 280 + gpiod_put(config.ena_gpiod); 281 + 286 282 ret = PTR_ERR(ldo1->regulator); 287 283 dev_err(&pdev->dev, "Failed to register LDO1 supply: %d\n", 288 284 ret); ··· 344 334 return ret; 345 335 } 346 336 337 + static int arizona_ldo1_remove(struct platform_device *pdev) 338 + { 339 + struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev); 340 + 341 + if (ldo1->ena_gpiod) 342 + gpiod_put(ldo1->ena_gpiod); 343 + 344 + return 0; 345 + } 346 + 347 347 static struct platform_driver arizona_ldo1_driver = { 348 348 .probe = arizona_ldo1_probe, 349 + .remove = arizona_ldo1_remove, 349 350 .driver = { 350 351 .name = "arizona-ldo1", 351 352 },
+14 -28
drivers/regulator/bd71837-regulator.c
··· 2 2 // Copyright (C) 2018 ROHM Semiconductors 3 3 // bd71837-regulator.c ROHM BD71837MWV regulator driver 4 4 5 - #include <linux/kernel.h> 6 - #include <linux/module.h> 7 - #include <linux/init.h> 5 + #include <linux/delay.h> 8 6 #include <linux/err.h> 7 + #include <linux/gpio.h> 9 8 #include <linux/interrupt.h> 9 + #include <linux/kernel.h> 10 + #include <linux/mfd/rohm-bd718x7.h> 11 + #include <linux/module.h> 10 12 #include <linux/platform_device.h> 11 13 #include <linux/regulator/driver.h> 12 14 #include <linux/regulator/machine.h> 13 - #include <linux/delay.h> 14 - #include <linux/slab.h> 15 - #include <linux/gpio.h> 16 - #include <linux/mfd/bd71837.h> 17 15 #include <linux/regulator/of_regulator.h> 16 + #include <linux/slab.h> 18 17 19 18 struct bd71837_pmic { 20 19 struct regulator_desc descs[BD71837_REGULATOR_CNT]; ··· 38 39 int id = rdev->desc->id; 39 40 unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; 40 41 41 - dev_dbg(&(pmic->pdev->dev), "Buck[%d] Set Ramp = %d\n", id + 1, 42 + dev_dbg(&pmic->pdev->dev, "Buck[%d] Set Ramp = %d\n", id + 1, 42 43 ramp_delay); 43 44 switch (ramp_delay) { 44 45 case 1 ... 1250: ··· 72 73 static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, 73 74 unsigned int sel) 74 75 { 75 - int ret; 76 + if (regulator_is_enabled_regmap(rdev)) 77 + return -EBUSY; 76 78 77 - ret = regulator_is_enabled_regmap(rdev); 78 - if (!ret) 79 - ret = regulator_set_voltage_sel_regmap(rdev, sel); 80 - else if (ret == 1) 81 - ret = -EBUSY; 82 - return ret; 79 + return regulator_set_voltage_sel_regmap(rdev, sel); 83 80 } 84 81 85 82 static struct regulator_ops bd71837_ldo_regulator_ops = { ··· 190 195 * LDO2 191 196 * 0.8 or 0.9V 192 197 */ 193 - const unsigned int ldo_2_volts[] = { 198 + static const unsigned int ldo_2_volts[] = { 194 199 900000, 800000 195 200 }; 196 201 ··· 490 495 static int bd71837_probe(struct platform_device *pdev) 491 496 { 492 497 struct bd71837_pmic *pmic; 493 - struct bd71837_board *pdata; 494 498 struct regulator_config config = { 0 }; 495 499 struct reg_init pmic_regulator_inits[] = { 496 500 { ··· 542 548 543 549 int i, err; 544 550 545 - pmic = devm_kzalloc(&pdev->dev, sizeof(struct bd71837_pmic), 546 - GFP_KERNEL); 551 + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 547 552 if (!pmic) 548 553 return -ENOMEM; 549 554 ··· 557 564 goto err; 558 565 } 559 566 platform_set_drvdata(pdev, pmic); 560 - pdata = dev_get_platdata(pmic->mfd->dev); 561 567 562 568 /* Register LOCK release */ 563 569 err = regmap_update_bits(pmic->mfd->regmap, BD71837_REG_REGLOCK, ··· 565 573 dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); 566 574 goto err; 567 575 } else { 568 - dev_dbg(&pmic->pdev->dev, "%s: Unlocked lock register 0x%x\n", 569 - __func__, BD71837_REG_REGLOCK); 576 + dev_dbg(&pmic->pdev->dev, "Unlocked lock register 0x%x\n", 577 + BD71837_REG_REGLOCK); 570 578 } 571 579 572 580 for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { ··· 575 583 struct regulator_dev *rdev; 576 584 577 585 desc = &pmic->descs[i]; 578 - 579 - if (pdata) 580 - config.init_data = pdata->init_data[i]; 581 586 582 587 config.dev = pdev->dev.parent; 583 588 config.driver_data = pmic; ··· 608 619 pmic->rdev[i] = rdev; 609 620 } 610 621 611 - return 0; 612 - 613 622 err: 614 623 return err; 615 624 } ··· 615 628 static struct platform_driver bd71837_regulator = { 616 629 .driver = { 617 630 .name = "bd71837-pmic", 618 - .owner = THIS_MODULE, 619 631 }, 620 632 .probe = bd71837_probe, 621 633 };
+67 -5
drivers/regulator/bd9571mwv-regulator.c
··· 30 30 /* DDR Backup Power */ 31 31 u8 bkup_mode_cnt_keepon; /* from "rohm,ddr-backup-power" */ 32 32 u8 bkup_mode_cnt_saved; 33 + bool bkup_mode_enabled; 33 34 34 35 /* Power switch type */ 35 36 bool rstbmode_level; ··· 172 171 return 0; 173 172 } 174 173 174 + static ssize_t backup_mode_show(struct device *dev, 175 + struct device_attribute *attr, char *buf) 176 + { 177 + struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); 178 + 179 + return sprintf(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off"); 180 + } 181 + 182 + static ssize_t backup_mode_store(struct device *dev, 183 + struct device_attribute *attr, 184 + const char *buf, size_t count) 185 + { 186 + struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); 187 + unsigned int mode; 188 + int ret; 189 + 190 + if (!count) 191 + return 0; 192 + 193 + ret = kstrtobool(buf, &bdreg->bkup_mode_enabled); 194 + if (ret) 195 + return ret; 196 + 197 + if (!bdreg->rstbmode_level) 198 + return count; 199 + 200 + /* 201 + * Configure DDR Backup Mode, to change the role of the accessory power 202 + * switch from a power switch to a wake-up switch, or vice versa 203 + */ 204 + ret = bd9571mwv_bkup_mode_read(bdreg->bd, &mode); 205 + if (ret) 206 + return ret; 207 + 208 + mode &= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK; 209 + if (bdreg->bkup_mode_enabled) 210 + mode |= bdreg->bkup_mode_cnt_keepon; 211 + 212 + ret = bd9571mwv_bkup_mode_write(bdreg->bd, mode); 213 + if (ret) 214 + return ret; 215 + 216 + return count; 217 + } 218 + 219 + static DEVICE_ATTR_RW(backup_mode); 220 + 175 221 static int bd9571mwv_suspend(struct device *dev) 176 222 { 177 223 struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); 178 224 unsigned int mode; 179 225 int ret; 180 226 181 - if (!device_may_wakeup(dev)) 227 + if (!bdreg->bkup_mode_enabled) 182 228 return 0; 183 229 184 230 /* Save DDR Backup Mode */ ··· 252 204 { 253 205 struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); 254 206 255 - if (!device_may_wakeup(dev)) 207 + if (!bdreg->bkup_mode_enabled) 256 208 return 0; 257 209 258 210 /* Restore DDR Backup Mode */ ··· 263 215 SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend, bd9571mwv_resume) 264 216 }; 265 217 218 + static int bd9571mwv_regulator_remove(struct platform_device *pdev) 219 + { 220 + device_remove_file(&pdev->dev, &dev_attr_backup_mode); 221 + return 0; 222 + } 266 223 #define DEV_PM_OPS &bd9571mwv_pm 267 224 #else 268 225 #define DEV_PM_OPS NULL 226 + #define bd9571mwv_regulator_remove NULL 269 227 #endif /* CONFIG_PM_SLEEP */ 270 228 271 229 static int bd9571mwv_regulator_probe(struct platform_device *pdev) ··· 324 270 return -EINVAL; 325 271 } 326 272 273 + #ifdef CONFIG_PM_SLEEP 327 274 if (bdreg->bkup_mode_cnt_keepon) { 328 - device_set_wakeup_capable(&pdev->dev, true); 275 + int ret; 276 + 329 277 /* 330 - * Wakeup is enabled by default in pulse mode, but needs 278 + * Backup mode is enabled by default in pulse mode, but needs 331 279 * explicit user setup in level mode. 332 280 */ 333 - device_set_wakeup_enable(&pdev->dev, bdreg->rstbmode_pulse); 281 + bdreg->bkup_mode_enabled = bdreg->rstbmode_pulse; 282 + 283 + ret = device_create_file(&pdev->dev, &dev_attr_backup_mode); 284 + if (ret) 285 + return ret; 334 286 } 287 + #endif /* CONFIG_PM_SLEEP */ 335 288 336 289 return 0; 337 290 } ··· 355 294 .pm = DEV_PM_OPS, 356 295 }, 357 296 .probe = bd9571mwv_regulator_probe, 297 + .remove = bd9571mwv_regulator_remove, 358 298 .id_table = bd9571mwv_regulator_id_table, 359 299 }; 360 300 module_platform_driver(bd9571mwv_regulator_driver);
+29 -15
drivers/regulator/core.c
··· 1740 1740 rdev->use_count = 0; 1741 1741 } 1742 1742 1743 + device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); 1744 + 1743 1745 return regulator; 1744 1746 } 1745 1747 ··· 1831 1829 1832 1830 debugfs_remove_recursive(regulator->debugfs); 1833 1831 1834 - /* remove any sysfs entries */ 1835 - if (regulator->dev) 1832 + if (regulator->dev) { 1833 + int count = 0; 1834 + struct regulator *r; 1835 + 1836 + list_for_each_entry(r, &rdev->consumer_list, list) 1837 + if (r->dev == regulator->dev) 1838 + count++; 1839 + 1840 + if (count == 1) 1841 + device_link_remove(regulator->dev, &rdev->dev); 1842 + 1843 + /* remove any sysfs entries */ 1836 1844 sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 1845 + } 1846 + 1837 1847 regulator_lock(rdev); 1838 1848 list_del(&regulator->list); 1839 1849 ··· 4455 4441 EXPORT_SYMBOL_GPL(regulator_unregister); 4456 4442 4457 4443 #ifdef CONFIG_SUSPEND 4458 - static int _regulator_suspend_late(struct device *dev, void *data) 4444 + static int _regulator_suspend(struct device *dev, void *data) 4459 4445 { 4460 4446 struct regulator_dev *rdev = dev_to_rdev(dev); 4461 4447 suspend_state_t *state = data; ··· 4469 4455 } 4470 4456 4471 4457 /** 4472 - * regulator_suspend_late - prepare regulators for system wide suspend 4458 + * regulator_suspend - prepare regulators for system wide suspend 4473 4459 * @state: system suspend state 4474 4460 * 4475 4461 * Configure each regulator with it's suspend operating parameters for state. 4476 4462 */ 4477 - static int regulator_suspend_late(struct device *dev) 4463 + static int regulator_suspend(struct device *dev) 4478 4464 { 4479 4465 suspend_state_t state = pm_suspend_target_state; 4480 4466 4481 4467 return class_for_each_device(&regulator_class, NULL, &state, 4482 - _regulator_suspend_late); 4468 + _regulator_suspend); 4483 4469 } 4484 4470 4485 - static int _regulator_resume_early(struct device *dev, void *data) 4471 + static int _regulator_resume(struct device *dev, void *data) 4486 4472 { 4487 4473 int ret = 0; 4488 4474 struct regulator_dev *rdev = dev_to_rdev(dev); ··· 4495 4481 4496 4482 regulator_lock(rdev); 4497 4483 4498 - if (rdev->desc->ops->resume_early && 4484 + if (rdev->desc->ops->resume && 4499 4485 (rstate->enabled == ENABLE_IN_SUSPEND || 4500 4486 rstate->enabled == DISABLE_IN_SUSPEND)) 4501 - ret = rdev->desc->ops->resume_early(rdev); 4487 + ret = rdev->desc->ops->resume(rdev); 4502 4488 4503 4489 regulator_unlock(rdev); 4504 4490 4505 4491 return ret; 4506 4492 } 4507 4493 4508 - static int regulator_resume_early(struct device *dev) 4494 + static int regulator_resume(struct device *dev) 4509 4495 { 4510 4496 suspend_state_t state = pm_suspend_target_state; 4511 4497 4512 4498 return class_for_each_device(&regulator_class, NULL, &state, 4513 - _regulator_resume_early); 4499 + _regulator_resume); 4514 4500 } 4515 4501 4516 4502 #else /* !CONFIG_SUSPEND */ 4517 4503 4518 - #define regulator_suspend_late NULL 4519 - #define regulator_resume_early NULL 4504 + #define regulator_suspend NULL 4505 + #define regulator_resume NULL 4520 4506 4521 4507 #endif /* !CONFIG_SUSPEND */ 4522 4508 4523 4509 #ifdef CONFIG_PM 4524 4510 static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 4525 - .suspend_late = regulator_suspend_late, 4526 - .resume_early = regulator_resume_early, 4511 + .suspend = regulator_suspend, 4512 + .resume = regulator_resume, 4527 4513 }; 4528 4514 #endif 4529 4515
+103
drivers/regulator/cpcap-regulator.c
··· 271 271 }; 272 272 273 273 static const unsigned int unknown_val_tbl[] = { 0, }; 274 + static const unsigned int sw2_sw4_val_tbl[] = { 612500, 625000, 637500, 275 + 650000, 662500, 675000, 276 + 687500, 700000, 712500, 277 + 725000, 737500, 750000, 278 + 762500, 775000, 787500, 279 + 800000, 812500, 825000, 280 + 837500, 850000, 862500, 281 + 875000, 887500, 900000, 282 + 912500, 925000, 937500, 283 + 950000, 962500, 975000, 284 + 987500, 1000000, 1012500, 285 + 1025000, 1037500, 1050000, 286 + 1062500, 1075000, 1087500, 287 + 1100000, 1112500, 1125000, 288 + 1137500, 1150000, 1162500, 289 + 1175000, 1187500, 1200000, 290 + 1212500, 1225000, 1237500, 291 + 1250000, 1262500, 1275000, 292 + 1287500, 1300000, 1312500, 293 + 1325000, 1337500, 1350000, 294 + 1362500, 1375000, 1387500, 295 + 1400000, 1412500, 1425000, 296 + 1437500, 1450000, 1462500, }; 274 297 static const unsigned int sw5_val_tbl[] = { 0, 5050000, }; 275 298 static const unsigned int vcam_val_tbl[] = { 2600000, 2700000, 2800000, 276 299 2900000, }; ··· 412 389 { /* sentinel */ }, 413 390 }; 414 391 392 + static struct cpcap_regulator xoom_regulators[] = { 393 + CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2, 394 + CPCAP_BIT_SW1_SEL, unknown_val_tbl, 395 + 0, 0, 0, 0, 0, 0), 396 + CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2, 397 + CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl, 398 + 0xf00, 0x7f, 0, 0x800, 0, 120), 399 + CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2, 400 + CPCAP_BIT_SW3_SEL, unknown_val_tbl, 401 + 0, 0, 0, 0, 0, 0), 402 + CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2, 403 + CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl, 404 + 0xf00, 0x7f, 0, 0x900, 0, 100), 405 + CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2, 406 + CPCAP_BIT_SW5_SEL, sw5_val_tbl, 407 + 0x2a, 0, 0, 0x22, 0, 0), 408 + CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2, 409 + CPCAP_BIT_SW6_SEL, unknown_val_tbl, 410 + 0, 0, 0, 0, 0, 0), 411 + CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2, 412 + CPCAP_BIT_VCAM_SEL, vcam_val_tbl, 413 + 0x87, 0x30, 4, 0x7, 0, 420), 414 + CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3, 415 + CPCAP_BIT_VCSI_SEL, vcsi_val_tbl, 416 + 0x47, 0x10, 4, 0x7, 0, 350), 417 + CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3, 418 + CPCAP_BIT_VDAC_SEL, vdac_val_tbl, 419 + 0x87, 0x30, 4, 0x3, 0, 420), 420 + CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2, 421 + CPCAP_BIT_VDIG_SEL, vdig_val_tbl, 422 + 0x87, 0x30, 4, 0x5, 0, 420), 423 + CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3, 424 + CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl, 425 + 0x80, 0xf, 0, 0x80, 0, 420), 426 + CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3, 427 + CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl, 428 + 0x17, 0, 0, 0x2, 0, 0), 429 + CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2, 430 + CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl, 431 + 0x87, 0x38, 3, 0x2, 0, 420), 432 + CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3, 433 + CPCAP_BIT_VPLL_SEL, vpll_val_tbl, 434 + 0x43, 0x18, 3, 0x1, 0, 420), 435 + CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3, 436 + CPCAP_BIT_VRF1_SEL, vrf1_val_tbl, 437 + 0xac, 0x2, 1, 0xc, 0, 10), 438 + CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3, 439 + CPCAP_BIT_VRF2_SEL, vrf2_val_tbl, 440 + 0x23, 0x8, 3, 0x3, 0, 10), 441 + CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3, 442 + CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl, 443 + 0x23, 0x8, 3, 0x3, 0, 420), 444 + CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3, 445 + CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl, 446 + 0x47, 0x10, 4, 0x5, 0, 420), 447 + CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3, 448 + CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl, 449 + 0x20c, 0xc0, 6, 0x8, 0, 420), 450 + CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, 451 + 0xffff, vsim_val_tbl, 452 + 0x23, 0x8, 3, 0x3, 0, 420), 453 + CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, 454 + 0xffff, vsimcard_val_tbl, 455 + 0x1e80, 0x8, 3, 0x1e00, 0, 420), 456 + CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3, 457 + CPCAP_BIT_VVIB_SEL, vvib_val_tbl, 458 + 0x1, 0xc, 2, 0, 0x1, 500), 459 + CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3, 460 + CPCAP_BIT_VUSB_SEL, vusb_val_tbl, 461 + 0x11c, 0x40, 6, 0xc, 0, 0), 462 + CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4, 463 + CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl, 464 + 0x16, 0x1, 0, 0x4, 0, 0), 465 + { /* sentinel */ }, 466 + }; 467 + 415 468 static const struct of_device_id cpcap_regulator_id_table[] = { 416 469 { 417 470 .compatible = "motorola,cpcap-regulator", ··· 495 396 { 496 397 .compatible = "motorola,mapphone-cpcap-regulator", 497 398 .data = omap4_regulators, 399 + }, 400 + { 401 + .compatible = "motorola,xoom-cpcap-regulator", 402 + .data = xoom_regulators, 498 403 }, 499 404 {}, 500 405 };
+6 -16
drivers/regulator/max14577-regulator.c
··· 1 - /* 2 - * max14577.c - Regulator driver for the Maxim 14577/77836 3 - * 4 - * Copyright (C) 2013,2014 Samsung Electronics 5 - * Krzysztof Kozlowski <krzk@kernel.org> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - * GNU General Public License for more details. 16 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // max14577.c - Regulator driver for the Maxim 14577/77836 4 + // 5 + // Copyright (C) 2013,2014 Samsung Electronics 6 + // Krzysztof Kozlowski <krzk@kernel.org> 17 7 18 8 #include <linux/module.h> 19 9 #include <linux/platform_device.h>
+9 -23
drivers/regulator/max77686-regulator.c
··· 1 - /* 2 - * max77686.c - Regulator driver for the Maxim 77686 3 - * 4 - * Copyright (C) 2012 Samsung Electronics 5 - * Chiwoong Byun <woong.byun@samsung.com> 6 - * Jonghwa Lee <jonghwa3.lee@samsung.com> 7 - * 8 - * This program is free software; you can redistribute it and/or modify 9 - * it under the terms of the GNU General Public License as published by 10 - * the Free Software Foundation; either version 2 of the License, or 11 - * (at your option) any later version. 12 - * 13 - * This program is distributed in the hope that it will be useful, 14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 - * GNU General Public License for more details. 17 - * 18 - * You should have received a copy of the GNU General Public License 19 - * along with this program; if not, write to the Free Software 20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 - * 22 - * This driver is based on max8997.c 23 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // max77686.c - Regulator driver for the Maxim 77686 4 + // 5 + // Copyright (C) 2012 Samsung Electronics 6 + // Chiwoong Byun <woong.byun@samsung.com> 7 + // Jonghwa Lee <jonghwa3.lee@samsung.com> 8 + // 9 + // This driver is based on max8997.c 24 10 25 11 #include <linux/kernel.h> 26 12 #include <linux/bug.h>
+9 -23
drivers/regulator/max77693-regulator.c
··· 1 - /* 2 - * max77693.c - Regulator driver for the Maxim 77693 and 77843 3 - * 4 - * Copyright (C) 2013-2015 Samsung Electronics 5 - * Jonghwa Lee <jonghwa3.lee@samsung.com> 6 - * Krzysztof Kozlowski <krzk@kernel.org> 7 - * 8 - * This program is free software; you can redistribute it and/or modify 9 - * it under the terms of the GNU General Public License as published by 10 - * the Free Software Foundation; either version 2 of the License, or 11 - * (at your option) any later version. 12 - * 13 - * This program is distributed in the hope that it will be useful, 14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 - * GNU General Public License for more details. 17 - * 18 - * You should have received a copy of the GNU General Public License 19 - * along with this program; if not, write to the Free Software 20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 - * 22 - * This driver is based on max77686.c 23 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // max77693.c - Regulator driver for the Maxim 77693 and 77843 4 + // 5 + // Copyright (C) 2013-2015 Samsung Electronics 6 + // Jonghwa Lee <jonghwa3.lee@samsung.com> 7 + // Krzysztof Kozlowski <krzk@kernel.org> 8 + // 9 + // This driver is based on max77686.c 24 10 25 11 #include <linux/err.h> 26 12 #include <linux/slab.h>
+12 -22
drivers/regulator/max77802-regulator.c
··· 1 - /* 2 - * max77802.c - Regulator driver for the Maxim 77802 3 - * 4 - * Copyright (C) 2013-2014 Google, Inc 5 - * Simon Glass <sjg@chromium.org> 6 - * 7 - * Copyright (C) 2012 Samsung Electronics 8 - * Chiwoong Byun <woong.byun@samsung.com> 9 - * Jonghwa Lee <jonghwa3.lee@samsung.com> 10 - * 11 - * This program is free software; you can redistribute it and/or modify 12 - * it under the terms of the GNU General Public License as published by 13 - * the Free Software Foundation; either version 2 of the License, or 14 - * (at your option) any later version. 15 - * 16 - * This program is distributed in the hope that it will be useful, 17 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 - * GNU General Public License for more details. 20 - * 21 - * This driver is based on max8997.c 22 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // max77802.c - Regulator driver for the Maxim 77802 4 + // 5 + // Copyright (C) 2013-2014 Google, Inc 6 + // Simon Glass <sjg@chromium.org> 7 + // 8 + // Copyright (C) 2012 Samsung Electronics 9 + // Chiwoong Byun <woong.byun@samsung.com> 10 + // Jonghwa Lee <jonghwa3.lee@samsung.com> 11 + // 12 + // This driver is based on max8997.c 23 13 24 14 #include <linux/kernel.h> 25 15 #include <linux/bug.h>
+9 -24
drivers/regulator/max8997-regulator.c
··· 1 - /* 2 - * max8997.c - Regulator driver for the Maxim 8997/8966 3 - * 4 - * Copyright (C) 2011 Samsung Electronics 5 - * MyungJoo Ham <myungjoo.ham@samsung.com> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - * GNU General Public License for more details. 16 - * 17 - * You should have received a copy of the GNU General Public License 18 - * along with this program; if not, write to the Free Software 19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 - * 21 - * This driver is based on max8998.c 22 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // max8997.c - Regulator driver for the Maxim 8997/8966 4 + // 5 + // Copyright (C) 2011 Samsung Electronics 6 + // MyungJoo Ham <myungjoo.ham@samsung.com> 7 + // 8 + // This driver is based on max8998.c 23 9 24 10 #include <linux/bug.h> 25 11 #include <linux/err.h> ··· 151 165 int rid = rdev_get_id(rdev); 152 166 int val; 153 167 154 - if (rid >= ARRAY_SIZE(reg_voltage_map) || 155 - rid < 0) 168 + if (rid < 0 || rid >= ARRAY_SIZE(reg_voltage_map)) 156 169 return -EINVAL; 157 170 158 171 desc = reg_voltage_map[rid];
+7 -21
drivers/regulator/max8998.c
··· 1 - /* 2 - * max8998.c - Voltage regulator driver for the Maxim 8998 3 - * 4 - * Copyright (C) 2009-2010 Samsung Electronics 5 - * Kyungmin Park <kyungmin.park@samsung.com> 6 - * Marek Szyprowski <m.szyprowski@samsung.com> 7 - * 8 - * This program is free software; you can redistribute it and/or modify 9 - * it under the terms of the GNU General Public License as published by 10 - * the Free Software Foundation; either version 2 of the License, or 11 - * (at your option) any later version. 12 - * 13 - * This program is distributed in the hope that it will be useful, 14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 - * GNU General Public License for more details. 17 - * 18 - * You should have received a copy of the GNU General Public License 19 - * along with this program; if not, write to the Free Software 20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // max8998.c - Voltage regulator driver for the Maxim 8998 4 + // 5 + // Copyright (C) 2009-2010 Samsung Electronics 6 + // Kyungmin Park <kyungmin.park@samsung.com> 7 + // Marek Szyprowski <m.szyprowski@samsung.com> 22 8 23 9 #include <linux/module.h> 24 10 #include <linux/init.h>
+102 -10
drivers/regulator/pfuze100-regulator.c
··· 17 17 #include <linux/slab.h> 18 18 #include <linux/regmap.h> 19 19 20 + #define PFUZE_FLAG_DISABLE_SW BIT(1) 21 + 20 22 #define PFUZE_NUMREGS 128 21 23 #define PFUZE100_VOL_OFFSET 0 22 24 #define PFUZE100_STANDBY_OFFSET 1 ··· 46 44 #define PFUZE100_VGEN5VOL 0x70 47 45 #define PFUZE100_VGEN6VOL 0x71 48 46 49 - enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3 }; 47 + enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3, PFUZE3001 = 0x31, }; 50 48 51 49 struct pfuze_regulator { 52 50 struct regulator_desc desc; 53 51 unsigned char stby_reg; 54 52 unsigned char stby_mask; 53 + bool sw_reg; 55 54 }; 56 55 57 56 struct pfuze_chip { 58 57 int chip_id; 58 + int flags; 59 59 struct regmap *regmap; 60 60 struct device *dev; 61 61 struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR]; ··· 96 92 {.name = "pfuze100", .driver_data = PFUZE100}, 97 93 {.name = "pfuze200", .driver_data = PFUZE200}, 98 94 {.name = "pfuze3000", .driver_data = PFUZE3000}, 95 + {.name = "pfuze3001", .driver_data = PFUZE3001}, 99 96 { } 100 97 }; 101 98 MODULE_DEVICE_TABLE(i2c, pfuze_device_id); ··· 105 100 { .compatible = "fsl,pfuze100", .data = (void *)PFUZE100}, 106 101 { .compatible = "fsl,pfuze200", .data = (void *)PFUZE200}, 107 102 { .compatible = "fsl,pfuze3000", .data = (void *)PFUZE3000}, 103 + { .compatible = "fsl,pfuze3001", .data = (void *)PFUZE3001}, 108 104 { } 109 105 }; 110 106 MODULE_DEVICE_TABLE(of, pfuze_dt_ids); ··· 114 108 { 115 109 struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); 116 110 int id = rdev_get_id(rdev); 111 + bool reg_has_ramp_delay; 117 112 unsigned int ramp_bits; 118 113 int ret; 119 114 120 - if (id < PFUZE100_SWBST) { 115 + switch (pfuze100->chip_id) { 116 + case PFUZE3001: 117 + /* no dynamic voltage scaling for PF3001 */ 118 + reg_has_ramp_delay = false; 119 + break; 120 + case PFUZE3000: 121 + reg_has_ramp_delay = (id < PFUZE3000_SWBST); 122 + break; 123 + case PFUZE200: 124 + reg_has_ramp_delay = (id < PFUZE200_SWBST); 125 + break; 126 + case PFUZE100: 127 + default: 128 + reg_has_ramp_delay = (id < PFUZE100_SWBST); 129 + break; 130 + } 131 + 132 + if (reg_has_ramp_delay) { 121 133 ramp_delay = 12500 / ramp_delay; 122 134 ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3); 123 135 ret = regmap_update_bits(pfuze100->regmap, ··· 143 119 0xc0, ramp_bits << 6); 144 120 if (ret < 0) 145 121 dev_err(pfuze100->dev, "ramp failed, err %d\n", ret); 146 - } else 122 + } else { 147 123 ret = -EACCES; 124 + } 148 125 149 126 return ret; 150 127 } ··· 167 142 }; 168 143 169 144 static const struct regulator_ops pfuze100_sw_regulator_ops = { 145 + .list_voltage = regulator_list_voltage_linear, 146 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 147 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 148 + .set_voltage_time_sel = regulator_set_voltage_time_sel, 149 + .set_ramp_delay = pfuze100_set_ramp_delay, 150 + }; 151 + 152 + static const struct regulator_ops pfuze100_sw_disable_regulator_ops = { 170 153 .enable = regulator_enable_regmap, 171 154 .disable = regulator_disable_regmap, 172 155 .is_enabled = regulator_is_enabled_regmap, ··· 225 192 .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ 226 193 .vsel_mask = 0x3f, \ 227 194 .enable_reg = (base) + PFUZE100_MODE_OFFSET, \ 228 - .enable_val = 0xc, \ 229 - .disable_val = 0x0, \ 230 195 .enable_mask = 0xf, \ 231 - .enable_time = 500, \ 232 196 }, \ 233 197 .stby_reg = (base) + PFUZE100_STANDBY_OFFSET, \ 234 198 .stby_mask = 0x3f, \ 199 + .sw_reg = true, \ 235 200 } 236 201 237 202 #define PFUZE100_SWB_REG(_chip, _name, base, mask, voltages) \ ··· 392 361 PFUZE100_VGEN_REG(PFUZE3000, VLDO4, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), 393 362 }; 394 363 364 + static struct pfuze_regulator pfuze3001_regulators[] = { 365 + PFUZE100_SWB_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a), 366 + PFUZE100_SWB_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo), 367 + PFUZE3000_SW3_REG(PFUZE3001, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000), 368 + PFUZE100_SWB_REG(PFUZE3001, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), 369 + PFUZE100_VGEN_REG(PFUZE3001, VLDO1, PFUZE100_VGEN1VOL, 1800000, 3300000, 100000), 370 + PFUZE100_VGEN_REG(PFUZE3001, VLDO2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000), 371 + PFUZE3000_VCC_REG(PFUZE3001, VCCSD, PFUZE100_VGEN3VOL, 2850000, 3300000, 150000), 372 + PFUZE3000_VCC_REG(PFUZE3001, V33, PFUZE100_VGEN4VOL, 2850000, 3300000, 150000), 373 + PFUZE100_VGEN_REG(PFUZE3001, VLDO3, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000), 374 + PFUZE100_VGEN_REG(PFUZE3001, VLDO4, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), 375 + }; 376 + 395 377 #ifdef CONFIG_OF 396 378 /* PFUZE100 */ 397 379 static struct of_regulator_match pfuze100_matches[] = { ··· 462 418 { .name = "vldo4", }, 463 419 }; 464 420 421 + /* PFUZE3001 */ 422 + static struct of_regulator_match pfuze3001_matches[] = { 423 + 424 + { .name = "sw1", }, 425 + { .name = "sw2", }, 426 + { .name = "sw3", }, 427 + { .name = "vsnvs", }, 428 + { .name = "vldo1", }, 429 + { .name = "vldo2", }, 430 + { .name = "vccsd", }, 431 + { .name = "v33", }, 432 + { .name = "vldo3", }, 433 + { .name = "vldo4", }, 434 + }; 435 + 465 436 static struct of_regulator_match *pfuze_matches; 466 437 467 438 static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) ··· 489 430 if (!np) 490 431 return -EINVAL; 491 432 433 + if (of_property_read_bool(np, "fsl,pfuze-support-disable-sw")) 434 + chip->flags |= PFUZE_FLAG_DISABLE_SW; 435 + 492 436 parent = of_get_child_by_name(np, "regulators"); 493 437 if (!parent) { 494 438 dev_err(dev, "regulators node not found\n"); ··· 499 437 } 500 438 501 439 switch (chip->chip_id) { 440 + case PFUZE3001: 441 + pfuze_matches = pfuze3001_matches; 442 + ret = of_regulator_match(dev, parent, pfuze3001_matches, 443 + ARRAY_SIZE(pfuze3001_matches)); 444 + break; 502 445 case PFUZE3000: 503 446 pfuze_matches = pfuze3000_matches; 504 447 ret = of_regulator_match(dev, parent, pfuze3000_matches, ··· 575 508 */ 576 509 dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8"); 577 510 } else if ((value & 0x0f) != pfuze_chip->chip_id && 578 - (value & 0xf0) >> 4 != pfuze_chip->chip_id) { 511 + (value & 0xf0) >> 4 != pfuze_chip->chip_id && 512 + (value != pfuze_chip->chip_id)) { 579 513 /* device id NOT match with your setting */ 580 514 dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value); 581 515 return -ENODEV; ··· 656 588 657 589 /* use the right regulators after identify the right device */ 658 590 switch (pfuze_chip->chip_id) { 591 + case PFUZE3001: 592 + pfuze_chip->pfuze_regulators = pfuze3001_regulators; 593 + regulator_num = ARRAY_SIZE(pfuze3001_regulators); 594 + sw_check_start = PFUZE3001_SW2; 595 + sw_check_end = PFUZE3001_SW2; 596 + sw_hi = 1 << 3; 597 + break; 659 598 case PFUZE3000: 660 599 pfuze_chip->pfuze_regulators = pfuze3000_regulators; 661 600 regulator_num = ARRAY_SIZE(pfuze3000_regulators); ··· 686 611 } 687 612 dev_info(&client->dev, "pfuze%s found.\n", 688 613 (pfuze_chip->chip_id == PFUZE100) ? "100" : 689 - ((pfuze_chip->chip_id == PFUZE200) ? "200" : "3000")); 614 + (((pfuze_chip->chip_id == PFUZE200) ? "200" : 615 + ((pfuze_chip->chip_id == PFUZE3000) ? "3000" : "3001")))); 690 616 691 617 memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators, 692 618 sizeof(pfuze_chip->regulator_descs)); ··· 712 636 if (i >= sw_check_start && i <= sw_check_end) { 713 637 regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); 714 638 if (val & sw_hi) { 715 - if (pfuze_chip->chip_id == PFUZE3000) { 639 + if (pfuze_chip->chip_id == PFUZE3000 || 640 + pfuze_chip->chip_id == PFUZE3001) { 716 641 desc->volt_table = pfuze3000_sw2hi; 717 642 desc->n_voltages = ARRAY_SIZE(pfuze3000_sw2hi); 718 643 } else { ··· 721 644 desc->uV_step = 50000; 722 645 desc->n_voltages = 51; 723 646 } 647 + } 648 + } 649 + 650 + /* 651 + * Allow SW regulators to turn off. Checking it trough a flag is 652 + * a workaround to keep the backward compatibility with existing 653 + * old dtb's which may relay on the fact that we didn't disable 654 + * the switched regulator till yet. 655 + */ 656 + if (pfuze_chip->flags & PFUZE_FLAG_DISABLE_SW) { 657 + if (pfuze_chip->regulator_descs[i].sw_reg) { 658 + desc->ops = &pfuze100_sw_disable_regulator_ops; 659 + desc->enable_val = 0x8; 660 + desc->disable_val = 0x0; 661 + desc->enable_time = 500; 724 662 } 725 663 } 726 664 ··· 767 675 module_i2c_driver(pfuze_driver); 768 676 769 677 MODULE_AUTHOR("Robin Gong <b38343@freescale.com>"); 770 - MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/200/3000 PMIC"); 678 + MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/200/3000/3001 PMIC"); 771 679 MODULE_LICENSE("GPL v2");
+769
drivers/regulator/qcom-rpmh-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2018, The Linux Foundation. All rights reserved. 3 + 4 + #define pr_fmt(fmt) "%s: " fmt, __func__ 5 + 6 + #include <linux/err.h> 7 + #include <linux/kernel.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/of_device.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/slab.h> 13 + #include <linux/string.h> 14 + #include <linux/regulator/driver.h> 15 + #include <linux/regulator/machine.h> 16 + #include <linux/regulator/of_regulator.h> 17 + 18 + #include <soc/qcom/cmd-db.h> 19 + #include <soc/qcom/rpmh.h> 20 + 21 + #include <dt-bindings/regulator/qcom,rpmh-regulator.h> 22 + 23 + /** 24 + * enum rpmh_regulator_type - supported RPMh accelerator types 25 + * %VRM: RPMh VRM accelerator which supports voting on enable, voltage, 26 + * and mode of LDO, SMPS, and BOB type PMIC regulators. 27 + * %XOB: RPMh XOB accelerator which supports voting on the enable state 28 + * of PMIC regulators. 29 + */ 30 + enum rpmh_regulator_type { 31 + VRM, 32 + XOB, 33 + }; 34 + 35 + #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0 36 + #define RPMH_REGULATOR_REG_ENABLE 0x4 37 + #define RPMH_REGULATOR_REG_VRM_MODE 0x8 38 + 39 + #define PMIC4_LDO_MODE_RETENTION 4 40 + #define PMIC4_LDO_MODE_LPM 5 41 + #define PMIC4_LDO_MODE_HPM 7 42 + 43 + #define PMIC4_SMPS_MODE_RETENTION 4 44 + #define PMIC4_SMPS_MODE_PFM 5 45 + #define PMIC4_SMPS_MODE_AUTO 6 46 + #define PMIC4_SMPS_MODE_PWM 7 47 + 48 + #define PMIC4_BOB_MODE_PASS 0 49 + #define PMIC4_BOB_MODE_PFM 1 50 + #define PMIC4_BOB_MODE_AUTO 2 51 + #define PMIC4_BOB_MODE_PWM 3 52 + 53 + /** 54 + * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations 55 + * @regulator_type: RPMh accelerator type used to manage this 56 + * regulator 57 + * @ops: Pointer to regulator ops callback structure 58 + * @voltage_range: The single range of voltages supported by this 59 + * PMIC regulator type 60 + * @n_voltages: The number of unique voltage set points defined 61 + * by voltage_range 62 + * @hpm_min_load_uA: Minimum load current in microamps that requires 63 + * high power mode (HPM) operation. This is used 64 + * for LDO hardware type regulators only. 65 + * @pmic_mode_map: Array indexed by regulator framework mode 66 + * containing PMIC hardware modes. Must be large 67 + * enough to index all framework modes supported 68 + * by this regulator hardware type. 69 + * @of_map_mode: Maps an RPMH_REGULATOR_MODE_* mode value defined 70 + * in device tree to a regulator framework mode 71 + */ 72 + struct rpmh_vreg_hw_data { 73 + enum rpmh_regulator_type regulator_type; 74 + const struct regulator_ops *ops; 75 + const struct regulator_linear_range voltage_range; 76 + int n_voltages; 77 + int hpm_min_load_uA; 78 + const int *pmic_mode_map; 79 + unsigned int (*of_map_mode)(unsigned int mode); 80 + }; 81 + 82 + /** 83 + * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a 84 + * single regulator device 85 + * @dev: Device pointer for the top-level PMIC RPMh 86 + * regulator parent device. This is used as a 87 + * handle in RPMh write requests. 88 + * @addr: Base address of the regulator resource within 89 + * an RPMh accelerator 90 + * @rdesc: Regulator descriptor 91 + * @hw_data: PMIC regulator configuration data for this RPMh 92 + * regulator 93 + * @always_wait_for_ack: Boolean flag indicating if a request must always 94 + * wait for an ACK from RPMh before continuing even 95 + * if it corresponds to a strictly lower power 96 + * state (e.g. enabled --> disabled). 97 + * @enabled: Flag indicating if the regulator is enabled or 98 + * not 99 + * @bypassed: Boolean indicating if the regulator is in 100 + * bypass (pass-through) mode or not. This is 101 + * only used by BOB rpmh-regulator resources. 102 + * @voltage_selector: Selector used for get_voltage_sel() and 103 + * set_voltage_sel() callbacks 104 + * @mode: RPMh VRM regulator current framework mode 105 + */ 106 + struct rpmh_vreg { 107 + struct device *dev; 108 + u32 addr; 109 + struct regulator_desc rdesc; 110 + const struct rpmh_vreg_hw_data *hw_data; 111 + bool always_wait_for_ack; 112 + 113 + int enabled; 114 + bool bypassed; 115 + int voltage_selector; 116 + unsigned int mode; 117 + }; 118 + 119 + /** 120 + * struct rpmh_vreg_init_data - initialization data for an RPMh regulator 121 + * @name: Name for the regulator which also corresponds 122 + * to the device tree subnode name of the regulator 123 + * @resource_name: RPMh regulator resource name format string. 124 + * This must include exactly one field: '%s' which 125 + * is filled at run-time with the PMIC ID provided 126 + * by device tree property qcom,pmic-id. Example: 127 + * "ldo%s1" for RPMh resource "ldoa1". 128 + * @supply_name: Parent supply regulator name 129 + * @hw_data: Configuration data for this PMIC regulator type 130 + */ 131 + struct rpmh_vreg_init_data { 132 + const char *name; 133 + const char *resource_name; 134 + const char *supply_name; 135 + const struct rpmh_vreg_hw_data *hw_data; 136 + }; 137 + 138 + /** 139 + * rpmh_regulator_send_request() - send the request to RPMh 140 + * @vreg: Pointer to the RPMh regulator 141 + * @cmd: Pointer to the RPMh command to send 142 + * @wait_for_ack: Boolean indicating if execution must wait until the 143 + * request has been acknowledged as complete 144 + * 145 + * Return: 0 on success, errno on failure 146 + */ 147 + static int rpmh_regulator_send_request(struct rpmh_vreg *vreg, 148 + struct tcs_cmd *cmd, bool wait_for_ack) 149 + { 150 + int ret; 151 + 152 + if (wait_for_ack || vreg->always_wait_for_ack) 153 + ret = rpmh_write(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, 1); 154 + else 155 + ret = rpmh_write_async(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, 156 + 1); 157 + 158 + return ret; 159 + } 160 + 161 + static int _rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev, 162 + unsigned int selector, bool wait_for_ack) 163 + { 164 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 165 + struct tcs_cmd cmd = { 166 + .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE, 167 + }; 168 + int ret; 169 + 170 + /* VRM voltage control register is set with voltage in millivolts. */ 171 + cmd.data = DIV_ROUND_UP(regulator_list_voltage_linear_range(rdev, 172 + selector), 1000); 173 + 174 + ret = rpmh_regulator_send_request(vreg, &cmd, wait_for_ack); 175 + if (!ret) 176 + vreg->voltage_selector = selector; 177 + 178 + return ret; 179 + } 180 + 181 + static int rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev, 182 + unsigned int selector) 183 + { 184 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 185 + 186 + if (vreg->enabled == -EINVAL) { 187 + /* 188 + * Cache the voltage and send it later when the regulator is 189 + * enabled or disabled. 190 + */ 191 + vreg->voltage_selector = selector; 192 + return 0; 193 + } 194 + 195 + return _rpmh_regulator_vrm_set_voltage_sel(rdev, selector, 196 + selector > vreg->voltage_selector); 197 + } 198 + 199 + static int rpmh_regulator_vrm_get_voltage_sel(struct regulator_dev *rdev) 200 + { 201 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 202 + 203 + return vreg->voltage_selector; 204 + } 205 + 206 + static int rpmh_regulator_is_enabled(struct regulator_dev *rdev) 207 + { 208 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 209 + 210 + return vreg->enabled; 211 + } 212 + 213 + static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev, 214 + bool enable) 215 + { 216 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 217 + struct tcs_cmd cmd = { 218 + .addr = vreg->addr + RPMH_REGULATOR_REG_ENABLE, 219 + .data = enable, 220 + }; 221 + int ret; 222 + 223 + if (vreg->enabled == -EINVAL && 224 + vreg->voltage_selector != -ENOTRECOVERABLE) { 225 + ret = _rpmh_regulator_vrm_set_voltage_sel(rdev, 226 + vreg->voltage_selector, true); 227 + if (ret < 0) 228 + return ret; 229 + } 230 + 231 + ret = rpmh_regulator_send_request(vreg, &cmd, enable); 232 + if (!ret) 233 + vreg->enabled = enable; 234 + 235 + return ret; 236 + } 237 + 238 + static int rpmh_regulator_enable(struct regulator_dev *rdev) 239 + { 240 + return rpmh_regulator_set_enable_state(rdev, true); 241 + } 242 + 243 + static int rpmh_regulator_disable(struct regulator_dev *rdev) 244 + { 245 + return rpmh_regulator_set_enable_state(rdev, false); 246 + } 247 + 248 + static int rpmh_regulator_vrm_set_mode_bypass(struct rpmh_vreg *vreg, 249 + unsigned int mode, bool bypassed) 250 + { 251 + struct tcs_cmd cmd = { 252 + .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_MODE, 253 + }; 254 + int pmic_mode; 255 + 256 + if (mode > REGULATOR_MODE_STANDBY) 257 + return -EINVAL; 258 + 259 + pmic_mode = vreg->hw_data->pmic_mode_map[mode]; 260 + if (pmic_mode < 0) 261 + return pmic_mode; 262 + 263 + if (bypassed) 264 + cmd.data = PMIC4_BOB_MODE_PASS; 265 + else 266 + cmd.data = pmic_mode; 267 + 268 + return rpmh_regulator_send_request(vreg, &cmd, true); 269 + } 270 + 271 + static int rpmh_regulator_vrm_set_mode(struct regulator_dev *rdev, 272 + unsigned int mode) 273 + { 274 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 275 + int ret; 276 + 277 + if (mode == vreg->mode) 278 + return 0; 279 + 280 + ret = rpmh_regulator_vrm_set_mode_bypass(vreg, mode, vreg->bypassed); 281 + if (!ret) 282 + vreg->mode = mode; 283 + 284 + return ret; 285 + } 286 + 287 + static unsigned int rpmh_regulator_vrm_get_mode(struct regulator_dev *rdev) 288 + { 289 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 290 + 291 + return vreg->mode; 292 + } 293 + 294 + /** 295 + * rpmh_regulator_vrm_set_load() - set the regulator mode based upon the load 296 + * current requested 297 + * @rdev: Regulator device pointer for the rpmh-regulator 298 + * @load_uA: Aggregated load current in microamps 299 + * 300 + * This function is used in the regulator_ops for VRM type RPMh regulator 301 + * devices. 302 + * 303 + * Return: 0 on success, errno on failure 304 + */ 305 + static int rpmh_regulator_vrm_set_load(struct regulator_dev *rdev, int load_uA) 306 + { 307 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 308 + unsigned int mode; 309 + 310 + if (load_uA >= vreg->hw_data->hpm_min_load_uA) 311 + mode = REGULATOR_MODE_NORMAL; 312 + else 313 + mode = REGULATOR_MODE_IDLE; 314 + 315 + return rpmh_regulator_vrm_set_mode(rdev, mode); 316 + } 317 + 318 + static int rpmh_regulator_vrm_set_bypass(struct regulator_dev *rdev, 319 + bool enable) 320 + { 321 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 322 + int ret; 323 + 324 + if (vreg->bypassed == enable) 325 + return 0; 326 + 327 + ret = rpmh_regulator_vrm_set_mode_bypass(vreg, vreg->mode, enable); 328 + if (!ret) 329 + vreg->bypassed = enable; 330 + 331 + return ret; 332 + } 333 + 334 + static int rpmh_regulator_vrm_get_bypass(struct regulator_dev *rdev, 335 + bool *enable) 336 + { 337 + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); 338 + 339 + *enable = vreg->bypassed; 340 + 341 + return 0; 342 + } 343 + 344 + static const struct regulator_ops rpmh_regulator_vrm_ops = { 345 + .enable = rpmh_regulator_enable, 346 + .disable = rpmh_regulator_disable, 347 + .is_enabled = rpmh_regulator_is_enabled, 348 + .set_voltage_sel = rpmh_regulator_vrm_set_voltage_sel, 349 + .get_voltage_sel = rpmh_regulator_vrm_get_voltage_sel, 350 + .list_voltage = regulator_list_voltage_linear_range, 351 + .set_mode = rpmh_regulator_vrm_set_mode, 352 + .get_mode = rpmh_regulator_vrm_get_mode, 353 + }; 354 + 355 + static const struct regulator_ops rpmh_regulator_vrm_drms_ops = { 356 + .enable = rpmh_regulator_enable, 357 + .disable = rpmh_regulator_disable, 358 + .is_enabled = rpmh_regulator_is_enabled, 359 + .set_voltage_sel = rpmh_regulator_vrm_set_voltage_sel, 360 + .get_voltage_sel = rpmh_regulator_vrm_get_voltage_sel, 361 + .list_voltage = regulator_list_voltage_linear_range, 362 + .set_mode = rpmh_regulator_vrm_set_mode, 363 + .get_mode = rpmh_regulator_vrm_get_mode, 364 + .set_load = rpmh_regulator_vrm_set_load, 365 + }; 366 + 367 + static const struct regulator_ops rpmh_regulator_vrm_bypass_ops = { 368 + .enable = rpmh_regulator_enable, 369 + .disable = rpmh_regulator_disable, 370 + .is_enabled = rpmh_regulator_is_enabled, 371 + .set_voltage_sel = rpmh_regulator_vrm_set_voltage_sel, 372 + .get_voltage_sel = rpmh_regulator_vrm_get_voltage_sel, 373 + .list_voltage = regulator_list_voltage_linear_range, 374 + .set_mode = rpmh_regulator_vrm_set_mode, 375 + .get_mode = rpmh_regulator_vrm_get_mode, 376 + .set_bypass = rpmh_regulator_vrm_set_bypass, 377 + .get_bypass = rpmh_regulator_vrm_get_bypass, 378 + }; 379 + 380 + static const struct regulator_ops rpmh_regulator_xob_ops = { 381 + .enable = rpmh_regulator_enable, 382 + .disable = rpmh_regulator_disable, 383 + .is_enabled = rpmh_regulator_is_enabled, 384 + }; 385 + 386 + /** 387 + * rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator 388 + * vreg: Pointer to the individual rpmh-regulator resource 389 + * dev: Pointer to the top level rpmh-regulator PMIC device 390 + * node: Pointer to the individual rpmh-regulator resource 391 + * device node 392 + * pmic_id: String used to identify the top level rpmh-regulator 393 + * PMIC device on the board 394 + * pmic_rpmh_data: Pointer to a null-terminated array of rpmh-regulator 395 + * resources defined for the top level PMIC device 396 + * 397 + * Return: 0 on success, errno on failure 398 + */ 399 + static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, 400 + struct device_node *node, const char *pmic_id, 401 + const struct rpmh_vreg_init_data *pmic_rpmh_data) 402 + { 403 + struct regulator_config reg_config = {}; 404 + char rpmh_resource_name[20] = ""; 405 + const struct rpmh_vreg_init_data *rpmh_data; 406 + struct regulator_init_data *init_data; 407 + struct regulator_dev *rdev; 408 + int ret; 409 + 410 + vreg->dev = dev; 411 + 412 + for (rpmh_data = pmic_rpmh_data; rpmh_data->name; rpmh_data++) 413 + if (!strcmp(rpmh_data->name, node->name)) 414 + break; 415 + 416 + if (!rpmh_data->name) { 417 + dev_err(dev, "Unknown regulator %s\n", node->name); 418 + return -EINVAL; 419 + } 420 + 421 + scnprintf(rpmh_resource_name, sizeof(rpmh_resource_name), 422 + rpmh_data->resource_name, pmic_id); 423 + 424 + vreg->addr = cmd_db_read_addr(rpmh_resource_name); 425 + if (!vreg->addr) { 426 + dev_err(dev, "%s: could not find RPMh address for resource %s\n", 427 + node->name, rpmh_resource_name); 428 + return -ENODEV; 429 + } 430 + 431 + vreg->rdesc.name = rpmh_data->name; 432 + vreg->rdesc.supply_name = rpmh_data->supply_name; 433 + vreg->hw_data = rpmh_data->hw_data; 434 + 435 + vreg->enabled = -EINVAL; 436 + vreg->voltage_selector = -ENOTRECOVERABLE; 437 + vreg->mode = REGULATOR_MODE_INVALID; 438 + 439 + if (rpmh_data->hw_data->n_voltages) { 440 + vreg->rdesc.linear_ranges = &rpmh_data->hw_data->voltage_range; 441 + vreg->rdesc.n_linear_ranges = 1; 442 + vreg->rdesc.n_voltages = rpmh_data->hw_data->n_voltages; 443 + } 444 + 445 + vreg->always_wait_for_ack = of_property_read_bool(node, 446 + "qcom,always-wait-for-ack"); 447 + 448 + vreg->rdesc.owner = THIS_MODULE; 449 + vreg->rdesc.type = REGULATOR_VOLTAGE; 450 + vreg->rdesc.ops = vreg->hw_data->ops; 451 + vreg->rdesc.of_map_mode = vreg->hw_data->of_map_mode; 452 + 453 + init_data = of_get_regulator_init_data(dev, node, &vreg->rdesc); 454 + if (!init_data) 455 + return -ENOMEM; 456 + 457 + if (rpmh_data->hw_data->regulator_type == XOB && 458 + init_data->constraints.min_uV && 459 + init_data->constraints.min_uV == init_data->constraints.max_uV) { 460 + vreg->rdesc.fixed_uV = init_data->constraints.min_uV; 461 + vreg->rdesc.n_voltages = 1; 462 + } 463 + 464 + reg_config.dev = dev; 465 + reg_config.init_data = init_data; 466 + reg_config.of_node = node; 467 + reg_config.driver_data = vreg; 468 + 469 + rdev = devm_regulator_register(dev, &vreg->rdesc, &reg_config); 470 + if (IS_ERR(rdev)) { 471 + ret = PTR_ERR(rdev); 472 + dev_err(dev, "%s: devm_regulator_register() failed, ret=%d\n", 473 + node->name, ret); 474 + return ret; 475 + } 476 + 477 + dev_dbg(dev, "%s regulator registered for RPMh resource %s @ 0x%05X\n", 478 + node->name, rpmh_resource_name, vreg->addr); 479 + 480 + return 0; 481 + } 482 + 483 + static const int pmic_mode_map_pmic4_ldo[REGULATOR_MODE_STANDBY + 1] = { 484 + [REGULATOR_MODE_INVALID] = -EINVAL, 485 + [REGULATOR_MODE_STANDBY] = PMIC4_LDO_MODE_RETENTION, 486 + [REGULATOR_MODE_IDLE] = PMIC4_LDO_MODE_LPM, 487 + [REGULATOR_MODE_NORMAL] = PMIC4_LDO_MODE_HPM, 488 + [REGULATOR_MODE_FAST] = -EINVAL, 489 + }; 490 + 491 + static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode) 492 + { 493 + unsigned int mode; 494 + 495 + switch (rpmh_mode) { 496 + case RPMH_REGULATOR_MODE_HPM: 497 + mode = REGULATOR_MODE_NORMAL; 498 + break; 499 + case RPMH_REGULATOR_MODE_LPM: 500 + mode = REGULATOR_MODE_IDLE; 501 + break; 502 + case RPMH_REGULATOR_MODE_RET: 503 + mode = REGULATOR_MODE_STANDBY; 504 + break; 505 + default: 506 + mode = REGULATOR_MODE_INVALID; 507 + } 508 + 509 + return mode; 510 + } 511 + 512 + static const int pmic_mode_map_pmic4_smps[REGULATOR_MODE_STANDBY + 1] = { 513 + [REGULATOR_MODE_INVALID] = -EINVAL, 514 + [REGULATOR_MODE_STANDBY] = PMIC4_SMPS_MODE_RETENTION, 515 + [REGULATOR_MODE_IDLE] = PMIC4_SMPS_MODE_PFM, 516 + [REGULATOR_MODE_NORMAL] = PMIC4_SMPS_MODE_AUTO, 517 + [REGULATOR_MODE_FAST] = PMIC4_SMPS_MODE_PWM, 518 + }; 519 + 520 + static unsigned int 521 + rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode) 522 + { 523 + unsigned int mode; 524 + 525 + switch (rpmh_mode) { 526 + case RPMH_REGULATOR_MODE_HPM: 527 + mode = REGULATOR_MODE_FAST; 528 + break; 529 + case RPMH_REGULATOR_MODE_AUTO: 530 + mode = REGULATOR_MODE_NORMAL; 531 + break; 532 + case RPMH_REGULATOR_MODE_LPM: 533 + mode = REGULATOR_MODE_IDLE; 534 + break; 535 + case RPMH_REGULATOR_MODE_RET: 536 + mode = REGULATOR_MODE_STANDBY; 537 + break; 538 + default: 539 + mode = REGULATOR_MODE_INVALID; 540 + } 541 + 542 + return mode; 543 + } 544 + 545 + static const int pmic_mode_map_pmic4_bob[REGULATOR_MODE_STANDBY + 1] = { 546 + [REGULATOR_MODE_INVALID] = -EINVAL, 547 + [REGULATOR_MODE_STANDBY] = -EINVAL, 548 + [REGULATOR_MODE_IDLE] = PMIC4_BOB_MODE_PFM, 549 + [REGULATOR_MODE_NORMAL] = PMIC4_BOB_MODE_AUTO, 550 + [REGULATOR_MODE_FAST] = PMIC4_BOB_MODE_PWM, 551 + }; 552 + 553 + static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode) 554 + { 555 + unsigned int mode; 556 + 557 + switch (rpmh_mode) { 558 + case RPMH_REGULATOR_MODE_HPM: 559 + mode = REGULATOR_MODE_FAST; 560 + break; 561 + case RPMH_REGULATOR_MODE_AUTO: 562 + mode = REGULATOR_MODE_NORMAL; 563 + break; 564 + case RPMH_REGULATOR_MODE_LPM: 565 + mode = REGULATOR_MODE_IDLE; 566 + break; 567 + default: 568 + mode = REGULATOR_MODE_INVALID; 569 + } 570 + 571 + return mode; 572 + } 573 + 574 + static const struct rpmh_vreg_hw_data pmic4_pldo = { 575 + .regulator_type = VRM, 576 + .ops = &rpmh_regulator_vrm_drms_ops, 577 + .voltage_range = REGULATOR_LINEAR_RANGE(1664000, 0, 255, 8000), 578 + .n_voltages = 256, 579 + .hpm_min_load_uA = 10000, 580 + .pmic_mode_map = pmic_mode_map_pmic4_ldo, 581 + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, 582 + }; 583 + 584 + static const struct rpmh_vreg_hw_data pmic4_pldo_lv = { 585 + .regulator_type = VRM, 586 + .ops = &rpmh_regulator_vrm_drms_ops, 587 + .voltage_range = REGULATOR_LINEAR_RANGE(1256000, 0, 127, 8000), 588 + .n_voltages = 128, 589 + .hpm_min_load_uA = 10000, 590 + .pmic_mode_map = pmic_mode_map_pmic4_ldo, 591 + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, 592 + }; 593 + 594 + static const struct rpmh_vreg_hw_data pmic4_nldo = { 595 + .regulator_type = VRM, 596 + .ops = &rpmh_regulator_vrm_drms_ops, 597 + .voltage_range = REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000), 598 + .n_voltages = 128, 599 + .hpm_min_load_uA = 30000, 600 + .pmic_mode_map = pmic_mode_map_pmic4_ldo, 601 + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, 602 + }; 603 + 604 + static const struct rpmh_vreg_hw_data pmic4_hfsmps3 = { 605 + .regulator_type = VRM, 606 + .ops = &rpmh_regulator_vrm_ops, 607 + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), 608 + .n_voltages = 216, 609 + .pmic_mode_map = pmic_mode_map_pmic4_smps, 610 + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, 611 + }; 612 + 613 + static const struct rpmh_vreg_hw_data pmic4_ftsmps426 = { 614 + .regulator_type = VRM, 615 + .ops = &rpmh_regulator_vrm_ops, 616 + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000), 617 + .n_voltages = 259, 618 + .pmic_mode_map = pmic_mode_map_pmic4_smps, 619 + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, 620 + }; 621 + 622 + static const struct rpmh_vreg_hw_data pmic4_bob = { 623 + .regulator_type = VRM, 624 + .ops = &rpmh_regulator_vrm_bypass_ops, 625 + .voltage_range = REGULATOR_LINEAR_RANGE(1824000, 0, 83, 32000), 626 + .n_voltages = 84, 627 + .pmic_mode_map = pmic_mode_map_pmic4_bob, 628 + .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, 629 + }; 630 + 631 + static const struct rpmh_vreg_hw_data pmic4_lvs = { 632 + .regulator_type = XOB, 633 + .ops = &rpmh_regulator_xob_ops, 634 + /* LVS hardware does not support voltage or mode configuration. */ 635 + }; 636 + 637 + #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \ 638 + { \ 639 + .name = _name, \ 640 + .resource_name = _resource_name, \ 641 + .hw_data = _hw_data, \ 642 + .supply_name = _supply_name, \ 643 + } 644 + 645 + static const struct rpmh_vreg_init_data pm8998_vreg_data[] = { 646 + RPMH_VREG("smps1", "smp%s1", &pmic4_ftsmps426, "vdd-s1"), 647 + RPMH_VREG("smps2", "smp%s2", &pmic4_ftsmps426, "vdd-s2"), 648 + RPMH_VREG("smps3", "smp%s3", &pmic4_hfsmps3, "vdd-s3"), 649 + RPMH_VREG("smps4", "smp%s4", &pmic4_hfsmps3, "vdd-s4"), 650 + RPMH_VREG("smps5", "smp%s5", &pmic4_hfsmps3, "vdd-s5"), 651 + RPMH_VREG("smps6", "smp%s6", &pmic4_ftsmps426, "vdd-s6"), 652 + RPMH_VREG("smps7", "smp%s7", &pmic4_ftsmps426, "vdd-s7"), 653 + RPMH_VREG("smps8", "smp%s8", &pmic4_ftsmps426, "vdd-s8"), 654 + RPMH_VREG("smps9", "smp%s9", &pmic4_ftsmps426, "vdd-s9"), 655 + RPMH_VREG("smps10", "smp%s10", &pmic4_ftsmps426, "vdd-s10"), 656 + RPMH_VREG("smps11", "smp%s11", &pmic4_ftsmps426, "vdd-s11"), 657 + RPMH_VREG("smps12", "smp%s12", &pmic4_ftsmps426, "vdd-s12"), 658 + RPMH_VREG("smps13", "smp%s13", &pmic4_ftsmps426, "vdd-s13"), 659 + RPMH_VREG("ldo1", "ldo%s1", &pmic4_nldo, "vdd-l1-l27"), 660 + RPMH_VREG("ldo2", "ldo%s2", &pmic4_nldo, "vdd-l2-l8-l17"), 661 + RPMH_VREG("ldo3", "ldo%s3", &pmic4_nldo, "vdd-l3-l11"), 662 + RPMH_VREG("ldo4", "ldo%s4", &pmic4_nldo, "vdd-l4-l5"), 663 + RPMH_VREG("ldo5", "ldo%s5", &pmic4_nldo, "vdd-l4-l5"), 664 + RPMH_VREG("ldo6", "ldo%s6", &pmic4_pldo, "vdd-l6"), 665 + RPMH_VREG("ldo7", "ldo%s7", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), 666 + RPMH_VREG("ldo8", "ldo%s8", &pmic4_nldo, "vdd-l2-l8-l17"), 667 + RPMH_VREG("ldo9", "ldo%s9", &pmic4_pldo, "vdd-l9"), 668 + RPMH_VREG("ldo10", "ldo%s10", &pmic4_pldo, "vdd-l10-l23-l25"), 669 + RPMH_VREG("ldo11", "ldo%s11", &pmic4_nldo, "vdd-l3-l11"), 670 + RPMH_VREG("ldo12", "ldo%s12", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), 671 + RPMH_VREG("ldo13", "ldo%s13", &pmic4_pldo, "vdd-l13-l19-l21"), 672 + RPMH_VREG("ldo14", "ldo%s14", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), 673 + RPMH_VREG("ldo15", "ldo%s15", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), 674 + RPMH_VREG("ldo16", "ldo%s16", &pmic4_pldo, "vdd-l16-l28"), 675 + RPMH_VREG("ldo17", "ldo%s17", &pmic4_nldo, "vdd-l2-l8-l17"), 676 + RPMH_VREG("ldo18", "ldo%s18", &pmic4_pldo, "vdd-l18-l22"), 677 + RPMH_VREG("ldo19", "ldo%s19", &pmic4_pldo, "vdd-l13-l19-l21"), 678 + RPMH_VREG("ldo20", "ldo%s20", &pmic4_pldo, "vdd-l20-l24"), 679 + RPMH_VREG("ldo21", "ldo%s21", &pmic4_pldo, "vdd-l13-l19-l21"), 680 + RPMH_VREG("ldo22", "ldo%s22", &pmic4_pldo, "vdd-l18-l22"), 681 + RPMH_VREG("ldo23", "ldo%s23", &pmic4_pldo, "vdd-l10-l23-l25"), 682 + RPMH_VREG("ldo24", "ldo%s24", &pmic4_pldo, "vdd-l20-l24"), 683 + RPMH_VREG("ldo25", "ldo%s25", &pmic4_pldo, "vdd-l10-l23-l25"), 684 + RPMH_VREG("ldo26", "ldo%s26", &pmic4_nldo, "vdd-l26"), 685 + RPMH_VREG("ldo27", "ldo%s27", &pmic4_nldo, "vdd-l1-l27"), 686 + RPMH_VREG("ldo28", "ldo%s28", &pmic4_pldo, "vdd-l16-l28"), 687 + RPMH_VREG("lvs1", "vs%s1", &pmic4_lvs, "vin-lvs-1-2"), 688 + RPMH_VREG("lvs2", "vs%s2", &pmic4_lvs, "vin-lvs-1-2"), 689 + {}, 690 + }; 691 + 692 + static const struct rpmh_vreg_init_data pmi8998_vreg_data[] = { 693 + RPMH_VREG("bob", "bob%s1", &pmic4_bob, "vdd-bob"), 694 + {}, 695 + }; 696 + 697 + static const struct rpmh_vreg_init_data pm8005_vreg_data[] = { 698 + RPMH_VREG("smps1", "smp%s1", &pmic4_ftsmps426, "vdd-s1"), 699 + RPMH_VREG("smps2", "smp%s2", &pmic4_ftsmps426, "vdd-s2"), 700 + RPMH_VREG("smps3", "smp%s3", &pmic4_ftsmps426, "vdd-s3"), 701 + RPMH_VREG("smps4", "smp%s4", &pmic4_ftsmps426, "vdd-s4"), 702 + {}, 703 + }; 704 + 705 + static int rpmh_regulator_probe(struct platform_device *pdev) 706 + { 707 + struct device *dev = &pdev->dev; 708 + const struct rpmh_vreg_init_data *vreg_data; 709 + struct device_node *node; 710 + struct rpmh_vreg *vreg; 711 + const char *pmic_id; 712 + int ret; 713 + 714 + vreg_data = of_device_get_match_data(dev); 715 + if (!vreg_data) 716 + return -ENODEV; 717 + 718 + ret = of_property_read_string(dev->of_node, "qcom,pmic-id", &pmic_id); 719 + if (ret < 0) { 720 + dev_err(dev, "qcom,pmic-id missing in DT node\n"); 721 + return ret; 722 + } 723 + 724 + for_each_available_child_of_node(dev->of_node, node) { 725 + vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); 726 + if (!vreg) { 727 + of_node_put(node); 728 + return -ENOMEM; 729 + } 730 + 731 + ret = rpmh_regulator_init_vreg(vreg, dev, node, pmic_id, 732 + vreg_data); 733 + if (ret < 0) { 734 + of_node_put(node); 735 + return ret; 736 + } 737 + } 738 + 739 + return 0; 740 + } 741 + 742 + static const struct of_device_id rpmh_regulator_match_table[] = { 743 + { 744 + .compatible = "qcom,pm8998-rpmh-regulators", 745 + .data = pm8998_vreg_data, 746 + }, 747 + { 748 + .compatible = "qcom,pmi8998-rpmh-regulators", 749 + .data = pmi8998_vreg_data, 750 + }, 751 + { 752 + .compatible = "qcom,pm8005-rpmh-regulators", 753 + .data = pm8005_vreg_data, 754 + }, 755 + {} 756 + }; 757 + MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table); 758 + 759 + static struct platform_driver rpmh_regulator_driver = { 760 + .driver = { 761 + .name = "qcom-rpmh-regulator", 762 + .of_match_table = of_match_ptr(rpmh_regulator_match_table), 763 + }, 764 + .probe = rpmh_regulator_probe, 765 + }; 766 + module_platform_driver(rpmh_regulator_driver); 767 + 768 + MODULE_DESCRIPTION("Qualcomm RPMh regulator driver"); 769 + MODULE_LICENSE("GPL v2");
+23 -15
drivers/regulator/qcom_spmi-regulator.c
··· 1060 1060 #define SAW3_AVS_CTL_TGGL_MASK 0x8000000 1061 1061 #define SAW3_AVS_CTL_CLEAR_MASK 0x7efc00 1062 1062 1063 - static struct regmap *saw_regmap = NULL; 1063 + static struct regmap *saw_regmap; 1064 1064 1065 1065 static void spmi_saw_set_vdd(void *data) 1066 1066 { ··· 1728 1728 { "s2", 0x1700, "vdd_s2", }, 1729 1729 { "s3", 0x1a00, "vdd_s3", }, 1730 1730 { "l1", 0x4000, "vdd_l1", }, 1731 - { } 1731 + { } 1732 1732 }; 1733 1733 1734 1734 static const struct of_device_id qcom_spmi_regulator_match[] = { ··· 1752 1752 const char *name; 1753 1753 struct device *dev = &pdev->dev; 1754 1754 struct device_node *node = pdev->dev.of_node; 1755 - struct device_node *syscon; 1755 + struct device_node *syscon, *reg_node; 1756 + struct property *reg_prop; 1756 1757 int ret, lenp; 1757 1758 struct list_head *vreg_list; 1758 1759 ··· 1775 1774 syscon = of_parse_phandle(node, "qcom,saw-reg", 0); 1776 1775 saw_regmap = syscon_node_to_regmap(syscon); 1777 1776 of_node_put(syscon); 1778 - if (IS_ERR(regmap)) 1777 + if (IS_ERR(saw_regmap)) 1779 1778 dev_err(dev, "ERROR reading SAW regmap\n"); 1780 1779 } 1781 1780 1782 1781 for (reg = match->data; reg->name; reg++) { 1783 1782 1784 - if (saw_regmap && \ 1785 - of_find_property(of_find_node_by_name(node, reg->name), \ 1786 - "qcom,saw-slave", &lenp)) { 1787 - continue; 1783 + if (saw_regmap) { 1784 + reg_node = of_get_child_by_name(node, reg->name); 1785 + reg_prop = of_find_property(reg_node, "qcom,saw-slave", 1786 + &lenp); 1787 + of_node_put(reg_node); 1788 + if (reg_prop) 1789 + continue; 1788 1790 } 1789 1791 1790 1792 vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); ··· 1820 1816 if (ret) 1821 1817 continue; 1822 1818 1823 - if (saw_regmap && \ 1824 - of_find_property(of_find_node_by_name(node, reg->name), \ 1825 - "qcom,saw-leader", &lenp)) { 1826 - spmi_saw_ops = *(vreg->desc.ops); 1827 - spmi_saw_ops.set_voltage_sel = \ 1828 - spmi_regulator_saw_set_voltage; 1829 - vreg->desc.ops = &spmi_saw_ops; 1819 + if (saw_regmap) { 1820 + reg_node = of_get_child_by_name(node, reg->name); 1821 + reg_prop = of_find_property(reg_node, "qcom,saw-leader", 1822 + &lenp); 1823 + of_node_put(reg_node); 1824 + if (reg_prop) { 1825 + spmi_saw_ops = *(vreg->desc.ops); 1826 + spmi_saw_ops.set_voltage_sel = 1827 + spmi_regulator_saw_set_voltage; 1828 + vreg->desc.ops = &spmi_saw_ops; 1829 + } 1830 1830 } 1831 1831 1832 1832 config.dev = dev;
+4 -10
drivers/regulator/s2mpa01.c
··· 1 - /* 2 - * Copyright (c) 2013 Samsung Electronics Co., Ltd 3 - * http://www.samsung.com 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms of the GNU General Public License as published by the 7 - * Free Software Foundation; either version 2 of the License, or (at your 8 - * option) any later version. 9 - * 10 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // Copyright (c) 2013 Samsung Electronics Co., Ltd 4 + // http://www.samsung.com 11 5 12 6 #include <linux/bug.h> 13 7 #include <linux/err.h>
+4 -17
drivers/regulator/s2mps11.c
··· 1 - /* 2 - * s2mps11.c 3 - * 4 - * Copyright (c) 2012-2014 Samsung Electronics Co., Ltd 5 - * http://www.samsung.com 6 - * 7 - * This program is free software; you can redistribute it and/or modify it 8 - * under the terms of the GNU General Public License as published by the 9 - * Free Software Foundation; either version 2 of the License, or (at your 10 - * option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - * GNU General Public License for more details. 16 - * 17 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // Copyright (c) 2012-2014 Samsung Electronics Co., Ltd 4 + // http://www.samsung.com 18 5 19 6 #include <linux/bug.h> 20 7 #include <linux/err.h>
+4 -12
drivers/regulator/s5m8767.c
··· 1 - /* 2 - * s5m8767.c 3 - * 4 - * Copyright (c) 2011 Samsung Electronics Co., Ltd 5 - * http://www.samsung.com 6 - * 7 - * This program is free software; you can redistribute it and/or modify it 8 - * under the terms of the GNU General Public License as published by the 9 - * Free Software Foundation; either version 2 of the License, or (at your 10 - * option) any later version. 11 - * 12 - */ 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // Copyright (c) 2011 Samsung Electronics Co., Ltd 4 + // http://www.samsung.com 13 5 14 6 #include <linux/err.h> 15 7 #include <linux/of_gpio.h>
+2
drivers/regulator/tps65217-regulator.c
··· 232 232 tps->strobes = devm_kcalloc(&pdev->dev, 233 233 TPS65217_NUM_REGULATOR, sizeof(u8), 234 234 GFP_KERNEL); 235 + if (!tps->strobes) 236 + return -ENOMEM; 235 237 236 238 platform_set_drvdata(pdev, tps); 237 239
+213
drivers/regulator/uniphier-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Regulator controller driver for UniPhier SoC 4 + // Copyright 2018 Socionext Inc. 5 + // Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 6 + 7 + #include <linux/clk.h> 8 + #include <linux/io.h> 9 + #include <linux/module.h> 10 + #include <linux/of_device.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/regmap.h> 13 + #include <linux/regulator/driver.h> 14 + #include <linux/regulator/of_regulator.h> 15 + #include <linux/reset.h> 16 + 17 + #define MAX_CLKS 2 18 + #define MAX_RSTS 2 19 + 20 + struct uniphier_regulator_soc_data { 21 + int nclks; 22 + const char * const *clock_names; 23 + int nrsts; 24 + const char * const *reset_names; 25 + const struct regulator_desc *desc; 26 + const struct regmap_config *regconf; 27 + }; 28 + 29 + struct uniphier_regulator_priv { 30 + struct clk_bulk_data clk[MAX_CLKS]; 31 + struct reset_control *rst[MAX_RSTS]; 32 + const struct uniphier_regulator_soc_data *data; 33 + }; 34 + 35 + static struct regulator_ops uniphier_regulator_ops = { 36 + .enable = regulator_enable_regmap, 37 + .disable = regulator_disable_regmap, 38 + .is_enabled = regulator_is_enabled_regmap, 39 + }; 40 + 41 + static int uniphier_regulator_probe(struct platform_device *pdev) 42 + { 43 + struct device *dev = &pdev->dev; 44 + struct uniphier_regulator_priv *priv; 45 + struct regulator_config config = { }; 46 + struct regulator_dev *rdev; 47 + struct regmap *regmap; 48 + struct resource *res; 49 + void __iomem *base; 50 + const char *name; 51 + int i, ret, nr; 52 + 53 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 54 + if (!priv) 55 + return -ENOMEM; 56 + 57 + priv->data = of_device_get_match_data(dev); 58 + if (WARN_ON(!priv->data)) 59 + return -EINVAL; 60 + 61 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 62 + base = devm_ioremap_resource(dev, res); 63 + if (IS_ERR(base)) 64 + return PTR_ERR(base); 65 + 66 + for (i = 0; i < priv->data->nclks; i++) 67 + priv->clk[i].id = priv->data->clock_names[i]; 68 + ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk); 69 + if (ret) 70 + return ret; 71 + 72 + for (i = 0; i < priv->data->nrsts; i++) { 73 + name = priv->data->reset_names[i]; 74 + priv->rst[i] = devm_reset_control_get_shared(dev, name); 75 + if (IS_ERR(priv->rst[i])) 76 + return PTR_ERR(priv->rst[i]); 77 + } 78 + 79 + ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk); 80 + if (ret) 81 + return ret; 82 + 83 + for (nr = 0; nr < priv->data->nrsts; nr++) { 84 + ret = reset_control_deassert(priv->rst[nr]); 85 + if (ret) 86 + goto out_rst_assert; 87 + } 88 + 89 + regmap = devm_regmap_init_mmio(dev, base, priv->data->regconf); 90 + if (IS_ERR(regmap)) 91 + return PTR_ERR(regmap); 92 + 93 + config.dev = dev; 94 + config.driver_data = priv; 95 + config.of_node = dev->of_node; 96 + config.regmap = regmap; 97 + config.init_data = of_get_regulator_init_data(dev, dev->of_node, 98 + priv->data->desc); 99 + rdev = devm_regulator_register(dev, priv->data->desc, &config); 100 + if (IS_ERR(rdev)) { 101 + ret = PTR_ERR(rdev); 102 + goto out_rst_assert; 103 + } 104 + 105 + platform_set_drvdata(pdev, priv); 106 + 107 + return 0; 108 + 109 + out_rst_assert: 110 + while (nr--) 111 + reset_control_assert(priv->rst[nr]); 112 + 113 + clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); 114 + 115 + return ret; 116 + } 117 + 118 + static int uniphier_regulator_remove(struct platform_device *pdev) 119 + { 120 + struct uniphier_regulator_priv *priv = platform_get_drvdata(pdev); 121 + int i; 122 + 123 + for (i = 0; i < priv->data->nrsts; i++) 124 + reset_control_assert(priv->rst[i]); 125 + 126 + clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); 127 + 128 + return 0; 129 + } 130 + 131 + /* USB3 controller data */ 132 + #define USB3VBUS_OFFSET 0x0 133 + #define USB3VBUS_REG BIT(4) 134 + #define USB3VBUS_REG_EN BIT(3) 135 + static const struct regulator_desc uniphier_usb3_regulator_desc = { 136 + .name = "vbus", 137 + .of_match = of_match_ptr("vbus"), 138 + .ops = &uniphier_regulator_ops, 139 + .type = REGULATOR_VOLTAGE, 140 + .owner = THIS_MODULE, 141 + .enable_reg = USB3VBUS_OFFSET, 142 + .enable_mask = USB3VBUS_REG_EN | USB3VBUS_REG, 143 + .enable_val = USB3VBUS_REG_EN | USB3VBUS_REG, 144 + .disable_val = USB3VBUS_REG_EN, 145 + }; 146 + 147 + static const struct regmap_config uniphier_usb3_regulator_regconf = { 148 + .reg_bits = 32, 149 + .val_bits = 32, 150 + .reg_stride = 4, 151 + .max_register = 1, 152 + }; 153 + 154 + static const char * const uniphier_pro4_clock_reset_names[] = { 155 + "gio", "link", 156 + }; 157 + 158 + static const struct uniphier_regulator_soc_data uniphier_pro4_usb3_data = { 159 + .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names), 160 + .clock_names = uniphier_pro4_clock_reset_names, 161 + .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names), 162 + .reset_names = uniphier_pro4_clock_reset_names, 163 + .desc = &uniphier_usb3_regulator_desc, 164 + .regconf = &uniphier_usb3_regulator_regconf, 165 + }; 166 + 167 + static const char * const uniphier_pxs2_clock_reset_names[] = { 168 + "link", 169 + }; 170 + 171 + static const struct uniphier_regulator_soc_data uniphier_pxs2_usb3_data = { 172 + .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), 173 + .clock_names = uniphier_pxs2_clock_reset_names, 174 + .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), 175 + .reset_names = uniphier_pxs2_clock_reset_names, 176 + .desc = &uniphier_usb3_regulator_desc, 177 + .regconf = &uniphier_usb3_regulator_regconf, 178 + }; 179 + 180 + static const struct of_device_id uniphier_regulator_match[] = { 181 + /* USB VBUS */ 182 + { 183 + .compatible = "socionext,uniphier-pro4-usb3-regulator", 184 + .data = &uniphier_pro4_usb3_data, 185 + }, 186 + { 187 + .compatible = "socionext,uniphier-pxs2-usb3-regulator", 188 + .data = &uniphier_pxs2_usb3_data, 189 + }, 190 + { 191 + .compatible = "socionext,uniphier-ld20-usb3-regulator", 192 + .data = &uniphier_pxs2_usb3_data, 193 + }, 194 + { 195 + .compatible = "socionext,uniphier-pxs3-usb3-regulator", 196 + .data = &uniphier_pxs2_usb3_data, 197 + }, 198 + { /* Sentinel */ }, 199 + }; 200 + 201 + static struct platform_driver uniphier_regulator_driver = { 202 + .probe = uniphier_regulator_probe, 203 + .remove = uniphier_regulator_remove, 204 + .driver = { 205 + .name = "uniphier-regulator", 206 + .of_match_table = uniphier_regulator_match, 207 + }, 208 + }; 209 + module_platform_driver(uniphier_regulator_driver); 210 + 211 + MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 212 + MODULE_DESCRIPTION("UniPhier Regulator Controller Driver"); 213 + MODULE_LICENSE("GPL");
+27
drivers/soc/qcom/Kconfig
··· 40 40 functions for connecting the underlying serial UART, SPI, and I2C 41 41 devices to the output pins. 42 42 43 + config QCOM_LLCC 44 + tristate "Qualcomm Technologies, Inc. LLCC driver" 45 + depends on ARCH_QCOM 46 + help 47 + Qualcomm Technologies, Inc. platform specific 48 + Last Level Cache Controller(LLCC) driver. This provides interfaces 49 + to clients that use the LLCC. Say yes here to enable LLCC slice 50 + driver. 51 + 52 + config QCOM_SDM845_LLCC 53 + tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver" 54 + depends on QCOM_LLCC 55 + help 56 + Say yes here to enable the LLCC driver for SDM845. This provides 57 + data required to configure LLCC so that clients can start using the 58 + LLCC slices. 59 + 43 60 config QCOM_MDT_LOADER 44 61 tristate 45 62 select QCOM_SCM ··· 91 74 service and its clients. 92 75 93 76 Say y here if you intend to boot the modem remoteproc. 77 + 78 + config QCOM_RPMH 79 + bool "Qualcomm RPM-Hardened (RPMH) Communication" 80 + depends on ARCH_QCOM && ARM64 && OF || COMPILE_TEST 81 + help 82 + Support for communication with the hardened-RPM blocks in 83 + Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an 84 + internal bus to transmit state requests for shared resources. A set 85 + of hardware components aggregate requests for these resources and 86 + help apply the aggregated state on the resource. 94 87 95 88 config QCOM_SMEM 96 89 tristate "Qualcomm Shared Memory Manager (SMEM)"
+6
drivers/soc/qcom/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 + CFLAGS_rpmh-rsc.o := -I$(src) 2 3 obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o 3 4 obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o 4 5 obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o ··· 9 8 obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o 10 9 qmi_helpers-y += qmi_encdec.o qmi_interface.o 11 10 obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o 11 + obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o 12 + qcom_rpmh-y += rpmh-rsc.o 13 + qcom_rpmh-y += rpmh.o 12 14 obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o 13 15 obj-$(CONFIG_QCOM_SMEM) += smem.o 14 16 obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o ··· 19 15 obj-$(CONFIG_QCOM_SMSM) += smsm.o 20 16 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o 21 17 obj-$(CONFIG_QCOM_APR) += apr.o 18 + obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o 19 + obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
+94
drivers/soc/qcom/llcc-sdm845.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. 4 + * 5 + */ 6 + 7 + #include <linux/kernel.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/of_device.h> 11 + #include <linux/soc/qcom/llcc-qcom.h> 12 + 13 + /* 14 + * SCT(System Cache Table) entry contains of the following members: 15 + * usecase_id: Unique id for the client's use case 16 + * slice_id: llcc slice id for each client 17 + * max_cap: The maximum capacity of the cache slice provided in KB 18 + * priority: Priority of the client used to select victim line for replacement 19 + * fixed_size: Boolean indicating if the slice has a fixed capacity 20 + * bonus_ways: Bonus ways are additional ways to be used for any slice, 21 + * if client ends up using more than reserved cache ways. Bonus 22 + * ways are allocated only if they are not reserved for some 23 + * other client. 24 + * res_ways: Reserved ways for the cache slice, the reserved ways cannot 25 + * be used by any other client than the one its assigned to. 26 + * cache_mode: Each slice operates as a cache, this controls the mode of the 27 + * slice: normal or TCM(Tightly Coupled Memory) 28 + * probe_target_ways: Determines what ways to probe for access hit. When 29 + * configured to 1 only bonus and reserved ways are probed. 30 + * When configured to 0 all ways in llcc are probed. 31 + * dis_cap_alloc: Disable capacity based allocation for a client 32 + * retain_on_pc: If this bit is set and client has maintained active vote 33 + * then the ways assigned to this client are not flushed on power 34 + * collapse. 35 + * activate_on_init: Activate the slice immediately after the SCT is programmed 36 + */ 37 + #define SCT_ENTRY(uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \ 38 + { \ 39 + .usecase_id = uid, \ 40 + .slice_id = sid, \ 41 + .max_cap = mc, \ 42 + .priority = p, \ 43 + .fixed_size = fs, \ 44 + .bonus_ways = bway, \ 45 + .res_ways = rway, \ 46 + .cache_mode = cmod, \ 47 + .probe_target_ways = ptw, \ 48 + .dis_cap_alloc = dca, \ 49 + .retain_on_pc = rp, \ 50 + .activate_on_init = a, \ 51 + } 52 + 53 + static struct llcc_slice_config sdm845_data[] = { 54 + SCT_ENTRY(LLCC_CPUSS, 1, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 1), 55 + SCT_ENTRY(LLCC_VIDSC0, 2, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0), 56 + SCT_ENTRY(LLCC_VIDSC1, 3, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0), 57 + SCT_ENTRY(LLCC_ROTATOR, 4, 563, 2, 1, 0x0, 0x00e, 2, 0, 1, 1, 0), 58 + SCT_ENTRY(LLCC_VOICE, 5, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 59 + SCT_ENTRY(LLCC_AUDIO, 6, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 60 + SCT_ENTRY(LLCC_MDMHPGRW, 7, 1024, 2, 0, 0xfc, 0xf00, 0, 0, 1, 1, 0), 61 + SCT_ENTRY(LLCC_MDM, 8, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 62 + SCT_ENTRY(LLCC_CMPT, 10, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 63 + SCT_ENTRY(LLCC_GPUHTW, 11, 512, 1, 1, 0xc, 0x0, 0, 0, 1, 1, 0), 64 + SCT_ENTRY(LLCC_GPU, 12, 2304, 1, 0, 0xff0, 0x2, 0, 0, 1, 1, 0), 65 + SCT_ENTRY(LLCC_MMUHWT, 13, 256, 2, 0, 0x0, 0x1, 0, 0, 1, 0, 1), 66 + SCT_ENTRY(LLCC_CMPTDMA, 15, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 67 + SCT_ENTRY(LLCC_DISP, 16, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 68 + SCT_ENTRY(LLCC_VIDFW, 17, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0), 69 + SCT_ENTRY(LLCC_MDMHPFX, 20, 1024, 2, 1, 0x0, 0xf00, 0, 0, 1, 1, 0), 70 + SCT_ENTRY(LLCC_MDMPNG, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0), 71 + SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0), 72 + }; 73 + 74 + static int sdm845_qcom_llcc_probe(struct platform_device *pdev) 75 + { 76 + return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data)); 77 + } 78 + 79 + static const struct of_device_id sdm845_qcom_llcc_of_match[] = { 80 + { .compatible = "qcom,sdm845-llcc", }, 81 + { } 82 + }; 83 + 84 + static struct platform_driver sdm845_qcom_llcc_driver = { 85 + .driver = { 86 + .name = "sdm845-llcc", 87 + .of_match_table = sdm845_qcom_llcc_of_match, 88 + }, 89 + .probe = sdm845_qcom_llcc_probe, 90 + }; 91 + module_platform_driver(sdm845_qcom_llcc_driver); 92 + 93 + MODULE_DESCRIPTION("QCOM sdm845 LLCC driver"); 94 + MODULE_LICENSE("GPL v2");
+338
drivers/soc/qcom/llcc-slice.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. 4 + * 5 + */ 6 + 7 + #include <linux/bitmap.h> 8 + #include <linux/bitops.h> 9 + #include <linux/device.h> 10 + #include <linux/io.h> 11 + #include <linux/kernel.h> 12 + #include <linux/module.h> 13 + #include <linux/mutex.h> 14 + #include <linux/of_device.h> 15 + #include <linux/regmap.h> 16 + #include <linux/slab.h> 17 + #include <linux/soc/qcom/llcc-qcom.h> 18 + 19 + #define ACTIVATE BIT(0) 20 + #define DEACTIVATE BIT(1) 21 + #define ACT_CTRL_OPCODE_ACTIVATE BIT(0) 22 + #define ACT_CTRL_OPCODE_DEACTIVATE BIT(1) 23 + #define ACT_CTRL_ACT_TRIG BIT(0) 24 + #define ACT_CTRL_OPCODE_SHIFT 0x01 25 + #define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x02 26 + #define ATTR1_FIXED_SIZE_SHIFT 0x03 27 + #define ATTR1_PRIORITY_SHIFT 0x04 28 + #define ATTR1_MAX_CAP_SHIFT 0x10 29 + #define ATTR0_RES_WAYS_MASK GENMASK(11, 0) 30 + #define ATTR0_BONUS_WAYS_MASK GENMASK(27, 16) 31 + #define ATTR0_BONUS_WAYS_SHIFT 0x10 32 + #define LLCC_STATUS_READ_DELAY 100 33 + 34 + #define CACHE_LINE_SIZE_SHIFT 6 35 + 36 + #define LLCC_COMMON_STATUS0 0x0003000c 37 + #define LLCC_LB_CNT_MASK GENMASK(31, 28) 38 + #define LLCC_LB_CNT_SHIFT 28 39 + 40 + #define MAX_CAP_TO_BYTES(n) (n * SZ_1K) 41 + #define LLCC_TRP_ACT_CTRLn(n) (n * SZ_4K) 42 + #define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K) 43 + #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n) 44 + #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n) 45 + 46 + #define BANK_OFFSET_STRIDE 0x80000 47 + 48 + static struct llcc_drv_data *drv_data; 49 + 50 + static const struct regmap_config llcc_regmap_config = { 51 + .reg_bits = 32, 52 + .reg_stride = 4, 53 + .val_bits = 32, 54 + .fast_io = true, 55 + }; 56 + 57 + /** 58 + * llcc_slice_getd - get llcc slice descriptor 59 + * @uid: usecase_id for the client 60 + * 61 + * A pointer to llcc slice descriptor will be returned on success and 62 + * and error pointer is returned on failure 63 + */ 64 + struct llcc_slice_desc *llcc_slice_getd(u32 uid) 65 + { 66 + const struct llcc_slice_config *cfg; 67 + struct llcc_slice_desc *desc; 68 + u32 sz, count; 69 + 70 + cfg = drv_data->cfg; 71 + sz = drv_data->cfg_size; 72 + 73 + for (count = 0; cfg && count < sz; count++, cfg++) 74 + if (cfg->usecase_id == uid) 75 + break; 76 + 77 + if (count == sz || !cfg) 78 + return ERR_PTR(-ENODEV); 79 + 80 + desc = kzalloc(sizeof(*desc), GFP_KERNEL); 81 + if (!desc) 82 + return ERR_PTR(-ENOMEM); 83 + 84 + desc->slice_id = cfg->slice_id; 85 + desc->slice_size = cfg->max_cap; 86 + 87 + return desc; 88 + } 89 + EXPORT_SYMBOL_GPL(llcc_slice_getd); 90 + 91 + /** 92 + * llcc_slice_putd - llcc slice descritpor 93 + * @desc: Pointer to llcc slice descriptor 94 + */ 95 + void llcc_slice_putd(struct llcc_slice_desc *desc) 96 + { 97 + kfree(desc); 98 + } 99 + EXPORT_SYMBOL_GPL(llcc_slice_putd); 100 + 101 + static int llcc_update_act_ctrl(u32 sid, 102 + u32 act_ctrl_reg_val, u32 status) 103 + { 104 + u32 act_ctrl_reg; 105 + u32 status_reg; 106 + u32 slice_status; 107 + int ret; 108 + 109 + act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid); 110 + status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid); 111 + 112 + /* Set the ACTIVE trigger */ 113 + act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG; 114 + ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); 115 + if (ret) 116 + return ret; 117 + 118 + /* Clear the ACTIVE trigger */ 119 + act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG; 120 + ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); 121 + if (ret) 122 + return ret; 123 + 124 + ret = regmap_read_poll_timeout(drv_data->regmap, status_reg, 125 + slice_status, !(slice_status & status), 126 + 0, LLCC_STATUS_READ_DELAY); 127 + return ret; 128 + } 129 + 130 + /** 131 + * llcc_slice_activate - Activate the llcc slice 132 + * @desc: Pointer to llcc slice descriptor 133 + * 134 + * A value of zero will be returned on success and a negative errno will 135 + * be returned in error cases 136 + */ 137 + int llcc_slice_activate(struct llcc_slice_desc *desc) 138 + { 139 + int ret; 140 + u32 act_ctrl_val; 141 + 142 + mutex_lock(&drv_data->lock); 143 + if (test_bit(desc->slice_id, drv_data->bitmap)) { 144 + mutex_unlock(&drv_data->lock); 145 + return 0; 146 + } 147 + 148 + act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT; 149 + 150 + ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val, 151 + DEACTIVATE); 152 + if (ret) { 153 + mutex_unlock(&drv_data->lock); 154 + return ret; 155 + } 156 + 157 + __set_bit(desc->slice_id, drv_data->bitmap); 158 + mutex_unlock(&drv_data->lock); 159 + 160 + return ret; 161 + } 162 + EXPORT_SYMBOL_GPL(llcc_slice_activate); 163 + 164 + /** 165 + * llcc_slice_deactivate - Deactivate the llcc slice 166 + * @desc: Pointer to llcc slice descriptor 167 + * 168 + * A value of zero will be returned on success and a negative errno will 169 + * be returned in error cases 170 + */ 171 + int llcc_slice_deactivate(struct llcc_slice_desc *desc) 172 + { 173 + u32 act_ctrl_val; 174 + int ret; 175 + 176 + mutex_lock(&drv_data->lock); 177 + if (!test_bit(desc->slice_id, drv_data->bitmap)) { 178 + mutex_unlock(&drv_data->lock); 179 + return 0; 180 + } 181 + act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT; 182 + 183 + ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val, 184 + ACTIVATE); 185 + if (ret) { 186 + mutex_unlock(&drv_data->lock); 187 + return ret; 188 + } 189 + 190 + __clear_bit(desc->slice_id, drv_data->bitmap); 191 + mutex_unlock(&drv_data->lock); 192 + 193 + return ret; 194 + } 195 + EXPORT_SYMBOL_GPL(llcc_slice_deactivate); 196 + 197 + /** 198 + * llcc_get_slice_id - return the slice id 199 + * @desc: Pointer to llcc slice descriptor 200 + */ 201 + int llcc_get_slice_id(struct llcc_slice_desc *desc) 202 + { 203 + return desc->slice_id; 204 + } 205 + EXPORT_SYMBOL_GPL(llcc_get_slice_id); 206 + 207 + /** 208 + * llcc_get_slice_size - return the slice id 209 + * @desc: Pointer to llcc slice descriptor 210 + */ 211 + size_t llcc_get_slice_size(struct llcc_slice_desc *desc) 212 + { 213 + return desc->slice_size; 214 + } 215 + EXPORT_SYMBOL_GPL(llcc_get_slice_size); 216 + 217 + static int qcom_llcc_cfg_program(struct platform_device *pdev) 218 + { 219 + int i; 220 + u32 attr1_cfg; 221 + u32 attr0_cfg; 222 + u32 attr1_val; 223 + u32 attr0_val; 224 + u32 max_cap_cacheline; 225 + u32 sz; 226 + int ret; 227 + const struct llcc_slice_config *llcc_table; 228 + struct llcc_slice_desc desc; 229 + u32 bcast_off = drv_data->bcast_off; 230 + 231 + sz = drv_data->cfg_size; 232 + llcc_table = drv_data->cfg; 233 + 234 + for (i = 0; i < sz; i++) { 235 + attr1_cfg = bcast_off + 236 + LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); 237 + attr0_cfg = bcast_off + 238 + LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id); 239 + 240 + attr1_val = llcc_table[i].cache_mode; 241 + attr1_val |= llcc_table[i].probe_target_ways << 242 + ATTR1_PROBE_TARGET_WAYS_SHIFT; 243 + attr1_val |= llcc_table[i].fixed_size << 244 + ATTR1_FIXED_SIZE_SHIFT; 245 + attr1_val |= llcc_table[i].priority << 246 + ATTR1_PRIORITY_SHIFT; 247 + 248 + max_cap_cacheline = MAX_CAP_TO_BYTES(llcc_table[i].max_cap); 249 + 250 + /* LLCC instances can vary for each target. 251 + * The SW writes to broadcast register which gets propagated 252 + * to each llcc instace (llcc0,.. llccN). 253 + * Since the size of the memory is divided equally amongst the 254 + * llcc instances, we need to configure the max cap accordingly. 255 + */ 256 + max_cap_cacheline = max_cap_cacheline / drv_data->num_banks; 257 + max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT; 258 + attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT; 259 + 260 + attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK; 261 + attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT; 262 + 263 + ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val); 264 + if (ret) 265 + return ret; 266 + ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val); 267 + if (ret) 268 + return ret; 269 + if (llcc_table[i].activate_on_init) { 270 + desc.slice_id = llcc_table[i].slice_id; 271 + ret = llcc_slice_activate(&desc); 272 + } 273 + } 274 + return ret; 275 + } 276 + 277 + int qcom_llcc_probe(struct platform_device *pdev, 278 + const struct llcc_slice_config *llcc_cfg, u32 sz) 279 + { 280 + u32 num_banks; 281 + struct device *dev = &pdev->dev; 282 + struct resource *res; 283 + void __iomem *base; 284 + int ret, i; 285 + 286 + drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); 287 + if (!drv_data) 288 + return -ENOMEM; 289 + 290 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 291 + base = devm_ioremap_resource(&pdev->dev, res); 292 + if (IS_ERR(base)) 293 + return PTR_ERR(base); 294 + 295 + drv_data->regmap = devm_regmap_init_mmio(dev, base, 296 + &llcc_regmap_config); 297 + if (IS_ERR(drv_data->regmap)) 298 + return PTR_ERR(drv_data->regmap); 299 + 300 + ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, 301 + &num_banks); 302 + if (ret) 303 + return ret; 304 + 305 + num_banks &= LLCC_LB_CNT_MASK; 306 + num_banks >>= LLCC_LB_CNT_SHIFT; 307 + drv_data->num_banks = num_banks; 308 + 309 + for (i = 0; i < sz; i++) 310 + if (llcc_cfg[i].slice_id > drv_data->max_slices) 311 + drv_data->max_slices = llcc_cfg[i].slice_id; 312 + 313 + drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32), 314 + GFP_KERNEL); 315 + if (!drv_data->offsets) 316 + return -ENOMEM; 317 + 318 + for (i = 0; i < num_banks; i++) 319 + drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; 320 + 321 + drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE; 322 + 323 + drv_data->bitmap = devm_kcalloc(dev, 324 + BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), 325 + GFP_KERNEL); 326 + if (!drv_data->bitmap) 327 + return -ENOMEM; 328 + 329 + drv_data->cfg = llcc_cfg; 330 + drv_data->cfg_size = sz; 331 + mutex_init(&drv_data->lock); 332 + platform_set_drvdata(pdev, drv_data); 333 + 334 + return qcom_llcc_cfg_program(pdev); 335 + } 336 + EXPORT_SYMBOL_GPL(qcom_llcc_probe); 337 + 338 + MODULE_LICENSE("GPL v2");
+1 -2
drivers/soc/qcom/rmtfs_mem.c
··· 184 184 device_initialize(&rmtfs_mem->dev); 185 185 rmtfs_mem->dev.parent = &pdev->dev; 186 186 rmtfs_mem->dev.groups = qcom_rmtfs_mem_groups; 187 + rmtfs_mem->dev.release = qcom_rmtfs_mem_release_device; 187 188 188 189 rmtfs_mem->base = devm_memremap(&rmtfs_mem->dev, rmtfs_mem->addr, 189 190 rmtfs_mem->size, MEMREMAP_WC); ··· 206 205 dev_err(&pdev->dev, "failed to add cdev: %d\n", ret); 207 206 goto put_device; 208 207 } 209 - 210 - rmtfs_mem->dev.release = qcom_rmtfs_mem_release_device; 211 208 212 209 ret = of_property_read_u32(node, "qcom,vmid", &vmid); 213 210 if (ret < 0 && ret != -EINVAL) {
+114
drivers/soc/qcom/rpmh-internal.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + 7 + #ifndef __RPM_INTERNAL_H__ 8 + #define __RPM_INTERNAL_H__ 9 + 10 + #include <linux/bitmap.h> 11 + #include <soc/qcom/tcs.h> 12 + 13 + #define TCS_TYPE_NR 4 14 + #define MAX_CMDS_PER_TCS 16 15 + #define MAX_TCS_PER_TYPE 3 16 + #define MAX_TCS_NR (MAX_TCS_PER_TYPE * TCS_TYPE_NR) 17 + #define MAX_TCS_SLOTS (MAX_CMDS_PER_TCS * MAX_TCS_PER_TYPE) 18 + 19 + struct rsc_drv; 20 + 21 + /** 22 + * struct tcs_group: group of Trigger Command Sets (TCS) to send state requests 23 + * to the controller 24 + * 25 + * @drv: the controller 26 + * @type: type of the TCS in this group - active, sleep, wake 27 + * @mask: mask of the TCSes relative to all the TCSes in the RSC 28 + * @offset: start of the TCS group relative to the TCSes in the RSC 29 + * @num_tcs: number of TCSes in this type 30 + * @ncpt: number of commands in each TCS 31 + * @lock: lock for synchronizing this TCS writes 32 + * @req: requests that are sent from the TCS 33 + * @cmd_cache: flattened cache of cmds in sleep/wake TCS 34 + * @slots: indicates which of @cmd_addr are occupied 35 + */ 36 + struct tcs_group { 37 + struct rsc_drv *drv; 38 + int type; 39 + u32 mask; 40 + u32 offset; 41 + int num_tcs; 42 + int ncpt; 43 + spinlock_t lock; 44 + const struct tcs_request *req[MAX_TCS_PER_TYPE]; 45 + u32 *cmd_cache; 46 + DECLARE_BITMAP(slots, MAX_TCS_SLOTS); 47 + }; 48 + 49 + /** 50 + * struct rpmh_request: the message to be sent to rpmh-rsc 51 + * 52 + * @msg: the request 53 + * @cmd: the payload that will be part of the @msg 54 + * @completion: triggered when request is done 55 + * @dev: the device making the request 56 + * @err: err return from the controller 57 + * @needs_free: check to free dynamically allocated request object 58 + */ 59 + struct rpmh_request { 60 + struct tcs_request msg; 61 + struct tcs_cmd cmd[MAX_RPMH_PAYLOAD]; 62 + struct completion *completion; 63 + const struct device *dev; 64 + int err; 65 + bool needs_free; 66 + }; 67 + 68 + /** 69 + * struct rpmh_ctrlr: our representation of the controller 70 + * 71 + * @cache: the list of cached requests 72 + * @cache_lock: synchronize access to the cache data 73 + * @dirty: was the cache updated since flush 74 + * @batch_cache: Cache sleep and wake requests sent as batch 75 + */ 76 + struct rpmh_ctrlr { 77 + struct list_head cache; 78 + spinlock_t cache_lock; 79 + bool dirty; 80 + struct list_head batch_cache; 81 + }; 82 + 83 + /** 84 + * struct rsc_drv: the Direct Resource Voter (DRV) of the 85 + * Resource State Coordinator controller (RSC) 86 + * 87 + * @name: controller identifier 88 + * @tcs_base: start address of the TCS registers in this controller 89 + * @id: instance id in the controller (Direct Resource Voter) 90 + * @num_tcs: number of TCSes in this DRV 91 + * @tcs: TCS groups 92 + * @tcs_in_use: s/w state of the TCS 93 + * @lock: synchronize state of the controller 94 + * @client: handle to the DRV's client. 95 + */ 96 + struct rsc_drv { 97 + const char *name; 98 + void __iomem *tcs_base; 99 + int id; 100 + int num_tcs; 101 + struct tcs_group tcs[TCS_TYPE_NR]; 102 + DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR); 103 + spinlock_t lock; 104 + struct rpmh_ctrlr client; 105 + }; 106 + 107 + int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg); 108 + int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, 109 + const struct tcs_request *msg); 110 + int rpmh_rsc_invalidate(struct rsc_drv *drv); 111 + 112 + void rpmh_tx_done(const struct tcs_request *msg, int r); 113 + 114 + #endif /* __RPM_INTERNAL_H__ */
+693
drivers/soc/qcom/rpmh-rsc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME 7 + 8 + #include <linux/atomic.h> 9 + #include <linux/delay.h> 10 + #include <linux/interrupt.h> 11 + #include <linux/io.h> 12 + #include <linux/kernel.h> 13 + #include <linux/list.h> 14 + #include <linux/of.h> 15 + #include <linux/of_irq.h> 16 + #include <linux/of_platform.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/slab.h> 19 + #include <linux/spinlock.h> 20 + 21 + #include <soc/qcom/cmd-db.h> 22 + #include <soc/qcom/tcs.h> 23 + #include <dt-bindings/soc/qcom,rpmh-rsc.h> 24 + 25 + #include "rpmh-internal.h" 26 + 27 + #define CREATE_TRACE_POINTS 28 + #include "trace-rpmh.h" 29 + 30 + #define RSC_DRV_TCS_OFFSET 672 31 + #define RSC_DRV_CMD_OFFSET 20 32 + 33 + /* DRV Configuration Information Register */ 34 + #define DRV_PRNT_CHLD_CONFIG 0x0C 35 + #define DRV_NUM_TCS_MASK 0x3F 36 + #define DRV_NUM_TCS_SHIFT 6 37 + #define DRV_NCPT_MASK 0x1F 38 + #define DRV_NCPT_SHIFT 27 39 + 40 + /* Register offsets */ 41 + #define RSC_DRV_IRQ_ENABLE 0x00 42 + #define RSC_DRV_IRQ_STATUS 0x04 43 + #define RSC_DRV_IRQ_CLEAR 0x08 44 + #define RSC_DRV_CMD_WAIT_FOR_CMPL 0x10 45 + #define RSC_DRV_CONTROL 0x14 46 + #define RSC_DRV_STATUS 0x18 47 + #define RSC_DRV_CMD_ENABLE 0x1C 48 + #define RSC_DRV_CMD_MSGID 0x30 49 + #define RSC_DRV_CMD_ADDR 0x34 50 + #define RSC_DRV_CMD_DATA 0x38 51 + #define RSC_DRV_CMD_STATUS 0x3C 52 + #define RSC_DRV_CMD_RESP_DATA 0x40 53 + 54 + #define TCS_AMC_MODE_ENABLE BIT(16) 55 + #define TCS_AMC_MODE_TRIGGER BIT(24) 56 + 57 + /* TCS CMD register bit mask */ 58 + #define CMD_MSGID_LEN 8 59 + #define CMD_MSGID_RESP_REQ BIT(8) 60 + #define CMD_MSGID_WRITE BIT(16) 61 + #define CMD_STATUS_ISSUED BIT(8) 62 + #define CMD_STATUS_COMPL BIT(16) 63 + 64 + static u32 read_tcs_reg(struct rsc_drv *drv, int reg, int tcs_id, int cmd_id) 65 + { 66 + return readl_relaxed(drv->tcs_base + reg + RSC_DRV_TCS_OFFSET * tcs_id + 67 + RSC_DRV_CMD_OFFSET * cmd_id); 68 + } 69 + 70 + static void write_tcs_cmd(struct rsc_drv *drv, int reg, int tcs_id, int cmd_id, 71 + u32 data) 72 + { 73 + writel_relaxed(data, drv->tcs_base + reg + RSC_DRV_TCS_OFFSET * tcs_id + 74 + RSC_DRV_CMD_OFFSET * cmd_id); 75 + } 76 + 77 + static void write_tcs_reg(struct rsc_drv *drv, int reg, int tcs_id, u32 data) 78 + { 79 + writel_relaxed(data, drv->tcs_base + reg + RSC_DRV_TCS_OFFSET * tcs_id); 80 + } 81 + 82 + static void write_tcs_reg_sync(struct rsc_drv *drv, int reg, int tcs_id, 83 + u32 data) 84 + { 85 + writel(data, drv->tcs_base + reg + RSC_DRV_TCS_OFFSET * tcs_id); 86 + for (;;) { 87 + if (data == readl(drv->tcs_base + reg + 88 + RSC_DRV_TCS_OFFSET * tcs_id)) 89 + break; 90 + udelay(1); 91 + } 92 + } 93 + 94 + static bool tcs_is_free(struct rsc_drv *drv, int tcs_id) 95 + { 96 + return !test_bit(tcs_id, drv->tcs_in_use) && 97 + read_tcs_reg(drv, RSC_DRV_STATUS, tcs_id, 0); 98 + } 99 + 100 + static struct tcs_group *get_tcs_of_type(struct rsc_drv *drv, int type) 101 + { 102 + return &drv->tcs[type]; 103 + } 104 + 105 + static int tcs_invalidate(struct rsc_drv *drv, int type) 106 + { 107 + int m; 108 + struct tcs_group *tcs; 109 + 110 + tcs = get_tcs_of_type(drv, type); 111 + 112 + spin_lock(&tcs->lock); 113 + if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS)) { 114 + spin_unlock(&tcs->lock); 115 + return 0; 116 + } 117 + 118 + for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) { 119 + if (!tcs_is_free(drv, m)) { 120 + spin_unlock(&tcs->lock); 121 + return -EAGAIN; 122 + } 123 + write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); 124 + } 125 + bitmap_zero(tcs->slots, MAX_TCS_SLOTS); 126 + spin_unlock(&tcs->lock); 127 + 128 + return 0; 129 + } 130 + 131 + /** 132 + * rpmh_rsc_invalidate - Invalidate sleep and wake TCSes 133 + * 134 + * @drv: the RSC controller 135 + */ 136 + int rpmh_rsc_invalidate(struct rsc_drv *drv) 137 + { 138 + int ret; 139 + 140 + ret = tcs_invalidate(drv, SLEEP_TCS); 141 + if (!ret) 142 + ret = tcs_invalidate(drv, WAKE_TCS); 143 + 144 + return ret; 145 + } 146 + 147 + static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv, 148 + const struct tcs_request *msg) 149 + { 150 + int type, ret; 151 + struct tcs_group *tcs; 152 + 153 + switch (msg->state) { 154 + case RPMH_ACTIVE_ONLY_STATE: 155 + type = ACTIVE_TCS; 156 + break; 157 + case RPMH_WAKE_ONLY_STATE: 158 + type = WAKE_TCS; 159 + break; 160 + case RPMH_SLEEP_STATE: 161 + type = SLEEP_TCS; 162 + break; 163 + default: 164 + return ERR_PTR(-EINVAL); 165 + } 166 + 167 + /* 168 + * If we are making an active request on a RSC that does not have a 169 + * dedicated TCS for active state use, then re-purpose a wake TCS to 170 + * send active votes. 171 + * NOTE: The driver must be aware that this RSC does not have a 172 + * dedicated AMC, and therefore would invalidate the sleep and wake 173 + * TCSes before making an active state request. 174 + */ 175 + tcs = get_tcs_of_type(drv, type); 176 + if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs) { 177 + tcs = get_tcs_of_type(drv, WAKE_TCS); 178 + if (tcs->num_tcs) { 179 + ret = rpmh_rsc_invalidate(drv); 180 + if (ret) 181 + return ERR_PTR(ret); 182 + } 183 + } 184 + 185 + return tcs; 186 + } 187 + 188 + static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv, 189 + int tcs_id) 190 + { 191 + struct tcs_group *tcs; 192 + int i; 193 + 194 + for (i = 0; i < TCS_TYPE_NR; i++) { 195 + tcs = &drv->tcs[i]; 196 + if (tcs->mask & BIT(tcs_id)) 197 + return tcs->req[tcs_id - tcs->offset]; 198 + } 199 + 200 + return NULL; 201 + } 202 + 203 + /** 204 + * tcs_tx_done: TX Done interrupt handler 205 + */ 206 + static irqreturn_t tcs_tx_done(int irq, void *p) 207 + { 208 + struct rsc_drv *drv = p; 209 + int i, j, err = 0; 210 + unsigned long irq_status; 211 + const struct tcs_request *req; 212 + struct tcs_cmd *cmd; 213 + 214 + irq_status = read_tcs_reg(drv, RSC_DRV_IRQ_STATUS, 0, 0); 215 + 216 + for_each_set_bit(i, &irq_status, BITS_PER_LONG) { 217 + req = get_req_from_tcs(drv, i); 218 + if (!req) { 219 + WARN_ON(1); 220 + goto skip; 221 + } 222 + 223 + err = 0; 224 + for (j = 0; j < req->num_cmds; j++) { 225 + u32 sts; 226 + 227 + cmd = &req->cmds[j]; 228 + sts = read_tcs_reg(drv, RSC_DRV_CMD_STATUS, i, j); 229 + if (!(sts & CMD_STATUS_ISSUED) || 230 + ((req->wait_for_compl || cmd->wait) && 231 + !(sts & CMD_STATUS_COMPL))) { 232 + pr_err("Incomplete request: %s: addr=%#x data=%#x", 233 + drv->name, cmd->addr, cmd->data); 234 + err = -EIO; 235 + } 236 + } 237 + 238 + trace_rpmh_tx_done(drv, i, req, err); 239 + skip: 240 + /* Reclaim the TCS */ 241 + write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); 242 + write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i)); 243 + spin_lock(&drv->lock); 244 + clear_bit(i, drv->tcs_in_use); 245 + spin_unlock(&drv->lock); 246 + if (req) 247 + rpmh_tx_done(req, err); 248 + } 249 + 250 + return IRQ_HANDLED; 251 + } 252 + 253 + static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, 254 + const struct tcs_request *msg) 255 + { 256 + u32 msgid, cmd_msgid; 257 + u32 cmd_enable = 0; 258 + u32 cmd_complete; 259 + struct tcs_cmd *cmd; 260 + int i, j; 261 + 262 + cmd_msgid = CMD_MSGID_LEN; 263 + cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0; 264 + cmd_msgid |= CMD_MSGID_WRITE; 265 + 266 + cmd_complete = read_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0); 267 + 268 + for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) { 269 + cmd = &msg->cmds[i]; 270 + cmd_enable |= BIT(j); 271 + cmd_complete |= cmd->wait << j; 272 + msgid = cmd_msgid; 273 + msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0; 274 + 275 + write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid); 276 + write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr); 277 + write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data); 278 + trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); 279 + } 280 + 281 + write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete); 282 + cmd_enable |= read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); 283 + write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable); 284 + } 285 + 286 + static void __tcs_trigger(struct rsc_drv *drv, int tcs_id) 287 + { 288 + u32 enable; 289 + 290 + /* 291 + * HW req: Clear the DRV_CONTROL and enable TCS again 292 + * While clearing ensure that the AMC mode trigger is cleared 293 + * and then the mode enable is cleared. 294 + */ 295 + enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0); 296 + enable &= ~TCS_AMC_MODE_TRIGGER; 297 + write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); 298 + enable &= ~TCS_AMC_MODE_ENABLE; 299 + write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); 300 + 301 + /* Enable the AMC mode on the TCS and then trigger the TCS */ 302 + enable = TCS_AMC_MODE_ENABLE; 303 + write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); 304 + enable |= TCS_AMC_MODE_TRIGGER; 305 + write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); 306 + } 307 + 308 + static int check_for_req_inflight(struct rsc_drv *drv, struct tcs_group *tcs, 309 + const struct tcs_request *msg) 310 + { 311 + unsigned long curr_enabled; 312 + u32 addr; 313 + int i, j, k; 314 + int tcs_id = tcs->offset; 315 + 316 + for (i = 0; i < tcs->num_tcs; i++, tcs_id++) { 317 + if (tcs_is_free(drv, tcs_id)) 318 + continue; 319 + 320 + curr_enabled = read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); 321 + 322 + for_each_set_bit(j, &curr_enabled, MAX_CMDS_PER_TCS) { 323 + addr = read_tcs_reg(drv, RSC_DRV_CMD_ADDR, tcs_id, j); 324 + for (k = 0; k < msg->num_cmds; k++) { 325 + if (addr == msg->cmds[k].addr) 326 + return -EBUSY; 327 + } 328 + } 329 + } 330 + 331 + return 0; 332 + } 333 + 334 + static int find_free_tcs(struct tcs_group *tcs) 335 + { 336 + int i; 337 + 338 + for (i = 0; i < tcs->num_tcs; i++) { 339 + if (tcs_is_free(tcs->drv, tcs->offset + i)) 340 + return tcs->offset + i; 341 + } 342 + 343 + return -EBUSY; 344 + } 345 + 346 + static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg) 347 + { 348 + struct tcs_group *tcs; 349 + int tcs_id; 350 + unsigned long flags; 351 + int ret; 352 + 353 + tcs = get_tcs_for_msg(drv, msg); 354 + if (IS_ERR(tcs)) 355 + return PTR_ERR(tcs); 356 + 357 + spin_lock_irqsave(&tcs->lock, flags); 358 + spin_lock(&drv->lock); 359 + /* 360 + * The h/w does not like if we send a request to the same address, 361 + * when one is already in-flight or being processed. 362 + */ 363 + ret = check_for_req_inflight(drv, tcs, msg); 364 + if (ret) { 365 + spin_unlock(&drv->lock); 366 + goto done_write; 367 + } 368 + 369 + tcs_id = find_free_tcs(tcs); 370 + if (tcs_id < 0) { 371 + ret = tcs_id; 372 + spin_unlock(&drv->lock); 373 + goto done_write; 374 + } 375 + 376 + tcs->req[tcs_id - tcs->offset] = msg; 377 + set_bit(tcs_id, drv->tcs_in_use); 378 + spin_unlock(&drv->lock); 379 + 380 + __tcs_buffer_write(drv, tcs_id, 0, msg); 381 + __tcs_trigger(drv, tcs_id); 382 + 383 + done_write: 384 + spin_unlock_irqrestore(&tcs->lock, flags); 385 + return ret; 386 + } 387 + 388 + /** 389 + * rpmh_rsc_send_data: Validate the incoming message and write to the 390 + * appropriate TCS block. 391 + * 392 + * @drv: the controller 393 + * @msg: the data to be sent 394 + * 395 + * Return: 0 on success, -EINVAL on error. 396 + * Note: This call blocks until a valid data is written to the TCS. 397 + */ 398 + int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) 399 + { 400 + int ret; 401 + 402 + if (!msg || !msg->cmds || !msg->num_cmds || 403 + msg->num_cmds > MAX_RPMH_PAYLOAD) { 404 + WARN_ON(1); 405 + return -EINVAL; 406 + } 407 + 408 + do { 409 + ret = tcs_write(drv, msg); 410 + if (ret == -EBUSY) { 411 + pr_info_ratelimited("TCS Busy, retrying RPMH message send: addr=%#x\n", 412 + msg->cmds[0].addr); 413 + udelay(10); 414 + } 415 + } while (ret == -EBUSY); 416 + 417 + return ret; 418 + } 419 + 420 + static int find_match(const struct tcs_group *tcs, const struct tcs_cmd *cmd, 421 + int len) 422 + { 423 + int i, j; 424 + 425 + /* Check for already cached commands */ 426 + for_each_set_bit(i, tcs->slots, MAX_TCS_SLOTS) { 427 + if (tcs->cmd_cache[i] != cmd[0].addr) 428 + continue; 429 + if (i + len >= tcs->num_tcs * tcs->ncpt) 430 + goto seq_err; 431 + for (j = 0; j < len; j++) { 432 + if (tcs->cmd_cache[i + j] != cmd[j].addr) 433 + goto seq_err; 434 + } 435 + return i; 436 + } 437 + 438 + return -ENODATA; 439 + 440 + seq_err: 441 + WARN(1, "Message does not match previous sequence.\n"); 442 + return -EINVAL; 443 + } 444 + 445 + static int find_slots(struct tcs_group *tcs, const struct tcs_request *msg, 446 + int *tcs_id, int *cmd_id) 447 + { 448 + int slot, offset; 449 + int i = 0; 450 + 451 + /* Find if we already have the msg in our TCS */ 452 + slot = find_match(tcs, msg->cmds, msg->num_cmds); 453 + if (slot >= 0) 454 + goto copy_data; 455 + 456 + /* Do over, until we can fit the full payload in a TCS */ 457 + do { 458 + slot = bitmap_find_next_zero_area(tcs->slots, MAX_TCS_SLOTS, 459 + i, msg->num_cmds, 0); 460 + if (slot == tcs->num_tcs * tcs->ncpt) 461 + return -ENOMEM; 462 + i += tcs->ncpt; 463 + } while (slot + msg->num_cmds - 1 >= i); 464 + 465 + copy_data: 466 + bitmap_set(tcs->slots, slot, msg->num_cmds); 467 + /* Copy the addresses of the resources over to the slots */ 468 + for (i = 0; i < msg->num_cmds; i++) 469 + tcs->cmd_cache[slot + i] = msg->cmds[i].addr; 470 + 471 + offset = slot / tcs->ncpt; 472 + *tcs_id = offset + tcs->offset; 473 + *cmd_id = slot % tcs->ncpt; 474 + 475 + return 0; 476 + } 477 + 478 + static int tcs_ctrl_write(struct rsc_drv *drv, const struct tcs_request *msg) 479 + { 480 + struct tcs_group *tcs; 481 + int tcs_id = 0, cmd_id = 0; 482 + unsigned long flags; 483 + int ret; 484 + 485 + tcs = get_tcs_for_msg(drv, msg); 486 + if (IS_ERR(tcs)) 487 + return PTR_ERR(tcs); 488 + 489 + spin_lock_irqsave(&tcs->lock, flags); 490 + /* find the TCS id and the command in the TCS to write to */ 491 + ret = find_slots(tcs, msg, &tcs_id, &cmd_id); 492 + if (!ret) 493 + __tcs_buffer_write(drv, tcs_id, cmd_id, msg); 494 + spin_unlock_irqrestore(&tcs->lock, flags); 495 + 496 + return ret; 497 + } 498 + 499 + /** 500 + * rpmh_rsc_write_ctrl_data: Write request to the controller 501 + * 502 + * @drv: the controller 503 + * @msg: the data to be written to the controller 504 + * 505 + * There is no response returned for writing the request to the controller. 506 + */ 507 + int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, const struct tcs_request *msg) 508 + { 509 + if (!msg || !msg->cmds || !msg->num_cmds || 510 + msg->num_cmds > MAX_RPMH_PAYLOAD) { 511 + pr_err("Payload error\n"); 512 + return -EINVAL; 513 + } 514 + 515 + /* Data sent to this API will not be sent immediately */ 516 + if (msg->state == RPMH_ACTIVE_ONLY_STATE) 517 + return -EINVAL; 518 + 519 + return tcs_ctrl_write(drv, msg); 520 + } 521 + 522 + static int rpmh_probe_tcs_config(struct platform_device *pdev, 523 + struct rsc_drv *drv) 524 + { 525 + struct tcs_type_config { 526 + u32 type; 527 + u32 n; 528 + } tcs_cfg[TCS_TYPE_NR] = { { 0 } }; 529 + struct device_node *dn = pdev->dev.of_node; 530 + u32 config, max_tcs, ncpt, offset; 531 + int i, ret, n, st = 0; 532 + struct tcs_group *tcs; 533 + struct resource *res; 534 + void __iomem *base; 535 + char drv_id[10] = {0}; 536 + 537 + snprintf(drv_id, ARRAY_SIZE(drv_id), "drv-%d", drv->id); 538 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, drv_id); 539 + base = devm_ioremap_resource(&pdev->dev, res); 540 + if (IS_ERR(base)) 541 + return PTR_ERR(base); 542 + 543 + ret = of_property_read_u32(dn, "qcom,tcs-offset", &offset); 544 + if (ret) 545 + return ret; 546 + drv->tcs_base = base + offset; 547 + 548 + config = readl_relaxed(base + DRV_PRNT_CHLD_CONFIG); 549 + 550 + max_tcs = config; 551 + max_tcs &= DRV_NUM_TCS_MASK << (DRV_NUM_TCS_SHIFT * drv->id); 552 + max_tcs = max_tcs >> (DRV_NUM_TCS_SHIFT * drv->id); 553 + 554 + ncpt = config & (DRV_NCPT_MASK << DRV_NCPT_SHIFT); 555 + ncpt = ncpt >> DRV_NCPT_SHIFT; 556 + 557 + n = of_property_count_u32_elems(dn, "qcom,tcs-config"); 558 + if (n != 2 * TCS_TYPE_NR) 559 + return -EINVAL; 560 + 561 + for (i = 0; i < TCS_TYPE_NR; i++) { 562 + ret = of_property_read_u32_index(dn, "qcom,tcs-config", 563 + i * 2, &tcs_cfg[i].type); 564 + if (ret) 565 + return ret; 566 + if (tcs_cfg[i].type >= TCS_TYPE_NR) 567 + return -EINVAL; 568 + 569 + ret = of_property_read_u32_index(dn, "qcom,tcs-config", 570 + i * 2 + 1, &tcs_cfg[i].n); 571 + if (ret) 572 + return ret; 573 + if (tcs_cfg[i].n > MAX_TCS_PER_TYPE) 574 + return -EINVAL; 575 + } 576 + 577 + for (i = 0; i < TCS_TYPE_NR; i++) { 578 + tcs = &drv->tcs[tcs_cfg[i].type]; 579 + if (tcs->drv) 580 + return -EINVAL; 581 + tcs->drv = drv; 582 + tcs->type = tcs_cfg[i].type; 583 + tcs->num_tcs = tcs_cfg[i].n; 584 + tcs->ncpt = ncpt; 585 + spin_lock_init(&tcs->lock); 586 + 587 + if (!tcs->num_tcs || tcs->type == CONTROL_TCS) 588 + continue; 589 + 590 + if (st + tcs->num_tcs > max_tcs || 591 + st + tcs->num_tcs >= BITS_PER_BYTE * sizeof(tcs->mask)) 592 + return -EINVAL; 593 + 594 + tcs->mask = ((1 << tcs->num_tcs) - 1) << st; 595 + tcs->offset = st; 596 + st += tcs->num_tcs; 597 + 598 + /* 599 + * Allocate memory to cache sleep and wake requests to 600 + * avoid reading TCS register memory. 601 + */ 602 + if (tcs->type == ACTIVE_TCS) 603 + continue; 604 + 605 + tcs->cmd_cache = devm_kcalloc(&pdev->dev, 606 + tcs->num_tcs * ncpt, sizeof(u32), 607 + GFP_KERNEL); 608 + if (!tcs->cmd_cache) 609 + return -ENOMEM; 610 + } 611 + 612 + drv->num_tcs = st; 613 + 614 + return 0; 615 + } 616 + 617 + static int rpmh_rsc_probe(struct platform_device *pdev) 618 + { 619 + struct device_node *dn = pdev->dev.of_node; 620 + struct rsc_drv *drv; 621 + int ret, irq; 622 + 623 + /* 624 + * Even though RPMh doesn't directly use cmd-db, all of its children 625 + * do. To avoid adding this check to our children we'll do it now. 626 + */ 627 + ret = cmd_db_ready(); 628 + if (ret) { 629 + if (ret != -EPROBE_DEFER) 630 + dev_err(&pdev->dev, "Command DB not available (%d)\n", 631 + ret); 632 + return ret; 633 + } 634 + 635 + drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); 636 + if (!drv) 637 + return -ENOMEM; 638 + 639 + ret = of_property_read_u32(dn, "qcom,drv-id", &drv->id); 640 + if (ret) 641 + return ret; 642 + 643 + drv->name = of_get_property(dn, "label", NULL); 644 + if (!drv->name) 645 + drv->name = dev_name(&pdev->dev); 646 + 647 + ret = rpmh_probe_tcs_config(pdev, drv); 648 + if (ret) 649 + return ret; 650 + 651 + spin_lock_init(&drv->lock); 652 + bitmap_zero(drv->tcs_in_use, MAX_TCS_NR); 653 + 654 + irq = platform_get_irq(pdev, drv->id); 655 + if (irq < 0) 656 + return irq; 657 + 658 + ret = devm_request_irq(&pdev->dev, irq, tcs_tx_done, 659 + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, 660 + drv->name, drv); 661 + if (ret) 662 + return ret; 663 + 664 + /* Enable the active TCS to send requests immediately */ 665 + write_tcs_reg(drv, RSC_DRV_IRQ_ENABLE, 0, drv->tcs[ACTIVE_TCS].mask); 666 + 667 + spin_lock_init(&drv->client.cache_lock); 668 + INIT_LIST_HEAD(&drv->client.cache); 669 + INIT_LIST_HEAD(&drv->client.batch_cache); 670 + 671 + dev_set_drvdata(&pdev->dev, drv); 672 + 673 + return devm_of_platform_populate(&pdev->dev); 674 + } 675 + 676 + static const struct of_device_id rpmh_drv_match[] = { 677 + { .compatible = "qcom,rpmh-rsc", }, 678 + { } 679 + }; 680 + 681 + static struct platform_driver rpmh_driver = { 682 + .probe = rpmh_rsc_probe, 683 + .driver = { 684 + .name = "rpmh", 685 + .of_match_table = rpmh_drv_match, 686 + }, 687 + }; 688 + 689 + static int __init rpmh_driver_init(void) 690 + { 691 + return platform_driver_register(&rpmh_driver); 692 + } 693 + arch_initcall(rpmh_driver_init);
+513
drivers/soc/qcom/rpmh.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #include <linux/atomic.h> 7 + #include <linux/bug.h> 8 + #include <linux/interrupt.h> 9 + #include <linux/jiffies.h> 10 + #include <linux/kernel.h> 11 + #include <linux/list.h> 12 + #include <linux/module.h> 13 + #include <linux/of.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/slab.h> 16 + #include <linux/spinlock.h> 17 + #include <linux/types.h> 18 + #include <linux/wait.h> 19 + 20 + #include <soc/qcom/rpmh.h> 21 + 22 + #include "rpmh-internal.h" 23 + 24 + #define RPMH_TIMEOUT_MS msecs_to_jiffies(10000) 25 + 26 + #define DEFINE_RPMH_MSG_ONSTACK(dev, s, q, name) \ 27 + struct rpmh_request name = { \ 28 + .msg = { \ 29 + .state = s, \ 30 + .cmds = name.cmd, \ 31 + .num_cmds = 0, \ 32 + .wait_for_compl = true, \ 33 + }, \ 34 + .cmd = { { 0 } }, \ 35 + .completion = q, \ 36 + .dev = dev, \ 37 + .needs_free = false, \ 38 + } 39 + 40 + #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client) 41 + 42 + /** 43 + * struct cache_req: the request object for caching 44 + * 45 + * @addr: the address of the resource 46 + * @sleep_val: the sleep vote 47 + * @wake_val: the wake vote 48 + * @list: linked list obj 49 + */ 50 + struct cache_req { 51 + u32 addr; 52 + u32 sleep_val; 53 + u32 wake_val; 54 + struct list_head list; 55 + }; 56 + 57 + /** 58 + * struct batch_cache_req - An entry in our batch catch 59 + * 60 + * @list: linked list obj 61 + * @count: number of messages 62 + * @rpm_msgs: the messages 63 + */ 64 + 65 + struct batch_cache_req { 66 + struct list_head list; 67 + int count; 68 + struct rpmh_request rpm_msgs[]; 69 + }; 70 + 71 + static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev) 72 + { 73 + struct rsc_drv *drv = dev_get_drvdata(dev->parent); 74 + 75 + return &drv->client; 76 + } 77 + 78 + void rpmh_tx_done(const struct tcs_request *msg, int r) 79 + { 80 + struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, 81 + msg); 82 + struct completion *compl = rpm_msg->completion; 83 + 84 + rpm_msg->err = r; 85 + 86 + if (r) 87 + dev_err(rpm_msg->dev, "RPMH TX fail in msg addr=%#x, err=%d\n", 88 + rpm_msg->msg.cmds[0].addr, r); 89 + 90 + if (!compl) 91 + goto exit; 92 + 93 + /* Signal the blocking thread we are done */ 94 + complete(compl); 95 + 96 + exit: 97 + if (rpm_msg->needs_free) 98 + kfree(rpm_msg); 99 + } 100 + 101 + static struct cache_req *__find_req(struct rpmh_ctrlr *ctrlr, u32 addr) 102 + { 103 + struct cache_req *p, *req = NULL; 104 + 105 + list_for_each_entry(p, &ctrlr->cache, list) { 106 + if (p->addr == addr) { 107 + req = p; 108 + break; 109 + } 110 + } 111 + 112 + return req; 113 + } 114 + 115 + static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr, 116 + enum rpmh_state state, 117 + struct tcs_cmd *cmd) 118 + { 119 + struct cache_req *req; 120 + unsigned long flags; 121 + 122 + spin_lock_irqsave(&ctrlr->cache_lock, flags); 123 + req = __find_req(ctrlr, cmd->addr); 124 + if (req) 125 + goto existing; 126 + 127 + req = kzalloc(sizeof(*req), GFP_ATOMIC); 128 + if (!req) { 129 + req = ERR_PTR(-ENOMEM); 130 + goto unlock; 131 + } 132 + 133 + req->addr = cmd->addr; 134 + req->sleep_val = req->wake_val = UINT_MAX; 135 + INIT_LIST_HEAD(&req->list); 136 + list_add_tail(&req->list, &ctrlr->cache); 137 + 138 + existing: 139 + switch (state) { 140 + case RPMH_ACTIVE_ONLY_STATE: 141 + if (req->sleep_val != UINT_MAX) 142 + req->wake_val = cmd->data; 143 + break; 144 + case RPMH_WAKE_ONLY_STATE: 145 + req->wake_val = cmd->data; 146 + break; 147 + case RPMH_SLEEP_STATE: 148 + req->sleep_val = cmd->data; 149 + break; 150 + default: 151 + break; 152 + } 153 + 154 + ctrlr->dirty = true; 155 + unlock: 156 + spin_unlock_irqrestore(&ctrlr->cache_lock, flags); 157 + 158 + return req; 159 + } 160 + 161 + /** 162 + * __rpmh_write: Cache and send the RPMH request 163 + * 164 + * @dev: The device making the request 165 + * @state: Active/Sleep request type 166 + * @rpm_msg: The data that needs to be sent (cmds). 167 + * 168 + * Cache the RPMH request and send if the state is ACTIVE_ONLY. 169 + * SLEEP/WAKE_ONLY requests are not sent to the controller at 170 + * this time. Use rpmh_flush() to send them to the controller. 171 + */ 172 + static int __rpmh_write(const struct device *dev, enum rpmh_state state, 173 + struct rpmh_request *rpm_msg) 174 + { 175 + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 176 + int ret = -EINVAL; 177 + struct cache_req *req; 178 + int i; 179 + 180 + rpm_msg->msg.state = state; 181 + 182 + /* Cache the request in our store and link the payload */ 183 + for (i = 0; i < rpm_msg->msg.num_cmds; i++) { 184 + req = cache_rpm_request(ctrlr, state, &rpm_msg->msg.cmds[i]); 185 + if (IS_ERR(req)) 186 + return PTR_ERR(req); 187 + } 188 + 189 + rpm_msg->msg.state = state; 190 + 191 + if (state == RPMH_ACTIVE_ONLY_STATE) { 192 + WARN_ON(irqs_disabled()); 193 + ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg); 194 + } else { 195 + ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr), 196 + &rpm_msg->msg); 197 + /* Clean up our call by spoofing tx_done */ 198 + rpmh_tx_done(&rpm_msg->msg, ret); 199 + } 200 + 201 + return ret; 202 + } 203 + 204 + static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state, 205 + const struct tcs_cmd *cmd, u32 n) 206 + { 207 + if (!cmd || !n || n > MAX_RPMH_PAYLOAD) 208 + return -EINVAL; 209 + 210 + memcpy(req->cmd, cmd, n * sizeof(*cmd)); 211 + 212 + req->msg.state = state; 213 + req->msg.cmds = req->cmd; 214 + req->msg.num_cmds = n; 215 + 216 + return 0; 217 + } 218 + 219 + /** 220 + * rpmh_write_async: Write a set of RPMH commands 221 + * 222 + * @dev: The device making the request 223 + * @state: Active/sleep set 224 + * @cmd: The payload data 225 + * @n: The number of elements in payload 226 + * 227 + * Write a set of RPMH commands, the order of commands is maintained 228 + * and will be sent as a single shot. 229 + */ 230 + int rpmh_write_async(const struct device *dev, enum rpmh_state state, 231 + const struct tcs_cmd *cmd, u32 n) 232 + { 233 + struct rpmh_request *rpm_msg; 234 + int ret; 235 + 236 + rpm_msg = kzalloc(sizeof(*rpm_msg), GFP_ATOMIC); 237 + if (!rpm_msg) 238 + return -ENOMEM; 239 + rpm_msg->needs_free = true; 240 + 241 + ret = __fill_rpmh_msg(rpm_msg, state, cmd, n); 242 + if (ret) { 243 + kfree(rpm_msg); 244 + return ret; 245 + } 246 + 247 + return __rpmh_write(dev, state, rpm_msg); 248 + } 249 + EXPORT_SYMBOL(rpmh_write_async); 250 + 251 + /** 252 + * rpmh_write: Write a set of RPMH commands and block until response 253 + * 254 + * @rc: The RPMH handle got from rpmh_get_client 255 + * @state: Active/sleep set 256 + * @cmd: The payload data 257 + * @n: The number of elements in @cmd 258 + * 259 + * May sleep. Do not call from atomic contexts. 260 + */ 261 + int rpmh_write(const struct device *dev, enum rpmh_state state, 262 + const struct tcs_cmd *cmd, u32 n) 263 + { 264 + DECLARE_COMPLETION_ONSTACK(compl); 265 + DEFINE_RPMH_MSG_ONSTACK(dev, state, &compl, rpm_msg); 266 + int ret; 267 + 268 + if (!cmd || !n || n > MAX_RPMH_PAYLOAD) 269 + return -EINVAL; 270 + 271 + memcpy(rpm_msg.cmd, cmd, n * sizeof(*cmd)); 272 + rpm_msg.msg.num_cmds = n; 273 + 274 + ret = __rpmh_write(dev, state, &rpm_msg); 275 + if (ret) 276 + return ret; 277 + 278 + ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); 279 + WARN_ON(!ret); 280 + return (ret > 0) ? 0 : -ETIMEDOUT; 281 + } 282 + EXPORT_SYMBOL(rpmh_write); 283 + 284 + static void cache_batch(struct rpmh_ctrlr *ctrlr, struct batch_cache_req *req) 285 + { 286 + unsigned long flags; 287 + 288 + spin_lock_irqsave(&ctrlr->cache_lock, flags); 289 + list_add_tail(&req->list, &ctrlr->batch_cache); 290 + spin_unlock_irqrestore(&ctrlr->cache_lock, flags); 291 + } 292 + 293 + static int flush_batch(struct rpmh_ctrlr *ctrlr) 294 + { 295 + struct batch_cache_req *req; 296 + const struct rpmh_request *rpm_msg; 297 + unsigned long flags; 298 + int ret = 0; 299 + int i; 300 + 301 + /* Send Sleep/Wake requests to the controller, expect no response */ 302 + spin_lock_irqsave(&ctrlr->cache_lock, flags); 303 + list_for_each_entry(req, &ctrlr->batch_cache, list) { 304 + for (i = 0; i < req->count; i++) { 305 + rpm_msg = req->rpm_msgs + i; 306 + ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr), 307 + &rpm_msg->msg); 308 + if (ret) 309 + break; 310 + } 311 + } 312 + spin_unlock_irqrestore(&ctrlr->cache_lock, flags); 313 + 314 + return ret; 315 + } 316 + 317 + static void invalidate_batch(struct rpmh_ctrlr *ctrlr) 318 + { 319 + struct batch_cache_req *req, *tmp; 320 + unsigned long flags; 321 + 322 + spin_lock_irqsave(&ctrlr->cache_lock, flags); 323 + list_for_each_entry_safe(req, tmp, &ctrlr->batch_cache, list) 324 + kfree(req); 325 + INIT_LIST_HEAD(&ctrlr->batch_cache); 326 + spin_unlock_irqrestore(&ctrlr->cache_lock, flags); 327 + } 328 + 329 + /** 330 + * rpmh_write_batch: Write multiple sets of RPMH commands and wait for the 331 + * batch to finish. 332 + * 333 + * @dev: the device making the request 334 + * @state: Active/sleep set 335 + * @cmd: The payload data 336 + * @n: The array of count of elements in each batch, 0 terminated. 337 + * 338 + * Write a request to the RSC controller without caching. If the request 339 + * state is ACTIVE, then the requests are treated as completion request 340 + * and sent to the controller immediately. The function waits until all the 341 + * commands are complete. If the request was to SLEEP or WAKE_ONLY, then the 342 + * request is sent as fire-n-forget and no ack is expected. 343 + * 344 + * May sleep. Do not call from atomic contexts for ACTIVE_ONLY requests. 345 + */ 346 + int rpmh_write_batch(const struct device *dev, enum rpmh_state state, 347 + const struct tcs_cmd *cmd, u32 *n) 348 + { 349 + struct batch_cache_req *req; 350 + struct rpmh_request *rpm_msgs; 351 + DECLARE_COMPLETION_ONSTACK(compl); 352 + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 353 + unsigned long time_left; 354 + int count = 0; 355 + int ret, i, j; 356 + 357 + if (!cmd || !n) 358 + return -EINVAL; 359 + 360 + while (n[count] > 0) 361 + count++; 362 + if (!count) 363 + return -EINVAL; 364 + 365 + req = kzalloc(sizeof(*req) + count * sizeof(req->rpm_msgs[0]), 366 + GFP_ATOMIC); 367 + if (!req) 368 + return -ENOMEM; 369 + req->count = count; 370 + rpm_msgs = req->rpm_msgs; 371 + 372 + for (i = 0; i < count; i++) { 373 + __fill_rpmh_msg(rpm_msgs + i, state, cmd, n[i]); 374 + cmd += n[i]; 375 + } 376 + 377 + if (state != RPMH_ACTIVE_ONLY_STATE) { 378 + cache_batch(ctrlr, req); 379 + return 0; 380 + } 381 + 382 + for (i = 0; i < count; i++) { 383 + rpm_msgs[i].completion = &compl; 384 + ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg); 385 + if (ret) { 386 + pr_err("Error(%d) sending RPMH message addr=%#x\n", 387 + ret, rpm_msgs[i].msg.cmds[0].addr); 388 + for (j = i; j < count; j++) 389 + rpmh_tx_done(&rpm_msgs[j].msg, ret); 390 + break; 391 + } 392 + } 393 + 394 + time_left = RPMH_TIMEOUT_MS; 395 + for (i = 0; i < count; i++) { 396 + time_left = wait_for_completion_timeout(&compl, time_left); 397 + if (!time_left) { 398 + /* 399 + * Better hope they never finish because they'll signal 400 + * the completion on our stack and that's bad once 401 + * we've returned from the function. 402 + */ 403 + WARN_ON(1); 404 + ret = -ETIMEDOUT; 405 + goto exit; 406 + } 407 + } 408 + 409 + exit: 410 + kfree(req); 411 + 412 + return ret; 413 + } 414 + EXPORT_SYMBOL(rpmh_write_batch); 415 + 416 + static int is_req_valid(struct cache_req *req) 417 + { 418 + return (req->sleep_val != UINT_MAX && 419 + req->wake_val != UINT_MAX && 420 + req->sleep_val != req->wake_val); 421 + } 422 + 423 + static int send_single(const struct device *dev, enum rpmh_state state, 424 + u32 addr, u32 data) 425 + { 426 + DEFINE_RPMH_MSG_ONSTACK(dev, state, NULL, rpm_msg); 427 + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 428 + 429 + /* Wake sets are always complete and sleep sets are not */ 430 + rpm_msg.msg.wait_for_compl = (state == RPMH_WAKE_ONLY_STATE); 431 + rpm_msg.cmd[0].addr = addr; 432 + rpm_msg.cmd[0].data = data; 433 + rpm_msg.msg.num_cmds = 1; 434 + 435 + return rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr), &rpm_msg.msg); 436 + } 437 + 438 + /** 439 + * rpmh_flush: Flushes the buffered active and sleep sets to TCS 440 + * 441 + * @dev: The device making the request 442 + * 443 + * Return: -EBUSY if the controller is busy, probably waiting on a response 444 + * to a RPMH request sent earlier. 445 + * 446 + * This function is always called from the sleep code from the last CPU 447 + * that is powering down the entire system. Since no other RPMH API would be 448 + * executing at this time, it is safe to run lockless. 449 + */ 450 + int rpmh_flush(const struct device *dev) 451 + { 452 + struct cache_req *p; 453 + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 454 + int ret; 455 + 456 + if (!ctrlr->dirty) { 457 + pr_debug("Skipping flush, TCS has latest data.\n"); 458 + return 0; 459 + } 460 + 461 + /* First flush the cached batch requests */ 462 + ret = flush_batch(ctrlr); 463 + if (ret) 464 + return ret; 465 + 466 + /* 467 + * Nobody else should be calling this function other than system PM, 468 + * hence we can run without locks. 469 + */ 470 + list_for_each_entry(p, &ctrlr->cache, list) { 471 + if (!is_req_valid(p)) { 472 + pr_debug("%s: skipping RPMH req: a:%#x s:%#x w:%#x", 473 + __func__, p->addr, p->sleep_val, p->wake_val); 474 + continue; 475 + } 476 + ret = send_single(dev, RPMH_SLEEP_STATE, p->addr, p->sleep_val); 477 + if (ret) 478 + return ret; 479 + ret = send_single(dev, RPMH_WAKE_ONLY_STATE, 480 + p->addr, p->wake_val); 481 + if (ret) 482 + return ret; 483 + } 484 + 485 + ctrlr->dirty = false; 486 + 487 + return 0; 488 + } 489 + EXPORT_SYMBOL(rpmh_flush); 490 + 491 + /** 492 + * rpmh_invalidate: Invalidate all sleep and active sets 493 + * sets. 494 + * 495 + * @dev: The device making the request 496 + * 497 + * Invalidate the sleep and active values in the TCS blocks. 498 + */ 499 + int rpmh_invalidate(const struct device *dev) 500 + { 501 + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 502 + int ret; 503 + 504 + invalidate_batch(ctrlr); 505 + ctrlr->dirty = true; 506 + 507 + do { 508 + ret = rpmh_rsc_invalidate(ctrlr_to_drv(ctrlr)); 509 + } while (ret == -EAGAIN); 510 + 511 + return ret; 512 + } 513 + EXPORT_SYMBOL(rpmh_invalidate);
+5 -5
drivers/soc/qcom/smem.c
··· 364 364 end = phdr_to_last_uncached_entry(phdr); 365 365 cached = phdr_to_last_cached_entry(phdr); 366 366 367 - if (smem->global_partition) { 368 - dev_err(smem->dev, "Already found the global partition\n"); 369 - return -EINVAL; 370 - } 371 - 372 367 while (hdr < end) { 373 368 if (hdr->canary != SMEM_PRIVATE_CANARY) 374 369 goto bad_canary; ··· 730 735 u32 host0, host1, size; 731 736 bool found = false; 732 737 int i; 738 + 739 + if (smem->global_partition) { 740 + dev_err(smem->dev, "Already found the global partition\n"); 741 + return -EINVAL; 742 + } 733 743 734 744 ptable = qcom_smem_get_ptable(smem); 735 745 if (IS_ERR(ptable))
+82
drivers/soc/qcom/trace-rpmh.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #if !defined(_TRACE_RPMH_H) || defined(TRACE_HEADER_MULTI_READ) 7 + #define _TRACE_RPMH_H 8 + 9 + #undef TRACE_SYSTEM 10 + #define TRACE_SYSTEM rpmh 11 + 12 + #include <linux/tracepoint.h> 13 + #include "rpmh-internal.h" 14 + 15 + TRACE_EVENT(rpmh_tx_done, 16 + 17 + TP_PROTO(struct rsc_drv *d, int m, const struct tcs_request *r, int e), 18 + 19 + TP_ARGS(d, m, r, e), 20 + 21 + TP_STRUCT__entry( 22 + __string(name, d->name) 23 + __field(int, m) 24 + __field(u32, addr) 25 + __field(u32, data) 26 + __field(int, err) 27 + ), 28 + 29 + TP_fast_assign( 30 + __assign_str(name, d->name); 31 + __entry->m = m; 32 + __entry->addr = r->cmds[0].addr; 33 + __entry->data = r->cmds[0].data; 34 + __entry->err = e; 35 + ), 36 + 37 + TP_printk("%s: ack: tcs-m: %d addr: %#x data: %#x errno: %d", 38 + __get_str(name), __entry->m, __entry->addr, __entry->data, 39 + __entry->err) 40 + ); 41 + 42 + TRACE_EVENT(rpmh_send_msg, 43 + 44 + TP_PROTO(struct rsc_drv *d, int m, int n, u32 h, 45 + const struct tcs_cmd *c), 46 + 47 + TP_ARGS(d, m, n, h, c), 48 + 49 + TP_STRUCT__entry( 50 + __string(name, d->name) 51 + __field(int, m) 52 + __field(int, n) 53 + __field(u32, hdr) 54 + __field(u32, addr) 55 + __field(u32, data) 56 + __field(bool, wait) 57 + ), 58 + 59 + TP_fast_assign( 60 + __assign_str(name, d->name); 61 + __entry->m = m; 62 + __entry->n = n; 63 + __entry->hdr = h; 64 + __entry->addr = c->addr; 65 + __entry->data = c->data; 66 + __entry->wait = c->wait; 67 + ), 68 + 69 + TP_printk("%s: send-msg: tcs(m): %d cmd(n): %d msgid: %#x addr: %#x data: %#x complete: %d", 70 + __get_str(name), __entry->m, __entry->n, __entry->hdr, 71 + __entry->addr, __entry->data, __entry->wait) 72 + ); 73 + 74 + #endif /* _TRACE_RPMH_H */ 75 + 76 + #undef TRACE_INCLUDE_PATH 77 + #define TRACE_INCLUDE_PATH . 78 + 79 + #undef TRACE_INCLUDE_FILE 80 + #define TRACE_INCLUDE_FILE trace-rpmh 81 + 82 + #include <trace/define_trace.h>
+1 -4
include/dt-bindings/regulator/maxim,max77802.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 1 2 /* 2 3 * Copyright (C) 2014 Google, Inc 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 4 * 8 5 * Device Tree binding constants for the Maxim 77802 PMIC regulators 9 6 */
+36
include/dt-bindings/regulator/qcom,rpmh-regulator.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018, The Linux Foundation. All rights reserved. */ 3 + 4 + #ifndef __QCOM_RPMH_REGULATOR_H 5 + #define __QCOM_RPMH_REGULATOR_H 6 + 7 + /* 8 + * These mode constants may be used to specify modes for various RPMh regulator 9 + * device tree properties (e.g. regulator-initial-mode). Each type of regulator 10 + * supports a subset of the possible modes. 11 + * 12 + * %RPMH_REGULATOR_MODE_RET: Retention mode in which only an extremely small 13 + * load current is allowed. This mode is supported 14 + * by LDO and SMPS type regulators. 15 + * %RPMH_REGULATOR_MODE_LPM: Low power mode in which a small load current is 16 + * allowed. This mode corresponds to PFM for SMPS 17 + * and BOB type regulators. This mode is supported 18 + * by LDO, HFSMPS, BOB, and PMIC4 FTSMPS type 19 + * regulators. 20 + * %RPMH_REGULATOR_MODE_AUTO: Auto mode in which the regulator hardware 21 + * automatically switches between LPM and HPM based 22 + * upon the real-time load current. This mode is 23 + * supported by HFSMPS, BOB, and PMIC4 FTSMPS type 24 + * regulators. 25 + * %RPMH_REGULATOR_MODE_HPM: High power mode in which the full rated current 26 + * of the regulator is allowed. This mode 27 + * corresponds to PWM for SMPS and BOB type 28 + * regulators. This mode is supported by all types 29 + * of regulators. 30 + */ 31 + #define RPMH_REGULATOR_MODE_RET 0 32 + #define RPMH_REGULATOR_MODE_LPM 1 33 + #define RPMH_REGULATOR_MODE_AUTO 2 34 + #define RPMH_REGULATOR_MODE_HPM 3 35 + 36 + #endif
+14
include/dt-bindings/soc/qcom,rpmh-rsc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #ifndef __DT_QCOM_RPMH_RSC_H__ 7 + #define __DT_QCOM_RPMH_RSC_H__ 8 + 9 + #define SLEEP_TCS 0 10 + #define WAKE_TCS 1 11 + #define ACTIVE_TCS 2 12 + #define CONTROL_TCS 3 13 + 14 + #endif /* __DT_QCOM_RPMH_RSC_H__ */
+1
include/linux/device.h
··· 1316 1316 struct device_link *device_link_add(struct device *consumer, 1317 1317 struct device *supplier, u32 flags); 1318 1318 void device_link_del(struct device_link *link); 1319 + void device_link_remove(void *consumer, struct device *supplier); 1319 1320 1320 1321 #ifdef CONFIG_PRINTK 1321 1322
+4
include/linux/qcom_scm.h
··· 87 87 static inline int 88 88 qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; } 89 89 static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } 90 + static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, 91 + unsigned int *src, 92 + struct qcom_scm_vmperm *newvm, 93 + int dest_cnt) { return -ENODEV; } 90 94 static inline void qcom_scm_cpu_power_down(u32 flags) {} 91 95 static inline u32 qcom_scm_get_version(void) { return 0; } 92 96 static inline u32
+2 -2
include/linux/regulator/driver.h
··· 46 46 /** 47 47 * struct regulator_linear_range - specify linear voltage ranges 48 48 * 49 - * Specify a range of voltages for regulator_map_linar_range() and 49 + * Specify a range of voltages for regulator_map_linear_range() and 50 50 * regulator_list_linear_range(). 51 51 * 52 52 * @min_uV: Lowest voltage in range ··· 220 220 /* set regulator suspend operating mode (defined in consumer.h) */ 221 221 int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode); 222 222 223 - int (*resume_early)(struct regulator_dev *rdev); 223 + int (*resume)(struct regulator_dev *rdev); 224 224 225 225 int (*set_pull_down) (struct regulator_dev *); 226 226 };
+11
include/linux/regulator/pfuze100.h
··· 64 64 #define PFUZE3000_VLDO3 11 65 65 #define PFUZE3000_VLDO4 12 66 66 67 + #define PFUZE3001_SW1 0 68 + #define PFUZE3001_SW2 1 69 + #define PFUZE3001_SW3 2 70 + #define PFUZE3001_VSNVS 3 71 + #define PFUZE3001_VLDO1 4 72 + #define PFUZE3001_VLDO2 5 73 + #define PFUZE3001_VCCSD 6 74 + #define PFUZE3001_V33 7 75 + #define PFUZE3001_VLDO3 8 76 + #define PFUZE3001_VLDO4 9 77 + 67 78 struct regulator_init_data; 68 79 69 80 struct pfuze_regulator_platform_data {
+180
include/linux/soc/qcom/llcc-qcom.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. 4 + * 5 + */ 6 + 7 + #include <linux/platform_device.h> 8 + #ifndef __LLCC_QCOM__ 9 + #define __LLCC_QCOM__ 10 + 11 + #define LLCC_CPUSS 1 12 + #define LLCC_VIDSC0 2 13 + #define LLCC_VIDSC1 3 14 + #define LLCC_ROTATOR 4 15 + #define LLCC_VOICE 5 16 + #define LLCC_AUDIO 6 17 + #define LLCC_MDMHPGRW 7 18 + #define LLCC_MDM 8 19 + #define LLCC_CMPT 10 20 + #define LLCC_GPUHTW 11 21 + #define LLCC_GPU 12 22 + #define LLCC_MMUHWT 13 23 + #define LLCC_CMPTDMA 15 24 + #define LLCC_DISP 16 25 + #define LLCC_VIDFW 17 26 + #define LLCC_MDMHPFX 20 27 + #define LLCC_MDMPNG 21 28 + #define LLCC_AUDHW 22 29 + 30 + /** 31 + * llcc_slice_desc - Cache slice descriptor 32 + * @slice_id: llcc slice id 33 + * @slice_size: Size allocated for the llcc slice 34 + */ 35 + struct llcc_slice_desc { 36 + u32 slice_id; 37 + size_t slice_size; 38 + }; 39 + 40 + /** 41 + * llcc_slice_config - Data associated with the llcc slice 42 + * @usecase_id: usecase id for which the llcc slice is used 43 + * @slice_id: llcc slice id assigned to each slice 44 + * @max_cap: maximum capacity of the llcc slice 45 + * @priority: priority of the llcc slice 46 + * @fixed_size: whether the llcc slice can grow beyond its size 47 + * @bonus_ways: bonus ways associated with llcc slice 48 + * @res_ways: reserved ways associated with llcc slice 49 + * @cache_mode: mode of the llcc slice 50 + * @probe_target_ways: Probe only reserved and bonus ways on a cache miss 51 + * @dis_cap_alloc: Disable capacity based allocation 52 + * @retain_on_pc: Retain through power collapse 53 + * @activate_on_init: activate the slice on init 54 + */ 55 + struct llcc_slice_config { 56 + u32 usecase_id; 57 + u32 slice_id; 58 + u32 max_cap; 59 + u32 priority; 60 + bool fixed_size; 61 + u32 bonus_ways; 62 + u32 res_ways; 63 + u32 cache_mode; 64 + u32 probe_target_ways; 65 + bool dis_cap_alloc; 66 + bool retain_on_pc; 67 + bool activate_on_init; 68 + }; 69 + 70 + /** 71 + * llcc_drv_data - Data associated with the llcc driver 72 + * @regmap: regmap associated with the llcc device 73 + * @cfg: pointer to the data structure for slice configuration 74 + * @lock: mutex associated with each slice 75 + * @cfg_size: size of the config data table 76 + * @max_slices: max slices as read from device tree 77 + * @bcast_off: Offset of the broadcast bank 78 + * @num_banks: Number of llcc banks 79 + * @bitmap: Bit map to track the active slice ids 80 + * @offsets: Pointer to the bank offsets array 81 + */ 82 + struct llcc_drv_data { 83 + struct regmap *regmap; 84 + const struct llcc_slice_config *cfg; 85 + struct mutex lock; 86 + u32 cfg_size; 87 + u32 max_slices; 88 + u32 bcast_off; 89 + u32 num_banks; 90 + unsigned long *bitmap; 91 + u32 *offsets; 92 + }; 93 + 94 + #if IS_ENABLED(CONFIG_QCOM_LLCC) 95 + /** 96 + * llcc_slice_getd - get llcc slice descriptor 97 + * @uid: usecase_id of the client 98 + */ 99 + struct llcc_slice_desc *llcc_slice_getd(u32 uid); 100 + 101 + /** 102 + * llcc_slice_putd - llcc slice descritpor 103 + * @desc: Pointer to llcc slice descriptor 104 + */ 105 + void llcc_slice_putd(struct llcc_slice_desc *desc); 106 + 107 + /** 108 + * llcc_get_slice_id - get slice id 109 + * @desc: Pointer to llcc slice descriptor 110 + */ 111 + int llcc_get_slice_id(struct llcc_slice_desc *desc); 112 + 113 + /** 114 + * llcc_get_slice_size - llcc slice size 115 + * @desc: Pointer to llcc slice descriptor 116 + */ 117 + size_t llcc_get_slice_size(struct llcc_slice_desc *desc); 118 + 119 + /** 120 + * llcc_slice_activate - Activate the llcc slice 121 + * @desc: Pointer to llcc slice descriptor 122 + */ 123 + int llcc_slice_activate(struct llcc_slice_desc *desc); 124 + 125 + /** 126 + * llcc_slice_deactivate - Deactivate the llcc slice 127 + * @desc: Pointer to llcc slice descriptor 128 + */ 129 + int llcc_slice_deactivate(struct llcc_slice_desc *desc); 130 + 131 + /** 132 + * qcom_llcc_probe - program the sct table 133 + * @pdev: platform device pointer 134 + * @table: soc sct table 135 + * @sz: Size of the config table 136 + */ 137 + int qcom_llcc_probe(struct platform_device *pdev, 138 + const struct llcc_slice_config *table, u32 sz); 139 + #else 140 + static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid) 141 + { 142 + return NULL; 143 + } 144 + 145 + static inline void llcc_slice_putd(struct llcc_slice_desc *desc) 146 + { 147 + 148 + }; 149 + 150 + static inline int llcc_get_slice_id(struct llcc_slice_desc *desc) 151 + { 152 + return -EINVAL; 153 + } 154 + 155 + static inline size_t llcc_get_slice_size(struct llcc_slice_desc *desc) 156 + { 157 + return 0; 158 + } 159 + static inline int llcc_slice_activate(struct llcc_slice_desc *desc) 160 + { 161 + return -EINVAL; 162 + } 163 + 164 + static inline int llcc_slice_deactivate(struct llcc_slice_desc *desc) 165 + { 166 + return -EINVAL; 167 + } 168 + static inline int qcom_llcc_probe(struct platform_device *pdev, 169 + const struct llcc_slice_config *table, u32 sz) 170 + { 171 + return -ENODEV; 172 + } 173 + 174 + static inline int qcom_llcc_remove(struct platform_device *pdev) 175 + { 176 + return -ENODEV; 177 + } 178 + #endif 179 + 180 + #endif
+51
include/soc/qcom/rpmh.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #ifndef __SOC_QCOM_RPMH_H__ 7 + #define __SOC_QCOM_RPMH_H__ 8 + 9 + #include <soc/qcom/tcs.h> 10 + #include <linux/platform_device.h> 11 + 12 + 13 + #if IS_ENABLED(CONFIG_QCOM_RPMH) 14 + int rpmh_write(const struct device *dev, enum rpmh_state state, 15 + const struct tcs_cmd *cmd, u32 n); 16 + 17 + int rpmh_write_async(const struct device *dev, enum rpmh_state state, 18 + const struct tcs_cmd *cmd, u32 n); 19 + 20 + int rpmh_write_batch(const struct device *dev, enum rpmh_state state, 21 + const struct tcs_cmd *cmd, u32 *n); 22 + 23 + int rpmh_flush(const struct device *dev); 24 + 25 + int rpmh_invalidate(const struct device *dev); 26 + 27 + #else 28 + 29 + static inline int rpmh_write(const struct device *dev, enum rpmh_state state, 30 + const struct tcs_cmd *cmd, u32 n) 31 + { return -ENODEV; } 32 + 33 + static inline int rpmh_write_async(const struct device *dev, 34 + enum rpmh_state state, 35 + const struct tcs_cmd *cmd, u32 n) 36 + { return -ENODEV; } 37 + 38 + static inline int rpmh_write_batch(const struct device *dev, 39 + enum rpmh_state state, 40 + const struct tcs_cmd *cmd, u32 *n) 41 + { return -ENODEV; } 42 + 43 + static inline int rpmh_flush(const struct device *dev) 44 + { return -ENODEV; } 45 + 46 + static inline int rpmh_invalidate(const struct device *dev) 47 + { return -ENODEV; } 48 + 49 + #endif /* CONFIG_QCOM_RPMH */ 50 + 51 + #endif /* __SOC_QCOM_RPMH_H__ */
+56
include/soc/qcom/tcs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #ifndef __SOC_QCOM_TCS_H__ 7 + #define __SOC_QCOM_TCS_H__ 8 + 9 + #define MAX_RPMH_PAYLOAD 16 10 + 11 + /** 12 + * rpmh_state: state for the request 13 + * 14 + * RPMH_SLEEP_STATE: State of the resource when the processor subsystem 15 + * is powered down. There is no client using the 16 + * resource actively. 17 + * RPMH_WAKE_ONLY_STATE: Resume resource state to the value previously 18 + * requested before the processor was powered down. 19 + * RPMH_ACTIVE_ONLY_STATE: Active or AMC mode requests. Resource state 20 + * is aggregated immediately. 21 + */ 22 + enum rpmh_state { 23 + RPMH_SLEEP_STATE, 24 + RPMH_WAKE_ONLY_STATE, 25 + RPMH_ACTIVE_ONLY_STATE, 26 + }; 27 + 28 + /** 29 + * struct tcs_cmd: an individual request to RPMH. 30 + * 31 + * @addr: the address of the resource slv_id:18:16 | offset:0:15 32 + * @data: the resource state request 33 + * @wait: wait for this request to be complete before sending the next 34 + */ 35 + struct tcs_cmd { 36 + u32 addr; 37 + u32 data; 38 + u32 wait; 39 + }; 40 + 41 + /** 42 + * struct tcs_request: A set of tcs_cmds sent together in a TCS 43 + * 44 + * @state: state for the request. 45 + * @wait_for_compl: wait until we get a response from the h/w accelerator 46 + * @num_cmds: the number of @cmds in this request 47 + * @cmds: an array of tcs_cmds 48 + */ 49 + struct tcs_request { 50 + enum rpmh_state state; 51 + u32 wait_for_compl; 52 + u32 num_cmds; 53 + struct tcs_cmd *cmds; 54 + }; 55 + 56 + #endif /* __SOC_QCOM_TCS_H__ */