mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
- New Drivers
- Add STMPE ADC Input driver - Add STMicroelectronics STPMIC1 Parent driver - Add STMicroelectronics STPMIC1 OnKey Misc driver - Add STMicroelectronics STPMIC1 Watchdog driver - Add Cirrus Logic Lochnagar Parent driver - Add TQ-Systems TQMX86 Parent driver - New Device Support - Add support for ADC to STMPE - New (or moved) Functionality - Move Lightbar functionality to its own driver; cros_ec_lightbar - Move VBC functionality to its own driver; cros_ec_vbc - Move VBC functionality to its own driver; cros_ec_vbc - Move DebugFS functionality to its own driver; cros_ec_debugfs - Move SYSFS functionality to its own driver; cros_ec_sysfs - Add support for input voltage options; tps65218 - Fix-ups - Use devm_* managed resources; cros_ec - Device Tree documentation; stmpe, aspeed-lpc, lochnagar - Trivial Clean-ups; stmpe - Rip out broken modular code; aat2870-core, adp5520, as3711, db8500-prcmu, htc-i2cpld, max8925-core, rc5t583, sta2x11-mfd, syscon, tps65090, tps65910, tps68470 tps80031, wm831x-spi, wm831x-i2c, wm831x-core, wm8350-i2c, wm8350-core, wm8400-core - Kconfig fixups; INTEL_SOC_PMIC - Improve error path; sm501, sec-core - Use struct_size() helper; sm501 - Constify; at91-usart - Use pointers instead of copying data; at91-usart - Deliver proper return value; cros_ec_dev - Trivial formatting/whitespace; sec-core -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAlyA5j4ACgkQUa+KL4f8 d2EAyw/+N7N77ex5Ryxmyn61SWvgTL221tj+olw6RqC92Vfw6S2ZFP1CsM/E7tZb qCLYkkJSgBLKoOCI5OLiXsvWCPjyLU33nG/oS0SSiMJ1Fp9M0h7uRnOtOio3z31i w9MJAvEY3RN8I1bRGMO6aWUtT0q3AzHNtdl+7BqAkjjeXiUE0lGd5eARRS1zRWSa ki0OzUkJeszPk+6E6N0K+BQZxcL3cBEsR8ZAif903cMEbqsJIv4nmif4b5D63BKH PtOLn+6HVMG4bzqRRytVhcO/z2uj2jlLCHH9wBnyd4b7SoLFuz15yN5DhD4bKLt7 0UMqiBlC2MeaTv3wyKjeNPQtaMY7zJNUpdFly1PHAYR4oy5kbqk2IAv30N/zRfPK zLmWWq7DYdazBxSSGKmpGEW63Dkr/MQY2oj4nUlcank/X0K7LvmXv7kIxp9jJhA5 bE76f77uHneHvq5OTc5CZtaYNqZbE6tO8rqZ2QlfCqa0M8VxbcrYiym0fQFJBdsH eFtaTG162ssZq1npV759c4/2E3zQ3EW+rj89/AWp8ViJULQLyPY2nUYddx+w04Se kSdgYCvMI5byvF+Tuq/CbUWz7kyca3D+EFiYTkzIfrZr+4yiG2VO8wEO1knkEUVo 9X/wnAD5hQJePEM8CyPZrnirndB0W6SAvSmRZlF/OAbuCBz1DkQ= =tUge -----END PGP SIGNATURE----- Merge tag 'mfd-next-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd Pull MFD updates from Lee Jones: "New Drivers: - Add STMPE ADC Input driver - Add STMicroelectronics STPMIC1 Parent driver - Add STMicroelectronics STPMIC1 OnKey Misc driver - Add STMicroelectronics STPMIC1 Watchdog driver - Add Cirrus Logic Lochnagar Parent driver - Add TQ-Systems TQMX86 Parent driver New Device Support: - Add support for ADC to STMPE New (or moved) Functionality: - Move Lightbar functionality to its own driver; cros_ec_lightbar - Move VBC functionality to its own driver; cros_ec_vbc - Move VBC functionality to its own driver; cros_ec_vbc - Move DebugFS functionality to its own driver; cros_ec_debugfs - Move SYSFS functionality to its own driver; cros_ec_sysfs - Add support for input voltage options; tps65218 Fixes: - Use devm_* managed resources; cros_ec - Device Tree documentation; stmpe, aspeed-lpc, lochnagar - Trivial Clean-ups; stmpe - Rip out broken modular code; aat2870-core, adp5520, as3711, db8500-prcmu, htc-i2cpld, max8925-core, rc5t583, sta2x11-mfd, syscon, tps65090, tps65910, tps68470 tps80031, wm831x-spi, wm831x-i2c, wm831x-core, wm8350-i2c, wm8350-core, wm8400-core - Kconfig fixups; INTEL_SOC_PMIC - Improve error path; sm501, sec-core - Use struct_size() helper; sm501 - Constify; at91-usart - Use pointers instead of copying data; at91-usart - Deliver proper return value; cros_ec_dev - Trivial formatting/whitespace; sec-core" * tag 'mfd-next-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (53 commits) mfd: mxs-lradc: Mark expected switch fall-through mfd: sec-core: Cleanup formatting to a consistent style mfd: tqmx86: IO controller with I2C, Wachdog and GPIO mfd: intel-lpss: Move linux/pm.h to the local header mfd: cros_ec_dev: Return number of bytes read with CROS_EC_DEV_IOCRDMEM mfd: tps68470: Drop unused MODULE_DEVICE_TABLE mfd: at91-usart: No need to copy mfd_cell in probe mfd: at91-usart: Constify at91_usart_spi_subdev and at91_usart_serial_subdev mfd: lochnagar: Add support for the Cirrus Logic Lochnagar mfd: lochnagar: Add initial binding documentation dt-bindings: mfd: aspeed-lpc: Make parameter optional mfd: sec-core: Return gracefully instead of BUG() if device cannot match mfd: sm501: Use struct_size() in devm_kzalloc() mfd: sm501: Fix potential NULL pointer dereference mfd: Kconfig: Fix I2C_DESIGNWARE_PLATFORM dependencies mfd: tps65218.c: Add input voltage options mfd: wm8400-core: Make it explicitly non-modular mfd: wm8350-core: Drop unused module infrastructure from non-modular code mfd: wm8350-i2c: Make it explicitly non-modular mfd: wm831x-core: Drop unused module infrastructure from non-modular code ...
This commit is contained in:
commit
cf2e8c544c
32
Documentation/ABI/testing/sysfs-class-chromeos
Normal file
32
Documentation/ABI/testing/sysfs-class-chromeos
Normal file
@ -0,0 +1,32 @@
|
||||
What: /sys/class/chromeos/<ec-device-name>/flashinfo
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
Show the EC flash information.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/kb_wake_angle
|
||||
Date: March 2018
|
||||
KernelVersion: 4.17
|
||||
Description:
|
||||
Control the keyboard wake lid angle. Values are between
|
||||
0 and 360. This file will also show the keyboard wake lid
|
||||
angle by querying the hardware.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/reboot
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
Tell the EC to reboot in various ways. Options are:
|
||||
"cancel": Cancel a pending reboot.
|
||||
"ro": Jump to RO without rebooting.
|
||||
"rw": Jump to RW without rebooting.
|
||||
"cold": Cold reboot.
|
||||
"disable-jump": Disable jump until next reboot.
|
||||
"hibernate": Hibernate the EC.
|
||||
"at-shutdown": Reboot after an AP shutdown.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/version
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
Show the information about the EC software and hardware.
|
@ -0,0 +1,74 @@
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/brightness
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
Writing to this file adjusts the overall brightness of
|
||||
the lightbar, separate from any color intensity. The
|
||||
valid range is 0 (off) to 255 (maximum brightness).
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/interval_msec
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
The lightbar is controlled by an embedded controller (EC),
|
||||
which also manages the keyboard, battery charging, fans,
|
||||
and other system hardware. To prevent unprivileged users
|
||||
from interfering with the other EC functions, the rate at
|
||||
which the lightbar control files can be read or written is
|
||||
limited.
|
||||
|
||||
Reading this file will return the number of milliseconds
|
||||
that must elapse between accessing any of the lightbar
|
||||
functions through this interface. Going faster will simply
|
||||
block until the necessary interval has lapsed. The interval
|
||||
applies uniformly to all accesses of any kind by any user.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/led_rgb
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
This allows you to control each LED segment. If the
|
||||
lightbar is already running one of the automatic
|
||||
sequences, you probably won’t see anything change because
|
||||
your color setting will be almost immediately replaced.
|
||||
To get useful results, you should stop the lightbar
|
||||
sequence first.
|
||||
|
||||
The values written to this file are sets of four integers,
|
||||
indicating LED, RED, GREEN, BLUE. The LED number is 0 to 3
|
||||
to select a single segment, or 4 to set all four segments
|
||||
to the same value at once. The RED, GREEN, and BLUE
|
||||
numbers should be in the range 0 (off) to 255 (maximum).
|
||||
You can update more than one segment at a time by writing
|
||||
more than one set of four integers.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/program
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
This allows you to upload and run custom lightbar sequences.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/sequence
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
The Pixel lightbar has a number of built-in sequences
|
||||
that it displays under various conditions, such as at
|
||||
power on, shut down, or while running. Reading from this
|
||||
file displays the current sequence that the lightbar is
|
||||
displaying. Writing to this file allows you to change the
|
||||
sequence.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/userspace_control
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
This allows you to take the control of the lightbar. This
|
||||
prevents the kernel from going through its normal
|
||||
sequences.
|
||||
|
||||
What: /sys/class/chromeos/<ec-device-name>/lightbar/version
|
||||
Date: August 2015
|
||||
KernelVersion: 4.2
|
||||
Description:
|
||||
Show the information about the lightbar version.
|
@ -0,0 +1,6 @@
|
||||
What: /sys/class/chromeos/<ec-device-name>/vbc/vboot_context
|
||||
Date: October 2015
|
||||
KernelVersion: 4.4
|
||||
Description:
|
||||
Read/write the verified boot context data included on a
|
||||
small nvram space on some EC implementations.
|
21
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Normal file
21
Documentation/devicetree/bindings/iio/adc/stmpe-adc.txt
Normal file
@ -0,0 +1,21 @@
|
||||
STMPE ADC driver
|
||||
----------------
|
||||
|
||||
Required properties:
|
||||
- compatible: "st,stmpe-adc"
|
||||
|
||||
Optional properties:
|
||||
Note that the ADC is shared with the STMPE touchscreen. ADC related settings
|
||||
have to be done in the mfd.
|
||||
- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
|
||||
requestable due to different usage (e.g. touch)
|
||||
|
||||
Node name must be stmpe_adc and should be child node of stmpe node to
|
||||
which it belongs.
|
||||
|
||||
Example:
|
||||
|
||||
stmpe_adc {
|
||||
compatible = "st,stmpe-adc";
|
||||
st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
|
||||
};
|
28
Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt
Normal file
28
Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt
Normal file
@ -0,0 +1,28 @@
|
||||
STMicroelectronics STPMIC1 Onkey
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible = "st,stpmic1-onkey";
|
||||
- interrupts: interrupt line to use
|
||||
- interrupt-names = "onkey-falling", "onkey-rising"
|
||||
onkey-falling: happens when onkey is pressed; IT_PONKEY_F of pmic
|
||||
onkey-rising: happens when onkey is released; IT_PONKEY_R of pmic
|
||||
|
||||
Optional properties:
|
||||
|
||||
- st,onkey-clear-cc-flag: onkey is able power on after an
|
||||
over-current shutdown event.
|
||||
- st,onkey-pu-inactive: onkey pull up is not active
|
||||
- power-off-time-sec: Duration in seconds which the key should be kept
|
||||
pressed for device to power off automatically (from 1 to 16 seconds).
|
||||
see See Documentation/devicetree/bindings/input/keys.txt
|
||||
|
||||
Example:
|
||||
|
||||
onkey {
|
||||
compatible = "st,stpmic1-onkey";
|
||||
interrupt-parent = <&pmic>;
|
||||
interrupts = <IT_PONKEY_F 0>,<IT_PONKEY_R 1>;
|
||||
interrupt-names = "onkey-falling", "onkey-rising";
|
||||
power-off-time-sec = <10>;
|
||||
};
|
@ -5,39 +5,105 @@ Required properties:
|
||||
- compatible: "st,stmpe-ts"
|
||||
|
||||
Optional properties:
|
||||
- st,sample-time: ADC converstion time in number of clock. (0 -> 36 clocks, 1 ->
|
||||
44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks, 5 -> 96 clocks, 6
|
||||
-> 144 clocks), recommended is 4.
|
||||
- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
|
||||
- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
|
||||
reference)
|
||||
- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
|
||||
- st,ave-ctrl: Sample average control (0 -> 1 sample, 1 -> 2 samples, 2 -> 4
|
||||
samples, 3 -> 8 samples)
|
||||
- st,touch-det-delay: Touch detect interrupt delay (0 -> 10 us, 1 -> 50 us, 2 ->
|
||||
100 us, 3 -> 500 us, 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) recommended
|
||||
is 3
|
||||
- st,settling: Panel driver settling time (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3
|
||||
-> 1 ms, 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) recommended is 2
|
||||
- st,fraction-z: Length of the fractional part in z (fraction-z ([0..7]) = Count of
|
||||
the fractional part) recommended is 7
|
||||
- st,i-drive: current limit value of the touchscreen drivers (0 -> 20 mA typical 35
|
||||
mA max, 1 -> 50 mA typical 80 mA max)
|
||||
- st,ave-ctrl : Sample average control
|
||||
0 -> 1 sample
|
||||
1 -> 2 samples
|
||||
2 -> 4 samples
|
||||
3 -> 8 samples
|
||||
- st,touch-det-delay : Touch detect interrupt delay (recommended is 3)
|
||||
0 -> 10 us
|
||||
1 -> 50 us
|
||||
2 -> 100 us
|
||||
3 -> 500 us
|
||||
4 -> 1 ms
|
||||
5 -> 5 ms
|
||||
6 -> 10 ms
|
||||
7 -> 50 ms
|
||||
- st,settling : Panel driver settling time (recommended is 2)
|
||||
0 -> 10 us
|
||||
1 -> 100 us
|
||||
2 -> 500 us
|
||||
3 -> 1 ms
|
||||
4 -> 5 ms
|
||||
5 -> 10 ms
|
||||
6 -> 50 ms
|
||||
7 -> 100 ms
|
||||
- st,fraction-z : Length of the fractional part in z (recommended is 7)
|
||||
(fraction-z ([0..7]) = Count of the fractional part)
|
||||
- st,i-drive : current limit value of the touchscreen drivers
|
||||
0 -> 20 mA (typical 35mA max)
|
||||
1 -> 50 mA (typical 80 mA max)
|
||||
|
||||
Optional properties common with MFD (deprecated):
|
||||
- st,sample-time : ADC conversion time in number of clock.
|
||||
0 -> 36 clocks
|
||||
1 -> 44 clocks
|
||||
2 -> 56 clocks
|
||||
3 -> 64 clocks
|
||||
4 -> 80 clocks (recommended)
|
||||
5 -> 96 clocks
|
||||
6 -> 124 clocks
|
||||
- st,mod-12b : ADC Bit mode
|
||||
0 -> 10bit ADC
|
||||
1 -> 12bit ADC
|
||||
- st,ref-sel : ADC reference source
|
||||
0 -> internal
|
||||
1 -> external
|
||||
- st,adc-freq : ADC Clock speed
|
||||
0 -> 1.625 MHz
|
||||
1 -> 3.25 MHz
|
||||
2 || 3 -> 6.5 MHz
|
||||
|
||||
Node name must be stmpe_touchscreen and should be child node of stmpe node to
|
||||
which it belongs.
|
||||
|
||||
Note that common ADC settings of stmpe_touchscreen (child) will take precedence
|
||||
over the settings done in MFD.
|
||||
|
||||
Example:
|
||||
|
||||
stmpe811@41 {
|
||||
compatible = "st,stmpe811";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_touch_int>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x41>;
|
||||
interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-parent = <&gpio4>;
|
||||
interrupt-controller;
|
||||
id = <0>;
|
||||
blocks = <0x5>;
|
||||
irq-trigger = <0x1>;
|
||||
/* Common ADC settings */
|
||||
/* 3.25 MHz ADC clock speed */
|
||||
st,adc-freq = <1>;
|
||||
/* 12-bit ADC */
|
||||
st,mod-12b = <1>;
|
||||
/* internal ADC reference */
|
||||
st,ref-sel = <0>;
|
||||
/* ADC converstion time: 80 clocks */
|
||||
st,sample-time = <4>;
|
||||
|
||||
stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
st,sample-time = <4>;
|
||||
st,mod-12b = <1>;
|
||||
st,ref-sel = <0>;
|
||||
st,adc-freq = <1>;
|
||||
st,ave-ctrl = <1>;
|
||||
st,touch-det-delay = <2>;
|
||||
st,settling = <2>;
|
||||
reg = <0>;
|
||||
/* 8 sample average control */
|
||||
st,ave-ctrl = <3>;
|
||||
/* 5 ms touch detect interrupt delay */
|
||||
st,touch-det-delay = <5>;
|
||||
/* 1 ms panel driver settling time */
|
||||
st,settling = <3>;
|
||||
/* 7 length fractional part in z */
|
||||
st,fraction-z = <7>;
|
||||
/*
|
||||
* 50 mA typical 80 mA max touchscreen drivers
|
||||
* current limit value
|
||||
*/
|
||||
st,i-drive = <1>;
|
||||
};
|
||||
stmpe_adc {
|
||||
compatible = "st,stmpe-adc";
|
||||
st,norequest-mask = <0x0F>;
|
||||
};
|
||||
};
|
||||
|
@ -135,6 +135,8 @@ Required properties:
|
||||
- clocks: contains a phandle to the syscon node describing the clocks.
|
||||
There should then be one cell representing the clock to use
|
||||
|
||||
Optional properties:
|
||||
|
||||
- memory-region: A phandle to a reserved_memory region to be used for the LPC
|
||||
to AHB mapping
|
||||
|
||||
|
68
Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
Normal file
68
Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
Normal file
@ -0,0 +1,68 @@
|
||||
Cirrus Logic Lochnagar Audio Development Board
|
||||
|
||||
Lochnagar is an evaluation and development board for Cirrus Logic
|
||||
Smart CODEC and Amp devices. It allows the connection of most Cirrus
|
||||
Logic devices on mini-cards, as well as allowing connection of
|
||||
various application processor systems to provide a full evaluation
|
||||
platform. Audio system topology, clocking and power can all be
|
||||
controlled through the Lochnagar, allowing the device under test
|
||||
to be used in a variety of possible use cases.
|
||||
|
||||
Also see these documents for generic binding information:
|
||||
[1] GPIO : ../gpio/gpio.txt
|
||||
|
||||
And these for relevant defines:
|
||||
[2] include/dt-bindings/pinctrl/lochnagar.h
|
||||
[3] include/dt-bindings/clock/lochnagar.h
|
||||
|
||||
And these documents for the required sub-node binding details:
|
||||
[4] Clock: ../clock/cirrus,lochnagar.txt
|
||||
[5] Pinctrl: ../pinctrl/cirrus,lochnagar.txt
|
||||
[6] Regulator: ../regulator/cirrus,lochnagar.txt
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of the following strings:
|
||||
"cirrus,lochnagar1"
|
||||
"cirrus,lochnagar2"
|
||||
|
||||
- reg : I2C slave address
|
||||
|
||||
- reset-gpios : Reset line to the Lochnagar, see [1].
|
||||
|
||||
Required sub-nodes:
|
||||
|
||||
- lochnagar-clk : Binding for the clocking components, see [4].
|
||||
|
||||
- lochnagar-pinctrl : Binding for the pin control components, see [5].
|
||||
|
||||
Optional sub-nodes:
|
||||
|
||||
- Bindings for the regulator components, see [6]. Only available on
|
||||
Lochnagar 2.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- present-gpios : Host present line, indicating the presence of a
|
||||
host system, see [1]. This can be omitted if the present line is
|
||||
tied in hardware.
|
||||
|
||||
Example:
|
||||
|
||||
lochnagar: lochnagar@22 {
|
||||
compatible = "cirrus,lochnagar2";
|
||||
reg = <0x22>;
|
||||
|
||||
reset-gpios = <&gpio0 55 0>;
|
||||
present-gpios = <&gpio0 60 0>;
|
||||
|
||||
lochnagar-clk {
|
||||
compatible = "cirrus,lochnagar2-clk";
|
||||
...
|
||||
};
|
||||
|
||||
lochnagar-pinctrl {
|
||||
compatible = "cirrus,lochnagar-pinctrl";
|
||||
...
|
||||
};
|
||||
};
|
61
Documentation/devicetree/bindings/mfd/st,stpmic1.txt
Normal file
61
Documentation/devicetree/bindings/mfd/st,stpmic1.txt
Normal file
@ -0,0 +1,61 @@
|
||||
* STMicroelectronics STPMIC1 Power Management IC
|
||||
|
||||
Required properties:
|
||||
- compatible: : "st,stpmic1"
|
||||
- reg: : The I2C slave address for the STPMIC1 chip.
|
||||
- interrupts: : The interrupt line the device is connected to.
|
||||
- #interrupt-cells: : Should be 1.
|
||||
- interrupt-controller: : Marks the device node as an interrupt controller.
|
||||
Interrupt numbers are defined at
|
||||
dt-bindings/mfd/st,stpmic1.h.
|
||||
|
||||
STPMIC1 consists in a varied group of sub-devices.
|
||||
Each sub-device binding is be described in own documentation file.
|
||||
|
||||
Device Description
|
||||
------ ------------
|
||||
st,stpmic1-onkey : Power on key, see ../input/st,stpmic1-onkey.txt
|
||||
st,stpmic1-regulators : Regulators, see ../regulator/st,stpmic1-regulator.txt
|
||||
st,stpmic1-wdt : Watchdog, see ../watchdog/st,stpmic1-wdt.txt
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/mfd/st,stpmic1.h>
|
||||
|
||||
pmic: pmic@33 {
|
||||
compatible = "st,stpmic1";
|
||||
reg = <0x33>;
|
||||
interrupt-parent = <&gpioa>;
|
||||
interrupts = <0 2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
onkey {
|
||||
compatible = "st,stpmic1-onkey";
|
||||
interrupts = <IT_PONKEY_F 0>,<IT_PONKEY_R 1>;
|
||||
interrupt-names = "onkey-falling", "onkey-rising";
|
||||
power-off-time-sec = <10>;
|
||||
};
|
||||
|
||||
watchdog {
|
||||
compatible = "st,stpmic1-wdt";
|
||||
};
|
||||
|
||||
regulators {
|
||||
compatible = "st,stpmic1-regulators";
|
||||
|
||||
vdd_core: buck1 {
|
||||
regulator-name = "vdd_core";
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <700000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
};
|
||||
vdd: buck3 {
|
||||
regulator-name = "vdd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-pull-down;
|
||||
};
|
||||
};
|
@ -4,15 +4,29 @@ STMPE is an MFD device which may expose the following inbuilt devices: gpio,
|
||||
keypad, touchscreen, adc, pwm, rotator.
|
||||
|
||||
Required properties:
|
||||
- compatible : "st,stmpe[610|801|811|1600|1601|2401|2403]"
|
||||
- reg : I2C/SPI address of the device
|
||||
- compatible : "st,stmpe[610|801|811|1600|1601|2401|2403]"
|
||||
- reg : I2C/SPI address of the device
|
||||
|
||||
Optional properties:
|
||||
- interrupts : The interrupt outputs from the controller
|
||||
- interrupt-controller : Marks the device node as an interrupt controller
|
||||
- wakeup-source : Marks the input device as wakable
|
||||
- st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024
|
||||
- irq-gpio : If present, which GPIO to use for event IRQ
|
||||
- interrupts : The interrupt outputs from the controller
|
||||
- interrupt-controller : Marks the device node as an interrupt controller
|
||||
- wakeup-source : Marks the input device as wakable
|
||||
- st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024
|
||||
- irq-gpio : If present, which GPIO to use for event IRQ
|
||||
|
||||
Optional properties for devices with touch and ADC (STMPE811|STMPE610):
|
||||
- st,sample-time : ADC conversion time in number of clock.
|
||||
0 -> 36 clocks 4 -> 80 clocks (recommended)
|
||||
1 -> 44 clocks 5 -> 96 clocks
|
||||
2 -> 56 clocks 6 -> 124 clocks
|
||||
3 -> 64 clocks
|
||||
- st,mod-12b : ADC Bit mode
|
||||
0 -> 10bit ADC 1 -> 12bit ADC
|
||||
- st,ref-sel : ADC reference source
|
||||
0 -> internal 1 -> external
|
||||
- st,adc-freq : ADC Clock speed
|
||||
0 -> 1.625 MHz 2 || 3 -> 6.5 MHz
|
||||
1 -> 3.25 MHz
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
STMicroelectronics STPMIC1 Watchdog
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "st,stpmic1-wdt"
|
||||
|
||||
Example:
|
||||
|
||||
watchdog {
|
||||
compatible = "st,stpmic1-wdt";
|
||||
};
|
17
MAINTAINERS
17
MAINTAINERS
@ -3777,6 +3777,23 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/cirrus/ep93xx_eth.c
|
||||
|
||||
CIRRUS LOGIC LOCHNAGAR DRIVER
|
||||
M: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
M: Richard Fitzgerald <rf@opensource.cirrus.com>
|
||||
L: patches@opensource.cirrus.com
|
||||
S: Supported
|
||||
F: drivers/clk/clk-lochnagar.c
|
||||
F: drivers/mfd/lochnagar-i2c.c
|
||||
F: drivers/pinctrl/cirrus/pinctrl-lochnagar.c
|
||||
F: drivers/regulator/lochnagar-regulator.c
|
||||
F: include/dt-bindings/clk/lochnagar.h
|
||||
F: include/dt-bindings/pinctrl/lochnagar.h
|
||||
F: include/linux/mfd/lochnagar*
|
||||
F: Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
|
||||
F: Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
|
||||
F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
|
||||
F: Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
|
||||
|
||||
CISCO FCOE HBA DRIVER
|
||||
M: Satish Kharat <satishkh@cisco.com>
|
||||
M: Sesidhar Baddela <sebaddel@cisco.com>
|
||||
|
@ -817,6 +817,13 @@ config STM32_DFSDM_ADC
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called stm32-dfsdm-adc.
|
||||
|
||||
config STMPE_ADC
|
||||
tristate "STMicroelectronics STMPE ADC driver"
|
||||
depends on OF && MFD_STMPE
|
||||
help
|
||||
Say yes here to build support for ST Microelectronics STMPE
|
||||
built-in ADC block (stmpe811).
|
||||
|
||||
config STX104
|
||||
tristate "Apex Embedded Systems STX104 driver"
|
||||
depends on PC104 && X86
|
||||
|
@ -77,6 +77,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
|
||||
obj-$(CONFIG_STM32_ADC) += stm32-adc.o
|
||||
obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o
|
||||
obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o
|
||||
obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o
|
||||
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
|
||||
obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
|
||||
obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
|
||||
|
363
drivers/iio/adc/stmpe-adc.c
Normal file
363
drivers/iio/adc/stmpe-adc.c
Normal file
@ -0,0 +1,363 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* STMicroelectronics STMPE811 IIO ADC Driver
|
||||
*
|
||||
* 4 channel, 10/12-bit ADC
|
||||
*
|
||||
* Copyright (C) 2013-2018 Toradex AG <stefan.agner@toradex.com>
|
||||
*/
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/stmpe.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#define STMPE_REG_INT_STA 0x0B
|
||||
#define STMPE_REG_ADC_INT_EN 0x0E
|
||||
#define STMPE_REG_ADC_INT_STA 0x0F
|
||||
|
||||
#define STMPE_REG_ADC_CTRL1 0x20
|
||||
#define STMPE_REG_ADC_CTRL2 0x21
|
||||
#define STMPE_REG_ADC_CAPT 0x22
|
||||
#define STMPE_REG_ADC_DATA_CH(channel) (0x30 + 2 * (channel))
|
||||
|
||||
#define STMPE_REG_TEMP_CTRL 0x60
|
||||
#define STMPE_TEMP_CTRL_ENABLE BIT(0)
|
||||
#define STMPE_TEMP_CTRL_ACQ BIT(1)
|
||||
#define STMPE_TEMP_CTRL_THRES_EN BIT(3)
|
||||
#define STMPE_START_ONE_TEMP_CONV (STMPE_TEMP_CTRL_ENABLE | \
|
||||
STMPE_TEMP_CTRL_ACQ | \
|
||||
STMPE_TEMP_CTRL_THRES_EN)
|
||||
#define STMPE_REG_TEMP_DATA 0x61
|
||||
#define STMPE_REG_TEMP_TH 0x63
|
||||
#define STMPE_ADC_LAST_NR 7
|
||||
#define STMPE_TEMP_CHANNEL (STMPE_ADC_LAST_NR + 1)
|
||||
|
||||
#define STMPE_ADC_CH(channel) ((1 << (channel)) & 0xff)
|
||||
|
||||
#define STMPE_ADC_TIMEOUT msecs_to_jiffies(1000)
|
||||
|
||||
struct stmpe_adc {
|
||||
struct stmpe *stmpe;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct mutex lock;
|
||||
|
||||
/* We are allocating plus one for the temperature channel */
|
||||
struct iio_chan_spec stmpe_adc_iio_channels[STMPE_ADC_LAST_NR + 2];
|
||||
|
||||
struct completion completion;
|
||||
|
||||
u8 channel;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
static int stmpe_read_voltage(struct stmpe_adc *info,
|
||||
struct iio_chan_spec const *chan, int *val)
|
||||
{
|
||||
long ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
info->channel = (u8)chan->channel;
|
||||
|
||||
if (info->channel > STMPE_ADC_LAST_NR) {
|
||||
mutex_unlock(&info->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
|
||||
STMPE_ADC_CH(info->channel));
|
||||
|
||||
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
|
||||
STMPE_ADC_CH(info->channel));
|
||||
|
||||
*val = info->value;
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout
|
||||
(&info->completion, STMPE_ADC_TIMEOUT);
|
||||
|
||||
if (ret <= 0) {
|
||||
mutex_unlock(&info->lock);
|
||||
if (ret == 0)
|
||||
return -ETIMEDOUT;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = info->value;
|
||||
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmpe_read_temp(struct stmpe_adc *info,
|
||||
struct iio_chan_spec const *chan, int *val)
|
||||
{
|
||||
long ret;
|
||||
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
info->channel = (u8)chan->channel;
|
||||
|
||||
if (info->channel != STMPE_TEMP_CHANNEL) {
|
||||
mutex_unlock(&info->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
|
||||
STMPE_START_ONE_TEMP_CONV);
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout
|
||||
(&info->completion, STMPE_ADC_TIMEOUT);
|
||||
|
||||
if (ret <= 0) {
|
||||
mutex_unlock(&info->lock);
|
||||
if (ret == 0)
|
||||
return -ETIMEDOUT;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* absolute temp = +V3.3 * value /7.51 [K]
|
||||
* scale to [milli °C]
|
||||
*/
|
||||
*val = ((449960l * info->value) / 1024l) - 273150;
|
||||
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmpe_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long mask)
|
||||
{
|
||||
struct stmpe_adc *info = iio_priv(indio_dev);
|
||||
long ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
case IIO_CHAN_INFO_PROCESSED:
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_VOLTAGE:
|
||||
ret = stmpe_read_voltage(info, chan, val);
|
||||
break;
|
||||
|
||||
case IIO_TEMP:
|
||||
ret = stmpe_read_temp(info, chan, val);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 3300;
|
||||
*val2 = info->stmpe->mod_12b ? 12 : 10;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct stmpe_adc *info = (struct stmpe_adc *)dev_id;
|
||||
u16 data;
|
||||
|
||||
if (info->channel > STMPE_TEMP_CHANNEL)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (info->channel <= STMPE_ADC_LAST_NR) {
|
||||
int int_sta;
|
||||
|
||||
int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
|
||||
|
||||
/* Is the interrupt relevant */
|
||||
if (!(int_sta & STMPE_ADC_CH(info->channel)))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Read value */
|
||||
stmpe_block_read(info->stmpe,
|
||||
STMPE_REG_ADC_DATA_CH(info->channel), 2, (u8 *) &data);
|
||||
|
||||
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
|
||||
} else if (info->channel == STMPE_TEMP_CHANNEL) {
|
||||
/* Read value */
|
||||
stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2,
|
||||
(u8 *) &data);
|
||||
}
|
||||
|
||||
info->value = (u32) be16_to_cpu(data);
|
||||
complete(&info->completion);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct iio_info stmpe_adc_iio_info = {
|
||||
.read_raw = &stmpe_read_raw,
|
||||
};
|
||||
|
||||
static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan)
|
||||
{
|
||||
ics->type = IIO_VOLTAGE;
|
||||
ics->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
||||
ics->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
|
||||
ics->indexed = 1;
|
||||
ics->channel = chan;
|
||||
}
|
||||
|
||||
static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan)
|
||||
{
|
||||
ics->type = IIO_TEMP;
|
||||
ics->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
|
||||
ics->indexed = 1;
|
||||
ics->channel = chan;
|
||||
}
|
||||
|
||||
static int stmpe_adc_init_hw(struct stmpe_adc *adc)
|
||||
{
|
||||
int ret;
|
||||
struct stmpe *stmpe = adc->stmpe;
|
||||
|
||||
ret = stmpe_enable(stmpe, STMPE_BLOCK_ADC);
|
||||
if (ret) {
|
||||
dev_err(stmpe->dev, "Could not enable clock for ADC\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stmpe811_adc_common_init(stmpe);
|
||||
if (ret) {
|
||||
stmpe_disable(stmpe, STMPE_BLOCK_ADC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* use temp irq for each conversion completion */
|
||||
stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0);
|
||||
stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmpe_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct stmpe_adc *info;
|
||||
struct device_node *np;
|
||||
u32 norequest_mask = 0;
|
||||
int irq_temp, irq_adc;
|
||||
int num_chan = 0;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
irq_adc = platform_get_irq_byname(pdev, "STMPE_ADC");
|
||||
if (irq_adc < 0)
|
||||
return irq_adc;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc));
|
||||
if (!indio_dev) {
|
||||
dev_err(&pdev->dev, "failed allocating iio device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info = iio_priv(indio_dev);
|
||||
mutex_init(&info->lock);
|
||||
|
||||
init_completion(&info->completion);
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq_adc, NULL,
|
||||
stmpe_adc_isr, IRQF_ONESHOT,
|
||||
"stmpe-adc", info);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
|
||||
irq_adc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
irq_temp = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS");
|
||||
if (irq_temp >= 0) {
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq_temp, NULL,
|
||||
stmpe_adc_isr, IRQF_ONESHOT,
|
||||
"stmpe-adc", info);
|
||||
if (ret < 0)
|
||||
dev_warn(&pdev->dev, "failed requesting irq for"
|
||||
" temp sensor, irq = %d\n", irq_temp);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
indio_dev->name = dev_name(&pdev->dev);
|
||||
indio_dev->dev.parent = &pdev->dev;
|
||||
indio_dev->info = &stmpe_adc_iio_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
info->stmpe = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
np = pdev->dev.of_node;
|
||||
|
||||
if (!np)
|
||||
dev_err(&pdev->dev, "no device tree node found\n");
|
||||
|
||||
of_property_read_u32(np, "st,norequest-mask", &norequest_mask);
|
||||
|
||||
for_each_clear_bit(i, (unsigned long *) &norequest_mask,
|
||||
(STMPE_ADC_LAST_NR + 1)) {
|
||||
stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i);
|
||||
num_chan++;
|
||||
}
|
||||
stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i);
|
||||
num_chan++;
|
||||
indio_dev->channels = info->stmpe_adc_iio_channels;
|
||||
indio_dev->num_channels = num_chan;
|
||||
|
||||
ret = stmpe_adc_init_hw(info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(&pdev->dev, indio_dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused stmpe_adc_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct stmpe_adc *info = iio_priv(indio_dev);
|
||||
|
||||
stmpe_adc_init_hw(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume);
|
||||
|
||||
static struct platform_driver stmpe_adc_driver = {
|
||||
.probe = stmpe_adc_probe,
|
||||
.driver = {
|
||||
.name = "stmpe-adc",
|
||||
.pm = &stmpe_adc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(stmpe_adc_driver);
|
||||
|
||||
MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>");
|
||||
MODULE_DESCRIPTION("STMPEXXX ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:stmpe-adc");
|
@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA
|
||||
To compile this driver as a module, choose M here. The module will
|
||||
be called sc27xx_vibra.
|
||||
|
||||
config INPUT_STPMIC1_ONKEY
|
||||
tristate "STPMIC1 PMIC Onkey support"
|
||||
depends on MFD_STPMIC1
|
||||
help
|
||||
Say Y to enable support of onkey embedded into STPMIC1 PMIC. onkey
|
||||
can be used to wakeup from low power modes and force a shut-down on
|
||||
long press.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stpmic1_onkey.
|
||||
|
||||
endif
|
||||
|
@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
|
||||
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
|
||||
obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
|
||||
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
|
||||
obj-$(CONFIG_INPUT_STPMIC1_ONKEY) += stpmic1_onkey.o
|
||||
obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
|
||||
@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
|
||||
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
|
||||
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
|
||||
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
|
||||
|
||||
|
198
drivers/input/misc/stpmic1_onkey.c
Normal file
198
drivers/input/misc/stpmic1_onkey.c
Normal file
@ -0,0 +1,198 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) STMicroelectronics 2018
|
||||
// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/stpmic1.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/**
|
||||
* struct stpmic1_onkey - OnKey data
|
||||
* @input_dev: pointer to input device
|
||||
* @irq_falling: irq that we are hooked on to
|
||||
* @irq_rising: irq that we are hooked on to
|
||||
*/
|
||||
struct stpmic1_onkey {
|
||||
struct input_dev *input_dev;
|
||||
int irq_falling;
|
||||
int irq_rising;
|
||||
};
|
||||
|
||||
static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
|
||||
{
|
||||
struct stpmic1_onkey *onkey = ponkey;
|
||||
struct input_dev *input_dev = onkey->input_dev;
|
||||
|
||||
input_report_key(input_dev, KEY_POWER, 1);
|
||||
pm_wakeup_event(input_dev->dev.parent, 0);
|
||||
input_sync(input_dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
|
||||
{
|
||||
struct stpmic1_onkey *onkey = ponkey;
|
||||
struct input_dev *input_dev = onkey->input_dev;
|
||||
|
||||
input_report_key(input_dev, KEY_POWER, 0);
|
||||
pm_wakeup_event(input_dev->dev.parent, 0);
|
||||
input_sync(input_dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int stpmic1_onkey_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct stpmic1 *pmic = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct input_dev *input_dev;
|
||||
struct stpmic1_onkey *onkey;
|
||||
unsigned int val, reg = 0;
|
||||
int error;
|
||||
|
||||
onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
|
||||
if (!onkey)
|
||||
return -ENOMEM;
|
||||
|
||||
onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
|
||||
if (onkey->irq_falling < 0) {
|
||||
dev_err(dev, "failed: request IRQ onkey-falling %d\n",
|
||||
onkey->irq_falling);
|
||||
return onkey->irq_falling;
|
||||
}
|
||||
|
||||
onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
|
||||
if (onkey->irq_rising < 0) {
|
||||
dev_err(dev, "failed: request IRQ onkey-rising %d\n",
|
||||
onkey->irq_rising);
|
||||
return onkey->irq_rising;
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(dev, "power-off-time-sec", &val)) {
|
||||
if (val > 0 && val <= 16) {
|
||||
dev_dbg(dev, "power-off-time=%d seconds\n", val);
|
||||
reg |= PONKEY_PWR_OFF;
|
||||
reg |= ((16 - val) & PONKEY_TURNOFF_TIMER_MASK);
|
||||
} else {
|
||||
dev_err(dev, "power-off-time-sec out of range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (device_property_present(dev, "st,onkey-clear-cc-flag"))
|
||||
reg |= PONKEY_CC_FLAG_CLEAR;
|
||||
|
||||
error = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR,
|
||||
PONKEY_TURNOFF_MASK, reg);
|
||||
if (error) {
|
||||
dev_err(dev, "PKEY_TURNOFF_CR write failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (device_property_present(dev, "st,onkey-pu-inactive")) {
|
||||
error = regmap_update_bits(pmic->regmap, PADS_PULL_CR,
|
||||
PONKEY_PU_INACTIVE,
|
||||
PONKEY_PU_INACTIVE);
|
||||
if (error) {
|
||||
dev_err(dev, "ONKEY Pads configuration failed: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
input_dev = devm_input_allocate_device(dev);
|
||||
if (!input_dev) {
|
||||
dev_err(dev, "Can't allocate Pwr Onkey Input Device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_dev->name = "pmic_onkey";
|
||||
input_dev->phys = "pmic_onkey/input0";
|
||||
|
||||
input_set_capability(input_dev, EV_KEY, KEY_POWER);
|
||||
|
||||
onkey->input_dev = input_dev;
|
||||
|
||||
/* interrupt is nested in a thread */
|
||||
error = devm_request_threaded_irq(dev, onkey->irq_falling, NULL,
|
||||
onkey_falling_irq, IRQF_ONESHOT,
|
||||
dev_name(dev), onkey);
|
||||
if (error) {
|
||||
dev_err(dev, "Can't get IRQ Onkey Falling: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(dev, onkey->irq_rising, NULL,
|
||||
onkey_rising_irq, IRQF_ONESHOT,
|
||||
dev_name(dev), onkey);
|
||||
if (error) {
|
||||
dev_err(dev, "Can't get IRQ Onkey Rising: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
dev_err(dev, "Can't register power button: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, onkey);
|
||||
device_init_wakeup(dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused stpmic1_onkey_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
enable_irq_wake(onkey->irq_falling);
|
||||
enable_irq_wake(onkey->irq_rising);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused stpmic1_onkey_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
disable_irq_wake(onkey->irq_falling);
|
||||
disable_irq_wake(onkey->irq_rising);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm,
|
||||
stpmic1_onkey_suspend,
|
||||
stpmic1_onkey_resume);
|
||||
|
||||
static const struct of_device_id of_stpmic1_onkey_match[] = {
|
||||
{ .compatible = "st,stpmic1-onkey" },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, of_stpmic1_onkey_match);
|
||||
|
||||
static struct platform_driver stpmic1_onkey_driver = {
|
||||
.probe = stpmic1_onkey_probe,
|
||||
.driver = {
|
||||
.name = "stpmic1_onkey",
|
||||
.of_match_table = of_match_ptr(of_stpmic1_onkey_match),
|
||||
.pm = &stpmic1_onkey_pm,
|
||||
},
|
||||
};
|
||||
module_platform_driver(stpmic1_onkey_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Onkey driver for STPMIC1");
|
||||
MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -30,8 +30,6 @@
|
||||
* with touchscreen controller
|
||||
*/
|
||||
#define STMPE_REG_INT_STA 0x0B
|
||||
#define STMPE_REG_ADC_CTRL1 0x20
|
||||
#define STMPE_REG_ADC_CTRL2 0x21
|
||||
#define STMPE_REG_TSC_CTRL 0x40
|
||||
#define STMPE_REG_TSC_CFG 0x41
|
||||
#define STMPE_REG_FIFO_TH 0x4A
|
||||
@ -49,17 +47,6 @@
|
||||
|
||||
#define STMPE_IRQ_TOUCH_DET 0
|
||||
|
||||
#define SAMPLE_TIME(x) ((x & 0xf) << 4)
|
||||
#define MOD_12B(x) ((x & 0x1) << 3)
|
||||
#define REF_SEL(x) ((x & 0x1) << 1)
|
||||
#define ADC_FREQ(x) (x & 0x3)
|
||||
#define AVE_CTRL(x) ((x & 0x3) << 6)
|
||||
#define DET_DELAY(x) ((x & 0x7) << 3)
|
||||
#define SETTLING(x) (x & 0x7)
|
||||
#define FRACTION_Z(x) (x & 0x7)
|
||||
#define I_DRIVE(x) (x & 0x1)
|
||||
#define OP_MODE(x) ((x & 0x7) << 1)
|
||||
|
||||
#define STMPE_TS_NAME "stmpe-ts"
|
||||
#define XY_MASK 0xfff
|
||||
|
||||
@ -69,15 +56,6 @@
|
||||
* @idev: registered input device
|
||||
* @work: a work item used to scan the device
|
||||
* @dev: a pointer back to the MFD cell struct device*
|
||||
* @sample_time: ADC converstion time in number of clock.
|
||||
* (0 -> 36 clocks, 1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks,
|
||||
* 4 -> 80 clocks, 5 -> 96 clocks, 6 -> 144 clocks),
|
||||
* recommended is 4.
|
||||
* @mod_12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
|
||||
* @ref_sel: ADC reference source
|
||||
* (0 -> internal reference, 1 -> external reference)
|
||||
* @adc_freq: ADC Clock speed
|
||||
* (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
|
||||
* @ave_ctrl: Sample average control
|
||||
* (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples)
|
||||
* @touch_det_delay: Touch detect interrupt delay
|
||||
@ -99,10 +77,6 @@ struct stmpe_touch {
|
||||
struct input_dev *idev;
|
||||
struct delayed_work work;
|
||||
struct device *dev;
|
||||
u8 sample_time;
|
||||
u8 mod_12b;
|
||||
u8 ref_sel;
|
||||
u8 adc_freq;
|
||||
u8 ave_ctrl;
|
||||
u8 touch_det_delay;
|
||||
u8 settling;
|
||||
@ -203,7 +177,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
|
||||
static int stmpe_init_hw(struct stmpe_touch *ts)
|
||||
{
|
||||
int ret;
|
||||
u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
|
||||
u8 tsc_cfg, tsc_cfg_mask;
|
||||
struct stmpe *stmpe = ts->stmpe;
|
||||
struct device *dev = ts->dev;
|
||||
|
||||
@ -213,27 +187,17 @@ static int stmpe_init_hw(struct stmpe_touch *ts)
|
||||
return ret;
|
||||
}
|
||||
|
||||
adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
|
||||
REF_SEL(ts->ref_sel);
|
||||
adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
|
||||
adc_ctrl1_mask, adc_ctrl1);
|
||||
ret = stmpe811_adc_common_init(stmpe);
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not setup ADC\n");
|
||||
stmpe_disable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
|
||||
ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not setup ADC\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
|
||||
SETTLING(ts->settling);
|
||||
tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff);
|
||||
tsc_cfg = STMPE_AVE_CTRL(ts->ave_ctrl) |
|
||||
STMPE_DET_DELAY(ts->touch_det_delay) |
|
||||
STMPE_SETTLING(ts->settling);
|
||||
tsc_cfg_mask = STMPE_AVE_CTRL(0xff) | STMPE_DET_DELAY(0xff) |
|
||||
STMPE_SETTLING(0xff);
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
|
||||
if (ret) {
|
||||
@ -242,14 +206,14 @@ static int stmpe_init_hw(struct stmpe_touch *ts)
|
||||
}
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
|
||||
FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z));
|
||||
STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z));
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not config touch\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
|
||||
I_DRIVE(0xff), I_DRIVE(ts->i_drive));
|
||||
STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive));
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not config touch\n");
|
||||
return ret;
|
||||
@ -263,7 +227,7 @@ static int stmpe_init_hw(struct stmpe_touch *ts)
|
||||
}
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
|
||||
OP_MODE(0xff), OP_MODE(OP_MOD_XYZ));
|
||||
STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ));
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not set mode\n");
|
||||
return ret;
|
||||
@ -303,13 +267,13 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev,
|
||||
|
||||
if (np) {
|
||||
if (!of_property_read_u32(np, "st,sample-time", &val))
|
||||
ts->sample_time = val;
|
||||
ts->stmpe->sample_time = val;
|
||||
if (!of_property_read_u32(np, "st,mod-12b", &val))
|
||||
ts->mod_12b = val;
|
||||
ts->stmpe->mod_12b = val;
|
||||
if (!of_property_read_u32(np, "st,ref-sel", &val))
|
||||
ts->ref_sel = val;
|
||||
ts->stmpe->ref_sel = val;
|
||||
if (!of_property_read_u32(np, "st,adc-freq", &val))
|
||||
ts->adc_freq = val;
|
||||
ts->stmpe->adc_freq = val;
|
||||
if (!of_property_read_u32(np, "st,ave-ctrl", &val))
|
||||
ts->ave_ctrl = val;
|
||||
if (!of_property_read_u32(np, "st,touch-det-delay", &val))
|
||||
|
@ -215,7 +215,6 @@ config MFD_CROS_EC
|
||||
config MFD_CROS_EC_CHARDEV
|
||||
tristate "Chrome OS Embedded Controller userspace device interface"
|
||||
depends on MFD_CROS_EC
|
||||
select CROS_EC_CTL
|
||||
---help---
|
||||
This driver adds support to talk with the ChromeOS EC from userspace.
|
||||
|
||||
@ -519,10 +518,10 @@ config INTEL_SOC_PMIC
|
||||
bool "Support for Crystal Cove PMIC"
|
||||
depends on ACPI && HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK
|
||||
depends on X86 || COMPILE_TEST
|
||||
depends on I2C_DESIGNWARE_PLATFORM=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select I2C_DESIGNWARE_PLATFORM
|
||||
help
|
||||
Select this option to enable support for Crystal Cove PMIC
|
||||
on some Intel SoC systems. The PMIC provides ADC, GPIO,
|
||||
@ -548,10 +547,10 @@ config INTEL_SOC_PMIC_CHTWC
|
||||
bool "Support for Intel Cherry Trail Whiskey Cove PMIC"
|
||||
depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK
|
||||
depends on X86 || COMPILE_TEST
|
||||
depends on I2C_DESIGNWARE_PLATFORM=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select I2C_DESIGNWARE_PLATFORM
|
||||
help
|
||||
Select this option to enable support for the Intel Cherry Trail
|
||||
Whiskey Cove PMIC found on some Intel Cherry Trail systems.
|
||||
@ -1205,7 +1204,7 @@ config MFD_STMPE
|
||||
|
||||
Currently supported devices are:
|
||||
|
||||
STMPE811: GPIO, Touchscreen
|
||||
STMPE811: GPIO, Touchscreen, ADC
|
||||
STMPE1601: GPIO, Keypad
|
||||
STMPE1801: GPIO, Keypad
|
||||
STMPE2401: GPIO, Keypad
|
||||
@ -1218,6 +1217,7 @@ config MFD_STMPE
|
||||
GPIO: stmpe-gpio
|
||||
Keypad: stmpe-keypad
|
||||
Touchscreen: stmpe-ts
|
||||
ADC: stmpe-adc
|
||||
|
||||
menu "STMicroelectronics STMPE Interface Drivers"
|
||||
depends on MFD_STMPE
|
||||
@ -1420,9 +1420,9 @@ config MFD_TPS65217
|
||||
config MFD_TPS68470
|
||||
bool "TI TPS68470 Power Management / LED chips"
|
||||
depends on ACPI && PCI && I2C=y
|
||||
depends on I2C_DESIGNWARE_PLATFORM=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select I2C_DESIGNWARE_PLATFORM
|
||||
help
|
||||
If you say yes here you get support for the TPS68470 series of
|
||||
Power Management / LED chips.
|
||||
@ -1677,6 +1677,14 @@ config MFD_TC6393XB
|
||||
help
|
||||
Support for Toshiba Mobile IO Controller TC6393XB
|
||||
|
||||
config MFD_TQMX86
|
||||
tristate "TQ-Systems IO controller TQMX86"
|
||||
select MFD_CORE
|
||||
help
|
||||
Say yes here to enable support for various functions of the
|
||||
TQ-Systems IO controller and watchdog device, found on their
|
||||
ComExpress CPU modules.
|
||||
|
||||
config MFD_VX855
|
||||
tristate "VIA VX855/VX875 integrated south bridge"
|
||||
depends on PCI
|
||||
@ -1686,6 +1694,14 @@ config MFD_VX855
|
||||
VIA VX855/VX875 south bridge. You will need to enable the vx855_spi
|
||||
and/or vx855_gpio drivers for this to do anything useful.
|
||||
|
||||
config MFD_LOCHNAGAR
|
||||
bool "Cirrus Logic Lochnagar Audio Development Board"
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
depends on I2C=y && OF
|
||||
help
|
||||
Support for Cirrus Logic Lochnagar audio development board.
|
||||
|
||||
config MFD_ARIZONA
|
||||
select REGMAP
|
||||
select REGMAP_IRQ
|
||||
@ -1872,6 +1888,22 @@ config MFD_STM32_TIMERS
|
||||
for PWM and IIO Timer. This driver allow to share the
|
||||
registers between the others drivers.
|
||||
|
||||
config MFD_STPMIC1
|
||||
tristate "Support for STPMIC1 PMIC"
|
||||
depends on (I2C=y && OF)
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select MFD_CORE
|
||||
help
|
||||
Support for ST Microelectronics STPMIC1 PMIC. STPMIC1 has power on
|
||||
key, watchdog and regulator functionalities which are supported via
|
||||
the relevant subsystems. This driver provides core support for the
|
||||
STPMIC1. In order to use the actual functionaltiy of the device other
|
||||
drivers must be enabled.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stpmic1.
|
||||
|
||||
menu "Multimedia Capabilities Port drivers"
|
||||
depends on ARCH_SA1100
|
||||
|
||||
|
@ -37,6 +37,9 @@ obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
|
||||
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
|
||||
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
|
||||
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
|
||||
obj-$(CONFIG_MFD_TQMX86) += tqmx86.o
|
||||
|
||||
obj-$(CONFIG_MFD_LOCHNAGAR) += lochnagar-i2c.o
|
||||
|
||||
obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o
|
||||
obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o
|
||||
@ -234,6 +237,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o
|
||||
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
|
||||
|
||||
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
|
||||
obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o
|
||||
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
|
||||
|
||||
obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
|
||||
|
@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
@ -349,18 +348,10 @@ static void aat2870_init_debugfs(struct aat2870_data *aat2870)
|
||||
"Failed to create debugfs register file\n");
|
||||
}
|
||||
|
||||
static void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
|
||||
{
|
||||
debugfs_remove_recursive(aat2870->dentry_root);
|
||||
}
|
||||
#else
|
||||
static inline void aat2870_init_debugfs(struct aat2870_data *aat2870)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static int aat2870_i2c_probe(struct i2c_client *client,
|
||||
@ -440,20 +431,6 @@ out_disable:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aat2870_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct aat2870_data *aat2870 = i2c_get_clientdata(client);
|
||||
|
||||
aat2870_uninit_debugfs(aat2870);
|
||||
|
||||
mfd_remove_devices(aat2870->dev);
|
||||
aat2870_disable(aat2870);
|
||||
if (aat2870->uninit)
|
||||
aat2870->uninit(aat2870);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int aat2870_i2c_suspend(struct device *dev)
|
||||
{
|
||||
@ -492,15 +469,14 @@ static const struct i2c_device_id aat2870_i2c_id_table[] = {
|
||||
{ "aat2870", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, aat2870_i2c_id_table);
|
||||
|
||||
static struct i2c_driver aat2870_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "aat2870",
|
||||
.pm = &aat2870_pm_ops,
|
||||
.name = "aat2870",
|
||||
.pm = &aat2870_pm_ops,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = aat2870_i2c_probe,
|
||||
.remove = aat2870_i2c_remove,
|
||||
.id_table = aat2870_i2c_id_table,
|
||||
};
|
||||
|
||||
@ -509,13 +485,3 @@ static int __init aat2870_init(void)
|
||||
return i2c_add_driver(&aat2870_i2c_driver);
|
||||
}
|
||||
subsys_initcall(aat2870_init);
|
||||
|
||||
static void __exit aat2870_exit(void)
|
||||
{
|
||||
i2c_del_driver(&aat2870_i2c_driver);
|
||||
}
|
||||
module_exit(aat2870_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
|
||||
|
@ -7,6 +7,8 @@
|
||||
*
|
||||
* Copyright 2009 Analog Devices Inc.
|
||||
*
|
||||
* Author: Michael Hennerich <michael.hennerich@analog.com>
|
||||
*
|
||||
* Derived from da903x:
|
||||
* Copyright (C) 2008 Compulab, Ltd.
|
||||
* Mike Rapoport <mike@compulab.co.il>
|
||||
@ -18,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -304,18 +306,6 @@ out_free_irq:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adp5520_remove(struct i2c_client *client)
|
||||
{
|
||||
struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
|
||||
|
||||
if (chip->irq)
|
||||
free_irq(chip->irq, chip);
|
||||
|
||||
adp5520_remove_subdevs(chip);
|
||||
adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int adp5520_suspend(struct device *dev)
|
||||
{
|
||||
@ -346,20 +336,14 @@ static const struct i2c_device_id adp5520_id[] = {
|
||||
{ "pmic-adp5501", ID_ADP5501 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adp5520_id);
|
||||
|
||||
static struct i2c_driver adp5520_driver = {
|
||||
.driver = {
|
||||
.name = "adp5520",
|
||||
.pm = &adp5520_pm,
|
||||
.name = "adp5520",
|
||||
.pm = &adp5520_pm,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = adp5520_probe,
|
||||
.remove = adp5520_remove,
|
||||
.id_table = adp5520_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(adp5520_driver);
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||
MODULE_DESCRIPTION("ADP5520(01) PMIC-MFD Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
builtin_i2c_driver(adp5520_driver);
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/as3711.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
@ -118,7 +117,6 @@ static const struct of_device_id as3711_of_match[] = {
|
||||
{.compatible = "ams,as3711",},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, as3711_of_match);
|
||||
#endif
|
||||
|
||||
static int as3711_i2c_probe(struct i2c_client *client,
|
||||
@ -202,8 +200,6 @@ static const struct i2c_device_id as3711_i2c_id[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, as3711_i2c_id);
|
||||
|
||||
static struct i2c_driver as3711_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "as3711",
|
||||
@ -219,13 +215,3 @@ static int __init as3711_i2c_init(void)
|
||||
}
|
||||
/* Initialise early */
|
||||
subsys_initcall(as3711_i2c_init);
|
||||
|
||||
static void __exit as3711_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&as3711_i2c_driver);
|
||||
}
|
||||
module_exit(as3711_i2c_exit);
|
||||
|
||||
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
|
||||
MODULE_DESCRIPTION("AS3711 PMIC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -15,29 +15,29 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
static struct mfd_cell at91_usart_spi_subdev = {
|
||||
.name = "at91_usart_spi",
|
||||
.of_compatible = "microchip,at91sam9g45-usart-spi",
|
||||
};
|
||||
static const struct mfd_cell at91_usart_spi_subdev = {
|
||||
.name = "at91_usart_spi",
|
||||
.of_compatible = "microchip,at91sam9g45-usart-spi",
|
||||
};
|
||||
|
||||
static struct mfd_cell at91_usart_serial_subdev = {
|
||||
.name = "atmel_usart_serial",
|
||||
.of_compatible = "atmel,at91rm9200-usart-serial",
|
||||
};
|
||||
static const struct mfd_cell at91_usart_serial_subdev = {
|
||||
.name = "atmel_usart_serial",
|
||||
.of_compatible = "atmel,at91rm9200-usart-serial",
|
||||
};
|
||||
|
||||
static int at91_usart_mode_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mfd_cell cell;
|
||||
const struct mfd_cell *cell;
|
||||
u32 opmode = AT91_USART_MODE_SERIAL;
|
||||
|
||||
device_property_read_u32(&pdev->dev, "atmel,usart-mode", &opmode);
|
||||
|
||||
switch (opmode) {
|
||||
case AT91_USART_MODE_SPI:
|
||||
cell = at91_usart_spi_subdev;
|
||||
cell = &at91_usart_spi_subdev;
|
||||
break;
|
||||
case AT91_USART_MODE_SERIAL:
|
||||
cell = at91_usart_serial_subdev;
|
||||
cell = &at91_usart_serial_subdev;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "atmel,usart-mode has an invalid value %u\n",
|
||||
@ -45,7 +45,7 @@ static int at91_usart_mode_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, &cell, 1,
|
||||
return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, cell, 1,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
|
@ -129,8 +129,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||
}
|
||||
}
|
||||
|
||||
err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell, 1,
|
||||
NULL, ec_dev->irq, NULL);
|
||||
err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell,
|
||||
1, NULL, ec_dev->irq, NULL);
|
||||
if (err) {
|
||||
dev_err(dev,
|
||||
"Failed to register Embedded Controller subdevice %d\n",
|
||||
@ -147,7 +147,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||
* - the EC is responsive at init time (it is not true for a
|
||||
* sensor hub.
|
||||
*/
|
||||
err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO,
|
||||
err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO,
|
||||
&ec_pd_cell, 1, NULL, ec_dev->irq, NULL);
|
||||
if (err) {
|
||||
dev_err(dev,
|
||||
@ -181,14 +181,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_register);
|
||||
|
||||
int cros_ec_remove(struct cros_ec_device *ec_dev)
|
||||
{
|
||||
mfd_remove_devices(ec_dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_remove);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int cros_ec_suspend(struct cros_ec_device *ec_dev)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
@ -34,17 +35,9 @@
|
||||
#define CROS_MAX_DEV 128
|
||||
static int ec_major;
|
||||
|
||||
static const struct attribute_group *cros_ec_groups[] = {
|
||||
&cros_ec_attr_group,
|
||||
&cros_ec_lightbar_attr_group,
|
||||
&cros_ec_vbc_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct class cros_class = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "chromeos",
|
||||
.dev_groups = cros_ec_groups,
|
||||
};
|
||||
|
||||
/* Basic communication */
|
||||
@ -231,7 +224,7 @@ static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg)
|
||||
if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
return num;
|
||||
}
|
||||
|
||||
static long ec_device_ioctl(struct file *filp, unsigned int cmd,
|
||||
@ -395,9 +388,20 @@ static const struct mfd_cell cros_usbpd_charger_cells[] = {
|
||||
{ .name = "cros-usbpd-charger" }
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_platform_cells[] = {
|
||||
{ .name = "cros-ec-debugfs" },
|
||||
{ .name = "cros-ec-lightbar" },
|
||||
{ .name = "cros-ec-sysfs" },
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_vbc_cells[] = {
|
||||
{ .name = "cros-ec-vbc" }
|
||||
};
|
||||
|
||||
static int ec_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
int retval = -ENOMEM;
|
||||
struct device_node *node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
|
||||
struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
|
||||
@ -470,9 +474,6 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
retval);
|
||||
}
|
||||
|
||||
/* Take control of the lightbar from the EC. */
|
||||
lb_manual_suspend_ctrl(ec, 1);
|
||||
|
||||
/* We can now add the sysfs class, we know which parameter to show */
|
||||
retval = cdev_device_add(&ec->cdev, &ec->class_dev);
|
||||
if (retval) {
|
||||
@ -480,8 +481,26 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (cros_ec_debugfs_init(ec))
|
||||
dev_warn(dev, "failed to create debugfs directory\n");
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_platform_cells,
|
||||
ARRAY_SIZE(cros_ec_platform_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_warn(ec->dev,
|
||||
"failed to add cros-ec platform devices: %d\n",
|
||||
retval);
|
||||
|
||||
/* Check whether this EC instance has a VBC NVRAM */
|
||||
node = ec->ec_dev->dev->of_node;
|
||||
if (of_property_read_bool(node, "google,has-vbc-nvram")) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_vbc_cells,
|
||||
ARRAY_SIZE(cros_ec_vbc_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_warn(ec->dev, "failed to add VBC devices: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -494,69 +513,25 @@ static int ec_device_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
/* Let the EC take over the lightbar again. */
|
||||
lb_manual_suspend_ctrl(ec, 0);
|
||||
|
||||
cros_ec_debugfs_remove(ec);
|
||||
|
||||
mfd_remove_devices(ec->dev);
|
||||
cdev_del(&ec->cdev);
|
||||
device_unregister(&ec->class_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ec_device_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
/* Be sure to clear up debugfs delayed works */
|
||||
cros_ec_debugfs_remove(ec);
|
||||
}
|
||||
|
||||
static const struct platform_device_id cros_ec_id[] = {
|
||||
{ DRV_NAME, 0 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, cros_ec_id);
|
||||
|
||||
static __maybe_unused int ec_device_suspend(struct device *dev)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev);
|
||||
|
||||
cros_ec_debugfs_suspend(ec);
|
||||
|
||||
lb_suspend(ec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int ec_device_resume(struct device *dev)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev);
|
||||
|
||||
cros_ec_debugfs_resume(ec);
|
||||
|
||||
lb_resume(ec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops cros_ec_dev_pm_ops = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend = ec_device_suspend,
|
||||
.resume = ec_device_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct platform_driver cros_ec_dev_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &cros_ec_dev_pm_ops,
|
||||
},
|
||||
.id_table = cros_ec_id,
|
||||
.probe = ec_device_probe,
|
||||
.remove = ec_device_remove,
|
||||
.shutdown = ec_device_shutdown,
|
||||
};
|
||||
|
||||
static int __init cros_ec_dev_init(void)
|
||||
|
@ -44,10 +44,4 @@ struct cros_ec_readmem {
|
||||
#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
|
||||
#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
|
||||
|
||||
/* Lightbar utilities */
|
||||
extern bool ec_has_lightbar(struct cros_ec_dev *ec);
|
||||
extern int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable);
|
||||
extern int lb_suspend(struct cros_ec_dev *ec);
|
||||
extern int lb_resume(struct cros_ec_dev *ec);
|
||||
|
||||
#endif /* _CROS_EC_DEV_H_ */
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
* DB8500 PRCM Unit driver
|
||||
*
|
||||
* Copyright (C) STMicroelectronics 2009
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
@ -10,7 +12,8 @@
|
||||
* U8500 PRCM Unit interface driver
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
@ -3188,9 +3191,4 @@ static int __init db8500_prcmu_init(void)
|
||||
{
|
||||
return platform_driver_register(&db8500_prcmu_driver);
|
||||
}
|
||||
|
||||
core_initcall(db8500_prcmu_init);
|
||||
|
||||
MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>");
|
||||
MODULE_DESCRIPTION("DB8500 PRCM Unit driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -614,8 +613,6 @@ static const struct i2c_device_id htcpld_chip_id[] = {
|
||||
{ "htcpld-chip", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, htcpld_chip_id);
|
||||
|
||||
|
||||
static struct i2c_driver htcpld_chip_driver = {
|
||||
.driver = {
|
||||
@ -643,17 +640,4 @@ static int __init htcpld_core_init(void)
|
||||
/* Probe for our chips */
|
||||
return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
|
||||
}
|
||||
|
||||
static void __exit htcpld_core_exit(void)
|
||||
{
|
||||
i2c_del_driver(&htcpld_chip_driver);
|
||||
platform_driver_unregister(&htcpld_core_driver);
|
||||
}
|
||||
|
||||
module_init(htcpld_core_init);
|
||||
module_exit(htcpld_core_exit);
|
||||
|
||||
MODULE_AUTHOR("Cory Maccarrone <darkstar6262@gmail.com>");
|
||||
MODULE_DESCRIPTION("I2C HTC PLD Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
device_initcall(htcpld_core_init);
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#ifndef __MFD_INTEL_LPSS_H
|
||||
#define __MFD_INTEL_LPSS_H
|
||||
|
||||
#include <linux/pm.h>
|
||||
|
||||
struct device;
|
||||
struct resource;
|
||||
struct property_entry;
|
||||
|
398
drivers/mfd/lochnagar-i2c.c
Normal file
398
drivers/mfd/lochnagar-i2c.c
Normal file
@ -0,0 +1,398 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Lochnagar I2C bus interface
|
||||
*
|
||||
* Copyright (c) 2012-2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <linux/mfd/lochnagar.h>
|
||||
#include <linux/mfd/lochnagar1_regs.h>
|
||||
#include <linux/mfd/lochnagar2_regs.h>
|
||||
|
||||
#define LOCHNAGAR_BOOT_RETRIES 10
|
||||
#define LOCHNAGAR_BOOT_DELAY_MS 350
|
||||
|
||||
#define LOCHNAGAR_CONFIG_POLL_US 10000
|
||||
|
||||
static bool lochnagar1_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case LOCHNAGAR_SOFTWARE_RESET:
|
||||
case LOCHNAGAR_FIRMWARE_ID1...LOCHNAGAR_FIRMWARE_ID2:
|
||||
case LOCHNAGAR1_CDC_AIF1_SEL...LOCHNAGAR1_CDC_AIF3_SEL:
|
||||
case LOCHNAGAR1_CDC_MCLK1_SEL...LOCHNAGAR1_CDC_MCLK2_SEL:
|
||||
case LOCHNAGAR1_CDC_AIF_CTRL1...LOCHNAGAR1_CDC_AIF_CTRL2:
|
||||
case LOCHNAGAR1_EXT_AIF_CTRL:
|
||||
case LOCHNAGAR1_DSP_AIF1_SEL...LOCHNAGAR1_DSP_AIF2_SEL:
|
||||
case LOCHNAGAR1_DSP_CLKIN_SEL:
|
||||
case LOCHNAGAR1_DSP_AIF:
|
||||
case LOCHNAGAR1_GF_AIF1...LOCHNAGAR1_GF_AIF2:
|
||||
case LOCHNAGAR1_PSIA_AIF:
|
||||
case LOCHNAGAR1_PSIA1_SEL...LOCHNAGAR1_PSIA2_SEL:
|
||||
case LOCHNAGAR1_SPDIF_AIF_SEL:
|
||||
case LOCHNAGAR1_GF_AIF3_SEL...LOCHNAGAR1_GF_AIF4_SEL:
|
||||
case LOCHNAGAR1_GF_CLKOUT1_SEL:
|
||||
case LOCHNAGAR1_GF_AIF1_SEL...LOCHNAGAR1_GF_AIF2_SEL:
|
||||
case LOCHNAGAR1_GF_GPIO2...LOCHNAGAR1_GF_GPIO7:
|
||||
case LOCHNAGAR1_RST:
|
||||
case LOCHNAGAR1_LED1...LOCHNAGAR1_LED2:
|
||||
case LOCHNAGAR1_I2C_CTRL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config lochnagar1_i2c_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
.val_format_endian = REGMAP_ENDIAN_BIG,
|
||||
|
||||
.max_register = 0x50,
|
||||
.readable_reg = lochnagar1_readable_register,
|
||||
|
||||
.use_single_read = true,
|
||||
.use_single_write = true,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static const struct reg_sequence lochnagar1_patch[] = {
|
||||
{ 0x40, 0x0083 },
|
||||
{ 0x47, 0x0018 },
|
||||
{ 0x50, 0x0000 },
|
||||
};
|
||||
|
||||
static bool lochnagar2_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case LOCHNAGAR_SOFTWARE_RESET:
|
||||
case LOCHNAGAR_FIRMWARE_ID1...LOCHNAGAR_FIRMWARE_ID2:
|
||||
case LOCHNAGAR2_CDC_AIF1_CTRL...LOCHNAGAR2_CDC_AIF3_CTRL:
|
||||
case LOCHNAGAR2_DSP_AIF1_CTRL...LOCHNAGAR2_DSP_AIF2_CTRL:
|
||||
case LOCHNAGAR2_PSIA1_CTRL...LOCHNAGAR2_PSIA2_CTRL:
|
||||
case LOCHNAGAR2_GF_AIF3_CTRL...LOCHNAGAR2_GF_AIF4_CTRL:
|
||||
case LOCHNAGAR2_GF_AIF1_CTRL...LOCHNAGAR2_GF_AIF2_CTRL:
|
||||
case LOCHNAGAR2_SPDIF_AIF_CTRL:
|
||||
case LOCHNAGAR2_USB_AIF1_CTRL...LOCHNAGAR2_USB_AIF2_CTRL:
|
||||
case LOCHNAGAR2_ADAT_AIF_CTRL:
|
||||
case LOCHNAGAR2_CDC_MCLK1_CTRL...LOCHNAGAR2_CDC_MCLK2_CTRL:
|
||||
case LOCHNAGAR2_DSP_CLKIN_CTRL:
|
||||
case LOCHNAGAR2_PSIA1_MCLK_CTRL...LOCHNAGAR2_PSIA2_MCLK_CTRL:
|
||||
case LOCHNAGAR2_SPDIF_MCLK_CTRL:
|
||||
case LOCHNAGAR2_GF_CLKOUT1_CTRL...LOCHNAGAR2_GF_CLKOUT2_CTRL:
|
||||
case LOCHNAGAR2_ADAT_MCLK_CTRL:
|
||||
case LOCHNAGAR2_SOUNDCARD_MCLK_CTRL:
|
||||
case LOCHNAGAR2_GPIO_FPGA_GPIO1...LOCHNAGAR2_GPIO_FPGA_GPIO6:
|
||||
case LOCHNAGAR2_GPIO_CDC_GPIO1...LOCHNAGAR2_GPIO_CDC_GPIO8:
|
||||
case LOCHNAGAR2_GPIO_DSP_GPIO1...LOCHNAGAR2_GPIO_DSP_GPIO6:
|
||||
case LOCHNAGAR2_GPIO_GF_GPIO2...LOCHNAGAR2_GPIO_GF_GPIO7:
|
||||
case LOCHNAGAR2_GPIO_CDC_AIF1_BCLK...LOCHNAGAR2_GPIO_CDC_AIF3_TXDAT:
|
||||
case LOCHNAGAR2_GPIO_DSP_AIF1_BCLK...LOCHNAGAR2_GPIO_DSP_AIF2_TXDAT:
|
||||
case LOCHNAGAR2_GPIO_PSIA1_BCLK...LOCHNAGAR2_GPIO_PSIA2_TXDAT:
|
||||
case LOCHNAGAR2_GPIO_GF_AIF3_BCLK...LOCHNAGAR2_GPIO_GF_AIF4_TXDAT:
|
||||
case LOCHNAGAR2_GPIO_GF_AIF1_BCLK...LOCHNAGAR2_GPIO_GF_AIF2_TXDAT:
|
||||
case LOCHNAGAR2_GPIO_DSP_UART1_RX...LOCHNAGAR2_GPIO_DSP_UART2_TX:
|
||||
case LOCHNAGAR2_GPIO_GF_UART2_RX...LOCHNAGAR2_GPIO_GF_UART2_TX:
|
||||
case LOCHNAGAR2_GPIO_USB_UART_RX:
|
||||
case LOCHNAGAR2_GPIO_CDC_PDMCLK1...LOCHNAGAR2_GPIO_CDC_PDMDAT2:
|
||||
case LOCHNAGAR2_GPIO_CDC_DMICCLK1...LOCHNAGAR2_GPIO_CDC_DMICDAT4:
|
||||
case LOCHNAGAR2_GPIO_DSP_DMICCLK1...LOCHNAGAR2_GPIO_DSP_DMICDAT2:
|
||||
case LOCHNAGAR2_GPIO_I2C2_SCL...LOCHNAGAR2_GPIO_I2C4_SDA:
|
||||
case LOCHNAGAR2_GPIO_DSP_STANDBY:
|
||||
case LOCHNAGAR2_GPIO_CDC_MCLK1...LOCHNAGAR2_GPIO_CDC_MCLK2:
|
||||
case LOCHNAGAR2_GPIO_DSP_CLKIN:
|
||||
case LOCHNAGAR2_GPIO_PSIA1_MCLK...LOCHNAGAR2_GPIO_PSIA2_MCLK:
|
||||
case LOCHNAGAR2_GPIO_GF_GPIO1...LOCHNAGAR2_GPIO_GF_GPIO5:
|
||||
case LOCHNAGAR2_GPIO_DSP_GPIO20:
|
||||
case LOCHNAGAR2_GPIO_CHANNEL1...LOCHNAGAR2_GPIO_CHANNEL16:
|
||||
case LOCHNAGAR2_MINICARD_RESETS:
|
||||
case LOCHNAGAR2_ANALOGUE_PATH_CTRL1...LOCHNAGAR2_ANALOGUE_PATH_CTRL2:
|
||||
case LOCHNAGAR2_COMMS_CTRL4:
|
||||
case LOCHNAGAR2_SPDIF_CTRL:
|
||||
case LOCHNAGAR2_IMON_CTRL1...LOCHNAGAR2_IMON_CTRL4:
|
||||
case LOCHNAGAR2_IMON_DATA1...LOCHNAGAR2_IMON_DATA2:
|
||||
case LOCHNAGAR2_POWER_CTRL:
|
||||
case LOCHNAGAR2_MICVDD_CTRL1:
|
||||
case LOCHNAGAR2_MICVDD_CTRL2:
|
||||
case LOCHNAGAR2_VDDCORE_CDC_CTRL1:
|
||||
case LOCHNAGAR2_VDDCORE_CDC_CTRL2:
|
||||
case LOCHNAGAR2_SOUNDCARD_AIF_CTRL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool lochnagar2_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case LOCHNAGAR2_GPIO_CHANNEL1...LOCHNAGAR2_GPIO_CHANNEL16:
|
||||
case LOCHNAGAR2_ANALOGUE_PATH_CTRL1:
|
||||
case LOCHNAGAR2_IMON_CTRL3...LOCHNAGAR2_IMON_CTRL4:
|
||||
case LOCHNAGAR2_IMON_DATA1...LOCHNAGAR2_IMON_DATA2:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config lochnagar2_i2c_regmap = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 16,
|
||||
.reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
.val_format_endian = REGMAP_ENDIAN_BIG,
|
||||
|
||||
.max_register = 0x1F1F,
|
||||
.readable_reg = lochnagar2_readable_register,
|
||||
.volatile_reg = lochnagar2_volatile_register,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static const struct reg_sequence lochnagar2_patch[] = {
|
||||
{ 0x00EE, 0x0000 },
|
||||
};
|
||||
|
||||
struct lochnagar_config {
|
||||
int id;
|
||||
const char * const name;
|
||||
enum lochnagar_type type;
|
||||
const struct regmap_config *regmap;
|
||||
const struct reg_sequence *patch;
|
||||
int npatch;
|
||||
};
|
||||
|
||||
static struct lochnagar_config lochnagar_configs[] = {
|
||||
{
|
||||
.id = 0x50,
|
||||
.name = "lochnagar1",
|
||||
.type = LOCHNAGAR1,
|
||||
.regmap = &lochnagar1_i2c_regmap,
|
||||
.patch = lochnagar1_patch,
|
||||
.npatch = ARRAY_SIZE(lochnagar1_patch),
|
||||
},
|
||||
{
|
||||
.id = 0xCB58,
|
||||
.name = "lochnagar2",
|
||||
.type = LOCHNAGAR2,
|
||||
.regmap = &lochnagar2_i2c_regmap,
|
||||
.patch = lochnagar2_patch,
|
||||
.npatch = ARRAY_SIZE(lochnagar2_patch),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id lochnagar_of_match[] = {
|
||||
{ .compatible = "cirrus,lochnagar1", .data = &lochnagar_configs[0] },
|
||||
{ .compatible = "cirrus,lochnagar2", .data = &lochnagar_configs[1] },
|
||||
{},
|
||||
};
|
||||
|
||||
static int lochnagar_wait_for_boot(struct regmap *regmap, unsigned int *id)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < LOCHNAGAR_BOOT_RETRIES; ++i) {
|
||||
msleep(LOCHNAGAR_BOOT_DELAY_MS);
|
||||
|
||||
/* The reset register will return the device ID when read */
|
||||
ret = regmap_read(regmap, LOCHNAGAR_SOFTWARE_RESET, id);
|
||||
if (!ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* lochnagar_update_config - Synchronise the boards analogue configuration to
|
||||
* the hardware.
|
||||
*
|
||||
* @lochnagar: A pointer to the primary core data structure.
|
||||
*
|
||||
* Return: Zero on success or an appropriate negative error code on failure.
|
||||
*/
|
||||
int lochnagar_update_config(struct lochnagar *lochnagar)
|
||||
{
|
||||
struct regmap *regmap = lochnagar->regmap;
|
||||
unsigned int done = LOCHNAGAR2_ANALOGUE_PATH_UPDATE_STS_MASK;
|
||||
int timeout_ms = LOCHNAGAR_BOOT_DELAY_MS * LOCHNAGAR_BOOT_RETRIES;
|
||||
unsigned int val = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&lochnagar->analogue_config_lock);
|
||||
|
||||
if (lochnagar->type != LOCHNAGAR2)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Toggle the ANALOGUE_PATH_UPDATE bit and wait for the device to
|
||||
* acknowledge that any outstanding changes to the analogue
|
||||
* configuration have been applied.
|
||||
*/
|
||||
ret = regmap_write(regmap, LOCHNAGAR2_ANALOGUE_PATH_CTRL1, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(regmap, LOCHNAGAR2_ANALOGUE_PATH_CTRL1,
|
||||
LOCHNAGAR2_ANALOGUE_PATH_UPDATE_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read_poll_timeout(regmap,
|
||||
LOCHNAGAR2_ANALOGUE_PATH_CTRL1, val,
|
||||
(val & done), LOCHNAGAR_CONFIG_POLL_US,
|
||||
timeout_ms * 1000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lochnagar_update_config);
|
||||
|
||||
static int lochnagar_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
struct device *dev = &i2c->dev;
|
||||
const struct lochnagar_config *config = NULL;
|
||||
const struct of_device_id *of_id;
|
||||
struct lochnagar *lochnagar;
|
||||
struct gpio_desc *reset, *present;
|
||||
unsigned int val;
|
||||
unsigned int firmwareid;
|
||||
unsigned int devid, rev;
|
||||
int ret;
|
||||
|
||||
lochnagar = devm_kzalloc(dev, sizeof(*lochnagar), GFP_KERNEL);
|
||||
if (!lochnagar)
|
||||
return -ENOMEM;
|
||||
|
||||
of_id = of_match_device(lochnagar_of_match, dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
config = of_id->data;
|
||||
|
||||
lochnagar->dev = dev;
|
||||
mutex_init(&lochnagar->analogue_config_lock);
|
||||
|
||||
dev_set_drvdata(dev, lochnagar);
|
||||
|
||||
reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(reset)) {
|
||||
ret = PTR_ERR(reset);
|
||||
dev_err(dev, "Failed to get reset GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
present = devm_gpiod_get_optional(dev, "present", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(present)) {
|
||||
ret = PTR_ERR(present);
|
||||
dev_err(dev, "Failed to get present GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Leave the Lochnagar in reset for a reasonable amount of time */
|
||||
msleep(20);
|
||||
|
||||
/* Bring Lochnagar out of reset */
|
||||
gpiod_set_value_cansleep(reset, 1);
|
||||
|
||||
/* Identify Lochnagar */
|
||||
lochnagar->type = config->type;
|
||||
|
||||
lochnagar->regmap = devm_regmap_init_i2c(i2c, config->regmap);
|
||||
if (IS_ERR(lochnagar->regmap)) {
|
||||
ret = PTR_ERR(lochnagar->regmap);
|
||||
dev_err(dev, "Failed to allocate register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait for Lochnagar to boot */
|
||||
ret = lochnagar_wait_for_boot(lochnagar->regmap, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read device ID: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
devid = val & LOCHNAGAR_DEVICE_ID_MASK;
|
||||
rev = val & LOCHNAGAR_REV_ID_MASK;
|
||||
|
||||
if (devid != config->id) {
|
||||
dev_err(dev,
|
||||
"ID does not match %s (expected 0x%x got 0x%x)\n",
|
||||
config->name, config->id, devid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Identify firmware */
|
||||
ret = regmap_read(lochnagar->regmap, LOCHNAGAR_FIRMWARE_ID1, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read firmware id 1: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
firmwareid = val;
|
||||
|
||||
ret = regmap_read(lochnagar->regmap, LOCHNAGAR_FIRMWARE_ID2, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read firmware id 2: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
firmwareid |= (val << config->regmap->val_bits);
|
||||
|
||||
dev_info(dev, "Found %s (0x%x) revision %u firmware 0x%.6x\n",
|
||||
config->name, devid, rev + 1, firmwareid);
|
||||
|
||||
ret = regmap_register_patch(lochnagar->regmap, config->patch,
|
||||
config->npatch);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register patch: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_of_platform_populate(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to populate child nodes: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct i2c_driver lochnagar_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "lochnagar",
|
||||
.of_match_table = of_match_ptr(lochnagar_of_match),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe_new = lochnagar_i2c_probe,
|
||||
};
|
||||
|
||||
static int __init lochnagar_i2c_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&lochnagar_i2c_driver);
|
||||
if (ret)
|
||||
pr_err("Failed to register Lochnagar driver: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(lochnagar_i2c_init);
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -919,8 +919,3 @@ void max8925_device_exit(struct max8925_chip *chip)
|
||||
free_irq(chip->tsc_irq, chip);
|
||||
mfd_remove_devices(chip->dev);
|
||||
}
|
||||
|
||||
|
||||
MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -181,7 +181,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
|
||||
MXS_LRADC_TOUCHSCREEN_5WIRE;
|
||||
break;
|
||||
}
|
||||
/* fall through to an error message for i.MX23 */
|
||||
/* fall through - to an error message for i.MX23 */
|
||||
default:
|
||||
dev_err(&pdev->dev,
|
||||
"Unsupported number of touchscreen wires (%d)\n"
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
@ -298,8 +297,6 @@ static const struct i2c_device_id rc5t583_i2c_id[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, rc5t583_i2c_id);
|
||||
|
||||
static struct i2c_driver rc5t583_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rc5t583",
|
||||
@ -313,14 +310,3 @@ static int __init rc5t583_i2c_init(void)
|
||||
return i2c_add_driver(&rc5t583_i2c_driver);
|
||||
}
|
||||
subsys_initcall(rc5t583_i2c_init);
|
||||
|
||||
static void __exit rc5t583_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rc5t583_i2c_driver);
|
||||
}
|
||||
|
||||
module_exit(rc5t583_i2c_exit);
|
||||
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_DESCRIPTION("RICOH RC5T583 power management system device driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -114,7 +114,8 @@ static const struct mfd_cell s2mpu02_devs[] = {
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id sec_dt_match[] = {
|
||||
{ .compatible = "samsung,s5m8767-pmic",
|
||||
{
|
||||
.compatible = "samsung,s5m8767-pmic",
|
||||
.data = (void *)S5M8767X,
|
||||
}, {
|
||||
.compatible = "samsung,s2mps11-pmic",
|
||||
@ -309,8 +310,8 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
|
||||
* the sub-modules need not instantiate another instance while parsing their
|
||||
* platform data.
|
||||
*/
|
||||
static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
static struct sec_platform_data *
|
||||
sec_pmic_i2c_parse_dt_pdata(struct device *dev)
|
||||
{
|
||||
struct sec_platform_data *pd;
|
||||
|
||||
@ -331,8 +332,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
|
||||
return pd;
|
||||
}
|
||||
#else
|
||||
static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
static struct sec_platform_data *
|
||||
sec_pmic_i2c_parse_dt_pdata(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -471,8 +472,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
|
||||
num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
|
||||
break;
|
||||
default:
|
||||
/* If this happens the probe function is problem */
|
||||
BUG();
|
||||
dev_err(&i2c->dev, "Unsupported device type (%lu)\n",
|
||||
sec_pmic->device_type);
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
|
||||
NULL, 0, NULL);
|
||||
|
@ -1142,9 +1142,11 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
|
||||
return -ENOMEM;
|
||||
|
||||
/* Create a gpiod lookup using gpiochip-local offsets */
|
||||
lookup = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
|
||||
lookup = devm_kzalloc(&pdev->dev, struct_size(lookup, table, 3),
|
||||
GFP_KERNEL);
|
||||
if (!lookup)
|
||||
return -ENOMEM;
|
||||
|
||||
lookup->dev_id = "i2c-gpio";
|
||||
if (iic->pin_sda < 32)
|
||||
lookup->table[0].chip_label = "SM501-LOW";
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
* STA2x11 mfd for GPIO, SCTL and APBREG
|
||||
*
|
||||
* Copyright (c) 2009-2011 Wind River Systems, Inc.
|
||||
* Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
|
||||
*
|
||||
@ -18,7 +20,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/device.h>
|
||||
@ -653,8 +656,3 @@ static int __init sta2x11_mfd_init(void)
|
||||
*/
|
||||
subsys_initcall(sta2x11_drivers_init);
|
||||
rootfs_initcall(sta2x11_mfd_init);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Wind River");
|
||||
MODULE_DESCRIPTION("STA2x11 mfd for GPIO, SCTL and APBREG");
|
||||
MODULE_DEVICE_TABLE(pci, sta2x11_mfd_tbl);
|
||||
|
@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell = {
|
||||
.num_resources = ARRAY_SIZE(stmpe_ts_resources),
|
||||
};
|
||||
|
||||
/*
|
||||
* ADC (STMPE811)
|
||||
*/
|
||||
|
||||
static struct resource stmpe_adc_resources[] = {
|
||||
{
|
||||
.name = "STMPE_TEMP_SENS",
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "STMPE_ADC",
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mfd_cell stmpe_adc_cell = {
|
||||
.name = "stmpe-adc",
|
||||
.of_compatible = "st,stmpe-adc",
|
||||
.resources = stmpe_adc_resources,
|
||||
.num_resources = ARRAY_SIZE(stmpe_adc_resources),
|
||||
};
|
||||
|
||||
/*
|
||||
* STMPE811 or STMPE610
|
||||
*/
|
||||
@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
|
||||
.irq = STMPE811_IRQ_TOUCH_DET,
|
||||
.block = STMPE_BLOCK_TOUCHSCREEN,
|
||||
},
|
||||
{
|
||||
.cell = &stmpe_adc_cell,
|
||||
.irq = STMPE811_IRQ_TEMP_SENS,
|
||||
.block = STMPE_BLOCK_ADC,
|
||||
},
|
||||
};
|
||||
|
||||
static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
|
||||
@ -517,6 +544,35 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
|
||||
enable ? 0 : mask);
|
||||
}
|
||||
|
||||
int stmpe811_adc_common_init(struct stmpe *stmpe)
|
||||
{
|
||||
int ret;
|
||||
u8 adc_ctrl1, adc_ctrl1_mask;
|
||||
|
||||
adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) |
|
||||
STMPE_MOD_12B(stmpe->mod_12b) |
|
||||
STMPE_REF_SEL(stmpe->ref_sel);
|
||||
adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) |
|
||||
STMPE_REF_SEL(0xff);
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL1,
|
||||
adc_ctrl1_mask, adc_ctrl1);
|
||||
if (ret) {
|
||||
dev_err(stmpe->dev, "Could not setup ADC\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL2,
|
||||
STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq));
|
||||
if (ret) {
|
||||
dev_err(stmpe->dev, "Could not setup ADC\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stmpe811_adc_common_init);
|
||||
|
||||
static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
|
||||
{
|
||||
/* 0 for touchscreen, 1 for GPIO */
|
||||
@ -1325,6 +1381,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
|
||||
struct device_node *np = ci->dev->of_node;
|
||||
struct stmpe *stmpe;
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
@ -1342,6 +1399,15 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
|
||||
mutex_init(&stmpe->irq_lock);
|
||||
mutex_init(&stmpe->lock);
|
||||
|
||||
if (!of_property_read_u32(np, "st,sample-time", &val))
|
||||
stmpe->sample_time = val;
|
||||
if (!of_property_read_u32(np, "st,mod-12b", &val))
|
||||
stmpe->mod_12b = val;
|
||||
if (!of_property_read_u32(np, "st,ref-sel", &val))
|
||||
stmpe->ref_sel = val;
|
||||
if (!of_property_read_u32(np, "st,adc-freq", &val))
|
||||
stmpe->adc_freq = val;
|
||||
|
||||
stmpe->dev = ci->dev;
|
||||
stmpe->client = ci->client;
|
||||
stmpe->pdata = pdata;
|
||||
@ -1433,6 +1499,8 @@ int stmpe_remove(struct stmpe *stmpe)
|
||||
if (!IS_ERR(stmpe->vcc))
|
||||
regulator_disable(stmpe->vcc);
|
||||
|
||||
__stmpe_disable(stmpe, STMPE_BLOCK_ADC);
|
||||
|
||||
mfd_remove_devices(stmpe->dev);
|
||||
|
||||
return 0;
|
||||
|
213
drivers/mfd/stpmic1.c
Normal file
213
drivers/mfd/stpmic1.c
Normal file
@ -0,0 +1,213 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) STMicroelectronics 2018
|
||||
// Author: Pascal Paillet <p.paillet@st.com>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/stpmic1.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <dt-bindings/mfd/st,stpmic1.h>
|
||||
|
||||
#define STPMIC1_MAIN_IRQ 0
|
||||
|
||||
static const struct regmap_range stpmic1_readable_ranges[] = {
|
||||
regmap_reg_range(TURN_ON_SR, VERSION_SR),
|
||||
regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR),
|
||||
regmap_reg_range(BST_SW_CR, BST_SW_CR),
|
||||
regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),
|
||||
regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),
|
||||
regmap_reg_range(INT_MASK_R1, INT_MASK_R4),
|
||||
regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),
|
||||
regmap_reg_range(INT_CLEAR_MASK_R1, INT_CLEAR_MASK_R4),
|
||||
regmap_reg_range(INT_SRC_R1, INT_SRC_R1),
|
||||
};
|
||||
|
||||
static const struct regmap_range stpmic1_writeable_ranges[] = {
|
||||
regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR),
|
||||
regmap_reg_range(BST_SW_CR, BST_SW_CR),
|
||||
regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),
|
||||
regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),
|
||||
regmap_reg_range(INT_CLEAR_MASK_R1, INT_CLEAR_MASK_R4),
|
||||
};
|
||||
|
||||
static const struct regmap_range stpmic1_volatile_ranges[] = {
|
||||
regmap_reg_range(TURN_ON_SR, VERSION_SR),
|
||||
regmap_reg_range(WCHDG_CR, WCHDG_CR),
|
||||
regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),
|
||||
regmap_reg_range(INT_SRC_R1, INT_SRC_R4),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table stpmic1_readable_table = {
|
||||
.yes_ranges = stpmic1_readable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(stpmic1_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table stpmic1_writeable_table = {
|
||||
.yes_ranges = stpmic1_writeable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(stpmic1_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table stpmic1_volatile_table = {
|
||||
.yes_ranges = stpmic1_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(stpmic1_volatile_ranges),
|
||||
};
|
||||
|
||||
const struct regmap_config stpmic1_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.max_register = PMIC_MAX_REGISTER_ADDRESS,
|
||||
.rd_table = &stpmic1_readable_table,
|
||||
.wr_table = &stpmic1_writeable_table,
|
||||
.volatile_table = &stpmic1_volatile_table,
|
||||
};
|
||||
|
||||
static const struct regmap_irq stpmic1_irqs[] = {
|
||||
REGMAP_IRQ_REG(IT_PONKEY_F, 0, 0x01),
|
||||
REGMAP_IRQ_REG(IT_PONKEY_R, 0, 0x02),
|
||||
REGMAP_IRQ_REG(IT_WAKEUP_F, 0, 0x04),
|
||||
REGMAP_IRQ_REG(IT_WAKEUP_R, 0, 0x08),
|
||||
REGMAP_IRQ_REG(IT_VBUS_OTG_F, 0, 0x10),
|
||||
REGMAP_IRQ_REG(IT_VBUS_OTG_R, 0, 0x20),
|
||||
REGMAP_IRQ_REG(IT_SWOUT_F, 0, 0x40),
|
||||
REGMAP_IRQ_REG(IT_SWOUT_R, 0, 0x80),
|
||||
|
||||
REGMAP_IRQ_REG(IT_CURLIM_BUCK1, 1, 0x01),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_BUCK2, 1, 0x02),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_BUCK3, 1, 0x04),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_BUCK4, 1, 0x08),
|
||||
REGMAP_IRQ_REG(IT_OCP_OTG, 1, 0x10),
|
||||
REGMAP_IRQ_REG(IT_OCP_SWOUT, 1, 0x20),
|
||||
REGMAP_IRQ_REG(IT_OCP_BOOST, 1, 0x40),
|
||||
REGMAP_IRQ_REG(IT_OVP_BOOST, 1, 0x80),
|
||||
|
||||
REGMAP_IRQ_REG(IT_CURLIM_LDO1, 2, 0x01),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_LDO2, 2, 0x02),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_LDO3, 2, 0x04),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_LDO4, 2, 0x08),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_LDO5, 2, 0x10),
|
||||
REGMAP_IRQ_REG(IT_CURLIM_LDO6, 2, 0x20),
|
||||
REGMAP_IRQ_REG(IT_SHORT_SWOTG, 2, 0x40),
|
||||
REGMAP_IRQ_REG(IT_SHORT_SWOUT, 2, 0x80),
|
||||
|
||||
REGMAP_IRQ_REG(IT_TWARN_F, 3, 0x01),
|
||||
REGMAP_IRQ_REG(IT_TWARN_R, 3, 0x02),
|
||||
REGMAP_IRQ_REG(IT_VINLOW_F, 3, 0x04),
|
||||
REGMAP_IRQ_REG(IT_VINLOW_R, 3, 0x08),
|
||||
REGMAP_IRQ_REG(IT_SWIN_F, 3, 0x40),
|
||||
REGMAP_IRQ_REG(IT_SWIN_R, 3, 0x80),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip stpmic1_regmap_irq_chip = {
|
||||
.name = "pmic_irq",
|
||||
.status_base = INT_PENDING_R1,
|
||||
.mask_base = INT_CLEAR_MASK_R1,
|
||||
.unmask_base = INT_SET_MASK_R1,
|
||||
.ack_base = INT_CLEAR_R1,
|
||||
.num_regs = STPMIC1_PMIC_NUM_IRQ_REGS,
|
||||
.irqs = stpmic1_irqs,
|
||||
.num_irqs = ARRAY_SIZE(stpmic1_irqs),
|
||||
};
|
||||
|
||||
static int stpmic1_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct stpmic1 *ddata;
|
||||
struct device *dev = &i2c->dev;
|
||||
int ret;
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 reg;
|
||||
|
||||
ddata = devm_kzalloc(dev, sizeof(struct stpmic1), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, ddata);
|
||||
ddata->dev = dev;
|
||||
|
||||
ddata->regmap = devm_regmap_init_i2c(i2c, &stpmic1_regmap_config);
|
||||
if (IS_ERR(ddata->regmap))
|
||||
return PTR_ERR(ddata->regmap);
|
||||
|
||||
ddata->irq = of_irq_get(np, STPMIC1_MAIN_IRQ);
|
||||
if (ddata->irq < 0) {
|
||||
dev_err(dev, "Failed to get main IRQ: %d\n", ddata->irq);
|
||||
return ddata->irq;
|
||||
}
|
||||
|
||||
ret = regmap_read(ddata->regmap, VERSION_SR, ®);
|
||||
if (ret) {
|
||||
dev_err(dev, "Unable to read PMIC version\n");
|
||||
return ret;
|
||||
}
|
||||
dev_info(dev, "PMIC Chip Version: 0x%x\n", reg);
|
||||
|
||||
/* Initialize PMIC IRQ Chip & associated IRQ domains */
|
||||
ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED,
|
||||
0, &stpmic1_regmap_irq_chip,
|
||||
&ddata->irq_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ Chip registration failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_of_platform_populate(dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int stpmic1_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = to_i2c_client(dev);
|
||||
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
|
||||
|
||||
disable_irq(pmic_dev->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stpmic1_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = to_i2c_client(dev);
|
||||
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
|
||||
ret = regcache_sync(pmic_dev->regmap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
enable_irq(pmic_dev->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(stpmic1_pm, stpmic1_suspend, stpmic1_resume);
|
||||
|
||||
static const struct of_device_id stpmic1_of_match[] = {
|
||||
{ .compatible = "st,stpmic1", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stpmic1_of_match);
|
||||
|
||||
static struct i2c_driver stpmic1_driver = {
|
||||
.driver = {
|
||||
.name = "stpmic1",
|
||||
.of_match_table = of_match_ptr(stpmic1_of_match),
|
||||
.pm = &stpmic1_pm,
|
||||
},
|
||||
.probe = stpmic1_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(stpmic1_driver);
|
||||
|
||||
MODULE_DESCRIPTION("STPMIC1 PMIC Driver");
|
||||
MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -15,7 +15,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwspinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
@ -272,13 +272,3 @@ static int __init syscon_init(void)
|
||||
return platform_driver_register(&syscon_driver);
|
||||
}
|
||||
postcore_initcall(syscon_init);
|
||||
|
||||
static void __exit syscon_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&syscon_driver);
|
||||
}
|
||||
module_exit(syscon_exit);
|
||||
|
||||
MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
|
||||
MODULE_DESCRIPTION("System Control driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -2,7 +2,9 @@
|
||||
* Core driver for TI TPS65090 PMIC family
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
*
|
||||
* Author: Venu Byravarasu <vbyravarasu@nvidia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
@ -19,7 +21,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -171,7 +173,6 @@ static const struct of_device_id tps65090_of_match[] = {
|
||||
{ .compatible = "ti,tps65090",},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps65090_of_match);
|
||||
#endif
|
||||
|
||||
static int tps65090_i2c_probe(struct i2c_client *client,
|
||||
@ -236,30 +237,19 @@ err_irq_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65090_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps65090 *tps65090 = i2c_get_clientdata(client);
|
||||
|
||||
mfd_remove_devices(tps65090->dev);
|
||||
if (client->irq)
|
||||
regmap_del_irq_chip(client->irq, tps65090->irq_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps65090_id_table[] = {
|
||||
{ "tps65090", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps65090_id_table);
|
||||
|
||||
static struct i2c_driver tps65090_driver = {
|
||||
.driver = {
|
||||
.name = "tps65090",
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = of_match_ptr(tps65090_of_match),
|
||||
},
|
||||
.probe = tps65090_i2c_probe,
|
||||
.remove = tps65090_i2c_remove,
|
||||
.id_table = tps65090_id_table,
|
||||
};
|
||||
|
||||
@ -268,13 +258,3 @@ static int __init tps65090_init(void)
|
||||
return i2c_add_driver(&tps65090_driver);
|
||||
}
|
||||
subsys_initcall(tps65090_init);
|
||||
|
||||
static void __exit tps65090_exit(void)
|
||||
{
|
||||
i2c_del_driver(&tps65090_driver);
|
||||
}
|
||||
module_exit(tps65090_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TPS65090 core driver");
|
||||
MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -211,6 +211,83 @@ static const struct of_device_id of_tps65218_match_table[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_tps65218_match_table);
|
||||
|
||||
static int tps65218_voltage_set_strict(struct tps65218 *tps)
|
||||
{
|
||||
u32 strict;
|
||||
|
||||
if (of_property_read_u32(tps->dev->of_node,
|
||||
"ti,strict-supply-voltage-supervision",
|
||||
&strict))
|
||||
return 0;
|
||||
|
||||
if (strict != 0 && strict != 1) {
|
||||
dev_err(tps->dev,
|
||||
"Invalid ti,strict-supply-voltage-supervision value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tps65218_update_bits(tps, TPS65218_REG_CONFIG1,
|
||||
TPS65218_CONFIG1_STRICT,
|
||||
strict ? TPS65218_CONFIG1_STRICT : 0,
|
||||
TPS65218_PROTECT_L1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65218_voltage_set_uv_hyst(struct tps65218 *tps)
|
||||
{
|
||||
u32 hyst;
|
||||
|
||||
if (of_property_read_u32(tps->dev->of_node,
|
||||
"ti,under-voltage-hyst-microvolt", &hyst))
|
||||
return 0;
|
||||
|
||||
if (hyst != 400000 && hyst != 200000) {
|
||||
dev_err(tps->dev,
|
||||
"Invalid ti,under-voltage-hyst-microvolt value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tps65218_update_bits(tps, TPS65218_REG_CONFIG2,
|
||||
TPS65218_CONFIG2_UVLOHYS,
|
||||
hyst == 400000 ? TPS65218_CONFIG2_UVLOHYS : 0,
|
||||
TPS65218_PROTECT_L1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65218_voltage_set_uvlo(struct tps65218 *tps)
|
||||
{
|
||||
u32 uvlo;
|
||||
int uvloval;
|
||||
|
||||
if (of_property_read_u32(tps->dev->of_node,
|
||||
"ti,under-voltage-limit-microvolt", &uvlo))
|
||||
return 0;
|
||||
|
||||
switch (uvlo) {
|
||||
case 2750000:
|
||||
uvloval = TPS65218_CONFIG1_UVLO_2750000;
|
||||
break;
|
||||
case 2950000:
|
||||
uvloval = TPS65218_CONFIG1_UVLO_2950000;
|
||||
break;
|
||||
case 3250000:
|
||||
uvloval = TPS65218_CONFIG1_UVLO_3250000;
|
||||
break;
|
||||
case 3350000:
|
||||
uvloval = TPS65218_CONFIG1_UVLO_3350000;
|
||||
break;
|
||||
default:
|
||||
dev_err(tps->dev,
|
||||
"Invalid ti,under-voltage-limit-microvolt value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tps65218_update_bits(tps, TPS65218_REG_CONFIG1,
|
||||
TPS65218_CONFIG1_UVLO_MASK, uvloval,
|
||||
TPS65218_PROTECT_L1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65218_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *ids)
|
||||
{
|
||||
@ -249,6 +326,18 @@ static int tps65218_probe(struct i2c_client *client,
|
||||
|
||||
tps->rev = chipid & TPS65218_CHIPID_REV_MASK;
|
||||
|
||||
ret = tps65218_voltage_set_strict(tps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tps65218_voltage_set_uvlo(tps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tps65218_voltage_set_uv_hyst(tps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells,
|
||||
ARRAY_SIZE(tps65218_cells), NULL, 0,
|
||||
regmap_irq_get_domain(tps->irq_data));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* tps65910.c -- TI TPS6591x
|
||||
* tps65910.c -- TI TPS6591x chip family multi-function driver
|
||||
*
|
||||
* Copyright 2010 Texas Instruments Inc.
|
||||
*
|
||||
@ -13,8 +13,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
@ -374,7 +372,6 @@ static const struct of_device_id tps65910_of_match[] = {
|
||||
{ .compatible = "ti,tps65911", .data = (void *)TPS65911},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps65910_of_match);
|
||||
|
||||
static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
|
||||
unsigned long *chip_id)
|
||||
@ -527,8 +524,6 @@ static const struct i2c_device_id tps65910_i2c_id[] = {
|
||||
{ "tps65911", TPS65911 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id);
|
||||
|
||||
|
||||
static struct i2c_driver tps65910_i2c_driver = {
|
||||
.driver = {
|
||||
@ -545,14 +540,3 @@ static int __init tps65910_i2c_init(void)
|
||||
}
|
||||
/* init early so consumer devices can complete system boot */
|
||||
subsys_initcall(tps65910_i2c_init);
|
||||
|
||||
static void __exit tps65910_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&tps65910_i2c_driver);
|
||||
}
|
||||
module_exit(tps65910_i2c_exit);
|
||||
|
||||
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
|
||||
MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>");
|
||||
MODULE_DESCRIPTION("TPS6591x chip family multi-function driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -86,7 +86,6 @@ static const struct acpi_device_id tps68470_acpi_ids[] = {
|
||||
{"INT3472"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, tps68470_acpi_ids);
|
||||
|
||||
static struct i2c_driver tps68470_driver = {
|
||||
.driver = {
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps80031.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
@ -516,40 +515,18 @@ fail_client_reg:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps80031 *tps80031 = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
||||
if (tps80031_power_off_dev == tps80031) {
|
||||
tps80031_power_off_dev = NULL;
|
||||
pm_power_off = NULL;
|
||||
}
|
||||
|
||||
mfd_remove_devices(tps80031->dev);
|
||||
|
||||
regmap_del_irq_chip(client->irq, tps80031->irq_data);
|
||||
|
||||
for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
|
||||
if (tps80031->clients[i] != client)
|
||||
i2c_unregister_device(tps80031->clients[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps80031_id_table[] = {
|
||||
{ "tps80031", TPS80031 },
|
||||
{ "tps80032", TPS80032 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps80031_id_table);
|
||||
|
||||
static struct i2c_driver tps80031_driver = {
|
||||
.driver = {
|
||||
.name = "tps80031",
|
||||
.name = "tps80031",
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = tps80031_probe,
|
||||
.remove = tps80031_remove,
|
||||
.id_table = tps80031_id_table,
|
||||
};
|
||||
|
||||
@ -558,13 +535,3 @@ static int __init tps80031_init(void)
|
||||
return i2c_add_driver(&tps80031_driver);
|
||||
}
|
||||
subsys_initcall(tps80031_init);
|
||||
|
||||
static void __exit tps80031_exit(void)
|
||||
{
|
||||
i2c_del_driver(&tps80031_driver);
|
||||
}
|
||||
module_exit(tps80031_exit);
|
||||
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_DESCRIPTION("TPS80031 core driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
281
drivers/mfd/tqmx86.c
Normal file
281
drivers/mfd/tqmx86.c
Normal file
@ -0,0 +1,281 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* TQ-Systems PLD MFD core driver, based on vendor driver by
|
||||
* Vadim V.Vlasov <vvlasov@dev.rtsoft.ru>
|
||||
*
|
||||
* Copyright (c) 2015 TQ-Systems GmbH
|
||||
* Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/i2c-ocores.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define TQMX86_IOBASE 0x160
|
||||
#define TQMX86_IOSIZE 0x3f
|
||||
#define TQMX86_IOBASE_I2C 0x1a0
|
||||
#define TQMX86_IOSIZE_I2C 0xa
|
||||
#define TQMX86_IOBASE_WATCHDOG 0x18b
|
||||
#define TQMX86_IOSIZE_WATCHDOG 0x2
|
||||
#define TQMX86_IOBASE_GPIO 0x18d
|
||||
#define TQMX86_IOSIZE_GPIO 0x4
|
||||
|
||||
#define TQMX86_REG_BOARD_ID 0x20
|
||||
#define TQMX86_REG_BOARD_ID_E38M 1
|
||||
#define TQMX86_REG_BOARD_ID_50UC 2
|
||||
#define TQMX86_REG_BOARD_ID_E38C 3
|
||||
#define TQMX86_REG_BOARD_ID_60EB 4
|
||||
#define TQMX86_REG_BOARD_ID_E39M 5
|
||||
#define TQMX86_REG_BOARD_ID_E39C 6
|
||||
#define TQMX86_REG_BOARD_ID_E39x 7
|
||||
#define TQMX86_REG_BOARD_ID_70EB 8
|
||||
#define TQMX86_REG_BOARD_ID_80UC 9
|
||||
#define TQMX86_REG_BOARD_ID_90UC 10
|
||||
#define TQMX86_REG_BOARD_REV 0x21
|
||||
#define TQMX86_REG_IO_EXT_INT 0x26
|
||||
#define TQMX86_REG_IO_EXT_INT_NONE 0
|
||||
#define TQMX86_REG_IO_EXT_INT_7 1
|
||||
#define TQMX86_REG_IO_EXT_INT_9 2
|
||||
#define TQMX86_REG_IO_EXT_INT_12 3
|
||||
#define TQMX86_REG_IO_EXT_INT_MASK 0x3
|
||||
#define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4
|
||||
|
||||
#define TQMX86_REG_I2C_DETECT 0x47
|
||||
#define TQMX86_REG_I2C_DETECT_SOFT 0xa5
|
||||
#define TQMX86_REG_I2C_INT_EN 0x49
|
||||
|
||||
static uint gpio_irq;
|
||||
module_param(gpio_irq, uint, 0);
|
||||
MODULE_PARM_DESC(gpio_irq, "GPIO IRQ number (7, 9, 12)");
|
||||
|
||||
static const struct resource tqmx_i2c_soft_resources[] = {
|
||||
DEFINE_RES_IO(TQMX86_IOBASE_I2C, TQMX86_IOSIZE_I2C),
|
||||
};
|
||||
|
||||
static const struct resource tqmx_watchdog_resources[] = {
|
||||
DEFINE_RES_IO(TQMX86_IOBASE_WATCHDOG, TQMX86_IOSIZE_WATCHDOG),
|
||||
};
|
||||
|
||||
/*
|
||||
* The IRQ resource must be first, since it is updated with the
|
||||
* configured IRQ in the probe function.
|
||||
*/
|
||||
static struct resource tqmx_gpio_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
DEFINE_RES_IO(TQMX86_IOBASE_GPIO, TQMX86_IOSIZE_GPIO),
|
||||
};
|
||||
|
||||
static struct i2c_board_info tqmx86_i2c_devices[] = {
|
||||
{
|
||||
/* 4K EEPROM at 0x50 */
|
||||
I2C_BOARD_INFO("24c32", 0x50),
|
||||
},
|
||||
};
|
||||
|
||||
static struct ocores_i2c_platform_data ocores_platfom_data = {
|
||||
.num_devices = ARRAY_SIZE(tqmx86_i2c_devices),
|
||||
.devices = tqmx86_i2c_devices,
|
||||
};
|
||||
|
||||
static const struct mfd_cell tqmx86_i2c_soft_dev[] = {
|
||||
{
|
||||
.name = "ocores-i2c",
|
||||
.platform_data = &ocores_platfom_data,
|
||||
.pdata_size = sizeof(ocores_platfom_data),
|
||||
.resources = tqmx_i2c_soft_resources,
|
||||
.num_resources = ARRAY_SIZE(tqmx_i2c_soft_resources),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mfd_cell tqmx86_devs[] = {
|
||||
{
|
||||
.name = "tqmx86-wdt",
|
||||
.resources = tqmx_watchdog_resources,
|
||||
.num_resources = ARRAY_SIZE(tqmx_watchdog_resources),
|
||||
.ignore_resource_conflicts = true,
|
||||
},
|
||||
{
|
||||
.name = "tqmx86-gpio",
|
||||
.resources = tqmx_gpio_resources,
|
||||
.num_resources = ARRAY_SIZE(tqmx_gpio_resources),
|
||||
.ignore_resource_conflicts = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *tqmx86_board_id_to_name(u8 board_id)
|
||||
{
|
||||
switch (board_id) {
|
||||
case TQMX86_REG_BOARD_ID_E38M:
|
||||
return "TQMxE38M";
|
||||
case TQMX86_REG_BOARD_ID_50UC:
|
||||
return "TQMx50UC";
|
||||
case TQMX86_REG_BOARD_ID_E38C:
|
||||
return "TQMxE38C";
|
||||
case TQMX86_REG_BOARD_ID_60EB:
|
||||
return "TQMx60EB";
|
||||
case TQMX86_REG_BOARD_ID_E39M:
|
||||
return "TQMxE39M";
|
||||
case TQMX86_REG_BOARD_ID_E39C:
|
||||
return "TQMxE39C";
|
||||
case TQMX86_REG_BOARD_ID_E39x:
|
||||
return "TQMxE39x";
|
||||
case TQMX86_REG_BOARD_ID_70EB:
|
||||
return "TQMx70EB";
|
||||
case TQMX86_REG_BOARD_ID_80UC:
|
||||
return "TQMx80UC";
|
||||
case TQMX86_REG_BOARD_ID_90UC:
|
||||
return "TQMx90UC";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int tqmx86_board_id_to_clk_rate(u8 board_id)
|
||||
{
|
||||
switch (board_id) {
|
||||
case TQMX86_REG_BOARD_ID_50UC:
|
||||
case TQMX86_REG_BOARD_ID_60EB:
|
||||
case TQMX86_REG_BOARD_ID_70EB:
|
||||
case TQMX86_REG_BOARD_ID_80UC:
|
||||
case TQMX86_REG_BOARD_ID_90UC:
|
||||
return 24000;
|
||||
case TQMX86_REG_BOARD_ID_E39M:
|
||||
case TQMX86_REG_BOARD_ID_E39C:
|
||||
case TQMX86_REG_BOARD_ID_E39x:
|
||||
return 25000;
|
||||
case TQMX86_REG_BOARD_ID_E38M:
|
||||
case TQMX86_REG_BOARD_ID_E38C:
|
||||
return 33000;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tqmx86_probe(struct platform_device *pdev)
|
||||
{
|
||||
u8 board_id, rev, i2c_det, i2c_ien, io_ext_int_val;
|
||||
struct device *dev = &pdev->dev;
|
||||
u8 gpio_irq_cfg, readback;
|
||||
const char *board_name;
|
||||
void __iomem *io_base;
|
||||
int err;
|
||||
|
||||
switch (gpio_irq) {
|
||||
case 0:
|
||||
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_NONE;
|
||||
break;
|
||||
case 7:
|
||||
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_7;
|
||||
break;
|
||||
case 9:
|
||||
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_9;
|
||||
break;
|
||||
case 12:
|
||||
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_12;
|
||||
break;
|
||||
default:
|
||||
pr_err("tqmx86: Invalid GPIO IRQ (%d)\n", gpio_irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
io_base = devm_ioport_map(dev, TQMX86_IOBASE, TQMX86_IOSIZE);
|
||||
if (!io_base)
|
||||
return -ENOMEM;
|
||||
|
||||
board_id = ioread8(io_base + TQMX86_REG_BOARD_ID);
|
||||
board_name = tqmx86_board_id_to_name(board_id);
|
||||
rev = ioread8(io_base + TQMX86_REG_BOARD_REV);
|
||||
|
||||
dev_info(dev,
|
||||
"Found %s - Board ID %d, PCB Revision %d, PLD Revision %d\n",
|
||||
board_name, board_id, rev >> 4, rev & 0xf);
|
||||
|
||||
i2c_det = ioread8(io_base + TQMX86_REG_I2C_DETECT);
|
||||
i2c_ien = ioread8(io_base + TQMX86_REG_I2C_INT_EN);
|
||||
|
||||
if (gpio_irq_cfg) {
|
||||
io_ext_int_val =
|
||||
gpio_irq_cfg << TQMX86_REG_IO_EXT_INT_GPIO_SHIFT;
|
||||
iowrite8(io_ext_int_val, io_base + TQMX86_REG_IO_EXT_INT);
|
||||
readback = ioread8(io_base + TQMX86_REG_IO_EXT_INT);
|
||||
if (readback != io_ext_int_val) {
|
||||
dev_warn(dev, "GPIO interrupts not supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Assumes the IRQ resource is first. */
|
||||
tqmx_gpio_resources[0].start = gpio_irq;
|
||||
}
|
||||
|
||||
ocores_platfom_data.clock_khz = tqmx86_board_id_to_clk_rate(board_id);
|
||||
|
||||
if (i2c_det == TQMX86_REG_I2C_DETECT_SOFT) {
|
||||
err = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
tqmx86_i2c_soft_dev,
|
||||
ARRAY_SIZE(tqmx86_i2c_soft_dev),
|
||||
NULL, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
tqmx86_devs,
|
||||
ARRAY_SIZE(tqmx86_devs),
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static int tqmx86_create_platform_device(const struct dmi_system_id *id)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
int err;
|
||||
|
||||
pdev = platform_device_alloc("tqmx86", -1);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
err = platform_device_add(pdev);
|
||||
if (err)
|
||||
platform_device_put(pdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id tqmx86_dmi_table[] __initconst = {
|
||||
{
|
||||
.ident = "TQMX86",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TQ-Group"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TQMx"),
|
||||
},
|
||||
.callback = tqmx86_create_platform_device,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, tqmx86_dmi_table);
|
||||
|
||||
static struct platform_driver tqmx86_driver = {
|
||||
.driver = {
|
||||
.name = "tqmx86",
|
||||
},
|
||||
.probe = tqmx86_probe,
|
||||
};
|
||||
|
||||
static int __init tqmx86_init(void)
|
||||
{
|
||||
if (!dmi_check_system(tqmx86_dmi_table))
|
||||
return -ENODEV;
|
||||
|
||||
return platform_driver_register(&tqmx86_driver);
|
||||
}
|
||||
|
||||
module_init(tqmx86_init);
|
||||
|
||||
MODULE_DESCRIPTION("TQx86 PLD Core Driver");
|
||||
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:tqmx86");
|
@ -13,7 +13,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mfd/core.h>
|
||||
@ -1892,14 +1893,6 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wm831x_device_exit(struct wm831x *wm831x)
|
||||
{
|
||||
wm831x_otp_exit(wm831x);
|
||||
mfd_remove_devices(wm831x->dev);
|
||||
free_irq(wm831x_irq(wm831x, WM831X_IRQ_AUXADC_DATA), wm831x);
|
||||
wm831x_irq_exit(wm831x);
|
||||
}
|
||||
|
||||
int wm831x_device_suspend(struct wm831x *wm831x)
|
||||
{
|
||||
int reg, mask;
|
||||
@ -1944,7 +1937,3 @@ void wm831x_device_shutdown(struct wm831x *wm831x)
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
|
||||
|
||||
MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mark Brown");
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mfd/core.h>
|
||||
@ -68,15 +68,6 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
|
||||
return wm831x_device_init(wm831x, i2c->irq);
|
||||
}
|
||||
|
||||
static int wm831x_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct wm831x *wm831x = i2c_get_clientdata(i2c);
|
||||
|
||||
wm831x_device_exit(wm831x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(dev);
|
||||
@ -103,7 +94,6 @@ static const struct i2c_device_id wm831x_i2c_id[] = {
|
||||
{ "wm8326", WM8326 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
|
||||
|
||||
static const struct dev_pm_ops wm831x_pm_ops = {
|
||||
.suspend = wm831x_i2c_suspend,
|
||||
@ -115,9 +105,9 @@ static struct i2c_driver wm831x_i2c_driver = {
|
||||
.name = "wm831x",
|
||||
.pm = &wm831x_pm_ops,
|
||||
.of_match_table = of_match_ptr(wm831x_of_match),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = wm831x_i2c_probe,
|
||||
.remove = wm831x_i2c_remove,
|
||||
.id_table = wm831x_i2c_id,
|
||||
};
|
||||
|
||||
@ -132,9 +122,3 @@ static int __init wm831x_i2c_init(void)
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(wm831x_i2c_init);
|
||||
|
||||
static void __exit wm831x_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&wm831x_i2c_driver);
|
||||
}
|
||||
module_exit(wm831x_i2c_exit);
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm.h>
|
||||
@ -67,15 +67,6 @@ static int wm831x_spi_probe(struct spi_device *spi)
|
||||
return wm831x_device_init(wm831x, spi->irq);
|
||||
}
|
||||
|
||||
static int wm831x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct wm831x *wm831x = spi_get_drvdata(spi);
|
||||
|
||||
wm831x_device_exit(wm831x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_spi_suspend(struct device *dev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(dev);
|
||||
@ -108,17 +99,16 @@ static const struct spi_device_id wm831x_spi_ids[] = {
|
||||
{ "wm8326", WM8326 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, wm831x_spi_ids);
|
||||
|
||||
static struct spi_driver wm831x_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wm831x",
|
||||
.pm = &wm831x_spi_pm,
|
||||
.of_match_table = of_match_ptr(wm831x_of_match),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.id_table = wm831x_spi_ids,
|
||||
.probe = wm831x_spi_probe,
|
||||
.remove = wm831x_spi_remove,
|
||||
};
|
||||
|
||||
static int __init wm831x_spi_init(void)
|
||||
@ -132,13 +122,3 @@ static int __init wm831x_spi_init(void)
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(wm831x_spi_init);
|
||||
|
||||
static void __exit wm831x_spi_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&wm831x_spi_driver);
|
||||
}
|
||||
module_exit(wm831x_spi_exit);
|
||||
|
||||
MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mark Brown");
|
||||
|
@ -13,7 +13,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/device.h>
|
||||
@ -442,30 +443,3 @@ err:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm8350_device_init);
|
||||
|
||||
void wm8350_device_exit(struct wm8350 *wm8350)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8350->pmic.led); i++)
|
||||
platform_device_unregister(wm8350->pmic.led[i].pdev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
|
||||
platform_device_unregister(wm8350->pmic.pdev[i]);
|
||||
|
||||
platform_device_unregister(wm8350->wdt.pdev);
|
||||
platform_device_unregister(wm8350->rtc.pdev);
|
||||
platform_device_unregister(wm8350->power.pdev);
|
||||
platform_device_unregister(wm8350->hwmon.pdev);
|
||||
platform_device_unregister(wm8350->gpio.pdev);
|
||||
platform_device_unregister(wm8350->codec.pdev);
|
||||
|
||||
if (wm8350->irq_base)
|
||||
free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
|
||||
|
||||
wm8350_irq_exit(wm8350);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm8350_device_exit);
|
||||
|
||||
MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -13,8 +13,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -48,30 +46,19 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
|
||||
return wm8350_device_init(wm8350, i2c->irq, pdata);
|
||||
}
|
||||
|
||||
static int wm8350_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
|
||||
|
||||
wm8350_device_exit(wm8350);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id wm8350_i2c_id[] = {
|
||||
{ "wm8350", 0 },
|
||||
{ "wm8351", 0 },
|
||||
{ "wm8352", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
|
||||
|
||||
|
||||
static struct i2c_driver wm8350_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "wm8350",
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = wm8350_i2c_probe,
|
||||
.remove = wm8350_i2c_remove,
|
||||
.id_table = wm8350_i2c_id,
|
||||
};
|
||||
|
||||
@ -81,12 +68,3 @@ static int __init wm8350_i2c_init(void)
|
||||
}
|
||||
/* init early so consumer devices can complete system boot */
|
||||
subsys_initcall(wm8350_i2c_init);
|
||||
|
||||
static void __exit wm8350_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&wm8350_i2c_driver);
|
||||
}
|
||||
module_exit(wm8350_i2c_exit);
|
||||
|
||||
MODULE_DESCRIPTION("I2C support for the WM8350 AudioPlus PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -150,7 +150,6 @@ static const struct i2c_device_id wm8400_i2c_id[] = {
|
||||
{ "wm8400", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wm8400_i2c_id);
|
||||
|
||||
static struct i2c_driver wm8400_i2c_driver = {
|
||||
.driver = {
|
||||
@ -161,7 +160,7 @@ static struct i2c_driver wm8400_i2c_driver = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init wm8400_module_init(void)
|
||||
static int __init wm8400_driver_init(void)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
@ -173,15 +172,4 @@ static int __init wm8400_module_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(wm8400_module_init);
|
||||
|
||||
static void __exit wm8400_module_exit(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
i2c_del_driver(&wm8400_i2c_driver);
|
||||
#endif
|
||||
}
|
||||
module_exit(wm8400_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
subsys_initcall(wm8400_driver_init);
|
||||
|
@ -49,9 +49,6 @@ config CHROMEOS_TBMC
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called chromeos_tbmc.
|
||||
|
||||
config CROS_EC_CTL
|
||||
tristate
|
||||
|
||||
config CROS_EC_I2C
|
||||
tristate "ChromeOS Embedded Controller (I2C)"
|
||||
depends on MFD_CROS_EC && I2C
|
||||
@ -111,4 +108,48 @@ config CROS_KBD_LED_BACKLIGHT
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_kbd_led_backlight.
|
||||
|
||||
config CROS_EC_LIGHTBAR
|
||||
tristate "Chromebook Pixel's lightbar support"
|
||||
depends on MFD_CROS_EC_CHARDEV
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
help
|
||||
This option exposes the Chromebook Pixel's lightbar to
|
||||
userspace.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_lightbar.
|
||||
|
||||
config CROS_EC_VBC
|
||||
tristate "ChromeOS EC vboot context support"
|
||||
depends on MFD_CROS_EC_CHARDEV && OF
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
help
|
||||
This option exposes the ChromeOS EC vboot context nvram to
|
||||
userspace.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_vbc.
|
||||
|
||||
config CROS_EC_DEBUGFS
|
||||
tristate "Export ChromeOS EC internals in DebugFS"
|
||||
depends on MFD_CROS_EC_CHARDEV && DEBUG_FS
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
help
|
||||
This option exposes the ChromeOS EC device internals to
|
||||
userspace.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_debugfs.
|
||||
|
||||
config CROS_EC_SYSFS
|
||||
tristate "ChromeOS EC control and information through sysfs"
|
||||
depends on MFD_CROS_EC_CHARDEV && SYSFS
|
||||
default MFD_CROS_EC_CHARDEV
|
||||
help
|
||||
This option exposes some sysfs attributes to control and get
|
||||
information from ChromeOS EC.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_sysfs.
|
||||
|
||||
endif # CHROMEOS_PLATFORMS
|
||||
|
@ -3,9 +3,6 @@
|
||||
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
|
||||
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
|
||||
obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
|
||||
cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \
|
||||
cros_ec_vbc.o cros_ec_debugfs.o
|
||||
obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o
|
||||
obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
|
||||
cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_reg.o
|
||||
@ -13,3 +10,7 @@ cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
|
||||
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
|
||||
obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o
|
||||
obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o
|
||||
obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
|
||||
obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
|
||||
obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
|
||||
obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
|
||||
|
@ -23,12 +23,16 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-debugfs"
|
||||
|
||||
#define LOG_SHIFT 14
|
||||
#define LOG_SIZE (1 << LOG_SHIFT)
|
||||
#define LOG_POLL_SEC 10
|
||||
@ -423,8 +427,9 @@ static int cros_ec_create_pdinfo(struct cros_ec_debugfs *debug_info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cros_ec_debugfs_init(struct cros_ec_dev *ec)
|
||||
static int cros_ec_debugfs_probe(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent);
|
||||
struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev);
|
||||
const char *name = ec_platform->ec_name;
|
||||
struct cros_ec_debugfs *debug_info;
|
||||
@ -453,40 +458,57 @@ int cros_ec_debugfs_init(struct cros_ec_dev *ec)
|
||||
|
||||
ec->debug_info = debug_info;
|
||||
|
||||
dev_set_drvdata(&pd->dev, ec);
|
||||
|
||||
return 0;
|
||||
|
||||
remove_debugfs:
|
||||
debugfs_remove_recursive(debug_info->dir);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_debugfs_init);
|
||||
|
||||
void cros_ec_debugfs_remove(struct cros_ec_dev *ec)
|
||||
static int cros_ec_debugfs_remove(struct platform_device *pd)
|
||||
{
|
||||
if (!ec->debug_info)
|
||||
return;
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent);
|
||||
|
||||
debugfs_remove_recursive(ec->debug_info->dir);
|
||||
cros_ec_cleanup_console_log(ec->debug_info);
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_debugfs_remove);
|
||||
|
||||
void cros_ec_debugfs_suspend(struct cros_ec_dev *ec)
|
||||
{
|
||||
/*
|
||||
* cros_ec_debugfs_init() failures are non-fatal; it's also possible
|
||||
* that we initted things but decided that console log wasn't supported.
|
||||
* We'll use the same set of checks that cros_ec_debugfs_remove() +
|
||||
* cros_ec_cleanup_console_log() end up using to handle those cases.
|
||||
*/
|
||||
if (ec->debug_info && ec->debug_info->log_buffer.buf)
|
||||
cancel_delayed_work_sync(&ec->debug_info->log_poll_work);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_debugfs_suspend);
|
||||
|
||||
void cros_ec_debugfs_resume(struct cros_ec_dev *ec)
|
||||
static int __maybe_unused cros_ec_debugfs_suspend(struct device *dev)
|
||||
{
|
||||
if (ec->debug_info && ec->debug_info->log_buffer.buf)
|
||||
schedule_delayed_work(&ec->debug_info->log_poll_work, 0);
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev);
|
||||
|
||||
cancel_delayed_work_sync(&ec->debug_info->log_poll_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_debugfs_resume);
|
||||
|
||||
static int __maybe_unused cros_ec_debugfs_resume(struct device *dev)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev);
|
||||
|
||||
schedule_delayed_work(&ec->debug_info->log_poll_work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cros_ec_debugfs_pm_ops,
|
||||
cros_ec_debugfs_suspend, cros_ec_debugfs_resume);
|
||||
|
||||
static struct platform_driver cros_ec_debugfs_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &cros_ec_debugfs_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_debugfs_probe,
|
||||
.remove = cros_ec_debugfs_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(cros_ec_debugfs_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Debug logs for ChromeOS EC");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
|
@ -317,15 +317,6 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
|
||||
|
||||
cros_ec_remove(ec_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int cros_ec_i2c_suspend(struct device *dev)
|
||||
{
|
||||
@ -376,7 +367,6 @@ static struct i2c_driver cros_ec_driver = {
|
||||
.pm = &cros_ec_i2c_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_i2c_probe,
|
||||
.remove = cros_ec_i2c_remove,
|
||||
.id_table = cros_ec_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-lightbar"
|
||||
|
||||
/* Rate-limit the lightbar interface to prevent DoS. */
|
||||
static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
|
||||
|
||||
@ -41,7 +43,6 @@ static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
|
||||
* If this is true, we won't do anything during suspend/resume.
|
||||
*/
|
||||
static bool userspace_control;
|
||||
static struct cros_ec_dev *ec_with_lightbar;
|
||||
|
||||
static ssize_t interval_msec_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
@ -373,15 +374,12 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
|
||||
static int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
|
||||
{
|
||||
struct ec_params_lightbar *param;
|
||||
struct cros_ec_command *msg;
|
||||
int ret;
|
||||
|
||||
if (ec != ec_with_lightbar)
|
||||
return 0;
|
||||
|
||||
msg = alloc_lightbar_cmd_msg(ec);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
@ -408,25 +406,6 @@ error:
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lb_manual_suspend_ctrl);
|
||||
|
||||
int lb_suspend(struct cros_ec_dev *ec)
|
||||
{
|
||||
if (userspace_control || ec != ec_with_lightbar)
|
||||
return 0;
|
||||
|
||||
return lb_send_empty_cmd(ec, LIGHTBAR_CMD_SUSPEND);
|
||||
}
|
||||
EXPORT_SYMBOL(lb_suspend);
|
||||
|
||||
int lb_resume(struct cros_ec_dev *ec)
|
||||
{
|
||||
if (userspace_control || ec != ec_with_lightbar)
|
||||
return 0;
|
||||
|
||||
return lb_send_empty_cmd(ec, LIGHTBAR_CMD_RESUME);
|
||||
}
|
||||
EXPORT_SYMBOL(lb_resume);
|
||||
|
||||
static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
@ -584,36 +563,91 @@ static struct attribute *__lb_cmds_attrs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
bool ec_has_lightbar(struct cros_ec_dev *ec)
|
||||
{
|
||||
return !!get_lightbar_version(ec, NULL, NULL);
|
||||
}
|
||||
|
||||
static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct cros_ec_dev *ec = to_cros_ec_dev(dev);
|
||||
struct platform_device *pdev = to_platform_device(ec->dev);
|
||||
struct cros_ec_platform *pdata = pdev->dev.platform_data;
|
||||
int is_cros_ec;
|
||||
|
||||
is_cros_ec = strcmp(pdata->ec_name, CROS_EC_DEV_NAME);
|
||||
|
||||
if (is_cros_ec != 0)
|
||||
return 0;
|
||||
|
||||
/* Only instantiate this stuff if the EC has a lightbar */
|
||||
if (ec_has_lightbar(ec)) {
|
||||
ec_with_lightbar = ec;
|
||||
return a->mode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct attribute_group cros_ec_lightbar_attr_group = {
|
||||
.name = "lightbar",
|
||||
.attrs = __lb_cmds_attrs,
|
||||
.is_visible = cros_ec_lightbar_attrs_are_visible,
|
||||
};
|
||||
EXPORT_SYMBOL(cros_ec_lightbar_attr_group);
|
||||
|
||||
static int cros_ec_lightbar_probe(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
|
||||
struct cros_ec_platform *pdata = dev_get_platdata(ec_dev->dev);
|
||||
struct device *dev = &pd->dev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Only instantiate the lightbar if the EC name is 'cros_ec'. Other EC
|
||||
* devices like 'cros_pd' doesn't have a lightbar.
|
||||
*/
|
||||
if (strcmp(pdata->ec_name, CROS_EC_DEV_NAME) != 0)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Ask then for the lightbar version, if it's 0 then the 'cros_ec'
|
||||
* doesn't have a lightbar.
|
||||
*/
|
||||
if (!get_lightbar_version(ec_dev, NULL, NULL))
|
||||
return -ENODEV;
|
||||
|
||||
/* Take control of the lightbar from the EC. */
|
||||
lb_manual_suspend_ctrl(ec_dev, 1);
|
||||
|
||||
ret = sysfs_create_group(&ec_dev->class_dev.kobj,
|
||||
&cros_ec_lightbar_attr_group);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "failed to create %s attributes. err=%d\n",
|
||||
cros_ec_lightbar_attr_group.name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cros_ec_lightbar_remove(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
|
||||
|
||||
sysfs_remove_group(&ec_dev->class_dev.kobj,
|
||||
&cros_ec_lightbar_attr_group);
|
||||
|
||||
/* Let the EC take over the lightbar again. */
|
||||
lb_manual_suspend_ctrl(ec_dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused cros_ec_lightbar_resume(struct device *dev)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (userspace_control)
|
||||
return 0;
|
||||
|
||||
return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_RESUME);
|
||||
}
|
||||
|
||||
static int __maybe_unused cros_ec_lightbar_suspend(struct device *dev)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (userspace_control)
|
||||
return 0;
|
||||
|
||||
return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_SUSPEND);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cros_ec_lightbar_pm_ops,
|
||||
cros_ec_lightbar_suspend, cros_ec_lightbar_resume);
|
||||
|
||||
static struct platform_driver cros_ec_lightbar_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &cros_ec_lightbar_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_lightbar_probe,
|
||||
.remove = cros_ec_lightbar_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(cros_ec_lightbar_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Expose the Chromebook Pixel's lightbar to userspace");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
|
@ -327,7 +327,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
|
||||
|
||||
static int cros_ec_lpc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_device *ec_dev;
|
||||
struct acpi_device *adev;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
@ -335,9 +334,6 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
|
||||
acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
|
||||
cros_ec_lpc_acpi_notify);
|
||||
|
||||
ec_dev = platform_get_drvdata(pdev);
|
||||
cros_ec_remove(ec_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -685,16 +685,6 @@ static int cros_ec_spi_probe(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct cros_ec_device *ec_dev;
|
||||
|
||||
ec_dev = spi_get_drvdata(spi);
|
||||
cros_ec_remove(ec_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int cros_ec_spi_suspend(struct device *dev)
|
||||
{
|
||||
@ -733,7 +723,6 @@ static struct spi_driver cros_ec_driver_spi = {
|
||||
.pm = &cros_ec_spi_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_spi_probe,
|
||||
.remove = cros_ec_spi_remove,
|
||||
.id_table = cros_ec_spi_id,
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-sysfs"
|
||||
|
||||
/* Accessor functions */
|
||||
|
||||
static ssize_t reboot_show(struct device *dev,
|
||||
@ -353,7 +355,39 @@ struct attribute_group cros_ec_attr_group = {
|
||||
.attrs = __ec_attrs,
|
||||
.is_visible = cros_ec_ctrl_visible,
|
||||
};
|
||||
EXPORT_SYMBOL(cros_ec_attr_group);
|
||||
|
||||
static int cros_ec_sysfs_probe(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
|
||||
struct device *dev = &pd->dev;
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "failed to create attributes. err=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cros_ec_sysfs_remove(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
|
||||
|
||||
sysfs_remove_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cros_ec_sysfs_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = cros_ec_sysfs_probe,
|
||||
.remove = cros_ec_sysfs_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(cros_ec_sysfs_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("ChromeOS EC control driver");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
|
@ -22,8 +22,11 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-vbc"
|
||||
|
||||
static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *att, char *buf,
|
||||
loff_t pos, size_t count)
|
||||
@ -105,21 +108,6 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
|
||||
return data_sz;
|
||||
}
|
||||
|
||||
static umode_t cros_ec_vbc_is_visible(struct kobject *kobj,
|
||||
struct bin_attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct cros_ec_dev *ec = to_cros_ec_dev(dev);
|
||||
struct device_node *np = ec->ec_dev->dev->of_node;
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF) && np) {
|
||||
if (of_property_read_bool(np, "google,has-vbc-nvram"))
|
||||
return a->attr.mode;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BIN_ATTR_RW(vboot_context, 16);
|
||||
|
||||
static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
|
||||
@ -130,6 +118,43 @@ static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
|
||||
struct attribute_group cros_ec_vbc_attr_group = {
|
||||
.name = "vbc",
|
||||
.bin_attrs = cros_ec_vbc_bin_attrs,
|
||||
.is_bin_visible = cros_ec_vbc_is_visible,
|
||||
};
|
||||
EXPORT_SYMBOL(cros_ec_vbc_attr_group);
|
||||
|
||||
static int cros_ec_vbc_probe(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
|
||||
struct device *dev = &pd->dev;
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_group(&ec_dev->class_dev.kobj,
|
||||
&cros_ec_vbc_attr_group);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "failed to create %s attributes. err=%d\n",
|
||||
cros_ec_vbc_attr_group.name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cros_ec_vbc_remove(struct platform_device *pd)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
|
||||
|
||||
sysfs_remove_group(&ec_dev->class_dev.kobj,
|
||||
&cros_ec_vbc_attr_group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cros_ec_vbc_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = cros_ec_vbc_probe,
|
||||
.remove = cros_ec_vbc_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(cros_ec_vbc_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Expose the vboot context nvram to userspace");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
|
@ -817,6 +817,18 @@ config STM32_WATCHDOG
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stm32_iwdg.
|
||||
|
||||
config STPMIC1_WATCHDOG
|
||||
tristate "STPMIC1 PMIC watchdog support"
|
||||
depends on MFD_STPMIC1
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
Say Y here to include watchdog support embedded into STPMIC1 PMIC.
|
||||
If the watchdog timer expires, stpmic1 will shut down all its power
|
||||
supplies.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called spmic1_wdt.
|
||||
|
||||
config UNIPHIER_WATCHDOG
|
||||
tristate "UniPhier watchdog support"
|
||||
depends on ARCH_UNIPHIER || COMPILE_TEST
|
||||
|
@ -220,3 +220,4 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
|
||||
obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
|
||||
obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
|
||||
obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
|
||||
obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
|
||||
|
139
drivers/watchdog/stpmic1_wdt.c
Normal file
139
drivers/watchdog/stpmic1_wdt.c
Normal file
@ -0,0 +1,139 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) STMicroelectronics 2018
|
||||
// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/stpmic1.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
/* WATCHDOG CONTROL REGISTER bit */
|
||||
#define WDT_START BIT(0)
|
||||
#define WDT_PING BIT(1)
|
||||
#define WDT_START_MASK BIT(0)
|
||||
#define WDT_PING_MASK BIT(1)
|
||||
#define WDT_STOP 0
|
||||
|
||||
#define PMIC_WDT_MIN_TIMEOUT 1
|
||||
#define PMIC_WDT_MAX_TIMEOUT 256
|
||||
#define PMIC_WDT_DEFAULT_TIMEOUT 30
|
||||
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
module_param(nowayout, bool, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
struct stpmic1_wdt {
|
||||
struct stpmic1 *pmic;
|
||||
struct watchdog_device wdtdev;
|
||||
};
|
||||
|
||||
static int pmic_wdt_start(struct watchdog_device *wdd)
|
||||
{
|
||||
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
return regmap_update_bits(wdt->pmic->regmap,
|
||||
WCHDG_CR, WDT_START_MASK, WDT_START);
|
||||
}
|
||||
|
||||
static int pmic_wdt_stop(struct watchdog_device *wdd)
|
||||
{
|
||||
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
return regmap_update_bits(wdt->pmic->regmap,
|
||||
WCHDG_CR, WDT_START_MASK, WDT_STOP);
|
||||
}
|
||||
|
||||
static int pmic_wdt_ping(struct watchdog_device *wdd)
|
||||
{
|
||||
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
return regmap_update_bits(wdt->pmic->regmap,
|
||||
WCHDG_CR, WDT_PING_MASK, WDT_PING);
|
||||
}
|
||||
|
||||
static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
unsigned int timeout)
|
||||
{
|
||||
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
wdd->timeout = timeout;
|
||||
/* timeout is equal to register value + 1 */
|
||||
return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1);
|
||||
}
|
||||
|
||||
static const struct watchdog_info pmic_watchdog_info = {
|
||||
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
|
||||
.identity = "STPMIC1 PMIC Watchdog",
|
||||
};
|
||||
|
||||
static const struct watchdog_ops pmic_watchdog_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = pmic_wdt_start,
|
||||
.stop = pmic_wdt_stop,
|
||||
.ping = pmic_wdt_ping,
|
||||
.set_timeout = pmic_wdt_set_timeout,
|
||||
};
|
||||
|
||||
static int pmic_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct stpmic1 *pmic;
|
||||
struct stpmic1_wdt *wdt;
|
||||
|
||||
if (!pdev->dev.parent)
|
||||
return -EINVAL;
|
||||
|
||||
pmic = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!pmic)
|
||||
return -EINVAL;
|
||||
|
||||
wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_wdt), GFP_KERNEL);
|
||||
if (!wdt)
|
||||
return -ENOMEM;
|
||||
|
||||
wdt->pmic = pmic;
|
||||
|
||||
wdt->wdtdev.info = &pmic_watchdog_info;
|
||||
wdt->wdtdev.ops = &pmic_watchdog_ops;
|
||||
wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
|
||||
wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
|
||||
wdt->wdtdev.parent = &pdev->dev;
|
||||
|
||||
wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
|
||||
watchdog_init_timeout(&wdt->wdtdev, 0, &pdev->dev);
|
||||
|
||||
watchdog_set_nowayout(&wdt->wdtdev, nowayout);
|
||||
watchdog_set_drvdata(&wdt->wdtdev, wdt);
|
||||
|
||||
ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_pmic_wdt_match[] = {
|
||||
{ .compatible = "st,stpmic1-wdt" },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
|
||||
|
||||
static struct platform_driver stpmic1_wdt_driver = {
|
||||
.probe = pmic_wdt_probe,
|
||||
.driver = {
|
||||
.name = "stpmic1-wdt",
|
||||
.of_match_table = of_pmic_wdt_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(stpmic1_wdt_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Watchdog driver for STPMIC1 device");
|
||||
MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
26
include/dt-bindings/clk/lochnagar.h
Normal file
26
include/dt-bindings/clk/lochnagar.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Device Tree defines for Lochnagar clocking
|
||||
*
|
||||
* Copyright (c) 2017-2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#ifndef DT_BINDINGS_CLK_LOCHNAGAR_H
|
||||
#define DT_BINDINGS_CLK_LOCHNAGAR_H
|
||||
|
||||
#define LOCHNAGAR_CDC_MCLK1 0
|
||||
#define LOCHNAGAR_CDC_MCLK2 1
|
||||
#define LOCHNAGAR_DSP_CLKIN 2
|
||||
#define LOCHNAGAR_GF_CLKOUT1 3
|
||||
#define LOCHNAGAR_GF_CLKOUT2 4
|
||||
#define LOCHNAGAR_PSIA1_MCLK 5
|
||||
#define LOCHNAGAR_PSIA2_MCLK 6
|
||||
#define LOCHNAGAR_SPDIF_MCLK 7
|
||||
#define LOCHNAGAR_ADAT_MCLK 8
|
||||
#define LOCHNAGAR_SOUNDCARD_MCLK 9
|
||||
#define LOCHNAGAR_SPDIF_CLKOUT 10
|
||||
|
||||
#endif
|
50
include/dt-bindings/mfd/st,stpmic1.h
Normal file
50
include/dt-bindings/mfd/st,stpmic1.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
* Author: Philippe Peurichard <philippe.peurichard@st.com>,
|
||||
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_STPMIC1_H__
|
||||
#define __DT_BINDINGS_STPMIC1_H__
|
||||
|
||||
/* IRQ definitions */
|
||||
#define IT_PONKEY_F 0
|
||||
#define IT_PONKEY_R 1
|
||||
#define IT_WAKEUP_F 2
|
||||
#define IT_WAKEUP_R 3
|
||||
#define IT_VBUS_OTG_F 4
|
||||
#define IT_VBUS_OTG_R 5
|
||||
#define IT_SWOUT_F 6
|
||||
#define IT_SWOUT_R 7
|
||||
|
||||
#define IT_CURLIM_BUCK1 8
|
||||
#define IT_CURLIM_BUCK2 9
|
||||
#define IT_CURLIM_BUCK3 10
|
||||
#define IT_CURLIM_BUCK4 11
|
||||
#define IT_OCP_OTG 12
|
||||
#define IT_OCP_SWOUT 13
|
||||
#define IT_OCP_BOOST 14
|
||||
#define IT_OVP_BOOST 15
|
||||
|
||||
#define IT_CURLIM_LDO1 16
|
||||
#define IT_CURLIM_LDO2 17
|
||||
#define IT_CURLIM_LDO3 18
|
||||
#define IT_CURLIM_LDO4 19
|
||||
#define IT_CURLIM_LDO5 20
|
||||
#define IT_CURLIM_LDO6 21
|
||||
#define IT_SHORT_SWOTG 22
|
||||
#define IT_SHORT_SWOUT 23
|
||||
|
||||
#define IT_TWARN_F 24
|
||||
#define IT_TWARN_R 25
|
||||
#define IT_VINLOW_F 26
|
||||
#define IT_VINLOW_R 27
|
||||
#define IT_SWIN_F 30
|
||||
#define IT_SWIN_R 31
|
||||
|
||||
/* BUCK MODES definitions */
|
||||
#define STPMIC1_BUCK_MODE_NORMAL 0
|
||||
#define STPMIC1_BUCK_MODE_LP 2
|
||||
|
||||
#endif /* __DT_BINDINGS_STPMIC1_H__ */
|
132
include/dt-bindings/pinctrl/lochnagar.h
Normal file
132
include/dt-bindings/pinctrl/lochnagar.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Device Tree defines for Lochnagar pinctrl
|
||||
*
|
||||
* Copyright (c) 2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#ifndef DT_BINDINGS_PINCTRL_LOCHNAGAR_H
|
||||
#define DT_BINDINGS_PINCTRL_LOCHNAGAR_H
|
||||
|
||||
#define LOCHNAGAR1_PIN_CDC_RESET 0
|
||||
#define LOCHNAGAR1_PIN_DSP_RESET 1
|
||||
#define LOCHNAGAR1_PIN_CDC_CIF1MODE 2
|
||||
#define LOCHNAGAR1_PIN_NUM_GPIOS 3
|
||||
|
||||
#define LOCHNAGAR2_PIN_CDC_RESET 0
|
||||
#define LOCHNAGAR2_PIN_DSP_RESET 1
|
||||
#define LOCHNAGAR2_PIN_CDC_CIF1MODE 2
|
||||
#define LOCHNAGAR2_PIN_CDC_LDOENA 3
|
||||
#define LOCHNAGAR2_PIN_SPDIF_HWMODE 4
|
||||
#define LOCHNAGAR2_PIN_SPDIF_RESET 5
|
||||
#define LOCHNAGAR2_PIN_FPGA_GPIO1 6
|
||||
#define LOCHNAGAR2_PIN_FPGA_GPIO2 7
|
||||
#define LOCHNAGAR2_PIN_FPGA_GPIO3 8
|
||||
#define LOCHNAGAR2_PIN_FPGA_GPIO4 9
|
||||
#define LOCHNAGAR2_PIN_FPGA_GPIO5 10
|
||||
#define LOCHNAGAR2_PIN_FPGA_GPIO6 11
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO1 12
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO2 13
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO3 14
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO4 15
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO5 16
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO6 17
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO7 18
|
||||
#define LOCHNAGAR2_PIN_CDC_GPIO8 19
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO1 20
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO2 21
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO3 22
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO4 23
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO5 24
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO6 25
|
||||
#define LOCHNAGAR2_PIN_GF_GPIO2 26
|
||||
#define LOCHNAGAR2_PIN_GF_GPIO3 27
|
||||
#define LOCHNAGAR2_PIN_GF_GPIO7 28
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF1_BCLK 29
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF1_RXDAT 30
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF1_LRCLK 31
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF1_TXDAT 32
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF2_BCLK 33
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF2_RXDAT 34
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF2_LRCLK 35
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF2_TXDAT 36
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF3_BCLK 37
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF3_RXDAT 38
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF3_LRCLK 39
|
||||
#define LOCHNAGAR2_PIN_CDC_AIF3_TXDAT 40
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF1_BCLK 41
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF1_RXDAT 42
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF1_LRCLK 43
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF1_TXDAT 44
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF2_BCLK 45
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF2_RXDAT 46
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF2_LRCLK 47
|
||||
#define LOCHNAGAR2_PIN_DSP_AIF2_TXDAT 48
|
||||
#define LOCHNAGAR2_PIN_PSIA1_BCLK 49
|
||||
#define LOCHNAGAR2_PIN_PSIA1_RXDAT 50
|
||||
#define LOCHNAGAR2_PIN_PSIA1_LRCLK 51
|
||||
#define LOCHNAGAR2_PIN_PSIA1_TXDAT 52
|
||||
#define LOCHNAGAR2_PIN_PSIA2_BCLK 53
|
||||
#define LOCHNAGAR2_PIN_PSIA2_RXDAT 54
|
||||
#define LOCHNAGAR2_PIN_PSIA2_LRCLK 55
|
||||
#define LOCHNAGAR2_PIN_PSIA2_TXDAT 56
|
||||
#define LOCHNAGAR2_PIN_GF_AIF3_BCLK 57
|
||||
#define LOCHNAGAR2_PIN_GF_AIF3_RXDAT 58
|
||||
#define LOCHNAGAR2_PIN_GF_AIF3_LRCLK 59
|
||||
#define LOCHNAGAR2_PIN_GF_AIF3_TXDAT 60
|
||||
#define LOCHNAGAR2_PIN_GF_AIF4_BCLK 61
|
||||
#define LOCHNAGAR2_PIN_GF_AIF4_RXDAT 62
|
||||
#define LOCHNAGAR2_PIN_GF_AIF4_LRCLK 63
|
||||
#define LOCHNAGAR2_PIN_GF_AIF4_TXDAT 64
|
||||
#define LOCHNAGAR2_PIN_GF_AIF1_BCLK 65
|
||||
#define LOCHNAGAR2_PIN_GF_AIF1_RXDAT 66
|
||||
#define LOCHNAGAR2_PIN_GF_AIF1_LRCLK 67
|
||||
#define LOCHNAGAR2_PIN_GF_AIF1_TXDAT 68
|
||||
#define LOCHNAGAR2_PIN_GF_AIF2_BCLK 69
|
||||
#define LOCHNAGAR2_PIN_GF_AIF2_RXDAT 70
|
||||
#define LOCHNAGAR2_PIN_GF_AIF2_LRCLK 71
|
||||
#define LOCHNAGAR2_PIN_GF_AIF2_TXDAT 72
|
||||
#define LOCHNAGAR2_PIN_DSP_UART1_RX 73
|
||||
#define LOCHNAGAR2_PIN_DSP_UART1_TX 74
|
||||
#define LOCHNAGAR2_PIN_DSP_UART2_RX 75
|
||||
#define LOCHNAGAR2_PIN_DSP_UART2_TX 76
|
||||
#define LOCHNAGAR2_PIN_GF_UART2_RX 77
|
||||
#define LOCHNAGAR2_PIN_GF_UART2_TX 78
|
||||
#define LOCHNAGAR2_PIN_USB_UART_RX 79
|
||||
#define LOCHNAGAR2_PIN_CDC_PDMCLK1 80
|
||||
#define LOCHNAGAR2_PIN_CDC_PDMDAT1 81
|
||||
#define LOCHNAGAR2_PIN_CDC_PDMCLK2 82
|
||||
#define LOCHNAGAR2_PIN_CDC_PDMDAT2 83
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICCLK1 84
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICDAT1 85
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICCLK2 86
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICDAT2 87
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICCLK3 88
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICDAT3 89
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICCLK4 90
|
||||
#define LOCHNAGAR2_PIN_CDC_DMICDAT4 91
|
||||
#define LOCHNAGAR2_PIN_DSP_DMICCLK1 92
|
||||
#define LOCHNAGAR2_PIN_DSP_DMICDAT1 93
|
||||
#define LOCHNAGAR2_PIN_DSP_DMICCLK2 94
|
||||
#define LOCHNAGAR2_PIN_DSP_DMICDAT2 95
|
||||
#define LOCHNAGAR2_PIN_I2C2_SCL 96
|
||||
#define LOCHNAGAR2_PIN_I2C2_SDA 97
|
||||
#define LOCHNAGAR2_PIN_I2C3_SCL 98
|
||||
#define LOCHNAGAR2_PIN_I2C3_SDA 99
|
||||
#define LOCHNAGAR2_PIN_I2C4_SCL 100
|
||||
#define LOCHNAGAR2_PIN_I2C4_SDA 101
|
||||
#define LOCHNAGAR2_PIN_DSP_STANDBY 102
|
||||
#define LOCHNAGAR2_PIN_CDC_MCLK1 103
|
||||
#define LOCHNAGAR2_PIN_CDC_MCLK2 104
|
||||
#define LOCHNAGAR2_PIN_DSP_CLKIN 105
|
||||
#define LOCHNAGAR2_PIN_PSIA1_MCLK 106
|
||||
#define LOCHNAGAR2_PIN_PSIA2_MCLK 107
|
||||
#define LOCHNAGAR2_PIN_GF_GPIO1 108
|
||||
#define LOCHNAGAR2_PIN_GF_GPIO5 109
|
||||
#define LOCHNAGAR2_PIN_DSP_GPIO20 110
|
||||
#define LOCHNAGAR2_PIN_NUM_GPIOS 111
|
||||
|
||||
#endif
|
@ -281,16 +281,6 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
|
||||
int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg);
|
||||
|
||||
/**
|
||||
* cros_ec_remove() - Remove a ChromeOS EC.
|
||||
* @ec_dev: Device to register.
|
||||
*
|
||||
* Call this to deregister a ChromeOS EC, then clean up any private data.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int cros_ec_remove(struct cros_ec_device *ec_dev);
|
||||
|
||||
/**
|
||||
* cros_ec_register() - Register a new ChromeOS EC, using the provided info.
|
||||
* @ec_dev: Device to register.
|
||||
@ -335,15 +325,4 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
|
||||
*/
|
||||
u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
|
||||
|
||||
/* sysfs stuff */
|
||||
extern struct attribute_group cros_ec_attr_group;
|
||||
extern struct attribute_group cros_ec_lightbar_attr_group;
|
||||
extern struct attribute_group cros_ec_vbc_attr_group;
|
||||
|
||||
/* debugfs stuff */
|
||||
int cros_ec_debugfs_init(struct cros_ec_dev *ec);
|
||||
void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
|
||||
void cros_ec_debugfs_suspend(struct cros_ec_dev *ec);
|
||||
void cros_ec_debugfs_resume(struct cros_ec_dev *ec);
|
||||
|
||||
#endif /* __LINUX_MFD_CROS_EC_H */
|
||||
|
55
include/linux/mfd/lochnagar.h
Normal file
55
include/linux/mfd/lochnagar.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Lochnagar internals
|
||||
*
|
||||
* Copyright (c) 2013-2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#ifndef CIRRUS_LOCHNAGAR_H
|
||||
#define CIRRUS_LOCHNAGAR_H
|
||||
|
||||
enum lochnagar_type {
|
||||
LOCHNAGAR1,
|
||||
LOCHNAGAR2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct lochnagar - Core data for the Lochnagar audio board driver.
|
||||
*
|
||||
* @type: The type of Lochnagar device connected.
|
||||
* @dev: A pointer to the struct device for the main MFD.
|
||||
* @regmap: The devices main register map.
|
||||
* @analogue_config_lock: Lock used to protect updates in the analogue
|
||||
* configuration as these must not be changed whilst the hardware is processing
|
||||
* the last update.
|
||||
*/
|
||||
struct lochnagar {
|
||||
enum lochnagar_type type;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
|
||||
/* Lock to protect updates to the analogue configuration */
|
||||
struct mutex analogue_config_lock;
|
||||
};
|
||||
|
||||
/* Register Addresses */
|
||||
#define LOCHNAGAR_SOFTWARE_RESET 0x00
|
||||
#define LOCHNAGAR_FIRMWARE_ID1 0x01
|
||||
#define LOCHNAGAR_FIRMWARE_ID2 0x02
|
||||
|
||||
/* (0x0000) Software Reset */
|
||||
#define LOCHNAGAR_DEVICE_ID_MASK 0xFFFC
|
||||
#define LOCHNAGAR_DEVICE_ID_SHIFT 2
|
||||
#define LOCHNAGAR_REV_ID_MASK 0x0003
|
||||
#define LOCHNAGAR_REV_ID_SHIFT 0
|
||||
|
||||
int lochnagar_update_config(struct lochnagar *lochnagar);
|
||||
|
||||
#endif
|
157
include/linux/mfd/lochnagar1_regs.h
Normal file
157
include/linux/mfd/lochnagar1_regs.h
Normal file
@ -0,0 +1,157 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Lochnagar1 register definitions
|
||||
*
|
||||
* Copyright (c) 2017-2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#ifndef LOCHNAGAR1_REGISTERS_H
|
||||
#define LOCHNAGAR1_REGISTERS_H
|
||||
|
||||
/* Register Addresses */
|
||||
#define LOCHNAGAR1_CDC_AIF1_SEL 0x0008
|
||||
#define LOCHNAGAR1_CDC_AIF2_SEL 0x0009
|
||||
#define LOCHNAGAR1_CDC_AIF3_SEL 0x000A
|
||||
#define LOCHNAGAR1_CDC_MCLK1_SEL 0x000B
|
||||
#define LOCHNAGAR1_CDC_MCLK2_SEL 0x000C
|
||||
#define LOCHNAGAR1_CDC_AIF_CTRL1 0x000D
|
||||
#define LOCHNAGAR1_CDC_AIF_CTRL2 0x000E
|
||||
#define LOCHNAGAR1_EXT_AIF_CTRL 0x000F
|
||||
#define LOCHNAGAR1_DSP_AIF1_SEL 0x0010
|
||||
#define LOCHNAGAR1_DSP_AIF2_SEL 0x0011
|
||||
#define LOCHNAGAR1_DSP_CLKIN_SEL 0x0012
|
||||
#define LOCHNAGAR1_DSP_AIF 0x0013
|
||||
#define LOCHNAGAR1_GF_AIF1 0x0014
|
||||
#define LOCHNAGAR1_GF_AIF2 0x0015
|
||||
#define LOCHNAGAR1_PSIA_AIF 0x0016
|
||||
#define LOCHNAGAR1_PSIA1_SEL 0x0017
|
||||
#define LOCHNAGAR1_PSIA2_SEL 0x0018
|
||||
#define LOCHNAGAR1_SPDIF_AIF_SEL 0x0019
|
||||
#define LOCHNAGAR1_GF_AIF3_SEL 0x001C
|
||||
#define LOCHNAGAR1_GF_AIF4_SEL 0x001D
|
||||
#define LOCHNAGAR1_GF_CLKOUT1_SEL 0x001E
|
||||
#define LOCHNAGAR1_GF_AIF1_SEL 0x001F
|
||||
#define LOCHNAGAR1_GF_AIF2_SEL 0x0020
|
||||
#define LOCHNAGAR1_GF_GPIO2 0x0026
|
||||
#define LOCHNAGAR1_GF_GPIO3 0x0027
|
||||
#define LOCHNAGAR1_GF_GPIO7 0x0028
|
||||
#define LOCHNAGAR1_RST 0x0029
|
||||
#define LOCHNAGAR1_LED1 0x002A
|
||||
#define LOCHNAGAR1_LED2 0x002B
|
||||
#define LOCHNAGAR1_I2C_CTRL 0x0046
|
||||
|
||||
/*
|
||||
* (0x0008 - 0x000C, 0x0010 - 0x0012, 0x0017 - 0x0020)
|
||||
* CDC_AIF1_SEL - GF_AIF2_SEL
|
||||
*/
|
||||
#define LOCHNAGAR1_SRC_MASK 0xFF
|
||||
#define LOCHNAGAR1_SRC_SHIFT 0
|
||||
|
||||
/* (0x000D) CDC_AIF_CTRL1 */
|
||||
#define LOCHNAGAR1_CDC_AIF2_LRCLK_DIR_MASK 0x40
|
||||
#define LOCHNAGAR1_CDC_AIF2_LRCLK_DIR_SHIFT 6
|
||||
#define LOCHNAGAR1_CDC_AIF2_BCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_CDC_AIF2_BCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_CDC_AIF2_ENA_MASK 0x10
|
||||
#define LOCHNAGAR1_CDC_AIF2_ENA_SHIFT 4
|
||||
#define LOCHNAGAR1_CDC_AIF1_LRCLK_DIR_MASK 0x04
|
||||
#define LOCHNAGAR1_CDC_AIF1_LRCLK_DIR_SHIFT 2
|
||||
#define LOCHNAGAR1_CDC_AIF1_BCLK_DIR_MASK 0x02
|
||||
#define LOCHNAGAR1_CDC_AIF1_BCLK_DIR_SHIFT 1
|
||||
#define LOCHNAGAR1_CDC_AIF1_ENA_MASK 0x01
|
||||
#define LOCHNAGAR1_CDC_AIF1_ENA_SHIFT 0
|
||||
|
||||
/* (0x000E) CDC_AIF_CTRL2 */
|
||||
#define LOCHNAGAR1_CDC_AIF3_LRCLK_DIR_MASK 0x40
|
||||
#define LOCHNAGAR1_CDC_AIF3_LRCLK_DIR_SHIFT 6
|
||||
#define LOCHNAGAR1_CDC_AIF3_BCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_CDC_AIF3_BCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_CDC_AIF3_ENA_MASK 0x10
|
||||
#define LOCHNAGAR1_CDC_AIF3_ENA_SHIFT 4
|
||||
#define LOCHNAGAR1_CDC_MCLK1_ENA_MASK 0x02
|
||||
#define LOCHNAGAR1_CDC_MCLK1_ENA_SHIFT 1
|
||||
#define LOCHNAGAR1_CDC_MCLK2_ENA_MASK 0x01
|
||||
#define LOCHNAGAR1_CDC_MCLK2_ENA_SHIFT 0
|
||||
|
||||
/* (0x000F) EXT_AIF_CTRL */
|
||||
#define LOCHNAGAR1_SPDIF_AIF_LRCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_SPDIF_AIF_LRCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_SPDIF_AIF_BCLK_DIR_MASK 0x10
|
||||
#define LOCHNAGAR1_SPDIF_AIF_BCLK_DIR_SHIFT 4
|
||||
#define LOCHNAGAR1_SPDIF_AIF_ENA_MASK 0x08
|
||||
#define LOCHNAGAR1_SPDIF_AIF_ENA_SHIFT 3
|
||||
|
||||
/* (0x0013) DSP_AIF */
|
||||
#define LOCHNAGAR1_DSP_AIF2_LRCLK_DIR_MASK 0x40
|
||||
#define LOCHNAGAR1_DSP_AIF2_LRCLK_DIR_SHIFT 6
|
||||
#define LOCHNAGAR1_DSP_AIF2_BCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_DSP_AIF2_BCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_DSP_AIF2_ENA_MASK 0x10
|
||||
#define LOCHNAGAR1_DSP_AIF2_ENA_SHIFT 4
|
||||
#define LOCHNAGAR1_DSP_CLKIN_ENA_MASK 0x08
|
||||
#define LOCHNAGAR1_DSP_CLKIN_ENA_SHIFT 3
|
||||
#define LOCHNAGAR1_DSP_AIF1_LRCLK_DIR_MASK 0x04
|
||||
#define LOCHNAGAR1_DSP_AIF1_LRCLK_DIR_SHIFT 2
|
||||
#define LOCHNAGAR1_DSP_AIF1_BCLK_DIR_MASK 0x02
|
||||
#define LOCHNAGAR1_DSP_AIF1_BCLK_DIR_SHIFT 1
|
||||
#define LOCHNAGAR1_DSP_AIF1_ENA_MASK 0x01
|
||||
#define LOCHNAGAR1_DSP_AIF1_ENA_SHIFT 0
|
||||
|
||||
/* (0x0014) GF_AIF1 */
|
||||
#define LOCHNAGAR1_GF_CLKOUT1_ENA_MASK 0x40
|
||||
#define LOCHNAGAR1_GF_CLKOUT1_ENA_SHIFT 6
|
||||
#define LOCHNAGAR1_GF_AIF3_LRCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_GF_AIF3_LRCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_GF_AIF3_BCLK_DIR_MASK 0x10
|
||||
#define LOCHNAGAR1_GF_AIF3_BCLK_DIR_SHIFT 4
|
||||
#define LOCHNAGAR1_GF_AIF3_ENA_MASK 0x08
|
||||
#define LOCHNAGAR1_GF_AIF3_ENA_SHIFT 3
|
||||
#define LOCHNAGAR1_GF_AIF1_LRCLK_DIR_MASK 0x04
|
||||
#define LOCHNAGAR1_GF_AIF1_LRCLK_DIR_SHIFT 2
|
||||
#define LOCHNAGAR1_GF_AIF1_BCLK_DIR_MASK 0x02
|
||||
#define LOCHNAGAR1_GF_AIF1_BCLK_DIR_SHIFT 1
|
||||
#define LOCHNAGAR1_GF_AIF1_ENA_MASK 0x01
|
||||
#define LOCHNAGAR1_GF_AIF1_ENA_SHIFT 0
|
||||
|
||||
/* (0x0015) GF_AIF2 */
|
||||
#define LOCHNAGAR1_GF_AIF4_LRCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_GF_AIF4_LRCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_GF_AIF4_BCLK_DIR_MASK 0x10
|
||||
#define LOCHNAGAR1_GF_AIF4_BCLK_DIR_SHIFT 4
|
||||
#define LOCHNAGAR1_GF_AIF4_ENA_MASK 0x08
|
||||
#define LOCHNAGAR1_GF_AIF4_ENA_SHIFT 3
|
||||
#define LOCHNAGAR1_GF_AIF2_LRCLK_DIR_MASK 0x04
|
||||
#define LOCHNAGAR1_GF_AIF2_LRCLK_DIR_SHIFT 2
|
||||
#define LOCHNAGAR1_GF_AIF2_BCLK_DIR_MASK 0x02
|
||||
#define LOCHNAGAR1_GF_AIF2_BCLK_DIR_SHIFT 1
|
||||
#define LOCHNAGAR1_GF_AIF2_ENA_MASK 0x01
|
||||
#define LOCHNAGAR1_GF_AIF2_ENA_SHIFT 0
|
||||
|
||||
/* (0x0016) PSIA_AIF */
|
||||
#define LOCHNAGAR1_PSIA2_LRCLK_DIR_MASK 0x40
|
||||
#define LOCHNAGAR1_PSIA2_LRCLK_DIR_SHIFT 6
|
||||
#define LOCHNAGAR1_PSIA2_BCLK_DIR_MASK 0x20
|
||||
#define LOCHNAGAR1_PSIA2_BCLK_DIR_SHIFT 5
|
||||
#define LOCHNAGAR1_PSIA2_ENA_MASK 0x10
|
||||
#define LOCHNAGAR1_PSIA2_ENA_SHIFT 4
|
||||
#define LOCHNAGAR1_PSIA1_LRCLK_DIR_MASK 0x04
|
||||
#define LOCHNAGAR1_PSIA1_LRCLK_DIR_SHIFT 2
|
||||
#define LOCHNAGAR1_PSIA1_BCLK_DIR_MASK 0x02
|
||||
#define LOCHNAGAR1_PSIA1_BCLK_DIR_SHIFT 1
|
||||
#define LOCHNAGAR1_PSIA1_ENA_MASK 0x01
|
||||
#define LOCHNAGAR1_PSIA1_ENA_SHIFT 0
|
||||
|
||||
/* (0x0029) RST */
|
||||
#define LOCHNAGAR1_DSP_RESET_MASK 0x02
|
||||
#define LOCHNAGAR1_DSP_RESET_SHIFT 1
|
||||
#define LOCHNAGAR1_CDC_RESET_MASK 0x01
|
||||
#define LOCHNAGAR1_CDC_RESET_SHIFT 0
|
||||
|
||||
/* (0x0046) I2C_CTRL */
|
||||
#define LOCHNAGAR1_CDC_CIF_MODE_MASK 0x01
|
||||
#define LOCHNAGAR1_CDC_CIF_MODE_SHIFT 0
|
||||
|
||||
#endif
|
291
include/linux/mfd/lochnagar2_regs.h
Normal file
291
include/linux/mfd/lochnagar2_regs.h
Normal file
@ -0,0 +1,291 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Lochnagar2 register definitions
|
||||
*
|
||||
* Copyright (c) 2017-2018 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#ifndef LOCHNAGAR2_REGISTERS_H
|
||||
#define LOCHNAGAR2_REGISTERS_H
|
||||
|
||||
/* Register Addresses */
|
||||
#define LOCHNAGAR2_CDC_AIF1_CTRL 0x000D
|
||||
#define LOCHNAGAR2_CDC_AIF2_CTRL 0x000E
|
||||
#define LOCHNAGAR2_CDC_AIF3_CTRL 0x000F
|
||||
#define LOCHNAGAR2_DSP_AIF1_CTRL 0x0010
|
||||
#define LOCHNAGAR2_DSP_AIF2_CTRL 0x0011
|
||||
#define LOCHNAGAR2_PSIA1_CTRL 0x0012
|
||||
#define LOCHNAGAR2_PSIA2_CTRL 0x0013
|
||||
#define LOCHNAGAR2_GF_AIF3_CTRL 0x0014
|
||||
#define LOCHNAGAR2_GF_AIF4_CTRL 0x0015
|
||||
#define LOCHNAGAR2_GF_AIF1_CTRL 0x0016
|
||||
#define LOCHNAGAR2_GF_AIF2_CTRL 0x0017
|
||||
#define LOCHNAGAR2_SPDIF_AIF_CTRL 0x0018
|
||||
#define LOCHNAGAR2_USB_AIF1_CTRL 0x0019
|
||||
#define LOCHNAGAR2_USB_AIF2_CTRL 0x001A
|
||||
#define LOCHNAGAR2_ADAT_AIF_CTRL 0x001B
|
||||
#define LOCHNAGAR2_CDC_MCLK1_CTRL 0x001E
|
||||
#define LOCHNAGAR2_CDC_MCLK2_CTRL 0x001F
|
||||
#define LOCHNAGAR2_DSP_CLKIN_CTRL 0x0020
|
||||
#define LOCHNAGAR2_PSIA1_MCLK_CTRL 0x0021
|
||||
#define LOCHNAGAR2_PSIA2_MCLK_CTRL 0x0022
|
||||
#define LOCHNAGAR2_SPDIF_MCLK_CTRL 0x0023
|
||||
#define LOCHNAGAR2_GF_CLKOUT1_CTRL 0x0024
|
||||
#define LOCHNAGAR2_GF_CLKOUT2_CTRL 0x0025
|
||||
#define LOCHNAGAR2_ADAT_MCLK_CTRL 0x0026
|
||||
#define LOCHNAGAR2_SOUNDCARD_MCLK_CTRL 0x0027
|
||||
#define LOCHNAGAR2_GPIO_FPGA_GPIO1 0x0031
|
||||
#define LOCHNAGAR2_GPIO_FPGA_GPIO2 0x0032
|
||||
#define LOCHNAGAR2_GPIO_FPGA_GPIO3 0x0033
|
||||
#define LOCHNAGAR2_GPIO_FPGA_GPIO4 0x0034
|
||||
#define LOCHNAGAR2_GPIO_FPGA_GPIO5 0x0035
|
||||
#define LOCHNAGAR2_GPIO_FPGA_GPIO6 0x0036
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO1 0x0037
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO2 0x0038
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO3 0x0039
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO4 0x003A
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO5 0x003B
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO6 0x003C
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO7 0x003D
|
||||
#define LOCHNAGAR2_GPIO_CDC_GPIO8 0x003E
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO1 0x003F
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO2 0x0040
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO3 0x0041
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO4 0x0042
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO5 0x0043
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO6 0x0044
|
||||
#define LOCHNAGAR2_GPIO_GF_GPIO2 0x0045
|
||||
#define LOCHNAGAR2_GPIO_GF_GPIO3 0x0046
|
||||
#define LOCHNAGAR2_GPIO_GF_GPIO7 0x0047
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF1_BCLK 0x0048
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF1_RXDAT 0x0049
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF1_LRCLK 0x004A
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF1_TXDAT 0x004B
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF2_BCLK 0x004C
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF2_RXDAT 0x004D
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF2_LRCLK 0x004E
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF2_TXDAT 0x004F
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF3_BCLK 0x0050
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF3_RXDAT 0x0051
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF3_LRCLK 0x0052
|
||||
#define LOCHNAGAR2_GPIO_CDC_AIF3_TXDAT 0x0053
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF1_BCLK 0x0054
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF1_RXDAT 0x0055
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF1_LRCLK 0x0056
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF1_TXDAT 0x0057
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF2_BCLK 0x0058
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF2_RXDAT 0x0059
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF2_LRCLK 0x005A
|
||||
#define LOCHNAGAR2_GPIO_DSP_AIF2_TXDAT 0x005B
|
||||
#define LOCHNAGAR2_GPIO_PSIA1_BCLK 0x005C
|
||||
#define LOCHNAGAR2_GPIO_PSIA1_RXDAT 0x005D
|
||||
#define LOCHNAGAR2_GPIO_PSIA1_LRCLK 0x005E
|
||||
#define LOCHNAGAR2_GPIO_PSIA1_TXDAT 0x005F
|
||||
#define LOCHNAGAR2_GPIO_PSIA2_BCLK 0x0060
|
||||
#define LOCHNAGAR2_GPIO_PSIA2_RXDAT 0x0061
|
||||
#define LOCHNAGAR2_GPIO_PSIA2_LRCLK 0x0062
|
||||
#define LOCHNAGAR2_GPIO_PSIA2_TXDAT 0x0063
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF3_BCLK 0x0064
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF3_RXDAT 0x0065
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF3_LRCLK 0x0066
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF3_TXDAT 0x0067
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF4_BCLK 0x0068
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF4_RXDAT 0x0069
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF4_LRCLK 0x006A
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF4_TXDAT 0x006B
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF1_BCLK 0x006C
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF1_RXDAT 0x006D
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF1_LRCLK 0x006E
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF1_TXDAT 0x006F
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF2_BCLK 0x0070
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF2_RXDAT 0x0071
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF2_LRCLK 0x0072
|
||||
#define LOCHNAGAR2_GPIO_GF_AIF2_TXDAT 0x0073
|
||||
#define LOCHNAGAR2_GPIO_DSP_UART1_RX 0x0074
|
||||
#define LOCHNAGAR2_GPIO_DSP_UART1_TX 0x0075
|
||||
#define LOCHNAGAR2_GPIO_DSP_UART2_RX 0x0076
|
||||
#define LOCHNAGAR2_GPIO_DSP_UART2_TX 0x0077
|
||||
#define LOCHNAGAR2_GPIO_GF_UART2_RX 0x0078
|
||||
#define LOCHNAGAR2_GPIO_GF_UART2_TX 0x0079
|
||||
#define LOCHNAGAR2_GPIO_USB_UART_RX 0x007A
|
||||
#define LOCHNAGAR2_GPIO_CDC_PDMCLK1 0x007C
|
||||
#define LOCHNAGAR2_GPIO_CDC_PDMDAT1 0x007D
|
||||
#define LOCHNAGAR2_GPIO_CDC_PDMCLK2 0x007E
|
||||
#define LOCHNAGAR2_GPIO_CDC_PDMDAT2 0x007F
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICCLK1 0x0080
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICDAT1 0x0081
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICCLK2 0x0082
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICDAT2 0x0083
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICCLK3 0x0084
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICDAT3 0x0085
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICCLK4 0x0086
|
||||
#define LOCHNAGAR2_GPIO_CDC_DMICDAT4 0x0087
|
||||
#define LOCHNAGAR2_GPIO_DSP_DMICCLK1 0x0088
|
||||
#define LOCHNAGAR2_GPIO_DSP_DMICDAT1 0x0089
|
||||
#define LOCHNAGAR2_GPIO_DSP_DMICCLK2 0x008A
|
||||
#define LOCHNAGAR2_GPIO_DSP_DMICDAT2 0x008B
|
||||
#define LOCHNAGAR2_GPIO_I2C2_SCL 0x008C
|
||||
#define LOCHNAGAR2_GPIO_I2C2_SDA 0x008D
|
||||
#define LOCHNAGAR2_GPIO_I2C3_SCL 0x008E
|
||||
#define LOCHNAGAR2_GPIO_I2C3_SDA 0x008F
|
||||
#define LOCHNAGAR2_GPIO_I2C4_SCL 0x0090
|
||||
#define LOCHNAGAR2_GPIO_I2C4_SDA 0x0091
|
||||
#define LOCHNAGAR2_GPIO_DSP_STANDBY 0x0092
|
||||
#define LOCHNAGAR2_GPIO_CDC_MCLK1 0x0093
|
||||
#define LOCHNAGAR2_GPIO_CDC_MCLK2 0x0094
|
||||
#define LOCHNAGAR2_GPIO_DSP_CLKIN 0x0095
|
||||
#define LOCHNAGAR2_GPIO_PSIA1_MCLK 0x0096
|
||||
#define LOCHNAGAR2_GPIO_PSIA2_MCLK 0x0097
|
||||
#define LOCHNAGAR2_GPIO_GF_GPIO1 0x0098
|
||||
#define LOCHNAGAR2_GPIO_GF_GPIO5 0x0099
|
||||
#define LOCHNAGAR2_GPIO_DSP_GPIO20 0x009A
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL1 0x00B9
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL2 0x00BA
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL3 0x00BB
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL4 0x00BC
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL5 0x00BD
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL6 0x00BE
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL7 0x00BF
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL8 0x00C0
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL9 0x00C1
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL10 0x00C2
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL11 0x00C3
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL12 0x00C4
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL13 0x00C5
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL14 0x00C6
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL15 0x00C7
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL16 0x00C8
|
||||
#define LOCHNAGAR2_MINICARD_RESETS 0x00DF
|
||||
#define LOCHNAGAR2_ANALOGUE_PATH_CTRL1 0x00E3
|
||||
#define LOCHNAGAR2_ANALOGUE_PATH_CTRL2 0x00E4
|
||||
#define LOCHNAGAR2_COMMS_CTRL4 0x00F0
|
||||
#define LOCHNAGAR2_SPDIF_CTRL 0x00FE
|
||||
#define LOCHNAGAR2_IMON_CTRL1 0x0108
|
||||
#define LOCHNAGAR2_IMON_CTRL2 0x0109
|
||||
#define LOCHNAGAR2_IMON_CTRL3 0x010A
|
||||
#define LOCHNAGAR2_IMON_CTRL4 0x010B
|
||||
#define LOCHNAGAR2_IMON_DATA1 0x010C
|
||||
#define LOCHNAGAR2_IMON_DATA2 0x010D
|
||||
#define LOCHNAGAR2_POWER_CTRL 0x0116
|
||||
#define LOCHNAGAR2_MICVDD_CTRL1 0x0119
|
||||
#define LOCHNAGAR2_MICVDD_CTRL2 0x011B
|
||||
#define LOCHNAGAR2_VDDCORE_CDC_CTRL1 0x011E
|
||||
#define LOCHNAGAR2_VDDCORE_CDC_CTRL2 0x0120
|
||||
#define LOCHNAGAR2_SOUNDCARD_AIF_CTRL 0x0180
|
||||
|
||||
/* (0x000D-0x001B, 0x0180) CDC_AIF1_CTRL - SOUNCARD_AIF_CTRL */
|
||||
#define LOCHNAGAR2_AIF_ENA_MASK 0x8000
|
||||
#define LOCHNAGAR2_AIF_ENA_SHIFT 15
|
||||
#define LOCHNAGAR2_AIF_LRCLK_DIR_MASK 0x4000
|
||||
#define LOCHNAGAR2_AIF_LRCLK_DIR_SHIFT 14
|
||||
#define LOCHNAGAR2_AIF_BCLK_DIR_MASK 0x2000
|
||||
#define LOCHNAGAR2_AIF_BCLK_DIR_SHIFT 13
|
||||
#define LOCHNAGAR2_AIF_SRC_MASK 0x00FF
|
||||
#define LOCHNAGAR2_AIF_SRC_SHIFT 0
|
||||
|
||||
/* (0x001E - 0x0027) CDC_MCLK1_CTRL - SOUNDCARD_MCLK_CTRL */
|
||||
#define LOCHNAGAR2_CLK_ENA_MASK 0x8000
|
||||
#define LOCHNAGAR2_CLK_ENA_SHIFT 15
|
||||
#define LOCHNAGAR2_CLK_SRC_MASK 0x00FF
|
||||
#define LOCHNAGAR2_CLK_SRC_SHIFT 0
|
||||
|
||||
/* (0x0031 - 0x009A) GPIO_FPGA_GPIO1 - GPIO_DSP_GPIO20 */
|
||||
#define LOCHNAGAR2_GPIO_SRC_MASK 0x00FF
|
||||
#define LOCHNAGAR2_GPIO_SRC_SHIFT 0
|
||||
|
||||
/* (0x00B9 - 0x00C8) GPIO_CHANNEL1 - GPIO_CHANNEL16 */
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL_STS_MASK 0x8000
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL_STS_SHIFT 15
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL_SRC_MASK 0x00FF
|
||||
#define LOCHNAGAR2_GPIO_CHANNEL_SRC_SHIFT 0
|
||||
|
||||
/* (0x00DF) MINICARD_RESETS */
|
||||
#define LOCHNAGAR2_DSP_RESET_MASK 0x0002
|
||||
#define LOCHNAGAR2_DSP_RESET_SHIFT 1
|
||||
#define LOCHNAGAR2_CDC_RESET_MASK 0x0001
|
||||
#define LOCHNAGAR2_CDC_RESET_SHIFT 0
|
||||
|
||||
/* (0x00E3) ANALOGUE_PATH_CTRL1 */
|
||||
#define LOCHNAGAR2_ANALOGUE_PATH_UPDATE_MASK 0x8000
|
||||
#define LOCHNAGAR2_ANALOGUE_PATH_UPDATE_SHIFT 15
|
||||
#define LOCHNAGAR2_ANALOGUE_PATH_UPDATE_STS_MASK 0x4000
|
||||
#define LOCHNAGAR2_ANALOGUE_PATH_UPDATE_STS_SHIFT 14
|
||||
|
||||
/* (0x00E4) ANALOGUE_PATH_CTRL2 */
|
||||
#define LOCHNAGAR2_P2_INPUT_BIAS_ENA_MASK 0x0080
|
||||
#define LOCHNAGAR2_P2_INPUT_BIAS_ENA_SHIFT 7
|
||||
#define LOCHNAGAR2_P1_INPUT_BIAS_ENA_MASK 0x0040
|
||||
#define LOCHNAGAR2_P1_INPUT_BIAS_ENA_SHIFT 6
|
||||
#define LOCHNAGAR2_P2_MICBIAS_SRC_MASK 0x0038
|
||||
#define LOCHNAGAR2_P2_MICBIAS_SRC_SHIFT 3
|
||||
#define LOCHNAGAR2_P1_MICBIAS_SRC_MASK 0x0007
|
||||
#define LOCHNAGAR2_P1_MICBIAS_SRC_SHIFT 0
|
||||
|
||||
/* (0x00F0) COMMS_CTRL4 */
|
||||
#define LOCHNAGAR2_CDC_CIF1MODE_MASK 0x0001
|
||||
#define LOCHNAGAR2_CDC_CIF1MODE_SHIFT 0
|
||||
|
||||
/* (0x00FE) SPDIF_CTRL */
|
||||
#define LOCHNAGAR2_SPDIF_HWMODE_MASK 0x0008
|
||||
#define LOCHNAGAR2_SPDIF_HWMODE_SHIFT 3
|
||||
#define LOCHNAGAR2_SPDIF_RESET_MASK 0x0001
|
||||
#define LOCHNAGAR2_SPDIF_RESET_SHIFT 0
|
||||
|
||||
/* (0x0108) IMON_CTRL1 */
|
||||
#define LOCHNAGAR2_IMON_ENA_MASK 0x8000
|
||||
#define LOCHNAGAR2_IMON_ENA_SHIFT 15
|
||||
#define LOCHNAGAR2_IMON_MEASURED_CHANNELS_MASK 0x03FC
|
||||
#define LOCHNAGAR2_IMON_MEASURED_CHANNELS_SHIFT 2
|
||||
#define LOCHNAGAR2_IMON_MODE_SEL_MASK 0x0003
|
||||
#define LOCHNAGAR2_IMON_MODE_SEL_SHIFT 0
|
||||
|
||||
/* (0x0109) IMON_CTRL2 */
|
||||
#define LOCHNAGAR2_IMON_FSR_MASK 0x03FF
|
||||
#define LOCHNAGAR2_IMON_FSR_SHIFT 0
|
||||
|
||||
/* (0x010A) IMON_CTRL3 */
|
||||
#define LOCHNAGAR2_IMON_DONE_MASK 0x0004
|
||||
#define LOCHNAGAR2_IMON_DONE_SHIFT 2
|
||||
#define LOCHNAGAR2_IMON_CONFIGURE_MASK 0x0002
|
||||
#define LOCHNAGAR2_IMON_CONFIGURE_SHIFT 1
|
||||
#define LOCHNAGAR2_IMON_MEASURE_MASK 0x0001
|
||||
#define LOCHNAGAR2_IMON_MEASURE_SHIFT 0
|
||||
|
||||
/* (0x010B) IMON_CTRL4 */
|
||||
#define LOCHNAGAR2_IMON_DATA_REQ_MASK 0x0080
|
||||
#define LOCHNAGAR2_IMON_DATA_REQ_SHIFT 7
|
||||
#define LOCHNAGAR2_IMON_CH_SEL_MASK 0x0070
|
||||
#define LOCHNAGAR2_IMON_CH_SEL_SHIFT 4
|
||||
#define LOCHNAGAR2_IMON_DATA_RDY_MASK 0x0008
|
||||
#define LOCHNAGAR2_IMON_DATA_RDY_SHIFT 3
|
||||
#define LOCHNAGAR2_IMON_CH_SRC_MASK 0x0007
|
||||
#define LOCHNAGAR2_IMON_CH_SRC_SHIFT 0
|
||||
|
||||
/* (0x010C, 0x010D) IMON_DATA1, IMON_DATA2 */
|
||||
#define LOCHNAGAR2_IMON_DATA_MASK 0xFFFF
|
||||
#define LOCHNAGAR2_IMON_DATA_SHIFT 0
|
||||
|
||||
/* (0x0116) POWER_CTRL */
|
||||
#define LOCHNAGAR2_PWR_ENA_MASK 0x0001
|
||||
#define LOCHNAGAR2_PWR_ENA_SHIFT 0
|
||||
|
||||
/* (0x0119) MICVDD_CTRL1 */
|
||||
#define LOCHNAGAR2_MICVDD_REG_ENA_MASK 0x8000
|
||||
#define LOCHNAGAR2_MICVDD_REG_ENA_SHIFT 15
|
||||
|
||||
/* (0x011B) MICVDD_CTRL2 */
|
||||
#define LOCHNAGAR2_MICVDD_VSEL_MASK 0x001F
|
||||
#define LOCHNAGAR2_MICVDD_VSEL_SHIFT 0
|
||||
|
||||
/* (0x011E) VDDCORE_CDC_CTRL1 */
|
||||
#define LOCHNAGAR2_VDDCORE_CDC_REG_ENA_MASK 0x8000
|
||||
#define LOCHNAGAR2_VDDCORE_CDC_REG_ENA_SHIFT 15
|
||||
|
||||
/* (0x0120) VDDCORE_CDC_CTRL2 */
|
||||
#define LOCHNAGAR2_VDDCORE_CDC_VSEL_MASK 0x007F
|
||||
#define LOCHNAGAR2_VDDCORE_CDC_VSEL_SHIFT 0
|
||||
|
||||
#endif
|
@ -10,6 +10,20 @@
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define STMPE_SAMPLE_TIME(x) ((x & 0xf) << 4)
|
||||
#define STMPE_MOD_12B(x) ((x & 0x1) << 3)
|
||||
#define STMPE_REF_SEL(x) ((x & 0x1) << 1)
|
||||
#define STMPE_ADC_FREQ(x) (x & 0x3)
|
||||
#define STMPE_AVE_CTRL(x) ((x & 0x3) << 6)
|
||||
#define STMPE_DET_DELAY(x) ((x & 0x7) << 3)
|
||||
#define STMPE_SETTLING(x) (x & 0x7)
|
||||
#define STMPE_FRACTION_Z(x) (x & 0x7)
|
||||
#define STMPE_I_DRIVE(x) (x & 0x1)
|
||||
#define STMPE_OP_MODE(x) ((x & 0x7) << 1)
|
||||
|
||||
#define STMPE811_REG_ADC_CTRL1 0x20
|
||||
#define STMPE811_REG_ADC_CTRL2 0x21
|
||||
|
||||
struct device;
|
||||
struct regulator;
|
||||
|
||||
@ -123,6 +137,12 @@ struct stmpe {
|
||||
u8 ier[2];
|
||||
u8 oldier[2];
|
||||
struct stmpe_platform_data *pdata;
|
||||
|
||||
/* For devices that use an ADC */
|
||||
u8 sample_time;
|
||||
u8 mod_12b;
|
||||
u8 ref_sel;
|
||||
u8 adc_freq;
|
||||
};
|
||||
|
||||
extern int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 data);
|
||||
@ -136,6 +156,7 @@ extern int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins,
|
||||
enum stmpe_block block);
|
||||
extern int stmpe_enable(struct stmpe *stmpe, unsigned int blocks);
|
||||
extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks);
|
||||
extern int stmpe811_adc_common_init(struct stmpe *stmpe);
|
||||
|
||||
#define STMPE_GPIO_NOREQ_811_TOUCH (0xf0)
|
||||
|
||||
|
212
include/linux/mfd/stpmic1.h
Normal file
212
include/linux/mfd/stpmic1.h
Normal file
@ -0,0 +1,212 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
||||
* Author: Philippe Peurichard <philippe.peurichard@st.com>,
|
||||
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_STPMIC1_H
|
||||
#define __LINUX_MFD_STPMIC1_H
|
||||
|
||||
#define TURN_ON_SR 0x1
|
||||
#define TURN_OFF_SR 0x2
|
||||
#define ICC_LDO_TURN_OFF_SR 0x3
|
||||
#define ICC_BUCK_TURN_OFF_SR 0x4
|
||||
#define RREQ_STATE_SR 0x5
|
||||
#define VERSION_SR 0x6
|
||||
|
||||
#define SWOFF_PWRCTRL_CR 0x10
|
||||
#define PADS_PULL_CR 0x11
|
||||
#define BUCKS_PD_CR 0x12
|
||||
#define LDO14_PD_CR 0x13
|
||||
#define LDO56_VREF_PD_CR 0x14
|
||||
#define VBUS_DET_VIN_CR 0x15
|
||||
#define PKEY_TURNOFF_CR 0x16
|
||||
#define BUCKS_MASK_RANK_CR 0x17
|
||||
#define BUCKS_MASK_RESET_CR 0x18
|
||||
#define LDOS_MASK_RANK_CR 0x19
|
||||
#define LDOS_MASK_RESET_CR 0x1A
|
||||
#define WCHDG_CR 0x1B
|
||||
#define WCHDG_TIMER_CR 0x1C
|
||||
#define BUCKS_ICCTO_CR 0x1D
|
||||
#define LDOS_ICCTO_CR 0x1E
|
||||
|
||||
#define BUCK1_ACTIVE_CR 0x20
|
||||
#define BUCK2_ACTIVE_CR 0x21
|
||||
#define BUCK3_ACTIVE_CR 0x22
|
||||
#define BUCK4_ACTIVE_CR 0x23
|
||||
#define VREF_DDR_ACTIVE_CR 0x24
|
||||
#define LDO1_ACTIVE_CR 0x25
|
||||
#define LDO2_ACTIVE_CR 0x26
|
||||
#define LDO3_ACTIVE_CR 0x27
|
||||
#define LDO4_ACTIVE_CR 0x28
|
||||
#define LDO5_ACTIVE_CR 0x29
|
||||
#define LDO6_ACTIVE_CR 0x2A
|
||||
|
||||
#define BUCK1_STDBY_CR 0x30
|
||||
#define BUCK2_STDBY_CR 0x31
|
||||
#define BUCK3_STDBY_CR 0x32
|
||||
#define BUCK4_STDBY_CR 0x33
|
||||
#define VREF_DDR_STDBY_CR 0x34
|
||||
#define LDO1_STDBY_CR 0x35
|
||||
#define LDO2_STDBY_CR 0x36
|
||||
#define LDO3_STDBY_CR 0x37
|
||||
#define LDO4_STDBY_CR 0x38
|
||||
#define LDO5_STDBY_CR 0x39
|
||||
#define LDO6_STDBY_CR 0x3A
|
||||
|
||||
#define BST_SW_CR 0x40
|
||||
|
||||
#define INT_PENDING_R1 0x50
|
||||
#define INT_PENDING_R2 0x51
|
||||
#define INT_PENDING_R3 0x52
|
||||
#define INT_PENDING_R4 0x53
|
||||
|
||||
#define INT_DBG_LATCH_R1 0x60
|
||||
#define INT_DBG_LATCH_R2 0x61
|
||||
#define INT_DBG_LATCH_R3 0x62
|
||||
#define INT_DBG_LATCH_R4 0x63
|
||||
|
||||
#define INT_CLEAR_R1 0x70
|
||||
#define INT_CLEAR_R2 0x71
|
||||
#define INT_CLEAR_R3 0x72
|
||||
#define INT_CLEAR_R4 0x73
|
||||
|
||||
#define INT_MASK_R1 0x80
|
||||
#define INT_MASK_R2 0x81
|
||||
#define INT_MASK_R3 0x82
|
||||
#define INT_MASK_R4 0x83
|
||||
|
||||
#define INT_SET_MASK_R1 0x90
|
||||
#define INT_SET_MASK_R2 0x91
|
||||
#define INT_SET_MASK_R3 0x92
|
||||
#define INT_SET_MASK_R4 0x93
|
||||
|
||||
#define INT_CLEAR_MASK_R1 0xA0
|
||||
#define INT_CLEAR_MASK_R2 0xA1
|
||||
#define INT_CLEAR_MASK_R3 0xA2
|
||||
#define INT_CLEAR_MASK_R4 0xA3
|
||||
|
||||
#define INT_SRC_R1 0xB0
|
||||
#define INT_SRC_R2 0xB1
|
||||
#define INT_SRC_R3 0xB2
|
||||
#define INT_SRC_R4 0xB3
|
||||
|
||||
#define PMIC_MAX_REGISTER_ADDRESS INT_SRC_R4
|
||||
|
||||
#define STPMIC1_PMIC_NUM_IRQ_REGS 4
|
||||
|
||||
#define TURN_OFF_SR_ICC_EVENT 0x08
|
||||
|
||||
#define LDO_VOLTAGE_MASK GENMASK(6, 2)
|
||||
#define BUCK_VOLTAGE_MASK GENMASK(7, 2)
|
||||
#define LDO_BUCK_VOLTAGE_SHIFT 2
|
||||
|
||||
#define LDO_ENABLE_MASK BIT(0)
|
||||
#define BUCK_ENABLE_MASK BIT(0)
|
||||
|
||||
#define BUCK_HPLP_ENABLE_MASK BIT(1)
|
||||
#define BUCK_HPLP_SHIFT 1
|
||||
|
||||
#define STDBY_ENABLE_MASK BIT(0)
|
||||
|
||||
#define BUCKS_PD_CR_REG_MASK GENMASK(7, 0)
|
||||
#define BUCK_MASK_RANK_REGISTER_MASK GENMASK(3, 0)
|
||||
#define BUCK_MASK_RESET_REGISTER_MASK GENMASK(3, 0)
|
||||
#define LDO1234_PULL_DOWN_REGISTER_MASK GENMASK(7, 0)
|
||||
#define LDO56_VREF_PD_CR_REG_MASK GENMASK(5, 0)
|
||||
#define LDO_MASK_RANK_REGISTER_MASK GENMASK(5, 0)
|
||||
#define LDO_MASK_RESET_REGISTER_MASK GENMASK(5, 0)
|
||||
|
||||
#define BUCK1_PULL_DOWN_REG BUCKS_PD_CR
|
||||
#define BUCK1_PULL_DOWN_MASK BIT(0)
|
||||
#define BUCK2_PULL_DOWN_REG BUCKS_PD_CR
|
||||
#define BUCK2_PULL_DOWN_MASK BIT(2)
|
||||
#define BUCK3_PULL_DOWN_REG BUCKS_PD_CR
|
||||
#define BUCK3_PULL_DOWN_MASK BIT(4)
|
||||
#define BUCK4_PULL_DOWN_REG BUCKS_PD_CR
|
||||
#define BUCK4_PULL_DOWN_MASK BIT(6)
|
||||
|
||||
#define LDO1_PULL_DOWN_REG LDO14_PD_CR
|
||||
#define LDO1_PULL_DOWN_MASK BIT(0)
|
||||
#define LDO2_PULL_DOWN_REG LDO14_PD_CR
|
||||
#define LDO2_PULL_DOWN_MASK BIT(2)
|
||||
#define LDO3_PULL_DOWN_REG LDO14_PD_CR
|
||||
#define LDO3_PULL_DOWN_MASK BIT(4)
|
||||
#define LDO4_PULL_DOWN_REG LDO14_PD_CR
|
||||
#define LDO4_PULL_DOWN_MASK BIT(6)
|
||||
#define LDO5_PULL_DOWN_REG LDO56_VREF_PD_CR
|
||||
#define LDO5_PULL_DOWN_MASK BIT(0)
|
||||
#define LDO6_PULL_DOWN_REG LDO56_VREF_PD_CR
|
||||
#define LDO6_PULL_DOWN_MASK BIT(2)
|
||||
#define VREF_DDR_PULL_DOWN_REG LDO56_VREF_PD_CR
|
||||
#define VREF_DDR_PULL_DOWN_MASK BIT(4)
|
||||
|
||||
#define BUCKS_ICCTO_CR_REG_MASK GENMASK(6, 0)
|
||||
#define LDOS_ICCTO_CR_REG_MASK GENMASK(5, 0)
|
||||
|
||||
#define LDO_BYPASS_MASK BIT(7)
|
||||
|
||||
/* Main PMIC Control Register
|
||||
* SWOFF_PWRCTRL_CR
|
||||
* Address : 0x10
|
||||
*/
|
||||
#define ICC_EVENT_ENABLED BIT(4)
|
||||
#define PWRCTRL_POLARITY_HIGH BIT(3)
|
||||
#define PWRCTRL_PIN_VALID BIT(2)
|
||||
#define RESTART_REQUEST_ENABLED BIT(1)
|
||||
#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0)
|
||||
|
||||
/* Main PMIC PADS Control Register
|
||||
* PADS_PULL_CR
|
||||
* Address : 0x11
|
||||
*/
|
||||
#define WAKEUP_DETECTOR_DISABLED BIT(4)
|
||||
#define PWRCTRL_PD_ACTIVE BIT(3)
|
||||
#define PWRCTRL_PU_ACTIVE BIT(2)
|
||||
#define WAKEUP_PD_ACTIVE BIT(1)
|
||||
#define PONKEY_PU_INACTIVE BIT(0)
|
||||
|
||||
/* Main PMIC VINLOW Control Register
|
||||
* VBUS_DET_VIN_CRC DMSC
|
||||
* Address : 0x15
|
||||
*/
|
||||
#define SWIN_DETECTOR_ENABLED BIT(7)
|
||||
#define SWOUT_DETECTOR_ENABLED BIT(6)
|
||||
#define VINLOW_ENABLED BIT(0)
|
||||
#define VINLOW_CTRL_REG_MASK GENMASK(7, 0)
|
||||
|
||||
/* USB Control Register
|
||||
* Address : 0x40
|
||||
*/
|
||||
#define BOOST_OVP_DISABLED BIT(7)
|
||||
#define VBUS_OTG_DETECTION_DISABLED BIT(6)
|
||||
#define SW_OUT_DISCHARGE BIT(5)
|
||||
#define VBUS_OTG_DISCHARGE BIT(4)
|
||||
#define OCP_LIMIT_HIGH BIT(3)
|
||||
#define SWIN_SWOUT_ENABLED BIT(2)
|
||||
#define USBSW_OTG_SWITCH_ENABLED BIT(1)
|
||||
#define BOOST_ENABLED BIT(0)
|
||||
|
||||
/* PKEY_TURNOFF_CR
|
||||
* Address : 0x16
|
||||
*/
|
||||
#define PONKEY_PWR_OFF BIT(7)
|
||||
#define PONKEY_CC_FLAG_CLEAR BIT(6)
|
||||
#define PONKEY_TURNOFF_TIMER_MASK GENMASK(3, 0)
|
||||
#define PONKEY_TURNOFF_MASK GENMASK(7, 0)
|
||||
|
||||
/*
|
||||
* struct stpmic1 - stpmic1 master device for sub-drivers
|
||||
* @dev: master device of the chip (can be used to access platform data)
|
||||
* @irq: main IRQ number
|
||||
* @regmap_irq_chip_data: irq chip data
|
||||
*/
|
||||
struct stpmic1 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
int irq;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_MFD_STPMIC1_H */
|
@ -137,6 +137,10 @@
|
||||
#define TPS65218_CONFIG1_PGDLY_MASK 0x18
|
||||
#define TPS65218_CONFIG1_STRICT BIT(2)
|
||||
#define TPS65218_CONFIG1_UVLO_MASK 0x3
|
||||
#define TPS65218_CONFIG1_UVLO_2750000 0x0
|
||||
#define TPS65218_CONFIG1_UVLO_2950000 0x1
|
||||
#define TPS65218_CONFIG1_UVLO_3250000 0x2
|
||||
#define TPS65218_CONFIG1_UVLO_3350000 0x3
|
||||
|
||||
#define TPS65218_CONFIG2_DC12_RST BIT(7)
|
||||
#define TPS65218_CONFIG2_UVLOHYS BIT(6)
|
||||
|
@ -418,7 +418,6 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
|
||||
int count, u16 *buf);
|
||||
|
||||
int wm831x_device_init(struct wm831x *wm831x, int irq);
|
||||
void wm831x_device_exit(struct wm831x *wm831x);
|
||||
int wm831x_device_suspend(struct wm831x *wm831x);
|
||||
void wm831x_device_shutdown(struct wm831x *wm831x);
|
||||
int wm831x_irq_init(struct wm831x *wm831x, int irq);
|
||||
|
@ -643,7 +643,6 @@ struct wm8350_platform_data {
|
||||
*/
|
||||
int wm8350_device_init(struct wm8350 *wm8350, int irq,
|
||||
struct wm8350_platform_data *pdata);
|
||||
void wm8350_device_exit(struct wm8350 *wm8350);
|
||||
|
||||
/*
|
||||
* WM8350 device IO
|
||||
|
Loading…
Reference in New Issue
Block a user