Merge 1bdd629e5a ("Merge tag 'ovl-update-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs") into android-mainline

Steps on the way to 5.16-rc1

Resolves conflicts in:
    fs/overlayfs/file.c

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I78b4136a37129bcbd964bebc95243a51831bb7e6
This commit is contained in:
Greg Kroah-Hartman
2021-11-15 19:01:38 +01:00
263 changed files with 4126 additions and 3850 deletions

View File

@@ -73,6 +73,8 @@ Chris Chiu <chris.chiu@canonical.com> <chiu@endlessm.com>
Chris Chiu <chris.chiu@canonical.com> <chiu@endlessos.org>
Christophe Ricard <christophe.ricard@gmail.com>
Christoph Hellwig <hch@lst.de>
Colin Ian King <colin.king@intel.com> <colin.king@canonical.com>
Colin Ian King <colin.king@intel.com> <colin.i.king@gmail.com>
Corey Minyard <minyard@acm.org>
Damian Hobson-Garcia <dhobsong@igel.co.jp>
Daniel Borkmann <daniel@iogearbox.net> <danborkmann@googlemail.com>

View File

@@ -50,6 +50,7 @@ program using kcov:
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/types.h>
#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long)
#define KCOV_ENABLE _IO('c', 100)
@@ -177,6 +178,8 @@ Comparison operands collection is similar to coverage collection:
/* Read number of comparisons collected. */
n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
for (i = 0; i < n; i++) {
uint64_t ip;
type = cover[i * KCOV_WORDS_PER_CMP + 1];
/* arg1 and arg2 - operands of the comparison. */
arg1 = cover[i * KCOV_WORDS_PER_CMP + 2];
@@ -251,6 +254,8 @@ selectively from different subsystems.
.. code-block:: c
/* Same includes and defines as above. */
struct kcov_remote_arg {
__u32 trace_mode;
__u32 area_size;

View File

@@ -49,7 +49,7 @@ Example:
max77686: max77686@9 {
compatible = "maxim,max77686";
interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>;
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
reg = <0x09>;
#clock-cells = <1>;
@@ -74,7 +74,7 @@ Example:
max77802: max77802@9 {
compatible = "maxim,max77802";
interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>;
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
reg = <0x09>;
#clock-cells = <1>;

View File

@@ -1,75 +0,0 @@
AXP209 GPIO & pinctrl controller
This driver follows the usual GPIO bindings found in
Documentation/devicetree/bindings/gpio/gpio.txt
This driver follows the usual pinctrl bindings found in
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
This driver employs the per-pin muxing pattern.
Required properties:
- compatible: Should be one of:
- "x-powers,axp209-gpio"
- "x-powers,axp813-gpio"
- #gpio-cells: Should be two. The first cell is the pin number and the
second is the GPIO flags.
- gpio-controller: Marks the device node as a GPIO controller.
This node must be a subnode of the axp20x PMIC, documented in
Documentation/devicetree/bindings/mfd/axp20x.txt
Example:
axp209: pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
axp_gpio: gpio {
compatible = "x-powers,axp209-gpio";
gpio-controller;
#gpio-cells = <2>;
};
};
The GPIOs can be muxed to other functions and therefore, must be a subnode of
axp_gpio.
Example:
&axp_gpio {
gpio0_adc: gpio0-adc {
pins = "GPIO0";
function = "adc";
};
};
&example_node {
pinctrl-names = "default";
pinctrl-0 = <&gpio0_adc>;
};
GPIOs and their functions
-------------------------
Each GPIO is independent from the other (i.e. GPIO0 in gpio_in function does
not force GPIO1 and GPIO2 to be in gpio_in function as well).
axp209
------
GPIO | Functions
------------------------
GPIO0 | gpio_in, gpio_out, ldo, adc
GPIO1 | gpio_in, gpio_out, ldo, adc
GPIO2 | gpio_in, gpio_out
axp813
------
GPIO | Functions
------------------------
GPIO0 | gpio_in, gpio_out, ldo, adc
GPIO1 | gpio_in, gpio_out, ldo

View File

@@ -0,0 +1,55 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: "http://devicetree.org/schemas/gpio/x-powers,axp209-gpio.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: X-Powers AXP209 GPIO Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
properties:
"#gpio-cells":
const: 2
description: >
The first cell is the pin number and the second is the GPIO flags.
compatible:
oneOf:
- enum:
- x-powers,axp209-gpio
- x-powers,axp813-gpio
- items:
- const: x-powers,axp803-gpio
- const: x-powers,axp813-gpio
gpio-controller: true
patternProperties:
"^.*-pins?$":
$ref: /schemas/pinctrl/pinmux-node.yaml#
properties:
pins:
items:
enum:
- GPIO0
- GPIO1
- GPIO2
function:
enum:
- adc
- ldo
- gpio_in
- gpio_out
required:
- compatible
- "#gpio-cells"
- gpio-controller
additionalProperties: false
...

View File

@@ -55,7 +55,7 @@ examples:
#size-cells = <0>;
axp221: pmic@68 {
compatible = "x-powers,axp221";
/* compatible = "x-powers,axp221"; */
reg = <0x68>;
};
};

View File

@@ -0,0 +1,70 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/ti,am3359-adc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI AM3359 ADC
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
properties:
compatible:
enum:
- ti,am3359-adc
- ti,am4372-adc
'#io-channel-cells':
const: 1
ti,adc-channels:
description: List of analog inputs available for ADC. AIN0 = 0, AIN1 = 1 and
so on until AIN7 = 7.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
ti,chan-step-opendelay:
description: List of open delays for each channel of ADC in the order of
ti,adc-channels. The value corresponds to the number of ADC clock cycles
to wait after applying the step configuration registers and before sending
the start of ADC conversion. Maximum value is 0x3FFFF.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
ti,chan-step-sampledelay:
description: List of sample delays for each channel of ADC in the order of
ti,adc-channels. The value corresponds to the number of ADC clock cycles
to sample (to hold start of conversion high). Maximum value is 0xFF.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
ti,chan-step-avg:
description: Number of averages to be performed for each channel of ADC. If
average is 16 (this is also the maximum) then input is sampled 16 times
and averaged to get more accurate value. This increases the time taken by
ADC to generate a sample. Maximum value is 16.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
required:
- compatible
- '#io-channel-cells'
- ti,adc-channels
additionalProperties: false
examples:
- |
adc {
compatible = "ti,am3359-adc";
#io-channel-cells = <1>;
ti,adc-channels = <4 5 6 7>;
ti,chan-step-opendelay = <0x098 0x3ffff 0x098 0x0>;
ti,chan-step-sampledelay = <0xff 0x0 0xf 0x0>;
ti,chan-step-avg = <16 2 4 8>;
};

View File

@@ -0,0 +1,76 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/ti,am3359-tsc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI AM3359 Touchscreen controller
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
properties:
compatible:
const: ti,am3359-tsc
ti,wires:
description: Wires refer to application modes i.e. 4/5/8 wire touchscreen
support on the platform.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [4, 5, 8]
ti,x-plate-resistance:
description: X plate resistance
$ref: /schemas/types.yaml#/definitions/uint32
ti,coordinate-readouts:
description: The sequencer supports a total of 16 programmable steps. Each
step is used to read a single coordinate. A single readout is enough but
multiple reads can increase the quality. A value of 5 means, 5 reads for
X, 5 for Y and 2 for Z (always). This utilises 12 of the 16 software steps
available. The remaining 4 can be used by the ADC.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 6
ti,wire-config:
description: Different boards could have a different order for connecting
wires on touchscreen. We need to provide an 8-bit number where the
first four bits represent the analog lines and the next 4 bits represent
positive/negative terminal on that input line. Notations to represent the
input lines and terminals respectively are as follows, AIN0 = 0, AIN1 = 1
and so on until AIN7 = 7. XP = 0, XN = 1, YP = 2, YN = 3.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 4
maxItems: 8
ti,charge-delay:
description: Length of touch screen charge delay step in terms of ADC clock
cycles. Charge delay value should be large in order to avoid false pen-up
events. This value effects the overall sampling speed, hence need to be
kept as low as possible, while avoiding false pen-up event. Start from a
lower value, say 0x400, and increase value until false pen-up events are
avoided. The pen-up detection happens immediately after the charge step,
so this does in fact function as a hardware knob for adjusting the amount
of "settling time".
$ref: /schemas/types.yaml#/definitions/uint32
required:
- compatible
- ti,wires
- ti,x-plate-resistance
- ti,coordinate-readouts
- ti,wire-config
additionalProperties: false
examples:
- |
tsc {
compatible = "ti,am3359-tsc";
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,coordinate-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
ti,charge-delay = <0x400>;
};

View File

@@ -1,91 +0,0 @@
* TI - TSC ADC (Touschscreen and analog digital converter)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Required properties:
- mfd
compatible: Should be
"ti,am3359-tscadc" for AM335x/AM437x SoCs
"ti,am654-tscadc", "ti,am3359-tscadc" for AM654 SoCs
- child "tsc"
compatible: Should be "ti,am3359-tsc".
ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen
support on the platform.
ti,x-plate-resistance: X plate resistance
ti,coordinate-readouts: The sequencer supports a total of 16
programmable steps each step is used to
read a single coordinate. A single
readout is enough but multiple reads can
increase the quality.
A value of 5 means, 5 reads for X, 5 for
Y and 2 for Z (always). This utilises 12
of the 16 software steps available. The
remaining 4 can be used by the ADC.
ti,wire-config: Different boards could have a different order for
connecting wires on touchscreen. We need to provide an
8 bit number where in the 1st four bits represent the
analog lines and the next 4 bits represent positive/
negative terminal on that input line. Notations to
represent the input lines and terminals resoectively
is as follows:
AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
XP = 0, XN = 1, YP = 2, YN = 3.
- child "adc"
compatible: Should be
"ti,am3359-adc" for AM335x/AM437x SoCs
"ti,am654-adc", "ti,am3359-adc" for AM654 SoCs
ti,adc-channels: List of analog inputs available for ADC.
AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
Optional properties:
- child "tsc"
ti,charge-delay: Length of touch screen charge delay step in terms of
ADC clock cycles. Charge delay value should be large
in order to avoid false pen-up events. This value
effects the overall sampling speed, hence need to be
kept as low as possible, while avoiding false pen-up
event. Start from a lower value, say 0x400, and
increase value until false pen-up events are avoided.
The pen-up detection happens immediately after the
charge step, so this does in fact function as a
hardware knob for adjusting the amount of "settling
time".
- child "adc"
ti,chan-step-opendelay: List of open delays for each channel of
ADC in the order of ti,adc-channels. The
value corresponds to the number of ADC
clock cycles to wait after applying the
step configuration registers and before
sending the start of ADC conversion.
Maximum value is 0x3FFFF.
ti,chan-step-sampledelay: List of sample delays for each channel
of ADC in the order of ti,adc-channels.
The value corresponds to the number of
ADC clock cycles to sample (to hold
start of conversion high).
Maximum value is 0xFF.
ti,chan-step-avg: Number of averages to be performed for each
channel of ADC. If average is 16 then input
is sampled 16 times and averaged to get more
accurate value. This increases the time taken
by ADC to generate a sample. Valid range is 0
average to 16 averages. Maximum value is 16.
Example:
tscadc: tscadc@44e0d000 {
compatible = "ti,am3359-tscadc";
tsc {
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,coordiante-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
ti,charge-delay = <0x400>;
};
adc {
ti,adc-channels = <4 5 6 7>;
ti,chan-step-opendelay = <0x098 0x3ffff 0x098 0x0>;
ti,chan-step-sampledelay = <0xff 0x0 0xf 0x0>;
ti,chan-step-avg = <16 2 4 8>;
};
}

View File

@@ -1,50 +0,0 @@
X-Powers AC100 Codec/RTC IC Device Tree bindings
AC100 is a audio codec and RTC subsystem combo IC. The 2 parts are
separated, including power supplies and interrupt lines, but share
a common register address space and host interface.
Required properties:
- compatible: "x-powers,ac100"
- reg: The I2C slave address or RSB hardware address for the chip
- sub-nodes:
- codec
- compatible: "x-powers,ac100-codec"
- interrupts: SoC NMI / GPIO interrupt connected to the
IRQ_AUDIO pin
- #clock-cells: Shall be 0
- clock-output-names: "4M_adda"
- see clock/clock-bindings.txt for common clock bindings
- rtc
- compatible: "x-powers,ac100-rtc"
- clocks: A phandle to the codec's "4M_adda" clock
- #clock-cells: Shall be 1
- clock-output-names: "cko1_rtc", "cko2_rtc", "cko3_rtc"
- see clock/clock-bindings.txt for common clock bindings
Example:
ac100: codec@e89 {
compatible = "x-powers,ac100";
reg = <0xe89>;
ac100_codec: codec {
compatible = "x-powers,ac100-codec";
interrupt-parent = <&r_pio>;
interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PL9 */
#clock-cells = <0>;
clock-output-names = "4M_adda";
};
ac100_rtc: rtc {
compatible = "x-powers,ac100-rtc";
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
clocks = <&ac100_codec>;
#clock-cells = <1>;
clock-output-names = "cko1_rtc", "cko2_rtc", "cko3_rtc";
};
};

View File

@@ -1,273 +0,0 @@
AXP family PMIC device tree bindings
The axp20x family current members :
axp152 (X-Powers)
axp202 (X-Powers)
axp209 (X-Powers)
axp221 (X-Powers)
axp223 (X-Powers)
axp803 (X-Powers)
axp806 (X-Powers)
axp809 (X-Powers)
axp813 (X-Powers)
The AXP813 is 2 chips packaged into 1. The 2 chips do not share anything
other than the packaging. Pins are routed separately. As such they should
be treated as separate entities. The other half is an AC100 RTC/codec
combo chip. Please see ./ac100.txt for its bindings.
Required properties:
- compatible: should be one of:
* "x-powers,axp152"
* "x-powers,axp202"
* "x-powers,axp209"
* "x-powers,axp221"
* "x-powers,axp223"
* "x-powers,axp803"
* "x-powers,axp806"
* "x-powers,axp805", "x-powers,axp806"
* "x-powers,axp305", "x-powers,axp805", "x-powers,axp806"
* "x-powers,axp809"
* "x-powers,axp813"
- reg: The I2C slave address or RSB hardware address for the AXP chip
- interrupt-controller: The PMIC has its own internal IRQs
- #interrupt-cells: Should be set to 1
Supported common regulator properties, see ../regulator/regulator.txt for
more information:
- regulator-ramp-delay: sets the ramp up delay in uV/us
AXP20x/DCDC2: 1600, 800
AXP20x/LDO3: 1600, 800
- regulator-soft-start: enable the output at the lowest possible voltage and
only then set the desired voltage
AXP20x/LDO3: software-based implementation
Optional properties:
- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
AXP152/20X: range: 750-1875, Default: 1.5 MHz
AXP22X/8XX: range: 1800-4050, Default: 3 MHz
- x-powers,drive-vbus-en: boolean, set this when the N_VBUSEN pin is
used as an output pin to control an external
regulator to drive the OTG VBus, rather then
as an input pin which signals whether the
board is driving OTG VBus or not.
(axp221 / axp223 / axp803/ axp813 only)
- x-powers,self-working-mode and
x-powers,master-mode: Boolean (axp806 only). Set either of these when the
PMIC is wired for self-working mode or master mode.
If neither is set then slave mode is assumed.
This corresponds to how the MODESET pin is wired.
- <input>-supply: a phandle to the regulator supply node. May be omitted if
inputs are unregulated, such as using the IPSOUT output
from the PMIC.
- regulators: A node that houses a sub-node for each regulator. Regulators
not used but preferred to be managed by the OS should be
listed as well.
See Documentation/devicetree/bindings/regulator/regulator.txt
for more information on standard regulator bindings.
Optional properties for DCDC regulators:
- x-powers,dcdc-workmode: 1 for PWM mode, 0 for AUTO (PWM/PFM) mode
Default: Current hardware setting
The DCDC regulators work in a mixed PWM/PFM mode,
using PFM under light loads and switching to PWM
for heavier loads. Forcing PWM mode trades efficiency
under light loads for lower output noise. This
probably makes sense for HiFi audio related
applications that aren't battery constrained.
AXP202/AXP209 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDC2 : DC-DC buck : vin2-supply
DCDC3 : DC-DC buck : vin3-supply
LDO1 : LDO : acin-supply : always on
LDO2 : LDO : ldo24in-supply : shared supply
LDO3 : LDO : ldo3in-supply
LDO4 : LDO : ldo24in-supply : shared supply
LDO5 : LDO : ldo5in-supply
AXP221/AXP223 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDC1 : DC-DC buck : vin1-supply
DCDC2 : DC-DC buck : vin2-supply
DCDC3 : DC-DC buck : vin3-supply
DCDC4 : DC-DC buck : vin4-supply
DCDC5 : DC-DC buck : vin5-supply
DC1SW : On/Off Switch : : DCDC1 secondary output
DC5LDO : LDO : : input from DCDC5
ALDO1 : LDO : aldoin-supply : shared supply
ALDO2 : LDO : aldoin-supply : shared supply
ALDO3 : LDO : aldoin-supply : shared supply
DLDO1 : LDO : dldoin-supply : shared supply
DLDO2 : LDO : dldoin-supply : shared supply
DLDO3 : LDO : dldoin-supply : shared supply
DLDO4 : LDO : dldoin-supply : shared supply
ELDO1 : LDO : eldoin-supply : shared supply
ELDO2 : LDO : eldoin-supply : shared supply
ELDO3 : LDO : eldoin-supply : shared supply
LDO_IO0 : LDO : ips-supply : GPIO 0
LDO_IO1 : LDO : ips-supply : GPIO 1
RTC_LDO : LDO : ips-supply : always on
DRIVEVBUS : Enable output : drivevbus-supply : external regulator
AXP803 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDC1 : DC-DC buck : vin1-supply
DCDC2 : DC-DC buck : vin2-supply : poly-phase capable
DCDC3 : DC-DC buck : vin3-supply : poly-phase capable
DCDC4 : DC-DC buck : vin4-supply
DCDC5 : DC-DC buck : vin5-supply : poly-phase capable
DCDC6 : DC-DC buck : vin6-supply : poly-phase capable
DC1SW : On/Off Switch : : DCDC1 secondary output
ALDO1 : LDO : aldoin-supply : shared supply
ALDO2 : LDO : aldoin-supply : shared supply
ALDO3 : LDO : aldoin-supply : shared supply
DLDO1 : LDO : dldoin-supply : shared supply
DLDO2 : LDO : dldoin-supply : shared supply
DLDO3 : LDO : dldoin-supply : shared supply
DLDO4 : LDO : dldoin-supply : shared supply
ELDO1 : LDO : eldoin-supply : shared supply
ELDO2 : LDO : eldoin-supply : shared supply
ELDO3 : LDO : eldoin-supply : shared supply
FLDO1 : LDO : fldoin-supply : shared supply
FLDO2 : LDO : fldoin-supply : shared supply
LDO_IO0 : LDO : ips-supply : GPIO 0
LDO_IO1 : LDO : ips-supply : GPIO 1
RTC_LDO : LDO : ips-supply : always on
DRIVEVBUS : Enable output : drivevbus-supply : external regulator
AXP806 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDCA : DC-DC buck : vina-supply : poly-phase capable
DCDCB : DC-DC buck : vinb-supply : poly-phase capable
DCDCC : DC-DC buck : vinc-supply : poly-phase capable
DCDCD : DC-DC buck : vind-supply : poly-phase capable
DCDCE : DC-DC buck : vine-supply : poly-phase capable
ALDO1 : LDO : aldoin-supply : shared supply
ALDO2 : LDO : aldoin-supply : shared supply
ALDO3 : LDO : aldoin-supply : shared supply
BLDO1 : LDO : bldoin-supply : shared supply
BLDO2 : LDO : bldoin-supply : shared supply
BLDO3 : LDO : bldoin-supply : shared supply
BLDO4 : LDO : bldoin-supply : shared supply
CLDO1 : LDO : cldoin-supply : shared supply
CLDO2 : LDO : cldoin-supply : shared supply
CLDO3 : LDO : cldoin-supply : shared supply
SW : On/Off Switch : swin-supply
Additionally, the AXP806 DC-DC regulators support poly-phase arrangements
for higher output current. The possible groupings are: A+B, A+B+C, D+E.
AXP809 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDC1 : DC-DC buck : vin1-supply
DCDC2 : DC-DC buck : vin2-supply
DCDC3 : DC-DC buck : vin3-supply
DCDC4 : DC-DC buck : vin4-supply
DCDC5 : DC-DC buck : vin5-supply
DC1SW : On/Off Switch : : DCDC1 secondary output
DC5LDO : LDO : : input from DCDC5
ALDO1 : LDO : aldoin-supply : shared supply
ALDO2 : LDO : aldoin-supply : shared supply
ALDO3 : LDO : aldoin-supply : shared supply
DLDO1 : LDO : dldoin-supply : shared supply
DLDO2 : LDO : dldoin-supply : shared supply
ELDO1 : LDO : eldoin-supply : shared supply
ELDO2 : LDO : eldoin-supply : shared supply
ELDO3 : LDO : eldoin-supply : shared supply
LDO_IO0 : LDO : ips-supply : GPIO 0
LDO_IO1 : LDO : ips-supply : GPIO 1
RTC_LDO : LDO : ips-supply : always on
SW : On/Off Switch : swin-supply
AXP813 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDC1 : DC-DC buck : vin1-supply
DCDC2 : DC-DC buck : vin2-supply : poly-phase capable
DCDC3 : DC-DC buck : vin3-supply : poly-phase capable
DCDC4 : DC-DC buck : vin4-supply
DCDC5 : DC-DC buck : vin5-supply : poly-phase capable
DCDC6 : DC-DC buck : vin6-supply : poly-phase capable
DCDC7 : DC-DC buck : vin7-supply
ALDO1 : LDO : aldoin-supply : shared supply
ALDO2 : LDO : aldoin-supply : shared supply
ALDO3 : LDO : aldoin-supply : shared supply
DLDO1 : LDO : dldoin-supply : shared supply
DLDO2 : LDO : dldoin-supply : shared supply
DLDO3 : LDO : dldoin-supply : shared supply
DLDO4 : LDO : dldoin-supply : shared supply
ELDO1 : LDO : eldoin-supply : shared supply
ELDO2 : LDO : eldoin-supply : shared supply
ELDO3 : LDO : eldoin-supply : shared supply
FLDO1 : LDO : fldoin-supply : shared supply
FLDO2 : LDO : fldoin-supply : shared supply
FLDO3 : LDO : fldoin-supply : shared supply
LDO_IO0 : LDO : ips-supply : GPIO 0
LDO_IO1 : LDO : ips-supply : GPIO 1
RTC_LDO : LDO : ips-supply : always on
SW : On/Off Switch : swin-supply
DRIVEVBUS : Enable output : drivevbus-supply : external regulator
Example:
axp209: pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
regulators {
x-powers,dcdc-freq = <1500>;
vdd_cpu: dcdc2 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1450000>;
regulator-name = "vdd-cpu";
};
vdd_int_dll: dcdc3 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-int-dll";
};
vdd_rtc: ldo1 {
regulator-always-on;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-rtc";
};
avcc: ldo2 {
regulator-always-on;
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3300000>;
regulator-name = "avcc";
};
ldo3 {
/* unused but preferred to be managed by OS */
};
};
};

View File

@@ -36,9 +36,15 @@ patternProperties:
'^clock-controller@[a-f0-9]+$':
$ref: ../clock/brcm,iproc-clocks.yaml
'^phy@[a-f0-9]+$':
$ref: ../phy/bcm-ns-usb2-phy.yaml
'^pin-controller@[a-f0-9]+$':
$ref: ../pinctrl/brcm,ns-pinmux.yaml
'^syscon@[a-f0-9]+$':
$ref: syscon.yaml
'^thermal@[a-f0-9]+$':
$ref: ../thermal/brcm,ns-thermal.yaml
@@ -49,6 +55,7 @@ required:
examples:
- |
#include <dt-bindings/clock/bcm-nsp.h>
cru-bus@1800c100 {
compatible = "brcm,ns-cru", "simple-mfd";
reg = <0x1800c100 0x1d0>;
@@ -73,6 +80,20 @@ examples:
"iprocfast", "sata1", "sata2";
};
phy@164 {
compatible = "brcm,ns-usb2-phy";
reg = <0x164 0x4>;
brcm,syscon-clkset = <&clkset>;
clocks = <&genpll BCM_NSP_GENPLL_USB_PHY_REF_CLK>;
clock-names = "phy-ref-clk";
#phy-cells = <0>;
};
clkset: syscon@180 {
compatible = "brcm,cru-clkset", "syscon";
reg = <0x180 0x4>;
};
pin-controller@1c0 {
compatible = "brcm,bcm4708-pinmux";
reg = <0x1c0 0x24>;

View File

@@ -0,0 +1,60 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/brcm,misc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom's MISC block
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
description: |
Broadcom's MISC is a hardware block used on some SoCs (e.g. bcm63xx and
bcm4908). It's used to implement some simple functions like a watchdog, PCIe
reset, UniMAC control and more.
properties:
compatible:
items:
- const: brcm,misc
- const: simple-mfd
reg:
description: MISC block registers
ranges: true
"#address-cells":
const: 1
"#size-cells":
const: 1
patternProperties:
'^reset-controller@[a-f0-9]+$':
$ref: ../reset/brcm,bcm4908-misc-pcie-reset.yaml
additionalProperties: false
required:
- reg
- '#address-cells'
- '#size-cells'
examples:
- |
misc@ff802600 {
compatible = "brcm,misc", "simple-mfd";
reg = <0xff802600 0xe4>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0xe4>;
reset-controller@44 {
compatible = "brcm,bcm4908-misc-pcie-reset";
reg = <0x44 0x4>;
#reset-cells = <1>;
};
};

View File

@@ -71,7 +71,7 @@ max14577@25 {
compatible = "maxim,max14577";
reg = <0x25>;
interrupt-parent = <&gpx1>;
interrupts = <5 IRQ_TYPE_NONE>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
muic: max14577-muic {
compatible = "maxim,max14577-muic";
@@ -106,7 +106,7 @@ max77836@25 {
compatible = "maxim,max77836";
reg = <0x25>;
interrupt-parent = <&gpx1>;
interrupts = <5 IRQ_TYPE_NONE>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
muic: max77836-muic {
compatible = "maxim,max77836-muic";

View File

@@ -21,6 +21,6 @@ Example:
max77686: pmic@9 {
compatible = "maxim,max77686";
interrupt-parent = <&wakeup_eint>;
interrupts = <26 0>;
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
reg = <0x09>;
};

View File

@@ -139,7 +139,7 @@ Example:
compatible = "maxim,max77693";
reg = <0x66>;
interrupt-parent = <&gpx1>;
interrupts = <5 2>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
regulators {
esafeout@1 {

View File

@@ -15,29 +15,38 @@ each. A function can consume one or more of these fixed-size register regions.
Required properties:
- compatible: Should contain one of:
"qcom,pm8941",
"qcom,pm8841",
"qcom,pma8084",
"qcom,pm8019",
"qcom,pm8226",
"qcom,pm8110",
"qcom,pma8084",
"qcom,pmi8962",
"qcom,pmd9635",
"qcom,pm8994",
"qcom,pmi8994",
"qcom,pm8916",
"qcom,pm8004",
"qcom,pm8909",
"qcom,pm8950",
"qcom,pmi8950",
"qcom,pm8998",
"qcom,pmi8998",
"qcom,pm8005",
"qcom,pm8350c",
"qcom,pmk8350",
"qcom,pm660",
"qcom,pm660l",
"qcom,pm7325",
"qcom,pm8004",
"qcom,pm8005",
"qcom,pm8019",
"qcom,pm8028",
"qcom,pm8110",
"qcom,pm8150",
"qcom,pm8150b",
"qcom,pm8150c",
"qcom,pm8150l",
"qcom,pm8226",
"qcom,pm8350c",
"qcom,pm8841",
"qcom,pm8901",
"qcom,pm8909",
"qcom,pm8916",
"qcom,pm8941",
"qcom,pm8950",
"qcom,pm8994",
"qcom,pm8998",
"qcom,pma8084",
"qcom,pmd9635",
"qcom,pmi8950",
"qcom,pmi8962",
"qcom,pmi8994",
"qcom,pmi8998",
"qcom,pmk8002",
"qcom,pmk8350",
"qcom,pmr735a",
"qcom,smb2351",
or generalized "qcom,spmi-pmic".
- reg: Specifies the SPMI USID slave address for this device.
For more information see:

View File

@@ -6,6 +6,7 @@ registers via syscon.
Required properties:
- compatible: Should contain:
"qcom,tcsr-ipq6018", "syscon", "simple-mfd" for IPQ6018
"qcom,tcsr-ipq8064", "syscon" for IPQ8064
"qcom,tcsr-apq8064", "syscon" for APQ8064
"qcom,tcsr-msm8660", "syscon" for MSM8660

View File

@@ -16,6 +16,7 @@ description: |
properties:
compatible:
enum:
- qcom,pm8018
- qcom,pm8058
- qcom,pm8821
- qcom,pm8921

View File

@@ -0,0 +1,91 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/samsung,s2mpa01.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S2MPA01 Power Management IC
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
description: |
This is a part of device tree bindings for S2M and S5M family of Power
Management IC (PMIC).
The Samsung S2MPA01 is a Power Management IC which includes voltage
and current regulators, RTC, clock outputs and other sub-blocks.
properties:
compatible:
const: samsung,s2mpa01-pmic
interrupts:
maxItems: 1
reg:
maxItems: 1
regulators:
$ref: ../regulator/samsung,s2mpa01.yaml
description:
List of child nodes that specify the regulators.
wakeup-source: true
required:
- compatible
- reg
- regulators
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "samsung,s2mpa01-pmic";
reg = <0x66>;
regulators {
ldo1_reg: LDO1 {
regulator-name = "VDD_ALIVE";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
ldo2_reg: LDO2 {
regulator-name = "VDDQ_MMC2";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-always-on;
};
// ...
buck1_reg: BUCK1 {
regulator-name = "vdd_mif";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};
buck2_reg: BUCK2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <50000>;
};
// ...
};
};
};

View File

@@ -0,0 +1,267 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/samsung,s2mps11.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S2MPS11/13/14/15 and S2MPU02 Power Management IC
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
description: |
This is a part of device tree bindings for S2M and S5M family of Power
Management IC (PMIC).
The Samsung S2MPS11/13/14/15 and S2MPU02 is a family of Power Management IC
which include voltage and current regulators, RTC, clock outputs and other
sub-blocks.
properties:
compatible:
enum:
- samsung,s2mps11-pmic
- samsung,s2mps13-pmic
- samsung,s2mps14-pmic
- samsung,s2mps15-pmic
- samsung,s2mpu02-pmic
clocks:
$ref: ../clock/samsung,s2mps11.yaml
description:
Child node describing clock provider.
interrupts:
maxItems: 1
reg:
maxItems: 1
regulators:
type: object
description:
List of child nodes that specify the regulators.
samsung,s2mps11-acokb-ground:
description: |
Indicates that ACOKB pin of S2MPS11 PMIC is connected to the ground so
the PMIC must manually set PWRHOLD bit in CTRL1 register to turn off the
power. Usually the ACOKB is pulled up to VBATT so when PWRHOLD pin goes
low, the rising ACOKB will trigger power off.
type: boolean
samsung,s2mps11-wrstbi-ground:
description: |
Indicates that WRSTBI pin of PMIC is pulled down. When the system is
suspended it will always go down thus triggerring unwanted buck warm
reset (setting buck voltages to default values).
type: boolean
wakeup-source: true
required:
- compatible
- reg
- regulators
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
const: samsung,s2mps11-pmic
then:
properties:
regulators:
$ref: ../regulator/samsung,s2mps11.yaml
samsung,s2mps11-wrstbi-ground: false
- if:
properties:
compatible:
contains:
const: samsung,s2mps13-pmic
then:
properties:
regulators:
$ref: ../regulator/samsung,s2mps13.yaml
samsung,s2mps11-acokb-ground: false
- if:
properties:
compatible:
contains:
const: samsung,s2mps14-pmic
then:
properties:
regulators:
$ref: ../regulator/samsung,s2mps14.yaml
samsung,s2mps11-acokb-ground: false
samsung,s2mps11-wrstbi-ground: false
- if:
properties:
compatible:
contains:
const: samsung,s2mps15-pmic
then:
properties:
regulators:
$ref: ../regulator/samsung,s2mps15.yaml
samsung,s2mps11-acokb-ground: false
samsung,s2mps11-wrstbi-ground: false
- if:
properties:
compatible:
contains:
const: samsung,s2mpu02-pmic
then:
properties:
regulators:
$ref: ../regulator/samsung,s2mpu02.yaml
samsung,s2mps11-acokb-ground: false
samsung,s2mps11-wrstbi-ground: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "samsung,s2mps11-pmic";
reg = <0x66>;
interrupt-parent = <&gpx0>;
interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&s2mps11_irq>;
samsung,s2mps11-acokb-ground;
wakeup-source;
clocks {
compatible = "samsung,s2mps11-clk";
#clock-cells = <1>;
clock-output-names = "s2mps11_ap", "s2mps11_cp", "s2mps11_bt";
};
regulators {
LDO1 {
regulator-name = "vdd_ldo1";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
LDO4 {
regulator-name = "vdd_adc";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
// ....
BUCK1 {
regulator-name = "vdd_mif";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
};
};
BUCK2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
regulator-coupled-with = <&buck3_reg>;
regulator-coupled-max-spread = <300000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
BUCK3 {
regulator-name = "vdd_int";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
regulator-coupled-with = <&buck2_reg>;
regulator-coupled-max-spread = <300000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
// ...
};
};
};
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "samsung,s2mps14-pmic";
reg = <0x66>;
interrupt-parent = <&gpx0>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
wakeup-source;
clocks {
compatible = "samsung,s2mps14-clk";
#clock-cells = <1>;
clock-output-names = "s2mps14_ap", "unused", "s2mps14_bt";
};
regulators {
LDO1 {
regulator-name = "VLDO1_1.0V";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
regulator-state-mem {
regulator-on-in-suspend;
};
};
// ...
BUCK1 {
regulator-name = "VBUCK1_1.0V";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
regulator-state-mem {
regulator-off-in-suspend;
};
};
// ...
};
};
};

View File

@@ -0,0 +1,307 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/samsung,s5m8767.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S5M8767 Power Management IC
maintainers:
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
description: |
This is a part of device tree bindings for S2M and S5M family of Power
Management IC (PMIC).
The Samsung S5M8767 is a Power Management IC which includes voltage
and current regulators, RTC, clock outputs and other sub-blocks.
properties:
compatible:
const: samsung,s5m8767-pmic
clocks:
$ref: ../clock/samsung,s2mps11.yaml
description:
Child node describing clock provider.
interrupts:
maxItems: 1
reg:
maxItems: 1
regulators:
$ref: ../regulator/samsung,s5m8767.yaml
description:
List of child nodes that specify the regulators.
s5m8767,pmic-buck2-dvs-voltage:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 8
maxItems: 8
description: |
A set of 8 voltage values in micro-volt (uV) units for buck2 when
changing voltage using gpio dvs.
s5m8767,pmic-buck3-dvs-voltage:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 8
maxItems: 8
description: |
A set of 8 voltage values in micro-volt (uV) units for buck3 when
changing voltage using gpio dvs.
s5m8767,pmic-buck4-dvs-voltage:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 8
maxItems: 8
description: |
A set of 8 voltage values in micro-volt (uV) units for buck4 when
changing voltage using gpio dvs.
s5m8767,pmic-buck-ds-gpios:
minItems: 3
maxItems: 3
description: |
GPIO specifiers for three host gpio's used for selecting GPIO DVS lines.
It is one-to-one mapped to dvs gpio lines.
s5m8767,pmic-buck2-uses-gpio-dvs:
type: boolean
description: buck2 can be controlled by gpio dvs.
s5m8767,pmic-buck3-uses-gpio-dvs:
type: boolean
description: buck3 can be controlled by gpio dvs.
s5m8767,pmic-buck4-uses-gpio-dvs:
type: boolean
description: buck4 can be controlled by gpio dvs.
s5m8767,pmic-buck-default-dvs-idx:
$ref: /schemas/types.yaml#/definitions/uint32-array
minimum: 0
maximum: 7
default: 0
description: |
Default voltage setting selected from the possible 8 options selectable
by the dvs gpios. The value of this property should be between 0 and 7.
If not specified or if out of range, the default value of this property
is set to 0.
s5m8767,pmic-buck-dvs-gpios:
minItems: 3
maxItems: 3
description: |
GPIO specifiers for three host gpio's used for dvs.
vinb1-supply:
description: Power supply for buck1
vinb2-supply:
description: Power supply for buck2
vinb3-supply:
description: Power supply for buck3
vinb4-supply:
description: Power supply for buck4
vinb5-supply:
description: Power supply for buck5
vinb6-supply:
description: Power supply for buck6
vinb7-supply:
description: Power supply for buck7
vinb8-supply:
description: Power supply for buck8
vinb9-supply:
description: Power supply for buck9
vinl1-supply:
description: Power supply for LDO3, LDO10, LDO26, LDO27
vinl2-supply:
description: Power supply for LDO13, LDO16, LDO25, LDO28
vinl3-supply:
description: Power supply for LDO11, LDO14
vinl4-supply:
description: Power supply for LDO4, LDO9
vinl5-supply:
description: Power supply for LDO12, LDO17, LDO19, LDO23
vinl6-supply:
description: Power supply for LDO18, LDO20, LDO21, LDO24
vinl7-supply:
description: Power supply for LDO5, LDO22
vinl8-supply:
description: Power supply for LDO1, LDO6, LDO7, LDO8, LDO15
vinl9-supply:
description: Power supply for LDO2
wakeup-source: true
required:
- compatible
- reg
- regulators
- s5m8767,pmic-buck-ds-gpios
dependencies:
s5m8767,pmic-buck2-dvs-voltage: [ 's5m8767,pmic-buck-dvs-gpios' ]
s5m8767,pmic-buck3-dvs-voltage: [ 's5m8767,pmic-buck-dvs-gpios' ]
s5m8767,pmic-buck4-dvs-voltage: [ 's5m8767,pmic-buck-dvs-gpios' ]
s5m8767,pmic-buck2-uses-gpio-dvs: [ 's5m8767,pmic-buck-dvs-gpios', 's5m8767,pmic-buck2-dvs-voltage' ]
s5m8767,pmic-buck3-uses-gpio-dvs: [ 's5m8767,pmic-buck-dvs-gpios', 's5m8767,pmic-buck3-dvs-voltage' ]
s5m8767,pmic-buck4-uses-gpio-dvs: [ 's5m8767,pmic-buck-dvs-gpios', 's5m8767,pmic-buck4-dvs-voltage' ]
additionalProperties: false
allOf:
- if:
required:
- s5m8767,pmic-buck2-uses-gpio-dvs
then:
properties:
s5m8767,pmic-buck3-uses-gpio-dvs: false
s5m8767,pmic-buck4-uses-gpio-dvs: false
- if:
required:
- s5m8767,pmic-buck3-uses-gpio-dvs
then:
properties:
s5m8767,pmic-buck2-uses-gpio-dvs: false
s5m8767,pmic-buck4-uses-gpio-dvs: false
- if:
required:
- s5m8767,pmic-buck4-uses-gpio-dvs
then:
properties:
s5m8767,pmic-buck2-uses-gpio-dvs: false
s5m8767,pmic-buck3-uses-gpio-dvs: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "samsung,s5m8767-pmic";
reg = <0x66>;
interrupt-parent = <&gpx3>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&s5m8767_irq &s5m8767_dvs &s5m8767_ds>;
wakeup-source;
s5m8767,pmic-buck-default-dvs-idx = <3>;
s5m8767,pmic-buck2-uses-gpio-dvs;
s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>,
<&gpd1 1 GPIO_ACTIVE_LOW>,
<&gpd1 2 GPIO_ACTIVE_LOW>;
s5m8767,pmic-buck-ds-gpios = <&gpx2 3 GPIO_ACTIVE_LOW>,
<&gpx2 4 GPIO_ACTIVE_LOW>,
<&gpx2 5 GPIO_ACTIVE_LOW>;
s5m8767,pmic-buck2-dvs-voltage = <1350000>, <1300000>,
<1250000>, <1200000>,
<1150000>, <1100000>,
<1000000>, <950000>;
s5m8767,pmic-buck3-dvs-voltage = <1100000>, <1100000>,
<1100000>, <1100000>,
<1000000>, <1000000>,
<1000000>, <1000000>;
s5m8767,pmic-buck4-dvs-voltage = <1200000>, <1200000>,
<1200000>, <1200000>,
<1200000>, <1200000>,
<1200000>, <1200000>;
clocks {
compatible = "samsung,s5m8767-clk";
#clock-cells = <1>;
clock-output-names = "en32khz_ap", "en32khz_cp", "en32khz_bt";
};
regulators {
LDO1 {
regulator-name = "VDD_ALIVE";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1100000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
};
// ...
BUCK1 {
regulator-name = "VDD_MIF";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1100000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
};
BUCK2 {
regulator-name = "VDD_ARM";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
};
// ...
};
};
};
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "samsung,s5m8767-pmic";
reg = <0x66>;
interrupt-parent = <&gpx3>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&s5m8767_irq &s5m8767_dvs &s5m8767_ds>;
wakeup-source;
s5m8767,pmic-buck-ds-gpios = <&gpx2 3 GPIO_ACTIVE_LOW>,
<&gpx2 4 GPIO_ACTIVE_LOW>,
<&gpx2 5 GPIO_ACTIVE_LOW>;
clocks {
compatible = "samsung,s5m8767-clk";
#clock-cells = <1>;
clock-output-names = "en32khz_ap", "en32khz_cp", "en32khz_bt";
};
regulators {
LDO1 {
regulator-name = "VDD_ALIVE";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1100000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
};
// ...
};
};
};

View File

@@ -1,86 +0,0 @@
Binding for Samsung S2M and S5M family multi-function device
============================================================
This is a part of device tree bindings for S2M and S5M family multi-function
devices.
The Samsung S2MPA01, S2MPS11/13/14/15, S2MPU02 and S5M8767 is a family
of multi-function devices which include voltage and current regulators, RTC,
charger controller, clock outputs and other sub-blocks. It is interfaced
to the host controller using an I2C interface. Each sub-block is usually
addressed by the host system using different I2C slave addresses.
This document describes bindings for main device node. Optional sub-blocks
must be a sub-nodes to it. Bindings for them can be found in:
- bindings/regulator/samsung,s2mpa01.txt
- bindings/regulator/samsung,s2mps11.txt
- bindings/regulator/samsung,s5m8767.txt
- bindings/clock/samsung,s2mps11.txt
Required properties:
- compatible: Should be one of the following
- "samsung,s2mpa01-pmic",
- "samsung,s2mps11-pmic",
- "samsung,s2mps13-pmic",
- "samsung,s2mps14-pmic",
- "samsung,s2mps15-pmic",
- "samsung,s2mpu02-pmic",
- "samsung,s5m8767-pmic".
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
Optional properties:
- interrupts: Interrupt specifiers for interrupt sources.
- samsung,s2mps11-wrstbi-ground: Indicates that WRSTBI pin of PMIC is pulled
down. When the system is suspended it will always go down thus triggerring
unwanted buck warm reset (setting buck voltages to default values).
- samsung,s2mps11-acokb-ground: Indicates that ACOKB pin of S2MPS11 PMIC is
connected to the ground so the PMIC must manually set PWRHOLD bit in CTRL1
register to turn off the power. Usually the ACOKB is pulled up to VBATT so
when PWRHOLD pin goes low, the rising ACOKB will trigger power off.
Example:
s2mps11_pmic@66 {
compatible = "samsung,s2mps11-pmic";
reg = <0x66>;
s2m_osc: clocks {
compatible = "samsung,s2mps11-clk";
#clock-cells = <1>;
clock-output-names = "xx", "yy", "zz";
};
regulators {
ldo1_reg: LDO1 {
regulator-name = "VDD_ABB_3.3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
ldo2_reg: LDO2 {
regulator-name = "VDD_ALIVE_1.1V";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1100000>;
regulator-always-on;
};
buck1_reg: BUCK1 {
regulator-name = "vdd_mif";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};
buck2_reg: BUCK2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <50000>;
};
};
};

View File

@@ -38,6 +38,7 @@ properties:
- allwinner,sun8i-h3-system-controller
- allwinner,sun8i-v3s-system-controller
- allwinner,sun50i-a64-system-controller
- brcm,cru-clkset
- hisilicon,dsa-subctrl
- hisilicon,hi6220-sramctrl
- hisilicon,pcie-sas-subctrl
@@ -49,12 +50,14 @@ properties:
- rockchip,rk3066-qos
- rockchip,rk3228-qos
- rockchip,rk3288-qos
- rockchip,rk3368-qos
- rockchip,rk3399-qos
- rockchip,rk3568-qos
- samsung,exynos3-sysreg
- samsung,exynos4-sysreg
- samsung,exynos5-sysreg
- samsung,exynos5433-sysreg
- samsung,exynosautov9-sysreg
- const: syscon

View File

@@ -0,0 +1,84 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/ti,am3359-tscadc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI AM3359 Touchscreen controller/ADC
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
properties:
compatible:
oneOf:
- const: ti,am3359-tscadc
- items:
- const: ti,am654-tscadc
- const: ti,am3359-tscadc
- const: ti,am4372-magadc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: fck
dmas:
items:
- description: DMA controller phandle and request line for FIFO0
- description: DMA controller phandle and request line for FIFO1
dma-names:
items:
- const: fifo0
- const: fifo1
adc:
type: object
description: ADC child
tsc:
type: object
description: Touchscreen controller child
mag:
type: object
description: Magnetic reader
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- dmas
- dma-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
tscadc@0 {
compatible = "ti,am3359-tscadc";
reg = <0x0 0x1000>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&adc_tsc_fck>;
clock-names = "fck";
dmas = <&edma 53 0>, <&edma 57 0>;
dma-names = "fifo0", "fifo1";
tsc {
};
adc {
};
};

View File

@@ -0,0 +1,116 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: "http://devicetree.org/schemas/mfd/x-powers,ac100.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: X-Powers AC100 Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
properties:
compatible:
const: x-powers,ac100
reg:
maxItems: 1
codec:
type: object
properties:
"#clock-cells":
const: 0
compatible:
const: x-powers,ac100-codec
interrupts:
maxItems: 1
clock-output-names:
maxItems: 1
description: >
Name of the 4M_adda clock exposed by the codec
required:
- "#clock-cells"
- compatible
- interrupts
- clock-output-names
additionalProperties: false
rtc:
type: object
properties:
"#clock-cells":
const: 1
compatible:
const: x-powers,ac100-rtc
interrupts:
maxItems: 1
clocks:
maxItems: 1
description: >
A phandle to the codec's "4M_adda" clock
clock-output-names:
maxItems: 3
description: >
Name of the cko1, cko2 and cko3 clocks exposed by the codec
required:
- "#clock-cells"
- compatible
- interrupts
- clocks
- clock-output-names
additionalProperties: false
required:
- compatible
- reg
- codec
- rtc
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
rsb {
#address-cells = <1>;
#size-cells = <0>;
codec@e89 {
compatible = "x-powers,ac100";
reg = <0xe89>;
ac100_codec: codec {
compatible = "x-powers,ac100-codec";
interrupt-parent = <&r_pio>;
interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PL9 */
#clock-cells = <0>;
clock-output-names = "4M_adda";
};
ac100_rtc: rtc {
compatible = "x-powers,ac100-rtc";
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
clocks = <&ac100_codec>;
#clock-cells = <1>;
clock-output-names = "cko1_rtc", "cko2_rtc", "cko3_rtc";
};
};
};
...

View File

@@ -0,0 +1,400 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/x-powers,axp152.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: X-Powers AXP PMIC Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
allOf:
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp152
- x-powers,axp202
- x-powers,axp209
then:
properties:
regulators:
properties:
x-powers,dcdc-freq:
minimum: 750
maximum: 1875
default: 1500
else:
properties:
regulators:
properties:
x-powers,dcdc-freq:
minimum: 1800
maximum: 4050
default: 3000
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp152
- x-powers,axp202
- x-powers,axp209
then:
not:
required:
- x-powers,drive-vbus-en
- if:
not:
properties:
compatible:
contains:
const: x-powers,axp806
then:
allOf:
- not:
required:
- x-powers,self-working-mode
- not:
required:
- x-powers,master-mode
- if:
not:
properties:
compatible:
contains:
const: x-powers,axp305
then:
required:
- interrupts
properties:
compatible:
oneOf:
- enum:
- x-powers,axp152
- x-powers,axp202
- x-powers,axp209
- x-powers,axp221
- x-powers,axp223
- x-powers,axp803
- x-powers,axp806
- x-powers,axp809
- x-powers,axp813
- items:
- const: x-powers,axp805
- const: x-powers,axp806
- items:
- const: x-powers,axp305
- const: x-powers,axp805
- const: x-powers,axp806
- items:
- const: x-powers,axp818
- const: x-powers,axp813
reg:
maxItems: 1
interrupts:
maxItems: 1
interrupt-controller: true
"#interrupt-cells":
const: 1
x-powers,drive-vbus-en:
type: boolean
description: >
Set this when the N_VBUSEN pin is used as an output pin to control an
external regulator to drive the OTG VBus, rather then as an input pin
which signals whether the board is driving OTG VBus or not.
x-powers,self-working-mode:
type: boolean
description: >
Set this when the PMIC is wired for self-working mode through the MODESET
pin.
x-powers,master-mode:
type: boolean
description: >
Set this when the PMIC is wired for master mode through the MODESET pin.
vin1-supply:
description: >
DCDC1 power supply node, if present.
vin2-supply:
description: >
DCDC2 power supply node, if present.
vin3-supply:
description: >
DCDC3 power supply node, if present.
vin4-supply:
description: >
DCDC4 power supply node, if present.
vin5-supply:
description: >
DCDC5 power supply node, if present.
vin6-supply:
description: >
DCDC6 power supply node, if present.
vin7-supply:
description: >
DCDC7 power supply node, if present.
vina-supply:
description: >
DCDCA power supply node, if present.
vinb-supply:
description: >
DCDCB power supply node, if present.
vinc-supply:
description: >
DCDCC power supply node, if present.
vind-supply:
description: >
DCDCD power supply node, if present.
vine-supply:
description: >
DCDCE power supply node, if present.
acin-supply:
description: >
LDO1 power supply node, if present.
ldo24in-supply:
description: >
LDO2 and LDO4 power supply node, if present.
ldo3in-supply:
description: >
LDO3 power supply node, if present.
ldo5in-supply:
description: >
LDO5 power supply node, if present.
aldoin-supply:
description: >
ALDO* power supply node, if present.
bldoin-supply:
description: >
BLDO* power supply node, if present.
cldoin-supply:
description: >
CLDO* power supply node, if present.
dldoin-supply:
description: >
DLDO* power supply node, if present.
eldoin-supply:
description: >
ELDO* power supply node, if present.
fldoin-supply:
description: >
FLDO* power supply node, if present.
ips-supply:
description: >
LDO_IO0, LDO_IO1 and RTC_LDO power supply node, if present.
drivevbus-supply:
description: >
DRIVEVBUS power supply node, if present.
swin-supply:
description: >
SW power supply node, if present.
adc:
$ref: /schemas/iio/adc/x-powers,axp209-adc.yaml#
gpio:
$ref: /schemas/gpio/x-powers,axp209-gpio.yaml#
ac-power:
$ref: /schemas/power/supply/x-powers,axp20x-ac-power-supply.yaml#
battery-power:
$ref: /schemas/power/supply/x-powers,axp20x-battery-power-supply.yaml#
usb-power:
$ref: /schemas/power/supply/x-powers,axp20x-usb-power-supply.yaml#
regulators:
type: object
properties:
x-powers,dcdc-freq:
$ref: /schemas/types.yaml#/definitions/uint32
description: >
Defines the work frequency of DC-DC in kHz.
patternProperties:
"^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|drivevbus|dc5ldo)$":
$ref: /schemas/regulator/regulator.yaml#
type: object
properties:
regulator-ramp-delay:
description: >
Only 800 and 1600 are valid for the DCDC2 and LDO3 regulators on
the AXP209.
regulator-soft-start:
description: >
Only valid for the LDO3 regulator.
x-powers,dcdc-workmode:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description: >
Only valid for DCDC regulators. Setup 1 for PWM mode, 0
for AUTO (PWM/PFM) mode. The DCDC regulators work in a
mixed PWM/PFM mode, using PFM under light loads and
switching to PWM for heavier loads. Forcing PWM mode
trades efficiency under light loads for lower output
noise. This probably makes sense for HiFi audio related
applications that aren't battery constrained.
additionalProperties: false
required:
- compatible
- reg
- "#interrupt-cells"
- interrupt-controller
additionalProperties: false
examples:
- |
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
pmic@30 {
compatible = "x-powers,axp152";
reg = <0x30>;
interrupts = <0>;
interrupt-controller;
#interrupt-cells = <1>;
};
};
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
ac_power_supply: ac-power {
compatible = "x-powers,axp202-ac-power-supply";
};
axp_adc: adc {
compatible = "x-powers,axp209-adc";
#io-channel-cells = <1>;
};
axp_gpio: gpio {
compatible = "x-powers,axp209-gpio";
gpio-controller;
#gpio-cells = <2>;
gpio0-adc-pin {
pins = "GPIO0";
function = "adc";
};
};
battery_power_supply: battery-power {
compatible = "x-powers,axp209-battery-power-supply";
};
regulators {
/* Default work frequency for buck regulators */
x-powers,dcdc-freq = <1500>;
reg_dcdc2: dcdc2 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1450000>;
regulator-name = "vdd-cpu";
};
reg_dcdc3: dcdc3 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-int-dll";
};
reg_ldo1: ldo1 {
/* LDO1 is a fixed output regulator */
regulator-always-on;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
regulator-name = "vdd-rtc";
};
reg_ldo2: ldo2 {
regulator-always-on;
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-name = "avcc";
};
reg_ldo3: ldo3 {
regulator-name = "ldo3";
};
reg_ldo4: ldo4 {
regulator-name = "ldo4";
};
reg_ldo5: ldo5 {
regulator-name = "ldo5";
};
};
usb_power_supply: usb-power {
compatible = "x-powers,axp202-usb-power-supply";
};
};
};

View File

@@ -46,6 +46,9 @@ patternProperties:
"^gpio@[0-9a-f]+$":
$ref: /schemas/gpio/xylon,logicvc-gpio.yaml#
"^display@[0-9a-f]+$":
$ref: /schemas/display/xylon,logicvc-display.yaml#
required:
- compatible
- reg

View File

@@ -43,7 +43,7 @@ Example:
max77686: pmic@9 {
compatible = "maxim,max77686";
interrupt-parent = <&wakeup_eint>;
interrupts = <26 IRQ_TYPE_NONE>;
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
reg = <0x09>;
voltage-regulators {

View File

@@ -767,7 +767,7 @@ F: drivers/crypto/allwinner/
ALLWINNER HARDWARE SPINLOCK SUPPORT
M: Wilken Gottwalt <wilken.gottwalt@posteo.net>
S: Maintained
F: Documentation/devicetree/bindings/hwlock/allwinner,sun6i-hwspinlock.yaml
F: Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml
F: drivers/hwspinlock/sun6i_hwspinlock.c
ALLWINNER THERMAL DRIVER
@@ -2783,7 +2783,7 @@ F: Documentation/devicetree/bindings/arm/toshiba.yaml
F: Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
F: Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
F: Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
F: Documentation/devicetree/bindings/pinctrl/toshiba,tmpv7700-pinctrl.yaml
F: Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml
F: Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
F: arch/arm64/boot/dts/toshiba/
F: drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
@@ -7119,6 +7119,20 @@ F: include/uapi/linux/mdio.h
F: include/uapi/linux/mii.h
F: net/core/of_net.c
EXEC & BINFMT API
R: Eric Biederman <ebiederm@xmission.com>
R: Kees Cook <keescook@chromium.org>
F: arch/alpha/kernel/binfmt_loader.c
F: arch/x86/ia32/ia32_aout.c
F: fs/*binfmt_*.c
F: fs/exec.c
F: include/linux/binfmts.h
F: include/linux/elf.h
F: include/uapi/linux/binfmts.h
F: tools/testing/selftests/exec/
N: asm/elf.h
N: binfmt
EXFAT FILE SYSTEM
M: Namjae Jeon <linkinjeon@kernel.org>
M: Sungjong Seo <sj1557.seo@samsung.com>
@@ -8562,7 +8576,6 @@ M: John Stultz <john.stultz@linaro.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/misc/hisi_hikey_usb.c
F: Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.yaml
HISILICON PMU DRIVER
M: Shaokun Zhang <zhangshaokun@hisilicon.com>
@@ -9628,7 +9641,7 @@ INTEL KEEM BAY DRM DRIVER
M: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
M: Edmund Dea <edmund.j.dea@intel.com>
S: Maintained
F: Documentation/devicetree/bindings/display/intel,kmb_display.yaml
F: Documentation/devicetree/bindings/display/intel,keembay-display.yaml
F: drivers/gpu/drm/kmb/
INTEL KEEM BAY OCS AES/SM4 CRYPTO DRIVER
@@ -16762,7 +16775,8 @@ L: linux-kernel@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml
F: Documentation/devicetree/bindings/mfd/samsung,sec-core.txt
F: Documentation/devicetree/bindings/mfd/samsung,s2m*.yaml
F: Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml
F: drivers/clk/clk-s2mps11.c

View File

@@ -129,9 +129,7 @@ dik_show_trace(unsigned long *sp, const char *loglvl)
extern char _stext[], _etext[];
unsigned long tmp = *sp;
sp++;
if (tmp < (unsigned long) &_stext)
continue;
if (tmp >= (unsigned long) &_etext)
if (!is_kernel_text(tmp))
continue;
printk("%s[<%lx>] %pSR\n", loglvl, tmp, (void *)tmp);
if (i > 40) {

View File

@@ -34,6 +34,7 @@
#include <linux/mm_types.h>
#include <linux/pgtable.h>
#include <linux/memblock.h>
#include <linux/kallsyms.h>
#include <asm/pgalloc.h>
#include <linux/io.h>
@@ -171,7 +172,7 @@ void __init mapin_ram(void)
for (s = 0; s < lowmem_size; s += PAGE_SIZE) {
f = _PAGE_PRESENT | _PAGE_ACCESSED |
_PAGE_SHARED | _PAGE_HWEXEC;
if ((char *) v < _stext || (char *) v >= _etext)
if (!is_kernel_text(v))
f |= _PAGE_WRENABLE;
else
/* On the MicroBlaze, no user access

View File

@@ -33,8 +33,6 @@
#include <mm/mmu_decl.h>
extern char etext[], _stext[], _sinittext[], _einittext[];
static u8 early_fixmap_pagetable[FIXMAP_PTE_SIZE] __page_aligned_data;
notrace void __init early_ioremap_init(void)
@@ -104,14 +102,13 @@ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
{
unsigned long v, s;
phys_addr_t p;
int ktext;
bool ktext;
s = offset;
v = PAGE_OFFSET + s;
p = memstart_addr + s;
for (; s < top; s += PAGE_SIZE) {
ktext = ((char *)v >= _stext && (char *)v < etext) ||
((char *)v >= _sinittext && (char *)v < _einittext);
ktext = core_kernel_text(v);
map_kernel_page(v, p, ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL);
v += PAGE_SIZE;
p += PAGE_SIZE;

View File

@@ -4,10 +4,14 @@
*/
#include <linux/delay.h>
#include <linux/math.h>
#include <linux/param.h>
#include <linux/timex.h>
#include <linux/types.h>
#include <linux/export.h>
#include <asm/processor.h>
/*
* This is copies from arch/arm/include/asm/delay.h
*

View File

@@ -9,8 +9,12 @@
#define __ASM_FACILITY_H
#include <asm/facility-defs.h>
#include <linux/minmax.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/preempt.h>
#include <asm/lowcore.h>
#define MAX_FACILITY_BIT (sizeof(stfle_fac_list) * 8)

View File

@@ -73,12 +73,23 @@ static int gart_mem_pfn_is_ram(unsigned long pfn)
(pfn >= aperture_pfn_start + aperture_page_count));
}
#ifdef CONFIG_PROC_VMCORE
static bool gart_oldmem_pfn_is_ram(struct vmcore_cb *cb, unsigned long pfn)
{
return !!gart_mem_pfn_is_ram(pfn);
}
static struct vmcore_cb gart_vmcore_cb = {
.pfn_is_ram = gart_oldmem_pfn_is_ram,
};
#endif
static void __init exclude_from_core(u64 aper_base, u32 aper_order)
{
aperture_pfn_start = aper_base >> PAGE_SHIFT;
aperture_page_count = (32 * 1024 * 1024) << aper_order >> PAGE_SHIFT;
#ifdef CONFIG_PROC_VMCORE
WARN_ON(register_oldmem_pfn_is_ram(&gart_mem_pfn_is_ram));
register_vmcore_cb(&gart_vmcore_cb);
#endif
#ifdef CONFIG_PROC_KCORE
WARN_ON(register_mem_pfn_is_ram(&gart_mem_pfn_is_ram));

View File

@@ -175,7 +175,7 @@ static struct orc_entry *orc_find(unsigned long ip)
}
/* vmlinux .init slow lookup: */
if (init_kernel_text(ip))
if (is_kernel_inittext(ip))
return __orc_find(__start_orc_unwind_ip, __start_orc_unwind,
__stop_orc_unwind_ip - __start_orc_unwind_ip, ip);

View File

@@ -238,11 +238,7 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base)
}
}
/*
* The <linux/kallsyms.h> already defines is_kernel_text,
* using '__' prefix not to get in conflict.
*/
static inline int __is_kernel_text(unsigned long addr)
static inline int is_x86_32_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end)
return 1;
@@ -333,8 +329,8 @@ repeat:
addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE +
PAGE_OFFSET + PAGE_SIZE-1;
if (__is_kernel_text(addr) ||
__is_kernel_text(addr2))
if (is_x86_32_kernel_text(addr) ||
is_x86_32_kernel_text(addr2))
prot = PAGE_KERNEL_LARGE_EXEC;
pages_2m++;
@@ -359,7 +355,7 @@ repeat:
*/
pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR);
if (__is_kernel_text(addr))
if (is_x86_32_kernel_text(addr))
prot = PAGE_KERNEL_EXEC;
pages_4k++;
@@ -789,7 +785,7 @@ static void mark_nxdata_nx(void)
*/
unsigned long start = PFN_ALIGN(_etext);
/*
* This comes from __is_kernel_text upper limit. Also HPAGE where used:
* This comes from is_x86_32_kernel_text upper limit. Also HPAGE where used:
*/
unsigned long size = (((unsigned long)__init_end + HPAGE_SIZE) & HPAGE_MASK) - start;

View File

@@ -9,39 +9,28 @@
#ifdef CONFIG_PROC_VMCORE
/*
* This function is used in two contexts:
* - the kdump kernel has to check whether a pfn of the crashed kernel
* was a ballooned page. vmcore is using this function to decide
* whether to access a pfn of the crashed kernel.
* - the kexec kernel has to check whether a pfn was ballooned by the
* previous kernel. If the pfn is ballooned, handle it properly.
* Returns 0 if the pfn is not backed by a RAM page, the caller may
* The kdump kernel has to check whether a pfn of the crashed kernel
* was a ballooned page. vmcore is using this function to decide
* whether to access a pfn of the crashed kernel.
* Returns "false" if the pfn is not backed by a RAM page, the caller may
* handle the pfn special in this case.
*/
static int xen_oldmem_pfn_is_ram(unsigned long pfn)
static bool xen_vmcore_pfn_is_ram(struct vmcore_cb *cb, unsigned long pfn)
{
struct xen_hvm_get_mem_type a = {
.domid = DOMID_SELF,
.pfn = pfn,
};
int ram;
if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a))
return -ENXIO;
switch (a.mem_type) {
case HVMMEM_mmio_dm:
ram = 0;
break;
case HVMMEM_ram_rw:
case HVMMEM_ram_ro:
default:
ram = 1;
break;
if (HYPERVISOR_hvm_op(HVMOP_get_mem_type, &a)) {
pr_warn_once("Unexpected HVMOP_get_mem_type failure\n");
return true;
}
return ram;
return a.mem_type != HVMMEM_mmio_dm;
}
static struct vmcore_cb xen_vmcore_cb = {
.pfn_is_ram = xen_vmcore_pfn_is_ram,
};
#endif
static void xen_hvm_exit_mmap(struct mm_struct *mm)
@@ -75,6 +64,6 @@ void __init xen_hvm_init_mmu_ops(void)
if (is_pagetable_dying_supported())
pv_ops.mmu.exit_mmap = xen_hvm_exit_mmap;
#ifdef CONFIG_PROC_VMCORE
WARN_ON(register_oldmem_pfn_is_ram(&xen_oldmem_pfn_is_ram));
register_vmcore_cb(&xen_vmcore_cb);
#endif
}

View File

@@ -116,6 +116,7 @@ static const struct omap_clkctrl_reg_data am4_l3s_clkctrl_regs[] __initconst = {
{ AM4_L3S_VPFE0_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk" },
{ AM4_L3S_VPFE1_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk" },
{ AM4_L3S_GPMC_CLKCTRL, NULL, CLKF_SW_SUP, "l3s_gclk" },
{ AM4_L3S_ADC1_CLKCTRL, NULL, CLKF_SW_SUP, "l3s_gclk" },
{ AM4_L3S_MCASP0_CLKCTRL, NULL, CLKF_SW_SUP, "mcasp0_fck" },
{ AM4_L3S_MCASP1_CLKCTRL, NULL, CLKF_SW_SUP, "mcasp1_fck" },
{ AM4_L3S_MMC3_CLKCTRL, NULL, CLKF_SW_SUP, "mmc_clk" },

View File

@@ -1668,13 +1668,10 @@ __dump_topology_ref_history(struct drm_dp_mst_topology_ref_history *history,
for (i = 0; i < history->len; i++) {
const struct drm_dp_mst_topology_ref_entry *entry =
&history->entries[i];
ulong *entries;
uint nr_entries;
u64 ts_nsec = entry->ts_nsec;
u32 rem_nsec = do_div(ts_nsec, 1000000000);
nr_entries = stack_depot_fetch(entry->backtrace, &entries);
stack_trace_snprint(buf, PAGE_SIZE, entries, nr_entries, 4);
stack_depot_snprint(entry->backtrace, buf, PAGE_SIZE, 4);
drm_printf(&p, " %d %ss (last at %5llu.%06u):\n%s",
entry->count,

View File

@@ -118,8 +118,6 @@ static noinline void save_stack(struct drm_mm_node *node)
static void show_leaks(struct drm_mm *mm)
{
struct drm_mm_node *node;
unsigned long *entries;
unsigned int nr_entries;
char *buf;
buf = kmalloc(BUFSZ, GFP_KERNEL);
@@ -133,8 +131,7 @@ static void show_leaks(struct drm_mm *mm)
continue;
}
nr_entries = stack_depot_fetch(node->stack, &entries);
stack_trace_snprint(buf, BUFSZ, entries, nr_entries, 0);
stack_depot_snprint(node->stack, buf, BUFSZ, 0);
DRM_ERROR("node [%08llx + %08llx]: inserted at\n%s",
node->start, node->size, buf);
}

View File

@@ -56,8 +56,6 @@ void i915_vma_free(struct i915_vma *vma)
static void vma_print_allocator(struct i915_vma *vma, const char *reason)
{
unsigned long *entries;
unsigned int nr_entries;
char buf[512];
if (!vma->node.stack) {
@@ -66,8 +64,7 @@ static void vma_print_allocator(struct i915_vma *vma, const char *reason)
return;
}
nr_entries = stack_depot_fetch(vma->node.stack, &entries);
stack_trace_snprint(buf, sizeof(buf), entries, nr_entries, 0);
stack_depot_snprint(vma->node.stack, buf, sizeof(buf), 0);
DRM_DEBUG_DRIVER("vma.node [%08llx + %08llx] %s: inserted at %s\n",
vma->node.start, vma->node.size, reason, buf);
}

View File

@@ -65,16 +65,6 @@ static noinline depot_stack_handle_t __save_depot_stack(void)
return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN);
}
static void __print_depot_stack(depot_stack_handle_t stack,
char *buf, int sz, int indent)
{
unsigned long *entries;
unsigned int nr_entries;
nr_entries = stack_depot_fetch(stack, &entries);
stack_trace_snprint(buf, sz, entries, nr_entries, indent);
}
static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
{
spin_lock_init(&rpm->debug.lock);
@@ -146,12 +136,12 @@ static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm,
if (!buf)
return;
__print_depot_stack(stack, buf, PAGE_SIZE, 2);
stack_depot_snprint(stack, buf, PAGE_SIZE, 2);
DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf);
stack = READ_ONCE(rpm->debug.last_release);
if (stack) {
__print_depot_stack(stack, buf, PAGE_SIZE, 2);
stack_depot_snprint(stack, buf, PAGE_SIZE, 2);
DRM_DEBUG_DRIVER("wakeref last released at\n%s", buf);
}
@@ -183,12 +173,12 @@ __print_intel_runtime_pm_wakeref(struct drm_printer *p,
return;
if (dbg->last_acquire) {
__print_depot_stack(dbg->last_acquire, buf, PAGE_SIZE, 2);
stack_depot_snprint(dbg->last_acquire, buf, PAGE_SIZE, 2);
drm_printf(p, "Wakeref last acquired:\n%s", buf);
}
if (dbg->last_release) {
__print_depot_stack(dbg->last_release, buf, PAGE_SIZE, 2);
stack_depot_snprint(dbg->last_release, buf, PAGE_SIZE, 2);
drm_printf(p, "Wakeref last released:\n%s", buf);
}
@@ -203,7 +193,7 @@ __print_intel_runtime_pm_wakeref(struct drm_printer *p,
rep = 1;
while (i + 1 < dbg->count && dbg->owners[i + 1] == stack)
rep++, i++;
__print_depot_stack(stack, buf, PAGE_SIZE, 2);
stack_depot_snprint(stack, buf, PAGE_SIZE, 2);
drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf);
}

View File

@@ -1,16 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* TI ADC MFD driver
*
* Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
@@ -25,6 +17,7 @@
#include <linux/of_device.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#include <linux/iopoll.h>
#include <linux/mfd/ti_am335x_tscadc.h>
#include <linux/iio/buffer.h>
@@ -65,7 +58,7 @@ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
}
static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
unsigned int val)
unsigned int val)
{
writel(val, adc->mfd_tscadc->tscadc_base + reg);
}
@@ -80,7 +73,7 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
}
static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev,
struct iio_chan_spec const *chan)
struct iio_chan_spec const *chan)
{
int i;
@@ -102,10 +95,18 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
return 1 << adc_dev->channel_step[chan];
}
static int tiadc_wait_idle(struct tiadc_device *adc_dev)
{
u32 val;
return readl_poll_timeout(adc_dev->mfd_tscadc->tscadc_base + REG_ADCFSM,
val, !(val & SEQ_STATUS), 10,
IDLE_TIMEOUT_MS * 1000 * adc_dev->channels);
}
static void tiadc_step_config(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct device *dev = adc_dev->mfd_tscadc->dev;
unsigned int stepconfig;
int i, steps = 0;
@@ -118,23 +119,14 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
* Channel would represent which analog input
* needs to be given to ADC to digitalize data.
*/
for (i = 0; i < adc_dev->channels; i++) {
int chan;
chan = adc_dev->channel_line[i];
if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) {
dev_warn(dev, "chan %d step_avg truncating to %d\n",
chan, STEPCONFIG_AVG_16);
adc_dev->step_avg[i] = STEPCONFIG_AVG_16;
}
if (adc_dev->step_avg[i])
stepconfig =
STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) |
STEPCONFIG_FIFO1;
stepconfig = STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) |
STEPCONFIG_FIFO1;
else
stepconfig = STEPCONFIG_FIFO1;
@@ -142,26 +134,13 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
stepconfig |= STEPCONFIG_MODE_SWCNT;
tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
stepconfig | STEPCONFIG_INP(chan) |
STEPCONFIG_INM_ADCREFM |
STEPCONFIG_RFP_VREFP |
STEPCONFIG_RFM_VREFN);
if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
chan);
adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK;
}
if (adc_dev->sample_delay[i] > 0xFF) {
dev_warn(dev, "chan %d sample delay truncating to 0xFF\n",
chan);
adc_dev->sample_delay[i] = 0xFF;
}
stepconfig | STEPCONFIG_INP(chan) |
STEPCONFIG_INM_ADCREFM | STEPCONFIG_RFP_VREFP |
STEPCONFIG_RFM_VREFN);
tiadc_writel(adc_dev, REG_STEPDELAY(steps),
STEPDELAY_OPEN(adc_dev->open_delay[i]) |
STEPDELAY_SAMPLE(adc_dev->sample_delay[i]));
STEPDELAY_OPEN(adc_dev->open_delay[i]) |
STEPDELAY_SAMPLE(adc_dev->sample_delay[i]));
adc_dev->channel_step[i] = steps;
steps++;
@@ -184,12 +163,14 @@ static irqreturn_t tiadc_irq_h(int irq, void *private)
if (status & IRQENB_FIFO1OVRRUN) {
/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
config = tiadc_readl(adc_dev, REG_CTRL);
config &= ~(CNTRLREG_TSCSSENB);
config &= ~(CNTRLREG_SSENB);
tiadc_writel(adc_dev, REG_CTRL, config);
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
tiadc_writel(adc_dev, REG_IRQSTATUS,
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW |
IRQENB_FIFO1THRES);
/* wait for idle state.
/*
* Wait for the idle state.
* ADC needs to finish the current conversion
* before disabling the module
*/
@@ -197,7 +178,7 @@ static irqreturn_t tiadc_irq_h(int irq, void *private)
adc_fsm = tiadc_readl(adc_dev, REG_ADCFSM);
} while (adc_fsm != 0x10 && count++ < 100);
tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_SSENB));
return IRQ_HANDLED;
} else if (status & IRQENB_FIFO1THRES) {
/* Disable irq and wake worker thread */
@@ -217,11 +198,11 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (k = 0; k < fifo1count; k = k + i) {
for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
for (i = 0; i < indio_dev->scan_bytes / 2; i++) {
read = tiadc_readl(adc_dev, REG_FIFO1);
data[i] = read & FIFOREAD_DATA_MASK;
}
iio_push_to_buffers(indio_dev, (u8 *) data);
iio_push_to_buffers(indio_dev, (u8 *)data);
}
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
@@ -254,6 +235,7 @@ static int tiadc_start_dma(struct iio_dev *indio_dev)
struct dma_async_tx_descriptor *desc;
dma->current_period = 0; /* We start to fill period 0 */
/*
* Make the fifo thresh as the multiple of total number of
* channels enabled, so make sure that cyclic DMA period
@@ -263,9 +245,10 @@ static int tiadc_start_dma(struct iio_dev *indio_dev)
*/
dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1,
adc_dev->total_ch_enabled) - 1;
/* Make sure that period length is multiple of fifo thresh level */
dma->period_size = rounddown(DMA_BUFFER_SIZE / 2,
(dma->fifo_thresh + 1) * sizeof(u16));
(dma->fifo_thresh + 1) * sizeof(u16));
dma->conf.src_maxburst = dma->fifo_thresh + 1;
dmaengine_slave_config(dma->chan, &dma->conf);
@@ -295,10 +278,15 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
int i, fifo1count;
int ret;
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN |
IRQENB_FIFO1UNDRFLW));
ret = tiadc_wait_idle(adc_dev);
if (ret)
return ret;
tiadc_writel(adc_dev, REG_IRQCLR,
IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN |
IRQENB_FIFO1UNDRFLW);
/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
@@ -328,8 +316,9 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
tiadc_writel(adc_dev, REG_IRQSTATUS,
IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN |
IRQENB_FIFO1UNDRFLW);
irq_enable = IRQENB_FIFO1OVRRUN;
if (!dma->chan)
@@ -345,8 +334,9 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
struct tiadc_dma *dma = &adc_dev->dma;
int fifo1count, i;
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
tiadc_writel(adc_dev, REG_IRQCLR,
IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN |
IRQENB_FIFO1UNDRFLW);
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
adc_dev->buffer_en_ch_steps = 0;
adc_dev->total_ch_enabled = 0;
@@ -378,12 +368,11 @@ static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
};
static int tiadc_iio_buffered_hardware_setup(struct device *dev,
struct iio_dev *indio_dev,
irqreturn_t (*pollfunc_bh)(int irq, void *p),
irqreturn_t (*pollfunc_th)(int irq, void *p),
int irq,
unsigned long flags,
const struct iio_buffer_setup_ops *setup_ops)
struct iio_dev *indio_dev,
irqreturn_t (*pollfunc_bh)(int irq, void *p),
irqreturn_t (*pollfunc_th)(int irq, void *p),
int irq, unsigned long flags,
const struct iio_buffer_setup_ops *setup_ops)
{
int ret;
@@ -394,7 +383,7 @@ static int tiadc_iio_buffered_hardware_setup(struct device *dev,
return ret;
return devm_request_threaded_irq(dev, irq, pollfunc_th, pollfunc_bh,
flags, indio_dev->name, indio_dev);
flags, indio_dev->name, indio_dev);
}
static const char * const chan_name_ain[] = {
@@ -419,16 +408,16 @@ static int tiadc_channel_init(struct device *dev, struct iio_dev *indio_dev,
indio_dev->num_channels = channels;
chan_array = devm_kcalloc(dev, channels, sizeof(*chan_array),
GFP_KERNEL);
if (chan_array == NULL)
if (!chan_array)
return -ENOMEM;
chan = chan_array;
for (i = 0; i < channels; i++, chan++) {
chan->type = IIO_VOLTAGE;
chan->indexed = 1;
chan->channel = adc_dev->channel_line[i];
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
chan->datasheet_name = chan_name_ain[chan->channel];
chan->scan_index = i;
chan->scan_type.sign = 'u';
@@ -442,16 +431,33 @@ static int tiadc_channel_init(struct device *dev, struct iio_dev *indio_dev,
}
static int tiadc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
struct iio_chan_spec const *chan, int *val, int *val2,
long mask)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
int ret = IIO_VAL_INT;
int i, map_val;
unsigned int fifo1count, read, stepid;
bool found = false;
u32 step_en;
unsigned long timeout;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
break;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 1800;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
@@ -461,15 +467,19 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
mutex_lock(&adc_dev->fifo1_lock);
ret = tiadc_wait_idle(adc_dev);
if (ret)
goto err_unlock;
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
while (fifo1count--)
tiadc_readl(adc_dev, REG_FIFO1);
am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
timeout = jiffies + msecs_to_jiffies
(IDLE_TIMEOUT * adc_dev->channels);
/* Wait for Fifo threshold interrupt */
timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT_MS * adc_dev->channels);
while (1) {
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
if (fifo1count)
@@ -481,6 +491,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
goto err_unlock;
}
}
map_val = adc_dev->channel_step[chan->scan_index];
/*
@@ -498,17 +509,18 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
if (stepid == map_val) {
read = read & FIFOREAD_DATA_MASK;
found = true;
*val = (u16) read;
*val = (u16)read;
}
}
am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
if (!found)
ret = -EBUSY;
ret = -EBUSY;
err_unlock:
mutex_unlock(&adc_dev->fifo1_lock);
return ret;
return ret ? ret : IIO_VAL_INT;
}
static const struct iio_info tiadc_info = {
@@ -545,6 +557,7 @@ static int tiadc_request_dma(struct platform_device *pdev,
goto err;
return 0;
err:
dma_release_channel(dma->chan);
return -ENOMEM;
@@ -558,6 +571,7 @@ static int tiadc_parse_dt(struct platform_device *pdev,
const __be32 *cur;
int channels = 0;
u32 val;
int i;
of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
adc_dev->channel_line[channels] = val;
@@ -570,6 +584,8 @@ static int tiadc_parse_dt(struct platform_device *pdev,
channels++;
}
adc_dev->channels = channels;
of_property_read_u32_array(node, "ti,chan-step-avg",
adc_dev->step_avg, channels);
of_property_read_u32_array(node, "ti,chan-step-opendelay",
@@ -577,7 +593,33 @@ static int tiadc_parse_dt(struct platform_device *pdev,
of_property_read_u32_array(node, "ti,chan-step-sampledelay",
adc_dev->sample_delay, channels);
adc_dev->channels = channels;
for (i = 0; i < adc_dev->channels; i++) {
int chan;
chan = adc_dev->channel_line[i];
if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) {
dev_warn(&pdev->dev,
"chan %d: wrong step avg, truncated to %ld\n",
chan, STEPCONFIG_AVG_16);
adc_dev->step_avg[i] = STEPCONFIG_AVG_16;
}
if (adc_dev->open_delay[i] > STEPCONFIG_MAX_OPENDLY) {
dev_warn(&pdev->dev,
"chan %d: wrong open delay, truncated to 0x%lX\n",
chan, STEPCONFIG_MAX_OPENDLY);
adc_dev->open_delay[i] = STEPCONFIG_MAX_OPENDLY;
}
if (adc_dev->sample_delay[i] > STEPCONFIG_MAX_SAMPLE) {
dev_warn(&pdev->dev,
"chan %d: wrong sample delay, truncated to 0x%lX\n",
chan, STEPCONFIG_MAX_SAMPLE);
adc_dev->sample_delay[i] = STEPCONFIG_MAX_SAMPLE;
}
}
return 0;
}
@@ -594,7 +636,7 @@ static int tiadc_probe(struct platform_device *pdev)
}
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
if (indio_dev == NULL) {
if (!indio_dev) {
dev_err(&pdev->dev, "failed to allocate iio device\n");
return -ENOMEM;
}
@@ -616,18 +658,17 @@ static int tiadc_probe(struct platform_device *pdev)
return err;
err = tiadc_iio_buffered_hardware_setup(&pdev->dev, indio_dev,
&tiadc_worker_h,
&tiadc_irq_h,
adc_dev->mfd_tscadc->irq,
IRQF_SHARED,
&tiadc_buffer_setup_ops);
&tiadc_worker_h,
&tiadc_irq_h,
adc_dev->mfd_tscadc->irq,
IRQF_SHARED,
&tiadc_buffer_setup_ops);
if (err)
goto err_free_channels;
return err;
err = iio_device_register(indio_dev);
if (err)
goto err_buffer_unregister;
return err;
platform_set_drvdata(pdev, indio_dev);
@@ -639,8 +680,7 @@ static int tiadc_probe(struct platform_device *pdev)
err_dma:
iio_device_unregister(indio_dev);
err_buffer_unregister:
err_free_channels:
return err;
}
@@ -671,9 +711,8 @@ static int __maybe_unused tiadc_suspend(struct device *dev)
unsigned int idle;
idle = tiadc_readl(adc_dev, REG_CTRL);
idle &= ~(CNTRLREG_TSCSSENB);
tiadc_writel(adc_dev, REG_CTRL, (idle |
CNTRLREG_POWERDOWN));
idle &= ~(CNTRLREG_SSENB);
tiadc_writel(adc_dev, REG_CTRL, idle | CNTRLREG_POWERDOWN);
return 0;
}
@@ -686,12 +725,12 @@ static int __maybe_unused tiadc_resume(struct device *dev)
/* Make sure ADC is powered up */
restore = tiadc_readl(adc_dev, REG_CTRL);
restore &= ~(CNTRLREG_POWERDOWN);
restore &= ~CNTRLREG_POWERDOWN;
tiadc_writel(adc_dev, REG_CTRL, restore);
tiadc_step_config(indio_dev);
am335x_tsc_se_set_cache(adc_dev->mfd_tscadc,
adc_dev->buffer_en_ch_steps);
adc_dev->buffer_en_ch_steps);
return 0;
}
@@ -699,6 +738,7 @@ static SIMPLE_DEV_PM_OPS(tiadc_pm_ops, tiadc_suspend, tiadc_resume);
static const struct of_device_id ti_adc_dt_ids[] = {
{ .compatible = "ti,am3359-adc", },
{ .compatible = "ti,am4372-adc", },
{ }
};
MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);

View File

@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/bits.h>
#include <linux/string.h>
int cxd2880_convert2s_complement(u32 value, u32 bitlen);

View File

@@ -93,7 +93,7 @@ config PMIC_ADP5520
bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
depends on I2C=y
help
Say yes here to add support for Analog Devices AD5520 and ADP5501,
Say yes here to add support for Analog Devices ADP5520 and ADP5501,
Multifunction Power Management IC. This includes
the I2C driver and the core APIs _only_, you have to select
individual components like LCD backlight, LEDs, GPIOs and Kepad
@@ -417,7 +417,9 @@ config MFD_EXYNOS_LPASS
select REGMAP_MMIO
help
Select this option to enable support for Samsung Exynos Low Power
Audio Subsystem.
Audio Subsystem present on some of Samsung Exynos
SoCs (e.g. Exynos5433).
Choose Y here only if you build for such Samsung SoC.
config MFD_GATEWORKS_GSC
tristate "Gateworks System Controller"
@@ -692,7 +694,7 @@ config MFD_INTEL_PMC_BXT
config MFD_INTEL_PMT
tristate "Intel Platform Monitoring Technology (PMT) support"
depends on PCI
depends on X86 && PCI
select MFD_CORE
help
The Intel Platform Monitoring Technology (PMT) is an interface that
@@ -1194,6 +1196,7 @@ config MFD_SI476X_CORE
config MFD_SIMPLE_MFD_I2C
tristate
depends on I2C
select MFD_CORE
select REGMAP_I2C
help
This driver creates a single register map with the intention for it
@@ -1622,20 +1625,6 @@ config MFD_TPS65912_SPI
If you say yes here you get support for the TPS65912 series of
PM chips with SPI interface.
config MFD_TPS80031
bool "TI TPS80031/TPS80032 Power Management chips"
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
If you say yes here you get support for the Texas Instruments
TPS80031/ TPS80032 Fully Integrated Power Management with Power
Path and Battery Charger. The device provides five configurable
step-down converters, 11 general purpose LDOs, USB OTG Module,
ADC, RTC, 2 PWM, System Voltage Regulator/Battery Charger with
Power Path from USB, 32K clock generator.
config TWL4030_CORE
bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
depends on I2C=y

View File

@@ -105,7 +105,6 @@ obj-$(CONFIG_MFD_TPS65910) += tps65910.o
obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o
obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o
obj-$(CONFIG_MFD_TPS80031) += tps80031.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o

View File

@@ -14,6 +14,7 @@
#include <linux/mfd/altera-a10sr.h>
#include <linux/mfd/core.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
@@ -150,6 +151,13 @@ static const struct of_device_id altr_a10sr_spi_of_match[] = {
{ .compatible = "altr,a10sr" },
{ },
};
MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match);
static const struct spi_device_id altr_a10sr_spi_ids[] = {
{ .name = "a10sr" },
{ },
};
MODULE_DEVICE_TABLE(spi, altr_a10sr_spi_ids);
static struct spi_driver altr_a10sr_spi_driver = {
.probe = altr_a10sr_spi_probe,
@@ -157,5 +165,6 @@ static struct spi_driver altr_a10sr_spi_driver = {
.name = "altr_a10sr",
.of_match_table = of_match_ptr(altr_a10sr_spi_of_match),
},
.id_table = altr_a10sr_spi_ids,
};
builtin_driver(altr_a10sr_spi_driver, spi_register_driver)

View File

@@ -153,7 +153,7 @@ static int sysmgr_probe(struct platform_device *pdev)
if (!base)
return -ENOMEM;
sysmgr_config.max_register = resource_size(res) - 3;
sysmgr_config.max_register = resource_size(res) - 4;
regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config);
}

View File

@@ -845,19 +845,6 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
return 0;
}
const struct of_device_id arizona_of_match[] = {
{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{ .compatible = "wlf,wm8998", .data = (void *)WM8998 },
{ .compatible = "wlf,wm1814", .data = (void *)WM1814 },
{ .compatible = "wlf,wm1831", .data = (void *)WM1831 },
{ .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
{},
};
EXPORT_SYMBOL_GPL(arizona_of_match);
#else
static inline int arizona_of_get_core_pdata(struct arizona *arizona)
{

View File

@@ -104,11 +104,23 @@ static const struct i2c_device_id arizona_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, arizona_i2c_id);
#ifdef CONFIG_OF
const struct of_device_id arizona_i2c_of_match[] = {
{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{ .compatible = "wlf,wm8998", .data = (void *)WM8998 },
{ .compatible = "wlf,wm1814", .data = (void *)WM1814 },
{},
};
#endif
static struct i2c_driver arizona_i2c_driver = {
.driver = {
.name = "arizona",
.pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match),
.of_match_table = of_match_ptr(arizona_i2c_of_match),
},
.probe = arizona_i2c_probe,
.remove = arizona_i2c_remove,

View File

@@ -225,11 +225,22 @@ static const struct spi_device_id arizona_spi_ids[] = {
};
MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
#ifdef CONFIG_OF
const struct of_device_id arizona_spi_of_match[] = {
{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm1831", .data = (void *)WM1831 },
{ .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
{},
};
#endif
static struct spi_driver arizona_spi_driver = {
.driver = {
.name = "arizona",
.pm = &arizona_pm_ops,
.of_match_table = of_match_ptr(arizona_of_match),
.of_match_table = of_match_ptr(arizona_spi_of_match),
.acpi_match_table = ACPI_PTR(arizona_acpi_match),
},
.probe = arizona_spi_probe,

View File

@@ -28,8 +28,6 @@ extern const struct regmap_config wm8998_i2c_regmap;
extern const struct dev_pm_ops arizona_pm_ops;
extern const struct of_device_id arizona_of_match[];
extern const struct regmap_irq_chip wm5102_aod;
extern const struct regmap_irq_chip wm5102_irq;

View File

@@ -326,7 +326,6 @@ static void __exit cros_ec_dev_exit(void)
module_init(cros_ec_dev_init);
module_exit(cros_ec_dev_exit);
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>");
MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
MODULE_VERSION("1.0");

View File

@@ -391,6 +391,7 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
&da9063_bb_da_volatile_table;
break;
case PMIC_DA9063_DA:
case PMIC_DA9063_EA:
da9063_regmap_config.rd_table =
&da9063_da_readable_table;
da9063_regmap_config.wr_table =
@@ -416,6 +417,7 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
&da9063l_bb_da_volatile_table;
break;
case PMIC_DA9063_DA:
case PMIC_DA9063_EA:
da9063_regmap_config.rd_table =
&da9063l_da_readable_table;
da9063_regmap_config.wr_table =

View File

@@ -50,6 +50,7 @@ enum dln2_handle {
DLN2_HANDLE_GPIO,
DLN2_HANDLE_I2C,
DLN2_HANDLE_SPI,
DLN2_HANDLE_ADC,
DLN2_HANDLES
};
@@ -653,6 +654,7 @@ enum {
DLN2_ACPI_MATCH_GPIO = 0,
DLN2_ACPI_MATCH_I2C = 1,
DLN2_ACPI_MATCH_SPI = 2,
DLN2_ACPI_MATCH_ADC = 3,
};
static struct dln2_platform_data dln2_pdata_gpio = {
@@ -683,6 +685,16 @@ static struct mfd_cell_acpi_match dln2_acpi_match_spi = {
.adr = DLN2_ACPI_MATCH_SPI,
};
/* Only one ADC port supported */
static struct dln2_platform_data dln2_pdata_adc = {
.handle = DLN2_HANDLE_ADC,
.port = 0,
};
static struct mfd_cell_acpi_match dln2_acpi_match_adc = {
.adr = DLN2_ACPI_MATCH_ADC,
};
static const struct mfd_cell dln2_devs[] = {
{
.name = "dln2-gpio",
@@ -702,6 +714,12 @@ static const struct mfd_cell dln2_devs[] = {
.platform_data = &dln2_pdata_spi,
.pdata_size = sizeof(struct dln2_platform_data),
},
{
.name = "dln2-adc",
.acpi_match = &dln2_acpi_match_adc,
.platform_data = &dln2_pdata_adc,
.pdata_size = sizeof(struct dln2_platform_data),
},
};
static void dln2_stop(struct dln2_dev *dln2)

View File

@@ -8,7 +8,6 @@
*/
#include <linux/mfd/core.h>
#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -30,19 +29,14 @@ static const struct regmap_config regmap_config = {
static int hi6421_spmi_pmic_probe(struct spmi_device *sdev)
{
struct device *dev = &sdev->dev;
struct regmap *regmap;
int ret;
struct hi6421_spmi_pmic *ddata;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
ddata->regmap = devm_regmap_init_spmi_ext(sdev, &regmap_config);
if (IS_ERR(ddata->regmap))
return PTR_ERR(ddata->regmap);
regmap = devm_regmap_init_spmi_ext(sdev, &regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
ddata->dev = dev;
dev_set_drvdata(&sdev->dev, ddata);
dev_set_drvdata(&sdev->dev, regmap);
ret = devm_mfd_add_devices(&sdev->dev, PLATFORM_DEVID_NONE,
hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),

View File

@@ -253,6 +253,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
/* ICL-N */
{ PCI_VDEVICE(INTEL, 0x38a8), (kernel_ulong_t)&bxt_uart_info },
/* TGL-H */
{ PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info },

View File

@@ -154,7 +154,7 @@ static ssize_t modulbus_number_show(struct device *dev,
{
struct cmodio_device *priv = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex);
return sysfs_emit(buf, "%x\n", priv->hex);
}
static DEVICE_ATTR_RO(modulbus_number);

View File

@@ -332,7 +332,7 @@ static int max77836_init(struct max14577 *max14577)
}
ret = regmap_add_irq_chip(max14577->regmap_pmic, max14577->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED,
IRQF_ONESHOT | IRQF_SHARED,
0, &max77836_pmic_irq_chip,
&max14577->irq_data_pmic);
if (ret != 0) {
@@ -418,14 +418,14 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
irq_chip = &max77836_muic_irq_chip;
mfd_devs = max77836_devs;
mfd_devs_size = ARRAY_SIZE(max77836_devs);
irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
irq_flags = IRQF_ONESHOT | IRQF_SHARED;
break;
case MAXIM_DEVICE_TYPE_MAX14577:
default:
irq_chip = &max14577_irq_chip;
mfd_devs = max14577_devs;
mfd_devs_size = ARRAY_SIZE(max14577_devs);
irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
irq_flags = IRQF_ONESHOT;
break;
}

View File

@@ -209,8 +209,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c)
ret = devm_regmap_add_irq_chip(&i2c->dev, max77686->regmap,
max77686->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_SHARED, 0, irq_chip,
IRQF_ONESHOT | IRQF_SHARED, 0, irq_chip,
&max77686->irq_data);
if (ret < 0) {
dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);

View File

@@ -222,8 +222,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
}
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
IRQF_ONESHOT | IRQF_SHARED, 0,
&max77693_led_irq_chip,
&max77693->irq_data_led);
if (ret) {
@@ -232,8 +231,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
}
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
IRQF_ONESHOT | IRQF_SHARED, 0,
&max77693_topsys_irq_chip,
&max77693->irq_data_topsys);
if (ret) {
@@ -242,8 +240,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
}
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
IRQF_ONESHOT | IRQF_SHARED, 0,
&max77693_charger_irq_chip,
&max77693->irq_data_chg);
if (ret) {
@@ -252,8 +249,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
}
ret = regmap_add_irq_chip(max77693->regmap_muic, max77693->irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
IRQF_ONESHOT | IRQF_SHARED, 0,
&max77693_muic_irq_chip,
&max77693->irq_data_muic);
if (ret) {

View File

@@ -496,15 +496,13 @@ int mc13xxx_common_init(struct device *dev)
}
EXPORT_SYMBOL_GPL(mc13xxx_common_init);
int mc13xxx_common_exit(struct device *dev)
void mc13xxx_common_exit(struct device *dev)
{
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
mfd_remove_devices(dev);
regmap_del_irq_chip(mc13xxx->irq, mc13xxx->irq_data);
mutex_destroy(&mc13xxx->lock);
return 0;
}
EXPORT_SYMBOL_GPL(mc13xxx_common_exit);

View File

@@ -87,7 +87,8 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
static int mc13xxx_i2c_remove(struct i2c_client *client)
{
return mc13xxx_common_exit(&client->dev);
mc13xxx_common_exit(&client->dev);
return 0;
}
static struct i2c_driver mc13xxx_i2c_driver = {

View File

@@ -168,7 +168,8 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
static int mc13xxx_spi_remove(struct spi_device *spi)
{
return mc13xxx_common_exit(&spi->dev);
mc13xxx_common_exit(&spi->dev);
return 0;
}
static struct spi_driver mc13xxx_spi_driver = {

View File

@@ -44,6 +44,6 @@ struct mc13xxx {
};
int mc13xxx_common_init(struct device *dev);
int mc13xxx_common_exit(struct device *dev);
void mc13xxx_common_exit(struct device *dev);
#endif /* __DRIVERS_MFD_MC13XXX_H */

View File

@@ -198,6 +198,7 @@ static int mfd_add_device(struct device *parent, int id,
if (of_device_is_compatible(np, cell->of_compatible)) {
/* Ignore 'disabled' devices error free */
if (!of_device_is_available(np)) {
of_node_put(np);
ret = 0;
goto fail_alias;
}
@@ -205,6 +206,7 @@ static int mfd_add_device(struct device *parent, int id,
ret = mfd_match_of_node_to_dev(pdev, np, cell);
if (ret == -EAGAIN)
continue;
of_node_put(np);
if (ret)
goto fail_alias;

View File

@@ -202,6 +202,13 @@ static const struct of_device_id cpcap_of_match[] = {
};
MODULE_DEVICE_TABLE(of, cpcap_of_match);
static const struct spi_device_id cpcap_spi_ids[] = {
{ .name = "cpcap", },
{ .name = "6556002", },
{},
};
MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
static const struct regmap_config cpcap_regmap_config = {
.reg_bits = 16,
.reg_stride = 4,
@@ -342,6 +349,7 @@ static struct spi_driver cpcap_driver = {
.pm = &cpcap_pm,
},
.probe = cpcap_probe,
.id_table = cpcap_spi_ids,
};
module_spi_driver(cpcap_driver);

View File

@@ -65,7 +65,7 @@
struct pm_irq_data {
int num_irqs;
struct irq_chip *irq_chip;
void (*irq_handler)(struct irq_desc *desc);
irq_handler_t irq_handler;
};
struct pm_irq_chip {
@@ -169,19 +169,16 @@ static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
return ret;
}
static void pm8xxx_irq_handler(struct irq_desc *desc)
static irqreturn_t pm8xxx_irq_handler(int irq, void *data)
{
struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
struct pm_irq_chip *chip = data;
unsigned int root;
int i, ret, masters = 0;
chained_irq_enter(irq_chip, desc);
ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
if (ret) {
pr_err("Can't read root status ret=%d\n", ret);
return;
return IRQ_NONE;
}
/* on pm8xxx series masters start from bit 1 of the root */
@@ -192,7 +189,7 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
if (masters & (1 << i))
pm8xxx_irq_master_handler(chip, i);
chained_irq_exit(irq_chip, desc);
return IRQ_HANDLED;
}
static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
@@ -230,19 +227,17 @@ static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
pm8821_irq_block_handler(chip, master, block);
}
static void pm8821_irq_handler(struct irq_desc *desc)
static irqreturn_t pm8821_irq_handler(int irq, void *data)
{
struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
struct pm_irq_chip *chip = data;
unsigned int master;
int ret;
chained_irq_enter(irq_chip, desc);
ret = regmap_read(chip->regmap,
PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
if (ret) {
pr_err("Failed to read master 0 ret=%d\n", ret);
goto done;
return IRQ_NONE;
}
/* bits 1 through 7 marks the first 7 blocks in master 0 */
@@ -251,19 +246,18 @@ static void pm8821_irq_handler(struct irq_desc *desc)
/* bit 0 marks if master 1 contains any bits */
if (!(master & BIT(0)))
goto done;
return IRQ_NONE;
ret = regmap_read(chip->regmap,
PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
if (ret) {
pr_err("Failed to read master 1 ret=%d\n", ret);
goto done;
return IRQ_NONE;
}
pm8821_irq_master_handler(chip, 1, master);
done:
chained_irq_exit(irq_chip, desc);
return IRQ_HANDLED;
}
static void pm8xxx_irq_mask_ack(struct irq_data *d)
@@ -574,14 +568,15 @@ static int pm8xxx_probe(struct platform_device *pdev)
if (!chip->irqdomain)
return -ENODEV;
irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
rc = devm_request_irq(&pdev->dev, irq, data->irq_handler, 0, dev_name(&pdev->dev), chip);
if (rc)
return rc;
irq_set_irq_wake(irq, 1);
rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
if (rc) {
irq_set_chained_handler_and_data(irq, NULL, NULL);
if (rc)
irq_domain_remove(chip->irqdomain);
}
return rc;
}
@@ -594,11 +589,9 @@ static int pm8xxx_remove_child(struct device *dev, void *unused)
static int pm8xxx_remove(struct platform_device *pdev)
{
int irq = platform_get_irq(pdev, 0);
struct pm_irq_chip *chip = platform_get_drvdata(pdev);
device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child);
irq_set_chained_handler_and_data(irq, NULL, NULL);
irq_domain_remove(chip->irqdomain);
return 0;

View File

@@ -31,6 +31,8 @@
#define PM8916_SUBTYPE 0x0b
#define PM8004_SUBTYPE 0x0c
#define PM8909_SUBTYPE 0x0d
#define PM8028_SUBTYPE 0x0e
#define PM8901_SUBTYPE 0x0f
#define PM8950_SUBTYPE 0x10
#define PMI8950_SUBTYPE 0x11
#define PM8998_SUBTYPE 0x14
@@ -38,29 +40,44 @@
#define PM8005_SUBTYPE 0x18
#define PM660L_SUBTYPE 0x1A
#define PM660_SUBTYPE 0x1B
#define PM8150_SUBTYPE 0x1E
#define PM8150L_SUBTYPE 0x1f
#define PM8150B_SUBTYPE 0x20
#define PMK8002_SUBTYPE 0x21
#define PM8009_SUBTYPE 0x24
#define PM8150C_SUBTYPE 0x26
#define SMB2351_SUBTYPE 0x29
static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
{ .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE },
{ .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE },
{ .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE },
{ .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE },
{ .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE },
{ .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE },
{ .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE },
{ .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE },
{ .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE },
{ .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE },
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE },
{ .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE },
{ .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE },
{ .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE },
{ .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE },
{ .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE },
{ .compatible = "qcom,pm660l", .data = (void *)PM660L_SUBTYPE },
{ .compatible = "qcom,pm660", .data = (void *)PM660_SUBTYPE },
{ .compatible = "qcom,pm660l", .data = (void *)PM660L_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE },
{ .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE },
{ .compatible = "qcom,pm8028", .data = (void *)PM8028_SUBTYPE },
{ .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE },
{ .compatible = "qcom,pm8150", .data = (void *)PM8150_SUBTYPE },
{ .compatible = "qcom,pm8150b", .data = (void *)PM8150B_SUBTYPE },
{ .compatible = "qcom,pm8150c", .data = (void *)PM8150C_SUBTYPE },
{ .compatible = "qcom,pm8150l", .data = (void *)PM8150L_SUBTYPE },
{ .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE },
{ .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE },
{ .compatible = "qcom,pm8901", .data = (void *)PM8901_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE },
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE },
{ .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE },
{ .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE },
{ .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE },
{ .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE },
{ .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE },
{ .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE },
{ .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE },
{ .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE },
{ .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE },
{ .compatible = "qcom,pmk8002", .data = (void *)PMK8002_SUBTYPE },
{ .compatible = "qcom,smb2351", .data = (void *)SMB2351_SUBTYPE },
{ .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
{ }
};

View File

@@ -543,6 +543,10 @@ static void rk808_pm_power_off(void)
reg = RK808_DEVCTRL_REG,
bit = DEV_OFF_RST;
break;
case RK817_ID:
reg = RK817_SYS_CFG(3);
bit = DEV_OFF;
break;
case RK818_ID:
reg = RK818_DEVCTRL_REG;
bit = DEV_OFF;

View File

@@ -479,8 +479,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
}
ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq, IRQF_ONESHOT,
0, sec_irq_chip, &sec_pmic->irq_data);
if (ret != 0) {
dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);

View File

@@ -18,6 +18,9 @@
#define SPRD_PMIC_INT_RAW_STATUS 0x4
#define SPRD_PMIC_INT_EN 0x8
#define SPRD_SC2730_IRQ_BASE 0x80
#define SPRD_SC2730_IRQ_NUMS 10
#define SPRD_SC2730_CHG_DET 0x1b9c
#define SPRD_SC2731_IRQ_BASE 0x140
#define SPRD_SC2731_IRQ_NUMS 16
#define SPRD_SC2731_CHG_DET 0xedc
@@ -52,6 +55,12 @@ struct sprd_pmic_data {
* base address and irq number, we should save irq number and irq base
* in the device data structure.
*/
static const struct sprd_pmic_data sc2730_data = {
.irq_base = SPRD_SC2730_IRQ_BASE,
.num_irqs = SPRD_SC2730_IRQ_NUMS,
.charger_det = SPRD_SC2730_CHG_DET,
};
static const struct sprd_pmic_data sc2731_data = {
.irq_base = SPRD_SC2731_IRQ_BASE,
.num_irqs = SPRD_SC2731_IRQ_NUMS,
@@ -232,10 +241,17 @@ static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume);
static const struct of_device_id sprd_pmic_match[] = {
{ .compatible = "sprd,sc2731", .data = &sc2731_data },
{ .compatible = "sprd,sc2730", .data = &sc2730_data },
{},
};
MODULE_DEVICE_TABLE(of, sprd_pmic_match);
static const struct spi_device_id sprd_pmic_spi_ids[] = {
{ .name = "sc2731", .driver_data = (unsigned long)&sc2731_data },
{},
};
MODULE_DEVICE_TABLE(spi, sprd_pmic_spi_ids);
static struct spi_driver sprd_pmic_driver = {
.driver = {
.name = "sc27xx-pmic",
@@ -243,6 +259,7 @@ static struct spi_driver sprd_pmic_driver = {
.pm = &sprd_pmic_pm_ops,
},
.probe = sprd_pmic_probe,
.id_table = sprd_pmic_spi_ids,
};
static int __init sprd_pmic_init(void)

View File

@@ -95,7 +95,9 @@ static int stmpe_i2c_remove(struct i2c_client *i2c)
{
struct stmpe *stmpe = dev_get_drvdata(&i2c->dev);
return stmpe_remove(stmpe);
stmpe_remove(stmpe);
return 0;
}
static const struct i2c_device_id stmpe_i2c_id[] = {

View File

@@ -106,7 +106,9 @@ static int stmpe_spi_remove(struct spi_device *spi)
{
struct stmpe *stmpe = spi_get_drvdata(spi);
return stmpe_remove(stmpe);
stmpe_remove(stmpe);
return 0;
}
static const struct of_device_id stmpe_spi_of_match[] = {

View File

@@ -1496,7 +1496,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
return ret;
}
int stmpe_remove(struct stmpe *stmpe)
void stmpe_remove(struct stmpe *stmpe)
{
if (!IS_ERR(stmpe->vio))
regulator_disable(stmpe->vio);
@@ -1506,8 +1506,6 @@ int stmpe_remove(struct stmpe *stmpe)
__stmpe_disable(stmpe, STMPE_BLOCK_ADC);
mfd_remove_devices(stmpe->dev);
return 0;
}
#ifdef CONFIG_PM

View File

@@ -98,7 +98,7 @@ struct stmpe_client_info {
};
int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum);
int stmpe_remove(struct stmpe *stmpe);
void stmpe_remove(struct stmpe *stmpe);
#define STMPE_ICR_LSB_HIGH (1 << 2)
#define STMPE_ICR_LSB_EDGE (1 << 1)

View File

@@ -1,16 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* TI Touch Screen / ADC MFD driver
*
* Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
@@ -113,59 +105,27 @@ static void tscadc_idle_config(struct ti_tscadc_dev *tscadc)
{
unsigned int idleconfig;
idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM |
STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN;
idleconfig = STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM;
if (ti_adc_with_touchscreen(tscadc))
idleconfig |= STEPCONFIG_YNN | STEPCONFIG_YPN;
regmap_write(tscadc->regmap, REG_IDLECONFIG, idleconfig);
}
static int ti_tscadc_probe(struct platform_device *pdev)
{
struct ti_tscadc_dev *tscadc;
struct resource *res;
struct clk *clk;
struct device_node *node;
struct mfd_cell *cell;
struct property *prop;
const __be32 *cur;
u32 val;
int err, ctrl;
int clock_rate;
int tsc_wires = 0, adc_channels = 0, total_channels;
int readouts = 0;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "Could not find valid DT data.\n");
return -EINVAL;
}
node = of_get_child_by_name(pdev->dev.of_node, "tsc");
of_property_read_u32(node, "ti,wires", &tsc_wires);
of_property_read_u32(node, "ti,coordiante-readouts", &readouts);
node = of_get_child_by_name(pdev->dev.of_node, "adc");
of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
adc_channels++;
if (val > 7) {
dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
val);
return -EINVAL;
}
}
total_channels = tsc_wires + adc_channels;
if (total_channels > 8) {
dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
return -EINVAL;
}
if (total_channels == 0) {
dev_err(&pdev->dev, "Need atleast one channel.\n");
return -EINVAL;
}
if (readouts * 2 + 2 + adc_channels > 16) {
dev_err(&pdev->dev, "Too many step configurations requested\n");
return -EINVAL;
}
struct ti_tscadc_dev *tscadc;
struct resource *res;
struct clk *clk;
struct device_node *node;
struct mfd_cell *cell;
struct property *prop;
const __be32 *cur;
bool use_tsc = false, use_mag = false;
u32 val;
int err;
int tscmag_wires = 0, adc_channels = 0, cell_idx = 0, total_channels;
int readouts = 0, mag_tracks = 0;
/* Allocate memory for device */
tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL);
@@ -174,9 +134,70 @@ static int ti_tscadc_probe(struct platform_device *pdev)
tscadc->dev = &pdev->dev;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "Could not find valid DT data.\n");
return -EINVAL;
}
tscadc->data = of_device_get_match_data(&pdev->dev);
if (ti_adc_with_touchscreen(tscadc)) {
node = of_get_child_by_name(pdev->dev.of_node, "tsc");
of_property_read_u32(node, "ti,wires", &tscmag_wires);
err = of_property_read_u32(node, "ti,coordinate-readouts",
&readouts);
if (err < 0)
of_property_read_u32(node, "ti,coordiante-readouts",
&readouts);
of_node_put(node);
if (tscmag_wires)
use_tsc = true;
} else {
/*
* When adding support for the magnetic stripe reader, here is
* the place to look for the number of tracks used from device
* tree. Let's default to 0 for now.
*/
mag_tracks = 0;
tscmag_wires = mag_tracks * 2;
if (tscmag_wires)
use_mag = true;
}
node = of_get_child_by_name(pdev->dev.of_node, "adc");
of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
adc_channels++;
if (val > 7) {
dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
val);
of_node_put(node);
return -EINVAL;
}
}
of_node_put(node);
total_channels = tscmag_wires + adc_channels;
if (total_channels > 8) {
dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
return -EINVAL;
}
if (total_channels == 0) {
dev_err(&pdev->dev, "Need at least one channel.\n");
return -EINVAL;
}
if (use_tsc && (readouts * 2 + 2 + adc_channels > 16)) {
dev_err(&pdev->dev, "Too many step configurations requested\n");
return -EINVAL;
}
err = platform_get_irq(pdev, 0);
if (err < 0)
goto ret;
return err;
else
tscadc->irq = err;
@@ -187,11 +208,11 @@ static int ti_tscadc_probe(struct platform_device *pdev)
tscadc->tscadc_phys_base = res->start;
tscadc->regmap = devm_regmap_init_mmio(&pdev->dev,
tscadc->tscadc_base, &tscadc_regmap_config);
tscadc->tscadc_base,
&tscadc_regmap_config);
if (IS_ERR(tscadc->regmap)) {
dev_err(&pdev->dev, "regmap init failed\n");
err = PTR_ERR(tscadc->regmap);
goto ret;
return PTR_ERR(tscadc->regmap);
}
spin_lock_init(&tscadc->reg_lock);
@@ -201,71 +222,70 @@ static int ti_tscadc_probe(struct platform_device *pdev)
pm_runtime_get_sync(&pdev->dev);
/*
* The TSC_ADC_Subsystem has 2 clock domains
* OCP_CLK and ADC_CLK.
* The ADC clock is expected to run at target of 3MHz,
* and expected to capture 12-bit data at a rate of 200 KSPS.
* The TSC_ADC_SS controller design assumes the OCP clock is
* at least 6x faster than the ADC clock.
* The TSC_ADC_Subsystem has 2 clock domains: OCP_CLK and ADC_CLK.
* ADCs produce a 12-bit sample every 15 ADC_CLK cycles.
* am33xx ADCs expect to capture 200ksps.
* am47xx ADCs expect to capture 867ksps.
* We need ADC clocks respectively running at 3MHz and 13MHz.
* These frequencies are valid since TSC_ADC_SS controller design
* assumes the OCP clock is at least 6x faster than the ADC clock.
*/
clk = devm_clk_get(&pdev->dev, "adc_tsc_fck");
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get TSC fck\n");
dev_err(&pdev->dev, "failed to get fck\n");
err = PTR_ERR(clk);
goto err_disable_clk;
}
clock_rate = clk_get_rate(clk);
tscadc->clk_div = clock_rate / ADC_CLK;
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
tscadc->clk_div--;
tscadc->clk_div = (clk_get_rate(clk) / tscadc->data->target_clk_rate) - 1;
regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div);
/* Set the control register bits */
ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID;
regmap_write(tscadc->regmap, REG_CTRL, ctrl);
/* Set register bits for Idle Config Mode */
if (tsc_wires > 0) {
tscadc->tsc_wires = tsc_wires;
if (tsc_wires == 5)
ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB;
else
ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
tscadc_idle_config(tscadc);
/*
* Set the control register bits. tscadc->ctrl stores the configuration
* of the CTRL register but not the subsystem enable bit which must be
* added manually when timely.
*/
tscadc->ctrl = CNTRLREG_STEPID;
if (ti_adc_with_touchscreen(tscadc)) {
tscadc->ctrl |= CNTRLREG_TSC_STEPCONFIGWRT;
if (use_tsc) {
tscadc->ctrl |= CNTRLREG_TSC_ENB;
if (tscmag_wires == 5)
tscadc->ctrl |= CNTRLREG_TSC_5WIRE;
else
tscadc->ctrl |= CNTRLREG_TSC_4WIRE;
}
} else {
tscadc->ctrl |= CNTRLREG_MAG_PREAMP_PWRDOWN |
CNTRLREG_MAG_PREAMP_BYPASS;
}
regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl);
tscadc_idle_config(tscadc);
/* Enable the TSC module enable bit */
ctrl |= CNTRLREG_TSCSSENB;
regmap_write(tscadc->regmap, REG_CTRL, ctrl);
regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl | CNTRLREG_SSENB);
tscadc->used_cells = 0;
tscadc->tsc_cell = -1;
tscadc->adc_cell = -1;
/* TSC Cell */
if (tsc_wires > 0) {
tscadc->tsc_cell = tscadc->used_cells;
cell = &tscadc->cells[tscadc->used_cells++];
cell->name = "TI-am335x-tsc";
cell->of_compatible = "ti,am3359-tsc";
/* TSC or MAG Cell */
if (use_tsc || use_mag) {
cell = &tscadc->cells[cell_idx++];
cell->name = tscadc->data->secondary_feature_name;
cell->of_compatible = tscadc->data->secondary_feature_compatible;
cell->platform_data = &tscadc;
cell->pdata_size = sizeof(tscadc);
}
/* ADC Cell */
if (adc_channels > 0) {
tscadc->adc_cell = tscadc->used_cells;
cell = &tscadc->cells[tscadc->used_cells++];
cell->name = "TI-am335x-adc";
cell->of_compatible = "ti,am3359-adc";
cell = &tscadc->cells[cell_idx++];
cell->name = tscadc->data->adc_feature_name;
cell->of_compatible = tscadc->data->adc_feature_compatible;
cell->platform_data = &tscadc;
cell->pdata_size = sizeof(tscadc);
}
err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
tscadc->cells, tscadc->used_cells, NULL,
0, NULL);
tscadc->cells, cell_idx, NULL, 0, NULL);
if (err < 0)
goto err_disable_clk;
@@ -275,13 +295,13 @@ static int ti_tscadc_probe(struct platform_device *pdev)
err_disable_clk:
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
ret:
return err;
}
static int ti_tscadc_remove(struct platform_device *pdev)
{
struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev);
struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev);
regmap_write(tscadc->regmap, REG_SE, 0x00);
@@ -300,7 +320,7 @@ static int __maybe_unused ti_tscadc_can_wakeup(struct device *dev, void *data)
static int __maybe_unused tscadc_suspend(struct device *dev)
{
struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
regmap_write(tscadc->regmap, REG_SE, 0x00);
if (device_for_each_child(dev, NULL, ti_tscadc_can_wakeup)) {
@@ -308,7 +328,7 @@ static int __maybe_unused tscadc_suspend(struct device *dev)
regmap_read(tscadc->regmap, REG_CTRL, &ctrl);
ctrl &= ~(CNTRLREG_POWERDOWN);
ctrl |= CNTRLREG_TSCSSENB;
ctrl |= CNTRLREG_SSENB;
regmap_write(tscadc->regmap, REG_CTRL, ctrl);
}
pm_runtime_put_sync(dev);
@@ -318,34 +338,39 @@ static int __maybe_unused tscadc_suspend(struct device *dev)
static int __maybe_unused tscadc_resume(struct device *dev)
{
struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
u32 ctrl;
struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev);
pm_runtime_get_sync(dev);
/* context restore */
ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID;
regmap_write(tscadc->regmap, REG_CTRL, ctrl);
if (tscadc->tsc_cell != -1) {
if (tscadc->tsc_wires == 5)
ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB;
else
ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
tscadc_idle_config(tscadc);
}
ctrl |= CNTRLREG_TSCSSENB;
regmap_write(tscadc->regmap, REG_CTRL, ctrl);
regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div);
regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl);
tscadc_idle_config(tscadc);
regmap_write(tscadc->regmap, REG_CTRL, tscadc->ctrl | CNTRLREG_SSENB);
return 0;
}
static SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume);
static const struct ti_tscadc_data tscdata = {
.adc_feature_name = "TI-am335x-adc",
.adc_feature_compatible = "ti,am3359-adc",
.secondary_feature_name = "TI-am335x-tsc",
.secondary_feature_compatible = "ti,am3359-tsc",
.target_clk_rate = TSC_ADC_CLK,
};
static const struct ti_tscadc_data magdata = {
.adc_feature_name = "TI-am43xx-adc",
.adc_feature_compatible = "ti,am4372-adc",
.secondary_feature_name = "TI-am43xx-mag",
.secondary_feature_compatible = "ti,am4372-mag",
.target_clk_rate = MAG_ADC_CLK,
};
static const struct of_device_id ti_tscadc_dt_ids[] = {
{ .compatible = "ti,am3359-tscadc", },
{ .compatible = "ti,am3359-tscadc", .data = &tscdata },
{ .compatible = "ti,am4372-magadc", .data = &magdata },
{ }
};
MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
@@ -363,6 +388,6 @@ static struct platform_driver ti_tscadc_driver = {
module_platform_driver(ti_tscadc_driver);
MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
MODULE_DESCRIPTION("TI touchscreen/magnetic stripe reader/ADC MFD controller driver");
MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
MODULE_LICENSE("GPL");

View File

@@ -115,11 +115,9 @@ int tps65912_device_init(struct tps65912 *tps)
}
EXPORT_SYMBOL_GPL(tps65912_device_init);
int tps65912_device_exit(struct tps65912 *tps)
void tps65912_device_exit(struct tps65912 *tps)
{
regmap_del_irq_chip(tps->irq, tps->irq_data);
return 0;
}
EXPORT_SYMBOL_GPL(tps65912_device_exit);

View File

@@ -55,7 +55,9 @@ static int tps65912_i2c_remove(struct i2c_client *client)
{
struct tps65912 *tps = i2c_get_clientdata(client);
return tps65912_device_exit(tps);
tps65912_device_exit(tps);
return 0;
}
static const struct i2c_device_id tps65912_i2c_id_table[] = {

View File

@@ -54,7 +54,9 @@ static int tps65912_spi_remove(struct spi_device *spi)
{
struct tps65912 *tps = spi_get_drvdata(spi);
return tps65912_device_exit(tps);
tps65912_device_exit(tps);
return 0;
}
static const struct spi_device_id tps65912_spi_id_table[] = {

View File

@@ -1,526 +0,0 @@
/*
* tps80031.c -- TI TPS80031/TPS80032 mfd core driver.
*
* MFD core driver for TI TPS80031/TPS80032 Fully Integrated
* Power Management with Power Path and Battery Charger
*
* Copyright (c) 2012, NVIDIA Corporation.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
* whether express or implied; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps80031.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
static const struct resource tps80031_rtc_resources[] = {
DEFINE_RES_IRQ(TPS80031_INT_RTC_ALARM),
};
/* TPS80031 sub mfd devices */
static const struct mfd_cell tps80031_cell[] = {
{
.name = "tps80031-pmic",
},
{
.name = "tps80031-clock",
},
{
.name = "tps80031-rtc",
.num_resources = ARRAY_SIZE(tps80031_rtc_resources),
.resources = tps80031_rtc_resources,
},
{
.name = "tps80031-gpadc",
},
{
.name = "tps80031-fuel-gauge",
},
{
.name = "tps80031-charger",
},
};
static int tps80031_slave_address[TPS80031_NUM_SLAVES] = {
TPS80031_I2C_ID0_ADDR,
TPS80031_I2C_ID1_ADDR,
TPS80031_I2C_ID2_ADDR,
TPS80031_I2C_ID3_ADDR,
};
struct tps80031_pupd_data {
u8 reg;
u8 pullup_bit;
u8 pulldown_bit;
};
#define TPS80031_IRQ(_reg, _mask) \
{ \
.reg_offset = (TPS80031_INT_MSK_LINE_##_reg) - \
TPS80031_INT_MSK_LINE_A, \
.mask = BIT(_mask), \
}
static const struct regmap_irq tps80031_main_irqs[] = {
[TPS80031_INT_PWRON] = TPS80031_IRQ(A, 0),
[TPS80031_INT_RPWRON] = TPS80031_IRQ(A, 1),
[TPS80031_INT_SYS_VLOW] = TPS80031_IRQ(A, 2),
[TPS80031_INT_RTC_ALARM] = TPS80031_IRQ(A, 3),
[TPS80031_INT_RTC_PERIOD] = TPS80031_IRQ(A, 4),
[TPS80031_INT_HOT_DIE] = TPS80031_IRQ(A, 5),
[TPS80031_INT_VXX_SHORT] = TPS80031_IRQ(A, 6),
[TPS80031_INT_SPDURATION] = TPS80031_IRQ(A, 7),
[TPS80031_INT_WATCHDOG] = TPS80031_IRQ(B, 0),
[TPS80031_INT_BAT] = TPS80031_IRQ(B, 1),
[TPS80031_INT_SIM] = TPS80031_IRQ(B, 2),
[TPS80031_INT_MMC] = TPS80031_IRQ(B, 3),
[TPS80031_INT_RES] = TPS80031_IRQ(B, 4),
[TPS80031_INT_GPADC_RT] = TPS80031_IRQ(B, 5),
[TPS80031_INT_GPADC_SW2_EOC] = TPS80031_IRQ(B, 6),
[TPS80031_INT_CC_AUTOCAL] = TPS80031_IRQ(B, 7),
[TPS80031_INT_ID_WKUP] = TPS80031_IRQ(C, 0),
[TPS80031_INT_VBUSS_WKUP] = TPS80031_IRQ(C, 1),
[TPS80031_INT_ID] = TPS80031_IRQ(C, 2),
[TPS80031_INT_VBUS] = TPS80031_IRQ(C, 3),
[TPS80031_INT_CHRG_CTRL] = TPS80031_IRQ(C, 4),
[TPS80031_INT_EXT_CHRG] = TPS80031_IRQ(C, 5),
[TPS80031_INT_INT_CHRG] = TPS80031_IRQ(C, 6),
[TPS80031_INT_RES2] = TPS80031_IRQ(C, 7),
};
static struct regmap_irq_chip tps80031_irq_chip = {
.name = "tps80031",
.irqs = tps80031_main_irqs,
.num_irqs = ARRAY_SIZE(tps80031_main_irqs),
.num_regs = 3,
.status_base = TPS80031_INT_STS_A,
.mask_base = TPS80031_INT_MSK_LINE_A,
};
#define PUPD_DATA(_reg, _pulldown_bit, _pullup_bit) \
{ \
.reg = TPS80031_CFG_INPUT_PUPD##_reg, \
.pulldown_bit = _pulldown_bit, \
.pullup_bit = _pullup_bit, \
}
static const struct tps80031_pupd_data tps80031_pupds[] = {
[TPS80031_PREQ1] = PUPD_DATA(1, BIT(0), BIT(1)),
[TPS80031_PREQ2A] = PUPD_DATA(1, BIT(2), BIT(3)),
[TPS80031_PREQ2B] = PUPD_DATA(1, BIT(4), BIT(5)),
[TPS80031_PREQ2C] = PUPD_DATA(1, BIT(6), BIT(7)),
[TPS80031_PREQ3] = PUPD_DATA(2, BIT(0), BIT(1)),
[TPS80031_NRES_WARM] = PUPD_DATA(2, 0, BIT(2)),
[TPS80031_PWM_FORCE] = PUPD_DATA(2, BIT(5), 0),
[TPS80031_CHRG_EXT_CHRG_STATZ] = PUPD_DATA(2, 0, BIT(6)),
[TPS80031_SIM] = PUPD_DATA(3, BIT(0), BIT(1)),
[TPS80031_MMC] = PUPD_DATA(3, BIT(2), BIT(3)),
[TPS80031_GPADC_START] = PUPD_DATA(3, BIT(4), 0),
[TPS80031_DVSI2C_SCL] = PUPD_DATA(4, 0, BIT(0)),
[TPS80031_DVSI2C_SDA] = PUPD_DATA(4, 0, BIT(1)),
[TPS80031_CTLI2C_SCL] = PUPD_DATA(4, 0, BIT(2)),
[TPS80031_CTLI2C_SDA] = PUPD_DATA(4, 0, BIT(3)),
};
static struct tps80031 *tps80031_power_off_dev;
int tps80031_ext_power_req_config(struct device *dev,
unsigned long ext_ctrl_flag, int preq_bit,
int state_reg_add, int trans_reg_add)
{
u8 res_ass_reg = 0;
int preq_mask_bit = 0;
int ret;
if (!(ext_ctrl_flag & TPS80031_EXT_PWR_REQ))
return 0;
if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ1) {
res_ass_reg = TPS80031_PREQ1_RES_ASS_A + (preq_bit >> 3);
preq_mask_bit = 5;
} else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ2) {
res_ass_reg = TPS80031_PREQ2_RES_ASS_A + (preq_bit >> 3);
preq_mask_bit = 6;
} else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ3) {
res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (preq_bit >> 3);
preq_mask_bit = 7;
}
/* Configure REQ_ASS registers */
ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1, res_ass_reg,
BIT(preq_bit & 0x7));
if (ret < 0) {
dev_err(dev, "reg 0x%02x setbit failed, err = %d\n",
res_ass_reg, ret);
return ret;
}
/* Unmask the PREQ */
ret = tps80031_clr_bits(dev, TPS80031_SLAVE_ID1,
TPS80031_PHOENIX_MSK_TRANSITION, BIT(preq_mask_bit));
if (ret < 0) {
dev_err(dev, "reg 0x%02x clrbit failed, err = %d\n",
TPS80031_PHOENIX_MSK_TRANSITION, ret);
return ret;
}
/* Switch regulator control to resource now */
if (ext_ctrl_flag & (TPS80031_PWR_REQ_INPUT_PREQ2 |
TPS80031_PWR_REQ_INPUT_PREQ3)) {
ret = tps80031_update(dev, TPS80031_SLAVE_ID1, state_reg_add,
0x0, TPS80031_STATE_MASK);
if (ret < 0)
dev_err(dev, "reg 0x%02x update failed, err = %d\n",
state_reg_add, ret);
} else {
ret = tps80031_update(dev, TPS80031_SLAVE_ID1, trans_reg_add,
TPS80031_TRANS_SLEEP_OFF,
TPS80031_TRANS_SLEEP_MASK);
if (ret < 0)
dev_err(dev, "reg 0x%02x update failed, err = %d\n",
trans_reg_add, ret);
}
return ret;
}
EXPORT_SYMBOL_GPL(tps80031_ext_power_req_config);
static void tps80031_power_off(void)
{
dev_info(tps80031_power_off_dev->dev, "switching off PMU\n");
tps80031_write(tps80031_power_off_dev->dev, TPS80031_SLAVE_ID1,
TPS80031_PHOENIX_DEV_ON, TPS80031_DEVOFF);
}
static void tps80031_pupd_init(struct tps80031 *tps80031,
struct tps80031_platform_data *pdata)
{
struct tps80031_pupd_init_data *pupd_init_data = pdata->pupd_init_data;
int data_size = pdata->pupd_init_data_size;
int i;
for (i = 0; i < data_size; ++i) {
struct tps80031_pupd_init_data *pupd_init = &pupd_init_data[i];
const struct tps80031_pupd_data *pupd =
&tps80031_pupds[pupd_init->input_pin];
u8 update_value = 0;
u8 update_mask = pupd->pulldown_bit | pupd->pullup_bit;
if (pupd_init->setting == TPS80031_PUPD_PULLDOWN)
update_value = pupd->pulldown_bit;
else if (pupd_init->setting == TPS80031_PUPD_PULLUP)
update_value = pupd->pullup_bit;
tps80031_update(tps80031->dev, TPS80031_SLAVE_ID1, pupd->reg,
update_value, update_mask);
}
}
static int tps80031_init_ext_control(struct tps80031 *tps80031,
struct tps80031_platform_data *pdata)
{
struct device *dev = tps80031->dev;
int ret;
int i;
/* Clear all external control for this rail */
for (i = 0; i < 9; ++i) {
ret = tps80031_write(dev, TPS80031_SLAVE_ID1,
TPS80031_PREQ1_RES_ASS_A + i, 0);
if (ret < 0) {
dev_err(dev, "reg 0x%02x write failed, err = %d\n",
TPS80031_PREQ1_RES_ASS_A + i, ret);
return ret;
}
}
/* Mask the PREQ */
ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1,
TPS80031_PHOENIX_MSK_TRANSITION, 0x7 << 5);
if (ret < 0) {
dev_err(dev, "reg 0x%02x set_bits failed, err = %d\n",
TPS80031_PHOENIX_MSK_TRANSITION, ret);
return ret;
}
return ret;
}
static int tps80031_irq_init(struct tps80031 *tps80031, int irq, int irq_base)
{
struct device *dev = tps80031->dev;
int i, ret;
/*
* The MASK register used for updating status register when
* interrupt occurs and LINE register used to pass the status
* to actual interrupt line. As per datasheet:
* When INT_MSK_LINE [i] is set to 1, the associated interrupt
* number i is INT line masked, which means that no interrupt is
* generated on the INT line.
* When INT_MSK_LINE [i] is set to 0, the associated interrupt
* number i is line enabled: An interrupt is generated on the
* INT line.
* In any case, the INT_STS [i] status bit may or may not be updated,
* only linked to the INT_MSK_STS [i] configuration register bit.
*
* When INT_MSK_STS [i] is set to 1, the associated interrupt number
* i is status masked, which means that no interrupt is stored in
* the INT_STS[i] status bit. Note that no interrupt number i is
* generated on the INT line, even if the INT_MSK_LINE [i] register
* bit is set to 0.
* When INT_MSK_STS [i] is set to 0, the associated interrupt number i
* is status enabled: An interrupt status is updated in the INT_STS [i]
* register. The interrupt may or may not be generated on the INT line,
* depending on the INT_MSK_LINE [i] configuration register bit.
*/
for (i = 0; i < 3; i++)
tps80031_write(dev, TPS80031_SLAVE_ID2,
TPS80031_INT_MSK_STS_A + i, 0x00);
ret = regmap_add_irq_chip(tps80031->regmap[TPS80031_SLAVE_ID2], irq,
IRQF_ONESHOT, irq_base,
&tps80031_irq_chip, &tps80031->irq_data);
if (ret < 0) {
dev_err(dev, "add irq failed, err = %d\n", ret);
return ret;
}
return ret;
}
static bool rd_wr_reg_id0(struct device *dev, unsigned int reg)
{
switch (reg) {
case TPS80031_SMPS1_CFG_FORCE ... TPS80031_SMPS2_CFG_VOLTAGE:
return true;
default:
return false;
}
}
static bool rd_wr_reg_id1(struct device *dev, unsigned int reg)
{
switch (reg) {
case TPS80031_SECONDS_REG ... TPS80031_RTC_RESET_STATUS_REG:
case TPS80031_VALIDITY0 ... TPS80031_VALIDITY7:
case TPS80031_PHOENIX_START_CONDITION ... TPS80031_KEY_PRESS_DUR_CFG:
case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE:
case TPS80031_BROADCAST_ADDR_ALL ... TPS80031_BROADCAST_ADDR_CLK_RST:
case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE:
case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE:
case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C:
case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING:
case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD:
case TPS80031_BACKUP_REG:
return true;
default:
return false;
}
}
static bool is_volatile_reg_id1(struct device *dev, unsigned int reg)
{
switch (reg) {
case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE:
case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE:
case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE:
case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C:
case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING:
case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD:
return true;
default:
return false;
}
}
static bool rd_wr_reg_id2(struct device *dev, unsigned int reg)
{
switch (reg) {
case TPS80031_USB_VENDOR_ID_LSB ... TPS80031_USB_OTG_REVISION:
case TPS80031_GPADC_CTRL ... TPS80031_CTRL_P1:
case TPS80031_RTCH0_LSB ... TPS80031_GPCH0_MSB:
case TPS80031_TOGGLE1 ... TPS80031_VIBMODE:
case TPS80031_PWM1ON ... TPS80031_PWM2OFF:
case TPS80031_FG_REG_00 ... TPS80031_FG_REG_11:
case TPS80031_INT_STS_A ... TPS80031_INT_MSK_STS_C:
case TPS80031_CONTROLLER_CTRL2 ... TPS80031_LED_PWM_CTRL2:
return true;
default:
return false;
}
}
static bool rd_wr_reg_id3(struct device *dev, unsigned int reg)
{
switch (reg) {
case TPS80031_GPADC_TRIM0 ... TPS80031_GPADC_TRIM18:
return true;
default:
return false;
}
}
static const struct regmap_config tps80031_regmap_configs[] = {
{
.reg_bits = 8,
.val_bits = 8,
.writeable_reg = rd_wr_reg_id0,
.readable_reg = rd_wr_reg_id0,
.max_register = TPS80031_MAX_REGISTER,
},
{
.reg_bits = 8,
.val_bits = 8,
.writeable_reg = rd_wr_reg_id1,
.readable_reg = rd_wr_reg_id1,
.volatile_reg = is_volatile_reg_id1,
.max_register = TPS80031_MAX_REGISTER,
},
{
.reg_bits = 8,
.val_bits = 8,
.writeable_reg = rd_wr_reg_id2,
.readable_reg = rd_wr_reg_id2,
.max_register = TPS80031_MAX_REGISTER,
},
{
.reg_bits = 8,
.val_bits = 8,
.writeable_reg = rd_wr_reg_id3,
.readable_reg = rd_wr_reg_id3,
.max_register = TPS80031_MAX_REGISTER,
},
};
static int tps80031_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps80031_platform_data *pdata = dev_get_platdata(&client->dev);
struct tps80031 *tps80031;
int ret;
uint8_t es_version;
uint8_t ep_ver;
int i;
if (!pdata) {
dev_err(&client->dev, "tps80031 requires platform data\n");
return -EINVAL;
}
tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
if (!tps80031)
return -ENOMEM;
for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
if (tps80031_slave_address[i] == client->addr)
tps80031->clients[i] = client;
else
tps80031->clients[i] = devm_i2c_new_dummy_device(&client->dev,
client->adapter, tps80031_slave_address[i]);
if (IS_ERR(tps80031->clients[i])) {
dev_err(&client->dev, "can't attach client %d\n", i);
return PTR_ERR(tps80031->clients[i]);
}
i2c_set_clientdata(tps80031->clients[i], tps80031);
tps80031->regmap[i] = devm_regmap_init_i2c(tps80031->clients[i],
&tps80031_regmap_configs[i]);
if (IS_ERR(tps80031->regmap[i])) {
ret = PTR_ERR(tps80031->regmap[i]);
dev_err(&client->dev,
"regmap %d init failed, err %d\n", i, ret);
return ret;
}
}
ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3,
TPS80031_JTAGVERNUM, &es_version);
if (ret < 0) {
dev_err(&client->dev,
"Silicon version number read failed: %d\n", ret);
return ret;
}
ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3,
TPS80031_EPROM_REV, &ep_ver);
if (ret < 0) {
dev_err(&client->dev,
"Silicon eeprom version read failed: %d\n", ret);
return ret;
}
dev_info(&client->dev, "ES version 0x%02x and EPROM version 0x%02x\n",
es_version, ep_ver);
tps80031->es_version = es_version;
tps80031->dev = &client->dev;
i2c_set_clientdata(client, tps80031);
tps80031->chip_info = id->driver_data;
ret = tps80031_irq_init(tps80031, client->irq, pdata->irq_base);
if (ret) {
dev_err(&client->dev, "IRQ init failed: %d\n", ret);
return ret;
}
tps80031_pupd_init(tps80031, pdata);
tps80031_init_ext_control(tps80031, pdata);
ret = mfd_add_devices(tps80031->dev, -1,
tps80031_cell, ARRAY_SIZE(tps80031_cell),
NULL, 0,
regmap_irq_get_domain(tps80031->irq_data));
if (ret < 0) {
dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
goto fail_mfd_add;
}
if (pdata->use_power_off && !pm_power_off) {
tps80031_power_off_dev = tps80031;
pm_power_off = tps80031_power_off;
}
return 0;
fail_mfd_add:
regmap_del_irq_chip(client->irq, tps80031->irq_data);
return ret;
}
static const struct i2c_device_id tps80031_id_table[] = {
{ "tps80031", TPS80031 },
{ "tps80032", TPS80032 },
{ }
};
static struct i2c_driver tps80031_driver = {
.driver = {
.name = "tps80031",
.suppress_bind_attrs = true,
},
.probe = tps80031_probe,
.id_table = tps80031_id_table,
};
static int __init tps80031_init(void)
{
return i2c_add_driver(&tps80031_driver);
}
subsys_initcall(tps80031_init);

View File

@@ -2,14 +2,13 @@
// Copyright (c) 2019, Linaro Limited
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wcd934x/registers.h>
#include <linux/mfd/wcd934x/wcd934x.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
@@ -210,7 +209,8 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
struct device *dev = &sdev->dev;
struct device_node *np = dev->of_node;
struct wcd934x_ddata *ddata;
int reset_gpio, ret;
struct gpio_desc *reset_gpio;
int ret;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
@@ -221,13 +221,6 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
return dev_err_probe(ddata->dev, ddata->irq,
"Failed to get IRQ\n");
reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
if (reset_gpio < 0) {
dev_err(dev, "Failed to get reset gpio: err = %d\n",
reset_gpio);
return reset_gpio;
}
ddata->extclk = devm_clk_get(dev, "extclk");
if (IS_ERR(ddata->extclk)) {
dev_err(dev, "Failed to get extclk");
@@ -258,9 +251,13 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
* SYS_RST_N shouldn't be pulled high during this time
*/
usleep_range(600, 650);
gpio_direction_output(reset_gpio, 0);
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(reset_gpio)) {
return dev_err_probe(dev, PTR_ERR(reset_gpio),
"Failed to get reset gpio: err = %ld\n", PTR_ERR(reset_gpio));
}
msleep(20);
gpio_set_value(reset_gpio, 1);
gpiod_set_value(reset_gpio, 1);
msleep(20);
ddata->dev = dev;

View File

@@ -10,7 +10,6 @@
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
@@ -220,7 +219,7 @@ static int hi6421v600_irq_probe(struct platform_device *pdev)
struct platform_device *pmic_pdev;
struct device *dev = &pdev->dev;
struct hi6421v600_irq *priv;
struct hi6421_spmi_pmic *pmic;
struct regmap *regmap;
unsigned int virq;
int i, ret;
@@ -229,8 +228,8 @@ static int hi6421v600_irq_probe(struct platform_device *pdev)
* which should first set drvdata. If this doesn't happen, hit
* a warn on and return.
*/
pmic = dev_get_drvdata(pmic_dev);
if (WARN_ON(!pmic))
regmap = dev_get_drvdata(pmic_dev);
if (WARN_ON(!regmap))
return -ENODEV;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -238,7 +237,7 @@ static int hi6421v600_irq_probe(struct platform_device *pdev)
return -ENOMEM;
priv->dev = dev;
priv->regmap = pmic->regmap;
priv->regmap = regmap;
spin_lock_init(&priv->lock);

View File

@@ -9,8 +9,8 @@
// Guodong Xu <guodong.xu@linaro.org>
#include <linux/delay.h>
#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
@@ -237,7 +237,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
struct hi6421_spmi_reg_priv *priv;
struct hi6421_spmi_reg_info *info;
struct device *dev = &pdev->dev;
struct hi6421_spmi_pmic *pmic;
struct regmap *regmap;
struct regulator_dev *rdev;
int i;
@@ -246,8 +246,8 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
* which should first set drvdata. If this doesn't happen, hit
* a warn on and return.
*/
pmic = dev_get_drvdata(pmic_dev);
if (WARN_ON(!pmic))
regmap = dev_get_drvdata(pmic_dev);
if (WARN_ON(!regmap))
return -ENODEV;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -261,7 +261,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
config.dev = pdev->dev.parent;
config.driver_data = priv;
config.regmap = pmic->regmap;
config.regmap = regmap;
rdev = devm_regulator_register(dev, &info->desc, &config);
if (IS_ERR(rdev)) {

View File

@@ -292,10 +292,13 @@ static ssize_t actual_brightness_show(struct device *dev,
struct backlight_device *bd = to_backlight_device(dev);
mutex_lock(&bd->ops_lock);
if (bd->ops && bd->ops->get_brightness)
rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd));
else
if (bd->ops && bd->ops->get_brightness) {
rc = bd->ops->get_brightness(bd);
if (rc >= 0)
rc = sprintf(buf, "%d\n", rc);
} else {
rc = sprintf(buf, "%d\n", bd->props.brightness);
}
mutex_unlock(&bd->ops_lock);
return rc;
@@ -381,9 +384,18 @@ ATTRIBUTE_GROUPS(bl_device);
void backlight_force_update(struct backlight_device *bd,
enum backlight_update_reason reason)
{
int brightness;
mutex_lock(&bd->ops_lock);
if (bd->ops && bd->ops->get_brightness)
bd->props.brightness = bd->ops->get_brightness(bd);
if (bd->ops && bd->ops->get_brightness) {
brightness = bd->ops->get_brightness(bd);
if (brightness >= 0)
bd->props.brightness = brightness;
else
dev_err(&bd->dev,
"Could not update brightness from device: %pe\n",
ERR_PTR(brightness));
}
mutex_unlock(&bd->ops_lock);
backlight_generate_event(bd, reason);
}
@@ -688,12 +700,6 @@ static struct backlight_device *of_find_backlight(struct device *dev)
of_node_put(np);
if (!bd)
return ERR_PTR(-EPROBE_DEFER);
/*
* Note: gpio_backlight uses brightness as
* power state during probe
*/
if (!bd->props.brightness)
bd->props.brightness = bd->props.max_brightness;
}
}

View File

@@ -251,10 +251,9 @@ int ili9320_probe_spi(struct spi_device *spi,
}
EXPORT_SYMBOL_GPL(ili9320_probe_spi);
int ili9320_remove(struct ili9320 *ili)
void ili9320_remove(struct ili9320 *ili)
{
ili9320_power(ili, FB_BLANK_POWERDOWN);
return 0;
}
EXPORT_SYMBOL_GPL(ili9320_remove);

View File

@@ -68,7 +68,7 @@ extern int ili9320_write_regs(struct ili9320 *ili,
extern int ili9320_probe_spi(struct spi_device *spi,
struct ili9320_client *cli);
extern int ili9320_remove(struct ili9320 *lcd);
extern void ili9320_remove(struct ili9320 *lcd);
extern void ili9320_shutdown(struct ili9320 *lcd);
/* PM */

View File

@@ -235,7 +235,9 @@ static int vgg2432a4_probe(struct spi_device *spi)
static int vgg2432a4_remove(struct spi_device *spi)
{
return ili9320_remove(spi_get_drvdata(spi));
ili9320_remove(spi_get_drvdata(spi));
return 0;
}
static void vgg2432a4_shutdown(struct spi_device *spi)

View File

@@ -111,6 +111,7 @@ config VIRTIO_MEM
depends on MEMORY_HOTPLUG
depends on MEMORY_HOTREMOVE
depends on CONTIG_ALLOC
depends on EXCLUSIVE_SYSTEM_RAM
help
This driver provides access to virtio-mem paravirtualized memory
devices, allowing to hotplug and hotunplug memory.

View File

@@ -223,6 +223,9 @@ struct virtio_mem {
* When this lock is held the pointers can't change, ONLINE and
* OFFLINE blocks can't change the state and no subblocks will get
* plugged/unplugged.
*
* In kdump mode, used to serialize requests, last_block_addr and
* last_block_plugged.
*/
struct mutex hotplug_mutex;
bool hotplug_active;
@@ -230,6 +233,9 @@ struct virtio_mem {
/* An error occurred we cannot handle - stop processing requests. */
bool broken;
/* Cached valued of is_kdump_kernel() when the device was probed. */
bool in_kdump;
/* The driver is being removed. */
spinlock_t removal_lock;
bool removing;
@@ -243,6 +249,13 @@ struct virtio_mem {
/* Memory notifier (online/offline events). */
struct notifier_block memory_notifier;
#ifdef CONFIG_PROC_VMCORE
/* vmcore callback for /proc/vmcore handling in kdump mode */
struct vmcore_cb vmcore_cb;
uint64_t last_block_addr;
bool last_block_plugged;
#endif /* CONFIG_PROC_VMCORE */
/* Next device in the list of virtio-mem devices. */
struct list_head next;
};
@@ -260,6 +273,8 @@ static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
unsigned long nr_pages);
static void virtio_mem_retry(struct virtio_mem *vm);
static int virtio_mem_create_resource(struct virtio_mem *vm);
static void virtio_mem_delete_resource(struct virtio_mem *vm);
/*
* Register a virtio-mem device so it will be considered for the online_page
@@ -2291,6 +2306,12 @@ static void virtio_mem_run_wq(struct work_struct *work)
uint64_t diff;
int rc;
if (unlikely(vm->in_kdump)) {
dev_warn_once(&vm->vdev->dev,
"unexpected workqueue run in kdump kernel\n");
return;
}
hrtimer_cancel(&vm->retry_timer);
if (vm->broken)
@@ -2392,41 +2413,11 @@ static int virtio_mem_init_vq(struct virtio_mem *vm)
return 0;
}
static int virtio_mem_init(struct virtio_mem *vm)
static int virtio_mem_init_hotplug(struct virtio_mem *vm)
{
const struct range pluggable_range = mhp_get_pluggable_range(true);
uint64_t sb_size, addr;
uint16_t node_id;
if (!vm->vdev->config->get) {
dev_err(&vm->vdev->dev, "config access disabled\n");
return -EINVAL;
}
/*
* We don't want to (un)plug or reuse any memory when in kdump. The
* memory is still accessible (but not mapped).
*/
if (is_kdump_kernel()) {
dev_warn(&vm->vdev->dev, "disabled in kdump kernel\n");
return -EBUSY;
}
/* Fetch all properties that can't change. */
virtio_cread_le(vm->vdev, struct virtio_mem_config, plugged_size,
&vm->plugged_size);
virtio_cread_le(vm->vdev, struct virtio_mem_config, block_size,
&vm->device_block_size);
virtio_cread_le(vm->vdev, struct virtio_mem_config, node_id,
&node_id);
vm->nid = virtio_mem_translate_node_id(vm, node_id);
virtio_cread_le(vm->vdev, struct virtio_mem_config, addr, &vm->addr);
virtio_cread_le(vm->vdev, struct virtio_mem_config, region_size,
&vm->region_size);
/* Determine the nid for the device based on the lowest address. */
if (vm->nid == NUMA_NO_NODE)
vm->nid = memory_add_physaddr_to_nid(vm->addr);
uint64_t unit_pages, sb_size, addr;
int rc;
/* bad device setup - warn only */
if (!IS_ALIGNED(vm->addr, memory_block_size_bytes()))
@@ -2496,10 +2487,6 @@ static int virtio_mem_init(struct virtio_mem *vm)
vm->offline_threshold);
}
dev_info(&vm->vdev->dev, "start address: 0x%llx", vm->addr);
dev_info(&vm->vdev->dev, "region size: 0x%llx", vm->region_size);
dev_info(&vm->vdev->dev, "device block size: 0x%llx",
(unsigned long long)vm->device_block_size);
dev_info(&vm->vdev->dev, "memory block size: 0x%lx",
memory_block_size_bytes());
if (vm->in_sbm)
@@ -2508,10 +2495,170 @@ static int virtio_mem_init(struct virtio_mem *vm)
else
dev_info(&vm->vdev->dev, "big block size: 0x%llx",
(unsigned long long)vm->bbm.bb_size);
/* create the parent resource for all memory */
rc = virtio_mem_create_resource(vm);
if (rc)
return rc;
/* use a single dynamic memory group to cover the whole memory device */
if (vm->in_sbm)
unit_pages = PHYS_PFN(memory_block_size_bytes());
else
unit_pages = PHYS_PFN(vm->bbm.bb_size);
rc = memory_group_register_dynamic(vm->nid, unit_pages);
if (rc < 0)
goto out_del_resource;
vm->mgid = rc;
/*
* If we still have memory plugged, we have to unplug all memory first.
* Registering our parent resource makes sure that this memory isn't
* actually in use (e.g., trying to reload the driver).
*/
if (vm->plugged_size) {
vm->unplug_all_required = true;
dev_info(&vm->vdev->dev, "unplugging all memory is required\n");
}
/* register callbacks */
vm->memory_notifier.notifier_call = virtio_mem_memory_notifier_cb;
rc = register_memory_notifier(&vm->memory_notifier);
if (rc)
goto out_unreg_group;
rc = register_virtio_mem_device(vm);
if (rc)
goto out_unreg_mem;
return 0;
out_unreg_mem:
unregister_memory_notifier(&vm->memory_notifier);
out_unreg_group:
memory_group_unregister(vm->mgid);
out_del_resource:
virtio_mem_delete_resource(vm);
return rc;
}
#ifdef CONFIG_PROC_VMCORE
static int virtio_mem_send_state_request(struct virtio_mem *vm, uint64_t addr,
uint64_t size)
{
const uint64_t nb_vm_blocks = size / vm->device_block_size;
const struct virtio_mem_req req = {
.type = cpu_to_virtio16(vm->vdev, VIRTIO_MEM_REQ_STATE),
.u.state.addr = cpu_to_virtio64(vm->vdev, addr),
.u.state.nb_blocks = cpu_to_virtio16(vm->vdev, nb_vm_blocks),
};
int rc = -ENOMEM;
dev_dbg(&vm->vdev->dev, "requesting state: 0x%llx - 0x%llx\n", addr,
addr + size - 1);
switch (virtio_mem_send_request(vm, &req)) {
case VIRTIO_MEM_RESP_ACK:
return virtio16_to_cpu(vm->vdev, vm->resp.u.state.state);
case VIRTIO_MEM_RESP_ERROR:
rc = -EINVAL;
break;
default:
break;
}
dev_dbg(&vm->vdev->dev, "requesting state failed: %d\n", rc);
return rc;
}
static bool virtio_mem_vmcore_pfn_is_ram(struct vmcore_cb *cb,
unsigned long pfn)
{
struct virtio_mem *vm = container_of(cb, struct virtio_mem,
vmcore_cb);
uint64_t addr = PFN_PHYS(pfn);
bool is_ram;
int rc;
if (!virtio_mem_contains_range(vm, addr, PAGE_SIZE))
return true;
if (!vm->plugged_size)
return false;
/*
* We have to serialize device requests and access to the information
* about the block queried last.
*/
mutex_lock(&vm->hotplug_mutex);
addr = ALIGN_DOWN(addr, vm->device_block_size);
if (addr != vm->last_block_addr) {
rc = virtio_mem_send_state_request(vm, addr,
vm->device_block_size);
/* On any kind of error, we're going to signal !ram. */
if (rc == VIRTIO_MEM_STATE_PLUGGED)
vm->last_block_plugged = true;
else
vm->last_block_plugged = false;
vm->last_block_addr = addr;
}
is_ram = vm->last_block_plugged;
mutex_unlock(&vm->hotplug_mutex);
return is_ram;
}
#endif /* CONFIG_PROC_VMCORE */
static int virtio_mem_init_kdump(struct virtio_mem *vm)
{
#ifdef CONFIG_PROC_VMCORE
dev_info(&vm->vdev->dev, "memory hot(un)plug disabled in kdump kernel\n");
vm->vmcore_cb.pfn_is_ram = virtio_mem_vmcore_pfn_is_ram;
register_vmcore_cb(&vm->vmcore_cb);
return 0;
#else /* CONFIG_PROC_VMCORE */
dev_warn(&vm->vdev->dev, "disabled in kdump kernel without vmcore\n");
return -EBUSY;
#endif /* CONFIG_PROC_VMCORE */
}
static int virtio_mem_init(struct virtio_mem *vm)
{
uint16_t node_id;
if (!vm->vdev->config->get) {
dev_err(&vm->vdev->dev, "config access disabled\n");
return -EINVAL;
}
/* Fetch all properties that can't change. */
virtio_cread_le(vm->vdev, struct virtio_mem_config, plugged_size,
&vm->plugged_size);
virtio_cread_le(vm->vdev, struct virtio_mem_config, block_size,
&vm->device_block_size);
virtio_cread_le(vm->vdev, struct virtio_mem_config, node_id,
&node_id);
vm->nid = virtio_mem_translate_node_id(vm, node_id);
virtio_cread_le(vm->vdev, struct virtio_mem_config, addr, &vm->addr);
virtio_cread_le(vm->vdev, struct virtio_mem_config, region_size,
&vm->region_size);
/* Determine the nid for the device based on the lowest address. */
if (vm->nid == NUMA_NO_NODE)
vm->nid = memory_add_physaddr_to_nid(vm->addr);
dev_info(&vm->vdev->dev, "start address: 0x%llx", vm->addr);
dev_info(&vm->vdev->dev, "region size: 0x%llx", vm->region_size);
dev_info(&vm->vdev->dev, "device block size: 0x%llx",
(unsigned long long)vm->device_block_size);
if (vm->nid != NUMA_NO_NODE && IS_ENABLED(CONFIG_NUMA))
dev_info(&vm->vdev->dev, "nid: %d", vm->nid);
return 0;
/*
* We don't want to (un)plug or reuse any memory when in kdump. The
* memory is still accessible (but not exposed to Linux).
*/
if (vm->in_kdump)
return virtio_mem_init_kdump(vm);
return virtio_mem_init_hotplug(vm);
}
static int virtio_mem_create_resource(struct virtio_mem *vm)
@@ -2525,8 +2672,10 @@ static int virtio_mem_create_resource(struct virtio_mem *vm)
if (!name)
return -ENOMEM;
/* Disallow mapping device memory via /dev/mem completely. */
vm->parent_resource = __request_mem_region(vm->addr, vm->region_size,
name, IORESOURCE_SYSTEM_RAM);
name, IORESOURCE_SYSTEM_RAM |
IORESOURCE_EXCLUSIVE);
if (!vm->parent_resource) {
kfree(name);
dev_warn(&vm->vdev->dev, "could not reserve device region\n");
@@ -2571,7 +2720,6 @@ static bool virtio_mem_has_memory_added(struct virtio_mem *vm)
static int virtio_mem_probe(struct virtio_device *vdev)
{
struct virtio_mem *vm;
uint64_t unit_pages;
int rc;
BUILD_BUG_ON(sizeof(struct virtio_mem_req) != 24);
@@ -2590,6 +2738,7 @@ static int virtio_mem_probe(struct virtio_device *vdev)
hrtimer_init(&vm->retry_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
vm->retry_timer.function = virtio_mem_timer_expired;
vm->retry_timer_ms = VIRTIO_MEM_RETRY_TIMER_MIN_MS;
vm->in_kdump = is_kdump_kernel();
/* register the virtqueue */
rc = virtio_mem_init_vq(vm);
@@ -2601,53 +2750,15 @@ static int virtio_mem_probe(struct virtio_device *vdev)
if (rc)
goto out_del_vq;
/* create the parent resource for all memory */
rc = virtio_mem_create_resource(vm);
if (rc)
goto out_del_vq;
/* use a single dynamic memory group to cover the whole memory device */
if (vm->in_sbm)
unit_pages = PHYS_PFN(memory_block_size_bytes());
else
unit_pages = PHYS_PFN(vm->bbm.bb_size);
rc = memory_group_register_dynamic(vm->nid, unit_pages);
if (rc < 0)
goto out_del_resource;
vm->mgid = rc;
/*
* If we still have memory plugged, we have to unplug all memory first.
* Registering our parent resource makes sure that this memory isn't
* actually in use (e.g., trying to reload the driver).
*/
if (vm->plugged_size) {
vm->unplug_all_required = true;
dev_info(&vm->vdev->dev, "unplugging all memory is required\n");
}
/* register callbacks */
vm->memory_notifier.notifier_call = virtio_mem_memory_notifier_cb;
rc = register_memory_notifier(&vm->memory_notifier);
if (rc)
goto out_unreg_group;
rc = register_virtio_mem_device(vm);
if (rc)
goto out_unreg_mem;
virtio_device_ready(vdev);
/* trigger a config update to start processing the requested_size */
atomic_set(&vm->config_changed, 1);
queue_work(system_freezable_wq, &vm->wq);
if (!vm->in_kdump) {
atomic_set(&vm->config_changed, 1);
queue_work(system_freezable_wq, &vm->wq);
}
return 0;
out_unreg_mem:
unregister_memory_notifier(&vm->memory_notifier);
out_unreg_group:
memory_group_unregister(vm->mgid);
out_del_resource:
virtio_mem_delete_resource(vm);
out_del_vq:
vdev->config->del_vqs(vdev);
out_free_vm:
@@ -2657,9 +2768,8 @@ out_free_vm:
return rc;
}
static void virtio_mem_remove(struct virtio_device *vdev)
static void virtio_mem_deinit_hotplug(struct virtio_mem *vm)
{
struct virtio_mem *vm = vdev->priv;
unsigned long mb_id;
int rc;
@@ -2706,7 +2816,8 @@ static void virtio_mem_remove(struct virtio_device *vdev)
* away. Warn at least.
*/
if (virtio_mem_has_memory_added(vm)) {
dev_warn(&vdev->dev, "device still has system memory added\n");
dev_warn(&vm->vdev->dev,
"device still has system memory added\n");
} else {
virtio_mem_delete_resource(vm);
kfree_const(vm->resource_name);
@@ -2720,6 +2831,23 @@ static void virtio_mem_remove(struct virtio_device *vdev)
} else {
vfree(vm->bbm.bb_states);
}
}
static void virtio_mem_deinit_kdump(struct virtio_mem *vm)
{
#ifdef CONFIG_PROC_VMCORE
unregister_vmcore_cb(&vm->vmcore_cb);
#endif /* CONFIG_PROC_VMCORE */
}
static void virtio_mem_remove(struct virtio_device *vdev)
{
struct virtio_mem *vm = vdev->priv;
if (vm->in_kdump)
virtio_mem_deinit_kdump(vm);
else
virtio_mem_deinit_hotplug(vm);
/* reset the device and cleanup the queues */
vdev->config->reset(vdev);
@@ -2733,6 +2861,9 @@ static void virtio_mem_config_changed(struct virtio_device *vdev)
{
struct virtio_mem *vm = vdev->priv;
if (unlikely(vm->in_kdump))
return;
atomic_set(&vm->config_changed, 1);
virtio_mem_retry(vm);
}

View File

@@ -2,6 +2,7 @@
config 9P_FS
tristate "Plan 9 Resource Sharing Support (9P2000)"
depends on INET && NET_9P
select NETFS_SUPPORT
help
If you say Y here, you will get experimental support for
Plan 9 resource sharing via the 9P2000 protocol.

View File

@@ -1,15 +1,7 @@
// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright IBM Corporation, 2010
* Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <linux/module.h>
@@ -123,6 +115,7 @@ static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl)
char *name;
size_t size;
void *buffer;
if (!acl)
return 0;

View File

@@ -1,28 +1,21 @@
/* SPDX-License-Identifier: LGPL-2.1 */
/*
* Copyright IBM Corporation, 2010
* Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef FS_9P_ACL_H
#define FS_9P_ACL_H
#ifdef CONFIG_9P_FS_POSIX_ACL
extern int v9fs_get_acl(struct inode *, struct p9_fid *);
extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type, bool rcu);
extern int v9fs_acl_chmod(struct inode *, struct p9_fid *);
extern int v9fs_set_create_acl(struct inode *, struct p9_fid *,
struct posix_acl *, struct posix_acl *);
extern int v9fs_acl_mode(struct inode *dir, umode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl);
extern void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl);
int v9fs_get_acl(struct inode *inode, struct p9_fid *fid);
struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type,
bool rcu);
int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid);
int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid,
struct posix_acl *dacl, struct posix_acl *acl);
int v9fs_acl_mode(struct inode *dir, umode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl);
void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl);
#else
#define v9fs_iop_get_acl NULL
static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)

View File

@@ -19,8 +19,8 @@
#define CACHETAG_LEN 11
struct fscache_netfs v9fs_cache_netfs = {
.name = "9p",
.version = 0,
.name = "9p",
.version = 0,
};
/*
@@ -199,140 +199,3 @@ void v9fs_cache_inode_reset_cookie(struct inode *inode)
mutex_unlock(&v9inode->fscache_lock);
}
int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
{
struct inode *inode = page->mapping->host;
struct v9fs_inode *v9inode = V9FS_I(inode);
BUG_ON(!v9inode->fscache);
return fscache_maybe_release_page(v9inode->fscache, page, gfp);
}
void __v9fs_fscache_invalidate_page(struct page *page)
{
struct inode *inode = page->mapping->host;
struct v9fs_inode *v9inode = V9FS_I(inode);
BUG_ON(!v9inode->fscache);
if (PageFsCache(page)) {
fscache_wait_on_page_write(v9inode->fscache, page);
BUG_ON(!PageLocked(page));
fscache_uncache_page(v9inode->fscache, page);
}
}
static void v9fs_vfs_readpage_complete(struct page *page, void *data,
int error)
{
if (!error)
SetPageUptodate(page);
unlock_page(page);
}
/*
* __v9fs_readpage_from_fscache - read a page from cache
*
* Returns 0 if the pages are in cache and a BIO is submitted,
* 1 if the pages are not in cache and -error otherwise.
*/
int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
{
int ret;
const struct v9fs_inode *v9inode = V9FS_I(inode);
p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
if (!v9inode->fscache)
return -ENOBUFS;
ret = fscache_read_or_alloc_page(v9inode->fscache,
page,
v9fs_vfs_readpage_complete,
NULL,
GFP_KERNEL);
switch (ret) {
case -ENOBUFS:
case -ENODATA:
p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret);
return 1;
case 0:
p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
return ret;
default:
p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
return ret;
}
}
/*
* __v9fs_readpages_from_fscache - read multiple pages from cache
*
* Returns 0 if the pages are in cache and a BIO is submitted,
* 1 if the pages are not in cache and -error otherwise.
*/
int __v9fs_readpages_from_fscache(struct inode *inode,
struct address_space *mapping,
struct list_head *pages,
unsigned *nr_pages)
{
int ret;
const struct v9fs_inode *v9inode = V9FS_I(inode);
p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages);
if (!v9inode->fscache)
return -ENOBUFS;
ret = fscache_read_or_alloc_pages(v9inode->fscache,
mapping, pages, nr_pages,
v9fs_vfs_readpage_complete,
NULL,
mapping_gfp_mask(mapping));
switch (ret) {
case -ENOBUFS:
case -ENODATA:
p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret);
return 1;
case 0:
BUG_ON(!list_empty(pages));
BUG_ON(*nr_pages != 0);
p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
return ret;
default:
p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
return ret;
}
}
/*
* __v9fs_readpage_to_fscache - write a page to the cache
*
*/
void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
{
int ret;
const struct v9fs_inode *v9inode = V9FS_I(inode);
p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
ret = fscache_write_page(v9inode->fscache, page,
i_size_read(&v9inode->vfs_inode), GFP_KERNEL);
p9_debug(P9_DEBUG_FSC, "ret = %d\n", ret);
if (ret != 0)
v9fs_uncache_page(inode, page);
}
/*
* wait for a page to complete writing to the cache
*/
void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
{
const struct v9fs_inode *v9inode = V9FS_I(inode);
p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
if (PageFsCache(page))
fscache_wait_on_page_write(v9inode->fscache, page);
}

View File

@@ -7,9 +7,10 @@
#ifndef _9P_CACHE_H
#define _9P_CACHE_H
#ifdef CONFIG_9P_FSCACHE
#define FSCACHE_USE_NEW_IO_API
#include <linux/fscache.h>
#include <linux/spinlock.h>
#ifdef CONFIG_9P_FSCACHE
extern struct fscache_netfs v9fs_cache_netfs;
extern const struct fscache_cookie_def v9fs_cache_session_index_def;
@@ -27,64 +28,6 @@ extern void v9fs_cache_inode_reset_cookie(struct inode *inode);
extern int __v9fs_cache_register(void);
extern void __v9fs_cache_unregister(void);
extern int __v9fs_fscache_release_page(struct page *page, gfp_t gfp);
extern void __v9fs_fscache_invalidate_page(struct page *page);
extern int __v9fs_readpage_from_fscache(struct inode *inode,
struct page *page);
extern int __v9fs_readpages_from_fscache(struct inode *inode,
struct address_space *mapping,
struct list_head *pages,
unsigned *nr_pages);
extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page);
extern void __v9fs_fscache_wait_on_page_write(struct inode *inode,
struct page *page);
static inline int v9fs_fscache_release_page(struct page *page,
gfp_t gfp)
{
return __v9fs_fscache_release_page(page, gfp);
}
static inline void v9fs_fscache_invalidate_page(struct page *page)
{
__v9fs_fscache_invalidate_page(page);
}
static inline int v9fs_readpage_from_fscache(struct inode *inode,
struct page *page)
{
return __v9fs_readpage_from_fscache(inode, page);
}
static inline int v9fs_readpages_from_fscache(struct inode *inode,
struct address_space *mapping,
struct list_head *pages,
unsigned *nr_pages)
{
return __v9fs_readpages_from_fscache(inode, mapping, pages,
nr_pages);
}
static inline void v9fs_readpage_to_fscache(struct inode *inode,
struct page *page)
{
if (PageFsCache(page))
__v9fs_readpage_to_fscache(inode, page);
}
static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
{
struct v9fs_inode *v9inode = V9FS_I(inode);
fscache_uncache_page(v9inode->fscache, page);
BUG_ON(PageFsCache(page));
}
static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
struct page *page)
{
return __v9fs_fscache_wait_on_page_write(inode, page);
}
#else /* CONFIG_9P_FSCACHE */
static inline void v9fs_cache_inode_get_cookie(struct inode *inode)
@@ -99,39 +42,5 @@ static inline void v9fs_cache_inode_set_cookie(struct inode *inode, struct file
{
}
static inline int v9fs_fscache_release_page(struct page *page,
gfp_t gfp) {
return 1;
}
static inline void v9fs_fscache_invalidate_page(struct page *page) {}
static inline int v9fs_readpage_from_fscache(struct inode *inode,
struct page *page)
{
return -ENOBUFS;
}
static inline int v9fs_readpages_from_fscache(struct inode *inode,
struct address_space *mapping,
struct list_head *pages,
unsigned *nr_pages)
{
return -ENOBUFS;
}
static inline void v9fs_readpage_to_fscache(struct inode *inode,
struct page *page)
{}
static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
{}
static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
struct page *page)
{
return;
}
#endif /* CONFIG_9P_FSCACHE */
#endif /* _9P_CACHE_H */

View File

@@ -103,6 +103,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
/* we'll recheck under lock if there's anything to look in */
if (!ret && dentry->d_fsdata) {
struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata;
spin_lock(&dentry->d_lock);
hlist_for_each_entry(fid, h, dlist) {
if (any || uid_eq(fid->uid, uid)) {
@@ -185,7 +186,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
return ERR_PTR(-EPERM);
if (v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses))
uname = NULL;
uname = NULL;
else
uname = v9ses->uname;

View File

@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/fs/9p/v9fs.c
*
* This file contains functions assisting in mapping VFS to 9P2000
*
* Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
@@ -166,7 +164,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
substring_t args[MAX_OPT_ARGS];
char *p;
int option = 0;
char *s, *e;
char *s;
int ret = 0;
/* setup defaults */
@@ -190,8 +188,10 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
while ((p = strsep(&options, ",")) != NULL) {
int token, r;
if (!*p)
continue;
token = match_token(p, tokens, args);
switch (token) {
case Opt_debug:
@@ -321,12 +321,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
v9ses->flags |= V9FS_ACCESS_CLIENT;
} else {
uid_t uid;
v9ses->flags |= V9FS_ACCESS_SINGLE;
uid = simple_strtoul(s, &e, 10);
if (*e != '\0') {
ret = -EINVAL;
pr_info("Unknown access argument %s\n",
s);
r = kstrtouint(s, 10, &uid);
if (r) {
ret = r;
pr_info("Unknown access argument %s: %d\n",
s, r);
kfree(s);
continue;
}
@@ -520,7 +521,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
* mark transport as disconnected and cancel all pending requests.
*/
void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
void v9fs_session_cancel(struct v9fs_session_info *v9ses)
{
p9_debug(P9_DEBUG_ERROR, "cancel session %p\n", v9ses);
p9_client_disconnect(v9ses->clnt);
}
@@ -659,6 +661,7 @@ static void v9fs_destroy_inode_cache(void)
static int v9fs_cache_register(void)
{
int ret;
ret = v9fs_init_inode_cache();
if (ret < 0)
return ret;
@@ -686,6 +689,7 @@ static void v9fs_cache_unregister(void)
static int __init init_v9fs(void)
{
int err;
pr_info("Installing v9fs 9p2000 file system support\n");
/* TODO: Setup list of registered trasnport modules */

View File

@@ -124,15 +124,24 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
return container_of(inode, struct v9fs_inode, vfs_inode);
}
static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *v9inode)
{
#ifdef CONFIG_9P_FSCACHE
return v9inode->fscache;
#else
return NULL;
#endif
}
extern int v9fs_show_options(struct seq_file *m, struct dentry *root);
struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
char *);
struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
const char *dev_name, char *data);
extern void v9fs_session_close(struct v9fs_session_info *v9ses);
extern void v9fs_session_cancel(struct v9fs_session_info *v9ses);
extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags);
unsigned int flags);
extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct user_namespace *mnt_userns,
@@ -158,7 +167,7 @@ extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
{
return (inode->i_sb->s_fs_info);
return inode->i_sb->s_fs_info;
}
static inline struct v9fs_session_info *v9fs_dentry2v9ses(struct dentry *dentry)

Some files were not shown because too many files have changed in this diff Show More