forked from luck/tmp_suning_uos_patched
- Core Frameworks
- Make better attempt at matching device with the correct OF node - Allow batch removal of hierarchical sub-devices - New Drivers - Add STM32 Clocksource driver - Add support for Khadas System Control Microcontroller - Driver Removal - Remove unused driver for TI's SMSC ECE1099 - New Device Support - Add support for Intel Emmitsburg PCH to Intel LPSS PCI - Add support for Intel Tiger Lake PCH-H to Intel LPSS PCI - Add support for Dialog DA revision to Dialog DA9063 - New Functionality - Add support for AXP803 to be probed by I2C - Fix-ups - Numerous W=1 warning fixes - Device Tree changes; stm32-lptimer, gateworks-gsc, khadas,mcu, stmfx, cros-ec, j721e-system-controller - Enabled Regmap 'fast I/O'; stm32-lptimer - Change BUG_ON to WARN_ON; arizona-core - Remove superfluous code/initialisation; madera, max14577 - Trivial formatting/spelling issues; madera-core, madera-i2c, da9055, max77693-private - Switch to of_platform_populate(); sprd-sc27xx-spi - Expand out set/get brightness/pwm macros; lm3533-ctrlbank - Disable IRQs on suspend; motorola-cpcap - Clean-up error handling; intel_soc_pmic_mrfld - Ensure correct removal order of sub-devices; madera - Many s/HTTP/HTTPS/ link changes - Ensure name used with Regmap is unique; syscon - Bug Fixes - Properly 'put' clock on unbind and error; arizona-core - Fix revision handling; da9063 - Fix 'assignment of read-only location' error; kempld-core - Avoid using the Regmap API when atomic; rn5t618 - Redefine volatile register description; rn5t618 - Use locking to protect event handler; dln2 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAl82oU4ACgkQUa+KL4f8 d2GMiw//Xil7CSDFOS5P3F0BQJHBFAl2L/BFtcFXx+BkkMQHvvuv0J1yTPoPFEI8 wQv0TFWdcQeco6Vkf/nyoM5vPvHXRMt3QzV5AAlxhN+eBaxLRKyq4vtYOeCH7iA/ R9CTI9KZvIg7tMTMDFuTnXFYPZoCSFIIl/7st8PrkC6JyVs4v/4vEXHvJz6DTOky yvVx7VsyQC2yrgiBXp/kAkvciD7hFSU2ibkJHn/6xDzgRrqc3PGmkmB8yMIXwSvz 7a4/KFxENLshRzPSywwm1CIubtqlhO0ZOy3Swivg0X7wudNrpo4ysFgI4HBQMpOC lHF2WGOUUdpMVfrQQ5ccG3/kbjSU2tUPXOGrdG1IWASPrZtzksqUT5vnCysB7z8+ LQT0j0WFsCZd9tbgEQt/i486M1c532Yh1iwsYhFv7PY6N4xhqArroFGu2ky5WvEY 9IwLVgD0V8nEKnVTk1Zmz9/FpDHKf1xhbTK8Dyxsztis2vn9cXdva+iJZ73mFehb E1kVvI+KccZnpgM7nZZ7AwkJFO39rws9Hm+zWoUOdUV4+Zb809QeWCEPJyJeDHy7 bqHyiGCDDYvV+eE9AOxEsI1D8QoXhS9gNPZxSW9rSxaWVbdE+7HD4Of5gEEH9C5Z 1RMdshrOT7mjBqhotzqxNe2NvMP8bgoL3pvDwCrkl9u72mCzweo= =X/Zn -----END PGP SIGNATURE----- Merge tag 'mfd-next-5.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd Pull MFD updates from Lee Jones: "Core Frameworks - Make better attempt at matching device with the correct OF node - Allow batch removal of hierarchical sub-devices New Drivers - Add STM32 Clocksource driver - Add support for Khadas System Control Microcontroller Driver Removal - Remove unused driver for TI's SMSC ECE1099 New Device Support - Add support for Intel Emmitsburg PCH to Intel LPSS PCI - Add support for Intel Tiger Lake PCH-H to Intel LPSS PCI - Add support for Dialog DA revision to Dialog DA9063 New Functionality - Add support for AXP803 to be probed by I2C Fix-ups - Numerous W=1 warning fixes - Device Tree changes (stm32-lptimer, gateworks-gsc, khadas,mcu, stmfx, cros-ec, j721e-system-controller) - Enabled Regmap 'fast I/O' in stm32-lptimer - Change BUG_ON to WARN_ON in arizona-core - Remove superfluous code/initialisation (madera, max14577) - Trivial formatting/spelling issues (madera-core, madera-i2c, da9055, max77693-private) - Switch to of_platform_populate() in sprd-sc27xx-spi - Expand out set/get brightness/pwm macros in lm3533-ctrlbank - Disable IRQs on suspend in motorola-cpcap - Clean-up error handling in intel_soc_pmic_mrfld - Ensure correct removal order of sub-devices in madera - Many s/HTTP/HTTPS/ link changes - Ensure name used with Regmap is unique in syscon Bug Fixes - Properly 'put' clock on unbind and error in arizona-core - Fix revision handling in da9063 - Fix 'assignment of read-only location' error in kempld-core - Avoid using the Regmap API when atomic in rn5t618 - Redefine volatile register description in rn5t618 - Use locking to protect event handler in dln2" * tag 'mfd-next-5.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (76 commits) mfd: syscon: Use a unique name with regmap_config mfd: Replace HTTP links with HTTPS ones mfd: dln2: Run event handler loop under spinlock mfd: madera: Improve handling of regulator unbinding mfd: mfd-core: Add mechanism for removal of a subset of children mfd: intel_soc_pmic_mrfld: Simplify the return expression of intel_scu_ipc_dev_iowrite8() mfd: max14577: Remove redundant initialization of variable current_bits mfd: rn5t618: Fix caching of battery related registers mfd: max77693-private: Drop a duplicated word mfd: da9055: pdata.h: Drop a duplicated word mfd: rn5t618: Make restart handler atomic safe mfd: kempld-core: Fix 'assignment of read-only location' error mfd: axp20x: Allow the AXP803 to be probed by I2C mfd: da9063: Add support for latest DA silicon revision mfd: da9063: Fix revision handling to correctly select reg tables dt-bindings: mfd: st,stmfx: Remove I2C unit name dt-bindings: mfd: ti,j721e-system-controller.yaml: Add J721e system controller mfd: motorola-cpcap: Disable interrupt for suspend mfd: smsc-ece1099: Remove driver mfd: core: Add OF_MFD_CELL_REG() helper ...
This commit is contained in:
commit
884e0d3dd5
|
@ -1,76 +0,0 @@
|
|||
ChromeOS Embedded Controller
|
||||
|
||||
Google's ChromeOS EC is a Cortex-M device which talks to the AP and
|
||||
implements various function such as keyboard and battery charging.
|
||||
|
||||
The EC can be connect through various means (I2C, SPI, LPC, RPMSG) and the
|
||||
compatible string used depends on the interface. Each connection method has
|
||||
its own driver which connects to the top level interface-agnostic EC driver.
|
||||
Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to
|
||||
the top-level driver.
|
||||
|
||||
Required properties (I2C):
|
||||
- compatible: "google,cros-ec-i2c"
|
||||
- reg: I2C slave address
|
||||
|
||||
Required properties (SPI):
|
||||
- compatible: "google,cros-ec-spi"
|
||||
- reg: SPI chip select
|
||||
|
||||
Required properties (RPMSG):
|
||||
- compatible: "google,cros-ec-rpmsg"
|
||||
|
||||
Optional properties (SPI):
|
||||
- google,cros-ec-spi-pre-delay: Some implementations of the EC need a little
|
||||
time to wake up from sleep before they can receive SPI transfers at a high
|
||||
clock rate. This property specifies the delay, in usecs, between the
|
||||
assertion of the CS to the start of the first clock pulse.
|
||||
- google,cros-ec-spi-msg-delay: Some implementations of the EC require some
|
||||
additional processing time in order to accept new transactions. If the delay
|
||||
between transactions is not long enough the EC may not be able to respond
|
||||
properly to subsequent transactions and cause them to hang. This property
|
||||
specifies the delay, in usecs, introduced between transactions to account
|
||||
for the time required by the EC to get back into a state in which new data
|
||||
can be accepted.
|
||||
|
||||
Required properties (LPC):
|
||||
- compatible: "google,cros-ec-lpc"
|
||||
- reg: List of (IO address, size) pairs defining the interface uses
|
||||
|
||||
Optional properties (all):
|
||||
- google,has-vbc-nvram: Some implementations of the EC include a small
|
||||
nvram space used to store verified boot context data. This boolean flag
|
||||
is used to specify whether this nvram is present or not.
|
||||
|
||||
Example for I2C:
|
||||
|
||||
i2c@12ca0000 {
|
||||
cros-ec@1e {
|
||||
reg = <0x1e>;
|
||||
compatible = "google,cros-ec-i2c";
|
||||
interrupts = <14 0>;
|
||||
interrupt-parent = <&wakeup_eint>;
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
|
||||
Example for SPI:
|
||||
|
||||
spi@131b0000 {
|
||||
ec@0 {
|
||||
compatible = "google,cros-ec-spi";
|
||||
reg = <0x0>;
|
||||
interrupts = <14 0>;
|
||||
interrupt-parent = <&wakeup_eint>;
|
||||
wakeup-source;
|
||||
spi-max-frequency = <5000000>;
|
||||
controller-data {
|
||||
cs-gpio = <&gpf0 3 4 3 0>;
|
||||
samsung,spi-cs;
|
||||
samsung,spi-feedback-delay = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Example for LPC is not supplied as it is not yet implemented.
|
|
@ -79,11 +79,12 @@ properties:
|
|||
description: |
|
||||
conversion mode:
|
||||
0 - temperature, in C*10
|
||||
1 - pre-scaled voltage value
|
||||
1 - pre-scaled 24-bit voltage value
|
||||
2 - scaled voltage based on an optional resistor divider
|
||||
and optional offset
|
||||
3 - pre-scaled 16-bit voltage value
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1, 2]
|
||||
enum: [0, 1, 2, 3]
|
||||
|
||||
gw,voltage-divider-ohms:
|
||||
description: Values of resistors for divider on raw ADC input
|
||||
|
|
129
Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
Normal file
129
Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
Normal file
|
@ -0,0 +1,129 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/google,cros-ec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ChromeOS Embedded Controller
|
||||
|
||||
maintainers:
|
||||
- Benson Leung <bleung@chromium.org>
|
||||
- Enric Balletbo i Serra <enric.balletbo@collabora.com>
|
||||
- Guenter Roeck <groeck@chromium.org>
|
||||
|
||||
description:
|
||||
Google's ChromeOS EC is a microcontroller which talks to the AP and
|
||||
implements various functions such as keyboard and battery charging.
|
||||
The EC can be connected through various interfaces (I2C, SPI, and others)
|
||||
and the compatible string specifies which interface is being used.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description:
|
||||
For implementations of the EC is connected through I2C.
|
||||
const: google,cros-ec-i2c
|
||||
- description:
|
||||
For implementations of the EC is connected through SPI.
|
||||
const: google,cros-ec-spi
|
||||
- description:
|
||||
For implementations of the EC is connected through RPMSG.
|
||||
const: google,cros-ec-rpmsg
|
||||
|
||||
google,cros-ec-spi-pre-delay:
|
||||
description:
|
||||
This property specifies the delay in usecs between the
|
||||
assertion of the CS and the first clock pulse.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- default: 0
|
||||
- minimum: 0
|
||||
|
||||
google,cros-ec-spi-msg-delay:
|
||||
description:
|
||||
This property specifies the delay in usecs between messages.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- default: 0
|
||||
- minimum: 0
|
||||
|
||||
google,has-vbc-nvram:
|
||||
description:
|
||||
Some implementations of the EC include a small nvram space used to
|
||||
store verified boot context data. This boolean flag is used to specify
|
||||
whether this nvram is present or not.
|
||||
type: boolean
|
||||
|
||||
spi-max-frequency:
|
||||
description: Maximum SPI frequency of the device in Hz.
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- google,cros-ec-i2c
|
||||
- google,cros-ec-rpmsg
|
||||
then:
|
||||
properties:
|
||||
google,cros-ec-spi-pre-delay: false
|
||||
google,cros-ec-spi-msg-delay: false
|
||||
spi-max-frequency: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Example for I2C
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cros-ec@1e {
|
||||
compatible = "google,cros-ec-i2c";
|
||||
reg = <0x1e>;
|
||||
interrupts = <6 0>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
};
|
||||
};
|
||||
|
||||
# Example for SPI
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cros-ec@0 {
|
||||
compatible = "google,cros-ec-spi";
|
||||
reg = <0x0>;
|
||||
google,cros-ec-spi-msg-delay = <30>;
|
||||
google,cros-ec-spi-pre-delay = <10>;
|
||||
interrupts = <99 0>;
|
||||
interrupt-parent = <&gpio7>;
|
||||
spi-max-frequency = <5000000>;
|
||||
};
|
||||
};
|
||||
|
||||
# Example for RPMSG
|
||||
- |
|
||||
scp0 {
|
||||
cros-ec {
|
||||
compatible = "google,cros-ec-rpmsg";
|
||||
};
|
||||
};
|
||||
...
|
44
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
Normal file
44
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
Normal file
|
@ -0,0 +1,44 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/khadas,mcu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Khadas on-board Microcontroller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <narmstrong@baylibre.com>
|
||||
|
||||
description: |
|
||||
Khadas embeds a microcontroller on their VIM and Edge boards adding some
|
||||
system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory
|
||||
storage, IR/Key resume control, system power LED control and more.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- khadas,mcu # MCU revision is discoverable
|
||||
|
||||
"#cooling-cells": # Only needed for boards having FAN control feature
|
||||
const: 2
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
khadas_mcu: system-controller@18 {
|
||||
compatible = "khadas,mcu";
|
||||
reg = <0x18>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
};
|
|
@ -33,6 +33,9 @@ properties:
|
|||
items:
|
||||
- const: mux
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
|
@ -106,11 +109,13 @@ additionalProperties: false
|
|||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
timer@40002400 {
|
||||
compatible = "st,stm32-lptimer";
|
||||
reg = <0x40002400 0x400>;
|
||||
clocks = <&timer_clk>;
|
||||
clock-names = "mux";
|
||||
interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
|
122
Documentation/devicetree/bindings/mfd/st,stmfx.yaml
Normal file
122
Documentation/devicetree/bindings/mfd/st,stmfx.yaml
Normal file
|
@ -0,0 +1,122 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/st,stmfx.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: STMicroelectonics Multi-Function eXpander (STMFX) bindings
|
||||
|
||||
description: ST Multi-Function eXpander (STMFX) is a slave controller using I2C for
|
||||
communication with the main MCU. Its main features are GPIO expansion,
|
||||
main MCU IDD measurement (IDD is the amount of current that flows
|
||||
through VDD) and resistive touchscreen controller.
|
||||
|
||||
maintainers:
|
||||
- Amelie Delaunay <amelie.delaunay@st.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stmfx-0300
|
||||
|
||||
reg:
|
||||
enum: [ 0x42, 0x43 ]
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
drive-open-drain: true
|
||||
|
||||
vdd-supply:
|
||||
maxItems: 1
|
||||
|
||||
pinctrl:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stmfx-0300-pinctrl
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
gpio-ranges:
|
||||
description: if all STMFX pins[24:0] are available (no other STMFX function in use),
|
||||
you should use gpio-ranges = <&stmfx_pinctrl 0 0 24>;
|
||||
if agpio[3:0] are not available (STMFX Touchscreen function in use),
|
||||
you should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>;
|
||||
if agpio[7:4] are not available (STMFX IDD function in use),
|
||||
you should use gpio-ranges = <&stmfx_pinctrl 0 0 20>;
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^[a-zA-Z]*-pins$":
|
||||
type: object
|
||||
|
||||
allOf:
|
||||
- $ref: ../pinctrl/pinmux-node.yaml
|
||||
|
||||
properties:
|
||||
pins: true
|
||||
bias-disable: true
|
||||
bias-pull-up: true
|
||||
bias-pull-pin-default: true
|
||||
bias-pull-down: true
|
||||
drive-open-drain: true
|
||||
drive-push-pull: true
|
||||
output-high: true
|
||||
output-low: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#gpio-cells"
|
||||
- "#interrupt-cells"
|
||||
- gpio-controller
|
||||
- interrupt-controller
|
||||
- gpio-ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
stmfx@42 {
|
||||
compatible = "st,stmfx-0300";
|
||||
reg = <0x42>;
|
||||
interrupts = <8 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&gpioi>;
|
||||
vdd-supply = <&v3v3>;
|
||||
|
||||
stmfx_pinctrl: pinctrl {
|
||||
compatible = "st,stmfx-0300-pinctrl";
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
gpio-ranges = <&stmfx_pinctrl 0 0 24>;
|
||||
|
||||
joystick_pins: joystick-pins {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4";
|
||||
drive-push-pull;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -1,28 +0,0 @@
|
|||
STMicroelectonics Multi-Function eXpander (STMFX) Core bindings
|
||||
|
||||
ST Multi-Function eXpander (STMFX) is a slave controller using I2C for
|
||||
communication with the main MCU. Its main features are GPIO expansion, main
|
||||
MCU IDD measurement (IDD is the amount of current that flows through VDD) and
|
||||
resistive touchscreen controller.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "st,stmfx-0300".
|
||||
- reg: I2C slave address of the device.
|
||||
- interrupts: interrupt specifier triggered by MFX_IRQ_OUT signal.
|
||||
Please refer to ../interrupt-controller/interrupt.txt
|
||||
|
||||
Optional properties:
|
||||
- drive-open-drain: configure MFX_IRQ_OUT as open drain.
|
||||
- vdd-supply: phandle of the regulator supplying STMFX.
|
||||
|
||||
Example:
|
||||
|
||||
stmfx: stmfx@42 {
|
||||
compatible = "st,stmfx-0300";
|
||||
reg = <0x42>;
|
||||
interrupts = <8 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&gpioi>;
|
||||
vdd-supply = <&v3v3>;
|
||||
};
|
||||
|
||||
Please refer to ../pinctrl/pinctrl-stmfx.txt for STMFX GPIO expander function bindings.
|
|
@ -26,7 +26,7 @@ Optional node:
|
|||
Example:
|
||||
/*
|
||||
* Integrated Power Management Chip
|
||||
* http://www.ti.com/lit/ds/symlink/twl6030.pdf
|
||||
* https://www.ti.com/lit/ds/symlink/twl6030.pdf
|
||||
*/
|
||||
twl@48 {
|
||||
compatible = "ti,twl6030";
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander bindings
|
||||
|
||||
ST Multi-Function eXpander (STMFX) offers up to 24 GPIOs expansion.
|
||||
Please refer to ../mfd/stmfx.txt for STMFX Core bindings.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "st,stmfx-0300-pinctrl".
|
||||
- #gpio-cells: should be <2>, the first cell is the GPIO number and the second
|
||||
cell is the gpio flags in accordance with <dt-bindings/gpio/gpio.h>.
|
||||
- gpio-controller: marks the device as a GPIO controller.
|
||||
- #interrupt-cells: should be <2>, the first cell is the GPIO number and the
|
||||
second cell is the interrupt flags in accordance with
|
||||
<dt-bindings/interrupt-controller/irq.h>.
|
||||
- interrupt-controller: marks the device as an interrupt controller.
|
||||
- gpio-ranges: specifies the mapping between gpio controller and pin
|
||||
controller pins. Check "Concerning gpio-ranges property" below.
|
||||
Please refer to ../gpio/gpio.txt.
|
||||
|
||||
Please refer to pinctrl-bindings.txt for pin configuration.
|
||||
|
||||
Required properties for pin configuration sub-nodes:
|
||||
- pins: list of pins to which the configuration applies.
|
||||
|
||||
Optional properties for pin configuration sub-nodes (pinconf-generic ones):
|
||||
- bias-disable: disable any bias on the pin.
|
||||
- bias-pull-up: the pin will be pulled up.
|
||||
- bias-pull-pin-default: use the pin-default pull state.
|
||||
- bias-pull-down: the pin will be pulled down.
|
||||
- drive-open-drain: the pin will be driven with open drain.
|
||||
- drive-push-pull: the pin will be driven actively high and low.
|
||||
- output-high: the pin will be configured as an output driving high level.
|
||||
- output-low: the pin will be configured as an output driving low level.
|
||||
|
||||
Note that STMFX pins[15:0] are called "gpio[15:0]", and STMFX pins[23:16] are
|
||||
called "agpio[7:0]". Example, to refer to pin 18 of STMFX, use "agpio2".
|
||||
|
||||
Concerning gpio-ranges property:
|
||||
- if all STMFX pins[24:0] are available (no other STMFX function in use), you
|
||||
should use gpio-ranges = <&stmfx_pinctrl 0 0 24>;
|
||||
- if agpio[3:0] are not available (STMFX Touchscreen function in use), you
|
||||
should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>;
|
||||
- if agpio[7:4] are not available (STMFX IDD function in use), you
|
||||
should use gpio-ranges = <&stmfx_pinctrl 0 0 20>;
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
stmfx: stmfx@42 {
|
||||
...
|
||||
|
||||
stmfx_pinctrl: stmfx-pin-controller {
|
||||
compatible = "st,stmfx-0300-pinctrl";
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
gpio-ranges = <&stmfx_pinctrl 0 0 24>;
|
||||
|
||||
joystick_pins: joystick {
|
||||
pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4";
|
||||
drive-push-pull;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example of STMFX GPIO consumers:
|
||||
|
||||
joystick {
|
||||
compatible = "gpio-keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-0 = <&joystick_pins>;
|
||||
pinctrl-names = "default";
|
||||
button-0 {
|
||||
label = "JoySel";
|
||||
linux,code = <KEY_ENTER>;
|
||||
interrupt-parent = <&stmfx_pinctrl>;
|
||||
interrupts = <0 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
button-1 {
|
||||
label = "JoyDown";
|
||||
linux,code = <KEY_DOWN>;
|
||||
interrupt-parent = <&stmfx_pinctrl>;
|
||||
interrupts = <1 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
button-2 {
|
||||
label = "JoyLeft";
|
||||
linux,code = <KEY_LEFT>;
|
||||
interrupt-parent = <&stmfx_pinctrl>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
button-3 {
|
||||
label = "JoyRight";
|
||||
linux,code = <KEY_RIGHT>;
|
||||
interrupt-parent = <&stmfx_pinctrl>;
|
||||
interrupts = <3 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
button-4 {
|
||||
label = "JoyUp";
|
||||
linux,code = <KEY_UP>;
|
||||
interrupt-parent = <&stmfx_pinctrl>;
|
||||
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
orange {
|
||||
gpios = <&stmfx_pinctrl 17 1>;
|
||||
};
|
||||
|
||||
blue {
|
||||
gpios = <&stmfx_pinctrl 19 1>;
|
||||
};
|
||||
}
|
|
@ -100,7 +100,6 @@ available subsections can be seen below.
|
|||
rfkill
|
||||
serial/index
|
||||
sm501
|
||||
smsc_ece1099
|
||||
switchtec
|
||||
sync_file
|
||||
vfio-mediated-device
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
=================================================
|
||||
Msc Keyboard Scan Expansion/GPIO Expansion device
|
||||
=================================================
|
||||
|
||||
What is smsc-ece1099?
|
||||
----------------------
|
||||
|
||||
The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion
|
||||
or GPIO Expansion device. The device supports a keyboard
|
||||
scan matrix of 23x8. The device is connected to a Master
|
||||
via the SMSC BC-Link interface or via the SMBus.
|
||||
Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals
|
||||
are multiplexed with GPIOs.
|
||||
|
||||
Interrupt generation
|
||||
--------------------
|
||||
|
||||
Interrupts can be generated by an edge detection on a GPIO
|
||||
pin or an edge detection on one of the bus interface pins.
|
||||
Interrupts can also be detected on the keyboard scan interface.
|
||||
The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if
|
||||
any bit in one of the Interrupt Status registers is 1 and
|
||||
the corresponding Interrupt Mask bit is also 1.
|
||||
|
||||
In order for software to determine which device is the source
|
||||
of an interrupt, it should first read the Group Interrupt Status Register
|
||||
to determine which Status register group is a source for the interrupt.
|
||||
Software should read both the Status register and the associated Mask register,
|
||||
then AND the two values together. Bits that are 1 in the result of the AND
|
||||
are active interrupts. Software clears an interrupt by writing a 1 to the
|
||||
corresponding bit in the Status register.
|
||||
|
||||
Communication Protocol
|
||||
----------------------
|
||||
|
||||
- SMbus slave Interface
|
||||
The host processor communicates with the ECE1099 device
|
||||
through a series of read/write registers via the SMBus
|
||||
interface. SMBus is a serial communication protocol between
|
||||
a computer host and its peripheral devices. The SMBus data
|
||||
rate is 10KHz minimum to 400 KHz maximum
|
||||
|
||||
- Slave Bus Interface
|
||||
The ECE1099 device SMBus implementation is a subset of the
|
||||
SMBus interface to the host. The device is a slave-only SMBus device.
|
||||
The implementation in the device is a subset of SMBus since it
|
||||
only supports four protocols.
|
||||
|
||||
The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the
|
||||
only valid SMBus protocols for the device.
|
||||
|
||||
- BC-LinkTM Interface
|
||||
The BC-Link is a proprietary bus that allows communication
|
||||
between a Master device and a Companion device. The Master
|
||||
device uses this serial bus to read and write registers
|
||||
located on the Companion device. The bus comprises three signals,
|
||||
BC_CLK, BC_DAT and BC_INT#. The Master device always provides the
|
||||
clock, BC_CLK, and the Companion device is the source for an
|
||||
independent asynchronous interrupt signal, BC_INT#. The ECE1099
|
||||
supports BC-Link speeds up to 24MHz.
|
41
MAINTAINERS
41
MAINTAINERS
|
@ -9678,6 +9678,15 @@ F: include/linux/kdb.h
|
|||
F: include/linux/kgdb.h
|
||||
F: kernel/debug/
|
||||
|
||||
KHADAS MCU MFD DRIVER
|
||||
M: Neil Armstrong <narmstrong@baylibre.com>
|
||||
L: linux-amlogic@lists.infradead.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
|
||||
F: drivers/mfd/khadas-mcu.c
|
||||
F: include/linux/mfd/khadas-mcu.h
|
||||
F: drivers/thermal/khadas_mcu_fan.c
|
||||
|
||||
KMEMLEAK
|
||||
M: Catalin Marinas <catalin.marinas@arm.com>
|
||||
S: Maintained
|
||||
|
@ -14887,6 +14896,13 @@ L: linux-serial@vger.kernel.org
|
|||
S: Odd Fixes
|
||||
F: drivers/tty/serial/rp2.*
|
||||
|
||||
ROHM BD99954 CHARGER IC
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
L: linux-power@fi.rohmeurope.com
|
||||
S: Supported
|
||||
F: drivers/power/supply/bd99954-charger.c
|
||||
F: drivers/power/supply/bd99954-charger.h
|
||||
|
||||
ROHM BH1750 AMBIENT LIGHT SENSOR DRIVER
|
||||
M: Tomasz Duszynski <tduszyns@gmail.com>
|
||||
S: Maintained
|
||||
|
@ -14904,6 +14920,31 @@ F: drivers/mfd/bd9571mwv.c
|
|||
F: drivers/regulator/bd9571mwv-regulator.c
|
||||
F: include/linux/mfd/bd9571mwv.h
|
||||
|
||||
ROHM POWER MANAGEMENT IC DEVICE DRIVERS
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
L: linux-power@fi.rohmeurope.com
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
|
||||
F: Documentation/devicetree/bindings/regulator/rohm,bd70528-regulator.txt
|
||||
F: drivers/clk/clk-bd718x7.c
|
||||
F: drivers/gpio/gpio-bd70528.c
|
||||
F: drivers/gpio/gpio-bd71828.c
|
||||
F: drivers/mfd/rohm-bd70528.c
|
||||
F: drivers/mfd/rohm-bd71828.c
|
||||
F: drivers/mfd/rohm-bd718x7.c
|
||||
F: drivers/power/supply/bd70528-charger.c
|
||||
F: drivers/regulator/bd70528-regulator.c
|
||||
F: drivers/regulator/bd71828-regulator.c
|
||||
F: drivers/regulator/bd718x7-regulator.c
|
||||
F: drivers/regulator/rohm-regulator.c
|
||||
F: drivers/rtc/rtc-bd70528.c
|
||||
F: drivers/watchdog/bd70528_wdt.c
|
||||
F: include/linux/mfd/rohm-bd70528.h
|
||||
F: include/linux/mfd/rohm-bd71828.h
|
||||
F: include/linux/mfd/rohm-bd718x7.h
|
||||
F: include/linux/mfd/rohm-generic.h
|
||||
F: include/linux/mfd/rohm-shared.h
|
||||
|
||||
ROSE NETWORK LAYER
|
||||
M: Ralf Baechle <ralf@linux-mips.org>
|
||||
L: linux-hams@vger.kernel.org
|
||||
|
|
|
@ -291,6 +291,10 @@ config CLKSRC_STM32
|
|||
select CLKSRC_MMIO
|
||||
select TIMER_OF
|
||||
|
||||
config CLKSRC_STM32_LP
|
||||
bool "Low power clocksource for STM32 SoCs"
|
||||
depends on MFD_STM32_LPTIMER || COMPILE_TEST
|
||||
|
||||
config CLKSRC_MPS2
|
||||
bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
|
||||
depends on GENERIC_SCHED_CLOCK
|
||||
|
|
|
@ -45,6 +45,7 @@ obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o
|
|||
obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o
|
||||
obj-$(CONFIG_CLKSRC_EFM32) += timer-efm32.o
|
||||
obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o
|
||||
obj-$(CONFIG_CLKSRC_STM32_LP) += timer-stm32-lp.o
|
||||
obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
|
||||
obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o
|
||||
obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o
|
||||
|
|
221
drivers/clocksource/timer-stm32-lp.c
Normal file
221
drivers/clocksource/timer-stm32-lp.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) STMicroelectronics 2019 - All Rights Reserved
|
||||
* Authors: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
|
||||
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/stm32-lptimer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
|
||||
#define CFGR_PSC_OFFSET 9
|
||||
#define STM32_LP_RATING 1000
|
||||
#define STM32_TARGET_CLKRATE (32000 * HZ)
|
||||
#define STM32_LP_MAX_PSC 7
|
||||
|
||||
struct stm32_lp_private {
|
||||
struct regmap *reg;
|
||||
struct clock_event_device clkevt;
|
||||
unsigned long period;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static struct stm32_lp_private*
|
||||
to_priv(struct clock_event_device *clkevt)
|
||||
{
|
||||
return container_of(clkevt, struct stm32_lp_private, clkevt);
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct stm32_lp_private *priv = to_priv(clkevt);
|
||||
|
||||
regmap_write(priv->reg, STM32_LPTIM_CR, 0);
|
||||
regmap_write(priv->reg, STM32_LPTIM_IER, 0);
|
||||
/* clear pending flags */
|
||||
regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_set_timer(unsigned long evt,
|
||||
struct clock_event_device *clkevt,
|
||||
int is_periodic)
|
||||
{
|
||||
struct stm32_lp_private *priv = to_priv(clkevt);
|
||||
|
||||
/* disable LPTIMER to be able to write into IER register*/
|
||||
regmap_write(priv->reg, STM32_LPTIM_CR, 0);
|
||||
/* enable ARR interrupt */
|
||||
regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);
|
||||
/* enable LPTIMER to be able to write into ARR register */
|
||||
regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);
|
||||
/* set next event counter */
|
||||
regmap_write(priv->reg, STM32_LPTIM_ARR, evt);
|
||||
|
||||
/* start counter */
|
||||
if (is_periodic)
|
||||
regmap_write(priv->reg, STM32_LPTIM_CR,
|
||||
STM32_LPTIM_CNTSTRT | STM32_LPTIM_ENABLE);
|
||||
else
|
||||
regmap_write(priv->reg, STM32_LPTIM_CR,
|
||||
STM32_LPTIM_SNGSTRT | STM32_LPTIM_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *clkevt)
|
||||
{
|
||||
return stm32_clkevent_lp_set_timer(evt, clkevt,
|
||||
clockevent_state_periodic(clkevt));
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_set_periodic(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct stm32_lp_private *priv = to_priv(clkevt);
|
||||
|
||||
return stm32_clkevent_lp_set_timer(priv->period, clkevt, true);
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_set_oneshot(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct stm32_lp_private *priv = to_priv(clkevt);
|
||||
|
||||
return stm32_clkevent_lp_set_timer(priv->period, clkevt, false);
|
||||
}
|
||||
|
||||
static irqreturn_t stm32_clkevent_lp_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
|
||||
struct stm32_lp_private *priv = to_priv(clkevt);
|
||||
|
||||
regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF);
|
||||
|
||||
if (clkevt->event_handler)
|
||||
clkevt->event_handler(clkevt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void stm32_clkevent_lp_set_prescaler(struct stm32_lp_private *priv,
|
||||
unsigned long *rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= STM32_LP_MAX_PSC; i++) {
|
||||
if (DIV_ROUND_CLOSEST(*rate, 1 << i) < STM32_TARGET_CLKRATE)
|
||||
break;
|
||||
}
|
||||
|
||||
regmap_write(priv->reg, STM32_LPTIM_CFGR, i << CFGR_PSC_OFFSET);
|
||||
|
||||
/* Adjust rate and period given the prescaler value */
|
||||
*rate = DIV_ROUND_CLOSEST(*rate, (1 << i));
|
||||
priv->period = DIV_ROUND_UP(*rate, HZ);
|
||||
}
|
||||
|
||||
static void stm32_clkevent_lp_init(struct stm32_lp_private *priv,
|
||||
struct device_node *np, unsigned long rate)
|
||||
{
|
||||
priv->clkevt.name = np->full_name;
|
||||
priv->clkevt.cpumask = cpu_possible_mask;
|
||||
priv->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT;
|
||||
priv->clkevt.set_state_shutdown = stm32_clkevent_lp_shutdown;
|
||||
priv->clkevt.set_state_periodic = stm32_clkevent_lp_set_periodic;
|
||||
priv->clkevt.set_state_oneshot = stm32_clkevent_lp_set_oneshot;
|
||||
priv->clkevt.set_next_event = stm32_clkevent_lp_set_next_event;
|
||||
priv->clkevt.rating = STM32_LP_RATING;
|
||||
|
||||
clockevents_config_and_register(&priv->clkevt, rate, 0x1,
|
||||
STM32_LPTIM_MAX_ARR);
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
|
||||
struct stm32_lp_private *priv;
|
||||
unsigned long rate;
|
||||
int ret, irq;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->reg = ddata->regmap;
|
||||
ret = clk_prepare_enable(ddata->clk);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
rate = clk_get_rate(ddata->clk);
|
||||
if (!rate) {
|
||||
ret = -EINVAL;
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0);
|
||||
if (irq <= 0) {
|
||||
ret = irq;
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) {
|
||||
ret = device_init_wakeup(&pdev->dev, true);
|
||||
if (ret)
|
||||
goto out_clk_disable;
|
||||
|
||||
ret = dev_pm_set_wake_irq(&pdev->dev, irq);
|
||||
if (ret)
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, stm32_clkevent_lp_irq_handler,
|
||||
IRQF_TIMER, pdev->name, &priv->clkevt);
|
||||
if (ret)
|
||||
goto out_clk_disable;
|
||||
|
||||
stm32_clkevent_lp_set_prescaler(priv, &rate);
|
||||
|
||||
stm32_clkevent_lp_init(priv, pdev->dev.parent->of_node, rate);
|
||||
|
||||
priv->dev = &pdev->dev;
|
||||
|
||||
return 0;
|
||||
|
||||
out_clk_disable:
|
||||
clk_disable_unprepare(ddata->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_clkevent_lp_remove(struct platform_device *pdev)
|
||||
{
|
||||
return -EBUSY; /* cannot unregister clockevent */
|
||||
}
|
||||
|
||||
static const struct of_device_id stm32_clkevent_lp_of_match[] = {
|
||||
{ .compatible = "st,stm32-lptimer-timer", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stm32_clkevent_lp_of_match);
|
||||
|
||||
static struct platform_driver stm32_clkevent_lp_driver = {
|
||||
.probe = stm32_clkevent_lp_probe,
|
||||
.remove = stm32_clkevent_lp_remove,
|
||||
.driver = {
|
||||
.name = "stm32-lptimer-timer",
|
||||
.of_match_table = of_match_ptr(stm32_clkevent_lp_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(stm32_clkevent_lp_driver);
|
||||
|
||||
MODULE_ALIAS("platform:stm32-lptimer-timer");
|
||||
MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -1193,18 +1193,6 @@ config MFD_SKY81452
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called sky81452.
|
||||
|
||||
config MFD_SMSC
|
||||
bool "SMSC ECE1099 series chips"
|
||||
depends on I2C=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
ece1099 chips from SMSC.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called smsc.
|
||||
|
||||
config MFD_SC27XX_PMIC
|
||||
tristate "Spreadtrum SC27xx PMICs"
|
||||
depends on ARCH_SPRD || COMPILE_TEST
|
||||
|
@ -2053,6 +2041,27 @@ config MFD_WCD934X
|
|||
This driver provides common support WCD934x audio codec and its
|
||||
associated Pin Controller, Soundwire Controller and Audio codec.
|
||||
|
||||
config MFD_KHADAS_MCU
|
||||
tristate "Support for Khadas System control Microcontroller"
|
||||
depends on I2C
|
||||
depends on ARCH_MESON || ARCH_ROCKCHIP || COMPILE_TEST
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Support for the Khadas System control Microcontroller interface
|
||||
present on their VIM and Edge boards.
|
||||
|
||||
This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and
|
||||
Edge boards.
|
||||
|
||||
It provides multiple boot control features like password check,
|
||||
power-on options, power-off control and system FAN control on recent
|
||||
boards.
|
||||
|
||||
This driver provides common support for accessing the device,
|
||||
additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
menu "Multimedia Capabilities Port drivers"
|
||||
depends on ARCH_SA1100
|
||||
|
||||
|
|
|
@ -127,7 +127,6 @@ obj-$(CONFIG_MFD_CPCAP) += motorola-cpcap.o
|
|||
obj-$(CONFIG_MCP) += mcp-core.o
|
||||
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
|
||||
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
|
||||
obj-$(CONFIG_MFD_SMSC) += smsc-ece1099.o
|
||||
obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
|
||||
|
||||
ifeq ($(CONFIG_SA1100_ASSABET),y)
|
||||
|
@ -262,5 +261,6 @@ obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o
|
|||
obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
|
||||
obj-$(CONFIG_MFD_STMFX) += stmfx.o
|
||||
obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o
|
||||
|
||||
obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
|
||||
|
|
|
@ -498,7 +498,7 @@ static ssize_t ab3100_get_set_reg(struct file *file,
|
|||
int i = 0;
|
||||
|
||||
/* Get userspace string and assure termination */
|
||||
buf_size = min(count, (sizeof(buf)-1));
|
||||
buf_size = min((ssize_t)count, (ssize_t)(sizeof(buf)-1));
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
buf[buf_size] = 0;
|
||||
|
|
|
@ -29,22 +29,22 @@
|
|||
|
||||
/**
|
||||
* struct ab3100_otp
|
||||
* @dev containing device
|
||||
* @locked whether the OTP is locked, after locking, no more bits
|
||||
* @dev: containing device
|
||||
* @locked: whether the OTP is locked, after locking, no more bits
|
||||
* can be changed but before locking it is still possible
|
||||
* to change bits from 1->0.
|
||||
* @freq clocking frequency for the OTP, this frequency is either
|
||||
* @freq: clocking frequency for the OTP, this frequency is either
|
||||
* 32768Hz or 1MHz/30
|
||||
* @paf product activation flag, indicates whether this is a real
|
||||
* @paf: product activation flag, indicates whether this is a real
|
||||
* product (paf true) or a lab board etc (paf false)
|
||||
* @imeich if this is set it is possible to override the
|
||||
* @imeich: if this is set it is possible to override the
|
||||
* IMEI number found in the tac, fac and svn fields with
|
||||
* (secured) software
|
||||
* @cid customer ID
|
||||
* @tac type allocation code of the IMEI
|
||||
* @fac final assembly code of the IMEI
|
||||
* @svn software version number of the IMEI
|
||||
* @debugfs a debugfs file used when dumping to file
|
||||
* @cid: customer ID
|
||||
* @tac: type allocation code of the IMEI
|
||||
* @fac: final assembly code of the IMEI
|
||||
* @svn: software version number of the IMEI
|
||||
* @debugfs: a debugfs file used when dumping to file
|
||||
*/
|
||||
struct ab3100_otp {
|
||||
struct device *dev;
|
||||
|
|
|
@ -1801,7 +1801,7 @@ static ssize_t ab8500_hwreg_write(struct file *file,
|
|||
int buf_size, ret;
|
||||
|
||||
/* Get userspace string and assure termination */
|
||||
buf_size = min(count, (sizeof(buf)-1));
|
||||
buf_size = min((int)count, (int)(sizeof(buf)-1));
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
buf[buf_size] = 0;
|
||||
|
|
|
@ -22,11 +22,9 @@
|
|||
/**
|
||||
* struct altr_sysmgr - Altera SOCFPGA System Manager
|
||||
* @regmap: the regmap used for System Manager accesses.
|
||||
* @base : the base address for the System Manager
|
||||
*/
|
||||
struct altr_sysmgr {
|
||||
struct regmap *regmap;
|
||||
resource_size_t *base;
|
||||
};
|
||||
|
||||
static struct platform_driver altr_sysmgr_driver;
|
||||
|
@ -91,6 +89,9 @@ static struct regmap_config altr_sysmgr_regmap_cfg = {
|
|||
* altr_sysmgr_regmap_lookup_by_phandle
|
||||
* Find the sysmgr previous configured in probe() and return regmap property.
|
||||
* Return: regmap if found or error if not found.
|
||||
*
|
||||
* @np: Pointer to device's Device Tree node
|
||||
* @property: Device Tree property name which references the sysmgr
|
||||
*/
|
||||
struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
|
||||
const char *property)
|
||||
|
@ -127,6 +128,7 @@ static int sysmgr_probe(struct platform_device *pdev)
|
|||
struct regmap_config sysmgr_config = altr_sysmgr_regmap_cfg;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
void __iomem *base;
|
||||
|
||||
sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL);
|
||||
if (!sysmgr)
|
||||
|
@ -139,22 +141,19 @@ static int sysmgr_probe(struct platform_device *pdev)
|
|||
sysmgr_config.max_register = resource_size(res) -
|
||||
sysmgr_config.reg_stride;
|
||||
if (of_device_is_compatible(np, "altr,sys-mgr-s10")) {
|
||||
/* Need physical address for SMCC call */
|
||||
sysmgr->base = (resource_size_t *)res->start;
|
||||
sysmgr_config.reg_read = s10_protected_reg_read;
|
||||
sysmgr_config.reg_write = s10_protected_reg_write;
|
||||
|
||||
regmap = devm_regmap_init(dev, NULL, sysmgr->base,
|
||||
/* Need physical address for SMCC call */
|
||||
regmap = devm_regmap_init(dev, NULL, (void *)res->start,
|
||||
&sysmgr_config);
|
||||
} else {
|
||||
sysmgr->base = devm_ioremap(dev, res->start,
|
||||
resource_size(res));
|
||||
if (!sysmgr->base)
|
||||
base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
sysmgr_config.max_register = res->end - res->start - 3;
|
||||
regmap = devm_regmap_init_mmio(dev, sysmgr->base,
|
||||
&sysmgr_config);
|
||||
regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config);
|
||||
}
|
||||
|
||||
if (IS_ERR(regmap)) {
|
||||
|
|
|
@ -80,7 +80,7 @@ int arizona_clk32k_disable(struct arizona *arizona)
|
|||
{
|
||||
mutex_lock(&arizona->clk_lock);
|
||||
|
||||
BUG_ON(arizona->clk32k_ref <= 0);
|
||||
WARN_ON(arizona->clk32k_ref <= 0);
|
||||
|
||||
arizona->clk32k_ref--;
|
||||
|
||||
|
@ -1426,6 +1426,15 @@ int arizona_dev_init(struct arizona *arizona)
|
|||
arizona_irq_exit(arizona);
|
||||
err_pm:
|
||||
pm_runtime_disable(arizona->dev);
|
||||
|
||||
switch (arizona->pdata.clk32k_src) {
|
||||
case ARIZONA_32KZ_MCLK1:
|
||||
case ARIZONA_32KZ_MCLK2:
|
||||
arizona_clk32k_disable(arizona);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
err_reset:
|
||||
arizona_enable_reset(arizona);
|
||||
regulator_disable(arizona->dcvdd);
|
||||
|
@ -1448,6 +1457,15 @@ int arizona_dev_exit(struct arizona *arizona)
|
|||
regulator_disable(arizona->dcvdd);
|
||||
regulator_put(arizona->dcvdd);
|
||||
|
||||
switch (arizona->pdata.clk32k_src) {
|
||||
case ARIZONA_32KZ_MCLK1:
|
||||
case ARIZONA_32KZ_MCLK2:
|
||||
arizona_clk32k_disable(arizona);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mfd_remove_devices(arizona->dev);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
|
||||
|
|
|
@ -237,7 +237,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_cycle);
|
|||
* atmel_smc_cs_conf_apply - apply an SMC CS conf
|
||||
* @regmap: the SMC regmap
|
||||
* @cs: the CS id
|
||||
* @conf the SMC CS conf to apply
|
||||
* @conf: the SMC CS conf to apply
|
||||
*
|
||||
* Applies an SMC CS configuration.
|
||||
* Only valid on at91sam9/avr32 SoCs.
|
||||
|
@ -257,7 +257,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply);
|
|||
* @regmap: the HSMC regmap
|
||||
* @cs: the CS id
|
||||
* @layout: the layout of registers
|
||||
* @conf the SMC CS conf to apply
|
||||
* @conf: the SMC CS conf to apply
|
||||
*
|
||||
* Applies an SMC CS configuration.
|
||||
* Only valid on post-sama5 SoCs.
|
||||
|
|
|
@ -63,6 +63,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
|
|||
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
|
||||
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
|
||||
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
|
||||
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
|
||||
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
|
||||
{ },
|
||||
};
|
||||
|
@ -74,11 +75,13 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
|
|||
{ "axp209", 0 },
|
||||
{ "axp221", 0 },
|
||||
{ "axp223", 0 },
|
||||
{ "axp803", 0 },
|
||||
{ "axp806", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id axp20x_i2c_acpi_match[] = {
|
||||
{
|
||||
.id = "INT33F4",
|
||||
|
@ -87,6 +90,7 @@ static const struct acpi_device_id axp20x_i2c_acpi_match[] = {
|
|||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, axp20x_i2c_acpi_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver axp20x_i2c_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -24,7 +24,7 @@ static struct class cros_class = {
|
|||
};
|
||||
|
||||
/**
|
||||
* cros_feature_to_name - CrOS feature id to name/short description.
|
||||
* struct cros_feature_to_name - CrOS feature id to name/short description.
|
||||
* @id: The feature identifier.
|
||||
* @name: Device name associated with the feature id.
|
||||
* @desc: Short name that will be displayed.
|
||||
|
@ -36,7 +36,7 @@ struct cros_feature_to_name {
|
|||
};
|
||||
|
||||
/**
|
||||
* cros_feature_to_cells - CrOS feature id to mfd cells association.
|
||||
* struct cros_feature_to_cells - CrOS feature id to mfd cells association.
|
||||
* @id: The feature identifier.
|
||||
* @mfd_cells: Pointer to the array of mfd cells that needs to be added.
|
||||
* @num_cells: Number of mfd cells into the array.
|
||||
|
|
|
@ -160,7 +160,6 @@ static int da9063_clear_fault_log(struct da9063 *da9063)
|
|||
|
||||
int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
||||
{
|
||||
int model, variant_id, variant_code;
|
||||
int ret;
|
||||
|
||||
ret = da9063_clear_fault_log(da9063);
|
||||
|
@ -171,36 +170,6 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
|||
da9063->irq_base = -1;
|
||||
da9063->chip_irq = irq;
|
||||
|
||||
ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model);
|
||||
if (ret < 0) {
|
||||
dev_err(da9063->dev, "Cannot read chip model id.\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (model != PMIC_CHIP_ID_DA9063) {
|
||||
dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &variant_id);
|
||||
if (ret < 0) {
|
||||
dev_err(da9063->dev, "Cannot read chip variant id.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
variant_code = variant_id >> DA9063_CHIP_VARIANT_SHIFT;
|
||||
|
||||
dev_info(da9063->dev,
|
||||
"Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
|
||||
model, variant_id);
|
||||
|
||||
if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
|
||||
dev_err(da9063->dev,
|
||||
"Cannot support variant code: 0x%02X\n", variant_code);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
da9063->variant_code = variant_code;
|
||||
|
||||
ret = da9063_irq_init(da9063);
|
||||
if (ret) {
|
||||
dev_err(da9063->dev, "Cannot initialize interrupts.\n");
|
||||
|
|
|
@ -22,12 +22,124 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
/*
|
||||
* Raw I2C access required for just accessing chip and variant info before we
|
||||
* know which device is present. The info read from the device using this
|
||||
* approach is then used to select the correct regmap tables.
|
||||
*/
|
||||
|
||||
#define DA9063_REG_PAGE_SIZE 0x100
|
||||
#define DA9063_REG_PAGED_ADDR_MASK 0xFF
|
||||
|
||||
enum da9063_page_sel_buf_fmt {
|
||||
DA9063_PAGE_SEL_BUF_PAGE_REG = 0,
|
||||
DA9063_PAGE_SEL_BUF_PAGE_VAL,
|
||||
DA9063_PAGE_SEL_BUF_SIZE,
|
||||
};
|
||||
|
||||
enum da9063_paged_read_msgs {
|
||||
DA9063_PAGED_READ_MSG_PAGE_SEL = 0,
|
||||
DA9063_PAGED_READ_MSG_REG_SEL,
|
||||
DA9063_PAGED_READ_MSG_DATA,
|
||||
DA9063_PAGED_READ_MSG_CNT,
|
||||
};
|
||||
|
||||
static int da9063_i2c_blockreg_read(struct i2c_client *client, u16 addr,
|
||||
u8 *buf, int count)
|
||||
{
|
||||
struct i2c_msg xfer[DA9063_PAGED_READ_MSG_CNT];
|
||||
u8 page_sel_buf[DA9063_PAGE_SEL_BUF_SIZE];
|
||||
u8 page_num, paged_addr;
|
||||
int ret;
|
||||
|
||||
/* Determine page info based on register address */
|
||||
page_num = (addr / DA9063_REG_PAGE_SIZE);
|
||||
if (page_num > 1) {
|
||||
dev_err(&client->dev, "Invalid register address provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
paged_addr = (addr % DA9063_REG_PAGE_SIZE) & DA9063_REG_PAGED_ADDR_MASK;
|
||||
page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_REG] = DA9063_REG_PAGE_CON;
|
||||
page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_VAL] =
|
||||
(page_num << DA9063_I2C_PAGE_SEL_SHIFT) & DA9063_REG_PAGE_MASK;
|
||||
|
||||
/* Write reg address, page selection */
|
||||
xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].addr = client->addr;
|
||||
xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].flags = 0;
|
||||
xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].len = DA9063_PAGE_SEL_BUF_SIZE;
|
||||
xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].buf = page_sel_buf;
|
||||
|
||||
/* Select register address */
|
||||
xfer[DA9063_PAGED_READ_MSG_REG_SEL].addr = client->addr;
|
||||
xfer[DA9063_PAGED_READ_MSG_REG_SEL].flags = 0;
|
||||
xfer[DA9063_PAGED_READ_MSG_REG_SEL].len = sizeof(paged_addr);
|
||||
xfer[DA9063_PAGED_READ_MSG_REG_SEL].buf = &paged_addr;
|
||||
|
||||
/* Read data */
|
||||
xfer[DA9063_PAGED_READ_MSG_DATA].addr = client->addr;
|
||||
xfer[DA9063_PAGED_READ_MSG_DATA].flags = I2C_M_RD;
|
||||
xfer[DA9063_PAGED_READ_MSG_DATA].len = count;
|
||||
xfer[DA9063_PAGED_READ_MSG_DATA].buf = buf;
|
||||
|
||||
ret = i2c_transfer(client->adapter, xfer, DA9063_PAGED_READ_MSG_CNT);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Paged block read failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != DA9063_PAGED_READ_MSG_CNT) {
|
||||
dev_err(&client->dev, "Paged block read failed to complete\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
DA9063_DEV_ID_REG = 0,
|
||||
DA9063_VAR_ID_REG,
|
||||
DA9063_CHIP_ID_REGS,
|
||||
};
|
||||
|
||||
static int da9063_get_device_type(struct i2c_client *i2c, struct da9063 *da9063)
|
||||
{
|
||||
u8 buf[DA9063_CHIP_ID_REGS];
|
||||
int ret;
|
||||
|
||||
ret = da9063_i2c_blockreg_read(i2c, DA9063_REG_DEVICE_ID, buf,
|
||||
DA9063_CHIP_ID_REGS);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (buf[DA9063_DEV_ID_REG] != PMIC_CHIP_ID_DA9063) {
|
||||
dev_err(da9063->dev,
|
||||
"Invalid chip device ID: 0x%02x\n",
|
||||
buf[DA9063_DEV_ID_REG]);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_info(da9063->dev,
|
||||
"Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
|
||||
buf[DA9063_DEV_ID_REG], buf[DA9063_VAR_ID_REG]);
|
||||
|
||||
da9063->variant_code =
|
||||
(buf[DA9063_VAR_ID_REG] & DA9063_VARIANT_ID_MRC_MASK)
|
||||
>> DA9063_VARIANT_ID_MRC_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Variant specific regmap configs
|
||||
*/
|
||||
|
||||
static const struct regmap_range da9063_ad_readable_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),
|
||||
regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
|
||||
regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_ad_writeable_ranges[] = {
|
||||
|
@ -72,7 +184,7 @@ static const struct regmap_range da9063_bb_readable_ranges[] = {
|
|||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
|
||||
regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
|
||||
regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_bb_writeable_ranges[] = {
|
||||
|
@ -85,7 +197,7 @@ static const struct regmap_range da9063_bb_writeable_ranges[] = {
|
|||
regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_bb_volatile_ranges[] = {
|
||||
static const struct regmap_range da9063_bb_da_volatile_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
|
||||
regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
|
||||
regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
|
||||
|
@ -107,9 +219,9 @@ static const struct regmap_access_table da9063_bb_writeable_table = {
|
|||
.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_bb_volatile_table = {
|
||||
.yes_ranges = da9063_bb_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
|
||||
static const struct regmap_access_table da9063_bb_da_volatile_table = {
|
||||
.yes_ranges = da9063_bb_da_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_bb_da_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_bb_readable_ranges[] = {
|
||||
|
@ -117,7 +229,7 @@ static const struct regmap_range da9063l_bb_readable_ranges[] = {
|
|||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
|
||||
regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
|
||||
regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_bb_writeable_ranges[] = {
|
||||
|
@ -129,7 +241,7 @@ static const struct regmap_range da9063l_bb_writeable_ranges[] = {
|
|||
regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_bb_volatile_ranges[] = {
|
||||
static const struct regmap_range da9063l_bb_da_volatile_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
|
||||
regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
|
||||
regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
|
||||
|
@ -151,15 +263,70 @@ static const struct regmap_access_table da9063l_bb_writeable_table = {
|
|||
.n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063l_bb_volatile_table = {
|
||||
.yes_ranges = da9063l_bb_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063l_bb_volatile_ranges),
|
||||
static const struct regmap_access_table da9063l_bb_da_volatile_table = {
|
||||
.yes_ranges = da9063l_bb_da_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063l_bb_da_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_da_readable_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),
|
||||
regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_da_writeable_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
|
||||
regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
|
||||
regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
|
||||
regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_da_readable_table = {
|
||||
.yes_ranges = da9063_da_readable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_da_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_da_writeable_table = {
|
||||
.yes_ranges = da9063_da_writeable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_da_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_da_readable_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),
|
||||
regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_da_writeable_ranges[] = {
|
||||
regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
|
||||
regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
|
||||
regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
|
||||
regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
|
||||
regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063l_da_readable_table = {
|
||||
.yes_ranges = da9063l_da_readable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063l_da_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063l_da_writeable_table = {
|
||||
.yes_ranges = da9063l_da_writeable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063l_da_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range_cfg da9063_range_cfg[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_CHIP_VARIANT,
|
||||
.range_max = DA9063_REG_CONFIG_ID,
|
||||
.selector_reg = DA9063_REG_PAGE_CON,
|
||||
.selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
|
||||
.selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
|
||||
|
@ -173,7 +340,7 @@ static struct regmap_config da9063_regmap_config = {
|
|||
.val_bits = 8,
|
||||
.ranges = da9063_range_cfg,
|
||||
.num_ranges = ARRAY_SIZE(da9063_range_cfg),
|
||||
.max_register = DA9063_REG_CHIP_VARIANT,
|
||||
.max_register = DA9063_REG_CONFIG_ID,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
@ -199,18 +366,72 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
|
|||
da9063->chip_irq = i2c->irq;
|
||||
da9063->type = id->driver_data;
|
||||
|
||||
if (da9063->variant_code == PMIC_DA9063_AD) {
|
||||
da9063_regmap_config.rd_table = &da9063_ad_readable_table;
|
||||
da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
|
||||
da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
|
||||
} else if (da9063->type == PMIC_TYPE_DA9063L) {
|
||||
da9063_regmap_config.rd_table = &da9063l_bb_readable_table;
|
||||
da9063_regmap_config.wr_table = &da9063l_bb_writeable_table;
|
||||
da9063_regmap_config.volatile_table = &da9063l_bb_volatile_table;
|
||||
} else {
|
||||
da9063_regmap_config.rd_table = &da9063_bb_readable_table;
|
||||
da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
|
||||
da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
|
||||
ret = da9063_get_device_type(i2c, da9063);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (da9063->type) {
|
||||
case PMIC_TYPE_DA9063:
|
||||
switch (da9063->variant_code) {
|
||||
case PMIC_DA9063_AD:
|
||||
da9063_regmap_config.rd_table =
|
||||
&da9063_ad_readable_table;
|
||||
da9063_regmap_config.wr_table =
|
||||
&da9063_ad_writeable_table;
|
||||
da9063_regmap_config.volatile_table =
|
||||
&da9063_ad_volatile_table;
|
||||
break;
|
||||
case PMIC_DA9063_BB:
|
||||
case PMIC_DA9063_CA:
|
||||
da9063_regmap_config.rd_table =
|
||||
&da9063_bb_readable_table;
|
||||
da9063_regmap_config.wr_table =
|
||||
&da9063_bb_writeable_table;
|
||||
da9063_regmap_config.volatile_table =
|
||||
&da9063_bb_da_volatile_table;
|
||||
break;
|
||||
case PMIC_DA9063_DA:
|
||||
da9063_regmap_config.rd_table =
|
||||
&da9063_da_readable_table;
|
||||
da9063_regmap_config.wr_table =
|
||||
&da9063_da_writeable_table;
|
||||
da9063_regmap_config.volatile_table =
|
||||
&da9063_bb_da_volatile_table;
|
||||
break;
|
||||
default:
|
||||
dev_err(da9063->dev,
|
||||
"Chip variant not supported for DA9063\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
break;
|
||||
case PMIC_TYPE_DA9063L:
|
||||
switch (da9063->variant_code) {
|
||||
case PMIC_DA9063_BB:
|
||||
case PMIC_DA9063_CA:
|
||||
da9063_regmap_config.rd_table =
|
||||
&da9063l_bb_readable_table;
|
||||
da9063_regmap_config.wr_table =
|
||||
&da9063l_bb_writeable_table;
|
||||
da9063_regmap_config.volatile_table =
|
||||
&da9063l_bb_da_volatile_table;
|
||||
break;
|
||||
case PMIC_DA9063_DA:
|
||||
da9063_regmap_config.rd_table =
|
||||
&da9063l_da_readable_table;
|
||||
da9063_regmap_config.wr_table =
|
||||
&da9063l_da_writeable_table;
|
||||
da9063_regmap_config.volatile_table =
|
||||
&da9063l_bb_da_volatile_table;
|
||||
break;
|
||||
default:
|
||||
dev_err(da9063->dev,
|
||||
"Chip variant not supported for DA9063L\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(da9063->dev, "Chip type not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
|
||||
|
|
|
@ -2276,6 +2276,8 @@ bool db8500_prcmu_is_ac_wake_requested(void)
|
|||
*
|
||||
* Saves the reset reason code and then sets the APE_SOFTRST register which
|
||||
* fires interrupt to fw
|
||||
*
|
||||
* @reset_code: The reason for system reset
|
||||
*/
|
||||
void db8500_prcmu_system_reset(u16 reset_code)
|
||||
{
|
||||
|
@ -3004,10 +3006,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent)
|
|||
return mfd_add_devices(parent, 0, ab850x_cell, 1, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
|
||||
*
|
||||
*/
|
||||
static int db8500_prcmu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
|
|
@ -287,7 +287,11 @@ static void dln2_rx(struct urb *urb)
|
|||
len = urb->actual_length - sizeof(struct dln2_header);
|
||||
|
||||
if (handle == DLN2_HANDLE_EVENT) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dln2->event_cb_lock, flags);
|
||||
dln2_run_event_callbacks(dln2, id, echo, data, len);
|
||||
spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
|
||||
} else {
|
||||
/* URB will be re-submitted in _dln2_transfer (free_rx_slot) */
|
||||
if (dln2_transfer_complete(dln2, urb, handle, echo))
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
|
||||
* http://www.hisilicon.com
|
||||
* Copyright (c) <2013-2017> Linaro Ltd.
|
||||
* http://www.linaro.org
|
||||
* https://www.linaro.org
|
||||
*
|
||||
* Author: Guodong Xu <guodong.xu@linaro.org>
|
||||
*/
|
||||
|
|
|
@ -201,6 +201,9 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x1ac4), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info },
|
||||
/* EBG */
|
||||
{ PCI_VDEVICE(INTEL, 0x1bad), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x1bae), (kernel_ulong_t)&bxt_uart_info },
|
||||
/* GLK */
|
||||
{ PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info },
|
||||
|
@ -230,6 +233,22 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
|
||||
/* TGL-H */
|
||||
{ PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43a9), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43aa), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43ab), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43ad), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43ae), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43d8), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43da), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43e8), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43e9), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43ea), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43eb), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43fb), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43fd), (kernel_ulong_t)&bxt_info },
|
||||
/* EHL */
|
||||
{ PCI_VDEVICE(INTEL, 0x4b28), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b29), (kernel_ulong_t)&bxt_uart_info },
|
||||
|
|
|
@ -91,13 +91,8 @@ static int bcove_ipc_byte_reg_write(void *context, unsigned int reg,
|
|||
{
|
||||
struct intel_soc_pmic *pmic = context;
|
||||
u8 ipc_in = val;
|
||||
int ret;
|
||||
|
||||
ret = intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in);
|
||||
}
|
||||
|
||||
static const struct regmap_config bcove_regmap_config = {
|
||||
|
|
|
@ -79,39 +79,31 @@ enum kempld_cells {
|
|||
KEMPLD_UART,
|
||||
};
|
||||
|
||||
static const struct mfd_cell kempld_devs[] = {
|
||||
[KEMPLD_I2C] = {
|
||||
.name = "kempld-i2c",
|
||||
},
|
||||
[KEMPLD_WDT] = {
|
||||
.name = "kempld-wdt",
|
||||
},
|
||||
[KEMPLD_GPIO] = {
|
||||
.name = "kempld-gpio",
|
||||
},
|
||||
[KEMPLD_UART] = {
|
||||
.name = "kempld-uart",
|
||||
},
|
||||
static const char *kempld_dev_names[] = {
|
||||
[KEMPLD_I2C] = "kempld-i2c",
|
||||
[KEMPLD_WDT] = "kempld-wdt",
|
||||
[KEMPLD_GPIO] = "kempld-gpio",
|
||||
[KEMPLD_UART] = "kempld-uart",
|
||||
};
|
||||
|
||||
#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_devs)
|
||||
#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_dev_names)
|
||||
|
||||
static int kempld_register_cells_generic(struct kempld_device_data *pld)
|
||||
{
|
||||
struct mfd_cell devs[KEMPLD_MAX_DEVS];
|
||||
struct mfd_cell devs[KEMPLD_MAX_DEVS] = {};
|
||||
int i = 0;
|
||||
|
||||
if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C)
|
||||
devs[i++] = kempld_devs[KEMPLD_I2C];
|
||||
devs[i++].name = kempld_dev_names[KEMPLD_I2C];
|
||||
|
||||
if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG)
|
||||
devs[i++] = kempld_devs[KEMPLD_WDT];
|
||||
devs[i++].name = kempld_dev_names[KEMPLD_WDT];
|
||||
|
||||
if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO)
|
||||
devs[i++] = kempld_devs[KEMPLD_GPIO];
|
||||
devs[i++].name = kempld_dev_names[KEMPLD_GPIO];
|
||||
|
||||
if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
|
||||
devs[i++] = kempld_devs[KEMPLD_UART];
|
||||
devs[i++].name = kempld_dev_names[KEMPLD_UART];
|
||||
|
||||
return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
|
||||
}
|
||||
|
|
142
drivers/mfd/khadas-mcu.c
Normal file
142
drivers/mfd/khadas-mcu.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for Khadas System control Microcontroller
|
||||
*
|
||||
* Copyright (C) 2020 BayLibre SAS
|
||||
*
|
||||
* Author(s): Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/khadas-mcu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (reg >= KHADAS_MCU_USER_DATA_0_REG &&
|
||||
reg < KHADAS_MCU_PWR_OFF_CMD_REG)
|
||||
return true;
|
||||
|
||||
switch (reg) {
|
||||
case KHADAS_MCU_PWR_OFF_CMD_REG:
|
||||
case KHADAS_MCU_PASSWD_START_REG:
|
||||
case KHADAS_MCU_CHECK_VEN_PASSWD_REG:
|
||||
case KHADAS_MCU_CHECK_USER_PASSWD_REG:
|
||||
case KHADAS_MCU_WOL_INIT_START_REG:
|
||||
case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool khadas_mcu_reg_writeable(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case KHADAS_MCU_PASSWD_VEN_0_REG:
|
||||
case KHADAS_MCU_PASSWD_VEN_1_REG:
|
||||
case KHADAS_MCU_PASSWD_VEN_2_REG:
|
||||
case KHADAS_MCU_PASSWD_VEN_3_REG:
|
||||
case KHADAS_MCU_PASSWD_VEN_4_REG:
|
||||
case KHADAS_MCU_PASSWD_VEN_5_REG:
|
||||
case KHADAS_MCU_MAC_0_REG:
|
||||
case KHADAS_MCU_MAC_1_REG:
|
||||
case KHADAS_MCU_MAC_2_REG:
|
||||
case KHADAS_MCU_MAC_3_REG:
|
||||
case KHADAS_MCU_MAC_4_REG:
|
||||
case KHADAS_MCU_MAC_5_REG:
|
||||
case KHADAS_MCU_USID_0_REG:
|
||||
case KHADAS_MCU_USID_1_REG:
|
||||
case KHADAS_MCU_USID_2_REG:
|
||||
case KHADAS_MCU_USID_3_REG:
|
||||
case KHADAS_MCU_USID_4_REG:
|
||||
case KHADAS_MCU_USID_5_REG:
|
||||
case KHADAS_MCU_VERSION_0_REG:
|
||||
case KHADAS_MCU_VERSION_1_REG:
|
||||
case KHADAS_MCU_DEVICE_NO_0_REG:
|
||||
case KHADAS_MCU_DEVICE_NO_1_REG:
|
||||
case KHADAS_MCU_FACTORY_TEST_REG:
|
||||
case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config khadas_mcu_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.reg_stride = 1,
|
||||
.val_bits = 8,
|
||||
.max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
|
||||
.volatile_reg = khadas_mcu_reg_volatile,
|
||||
.writeable_reg = khadas_mcu_reg_writeable,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static struct mfd_cell khadas_mcu_fan_cells[] = {
|
||||
/* VIM1/2 Rev13+ and VIM3 only */
|
||||
{ .name = "khadas-mcu-fan-ctrl", },
|
||||
};
|
||||
|
||||
static struct mfd_cell khadas_mcu_cells[] = {
|
||||
{ .name = "khadas-mcu-user-mem", },
|
||||
};
|
||||
|
||||
static int khadas_mcu_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct khadas_mcu *ddata;
|
||||
int ret;
|
||||
|
||||
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, ddata);
|
||||
|
||||
ddata->dev = dev;
|
||||
|
||||
ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
|
||||
if (IS_ERR(ddata->regmap)) {
|
||||
ret = PTR_ERR(ddata->regmap);
|
||||
dev_err(dev, "Failed to allocate register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
khadas_mcu_cells,
|
||||
ARRAY_SIZE(khadas_mcu_cells),
|
||||
NULL, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (of_find_property(dev->of_node, "#cooling-cells", NULL))
|
||||
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
khadas_mcu_fan_cells,
|
||||
ARRAY_SIZE(khadas_mcu_fan_cells),
|
||||
NULL, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id khadas_mcu_of_match[] = {
|
||||
{ .compatible = "khadas,mcu", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
|
||||
|
||||
static struct i2c_driver khadas_mcu_driver = {
|
||||
.driver = {
|
||||
.name = "khadas-mcu-core",
|
||||
.of_match_table = of_match_ptr(khadas_mcu_of_match),
|
||||
},
|
||||
.probe = khadas_mcu_probe,
|
||||
};
|
||||
module_i2c_driver(khadas_mcu_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Khadas MCU core driver");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -17,7 +17,6 @@
|
|||
#define LM3533_MAX_CURRENT_MAX 29800
|
||||
#define LM3533_MAX_CURRENT_STEP 800
|
||||
|
||||
#define LM3533_BRIGHTNESS_MAX 255
|
||||
#define LM3533_PWM_MAX 0x3f
|
||||
|
||||
#define LM3533_REG_PWM_BASE 0x14
|
||||
|
@ -89,41 +88,33 @@ int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_max_current);
|
||||
|
||||
#define lm3533_ctrlbank_set(_name, _NAME) \
|
||||
int lm3533_ctrlbank_set_##_name(struct lm3533_ctrlbank *cb, u8 val) \
|
||||
{ \
|
||||
u8 reg; \
|
||||
int ret; \
|
||||
\
|
||||
if (val > LM3533_##_NAME##_MAX) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \
|
||||
ret = lm3533_write(cb->lm3533, reg, val); \
|
||||
if (ret) \
|
||||
dev_err(cb->dev, "failed to set " #_name "\n"); \
|
||||
\
|
||||
return ret; \
|
||||
} \
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_##_name);
|
||||
int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u8 val)
|
||||
{
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
#define lm3533_ctrlbank_get(_name, _NAME) \
|
||||
int lm3533_ctrlbank_get_##_name(struct lm3533_ctrlbank *cb, u8 *val) \
|
||||
{ \
|
||||
u8 reg; \
|
||||
int ret; \
|
||||
\
|
||||
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \
|
||||
ret = lm3533_read(cb->lm3533, reg, val); \
|
||||
if (ret) \
|
||||
dev_err(cb->dev, "failed to get " #_name "\n"); \
|
||||
\
|
||||
return ret; \
|
||||
} \
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_##_name);
|
||||
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE);
|
||||
ret = lm3533_write(cb->lm3533, reg, val);
|
||||
if (ret)
|
||||
dev_err(cb->dev, "failed to set brightness\n");
|
||||
|
||||
lm3533_ctrlbank_set(brightness, BRIGHTNESS);
|
||||
lm3533_ctrlbank_get(brightness, BRIGHTNESS);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_brightness);
|
||||
|
||||
int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u8 *val)
|
||||
{
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE);
|
||||
ret = lm3533_read(cb->lm3533, reg, val);
|
||||
if (ret)
|
||||
dev_err(cb->dev, "failed to get brightness\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_brightness);
|
||||
|
||||
/*
|
||||
* PWM-input control mask:
|
||||
|
@ -135,9 +126,36 @@ lm3533_ctrlbank_get(brightness, BRIGHTNESS);
|
|||
* bit 1 - PWM-input enabled in Zone 0
|
||||
* bit 0 - PWM-input enabled
|
||||
*/
|
||||
lm3533_ctrlbank_set(pwm, PWM);
|
||||
lm3533_ctrlbank_get(pwm, PWM);
|
||||
int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val)
|
||||
{
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
if (val > LM3533_PWM_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE);
|
||||
ret = lm3533_write(cb->lm3533, reg, val);
|
||||
if (ret)
|
||||
dev_err(cb->dev, "failed to set PWM mask\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_pwm);
|
||||
|
||||
int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u8 *val)
|
||||
{
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE);
|
||||
ret = lm3533_read(cb->lm3533, reg, val);
|
||||
if (ret)
|
||||
dev_err(cb->dev, "failed to get PWM mask\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_pwm);
|
||||
|
||||
MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
|
||||
MODULE_DESCRIPTION("LM3533 Control Bank interface");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* Author: Keerthy <j-keerthy@ti.com>
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* Author: Keerthy <j-keerthy@ti.com>
|
||||
*/
|
||||
|
|
|
@ -44,7 +44,10 @@ static const char * const madera_core_supplies[] = {
|
|||
};
|
||||
|
||||
static const struct mfd_cell madera_ldo1_devs[] = {
|
||||
{ .name = "madera-ldo1" },
|
||||
{
|
||||
.name = "madera-ldo1",
|
||||
.level = MFD_DEP_LEVEL_HIGH,
|
||||
},
|
||||
};
|
||||
|
||||
static const char * const cs47l15_supplies[] = {
|
||||
|
@ -55,8 +58,8 @@ static const char * const cs47l15_supplies[] = {
|
|||
|
||||
static const struct mfd_cell cs47l15_devs[] = {
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq" },
|
||||
{ .name = "madera-gpio" },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-gpio", },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l15_supplies,
|
||||
|
@ -108,7 +111,7 @@ static const char * const cs47l85_supplies[] = {
|
|||
static const struct mfd_cell cs47l85_devs[] = {
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp" },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio", },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
|
@ -155,10 +158,10 @@ static const char * const cs47l92_supplies[] = {
|
|||
};
|
||||
|
||||
static const struct mfd_cell cs47l92_devs[] = {
|
||||
{ .name = "madera-pinctrl" },
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio" },
|
||||
{ .name = "madera-gpio", },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l92_supplies,
|
||||
|
@ -743,18 +746,22 @@ int madera_dev_exit(struct madera *madera)
|
|||
/* Prevent any IRQs being serviced while we clean up */
|
||||
disable_irq(madera->irq);
|
||||
|
||||
/*
|
||||
* DCVDD could be supplied by a child node, we must disable it before
|
||||
* removing the children, and prevent PM runtime from turning it back on
|
||||
*/
|
||||
pm_runtime_disable(madera->dev);
|
||||
pm_runtime_get_sync(madera->dev);
|
||||
|
||||
clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
|
||||
mfd_remove_devices(madera->dev);
|
||||
|
||||
pm_runtime_disable(madera->dev);
|
||||
|
||||
regulator_disable(madera->dcvdd);
|
||||
regulator_put(madera->dcvdd);
|
||||
|
||||
mfd_remove_devices(madera->dev);
|
||||
mfd_remove_devices_late(madera->dev);
|
||||
|
||||
pm_runtime_set_suspended(madera->dev);
|
||||
pm_runtime_put_noidle(madera->dev);
|
||||
|
||||
clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk);
|
||||
|
||||
madera_enable_hard_reset(madera);
|
||||
|
||||
regulator_bulk_disable(madera->num_core_supplies,
|
||||
|
|
|
@ -88,7 +88,6 @@ static int madera_i2c_probe(struct i2c_client *i2c,
|
|||
if (!madera)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config);
|
||||
if (IS_ERR(madera->regmap)) {
|
||||
ret = PTR_ERR(madera->regmap);
|
||||
|
|
|
@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(maxim_charger_currents);
|
|||
int maxim_charger_calc_reg_current(const struct maxim_charger_current *limits,
|
||||
unsigned int min_ua, unsigned int max_ua, u8 *dst)
|
||||
{
|
||||
unsigned int current_bits = 0xf;
|
||||
unsigned int current_bits;
|
||||
|
||||
if (min_ua > max_ua)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
@ -17,8 +18,17 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
static LIST_HEAD(mfd_of_node_list);
|
||||
|
||||
struct mfd_of_node_entry {
|
||||
struct list_head list;
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
};
|
||||
|
||||
static struct device_type mfd_dev_type = {
|
||||
.name = "mfd_device",
|
||||
};
|
||||
|
@ -107,6 +117,55 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
|
|||
}
|
||||
#endif
|
||||
|
||||
static int mfd_match_of_node_to_dev(struct platform_device *pdev,
|
||||
struct device_node *np,
|
||||
const struct mfd_cell *cell)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
struct mfd_of_node_entry *of_entry;
|
||||
const __be32 *reg;
|
||||
u64 of_node_addr;
|
||||
|
||||
/* Skip devices 'disabled' by Device Tree */
|
||||
if (!of_device_is_available(np))
|
||||
return -ENODEV;
|
||||
|
||||
/* Skip if OF node has previously been allocated to a device */
|
||||
list_for_each_entry(of_entry, &mfd_of_node_list, list)
|
||||
if (of_entry->np == np)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!cell->use_of_reg)
|
||||
/* No of_reg defined - allocate first free compatible match */
|
||||
goto allocate_of_node;
|
||||
|
||||
/* We only care about each node's first defined address */
|
||||
reg = of_get_address(np, 0, NULL, NULL);
|
||||
if (!reg)
|
||||
/* OF node does not contatin a 'reg' property to match to */
|
||||
return -EAGAIN;
|
||||
|
||||
of_node_addr = of_read_number(reg, of_n_addr_cells(np));
|
||||
|
||||
if (cell->of_reg != of_node_addr)
|
||||
/* No match */
|
||||
return -EAGAIN;
|
||||
|
||||
allocate_of_node:
|
||||
of_entry = kzalloc(sizeof(*of_entry), GFP_KERNEL);
|
||||
if (!of_entry)
|
||||
return -ENOMEM;
|
||||
|
||||
of_entry->dev = &pdev->dev;
|
||||
of_entry->np = np;
|
||||
list_add_tail(&of_entry->list, &mfd_of_node_list);
|
||||
|
||||
pdev->dev.of_node = np;
|
||||
pdev->dev.fwnode = &np->fwnode;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mfd_add_device(struct device *parent, int id,
|
||||
const struct mfd_cell *cell,
|
||||
struct resource *mem_base,
|
||||
|
@ -115,6 +174,7 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
struct resource *res;
|
||||
struct platform_device *pdev;
|
||||
struct device_node *np = NULL;
|
||||
struct mfd_of_node_entry *of_entry, *tmp;
|
||||
int ret = -ENOMEM;
|
||||
int platform_id;
|
||||
int r;
|
||||
|
@ -149,19 +209,22 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
if (ret < 0)
|
||||
goto fail_res;
|
||||
|
||||
if (parent->of_node && cell->of_compatible) {
|
||||
if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
|
||||
for_each_child_of_node(parent->of_node, np) {
|
||||
if (of_device_is_compatible(np, cell->of_compatible)) {
|
||||
if (!of_device_is_available(np)) {
|
||||
/* Ignore disabled devices error free */
|
||||
ret = 0;
|
||||
ret = mfd_match_of_node_to_dev(pdev, np, cell);
|
||||
if (ret == -EAGAIN)
|
||||
continue;
|
||||
if (ret)
|
||||
goto fail_alias;
|
||||
}
|
||||
pdev->dev.of_node = np;
|
||||
pdev->dev.fwnode = &np->fwnode;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
pr_warn("%s: Failed to locate of_node [id: %d]\n",
|
||||
cell->name, platform_id);
|
||||
}
|
||||
|
||||
mfd_acpi_add_device(cell, pdev);
|
||||
|
@ -170,13 +233,13 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
ret = platform_device_add_data(pdev,
|
||||
cell->platform_data, cell->pdata_size);
|
||||
if (ret)
|
||||
goto fail_alias;
|
||||
goto fail_of_entry;
|
||||
}
|
||||
|
||||
if (cell->properties) {
|
||||
ret = platform_device_add_properties(pdev, cell->properties);
|
||||
if (ret)
|
||||
goto fail_alias;
|
||||
goto fail_of_entry;
|
||||
}
|
||||
|
||||
for (r = 0; r < cell->num_resources; r++) {
|
||||
|
@ -213,18 +276,18 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
if (has_acpi_companion(&pdev->dev)) {
|
||||
ret = acpi_check_resource_conflict(&res[r]);
|
||||
if (ret)
|
||||
goto fail_alias;
|
||||
goto fail_of_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = platform_device_add_resources(pdev, res, cell->num_resources);
|
||||
if (ret)
|
||||
goto fail_alias;
|
||||
goto fail_of_entry;
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret)
|
||||
goto fail_alias;
|
||||
goto fail_of_entry;
|
||||
|
||||
if (cell->pm_runtime_no_callbacks)
|
||||
pm_runtime_no_callbacks(&pdev->dev);
|
||||
|
@ -233,6 +296,12 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
|
||||
return 0;
|
||||
|
||||
fail_of_entry:
|
||||
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
|
||||
if (of_entry->dev == &pdev->dev) {
|
||||
list_del(&of_entry->list);
|
||||
kfree(of_entry);
|
||||
}
|
||||
fail_alias:
|
||||
regulator_bulk_unregister_supply_alias(&pdev->dev,
|
||||
cell->parent_supplies,
|
||||
|
@ -287,6 +356,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
|
|||
{
|
||||
struct platform_device *pdev;
|
||||
const struct mfd_cell *cell;
|
||||
int *level = data;
|
||||
|
||||
if (dev->type != &mfd_dev_type)
|
||||
return 0;
|
||||
|
@ -294,16 +364,31 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
|
|||
pdev = to_platform_device(dev);
|
||||
cell = mfd_get_cell(pdev);
|
||||
|
||||
if (level && cell->level > *level)
|
||||
return 0;
|
||||
|
||||
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
|
||||
cell->num_parent_supplies);
|
||||
|
||||
kfree(cell);
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mfd_remove_devices_late(struct device *parent)
|
||||
{
|
||||
int level = MFD_DEP_LEVEL_HIGH;
|
||||
|
||||
device_for_each_child_reverse(parent, &level, mfd_remove_devices_fn);
|
||||
}
|
||||
EXPORT_SYMBOL(mfd_remove_devices_late);
|
||||
|
||||
void mfd_remove_devices(struct device *parent)
|
||||
{
|
||||
device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn);
|
||||
int level = MFD_DEP_LEVEL_NORMAL;
|
||||
|
||||
device_for_each_child_reverse(parent, &level, mfd_remove_devices_fn);
|
||||
}
|
||||
EXPORT_SYMBOL(mfd_remove_devices);
|
||||
|
||||
|
@ -318,6 +403,16 @@ static void devm_mfd_dev_release(struct device *dev, void *res)
|
|||
* Returns 0 on success or an appropriate negative error number on failure.
|
||||
* All child-devices of the MFD will automatically be removed when it gets
|
||||
* unbinded.
|
||||
*
|
||||
* @dev: Pointer to parent device.
|
||||
* @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care
|
||||
* of device numbering, or will be added to a device's cell_id.
|
||||
* @cells: Array of (struct mfd_cell)s describing child devices.
|
||||
* @n_devs: Number of child devices to register.
|
||||
* @mem_base: Parent register range resource for child devices.
|
||||
* @irq_base: Base of the range of virtual interrupt numbers allocated for
|
||||
* this MFD device. Unused if @domain is specified.
|
||||
* @domain: Interrupt domain to create mappings for hardware interrupts.
|
||||
*/
|
||||
int devm_mfd_add_devices(struct device *dev, int id,
|
||||
const struct mfd_cell *cells, int n_devs,
|
||||
|
|
|
@ -214,6 +214,28 @@ static const struct regmap_config cpcap_regmap_config = {
|
|||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int cpcap_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
||||
disable_irq(spi->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpcap_resume(struct device *dev)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
||||
enable_irq(spi->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cpcap_pm, cpcap_suspend, cpcap_resume);
|
||||
|
||||
static const struct mfd_cell cpcap_mfd_devices[] = {
|
||||
{
|
||||
.name = "cpcap_adc",
|
||||
|
@ -313,6 +335,7 @@ static struct spi_driver cpcap_driver = {
|
|||
.driver = {
|
||||
.name = "cpcap-core",
|
||||
.of_match_table = cpcap_of_match,
|
||||
.pm = &cpcap_pm,
|
||||
},
|
||||
.probe = cpcap_probe,
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI
|
||||
*
|
||||
* Copyright (C) 2011-2013 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Copyright (C) 2011-2013 Texas Instruments Incorporated - https://www.ti.com
|
||||
* Author: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
* Author: Roger Quadros <rogerq@ti.com>
|
||||
*/
|
||||
|
@ -120,7 +120,7 @@ static inline u32 usbhs_read(void __iomem *base, u32 reg)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
/*
|
||||
* Map 'enum usbhs_omap_port_mode' found in <linux/platform_data/usb-omap.h>
|
||||
* to the device tree binding portN-mode found in
|
||||
* 'Documentation/devicetree/bindings/mfd/omap-usb-host.txt'
|
||||
|
@ -526,6 +526,8 @@ static const struct of_device_id usbhs_child_match_table[] = {
|
|||
* usbhs_omap_probe - initialize TI-based HCDs
|
||||
*
|
||||
* Allocates basic resources for this USB host controller.
|
||||
*
|
||||
* @pdev: Pointer to this device's platform device structure
|
||||
*/
|
||||
static int usbhs_omap_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI
|
||||
*
|
||||
* Copyright (C) 2012-2013 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Copyright (C) 2012-2013 Texas Instruments Incorporated - https://www.ti.com
|
||||
* Author: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
* Author: Roger Quadros <rogerq@ti.com>
|
||||
*/
|
||||
|
@ -199,6 +199,8 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
|
|||
* usbtll_omap_probe - initialize TI-based HCDs
|
||||
*
|
||||
* Allocates basic resources for this USB host controller.
|
||||
*
|
||||
* @pdev: Pointer to this device's platform device structure
|
||||
*/
|
||||
static int usbtll_omap_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -96,7 +96,7 @@ struct rave_sp_deframer {
|
|||
* @data: Buffer to store reply payload in
|
||||
* @code: Expected reply code
|
||||
* @ackid: Expected reply ACK ID
|
||||
* @completion: Successful reply reception completion
|
||||
* @received: Successful reply reception completion
|
||||
*/
|
||||
struct rave_sp_reply {
|
||||
size_t length;
|
||||
|
|
|
@ -44,6 +44,9 @@ static bool rn5t618_volatile_reg(struct device *dev, unsigned int reg)
|
|||
case RN5T618_INTMON:
|
||||
case RN5T618_RTC_CTRL1 ... RN5T618_RTC_CTRL2:
|
||||
case RN5T618_RTC_SECONDS ... RN5T618_RTC_YEAR:
|
||||
case RN5T618_CHGSTATE:
|
||||
case RN5T618_CHGCTRL_IRR ... RN5T618_CHGERR_MONI:
|
||||
case RN5T618_CONTROL ... RN5T618_CC_AVEREG0:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -77,7 +80,7 @@ static const struct regmap_irq_chip rc5t619_irq_chip = {
|
|||
.mask_invert = true,
|
||||
};
|
||||
|
||||
static struct rn5t618 *rn5t618_pm_power_off;
|
||||
static struct i2c_client *rn5t618_pm_power_off;
|
||||
static struct notifier_block rn5t618_restart_handler;
|
||||
|
||||
static int rn5t618_irq_init(struct rn5t618 *rn5t618)
|
||||
|
@ -110,13 +113,38 @@ static int rn5t618_irq_init(struct rn5t618 *rn5t618)
|
|||
|
||||
static void rn5t618_trigger_poweroff_sequence(bool repower)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* disable automatic repower-on */
|
||||
regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_REPCNT,
|
||||
RN5T618_REPCNT_REPWRON,
|
||||
repower ? RN5T618_REPCNT_REPWRON : 0);
|
||||
ret = i2c_smbus_read_byte_data(rn5t618_pm_power_off, RN5T618_REPCNT);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret &= ~RN5T618_REPCNT_REPWRON;
|
||||
if (repower)
|
||||
ret |= RN5T618_REPCNT_REPWRON;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(rn5t618_pm_power_off,
|
||||
RN5T618_REPCNT, (u8)ret);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* start power-off sequence */
|
||||
regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_SLPCNT,
|
||||
RN5T618_SLPCNT_SWPWROFF, RN5T618_SLPCNT_SWPWROFF);
|
||||
ret = i2c_smbus_read_byte_data(rn5t618_pm_power_off, RN5T618_SLPCNT);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret |= RN5T618_SLPCNT_SWPWROFF;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(rn5t618_pm_power_off,
|
||||
RN5T618_SLPCNT, (u8)ret);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
dev_alert(&rn5t618_pm_power_off->dev, "Failed to shutdown (err = %d)\n", ret);
|
||||
}
|
||||
|
||||
static void rn5t618_power_off(void)
|
||||
|
@ -189,7 +217,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c)
|
|||
return ret;
|
||||
}
|
||||
|
||||
rn5t618_pm_power_off = priv;
|
||||
rn5t618_pm_power_off = i2c;
|
||||
if (of_device_is_system_power_controller(i2c->dev.of_node)) {
|
||||
if (!pm_power_off)
|
||||
pm_power_off = rn5t618_power_off;
|
||||
|
@ -211,9 +239,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c)
|
|||
|
||||
static int rn5t618_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct rn5t618 *priv = i2c_get_clientdata(i2c);
|
||||
|
||||
if (priv == rn5t618_pm_power_off) {
|
||||
if (i2c == rn5t618_pm_power_off) {
|
||||
rn5t618_pm_power_off = NULL;
|
||||
pm_power_off = NULL;
|
||||
}
|
||||
|
|
|
@ -241,13 +241,13 @@ static int si476x_core_parse_and_nag_about_error(struct si476x_core *core)
|
|||
/**
|
||||
* si476x_core_send_command() - sends a command to si476x and waits its
|
||||
* response
|
||||
* @core: si476x_device structure for the device we are
|
||||
* @core: si476x_device structure for the device we are
|
||||
* communicating with
|
||||
* @command: command id
|
||||
* @args: command arguments we are sending
|
||||
* @argn: actual size of @args
|
||||
* @response: buffer to place the expected response from the device
|
||||
* @respn: actual size of @response
|
||||
* @resp: buffer to place the expected response from the device
|
||||
* @respn: actual size of @resp
|
||||
* @usecs: amount of time to wait before reading the response (in
|
||||
* usecs)
|
||||
*
|
||||
|
@ -496,7 +496,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property);
|
|||
* enable 1MOhm pulldown
|
||||
* SI476X_DFS_DAUDIO - set the pin to be a part of digital
|
||||
* audio interface
|
||||
* @dout - DOUT pin function configuration:
|
||||
* @dout: - DOUT pin function configuration:
|
||||
* SI476X_DOUT_NOOP - do not modify the behaviour
|
||||
* SI476X_DOUT_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
|
@ -504,7 +504,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property);
|
|||
* port 1
|
||||
* SI476X_DOUT_I2S_INPUT - set this pin to be digital in on I2S
|
||||
* port 1
|
||||
* @xout - XOUT pin function configuration:
|
||||
* @xout: - XOUT pin function configuration:
|
||||
* SI476X_XOUT_NOOP - do not modify the behaviour
|
||||
* SI476X_XOUT_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
|
@ -540,25 +540,25 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg);
|
|||
|
||||
/**
|
||||
* si476x_cmd_zif_pin_cfg - send 'ZIF_PIN_CFG_COMMAND'
|
||||
* @core - device to send the command to
|
||||
* @iqclk - IQCL pin function configuration:
|
||||
* @core: - device to send the command to
|
||||
* @iqclk: - IQCL pin function configuration:
|
||||
* SI476X_IQCLK_NOOP - do not modify the behaviour
|
||||
* SI476X_IQCLK_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_IQCLK_IQ - set pin to be a part of I/Q interace
|
||||
* in master mode
|
||||
* @iqfs - IQFS pin function configuration:
|
||||
* @iqfs: - IQFS pin function configuration:
|
||||
* SI476X_IQFS_NOOP - do not modify the behaviour
|
||||
* SI476X_IQFS_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_IQFS_IQ - set pin to be a part of I/Q interace
|
||||
* in master mode
|
||||
* @iout - IOUT pin function configuration:
|
||||
* @iout: - IOUT pin function configuration:
|
||||
* SI476X_IOUT_NOOP - do not modify the behaviour
|
||||
* SI476X_IOUT_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_IOUT_OUTPUT - set pin to be I out
|
||||
* @qout - QOUT pin function configuration:
|
||||
* @qout: - QOUT pin function configuration:
|
||||
* SI476X_QOUT_NOOP - do not modify the behaviour
|
||||
* SI476X_QOUT_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
|
@ -590,29 +590,29 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg);
|
|||
/**
|
||||
* si476x_cmd_ic_link_gpo_ctl_pin_cfg - send
|
||||
* 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device
|
||||
* @core - device to send the command to
|
||||
* @icin - ICIN pin function configuration:
|
||||
* @core: - device to send the command to
|
||||
* @icin: - ICIN pin function configuration:
|
||||
* SI476X_ICIN_NOOP - do not modify the behaviour
|
||||
* SI476X_ICIN_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_ICIN_GPO1_HIGH - set pin to be an output, drive it high
|
||||
* SI476X_ICIN_GPO1_LOW - set pin to be an output, drive it low
|
||||
* SI476X_ICIN_IC_LINK - set the pin to be a part of Inter-Chip link
|
||||
* @icip - ICIP pin function configuration:
|
||||
* @icip: - ICIP pin function configuration:
|
||||
* SI476X_ICIP_NOOP - do not modify the behaviour
|
||||
* SI476X_ICIP_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_ICIP_GPO1_HIGH - set pin to be an output, drive it high
|
||||
* SI476X_ICIP_GPO1_LOW - set pin to be an output, drive it low
|
||||
* SI476X_ICIP_IC_LINK - set the pin to be a part of Inter-Chip link
|
||||
* @icon - ICON pin function configuration:
|
||||
* @icon: - ICON pin function configuration:
|
||||
* SI476X_ICON_NOOP - do not modify the behaviour
|
||||
* SI476X_ICON_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_ICON_I2S - set the pin to be a part of audio
|
||||
* interface in slave mode (DCLK)
|
||||
* SI476X_ICON_IC_LINK - set the pin to be a part of Inter-Chip link
|
||||
* @icop - ICOP pin function configuration:
|
||||
* @icop: - ICOP pin function configuration:
|
||||
* SI476X_ICOP_NOOP - do not modify the behaviour
|
||||
* SI476X_ICOP_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
|
@ -647,8 +647,8 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ic_link_gpo_ctl_pin_cfg);
|
|||
/**
|
||||
* si476x_cmd_ana_audio_pin_cfg - send 'ANA_AUDIO_PIN_CFG' to the
|
||||
* device
|
||||
* @core - device to send the command to
|
||||
* @lrout - LROUT pin function configuration:
|
||||
* @core: - device to send the command to
|
||||
* @lrout: - LROUT pin function configuration:
|
||||
* SI476X_LROUT_NOOP - do not modify the behaviour
|
||||
* SI476X_LROUT_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
|
@ -675,15 +675,15 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ana_audio_pin_cfg);
|
|||
|
||||
/**
|
||||
* si476x_cmd_intb_pin_cfg - send 'INTB_PIN_CFG' command to the device
|
||||
* @core - device to send the command to
|
||||
* @intb - INTB pin function configuration:
|
||||
* @core: - device to send the command to
|
||||
* @intb: - INTB pin function configuration:
|
||||
* SI476X_INTB_NOOP - do not modify the behaviour
|
||||
* SI476X_INTB_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
* SI476X_INTB_DAUDIO - set pin to be a part of digital
|
||||
* audio interface in slave mode
|
||||
* SI476X_INTB_IRQ - set pin to be an interrupt request line
|
||||
* @a1 - A1 pin function configuration:
|
||||
* @a1: - A1 pin function configuration:
|
||||
* SI476X_A1_NOOP - do not modify the behaviour
|
||||
* SI476X_A1_TRISTATE - put the pin in tristate condition,
|
||||
* enable 1MOhm pulldown
|
||||
|
@ -728,14 +728,10 @@ static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core,
|
|||
/**
|
||||
* si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the
|
||||
* device
|
||||
* @core - device to send the command to
|
||||
* @rsqack - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT,
|
||||
* RSSSILINT, BLENDINT, MULTHINT and MULTLINT
|
||||
* @attune - when set the values in the status report are the values
|
||||
* that were calculated at tune
|
||||
* @cancel - abort ongoing seek/tune opertation
|
||||
* @stcack - clear the STCINT bin in status register
|
||||
* @report - all signal quality information retured by the command
|
||||
* @core: - device to send the command to
|
||||
* @rsqargs: - pointer to a structure containing a group of sub-args
|
||||
* relevant to sending the RSQ status command
|
||||
* @report: - all signal quality information retured by the command
|
||||
* (if NULL then the output of the command is ignored)
|
||||
*
|
||||
* Function returns 0 on success and negative error code on failure
|
||||
|
@ -862,9 +858,9 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_am_acf_status);
|
|||
/**
|
||||
* si476x_cmd_fm_seek_start - send 'FM_SEEK_START' command to the
|
||||
* device
|
||||
* @core - device to send the command to
|
||||
* @seekup - if set the direction of the search is 'up'
|
||||
* @wrap - if set seek wraps when hitting band limit
|
||||
* @core: - device to send the command to
|
||||
* @seekup: - if set the direction of the search is 'up'
|
||||
* @wrap: - if set seek wraps when hitting band limit
|
||||
*
|
||||
* This function begins search for a valid station. The station is
|
||||
* considered valid when 'FM_VALID_SNR_THRESHOLD' and
|
||||
|
@ -890,12 +886,14 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start);
|
|||
/**
|
||||
* si476x_cmd_fm_rds_status - send 'FM_RDS_STATUS' command to the
|
||||
* device
|
||||
* @core - device to send the command to
|
||||
* @status_only - if set the data is not removed from RDSFIFO,
|
||||
* @core: - device to send the command to
|
||||
* @status_only: - if set the data is not removed from RDSFIFO,
|
||||
* RDSFIFOUSED is not decremented and data in all the
|
||||
* rest RDS data contains the last valid info received
|
||||
* @mtfifo if set the command clears RDS receive FIFO
|
||||
* @intack if set the command clards the RDSINT bit.
|
||||
* @mtfifo: if set the command clears RDS receive FIFO
|
||||
* @intack: if set the command clards the RDSINT bit.
|
||||
* @report: - all signal quality information retured by the command
|
||||
* (if NULL then the output of the command is ignored)
|
||||
*
|
||||
* Function returns 0 on success and negative error code on failure
|
||||
*/
|
||||
|
@ -1036,9 +1034,9 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_div_status);
|
|||
/**
|
||||
* si476x_cmd_am_seek_start - send 'FM_SEEK_START' command to the
|
||||
* device
|
||||
* @core - device to send the command to
|
||||
* @seekup - if set the direction of the search is 'up'
|
||||
* @wrap - if set seek wraps when hitting band limit
|
||||
* @core: - device to send the command to
|
||||
* @seekup: - if set the direction of the search is 'up'
|
||||
* @wrap: - if set seek wraps when hitting band limit
|
||||
*
|
||||
* This function begins search for a valid station. The station is
|
||||
* considered valid when 'FM_VALID_SNR_THRESHOLD' and
|
||||
|
|
|
@ -534,6 +534,11 @@ static irqreturn_t si476x_core_interrupt(int irq, void *dev)
|
|||
/**
|
||||
* si476x_firmware_version_to_revision()
|
||||
* @core: Core device structure
|
||||
* @func: Selects the boot function of the device:
|
||||
* *_BOOTLOADER - Boot loader
|
||||
* *_FM_RECEIVER - FM receiver
|
||||
* *_AM_RECEIVER - AM receiver
|
||||
* *_WB_RECEIVER - Weatherband receiver
|
||||
* @major: Firmware major number
|
||||
* @minor1: Firmware first minor number
|
||||
* @minor2: Firmware second minor number
|
||||
|
@ -583,7 +588,7 @@ static int si476x_core_fwver_to_revision(struct si476x_core *core,
|
|||
goto unknown_revision;
|
||||
}
|
||||
case SI476X_FUNC_BOOTLOADER:
|
||||
default: /* FALLTHROUG */
|
||||
default: /* FALLTHROUGH */
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* TI SMSC MFD Driver
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* Author: Sourav Poddar <sourav.poddar@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; GPL v2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/smsc.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
static const struct regmap_config smsc_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = SMSC_VEN_ID_H,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int smsc_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct smsc *smsc;
|
||||
int devid, rev, venid_l, venid_h;
|
||||
int ret;
|
||||
|
||||
smsc = devm_kzalloc(&i2c->dev, sizeof(*smsc), GFP_KERNEL);
|
||||
if (!smsc)
|
||||
return -ENOMEM;
|
||||
|
||||
smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
|
||||
if (IS_ERR(smsc->regmap))
|
||||
return PTR_ERR(smsc->regmap);
|
||||
|
||||
i2c_set_clientdata(i2c, smsc);
|
||||
smsc->dev = &i2c->dev;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
of_property_read_u32(i2c->dev.of_node, "clock", &smsc->clk);
|
||||
#endif
|
||||
|
||||
regmap_read(smsc->regmap, SMSC_DEV_ID, &devid);
|
||||
regmap_read(smsc->regmap, SMSC_DEV_REV, &rev);
|
||||
regmap_read(smsc->regmap, SMSC_VEN_ID_L, &venid_l);
|
||||
regmap_read(smsc->regmap, SMSC_VEN_ID_H, &venid_h);
|
||||
|
||||
dev_info(&i2c->dev, "SMSCxxx devid: %02x rev: %02x venid: %02x\n",
|
||||
devid, rev, (venid_h << 8) | venid_l);
|
||||
|
||||
ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (i2c->dev.of_node)
|
||||
ret = devm_of_platform_populate(&i2c->dev);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id smsc_i2c_id[] = {
|
||||
{ "smscece1099", 0},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct i2c_driver smsc_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "smsc",
|
||||
},
|
||||
.probe = smsc_i2c_probe,
|
||||
.id_table = smsc_i2c_id,
|
||||
};
|
||||
builtin_i2c_driver(smsc_i2c_driver);
|
|
@ -7,7 +7,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/sc27xx-pmic.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <uapi/linux/usb/charger.h>
|
||||
|
@ -93,73 +95,6 @@ enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type);
|
||||
|
||||
static const struct mfd_cell sprd_pmic_devs[] = {
|
||||
{
|
||||
.name = "sc27xx-wdt",
|
||||
.of_compatible = "sprd,sc2731-wdt",
|
||||
}, {
|
||||
.name = "sc27xx-rtc",
|
||||
.of_compatible = "sprd,sc2731-rtc",
|
||||
}, {
|
||||
.name = "sc27xx-charger",
|
||||
.of_compatible = "sprd,sc2731-charger",
|
||||
}, {
|
||||
.name = "sc27xx-chg-timer",
|
||||
.of_compatible = "sprd,sc2731-chg-timer",
|
||||
}, {
|
||||
.name = "sc27xx-fast-chg",
|
||||
.of_compatible = "sprd,sc2731-fast-chg",
|
||||
}, {
|
||||
.name = "sc27xx-chg-wdt",
|
||||
.of_compatible = "sprd,sc2731-chg-wdt",
|
||||
}, {
|
||||
.name = "sc27xx-typec",
|
||||
.of_compatible = "sprd,sc2731-typec",
|
||||
}, {
|
||||
.name = "sc27xx-flash",
|
||||
.of_compatible = "sprd,sc2731-flash",
|
||||
}, {
|
||||
.name = "sc27xx-eic",
|
||||
.of_compatible = "sprd,sc2731-eic",
|
||||
}, {
|
||||
.name = "sc27xx-efuse",
|
||||
.of_compatible = "sprd,sc2731-efuse",
|
||||
}, {
|
||||
.name = "sc27xx-thermal",
|
||||
.of_compatible = "sprd,sc2731-thermal",
|
||||
}, {
|
||||
.name = "sc27xx-adc",
|
||||
.of_compatible = "sprd,sc2731-adc",
|
||||
}, {
|
||||
.name = "sc27xx-audio-codec",
|
||||
.of_compatible = "sprd,sc2731-audio-codec",
|
||||
}, {
|
||||
.name = "sc27xx-regulator",
|
||||
.of_compatible = "sprd,sc2731-regulator",
|
||||
}, {
|
||||
.name = "sc27xx-vibrator",
|
||||
.of_compatible = "sprd,sc2731-vibrator",
|
||||
}, {
|
||||
.name = "sc27xx-keypad-led",
|
||||
.of_compatible = "sprd,sc2731-keypad-led",
|
||||
}, {
|
||||
.name = "sc27xx-bltc",
|
||||
.of_compatible = "sprd,sc2731-bltc",
|
||||
}, {
|
||||
.name = "sc27xx-fgu",
|
||||
.of_compatible = "sprd,sc2731-fgu",
|
||||
}, {
|
||||
.name = "sc27xx-7sreset",
|
||||
.of_compatible = "sprd,sc2731-7sreset",
|
||||
}, {
|
||||
.name = "sc27xx-poweroff",
|
||||
.of_compatible = "sprd,sc2731-poweroff",
|
||||
}, {
|
||||
.name = "sc27xx-syscon",
|
||||
.of_compatible = "sprd,sc2731-syscon",
|
||||
},
|
||||
};
|
||||
|
||||
static int sprd_pmic_spi_write(void *context, const void *data, size_t count)
|
||||
{
|
||||
struct device *dev = context;
|
||||
|
@ -250,10 +185,8 @@ static int sprd_pmic_probe(struct spi_device *spi)
|
|||
return -ENOMEM;
|
||||
|
||||
ddata->irq_chip.irqs = ddata->irqs;
|
||||
for (i = 0; i < pdata->num_irqs; i++) {
|
||||
ddata->irqs[i].reg_offset = i / pdata->num_irqs;
|
||||
ddata->irqs[i].mask = BIT(i % pdata->num_irqs);
|
||||
}
|
||||
for (i = 0; i < pdata->num_irqs; i++)
|
||||
ddata->irqs[i].mask = BIT(i);
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
|
||||
IRQF_ONESHOT | IRQF_NO_SUSPEND, 0,
|
||||
|
@ -263,12 +196,9 @@ static int sprd_pmic_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
|
||||
sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs),
|
||||
NULL, 0,
|
||||
regmap_irq_get_domain(ddata->irq_data));
|
||||
ret = devm_of_platform_populate(&spi->dev);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to register device %d\n", ret);
|
||||
dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ static const struct regmap_config stm32_lptimer_regmap_cfg = {
|
|||
.val_bits = 32,
|
||||
.reg_stride = sizeof(u32),
|
||||
.max_register = STM32_LPTIM_MAX_REGISTER,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
|
||||
|
|
|
@ -101,12 +101,14 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
|
|||
}
|
||||
}
|
||||
|
||||
syscon_config.name = of_node_full_name(np);
|
||||
syscon_config.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", np,
|
||||
(u64)res.start);
|
||||
syscon_config.reg_stride = reg_io_width;
|
||||
syscon_config.val_bits = reg_io_width * 8;
|
||||
syscon_config.max_register = resource_size(&res) - reg_io_width;
|
||||
|
||||
regmap = regmap_init_mmio(NULL, base, &syscon_config);
|
||||
kfree(syscon_config.name);
|
||||
if (IS_ERR(regmap)) {
|
||||
pr_err("regmap init failed\n");
|
||||
ret = PTR_ERR(regmap);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <linux/mfd/tc3589x.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/**
|
||||
/*
|
||||
* enum tc3589x_version - indicates the TC3589x version
|
||||
*/
|
||||
enum tc3589x_version {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* TI Touch Screen / ADC MFD driver
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
|
|
@ -404,7 +404,6 @@ static void tps65010_work(struct work_struct *work)
|
|||
tps65010_interrupt(tps);
|
||||
|
||||
if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) {
|
||||
int status;
|
||||
u8 chgconfig, tmp;
|
||||
|
||||
chgconfig = i2c_smbus_read_byte_data(tps->client,
|
||||
|
@ -415,8 +414,8 @@ static void tps65010_work(struct work_struct *work)
|
|||
else if (tps->vbus >= 100)
|
||||
chgconfig |= TPS_VBUS_CHARGING;
|
||||
|
||||
status = i2c_smbus_write_byte_data(tps->client,
|
||||
TPS_CHGCONFIG, chgconfig);
|
||||
i2c_smbus_write_byte_data(tps->client,
|
||||
TPS_CHGCONFIG, chgconfig);
|
||||
|
||||
/* vbus update fails unless VBUS is connected! */
|
||||
tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* TPS65217 chip family multi-function driver
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
@ -205,7 +205,7 @@ EXPORT_SYMBOL_GPL(tps65217_reg_read);
|
|||
/**
|
||||
* tps65217_reg_write: Write a single tps65217 register.
|
||||
*
|
||||
* @tps65217: Device to write to.
|
||||
* @tps: Device to write to.
|
||||
* @reg: Register to write to.
|
||||
* @val: Value to write.
|
||||
* @level: Password protected level
|
||||
|
@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(tps65217_reg_write);
|
|||
/**
|
||||
* tps65217_update_bits: Modify bits w.r.t mask, val and level.
|
||||
*
|
||||
* @tps65217: Device to write to.
|
||||
* @tps: Device to write to.
|
||||
* @reg: Register to read-write to.
|
||||
* @mask: Mask.
|
||||
* @val: Value to write.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Driver for TPS65218 Integrated power management chipsets
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -48,7 +48,7 @@ static const struct mfd_cell tps65218_cells[] = {
|
|||
/**
|
||||
* tps65218_reg_write: Write a single tps65218 register.
|
||||
*
|
||||
* @tps65218: Device to write to.
|
||||
* @tps: Device to write to.
|
||||
* @reg: Register to write to.
|
||||
* @val: Value to write.
|
||||
* @level: Password protected level
|
||||
|
@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(tps65218_reg_write);
|
|||
/**
|
||||
* tps65218_update_bits: Modify bits w.r.t mask, val and level.
|
||||
*
|
||||
* @tps65218: Device to write to.
|
||||
* @tps: Device to write to.
|
||||
* @reg: Register to read-write to.
|
||||
* @mask: Mask.
|
||||
* @val: Value to write.
|
||||
|
|
|
@ -309,18 +309,19 @@ static const struct irq_domain_ops tps6586x_domain_ops = {
|
|||
static irqreturn_t tps6586x_irq(int irq, void *data)
|
||||
{
|
||||
struct tps6586x *tps6586x = data;
|
||||
u32 acks;
|
||||
uint32_t acks;
|
||||
__le32 val;
|
||||
int ret = 0;
|
||||
|
||||
ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1,
|
||||
sizeof(acks), (uint8_t *)&acks);
|
||||
sizeof(acks), (uint8_t *)&val);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(tps6586x->dev, "failed to read interrupt status\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
acks = le32_to_cpu(acks);
|
||||
acks = le32_to_cpu(val);
|
||||
|
||||
while (acks) {
|
||||
int i = __ffs(acks);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Core functions for TI TPS65912x PMICs
|
||||
*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* I2C access driver for TI TPS65912x PMICs
|
||||
*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* SPI access driver for TI TPS65912x PMICs
|
||||
*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -477,7 +477,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
|
|||
|
||||
if (agent->imr_change_pending) {
|
||||
union {
|
||||
u32 word;
|
||||
__le32 word;
|
||||
u8 bytes[4];
|
||||
} imr;
|
||||
|
||||
|
@ -561,7 +561,7 @@ static inline int sih_read_isr(const struct sih *sih)
|
|||
int status;
|
||||
union {
|
||||
u8 bytes[4];
|
||||
u32 word;
|
||||
__le32 word;
|
||||
} isr;
|
||||
|
||||
/* FIXME need retry-on-error ... */
|
||||
|
|
|
@ -114,6 +114,8 @@ static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
|
|||
* The WM831x has a user key preventing writes to particularly
|
||||
* critical registers. This function locks those registers,
|
||||
* allowing writes to them.
|
||||
*
|
||||
* @wm831x: pointer to local driver data structure
|
||||
*/
|
||||
void wm831x_reg_lock(struct wm831x *wm831x)
|
||||
{
|
||||
|
@ -140,6 +142,8 @@ EXPORT_SYMBOL_GPL(wm831x_reg_lock);
|
|||
* The WM831x has a user key preventing writes to particularly
|
||||
* critical registers. This function locks those registers,
|
||||
* preventing spurious writes.
|
||||
*
|
||||
* @wm831x: pointer to local driver data structure
|
||||
*/
|
||||
int wm831x_reg_unlock(struct wm831x *wm831x)
|
||||
{
|
||||
|
|
|
@ -131,6 +131,8 @@ EXPORT_SYMBOL_GPL(wm8350_block_write);
|
|||
* The WM8350 has a hardware lock which can be used to prevent writes to
|
||||
* some registers (generally those which can cause particularly serious
|
||||
* problems if misused). This function enables that lock.
|
||||
*
|
||||
* @wm8350: pointer to local driver data structure
|
||||
*/
|
||||
int wm8350_reg_lock(struct wm8350 *wm8350)
|
||||
{
|
||||
|
@ -160,6 +162,8 @@ EXPORT_SYMBOL_GPL(wm8350_reg_lock);
|
|||
* problems if misused). This function disables that lock so updates
|
||||
* can be performed. For maximum safety this should be done only when
|
||||
* required.
|
||||
*
|
||||
* @wm8350: pointer to local driver data structure
|
||||
*/
|
||||
int wm8350_reg_unlock(struct wm8350 *wm8350)
|
||||
{
|
||||
|
|
|
@ -108,6 +108,8 @@ static const struct regmap_config wm8400_regmap_config = {
|
|||
/**
|
||||
* wm8400_reset_codec_reg_cache - Reset cached codec registers to
|
||||
* their default values.
|
||||
*
|
||||
* @wm8400: pointer to local driver data structure
|
||||
*/
|
||||
void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
|
||||
{
|
||||
|
|
|
@ -499,4 +499,15 @@ config SPRD_THERMAL
|
|||
help
|
||||
Support for the Spreadtrum thermal sensor driver in the Linux thermal
|
||||
framework.
|
||||
|
||||
config KHADAS_MCU_FAN_THERMAL
|
||||
tristate "Khadas MCU controller FAN cooling support"
|
||||
depends on OF || COMPILE_TEST
|
||||
depends on MFD_KHADAS_MCU
|
||||
select MFD_CORE
|
||||
select REGMAP
|
||||
help
|
||||
If you say yes here you get support for the FAN controlled
|
||||
by the Microcontroller found on the Khadas VIM boards.
|
||||
|
||||
endif
|
||||
|
|
|
@ -61,3 +61,4 @@ obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
|
|||
obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
|
||||
obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o
|
||||
obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o
|
||||
obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o
|
||||
|
|
162
drivers/thermal/khadas_mcu_fan.c
Normal file
162
drivers/thermal/khadas_mcu_fan.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Khadas MCU Controlled FAN driver
|
||||
*
|
||||
* Copyright (C) 2020 BayLibre SAS
|
||||
* Author(s): Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/khadas-mcu.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#define MAX_LEVEL 3
|
||||
|
||||
struct khadas_mcu_fan_ctx {
|
||||
struct khadas_mcu *mcu;
|
||||
unsigned int level;
|
||||
struct thermal_cooling_device *cdev;
|
||||
};
|
||||
|
||||
static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
|
||||
unsigned int level)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
|
||||
level);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx->level = level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
|
||||
unsigned long *state)
|
||||
{
|
||||
*state = MAX_LEVEL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int khadas_mcu_fan_get_cur_state(struct thermal_cooling_device *cdev,
|
||||
unsigned long *state)
|
||||
{
|
||||
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
|
||||
|
||||
*state = ctx->level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
||||
unsigned long state)
|
||||
{
|
||||
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
|
||||
|
||||
if (state > MAX_LEVEL)
|
||||
return -EINVAL;
|
||||
|
||||
if (state == ctx->level)
|
||||
return 0;
|
||||
|
||||
return khadas_mcu_fan_set_level(ctx, state);
|
||||
}
|
||||
|
||||
static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
|
||||
.get_max_state = khadas_mcu_fan_get_max_state,
|
||||
.get_cur_state = khadas_mcu_fan_get_cur_state,
|
||||
.set_cur_state = khadas_mcu_fan_set_cur_state,
|
||||
};
|
||||
|
||||
static int khadas_mcu_fan_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct khadas_mcu_fan_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
ctx->mcu = mcu;
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
cdev = devm_thermal_of_cooling_device_register(dev->parent,
|
||||
dev->parent->of_node, "khadas-mcu-fan", ctx,
|
||||
&khadas_mcu_fan_cooling_ops);
|
||||
if (IS_ERR(cdev)) {
|
||||
ret = PTR_ERR(cdev);
|
||||
dev_err(dev, "Failed to register khadas-mcu-fan as cooling device: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
ctx->cdev = cdev;
|
||||
thermal_cdev_update(cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void khadas_mcu_fan_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct khadas_mcu_fan_ctx *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
khadas_mcu_fan_set_level(ctx, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int khadas_mcu_fan_suspend(struct device *dev)
|
||||
{
|
||||
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
|
||||
unsigned int level_save = ctx->level;
|
||||
int ret;
|
||||
|
||||
ret = khadas_mcu_fan_set_level(ctx, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx->level = level_save;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int khadas_mcu_fan_resume(struct device *dev)
|
||||
{
|
||||
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
|
||||
|
||||
return khadas_mcu_fan_set_level(ctx, ctx->level);
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(khadas_mcu_fan_pm, khadas_mcu_fan_suspend,
|
||||
khadas_mcu_fan_resume);
|
||||
|
||||
static const struct platform_device_id khadas_mcu_fan_id_table[] = {
|
||||
{ .name = "khadas-mcu-fan-ctrl", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, khadas_mcu_fan_id_table);
|
||||
|
||||
static struct platform_driver khadas_mcu_fan_driver = {
|
||||
.probe = khadas_mcu_fan_probe,
|
||||
.shutdown = khadas_mcu_fan_shutdown,
|
||||
.driver = {
|
||||
.name = "khadas-mcu-fan-ctrl",
|
||||
.pm = &khadas_mcu_fan_pm,
|
||||
},
|
||||
.id_table = khadas_mcu_fan_id_table,
|
||||
};
|
||||
|
||||
module_platform_driver(khadas_mcu_fan_driver);
|
||||
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_DESCRIPTION("Khadas MCU FAN driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#define MFD_RES_SIZE(arr) (sizeof(arr) / sizeof(struct resource))
|
||||
|
||||
#define MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _match)\
|
||||
#define MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg, _use_of_reg, _match) \
|
||||
{ \
|
||||
.name = (_name), \
|
||||
.resources = (_res), \
|
||||
|
@ -22,24 +22,32 @@
|
|||
.platform_data = (_pdata), \
|
||||
.pdata_size = (_pdsize), \
|
||||
.of_compatible = (_compat), \
|
||||
.of_reg = (_of_reg), \
|
||||
.use_of_reg = (_use_of_reg), \
|
||||
.acpi_match = (_match), \
|
||||
.id = (_id), \
|
||||
}
|
||||
|
||||
#define OF_MFD_CELL(_name, _res, _pdata, _pdsize,_id, _compat) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, NULL) \
|
||||
#define OF_MFD_CELL_REG(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg, true, NULL)
|
||||
|
||||
#define ACPI_MFD_CELL(_name, _res, _pdata, _pdsize, _id, _match) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, _match) \
|
||||
#define OF_MFD_CELL(_name, _res, _pdata, _pdsize, _id, _compat) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, 0, false, NULL)
|
||||
|
||||
#define MFD_CELL_BASIC(_name, _res, _pdata, _pdsize, _id) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, NULL) \
|
||||
#define ACPI_MFD_CELL(_name, _res, _pdata, _pdsize, _id, _match) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, 0, false, _match)
|
||||
|
||||
#define MFD_CELL_RES(_name, _res) \
|
||||
MFD_CELL_ALL(_name, _res, NULL, 0, 0, NULL, NULL) \
|
||||
#define MFD_CELL_BASIC(_name, _res, _pdata, _pdsize, _id) \
|
||||
MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, 0, false, NULL)
|
||||
|
||||
#define MFD_CELL_NAME(_name) \
|
||||
MFD_CELL_ALL(_name, NULL, NULL, 0, 0, NULL, NULL) \
|
||||
#define MFD_CELL_RES(_name, _res) \
|
||||
MFD_CELL_ALL(_name, _res, NULL, 0, 0, NULL, 0, false, NULL)
|
||||
|
||||
#define MFD_CELL_NAME(_name) \
|
||||
MFD_CELL_ALL(_name, NULL, NULL, 0, 0, NULL, 0, false, NULL)
|
||||
|
||||
#define MFD_DEP_LEVEL_NORMAL 0
|
||||
#define MFD_DEP_LEVEL_HIGH 1
|
||||
|
||||
struct irq_domain;
|
||||
struct property_entry;
|
||||
|
@ -58,6 +66,7 @@ struct mfd_cell_acpi_match {
|
|||
struct mfd_cell {
|
||||
const char *name;
|
||||
int id;
|
||||
int level;
|
||||
|
||||
int (*enable)(struct platform_device *dev);
|
||||
int (*disable)(struct platform_device *dev);
|
||||
|
@ -78,6 +87,16 @@ struct mfd_cell {
|
|||
*/
|
||||
const char *of_compatible;
|
||||
|
||||
/*
|
||||
* Address as defined in Device Tree. Used to compement 'of_compatible'
|
||||
* (above) when matching OF nodes with devices that have identical
|
||||
* compatible strings
|
||||
*/
|
||||
const u64 of_reg;
|
||||
|
||||
/* Set to 'true' to use 'of_reg' (above) - allows for of_reg=0 */
|
||||
bool use_of_reg;
|
||||
|
||||
/* Matches ACPI */
|
||||
const struct mfd_cell_acpi_match *acpi_match;
|
||||
|
||||
|
@ -135,6 +154,7 @@ static inline int mfd_add_hotplug_devices(struct device *parent,
|
|||
}
|
||||
|
||||
extern void mfd_remove_devices(struct device *parent);
|
||||
extern void mfd_remove_devices_late(struct device *parent);
|
||||
|
||||
extern int devm_mfd_add_devices(struct device *dev, int id,
|
||||
const struct mfd_cell *cells, int n_devs,
|
||||
|
|
|
@ -35,7 +35,7 @@ struct da9055_pdata {
|
|||
int *gpio_rsel;
|
||||
/*
|
||||
* Regulator mode control bits value (GPI offset) that
|
||||
* that controls the regulator state, 0 if not available.
|
||||
* controls the regulator state, 0 if not available.
|
||||
*/
|
||||
enum gpio_select *reg_ren;
|
||||
/*
|
||||
|
|
|
@ -35,6 +35,7 @@ enum da9063_variant_codes {
|
|||
PMIC_DA9063_AD = 0x3,
|
||||
PMIC_DA9063_BB = 0x5,
|
||||
PMIC_DA9063_CA = 0x6,
|
||||
PMIC_DA9063_DA = 0x7,
|
||||
};
|
||||
|
||||
/* Interrupts */
|
||||
|
|
|
@ -292,8 +292,10 @@
|
|||
#define DA9063_BB_REG_GP_ID_19 0x134
|
||||
|
||||
/* Chip ID and variant */
|
||||
#define DA9063_REG_CHIP_ID 0x181
|
||||
#define DA9063_REG_CHIP_VARIANT 0x182
|
||||
#define DA9063_REG_DEVICE_ID 0x181
|
||||
#define DA9063_REG_VARIANT_ID 0x182
|
||||
#define DA9063_REG_CUSTOMER_ID 0x183
|
||||
#define DA9063_REG_CONFIG_ID 0x184
|
||||
|
||||
/*
|
||||
* PMIC registers bits
|
||||
|
@ -929,9 +931,6 @@
|
|||
#define DA9063_RTC_CLOCK 0x40
|
||||
#define DA9063_OUT_32K_EN 0x80
|
||||
|
||||
/* DA9063_REG_CHIP_VARIANT */
|
||||
#define DA9063_CHIP_VARIANT_SHIFT 4
|
||||
|
||||
/* DA9063_REG_BUCK_ILIM_A (addr=0x9A) */
|
||||
#define DA9063_BIO_ILIM_MASK 0x0F
|
||||
#define DA9063_BMEM_ILIM_MASK 0xF0
|
||||
|
@ -1065,4 +1064,10 @@
|
|||
#define DA9063_MON_A10_IDX_LDO9 0x04
|
||||
#define DA9063_MON_A10_IDX_LDO10 0x05
|
||||
|
||||
/* DA9063_REG_VARIANT_ID (addr=0x182) */
|
||||
#define DA9063_VARIANT_ID_VRC_SHIFT 0
|
||||
#define DA9063_VARIANT_ID_VRC_MASK 0x0F
|
||||
#define DA9063_VARIANT_ID_MRC_SHIFT 4
|
||||
#define DA9063_VARIANT_ID_MRC_MASK 0xF0
|
||||
|
||||
#endif /* _DA9063_REG_H */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
|
||||
* http://www.hisilicon.com
|
||||
* Copyright (c) <2013-2014> Linaro Ltd.
|
||||
* http://www.linaro.org
|
||||
* https://www.linaro.org
|
||||
*
|
||||
* Author: Guodong Xu <guodong.xu@linaro.org>
|
||||
*/
|
||||
|
|
91
include/linux/mfd/khadas-mcu.h
Normal file
91
include/linux/mfd/khadas-mcu.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Khadas System control Microcontroller Register map
|
||||
*
|
||||
* Copyright (C) 2020 BayLibre SAS
|
||||
*
|
||||
* Author(s): Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#ifndef MFD_KHADAS_MCU_H
|
||||
#define MFD_KHADAS_MCU_H
|
||||
|
||||
#define KHADAS_MCU_PASSWD_VEN_0_REG 0x00 /* RO */
|
||||
#define KHADAS_MCU_PASSWD_VEN_1_REG 0x01 /* RO */
|
||||
#define KHADAS_MCU_PASSWD_VEN_2_REG 0x02 /* RO */
|
||||
#define KHADAS_MCU_PASSWD_VEN_3_REG 0x03 /* RO */
|
||||
#define KHADAS_MCU_PASSWD_VEN_4_REG 0x04 /* RO */
|
||||
#define KHADAS_MCU_PASSWD_VEN_5_REG 0x05 /* RO */
|
||||
#define KHADAS_MCU_MAC_0_REG 0x06 /* RO */
|
||||
#define KHADAS_MCU_MAC_1_REG 0x07 /* RO */
|
||||
#define KHADAS_MCU_MAC_2_REG 0x08 /* RO */
|
||||
#define KHADAS_MCU_MAC_3_REG 0x09 /* RO */
|
||||
#define KHADAS_MCU_MAC_4_REG 0x0a /* RO */
|
||||
#define KHADAS_MCU_MAC_5_REG 0x0b /* RO */
|
||||
#define KHADAS_MCU_USID_0_REG 0x0c /* RO */
|
||||
#define KHADAS_MCU_USID_1_REG 0x0d /* RO */
|
||||
#define KHADAS_MCU_USID_2_REG 0x0e /* RO */
|
||||
#define KHADAS_MCU_USID_3_REG 0x0f /* RO */
|
||||
#define KHADAS_MCU_USID_4_REG 0x10 /* RO */
|
||||
#define KHADAS_MCU_USID_5_REG 0x11 /* RO */
|
||||
#define KHADAS_MCU_VERSION_0_REG 0x12 /* RO */
|
||||
#define KHADAS_MCU_VERSION_1_REG 0x13 /* RO */
|
||||
#define KHADAS_MCU_DEVICE_NO_0_REG 0x14 /* RO */
|
||||
#define KHADAS_MCU_DEVICE_NO_1_REG 0x15 /* RO */
|
||||
#define KHADAS_MCU_FACTORY_TEST_REG 0x16 /* R */
|
||||
#define KHADAS_MCU_BOOT_MODE_REG 0x20 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_WOL_REG 0x21 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_RTC_REG 0x22 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_EXP_REG 0x23 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_IR_REG 0x24 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_DCIN_REG 0x25 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_KEY_REG 0x26 /* RW */
|
||||
#define KHADAS_MCU_KEY_MODE_REG 0x27 /* RW */
|
||||
#define KHADAS_MCU_LED_MODE_ON_REG 0x28 /* RW */
|
||||
#define KHADAS_MCU_LED_MODE_OFF_REG 0x29 /* RW */
|
||||
#define KHADAS_MCU_SHUTDOWN_NORMAL_REG 0x2c /* RW */
|
||||
#define KHADAS_MCU_MAC_SWITCH_REG 0x2d /* RW */
|
||||
#define KHADAS_MCU_MCU_SLEEP_MODE_REG 0x2e /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_0_REG 0x2f /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_1_REG 0x30 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_2_REG 0x31 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_3_REG 0x32 /* RW */
|
||||
#define KHADAS_MCU_USB_PCIE_SWITCH_REG 0x33 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_0_REG 0x34 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_1_REG 0x35 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_2_REG 0x36 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_3_REG 0x37 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_0_REG 0x40 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_1_REG 0x41 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_2_REG 0x42 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_3_REG 0x43 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_4_REG 0x44 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_5_REG 0x45 /* RW */
|
||||
#define KHADAS_MCU_USER_DATA_0_REG 0x46 /* RW 56 bytes */
|
||||
#define KHADAS_MCU_PWR_OFF_CMD_REG 0x80 /* WO */
|
||||
#define KHADAS_MCU_PASSWD_START_REG 0x81 /* WO */
|
||||
#define KHADAS_MCU_CHECK_VEN_PASSWD_REG 0x82 /* WO */
|
||||
#define KHADAS_MCU_CHECK_USER_PASSWD_REG 0x83 /* WO */
|
||||
#define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG 0x86 /* RO */
|
||||
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
|
||||
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
|
||||
|
||||
enum {
|
||||
KHADAS_BOARD_VIM1 = 0x1,
|
||||
KHADAS_BOARD_VIM2,
|
||||
KHADAS_BOARD_VIM3,
|
||||
KHADAS_BOARD_EDGE = 0x11,
|
||||
KHADAS_BOARD_EDGE_V,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct khadas_mcu - Khadas MCU structure
|
||||
* @device: device reference used for logs
|
||||
* @regmap: register map
|
||||
*/
|
||||
struct khadas_mcu {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
#endif /* MFD_KHADAS_MCU_H */
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Functions to access LP873X power management chip.
|
||||
*
|
||||
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Functions to access LP87565 power management chip.
|
||||
*
|
||||
* Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_LP87565_H
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
struct gpio_desc;
|
||||
struct pinctrl_map;
|
||||
struct madera_codec_pdata;
|
||||
|
||||
/**
|
||||
* struct madera_pdata - Configuration data for Madera devices
|
||||
|
|
|
@ -131,7 +131,7 @@ enum max77693_pmic_reg {
|
|||
#define FLASH_INT_FLED1_SHORT BIT(3)
|
||||
#define FLASH_INT_OVER_CURRENT BIT(4)
|
||||
|
||||
/* Fast charge timer in in hours */
|
||||
/* Fast charge timer in hours */
|
||||
#define DEFAULT_FAST_CHARGE_TIMER 4
|
||||
/* microamps */
|
||||
#define DEFAULT_TOP_OFF_THRESHOLD_CURRENT 150000
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SMSC ECE1099
|
||||
*
|
||||
* Copyright 2012 Texas Instruments Inc.
|
||||
*
|
||||
* Author: Sourav Poddar <sourav.poddar@ti.com>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_SMSC_H
|
||||
#define __LINUX_MFD_SMSC_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define SMSC_ID_ECE1099 1
|
||||
#define SMSC_NUM_CLIENTS 2
|
||||
|
||||
#define SMSC_BASE_ADDR 0x38
|
||||
#define OMAP_GPIO_SMSC_IRQ 151
|
||||
|
||||
#define SMSC_MAXGPIO 32
|
||||
#define SMSC_BANK(offs) ((offs) >> 3)
|
||||
#define SMSC_BIT(offs) (1u << ((offs) & 0x7))
|
||||
|
||||
struct smsc {
|
||||
struct device *dev;
|
||||
struct i2c_client *i2c_clients[SMSC_NUM_CLIENTS];
|
||||
struct regmap *regmap;
|
||||
int clk;
|
||||
/* Stored chip id */
|
||||
int id;
|
||||
};
|
||||
|
||||
struct smsc_gpio;
|
||||
struct smsc_keypad;
|
||||
|
||||
static inline int smsc_read(struct device *child, unsigned int reg,
|
||||
unsigned int *dest)
|
||||
{
|
||||
struct smsc *smsc = dev_get_drvdata(child->parent);
|
||||
|
||||
return regmap_read(smsc->regmap, reg, dest);
|
||||
}
|
||||
|
||||
static inline int smsc_write(struct device *child, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
struct smsc *smsc = dev_get_drvdata(child->parent);
|
||||
|
||||
return regmap_write(smsc->regmap, reg, value);
|
||||
}
|
||||
|
||||
/* Registers for SMSC */
|
||||
#define SMSC_RESET 0xF5
|
||||
#define SMSC_GRP_INT 0xF9
|
||||
#define SMSC_CLK_CTRL 0xFA
|
||||
#define SMSC_WKUP_CTRL 0xFB
|
||||
#define SMSC_DEV_ID 0xFC
|
||||
#define SMSC_DEV_REV 0xFD
|
||||
#define SMSC_VEN_ID_L 0xFE
|
||||
#define SMSC_VEN_ID_H 0xFF
|
||||
|
||||
/* CLK VALUE */
|
||||
#define SMSC_CLK_VALUE 0x13
|
||||
|
||||
/* Registers for function GPIO INPUT */
|
||||
#define SMSC_GPIO_DATA_IN_START 0x00
|
||||
|
||||
/* Registers for function GPIO OUPUT */
|
||||
#define SMSC_GPIO_DATA_OUT_START 0x05
|
||||
|
||||
/* Definitions for SMSC GPIO CONFIGURATION REGISTER*/
|
||||
#define SMSC_GPIO_INPUT_LOW 0x01
|
||||
#define SMSC_GPIO_INPUT_RISING 0x09
|
||||
#define SMSC_GPIO_INPUT_FALLING 0x11
|
||||
#define SMSC_GPIO_INPUT_BOTH_EDGE 0x19
|
||||
#define SMSC_GPIO_OUTPUT_PP 0x21
|
||||
#define SMSC_GPIO_OUTPUT_OP 0x31
|
||||
|
||||
#define GRP_INT_STAT 0xf9
|
||||
#define SMSC_GPI_INT 0x0f
|
||||
#define SMSC_CFG_START 0x0A
|
||||
|
||||
/* Registers for SMSC GPIO INTERRUPT STATUS REGISTER*/
|
||||
#define SMSC_GPIO_INT_STAT_START 0x32
|
||||
|
||||
/* Registers for SMSC GPIO INTERRUPT MASK REGISTER*/
|
||||
#define SMSC_GPIO_INT_MASK_START 0x37
|
||||
|
||||
/* Registers for SMSC function KEYPAD*/
|
||||
#define SMSC_KP_OUT 0x40
|
||||
#define SMSC_KP_IN 0x41
|
||||
#define SMSC_KP_INT_STAT 0x42
|
||||
#define SMSC_KP_INT_MASK 0x43
|
||||
|
||||
/* Definitions for keypad */
|
||||
#define SMSC_KP_KSO 0x70
|
||||
#define SMSC_KP_KSI 0x51
|
||||
#define SMSC_KSO_ALL_LOW 0x20
|
||||
#define SMSC_KP_SET_LOW_PWR 0x0B
|
||||
#define SMSC_KP_SET_HIGH 0xFF
|
||||
#define SMSC_KSO_EVAL 0x00
|
||||
|
||||
#endif /* __LINUX_MFD_SMSC_H */
|
|
@ -27,10 +27,15 @@
|
|||
#define STM32_LPTIM_CMPOK BIT(3)
|
||||
|
||||
/* STM32_LPTIM_ICR - bit fields */
|
||||
#define STM32_LPTIM_ARRMCF BIT(1)
|
||||
#define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3)
|
||||
|
||||
/* STM32_LPTIM_IER - bit flieds */
|
||||
#define STM32_LPTIM_ARRMIE BIT(1)
|
||||
|
||||
/* STM32_LPTIM_CR - bit fields */
|
||||
#define STM32_LPTIM_CNTSTRT BIT(2)
|
||||
#define STM32_LPTIM_SNGSTRT BIT(1)
|
||||
#define STM32_LPTIM_ENABLE BIT(0)
|
||||
|
||||
/* STM32_LPTIM_CFGR - bit fields */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
/*
|
||||
* TI Touch Screen / ADC MFD driver
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Functions to access TPS65217 power management chip.
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Functions to access TPS65219 power management chip.
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
|
Loading…
Reference in New Issue
Block a user