- New Drivers
- Add Cirrus Logic Madera Codec (CS47L35, CS47L85 and CS47L90/91) driver - Add ChromeOS EC CEC driver - Add ROHM BD71837 PMIC driver - New Device Support - Add support for Dialog Semi DA9063L PMIC variant to DA9063 - Add support for Intel Ice Lake to Intel-PLSS-PCI - Add support for X-Powers AXP806 to AXP20x - New Functionality - Add support for USB Charging to the ChromeOS Embedded Controller - Add support for HDMI CEC to the ChromeOS Embedded Controller - Add support for HDMI CEC to Intel HDMI - Add support for accessory detection to Madera devices - Allow individual pins to be configured via DT' wlf,csnaddr-pd - Provide legacy platform specific EEPROM/Watchdog commands; rave-sp - Fix-ups - Trivial renaming/spelling fixes; cros_ec, da9063-* - Convert to Managed Resources (devm_*); da9063-*, ti_am335x_tscadc - Transition to helper macros/functions; da9063-* - Constify; kempld-core - Improve error path/messages; wm8994-core - Disable IRQs locally instead of relying on USB subsystem; dln2 - Remove unused code; rave-sp - New exports; sec-core - Bug Fixes - Fix possible false I2C transaction error; arizona-core - Fix declared memory area size; hi655x-pmic - Fix checksum type; rave-sp - Fix incorrect default serial port configuration: rave-sp - Fix incorrect coherent DMA mask for sub-devices; sm501 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAlt6fm8ACgkQUa+KL4f8 d2H8qA/8CLIKKEyc3CiQIF4LqmOPn+P20gSlnNdDFGHV+ZpVryL6qKItDy76nbQS +GrPCmhADDn7N224ENlv4TYsB1txr7iZvyNr6W7F0fbdTLq5Fl2+6WIB3NnopPPK MGhzR2jikfuYGwEG+BG3efvTnrjoi+NPbNPHDdoegOiy/Q1R8PhjMKh10xWo3pgG 0TeZVg61ztfewAiebieMixNz+ehzFKK959Lsa7neV2ZsstBbM8B44UpXmLF5JLYe SR1ai5etSPBLxEeTXxlE+oG+fnDWk9Eyile7z1Nwg4et9OiXdyqAXBoA+BNDj2N2 N8vHuU79pSra+XGbka/7Kyz8sXjb4u92mJlc1wDcsCF+hX+wGEmwkEUb0S4YEtOH 1POi4YuIq0WF1oLSgCla/Pui0OQPIZaT31XhInYLV7rAX+MPgH0cUuLDsmzcg4ut C6RvoSzWiGA2JVqlALExSDtAkWUoZLjYkqnPYmZwGs25xsGUqJmiw1E73HI0OWr/ EJuKQbeq/bOmRPqbbwO7z7peZJHOt6j344VCXBdP/sB7d/lR1sEGpxC03MIogHrA BuiPyfDXTF1NB/+ZPBFbSG2Xhcg51yL4ddRa1sMntP6J4Ht1dW7TOpLI21Yu3eRp jzKnA9DRa/LPUvoR1y+C2LxDeBcT5qFMg4mZedOgio/C0vCXvus= =4Yj4 -----END PGP SIGNATURE----- Merge tag 'mfd-next-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd Pull MFD updates from Lee Jones: "New Drivers: - Add Cirrus Logic Madera Codec (CS47L35, CS47L85 and CS47L90/91) driver - Add ChromeOS EC CEC driver - Add ROHM BD71837 PMIC driver New Device Support: - Add support for Dialog Semi DA9063L PMIC variant to DA9063 - Add support for Intel Ice Lake to Intel-PLSS-PCI - Add support for X-Powers AXP806 to AXP20x New Functionality: - Add support for USB Charging to the ChromeOS Embedded Controller - Add support for HDMI CEC to the ChromeOS Embedded Controller - Add support for HDMI CEC to Intel HDMI - Add support for accessory detection to Madera devices - Allow individual pins to be configured via DT' wlf,csnaddr-pd - Provide legacy platform specific EEPROM/Watchdog commands; rave-sp Fix-upsL - Trivial renaming/spelling fixes; cros_ec, da9063-* - Convert to Managed Resources (devm_*); da9063-*, ti_am335x_tscadc - Transition to helper macros/functions; da9063-* - Constify; kempld-core - Improve error path/messages; wm8994-core - Disable IRQs locally instead of relying on USB subsystem; dln2 - Remove unused code; rave-sp - New exports; sec-core Bug Fixes: - Fix possible false I2C transaction error; arizona-core - Fix declared memory area size; hi655x-pmic - Fix checksum type; rave-sp - Fix incorrect default serial port configuration: rave-sp - Fix incorrect coherent DMA mask for sub-devices; sm501" * tag 'mfd-next-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (60 commits) mfd: madera: Add register definitions for accessory detect mfd: sm501: Set coherent_dma_mask when creating subdevices mfd: bd71837: Devicetree bindings for ROHM BD71837 PMIC mfd: bd71837: Core driver for ROHM BD71837 PMIC media: platform: cros-ec-cec: Fix dependency on MFD_CROS_EC mfd: sec-core: Export OF module alias table mfd: as3722: Disable auto-power-on when AC OK mfd: axp20x: Support AXP806 in I2C mode mfd: axp20x: Add self-working mode support for AXP806 dt-bindings: mfd: axp20x: Add "self-working" mode for AXP806 mfd: wm8994: Allow to configure CS/ADDR Pulldown from dts mfd: wm8994: Allow to configure Speaker Mode Pullup from dts mfd: rave-sp: Emulate CMD_GET_STATUS on device that don't support it mfd: rave-sp: Add legacy watchdog ping command translation mfd: rave-sp: Add legacy EEPROM access command translation mfd: rave-sp: Initialize flow control and parity of the port mfd: rave-sp: Fix incorrectly specified checksum type mfd: rave-sp: Remove unused defines mfd: hi655x: Fix regmap area declared size for hi655x mfd: ti_am335x_tscadc: Fix struct clk memory leak ...
This commit is contained in:
Коммит
532c2b926d
|
@ -20,6 +20,8 @@ Optional properties:
|
|||
- ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on
|
||||
i2c scl/sda pins. Missing this will disable internal pullup on i2c
|
||||
scl/sda lines.
|
||||
- ams,enable-ac-ok-power-on: Boolean property, to enable exit out of power off
|
||||
mode with AC_OK pin (pin enabled in power off mode).
|
||||
|
||||
Optional submodule and their properties:
|
||||
=======================================
|
||||
|
|
|
@ -44,8 +44,11 @@ Optional properties:
|
|||
board is driving OTG VBus or not.
|
||||
(axp221 / axp223 / axp803/ axp813 only)
|
||||
|
||||
- x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is
|
||||
wired for master mode. The default is slave mode.
|
||||
- x-powers,self-working-mode and
|
||||
x-powers,master-mode: Boolean (axp806 only). Set either of these when the
|
||||
PMIC is wired for self-working mode or master mode.
|
||||
If neither is set then slave mode is assumed.
|
||||
This corresponds to how the MODESET pin is wired.
|
||||
|
||||
- <input>-supply: a phandle to the regulator supply node. May be omitted if
|
||||
inputs are unregulated, such as using the IPSOUT output
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
Cirrus Logic Madera class audio codecs Multi-Functional Device
|
||||
|
||||
These devices are audio SoCs with extensive digital capabilities and a range
|
||||
of analogue I/O.
|
||||
|
||||
See also the child driver bindings in:
|
||||
bindings/pinctrl/cirrus,madera-pinctrl.txt
|
||||
bindings/regulator/arizona-regulator.txt
|
||||
bindings/sound/madera.txt
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of the following chip-specific strings:
|
||||
"cirrus,cs47l35"
|
||||
"cirrus,cs47l85"
|
||||
"cirrus,cs47l90"
|
||||
"cirrus,cs47l91"
|
||||
"cirrus,wm1840"
|
||||
|
||||
- reg : I2C slave address when connected using I2C, chip select number when
|
||||
using SPI.
|
||||
|
||||
- DCVDD-supply : Power supply for the device as defined in
|
||||
bindings/regulator/regulator.txt
|
||||
Mandatory on CS47L35, CS47L90, CS47L91
|
||||
Optional on CS47L85, WM1840
|
||||
|
||||
- AVDD-supply, DBVDD1-supply, DBVDD2-supply, CPVDD1-supply, CPVDD2-supply :
|
||||
Power supplies for the device
|
||||
|
||||
- DBVDD3-supply, DBVDD4-supply : Power supplies for the device
|
||||
(CS47L85, CS47L90, CS47L91, WM1840)
|
||||
|
||||
- SPKVDDL-supply, SPKVDDR-supply : Power supplies for the device
|
||||
(CS47L85, WM1840)
|
||||
|
||||
- SPKVDD-supply : Power supply for the device
|
||||
(CS47L35)
|
||||
|
||||
- interrupt-controller : Indicates that this device is an interrupt controller
|
||||
|
||||
- #interrupt-cells: the number of cells to describe an IRQ, must be 2.
|
||||
The first cell is the IRQ number.
|
||||
The second cell is the flags, encoded as the trigger masks from
|
||||
bindings/interrupt-controller/interrupts.txt
|
||||
|
||||
- gpio-controller : Indicates this device is a GPIO controller.
|
||||
|
||||
- #gpio-cells : Must be 2. The first cell is the pin number. The second cell
|
||||
is reserved for future use and must be zero
|
||||
|
||||
- interrupt-parent : The parent interrupt controller.
|
||||
|
||||
- interrupts : The interrupt line the /IRQ signal for the device is
|
||||
connected to.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- MICVDD-supply : Power supply, only need to be specified if
|
||||
powered externally
|
||||
|
||||
- reset-gpios : One entry specifying the GPIO controlling /RESET.
|
||||
As defined in bindings/gpio.txt.
|
||||
Although optional, it is strongly recommended to use a hardware reset
|
||||
|
||||
- MICBIASx : Initial data for the MICBIAS regulators, as covered in
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
One for each MICBIAS generator (MICBIAS1, MICBIAS2, ...)
|
||||
(all codecs)
|
||||
|
||||
One for each output pin (MICBIAS1A, MIBCIAS1B, MICBIAS2A, ...)
|
||||
(all except CS47L85, WM1840)
|
||||
|
||||
The following following additional property is supported for the generator
|
||||
nodes:
|
||||
- cirrus,ext-cap : Set to 1 if the MICBIAS has external decoupling
|
||||
capacitors attached.
|
||||
|
||||
Optional child nodes:
|
||||
micvdd : Node containing initialization data for the micvdd regulator
|
||||
See bindings/regulator/arizona-regulator.txt
|
||||
|
||||
ldo1 : Node containing initialization data for the LDO1 regulator
|
||||
See bindings/regulator/arizona-regulator.txt
|
||||
(cs47l85, wm1840)
|
||||
|
||||
Example:
|
||||
|
||||
cs47l85@0 {
|
||||
compatible = "cirrus,cs47l85";
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&gpio 0>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <&host_irq1>;
|
||||
interrupt-parent = <&gic>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
* ROHM BD71837 Power Management Integrated Circuit bindings
|
||||
|
||||
BD71837MWV is a programmable Power Management IC for powering single-core,
|
||||
dual-core, and quad-core SoCs such as NXP-i.MX 8M. It is optimized for
|
||||
low BOM cost and compact solution footprint. It integrates 8 Buck
|
||||
egulators and 7 LDOs to provide all the power rails required by the SoC and
|
||||
the commonly used peripherals.
|
||||
|
||||
Datasheet for PMIC is available at:
|
||||
https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "rohm,bd71837".
|
||||
- reg : I2C slave address.
|
||||
- interrupt-parent : Phandle to the parent interrupt controller.
|
||||
- interrupts : The interrupt line the device is connected to.
|
||||
- clocks : The parent clock connected to PMIC. If this is missing
|
||||
32768 KHz clock is assumed.
|
||||
- #clock-cells : Should be 0.
|
||||
- regulators: : List of child nodes that specify the regulators.
|
||||
Please see ../regulator/rohm,bd71837-regulator.txt
|
||||
|
||||
Optional properties:
|
||||
- clock-output-names : Should contain name for output clock.
|
||||
|
||||
Example:
|
||||
|
||||
/* external oscillator node */
|
||||
osc: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <1>;
|
||||
clock-frequency = <32768>;
|
||||
clock-output-names = "osc";
|
||||
};
|
||||
|
||||
pmic: pmic@4b {
|
||||
compatible = "rohm,bd71837";
|
||||
reg = <0x4b>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <29 GPIO_ACTIVE_LOW>;
|
||||
interrupt-names = "irq";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&osc 0>;
|
||||
clock-output-names = "bd71837-32k-out";
|
||||
|
||||
regulators {
|
||||
buck1: BUCK1 {
|
||||
regulator-name = "buck1";
|
||||
regulator-min-microvolt = <700000>;
|
||||
regulator-max-microvolt = <1300000>;
|
||||
regulator-boot-on;
|
||||
regulator-ramp-delay = <1250>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* Clock consumer node */
|
||||
rtc@0 {
|
||||
compatible = "company,my-rtc";
|
||||
clock-names = "my-clock";
|
||||
clocks = <&pmic>;
|
||||
};
|
|
@ -22,7 +22,7 @@ Required properties:
|
|||
The valid regulator-compatible values are:
|
||||
tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
|
||||
vaux2, vaux33, vmmc, vbb
|
||||
tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
|
||||
tps65911: vrtc, vio, vdd1, vdd2, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
|
||||
ldo6, ldo7, ldo8
|
||||
|
||||
- xxx-supply: Input voltage supply regulator.
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
Cirrus Logic Madera class audio codecs pinctrl driver
|
||||
|
||||
The Cirrus Logic Madera codecs provide a number of GPIO functions for
|
||||
interfacing to external hardware and to provide logic outputs to other devices.
|
||||
Certain groups of GPIO pins also have an alternate function, normally as an
|
||||
audio interface.
|
||||
|
||||
The set of available GPIOs, functions and alternate function groups differs
|
||||
between codecs so refer to the datasheet for the codec for further information
|
||||
on what is supported on that device.
|
||||
|
||||
The properties for this driver exist within the parent MFD driver node.
|
||||
|
||||
See also
|
||||
the core bindings for the parent MFD driver:
|
||||
Documentation/devicetree/bindings/mfd/madera.txt
|
||||
|
||||
the generic pinmix bindings:
|
||||
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
|
||||
|
||||
Required properties of parent mfd node:
|
||||
- pinctrl-names : must be "default"
|
||||
- pinctrl-0 : a phandle to the node containing the subnodes containing default
|
||||
configurations
|
||||
|
||||
Required subnodes:
|
||||
One subnode is required to contain the default settings. It contains an
|
||||
arbitrary number of configuration subnodes, one for each group or pin
|
||||
configuration you want to apply as a default.
|
||||
|
||||
Required properties of configuration subnodes:
|
||||
- groups : name of one pin group to configure. One of:
|
||||
aif1, aif2, aif3, aif4, mif1, mif2, mif3, pdmspk1, pdmspk2,
|
||||
dmic4, dmic5, dmic6,
|
||||
gpio1, gpio2, ..., gpio40
|
||||
The gpioN groups select the single pin of this name for configuration
|
||||
|
||||
Optional properties of configuration subnodes:
|
||||
Any configuration option not explicitly listed in the dts will be left at
|
||||
chip default setting.
|
||||
|
||||
- function : name of function to assign to this group. One of:
|
||||
aif1, aif2, aif3, aif4, mif1, mif2, mif3, pdmspk1, pdmspk2,
|
||||
dmic3, dmic4, dmic5, dmic6,
|
||||
io, dsp-gpio, irq1, irq2,
|
||||
fll1-clk, fll1-lock, fll2-clk, fll2-lock, fll3-clk, fll3-lock,
|
||||
fllao-clk, fllao-lock,
|
||||
opclk, opclk-async, pwm1, pwm2, spdif,
|
||||
asrc1-in1-lock, asrc1-in2-lock, asrc2-in1-lock, asrc2-in2-lock,
|
||||
spkl-short-circuit, spkr-short-circuit, spk-shutdown,
|
||||
spk-overheat-shutdown, spk-overheat-warn,
|
||||
timer1-sts, timer2-sts, timer3-sts, timer4-sts, timer5-sts, timer6-sts,
|
||||
timer7-sts, timer8-sts,
|
||||
log1-fifo-ne, log2-fifo-ne, log3-fifo-ne, log4-fifo-ne, log5-fifo-ne,
|
||||
log6-fifo-ne, log7-fifo-ne, log8-fifo-ne,
|
||||
|
||||
- bias-disable : disable pull-up and pull-down
|
||||
- bias-bus-hold : enable buskeeper
|
||||
- bias-pull-up : output is pulled-up
|
||||
- bias-pull-down : output is pulled-down
|
||||
- drive-push-pull : CMOS output
|
||||
- drive-open-drain : open-drain output
|
||||
- drive-strength : drive strength in mA. Valid values are 4 or 8
|
||||
- input-schmitt-enable : enable schmitt-trigger mode
|
||||
- input-schmitt-disable : disable schmitt-trigger mode
|
||||
- input-debounce : A value of 0 disables debounce, a value !=0 enables
|
||||
debounce
|
||||
- output-low : set the pin to output mode with low level
|
||||
- output-high : set the pin to output mode with high level
|
||||
|
||||
Example:
|
||||
|
||||
cs47l85@0 {
|
||||
compatible = "cirrus,cs47l85";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cs47l85_defaults>;
|
||||
|
||||
cs47l85_defaults: cs47l85-gpio-defaults {
|
||||
aif1 {
|
||||
groups = "aif1";
|
||||
function = "aif1";
|
||||
bias-bus-hold;
|
||||
};
|
||||
|
||||
aif2 {
|
||||
groups = "aif2";
|
||||
function = "aif2";
|
||||
bias-bus-hold;
|
||||
};
|
||||
|
||||
opclk {
|
||||
groups = "gpio1";
|
||||
function = "opclk";
|
||||
bias-pull-up;
|
||||
drive-strength = <8>;
|
||||
};
|
||||
};
|
||||
};
|
16
MAINTAINERS
16
MAINTAINERS
|
@ -3562,6 +3562,22 @@ M: Christian Benvenuti <benve@cisco.com>
|
|||
S: Supported
|
||||
F: drivers/infiniband/hw/usnic/
|
||||
|
||||
CIRRUS LOGIC MADERA CODEC DRIVERS
|
||||
M: Charles Keepax <ckeepax@opensource.cirrus.com>
|
||||
M: Richard Fitzgerald <rf@opensource.cirrus.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
L: patches@opensource.cirrus.com
|
||||
T: git https://github.com/CirrusLogic/linux-drivers.git
|
||||
W: https://github.com/CirrusLogic/linux-drivers/wiki
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/mfd/madera.txt
|
||||
F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
|
||||
F: include/linux/mfd/madera/*
|
||||
F: drivers/gpio/gpio-madera*
|
||||
F: drivers/mfd/madera*
|
||||
F: drivers/mfd/cs47l*
|
||||
F: drivers/pinctrl/cirrus/*
|
||||
|
||||
CLANG-FORMAT FILE
|
||||
M: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
|
||||
S: Maintained
|
||||
|
|
|
@ -155,8 +155,8 @@ CONFIG_THERMAL_EMULATION=y
|
|||
CONFIG_WATCHDOG=y
|
||||
CONFIG_S3C2410_WATCHDOG=y
|
||||
CONFIG_MFD_CROS_EC=y
|
||||
CONFIG_MFD_CROS_EC_I2C=y
|
||||
CONFIG_MFD_CROS_EC_SPI=y
|
||||
CONFIG_CROS_EC_I2C=y
|
||||
CONFIG_CROS_EC_SPI=y
|
||||
CONFIG_MFD_MAX14577=y
|
||||
CONFIG_MFD_MAX77686=y
|
||||
CONFIG_MFD_MAX77693=y
|
||||
|
|
|
@ -490,8 +490,8 @@ CONFIG_MFD_AC100=y
|
|||
CONFIG_MFD_AXP20X_I2C=y
|
||||
CONFIG_MFD_AXP20X_RSB=y
|
||||
CONFIG_MFD_CROS_EC=m
|
||||
CONFIG_MFD_CROS_EC_I2C=m
|
||||
CONFIG_MFD_CROS_EC_SPI=m
|
||||
CONFIG_CROS_EC_I2C=m
|
||||
CONFIG_CROS_EC_SPI=m
|
||||
CONFIG_MFD_DA9063=m
|
||||
CONFIG_MFD_MAX14577=y
|
||||
CONFIG_MFD_MAX77686=y
|
||||
|
|
|
@ -398,8 +398,8 @@ CONFIG_MFD_AS3711=y
|
|||
CONFIG_MFD_BCM590XX=m
|
||||
CONFIG_MFD_AXP20X=y
|
||||
CONFIG_MFD_CROS_EC=m
|
||||
CONFIG_MFD_CROS_EC_I2C=m
|
||||
CONFIG_MFD_CROS_EC_SPI=m
|
||||
CONFIG_CROS_EC_I2C=m
|
||||
CONFIG_CROS_EC_SPI=m
|
||||
CONFIG_MFD_ASIC3=y
|
||||
CONFIG_PMIC_DA903X=y
|
||||
CONFIG_HTC_EGPIO=y
|
||||
|
|
|
@ -373,8 +373,8 @@ CONFIG_UNIPHIER_WATCHDOG=y
|
|||
CONFIG_BCM2835_WDT=y
|
||||
CONFIG_MFD_AXP20X_RSB=y
|
||||
CONFIG_MFD_CROS_EC=y
|
||||
CONFIG_MFD_CROS_EC_I2C=y
|
||||
CONFIG_MFD_CROS_EC_SPI=y
|
||||
CONFIG_CROS_EC_I2C=y
|
||||
CONFIG_CROS_EC_SPI=y
|
||||
CONFIG_MFD_CROS_EC_CHARDEV=m
|
||||
CONFIG_MFD_EXYNOS_LPASS=m
|
||||
CONFIG_MFD_HI6421_PMIC=y
|
||||
|
|
|
@ -1049,6 +1049,12 @@ config GPIO_LP87565
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called gpio-lp87565.
|
||||
|
||||
config GPIO_MADERA
|
||||
tristate "Cirrus Logic Madera class codecs"
|
||||
depends on PINCTRL_MADERA
|
||||
help
|
||||
Support for GPIOs on Cirrus Logic Madera class codecs.
|
||||
|
||||
config GPIO_MAX77620
|
||||
tristate "GPIO support for PMIC MAX77620 and MAX20024"
|
||||
depends on MFD_MAX77620
|
||||
|
|
|
@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
|
|||
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
|
||||
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
|
||||
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
|
||||
obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
|
||||
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
|
||||
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
|
||||
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* GPIO support for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/mfd/madera/core.h>
|
||||
#include <linux/mfd/madera/pdata.h>
|
||||
#include <linux/mfd/madera/registers.h>
|
||||
|
||||
struct madera_gpio {
|
||||
struct madera *madera;
|
||||
/* storage space for the gpio_chip we're using */
|
||||
struct gpio_chip gpio_chip;
|
||||
};
|
||||
|
||||
static int madera_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
|
||||
struct madera *madera = madera_gpio->madera;
|
||||
unsigned int reg_offset = 2 * offset;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_2 + reg_offset,
|
||||
&val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!(val & MADERA_GP1_DIR_MASK);
|
||||
}
|
||||
|
||||
static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
|
||||
struct madera *madera = madera_gpio->madera;
|
||||
unsigned int reg_offset = 2 * offset;
|
||||
|
||||
return regmap_update_bits(madera->regmap,
|
||||
MADERA_GPIO1_CTRL_2 + reg_offset,
|
||||
MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
|
||||
}
|
||||
|
||||
static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
|
||||
struct madera *madera = madera_gpio->madera;
|
||||
unsigned int reg_offset = 2 * offset;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_1 + reg_offset,
|
||||
&val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!(val & MADERA_GP1_LVL_MASK);
|
||||
}
|
||||
|
||||
static int madera_gpio_direction_out(struct gpio_chip *chip,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
|
||||
struct madera *madera = madera_gpio->madera;
|
||||
unsigned int reg_offset = 2 * offset;
|
||||
unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(madera->regmap,
|
||||
MADERA_GPIO1_CTRL_2 + reg_offset,
|
||||
MADERA_GP1_DIR_MASK, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return regmap_update_bits(madera->regmap,
|
||||
MADERA_GPIO1_CTRL_1 + reg_offset,
|
||||
MADERA_GP1_LVL_MASK, reg_val);
|
||||
}
|
||||
|
||||
static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
|
||||
struct madera *madera = madera_gpio->madera;
|
||||
unsigned int reg_offset = 2 * offset;
|
||||
unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(madera->regmap,
|
||||
MADERA_GPIO1_CTRL_1 + reg_offset,
|
||||
MADERA_GP1_LVL_MASK, reg_val);
|
||||
|
||||
/* set() doesn't return an error so log a warning */
|
||||
if (ret)
|
||||
dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
|
||||
MADERA_GPIO1_CTRL_1 + reg_offset, ret);
|
||||
}
|
||||
|
||||
static struct gpio_chip madera_gpio_chip = {
|
||||
.label = "madera",
|
||||
.owner = THIS_MODULE,
|
||||
.request = gpiochip_generic_request,
|
||||
.free = gpiochip_generic_free,
|
||||
.get_direction = madera_gpio_get_direction,
|
||||
.direction_input = madera_gpio_direction_in,
|
||||
.get = madera_gpio_get,
|
||||
.direction_output = madera_gpio_direction_out,
|
||||
.set = madera_gpio_set,
|
||||
.set_config = gpiochip_generic_config,
|
||||
.can_sleep = true,
|
||||
};
|
||||
|
||||
static int madera_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
|
||||
struct madera_pdata *pdata = dev_get_platdata(madera->dev);
|
||||
struct madera_gpio *madera_gpio;
|
||||
int ret;
|
||||
|
||||
madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!madera_gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
madera_gpio->madera = madera;
|
||||
|
||||
/* Construct suitable gpio_chip from the template in madera_gpio_chip */
|
||||
madera_gpio->gpio_chip = madera_gpio_chip;
|
||||
madera_gpio->gpio_chip.parent = pdev->dev.parent;
|
||||
|
||||
switch (madera->type) {
|
||||
case CS47L35:
|
||||
madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
|
||||
break;
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
|
||||
break;
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We want to be usable on systems that don't use devicetree or acpi */
|
||||
if (pdata && pdata->gpio_base)
|
||||
madera_gpio->gpio_chip.base = pdata->gpio_base;
|
||||
else
|
||||
madera_gpio->gpio_chip.base = -1;
|
||||
|
||||
ret = devm_gpiochip_add_data(&pdev->dev,
|
||||
&madera_gpio->gpio_chip,
|
||||
madera_gpio);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&pdev->dev, "Could not register gpiochip, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is part of a composite MFD device which can only be used with
|
||||
* the corresponding pinctrl driver. On all supported silicon the GPIO
|
||||
* to pinctrl mapping is fixed in the silicon, so we register it
|
||||
* explicitly instead of requiring a redundant gpio-ranges in the
|
||||
* devicetree.
|
||||
* In any case we also want to work on systems that don't use devicetree
|
||||
* or acpi.
|
||||
*/
|
||||
ret = gpiochip_add_pin_range(&madera_gpio->gpio_chip, "madera-pinctrl",
|
||||
0, 0, madera_gpio->gpio_chip.ngpio);
|
||||
if (ret) {
|
||||
dev_dbg(&pdev->dev, "Failed to add pin range (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver madera_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "madera-gpio",
|
||||
},
|
||||
.probe = madera_gpio_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(madera_gpio_driver);
|
||||
|
||||
MODULE_SOFTDEP("pre: pinctrl-madera");
|
||||
MODULE_DESCRIPTION("GPIO interface for Madera codecs");
|
||||
MODULE_AUTHOR("Nariman Poushin <nariman@opensource.cirrus.com>");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:madera-gpio");
|
|
@ -24,6 +24,7 @@ config DRM_I915
|
|||
select IOSF_MBI
|
||||
select CRC32
|
||||
select SND_HDA_I915 if SND_HDA_CORE
|
||||
select CEC_CORE if CEC_NOTIFIER
|
||||
help
|
||||
Choose this option if you have a system that has "Intel Graphics
|
||||
Media Accelerator" or "HD Graphics" integrated graphics,
|
||||
|
|
|
@ -126,6 +126,30 @@ enum port {
|
|||
|
||||
#define port_name(p) ((p) + 'A')
|
||||
|
||||
/*
|
||||
* Ports identifier referenced from other drivers.
|
||||
* Expected to remain stable over time
|
||||
*/
|
||||
static inline const char *port_identifier(enum port port)
|
||||
{
|
||||
switch (port) {
|
||||
case PORT_A:
|
||||
return "Port A";
|
||||
case PORT_B:
|
||||
return "Port B";
|
||||
case PORT_C:
|
||||
return "Port C";
|
||||
case PORT_D:
|
||||
return "Port D";
|
||||
case PORT_E:
|
||||
return "Port E";
|
||||
case PORT_F:
|
||||
return "Port F";
|
||||
default:
|
||||
return "<invalid>";
|
||||
}
|
||||
}
|
||||
|
||||
enum tc_port {
|
||||
PORT_TC_NONE = -1,
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
/**
|
||||
* __wait_for - magic wait macro
|
||||
|
@ -1016,6 +1017,7 @@ struct intel_hdmi {
|
|||
bool has_audio;
|
||||
bool rgb_quant_range_selectable;
|
||||
struct intel_connector *attached_connector;
|
||||
struct cec_notifier *cec_notifier;
|
||||
};
|
||||
|
||||
struct intel_dp_mst_encoder;
|
||||
|
|
|
@ -1899,6 +1899,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
|
|||
connected = true;
|
||||
}
|
||||
|
||||
cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
|
@ -1907,6 +1909,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
|
|||
{
|
||||
enum drm_connector_status status;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
|
@ -1922,6 +1925,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
|
|||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
|
||||
|
||||
if (status != connector_status_connected)
|
||||
cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2062,6 +2068,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
|
|||
|
||||
static void intel_hdmi_destroy(struct drm_connector *connector)
|
||||
{
|
||||
if (intel_attached_hdmi(connector)->cec_notifier)
|
||||
cec_notifier_put(intel_attached_hdmi(connector)->cec_notifier);
|
||||
kfree(to_intel_connector(connector)->detect_edid);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
|
@ -2382,6 +2390,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
|
||||
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
|
||||
}
|
||||
|
||||
intel_hdmi->cec_notifier = cec_notifier_get_conn(dev->dev,
|
||||
port_identifier(port));
|
||||
if (!intel_hdmi->cec_notifier)
|
||||
DRM_DEBUG_KMS("CEC notifier get failed\n");
|
||||
}
|
||||
|
||||
void intel_hdmi_init(struct drm_i915_private *dev_priv,
|
||||
|
|
|
@ -721,7 +721,7 @@ config KEYBOARD_CROS_EC
|
|||
help
|
||||
Say Y here to enable the matrix keyboard used by ChromeOS devices
|
||||
and implemented on the ChromeOS EC. You must enable one bus option
|
||||
(MFD_CROS_EC_I2C or MFD_CROS_EC_SPI) to use this.
|
||||
(CROS_EC_I2C or CROS_EC_SPI) to use this.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_keyb.
|
||||
|
|
|
@ -21,6 +21,7 @@ struct cec_notifier {
|
|||
struct list_head head;
|
||||
struct kref kref;
|
||||
struct device *dev;
|
||||
const char *conn;
|
||||
struct cec_adapter *cec_adap;
|
||||
void (*callback)(struct cec_adapter *adap, u16 pa);
|
||||
|
||||
|
@ -30,13 +31,14 @@ struct cec_notifier {
|
|||
static LIST_HEAD(cec_notifiers);
|
||||
static DEFINE_MUTEX(cec_notifiers_lock);
|
||||
|
||||
struct cec_notifier *cec_notifier_get(struct device *dev)
|
||||
struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
|
||||
{
|
||||
struct cec_notifier *n;
|
||||
|
||||
mutex_lock(&cec_notifiers_lock);
|
||||
list_for_each_entry(n, &cec_notifiers, head) {
|
||||
if (n->dev == dev) {
|
||||
if (n->dev == dev &&
|
||||
(!conn || !strcmp(n->conn, conn))) {
|
||||
kref_get(&n->kref);
|
||||
mutex_unlock(&cec_notifiers_lock);
|
||||
return n;
|
||||
|
@ -46,6 +48,8 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
|
|||
if (!n)
|
||||
goto unlock;
|
||||
n->dev = dev;
|
||||
if (conn)
|
||||
n->conn = kstrdup(conn, GFP_KERNEL);
|
||||
n->phys_addr = CEC_PHYS_ADDR_INVALID;
|
||||
mutex_init(&n->lock);
|
||||
kref_init(&n->kref);
|
||||
|
@ -54,7 +58,7 @@ unlock:
|
|||
mutex_unlock(&cec_notifiers_lock);
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_get);
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_get_conn);
|
||||
|
||||
static void cec_notifier_release(struct kref *kref)
|
||||
{
|
||||
|
@ -62,6 +66,7 @@ static void cec_notifier_release(struct kref *kref)
|
|||
container_of(kref, struct cec_notifier, kref);
|
||||
|
||||
list_del(&n->head);
|
||||
kfree(n->conn);
|
||||
kfree(n);
|
||||
}
|
||||
|
||||
|
|
|
@ -536,6 +536,17 @@ menuconfig CEC_PLATFORM_DRIVERS
|
|||
|
||||
if CEC_PLATFORM_DRIVERS
|
||||
|
||||
config VIDEO_CROS_EC_CEC
|
||||
tristate "ChromeOS EC CEC driver"
|
||||
depends on MFD_CROS_EC
|
||||
select CEC_CORE
|
||||
select CEC_NOTIFIER
|
||||
---help---
|
||||
If you say yes here you will get support for the
|
||||
ChromeOS Embedded Controller's CEC.
|
||||
The CEC bus is present in the HDMI connector and enables communication
|
||||
between compatible devices.
|
||||
|
||||
config VIDEO_MESON_AO_CEC
|
||||
tristate "Amlogic Meson AO CEC driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
|
|
|
@ -94,3 +94,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
|
|||
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
|
||||
|
||||
obj-y += meson/
|
||||
|
||||
obj-y += cros-ec-cec/
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
|
|
@ -0,0 +1,347 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* CEC driver for ChromeOS Embedded Controller
|
||||
*
|
||||
* Copyright (c) 2018 BayLibre, SAS
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/cec.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <media/cec.h>
|
||||
#include <media/cec-notifier.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-cec"
|
||||
|
||||
/**
|
||||
* struct cros_ec_cec - Driver data for EC CEC
|
||||
*
|
||||
* @cros_ec: Pointer to EC device
|
||||
* @notifier: Notifier info for responding to EC events
|
||||
* @adap: CEC adapter
|
||||
* @notify: CEC notifier pointer
|
||||
* @rx_msg: storage for a received message
|
||||
*/
|
||||
struct cros_ec_cec {
|
||||
struct cros_ec_device *cros_ec;
|
||||
struct notifier_block notifier;
|
||||
struct cec_adapter *adap;
|
||||
struct cec_notifier *notify;
|
||||
struct cec_msg rx_msg;
|
||||
};
|
||||
|
||||
static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
|
||||
{
|
||||
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
|
||||
uint8_t *cec_message = cros_ec->event_data.data.cec_message;
|
||||
unsigned int len = cros_ec->event_size;
|
||||
|
||||
cros_ec_cec->rx_msg.len = len;
|
||||
memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
|
||||
|
||||
cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg);
|
||||
}
|
||||
|
||||
static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
|
||||
{
|
||||
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
|
||||
uint32_t events = cros_ec->event_data.data.cec_events;
|
||||
|
||||
if (events & EC_MKBP_CEC_SEND_OK)
|
||||
cec_transmit_attempt_done(cros_ec_cec->adap,
|
||||
CEC_TX_STATUS_OK);
|
||||
|
||||
/* FW takes care of all retries, tell core to avoid more retries */
|
||||
if (events & EC_MKBP_CEC_SEND_FAILED)
|
||||
cec_transmit_attempt_done(cros_ec_cec->adap,
|
||||
CEC_TX_STATUS_MAX_RETRIES |
|
||||
CEC_TX_STATUS_NACK);
|
||||
}
|
||||
|
||||
static int cros_ec_cec_event(struct notifier_block *nb,
|
||||
unsigned long queued_during_suspend,
|
||||
void *_notify)
|
||||
{
|
||||
struct cros_ec_cec *cros_ec_cec;
|
||||
struct cros_ec_device *cros_ec;
|
||||
|
||||
cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier);
|
||||
cros_ec = cros_ec_cec->cros_ec;
|
||||
|
||||
if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) {
|
||||
handle_cec_event(cros_ec_cec);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) {
|
||||
handle_cec_message(cros_ec_cec);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
|
||||
{
|
||||
struct cros_ec_cec *cros_ec_cec = adap->priv;
|
||||
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
|
||||
struct {
|
||||
struct cros_ec_command msg;
|
||||
struct ec_params_cec_set data;
|
||||
} __packed msg = {};
|
||||
int ret;
|
||||
|
||||
msg.msg.command = EC_CMD_CEC_SET;
|
||||
msg.msg.outsize = sizeof(msg.data);
|
||||
msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS;
|
||||
msg.data.val = logical_addr;
|
||||
|
||||
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
|
||||
if (ret < 0) {
|
||||
dev_err(cros_ec->dev,
|
||||
"error setting CEC logical address on EC: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *cec_msg)
|
||||
{
|
||||
struct cros_ec_cec *cros_ec_cec = adap->priv;
|
||||
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
|
||||
struct {
|
||||
struct cros_ec_command msg;
|
||||
struct ec_params_cec_write data;
|
||||
} __packed msg = {};
|
||||
int ret;
|
||||
|
||||
msg.msg.command = EC_CMD_CEC_WRITE_MSG;
|
||||
msg.msg.outsize = cec_msg->len;
|
||||
memcpy(msg.data.msg, cec_msg->msg, cec_msg->len);
|
||||
|
||||
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
|
||||
if (ret < 0) {
|
||||
dev_err(cros_ec->dev,
|
||||
"error writing CEC msg on EC: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
{
|
||||
struct cros_ec_cec *cros_ec_cec = adap->priv;
|
||||
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
|
||||
struct {
|
||||
struct cros_ec_command msg;
|
||||
struct ec_params_cec_set data;
|
||||
} __packed msg = {};
|
||||
int ret;
|
||||
|
||||
msg.msg.command = EC_CMD_CEC_SET;
|
||||
msg.msg.outsize = sizeof(msg.data);
|
||||
msg.data.cmd = CEC_CMD_ENABLE;
|
||||
msg.data.val = enable;
|
||||
|
||||
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
|
||||
if (ret < 0) {
|
||||
dev_err(cros_ec->dev,
|
||||
"error %sabling CEC on EC: %d\n",
|
||||
(enable ? "en" : "dis"), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cec_adap_ops cros_ec_cec_ops = {
|
||||
.adap_enable = cros_ec_cec_adap_enable,
|
||||
.adap_log_addr = cros_ec_cec_set_log_addr,
|
||||
.adap_transmit = cros_ec_cec_transmit,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int cros_ec_cec_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
enable_irq_wake(cros_ec_cec->cros_ec->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_cec_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
disable_irq_wake(cros_ec_cec->cros_ec->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops,
|
||||
cros_ec_cec_suspend, cros_ec_cec_resume);
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI)
|
||||
|
||||
/*
|
||||
* The Firmware only handles a single CEC interface tied to a single HDMI
|
||||
* connector we specify along with the DRM device name handling the HDMI output
|
||||
*/
|
||||
|
||||
struct cec_dmi_match {
|
||||
char *sys_vendor;
|
||||
char *product_name;
|
||||
char *devname;
|
||||
char *conn;
|
||||
};
|
||||
|
||||
static const struct cec_dmi_match cec_dmi_match_table[] = {
|
||||
/* Google Fizz */
|
||||
{ "Google", "Fizz", "0000:00:02.0", "Port B" },
|
||||
};
|
||||
|
||||
static int cros_ec_cec_get_notifier(struct device *dev,
|
||||
struct cec_notifier **notify)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) {
|
||||
const struct cec_dmi_match *m = &cec_dmi_match_table[i];
|
||||
|
||||
if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) &&
|
||||
dmi_match(DMI_PRODUCT_NAME, m->product_name)) {
|
||||
struct device *d;
|
||||
|
||||
/* Find the device, bail out if not yet registered */
|
||||
d = bus_find_device_by_name(&pci_bus_type, NULL,
|
||||
m->devname);
|
||||
if (!d)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
*notify = cec_notifier_get_conn(d, m->conn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hardware support must be added in the cec_dmi_match_table */
|
||||
dev_warn(dev, "CEC notifier not configured for this hardware\n");
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int cros_ec_cec_get_notifier(struct device *dev,
|
||||
struct cec_notifier **notify)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int cros_ec_cec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct cros_ec_device *cros_ec = ec_dev->ec_dev;
|
||||
struct cros_ec_cec *cros_ec_cec;
|
||||
int ret;
|
||||
|
||||
cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec),
|
||||
GFP_KERNEL);
|
||||
if (!cros_ec_cec)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, cros_ec_cec);
|
||||
cros_ec_cec->cros_ec = cros_ec;
|
||||
|
||||
ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_init_wakeup(&pdev->dev, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize wakeup\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
|
||||
DRV_NAME, CEC_CAP_DEFAULTS, 1);
|
||||
if (IS_ERR(cros_ec_cec->adap))
|
||||
return PTR_ERR(cros_ec_cec->adap);
|
||||
|
||||
/* Get CEC events from the EC. */
|
||||
cros_ec_cec->notifier.notifier_call = cros_ec_cec_event;
|
||||
ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
|
||||
&cros_ec_cec->notifier);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register notifier\n");
|
||||
cec_delete_adapter(cros_ec_cec->adap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev);
|
||||
if (ret < 0) {
|
||||
cec_delete_adapter(cros_ec_cec->adap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_cec_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
ret = blocking_notifier_chain_unregister(
|
||||
&cros_ec_cec->cros_ec->event_notifier,
|
||||
&cros_ec_cec->notifier);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to unregister notifier\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
cec_unregister_adapter(cros_ec_cec->adap);
|
||||
|
||||
if (cros_ec_cec->notify)
|
||||
cec_notifier_put(cros_ec_cec->notify);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cros_ec_cec_driver = {
|
||||
.probe = cros_ec_cec_probe,
|
||||
.remove = cros_ec_cec_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &cros_ec_cec_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(cros_ec_cec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("CEC driver for ChromeOS ECs");
|
||||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
|
@ -202,26 +202,6 @@ config MFD_CROS_EC
|
|||
You also need to enable the driver for the bus you are using. The
|
||||
protocol for talking to the EC is defined by the bus driver.
|
||||
|
||||
config MFD_CROS_EC_I2C
|
||||
tristate "ChromeOS Embedded Controller (I2C)"
|
||||
depends on MFD_CROS_EC && I2C
|
||||
|
||||
help
|
||||
If you say Y here, you get support for talking to the ChromeOS
|
||||
EC through an I2C bus. This uses a simple byte-level protocol with
|
||||
a checksum. Failing accesses will be retried three times to
|
||||
improve reliability.
|
||||
|
||||
config MFD_CROS_EC_SPI
|
||||
tristate "ChromeOS Embedded Controller (SPI)"
|
||||
depends on MFD_CROS_EC && SPI
|
||||
|
||||
---help---
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
through a SPI bus, using a byte-level protocol. Since the EC's
|
||||
response time cannot be guaranteed, we support ignoring
|
||||
'pre-amble' bytes before the response actually starts.
|
||||
|
||||
config MFD_CROS_EC_CHARDEV
|
||||
tristate "Chrome OS Embedded Controller userspace device interface"
|
||||
depends on MFD_CROS_EC
|
||||
|
@ -232,6 +212,56 @@ config MFD_CROS_EC_CHARDEV
|
|||
If you have a supported Chromebook, choose Y or M here.
|
||||
The module will be called cros_ec_dev.
|
||||
|
||||
config MFD_MADERA
|
||||
tristate "Cirrus Logic Madera codecs"
|
||||
select MFD_CORE
|
||||
select REGMAP
|
||||
select REGMAP_IRQ
|
||||
select MADERA_IRQ
|
||||
select PINCTRL
|
||||
select PINCTRL_MADERA
|
||||
help
|
||||
Support for the Cirrus Logic Madera platform audio codecs
|
||||
|
||||
config MFD_MADERA_I2C
|
||||
tristate "Cirrus Logic Madera codecs with I2C"
|
||||
depends on MFD_MADERA
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Support for the Cirrus Logic Madera platform audio SoC
|
||||
core functionality controlled via I2C.
|
||||
|
||||
config MFD_MADERA_SPI
|
||||
tristate "Cirrus Logic Madera codecs with SPI"
|
||||
depends on MFD_MADERA
|
||||
depends on SPI_MASTER
|
||||
select REGMAP_SPI
|
||||
help
|
||||
Support for the Cirrus Logic Madera platform audio SoC
|
||||
core functionality controlled via SPI.
|
||||
|
||||
config MFD_CS47L35
|
||||
bool "Cirrus Logic CS47L35"
|
||||
select PINCTRL_CS47L35
|
||||
depends on MFD_MADERA
|
||||
help
|
||||
Support for Cirrus Logic CS47L35 Smart Codec
|
||||
|
||||
config MFD_CS47L85
|
||||
bool "Cirrus Logic CS47L85"
|
||||
select PINCTRL_CS47L85
|
||||
depends on MFD_MADERA
|
||||
help
|
||||
Support for Cirrus Logic CS47L85 Smart Codec
|
||||
|
||||
config MFD_CS47L90
|
||||
bool "Cirrus Logic CS47L90/91"
|
||||
select PINCTRL_CS47L90
|
||||
depends on MFD_MADERA
|
||||
help
|
||||
Support for Cirrus Logic CS47L90 and CS47L91 Smart Codecs
|
||||
|
||||
config MFD_ASIC3
|
||||
bool "Compaq ASIC3"
|
||||
depends on GPIOLIB && ARM
|
||||
|
@ -1787,6 +1817,19 @@ config MFD_STW481X
|
|||
in various ST Microelectronics and ST-Ericsson embedded
|
||||
Nomadik series.
|
||||
|
||||
config MFD_ROHM_BD718XX
|
||||
tristate "ROHM BD71837 Power Management IC"
|
||||
depends on I2C=y
|
||||
depends on OF
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select MFD_CORE
|
||||
help
|
||||
Select this option to get support for the ROHM BD71837
|
||||
Power Management ICs. BD71837 is designed to power processors like
|
||||
NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
|
||||
and emergency shut down as well as 32,768KHz clock output.
|
||||
|
||||
config MFD_STM32_LPTIMER
|
||||
tristate "Support for STM32 Low-Power Timer"
|
||||
depends on (ARCH_STM32 && OF) || COMPILE_TEST
|
||||
|
|
|
@ -14,8 +14,6 @@ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
|||
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
||||
cros_ec_core-objs := cros_ec.o
|
||||
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
|
||||
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
|
||||
|
||||
|
@ -72,6 +70,20 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o
|
|||
obj-$(CONFIG_MFD_WM8994) += wm8994.o
|
||||
obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o
|
||||
|
||||
madera-objs := madera-core.o
|
||||
ifeq ($(CONFIG_MFD_CS47L35),y)
|
||||
madera-objs += cs47l35-tables.o
|
||||
endif
|
||||
ifeq ($(CONFIG_MFD_CS47L85),y)
|
||||
madera-objs += cs47l85-tables.o
|
||||
endif
|
||||
ifeq ($(CONFIG_MFD_CS47L90),y)
|
||||
madera-objs += cs47l90-tables.o
|
||||
endif
|
||||
obj-$(CONFIG_MFD_MADERA) += madera.o
|
||||
obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o
|
||||
obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o
|
||||
|
||||
obj-$(CONFIG_TPS6105X) += tps6105x.o
|
||||
obj-$(CONFIG_TPS65010) += tps65010.o
|
||||
obj-$(CONFIG_TPS6507X) += tps6507x.o
|
||||
|
@ -227,4 +239,5 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
|
|||
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
|
||||
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
|
||||
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/mfd/arizona/core.h>
|
||||
|
@ -236,22 +237,39 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
|
|||
|
||||
#define ARIZONA_REG_POLL_DELAY_US 7500
|
||||
|
||||
static inline bool arizona_poll_reg_delay(ktime_t timeout)
|
||||
{
|
||||
if (ktime_compare(ktime_get(), timeout) > 0)
|
||||
return false;
|
||||
|
||||
usleep_range(ARIZONA_REG_POLL_DELAY_US / 2, ARIZONA_REG_POLL_DELAY_US);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int arizona_poll_reg(struct arizona *arizona,
|
||||
int timeout_ms, unsigned int reg,
|
||||
unsigned int mask, unsigned int target)
|
||||
{
|
||||
ktime_t timeout = ktime_add_us(ktime_get(), timeout_ms * USEC_PER_MSEC);
|
||||
unsigned int val = 0;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read_poll_timeout(arizona->regmap,
|
||||
reg, val, ((val & mask) == target),
|
||||
ARIZONA_REG_POLL_DELAY_US,
|
||||
timeout_ms * 1000);
|
||||
if (ret)
|
||||
dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n",
|
||||
reg, val);
|
||||
do {
|
||||
ret = regmap_read(arizona->regmap, reg, &val);
|
||||
|
||||
return ret;
|
||||
if ((val & mask) == target)
|
||||
return 0;
|
||||
} while (arizona_poll_reg_delay(timeout));
|
||||
|
||||
if (ret) {
|
||||
dev_err(arizona->dev, "Failed polling reg 0x%x: %d\n",
|
||||
reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n", reg, val);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int arizona_wait_for_boot(struct arizona *arizona)
|
||||
|
|
|
@ -349,6 +349,8 @@ static int as3722_i2c_of_probe(struct i2c_client *i2c,
|
|||
"ams,enable-internal-int-pullup");
|
||||
as3722->en_intern_i2c_pullup = of_property_read_bool(np,
|
||||
"ams,enable-internal-i2c-pullup");
|
||||
as3722->en_ac_ok_pwr_on = of_property_read_bool(np,
|
||||
"ams,enable-ac-ok-power-on");
|
||||
as3722->irq_flags = irqd_get_trigger_type(irq_data);
|
||||
dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags);
|
||||
return 0;
|
||||
|
@ -360,6 +362,7 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
|
|||
struct as3722 *as3722;
|
||||
unsigned long irq_flags;
|
||||
int ret;
|
||||
u8 val = 0;
|
||||
|
||||
as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
|
||||
if (!as3722)
|
||||
|
@ -398,6 +401,15 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (as3722->en_ac_ok_pwr_on)
|
||||
val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON;
|
||||
ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG,
|
||||
AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val);
|
||||
if (ret < 0) {
|
||||
dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,
|
||||
ARRAY_SIZE(as3722_devs), NULL, 0,
|
||||
regmap_irq_get_domain(as3722->irq_data));
|
||||
|
|
|
@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
|
|||
{ .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
|
||||
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
|
||||
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
|
||||
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
|
||||
|
@ -74,6 +75,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
|
|||
{ "axp202", 0 },
|
||||
{ "axp209", 0 },
|
||||
{ "axp221", 0 },
|
||||
{ "axp806", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
|
||||
|
|
|
@ -221,6 +221,11 @@ static const struct resource axp803_pek_resources[] = {
|
|||
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static const struct resource axp806_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_RISE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_FALL, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static const struct resource axp809_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
|
@ -730,6 +735,15 @@ static const struct mfd_cell axp803_cells[] = {
|
|||
{ .name = "axp20x-regulator" },
|
||||
};
|
||||
|
||||
static const struct mfd_cell axp806_self_working_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp806_pek_resources),
|
||||
.resources = axp806_pek_resources,
|
||||
},
|
||||
{ .name = "axp20x-regulator" },
|
||||
};
|
||||
|
||||
static const struct mfd_cell axp806_cells[] = {
|
||||
{
|
||||
.id = 2,
|
||||
|
@ -842,8 +856,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
|
|||
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
|
||||
break;
|
||||
case AXP806_ID:
|
||||
axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
|
||||
axp20x->cells = axp806_cells;
|
||||
if (of_property_read_bool(axp20x->dev->of_node,
|
||||
"x-powers,self-working-mode")) {
|
||||
axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
|
||||
axp20x->cells = axp806_self_working_cells;
|
||||
} else {
|
||||
axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
|
||||
axp20x->cells = axp806_cells;
|
||||
}
|
||||
axp20x->regmap_cfg = &axp806_regmap_config;
|
||||
axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
|
||||
break;
|
||||
|
@ -901,7 +921,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
|
|||
*/
|
||||
if (axp20x->variant == AXP806_ID) {
|
||||
if (of_property_read_bool(axp20x->dev->of_node,
|
||||
"x-powers,master-mode"))
|
||||
"x-powers,master-mode") ||
|
||||
of_property_read_bool(axp20x->dev->of_node,
|
||||
"x-powers,self-working-mode"))
|
||||
regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
|
||||
AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
|
||||
else
|
||||
|
|
|
@ -378,10 +378,18 @@ error:
|
|||
kfree(msg);
|
||||
}
|
||||
|
||||
static const struct mfd_cell cros_ec_cec_cells[] = {
|
||||
{ .name = "cros-ec-cec" }
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_rtc_cells[] = {
|
||||
{ .name = "cros-ec-rtc" }
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_usbpd_charger_cells[] = {
|
||||
{ .name = "cros-usbpd-charger" }
|
||||
};
|
||||
|
||||
static int ec_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
int retval = -ENOMEM;
|
||||
|
@ -420,6 +428,18 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
|
||||
cros_ec_sensors_register(ec);
|
||||
|
||||
/* Check whether this EC instance has CEC host command support */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_cec_cells,
|
||||
ARRAY_SIZE(cros_ec_cec_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add cros-ec-cec device: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/* Check whether this EC instance has RTC host command support */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
|
@ -432,6 +452,18 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||
retval);
|
||||
}
|
||||
|
||||
/* Check whether this EC instance has the PD charge manager */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_USB_PD)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_usbpd_charger_cells,
|
||||
ARRAY_SIZE(cros_usbpd_charger_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add cros-usbpd-charger device: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/* Take control of the lightbar from the EC. */
|
||||
lb_manual_suspend_ctrl(ec, 1);
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -76,7 +76,7 @@ static struct resource da9063_hwmon_resources[] = {
|
|||
};
|
||||
|
||||
|
||||
static const struct mfd_cell da9063_devs[] = {
|
||||
static const struct mfd_cell da9063_common_devs[] = {
|
||||
{
|
||||
.name = DA9063_DRVNAME_REGULATORS,
|
||||
.num_resources = ARRAY_SIZE(da9063_regulators_resources),
|
||||
|
@ -100,15 +100,19 @@ static const struct mfd_cell da9063_devs[] = {
|
|||
.resources = da9063_onkey_resources,
|
||||
.of_compatible = "dlg,da9063-onkey",
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_VIBRATION,
|
||||
},
|
||||
};
|
||||
|
||||
/* Only present on DA9063 , not on DA9063L */
|
||||
static const struct mfd_cell da9063_devs[] = {
|
||||
{
|
||||
.name = DA9063_DRVNAME_RTC,
|
||||
.num_resources = ARRAY_SIZE(da9063_rtc_resources),
|
||||
.resources = da9063_rtc_resources,
|
||||
.of_compatible = "dlg,da9063-rtc",
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_VIBRATION,
|
||||
},
|
||||
};
|
||||
|
||||
static int da9063_clear_fault_log(struct da9063 *da9063)
|
||||
|
@ -192,7 +196,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
|||
dev_err(da9063->dev, "Cannot read chip model id.\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (model != PMIC_DA9063) {
|
||||
if (model != PMIC_CHIP_ID_DA9063) {
|
||||
dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -215,7 +219,6 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
da9063->model = model;
|
||||
da9063->variant_code = variant_code;
|
||||
|
||||
ret = da9063_irq_init(da9063);
|
||||
|
@ -226,21 +229,28 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
|||
|
||||
da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
|
||||
|
||||
ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
|
||||
ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
|
||||
NULL);
|
||||
if (ret)
|
||||
dev_err(da9063->dev, "Cannot add MFD cells\n");
|
||||
ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
|
||||
da9063_common_devs,
|
||||
ARRAY_SIZE(da9063_common_devs),
|
||||
NULL, da9063->irq_base, NULL);
|
||||
if (ret) {
|
||||
dev_err(da9063->dev, "Failed to add child devices\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (da9063->type == PMIC_TYPE_DA9063) {
|
||||
ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
|
||||
da9063_devs, ARRAY_SIZE(da9063_devs),
|
||||
NULL, da9063->irq_base, NULL);
|
||||
if (ret) {
|
||||
dev_err(da9063->dev, "Failed to add child devices\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void da9063_device_exit(struct da9063 *da9063)
|
||||
{
|
||||
mfd_remove_devices(da9063->dev);
|
||||
da9063_irq_exit(da9063);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
|
||||
MODULE_AUTHOR("Krystian Garbaciak");
|
||||
MODULE_AUTHOR("Michal Hajduk");
|
||||
|
|
|
@ -29,78 +29,33 @@
|
|||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
static const struct regmap_range da9063_ad_readable_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_AD_REG_SECOND_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_ID_32_31,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ_A,
|
||||
.range_max = DA9063_REG_AUTO3_LOW,
|
||||
}, {
|
||||
.range_min = DA9063_REG_T_OFFSET,
|
||||
.range_max = DA9063_AD_REG_GP_ID_19,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CHIP_ID,
|
||||
.range_max = DA9063_REG_CHIP_VARIANT,
|
||||
},
|
||||
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),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_ad_writeable_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_PAGE_CON,
|
||||
}, {
|
||||
.range_min = DA9063_REG_FAULT_LOG,
|
||||
.range_max = DA9063_REG_VSYS_MON,
|
||||
}, {
|
||||
.range_min = DA9063_REG_COUNT_S,
|
||||
.range_max = DA9063_AD_REG_ALARM_Y,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_ID_32_31,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ_A,
|
||||
.range_max = DA9063_REG_AUTO3_LOW,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONFIG_I,
|
||||
.range_max = DA9063_AD_REG_MON_REG_4,
|
||||
}, {
|
||||
.range_min = DA9063_AD_REG_GP_ID_0,
|
||||
.range_max = DA9063_AD_REG_GP_ID_19,
|
||||
},
|
||||
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_AD_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_AD_REG_MON_REG_4),
|
||||
regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_ad_volatile_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_EVENT_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONTROL_A,
|
||||
.range_max = DA9063_REG_CONTROL_B,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONTROL_E,
|
||||
.range_max = DA9063_REG_CONTROL_F,
|
||||
}, {
|
||||
.range_min = DA9063_REG_BCORE2_CONT,
|
||||
.range_max = DA9063_REG_LDO11_CONT,
|
||||
}, {
|
||||
.range_min = DA9063_REG_DVC_1,
|
||||
.range_max = DA9063_REG_ADC_MAN,
|
||||
}, {
|
||||
.range_min = DA9063_REG_ADC_RES_L,
|
||||
.range_max = DA9063_AD_REG_SECOND_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_SEQ,
|
||||
}, {
|
||||
.range_min = DA9063_REG_EN_32K,
|
||||
.range_max = DA9063_REG_EN_32K,
|
||||
}, {
|
||||
.range_min = DA9063_AD_REG_MON_REG_5,
|
||||
.range_max = DA9063_AD_REG_MON_REG_6,
|
||||
},
|
||||
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),
|
||||
regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
|
||||
regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
|
||||
regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
|
||||
regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
|
||||
regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_ad_readable_table = {
|
||||
|
@ -119,78 +74,33 @@ static const struct regmap_access_table da9063_ad_volatile_table = {
|
|||
};
|
||||
|
||||
static const struct regmap_range da9063_bb_readable_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_BB_REG_SECOND_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_ID_32_31,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ_A,
|
||||
.range_max = DA9063_REG_AUTO3_LOW,
|
||||
}, {
|
||||
.range_min = DA9063_REG_T_OFFSET,
|
||||
.range_max = DA9063_BB_REG_GP_ID_19,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CHIP_ID,
|
||||
.range_max = DA9063_REG_CHIP_VARIANT,
|
||||
},
|
||||
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_19),
|
||||
regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_bb_writeable_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_PAGE_CON,
|
||||
}, {
|
||||
.range_min = DA9063_REG_FAULT_LOG,
|
||||
.range_max = DA9063_REG_VSYS_MON,
|
||||
}, {
|
||||
.range_min = DA9063_REG_COUNT_S,
|
||||
.range_max = DA9063_BB_REG_ALARM_Y,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_ID_32_31,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ_A,
|
||||
.range_max = DA9063_REG_AUTO3_LOW,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONFIG_I,
|
||||
.range_max = DA9063_BB_REG_MON_REG_4,
|
||||
}, {
|
||||
.range_min = DA9063_BB_REG_GP_ID_0,
|
||||
.range_max = DA9063_BB_REG_GP_ID_19,
|
||||
},
|
||||
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_19),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_bb_volatile_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_EVENT_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONTROL_A,
|
||||
.range_max = DA9063_REG_CONTROL_B,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONTROL_E,
|
||||
.range_max = DA9063_REG_CONTROL_F,
|
||||
}, {
|
||||
.range_min = DA9063_REG_BCORE2_CONT,
|
||||
.range_max = DA9063_REG_LDO11_CONT,
|
||||
}, {
|
||||
.range_min = DA9063_REG_DVC_1,
|
||||
.range_max = DA9063_REG_ADC_MAN,
|
||||
}, {
|
||||
.range_min = DA9063_REG_ADC_RES_L,
|
||||
.range_max = DA9063_BB_REG_SECOND_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_SEQ,
|
||||
}, {
|
||||
.range_min = DA9063_REG_EN_32K,
|
||||
.range_max = DA9063_REG_EN_32K,
|
||||
}, {
|
||||
.range_min = DA9063_BB_REG_MON_REG_5,
|
||||
.range_max = DA9063_BB_REG_MON_REG_6,
|
||||
},
|
||||
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),
|
||||
regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
|
||||
regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
|
||||
regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
|
||||
regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
|
||||
regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_bb_readable_table = {
|
||||
|
@ -208,6 +118,50 @@ static const struct regmap_access_table da9063_bb_volatile_table = {
|
|||
.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_bb_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_19),
|
||||
regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_bb_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_19),
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063l_bb_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),
|
||||
regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
|
||||
regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
|
||||
regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES),
|
||||
regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
|
||||
regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
|
||||
regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063l_bb_readable_table = {
|
||||
.yes_ranges = da9063l_bb_readable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063l_bb_writeable_table = {
|
||||
.yes_ranges = da9063l_bb_writeable_ranges,
|
||||
.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_range_cfg da9063_range_cfg[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
|
@ -232,11 +186,12 @@ static struct regmap_config da9063_regmap_config = {
|
|||
|
||||
static const struct of_device_id da9063_dt_ids[] = {
|
||||
{ .compatible = "dlg,da9063", },
|
||||
{ .compatible = "dlg,da9063l", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, da9063_dt_ids);
|
||||
static int da9063_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct da9063 *da9063;
|
||||
int ret;
|
||||
|
@ -248,11 +203,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
|
|||
i2c_set_clientdata(i2c, da9063);
|
||||
da9063->dev = &i2c->dev;
|
||||
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;
|
||||
|
@ -270,17 +230,9 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
|
|||
return da9063_device_init(da9063, i2c->irq);
|
||||
}
|
||||
|
||||
static int da9063_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct da9063 *da9063 = i2c_get_clientdata(i2c);
|
||||
|
||||
da9063_device_exit(da9063);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id da9063_i2c_id[] = {
|
||||
{"da9063", PMIC_DA9063},
|
||||
{ "da9063", PMIC_TYPE_DA9063 },
|
||||
{ "da9063l", PMIC_TYPE_DA9063L },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
|
||||
|
@ -291,7 +243,6 @@ static struct i2c_driver da9063_i2c_driver = {
|
|||
.of_match_table = of_match_ptr(da9063_dt_ids),
|
||||
},
|
||||
.probe = da9063_i2c_probe,
|
||||
.remove = da9063_i2c_remove,
|
||||
.id_table = da9063_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -28,132 +28,145 @@
|
|||
|
||||
static const struct regmap_irq da9063_irqs[] = {
|
||||
/* DA9063 event A register */
|
||||
[DA9063_IRQ_ONKEY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_ONKEY,
|
||||
},
|
||||
[DA9063_IRQ_ALARM] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_ALARM,
|
||||
},
|
||||
[DA9063_IRQ_TICK] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_TICK,
|
||||
},
|
||||
[DA9063_IRQ_ADC_RDY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_ADC_RDY,
|
||||
},
|
||||
[DA9063_IRQ_SEQ_RDY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_SEQ_RDY,
|
||||
},
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_ALARM,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_TICK,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
|
||||
/* DA9063 event B register */
|
||||
[DA9063_IRQ_WAKE] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_WAKE,
|
||||
},
|
||||
[DA9063_IRQ_TEMP] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_TEMP,
|
||||
},
|
||||
[DA9063_IRQ_COMP_1V2] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_COMP_1V2,
|
||||
},
|
||||
[DA9063_IRQ_LDO_LIM] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_LDO_LIM,
|
||||
},
|
||||
[DA9063_IRQ_REG_UVOV] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_UVOV,
|
||||
},
|
||||
[DA9063_IRQ_DVC_RDY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_DVC_RDY,
|
||||
},
|
||||
[DA9063_IRQ_VDD_MON] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_VDD_MON,
|
||||
},
|
||||
[DA9063_IRQ_WARN] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_VDD_WARN,
|
||||
},
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_WARN,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
|
||||
/* DA9063 event C register */
|
||||
[DA9063_IRQ_GPI0] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI0,
|
||||
},
|
||||
[DA9063_IRQ_GPI1] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI1,
|
||||
},
|
||||
[DA9063_IRQ_GPI2] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI2,
|
||||
},
|
||||
[DA9063_IRQ_GPI3] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI3,
|
||||
},
|
||||
[DA9063_IRQ_GPI4] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI4,
|
||||
},
|
||||
[DA9063_IRQ_GPI5] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI5,
|
||||
},
|
||||
[DA9063_IRQ_GPI6] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI6,
|
||||
},
|
||||
[DA9063_IRQ_GPI7] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI7,
|
||||
},
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
|
||||
/* DA9063 event D register */
|
||||
[DA9063_IRQ_GPI8] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI8,
|
||||
},
|
||||
[DA9063_IRQ_GPI9] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI9,
|
||||
},
|
||||
[DA9063_IRQ_GPI10] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI10,
|
||||
},
|
||||
[DA9063_IRQ_GPI11] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI11,
|
||||
},
|
||||
[DA9063_IRQ_GPI12] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI12,
|
||||
},
|
||||
[DA9063_IRQ_GPI13] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI13,
|
||||
},
|
||||
[DA9063_IRQ_GPI14] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI14,
|
||||
},
|
||||
[DA9063_IRQ_GPI15] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI15,
|
||||
},
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip da9063_irq_chip = {
|
||||
.name = "da9063-irq",
|
||||
.irqs = da9063_irqs,
|
||||
.num_irqs = DA9063_NUM_IRQ,
|
||||
.num_irqs = ARRAY_SIZE(da9063_irqs),
|
||||
.num_regs = 4,
|
||||
.status_base = DA9063_REG_EVENT_A,
|
||||
.mask_base = DA9063_REG_IRQ_MASK_A,
|
||||
.ack_base = DA9063_REG_EVENT_A,
|
||||
.init_ack_masked = true,
|
||||
};
|
||||
|
||||
static const struct regmap_irq da9063l_irqs[] = {
|
||||
/* DA9063 event A register */
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
|
||||
DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
|
||||
/* DA9063 event B register */
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_WARN,
|
||||
DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
|
||||
/* DA9063 event C register */
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
|
||||
DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
|
||||
/* DA9063 event D register */
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
|
||||
REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
|
||||
DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip da9063l_irq_chip = {
|
||||
.name = "da9063l-irq",
|
||||
.irqs = da9063l_irqs,
|
||||
.num_irqs = ARRAY_SIZE(da9063l_irqs),
|
||||
.num_regs = 4,
|
||||
.status_base = DA9063_REG_EVENT_A,
|
||||
.mask_base = DA9063_REG_IRQ_MASK_A,
|
||||
|
@ -163,6 +176,7 @@ static const struct regmap_irq_chip da9063_irq_chip = {
|
|||
|
||||
int da9063_irq_init(struct da9063 *da9063)
|
||||
{
|
||||
const struct regmap_irq_chip *irq_chip;
|
||||
int ret;
|
||||
|
||||
if (!da9063->chip_irq) {
|
||||
|
@ -170,10 +184,15 @@ int da9063_irq_init(struct da9063 *da9063)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq,
|
||||
if (da9063->type == PMIC_TYPE_DA9063)
|
||||
irq_chip = &da9063_irq_chip;
|
||||
else
|
||||
irq_chip = &da9063l_irq_chip;
|
||||
|
||||
ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap,
|
||||
da9063->chip_irq,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
|
||||
da9063->irq_base, &da9063_irq_chip,
|
||||
&da9063->regmap_irq);
|
||||
da9063->irq_base, irq_chip, &da9063->regmap_irq);
|
||||
if (ret) {
|
||||
dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
|
||||
da9063->chip_irq, ret);
|
||||
|
@ -182,8 +201,3 @@ int da9063_irq_init(struct da9063 *da9063)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void da9063_irq_exit(struct da9063 *da9063)
|
||||
{
|
||||
regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq);
|
||||
}
|
||||
|
|
|
@ -194,6 +194,7 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
|
|||
struct device *dev = &dln2->interface->dev;
|
||||
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
|
||||
struct dln2_rx_context *rxc;
|
||||
unsigned long flags;
|
||||
bool valid_slot = false;
|
||||
|
||||
if (rx_slot >= DLN2_MAX_RX_SLOTS)
|
||||
|
@ -201,18 +202,13 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
|
|||
|
||||
rxc = &rxs->slots[rx_slot];
|
||||
|
||||
/*
|
||||
* No need to disable interrupts as this lock is not taken in interrupt
|
||||
* context elsewhere in this driver. This function (or its callers) are
|
||||
* also not exported to other modules.
|
||||
*/
|
||||
spin_lock(&rxs->lock);
|
||||
spin_lock_irqsave(&rxs->lock, flags);
|
||||
if (rxc->in_use && !rxc->urb) {
|
||||
rxc->urb = urb;
|
||||
complete(&rxc->done);
|
||||
valid_slot = true;
|
||||
}
|
||||
spin_unlock(&rxs->lock);
|
||||
spin_unlock_irqrestore(&rxs->lock, flags);
|
||||
|
||||
out:
|
||||
if (!valid_slot)
|
||||
|
|
|
@ -49,7 +49,7 @@ static struct regmap_config hi655x_regmap_config = {
|
|||
.reg_bits = 32,
|
||||
.reg_stride = HI655X_STRIDE,
|
||||
.val_bits = 8,
|
||||
.max_register = HI655X_BUS_ADDR(0xFFF),
|
||||
.max_register = HI655X_BUS_ADDR(0x400) - HI655X_STRIDE,
|
||||
};
|
||||
|
||||
static struct resource pwrkey_resources[] = {
|
||||
|
|
|
@ -178,6 +178,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info },
|
||||
/* ICL-LP */
|
||||
{ PCI_VDEVICE(INTEL, 0x34a8), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34a9), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34aa), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34ab), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34c5), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34c6), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34c7), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34e8), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34e9), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ 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 },
|
||||
/* APL */
|
||||
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
|
||||
|
|
|
@ -143,7 +143,7 @@ static struct platform_device *kempld_pdev;
|
|||
|
||||
static int kempld_create_platform_device(const struct dmi_system_id *id)
|
||||
{
|
||||
struct kempld_platform_data *pdata = id->driver_data;
|
||||
const struct kempld_platform_data *pdata = id->driver_data;
|
||||
int ret;
|
||||
|
||||
kempld_pdev = platform_device_alloc("kempld", -1);
|
||||
|
@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(kempld_write32);
|
|||
*/
|
||||
void kempld_get_mutex(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
mutex_lock(&pld->lock);
|
||||
pdata->get_hardware_mutex(pld);
|
||||
|
@ -272,7 +272,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex);
|
|||
*/
|
||||
void kempld_release_mutex(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
pdata->release_hardware_mutex(pld);
|
||||
mutex_unlock(&pld->lock);
|
||||
|
@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
|
|||
static int kempld_get_info(struct kempld_device_data *pld)
|
||||
{
|
||||
int ret;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
char major, minor;
|
||||
|
||||
ret = pdata->get_info(pld);
|
||||
|
@ -332,7 +332,7 @@ static int kempld_get_info(struct kempld_device_data *pld)
|
|||
*/
|
||||
static int kempld_register_cells(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
return pdata->register_cells(pld);
|
||||
}
|
||||
|
@ -444,7 +444,8 @@ static int kempld_detect_device(struct kempld_device_data *pld)
|
|||
|
||||
static int kempld_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
const struct kempld_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct kempld_device_data *pld;
|
||||
struct resource *ioport;
|
||||
|
@ -476,7 +477,7 @@ static int kempld_probe(struct platform_device *pdev)
|
|||
static int kempld_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct kempld_device_data *pld = platform_get_drvdata(pdev);
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
|
||||
|
||||
|
|
|
@ -0,0 +1,609 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Core MFD support for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#include <linux/mfd/madera/core.h>
|
||||
#include <linux/mfd/madera/registers.h>
|
||||
|
||||
#include "madera.h"
|
||||
|
||||
#define CS47L35_SILICON_ID 0x6360
|
||||
#define CS47L85_SILICON_ID 0x6338
|
||||
#define CS47L90_SILICON_ID 0x6364
|
||||
|
||||
#define MADERA_32KZ_MCLK2 1
|
||||
|
||||
static const char * const madera_core_supplies[] = {
|
||||
"AVDD",
|
||||
"DBVDD1",
|
||||
};
|
||||
|
||||
static const struct mfd_cell madera_ldo1_devs[] = {
|
||||
{ .name = "madera-ldo1" },
|
||||
};
|
||||
|
||||
static const char * const cs47l35_supplies[] = {
|
||||
"MICVDD",
|
||||
"DBVDD2",
|
||||
"CPVDD1",
|
||||
"CPVDD2",
|
||||
"SPKVDD",
|
||||
};
|
||||
|
||||
static const struct mfd_cell cs47l35_devs[] = {
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio", },
|
||||
{ .name = "madera-extcon", },
|
||||
{
|
||||
.name = "cs47l35-codec",
|
||||
.parent_supplies = cs47l35_supplies,
|
||||
.num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),
|
||||
},
|
||||
};
|
||||
|
||||
static const char * const cs47l85_supplies[] = {
|
||||
"MICVDD",
|
||||
"DBVDD2",
|
||||
"DBVDD3",
|
||||
"DBVDD4",
|
||||
"CPVDD1",
|
||||
"CPVDD2",
|
||||
"SPKVDDL",
|
||||
"SPKVDDR",
|
||||
};
|
||||
|
||||
static const struct mfd_cell cs47l85_devs[] = {
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp" },
|
||||
{ .name = "madera-gpio", },
|
||||
{ .name = "madera-extcon", },
|
||||
{
|
||||
.name = "cs47l85-codec",
|
||||
.parent_supplies = cs47l85_supplies,
|
||||
.num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),
|
||||
},
|
||||
};
|
||||
|
||||
static const char * const cs47l90_supplies[] = {
|
||||
"MICVDD",
|
||||
"DBVDD2",
|
||||
"DBVDD3",
|
||||
"DBVDD4",
|
||||
"CPVDD1",
|
||||
"CPVDD2",
|
||||
};
|
||||
|
||||
static const struct mfd_cell cs47l90_devs[] = {
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio", },
|
||||
{ .name = "madera-extcon", },
|
||||
{
|
||||
.name = "cs47l90-codec",
|
||||
.parent_supplies = cs47l90_supplies,
|
||||
.num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),
|
||||
},
|
||||
};
|
||||
|
||||
/* Used by madera-i2c and madera-spi drivers */
|
||||
const char *madera_name_from_type(enum madera_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case CS47L35:
|
||||
return "CS47L35";
|
||||
case CS47L85:
|
||||
return "CS47L85";
|
||||
case CS47L90:
|
||||
return "CS47L90";
|
||||
case CS47L91:
|
||||
return "CS47L91";
|
||||
case WM1840:
|
||||
return "WM1840";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(madera_name_from_type);
|
||||
|
||||
#define MADERA_BOOT_POLL_MAX_INTERVAL_US 5000
|
||||
#define MADERA_BOOT_POLL_TIMEOUT_US 25000
|
||||
|
||||
static int madera_wait_for_boot(struct madera *madera)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We can't use an interrupt as we need to runtime resume to do so,
|
||||
* so we poll the status bit. This won't race with the interrupt
|
||||
* handler because it will be blocked on runtime resume.
|
||||
*/
|
||||
ret = regmap_read_poll_timeout(madera->regmap,
|
||||
MADERA_IRQ1_RAW_STATUS_1,
|
||||
val,
|
||||
(val & MADERA_BOOT_DONE_STS1),
|
||||
MADERA_BOOT_POLL_MAX_INTERVAL_US,
|
||||
MADERA_BOOT_POLL_TIMEOUT_US);
|
||||
|
||||
if (ret)
|
||||
dev_err(madera->dev, "Polling BOOT_DONE_STS failed: %d\n", ret);
|
||||
|
||||
/*
|
||||
* BOOT_DONE defaults to unmasked on boot so we must ack it.
|
||||
* Do this unconditionally to avoid interrupt storms.
|
||||
*/
|
||||
regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
|
||||
MADERA_BOOT_DONE_EINT1);
|
||||
|
||||
pm_runtime_mark_last_busy(madera->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int madera_soft_reset(struct madera *madera)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);
|
||||
if (ret != 0) {
|
||||
dev_err(madera->dev, "Failed to soft reset device: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allow time for internal clocks to startup after reset */
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void madera_enable_hard_reset(struct madera *madera)
|
||||
{
|
||||
if (!madera->pdata.reset)
|
||||
return;
|
||||
|
||||
/*
|
||||
* There are many existing out-of-tree users of these codecs that we
|
||||
* can't break so preserve the expected behaviour of setting the line
|
||||
* low to assert reset.
|
||||
*/
|
||||
gpiod_set_raw_value_cansleep(madera->pdata.reset, 0);
|
||||
}
|
||||
|
||||
static void madera_disable_hard_reset(struct madera *madera)
|
||||
{
|
||||
if (!madera->pdata.reset)
|
||||
return;
|
||||
|
||||
gpiod_set_raw_value_cansleep(madera->pdata.reset, 1);
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
static int __maybe_unused madera_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct madera *madera = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "Leaving sleep mode\n");
|
||||
|
||||
ret = regulator_enable(madera->dcvdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regcache_cache_only(madera->regmap, false);
|
||||
regcache_cache_only(madera->regmap_32bit, false);
|
||||
|
||||
ret = madera_wait_for_boot(madera);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = regcache_sync(madera->regmap);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to restore 16-bit register cache\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = regcache_sync(madera->regmap_32bit);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to restore 32-bit register cache\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
regcache_cache_only(madera->regmap_32bit, true);
|
||||
regcache_cache_only(madera->regmap, true);
|
||||
regulator_disable(madera->dcvdd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused madera_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct madera *madera = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(madera->dev, "Entering sleep mode\n");
|
||||
|
||||
regcache_cache_only(madera->regmap, true);
|
||||
regcache_mark_dirty(madera->regmap);
|
||||
regcache_cache_only(madera->regmap_32bit, true);
|
||||
regcache_mark_dirty(madera->regmap_32bit);
|
||||
|
||||
regulator_disable(madera->dcvdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dev_pm_ops madera_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(madera_runtime_suspend,
|
||||
madera_runtime_resume,
|
||||
NULL)
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_pm_ops);
|
||||
|
||||
const struct of_device_id madera_of_match[] = {
|
||||
{ .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
|
||||
{ .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
|
||||
{ .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
|
||||
{ .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
|
||||
{ .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
|
||||
{}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_of_match);
|
||||
|
||||
static int madera_get_reset_gpio(struct madera *madera)
|
||||
{
|
||||
struct gpio_desc *reset;
|
||||
int ret;
|
||||
|
||||
if (madera->pdata.reset)
|
||||
return 0;
|
||||
|
||||
reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(reset)) {
|
||||
ret = PTR_ERR(reset);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(madera->dev, "Failed to request /RESET: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* A hard reset is needed for full reset of the chip. We allow running
|
||||
* without hard reset only because it can be useful for early
|
||||
* prototyping and some debugging, but we need to warn it's not ideal.
|
||||
*/
|
||||
if (!reset)
|
||||
dev_warn(madera->dev,
|
||||
"Running without reset GPIO is not recommended\n");
|
||||
|
||||
madera->pdata.reset = reset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void madera_set_micbias_info(struct madera *madera)
|
||||
{
|
||||
/*
|
||||
* num_childbias is an array because future codecs can have different
|
||||
* childbiases for each micbias. Unspecified values default to 0.
|
||||
*/
|
||||
switch (madera->type) {
|
||||
case CS47L35:
|
||||
madera->num_micbias = 2;
|
||||
madera->num_childbias[0] = 2;
|
||||
madera->num_childbias[1] = 2;
|
||||
return;
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
madera->num_micbias = 4;
|
||||
/* no child biases */
|
||||
return;
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
madera->num_micbias = 2;
|
||||
madera->num_childbias[0] = 4;
|
||||
madera->num_childbias[1] = 4;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int madera_dev_init(struct madera *madera)
|
||||
{
|
||||
struct device *dev = madera->dev;
|
||||
unsigned int hwid;
|
||||
int (*patch_fn)(struct madera *) = NULL;
|
||||
const struct mfd_cell *mfd_devs;
|
||||
int n_devs = 0;
|
||||
int i, ret;
|
||||
|
||||
dev_set_drvdata(madera->dev, madera);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
|
||||
madera_set_micbias_info(madera);
|
||||
|
||||
/*
|
||||
* We need writable hw config info that all children can share.
|
||||
* Simplest to take one shared copy of pdata struct.
|
||||
*/
|
||||
if (dev_get_platdata(madera->dev)) {
|
||||
memcpy(&madera->pdata, dev_get_platdata(madera->dev),
|
||||
sizeof(madera->pdata));
|
||||
}
|
||||
|
||||
ret = madera_get_reset_gpio(madera);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regcache_cache_only(madera->regmap, true);
|
||||
regcache_cache_only(madera->regmap_32bit, true);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)
|
||||
madera->core_supplies[i].supply = madera_core_supplies[i];
|
||||
|
||||
madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);
|
||||
|
||||
/*
|
||||
* On some codecs DCVDD could be supplied by the internal LDO1.
|
||||
* For those we must add the LDO1 driver before requesting DCVDD
|
||||
* No devm_ because we need to control shutdown order of children.
|
||||
*/
|
||||
switch (madera->type) {
|
||||
case CS47L35:
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
break;
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
|
||||
madera_ldo1_devs,
|
||||
ARRAY_SIZE(madera_ldo1_devs),
|
||||
NULL, 0, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to add LDO1 child: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* No point continuing if the type is unknown */
|
||||
dev_err(madera->dev, "Unknown device type %d\n", madera->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, madera->num_core_supplies,
|
||||
madera->core_supplies);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request core supplies: %d\n", ret);
|
||||
goto err_devs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't use devres here. If the regulator is one of our children it
|
||||
* will already have been removed before devres cleanup on this mfd
|
||||
* driver tries to call put() on it. We need control of shutdown order.
|
||||
*/
|
||||
madera->dcvdd = regulator_get(madera->dev, "DCVDD");
|
||||
if (IS_ERR(madera->dcvdd)) {
|
||||
ret = PTR_ERR(madera->dcvdd);
|
||||
dev_err(dev, "Failed to request DCVDD: %d\n", ret);
|
||||
goto err_devs;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(madera->num_core_supplies,
|
||||
madera->core_supplies);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable core supplies: %d\n", ret);
|
||||
goto err_dcvdd;
|
||||
}
|
||||
|
||||
ret = regulator_enable(madera->dcvdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
madera_disable_hard_reset(madera);
|
||||
|
||||
regcache_cache_only(madera->regmap, false);
|
||||
regcache_cache_only(madera->regmap_32bit, false);
|
||||
|
||||
/*
|
||||
* Now we can power up and verify that this is a chip we know about
|
||||
* before we start doing any writes to its registers.
|
||||
*/
|
||||
ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read ID register: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
switch (hwid) {
|
||||
case CS47L35_SILICON_ID:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
|
||||
switch (madera->type) {
|
||||
case CS47L35:
|
||||
patch_fn = cs47l35_patch;
|
||||
mfd_devs = cs47l35_devs;
|
||||
n_devs = ARRAY_SIZE(cs47l35_devs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CS47L85_SILICON_ID:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
|
||||
switch (madera->type) {
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
patch_fn = cs47l85_patch;
|
||||
mfd_devs = cs47l85_devs;
|
||||
n_devs = ARRAY_SIZE(cs47l85_devs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CS47L90_SILICON_ID:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
|
||||
switch (madera->type) {
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
patch_fn = cs47l90_patch;
|
||||
mfd_devs = cs47l90_devs;
|
||||
n_devs = ARRAY_SIZE(cs47l90_devs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
|
||||
ret = -EINVAL;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
if (!n_devs) {
|
||||
dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid,
|
||||
madera->type_name);
|
||||
ret = -ENODEV;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
/*
|
||||
* It looks like a device we support. If we don't have a hard reset
|
||||
* we can now attempt a soft reset.
|
||||
*/
|
||||
if (!madera->pdata.reset) {
|
||||
ret = madera_soft_reset(madera);
|
||||
if (ret)
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
ret = madera_wait_for_boot(madera);
|
||||
if (ret) {
|
||||
dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,
|
||||
&madera->rev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read revision register: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
madera->rev &= MADERA_HW_REVISION_MASK;
|
||||
|
||||
dev_info(dev, "%s silicon revision %d\n", madera->type_name,
|
||||
madera->rev);
|
||||
|
||||
/* Apply hardware patch */
|
||||
if (patch_fn) {
|
||||
ret = patch_fn(madera);
|
||||
if (ret) {
|
||||
dev_err(madera->dev, "Failed to apply patch %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init 32k clock sourced from MCLK2 */
|
||||
ret = regmap_update_bits(madera->regmap,
|
||||
MADERA_CLOCK_32K_1,
|
||||
MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
|
||||
MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
|
||||
if (ret) {
|
||||
dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(madera->dev);
|
||||
pm_runtime_enable(madera->dev);
|
||||
pm_runtime_set_autosuspend_delay(madera->dev, 100);
|
||||
pm_runtime_use_autosuspend(madera->dev);
|
||||
|
||||
/* No devm_ because we need to control shutdown order of children */
|
||||
ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
|
||||
mfd_devs, n_devs,
|
||||
NULL, 0, NULL);
|
||||
if (ret) {
|
||||
dev_err(madera->dev, "Failed to add subdevices: %d\n", ret);
|
||||
goto err_pm_runtime;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_pm_runtime:
|
||||
pm_runtime_disable(madera->dev);
|
||||
err_reset:
|
||||
madera_enable_hard_reset(madera);
|
||||
regulator_disable(madera->dcvdd);
|
||||
err_enable:
|
||||
regulator_bulk_disable(madera->num_core_supplies,
|
||||
madera->core_supplies);
|
||||
err_dcvdd:
|
||||
regulator_put(madera->dcvdd);
|
||||
err_devs:
|
||||
mfd_remove_devices(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(madera_dev_init);
|
||||
|
||||
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);
|
||||
|
||||
regulator_disable(madera->dcvdd);
|
||||
regulator_put(madera->dcvdd);
|
||||
|
||||
mfd_remove_devices(madera->dev);
|
||||
madera_enable_hard_reset(madera);
|
||||
|
||||
regulator_bulk_disable(madera->num_core_supplies,
|
||||
madera->core_supplies);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(madera_dev_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Madera core MFD driver");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,140 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* I2C bus interface to Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <linux/mfd/madera/core.h>
|
||||
|
||||
#include "madera.h"
|
||||
|
||||
static int madera_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct madera *madera;
|
||||
const struct regmap_config *regmap_16bit_config = NULL;
|
||||
const struct regmap_config *regmap_32bit_config = NULL;
|
||||
const void *of_data;
|
||||
unsigned long type;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
of_data = of_device_get_match_data(&i2c->dev);
|
||||
if (of_data)
|
||||
type = (unsigned long)of_data;
|
||||
else
|
||||
type = id->driver_data;
|
||||
|
||||
switch (type) {
|
||||
case CS47L35:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
|
||||
regmap_16bit_config = &cs47l35_16bit_i2c_regmap;
|
||||
regmap_32bit_config = &cs47l35_32bit_i2c_regmap;
|
||||
}
|
||||
break;
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
|
||||
regmap_16bit_config = &cs47l85_16bit_i2c_regmap;
|
||||
regmap_32bit_config = &cs47l85_32bit_i2c_regmap;
|
||||
}
|
||||
break;
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
|
||||
regmap_16bit_config = &cs47l90_16bit_i2c_regmap;
|
||||
regmap_32bit_config = &cs47l90_32bit_i2c_regmap;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(&i2c->dev,
|
||||
"Unknown Madera I2C device type %ld\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
name = madera_name_from_type(type);
|
||||
|
||||
if (!regmap_16bit_config) {
|
||||
/* it's polite to say which codec isn't built into the kernel */
|
||||
dev_err(&i2c->dev,
|
||||
"Kernel does not include support for %s\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
madera = devm_kzalloc(&i2c->dev, sizeof(*madera), GFP_KERNEL);
|
||||
if (!madera)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config);
|
||||
if (IS_ERR(madera->regmap)) {
|
||||
ret = PTR_ERR(madera->regmap);
|
||||
dev_err(&i2c->dev,
|
||||
"Failed to allocate 16-bit register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
madera->regmap_32bit = devm_regmap_init_i2c(i2c, regmap_32bit_config);
|
||||
if (IS_ERR(madera->regmap_32bit)) {
|
||||
ret = PTR_ERR(madera->regmap_32bit);
|
||||
dev_err(&i2c->dev,
|
||||
"Failed to allocate 32-bit register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
madera->type = type;
|
||||
madera->type_name = name;
|
||||
madera->dev = &i2c->dev;
|
||||
madera->irq = i2c->irq;
|
||||
|
||||
return madera_dev_init(madera);
|
||||
}
|
||||
|
||||
static int madera_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct madera *madera = dev_get_drvdata(&i2c->dev);
|
||||
|
||||
madera_dev_exit(madera);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id madera_i2c_id[] = {
|
||||
{ "cs47l35", CS47L35 },
|
||||
{ "cs47l85", CS47L85 },
|
||||
{ "cs47l90", CS47L90 },
|
||||
{ "cs47l91", CS47L91 },
|
||||
{ "wm1840", WM1840 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, madera_i2c_id);
|
||||
|
||||
static struct i2c_driver madera_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "madera",
|
||||
.pm = &madera_pm_ops,
|
||||
.of_match_table = of_match_ptr(madera_of_match),
|
||||
},
|
||||
.probe = madera_i2c_probe,
|
||||
.remove = madera_i2c_remove,
|
||||
.id_table = madera_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(madera_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Madera I2C bus interface");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,139 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* SPI bus interface to Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <linux/mfd/madera/core.h>
|
||||
|
||||
#include "madera.h"
|
||||
|
||||
static int madera_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct spi_device_id *id = spi_get_device_id(spi);
|
||||
struct madera *madera;
|
||||
const struct regmap_config *regmap_16bit_config = NULL;
|
||||
const struct regmap_config *regmap_32bit_config = NULL;
|
||||
const void *of_data;
|
||||
unsigned long type;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
of_data = of_device_get_match_data(&spi->dev);
|
||||
if (of_data)
|
||||
type = (unsigned long)of_data;
|
||||
else
|
||||
type = id->driver_data;
|
||||
|
||||
switch (type) {
|
||||
case CS47L35:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
|
||||
regmap_16bit_config = &cs47l35_16bit_spi_regmap;
|
||||
regmap_32bit_config = &cs47l35_32bit_spi_regmap;
|
||||
}
|
||||
break;
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
|
||||
regmap_16bit_config = &cs47l85_16bit_spi_regmap;
|
||||
regmap_32bit_config = &cs47l85_32bit_spi_regmap;
|
||||
}
|
||||
break;
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
|
||||
regmap_16bit_config = &cs47l90_16bit_spi_regmap;
|
||||
regmap_32bit_config = &cs47l90_32bit_spi_regmap;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(&spi->dev,
|
||||
"Unknown Madera SPI device type %ld\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
name = madera_name_from_type(type);
|
||||
|
||||
if (!regmap_16bit_config) {
|
||||
/* it's polite to say which codec isn't built into the kernel */
|
||||
dev_err(&spi->dev,
|
||||
"Kernel does not include support for %s\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
madera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);
|
||||
if (!madera)
|
||||
return -ENOMEM;
|
||||
|
||||
madera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);
|
||||
if (IS_ERR(madera->regmap)) {
|
||||
ret = PTR_ERR(madera->regmap);
|
||||
dev_err(&spi->dev,
|
||||
"Failed to allocate 16-bit register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
madera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);
|
||||
if (IS_ERR(madera->regmap_32bit)) {
|
||||
ret = PTR_ERR(madera->regmap_32bit);
|
||||
dev_err(&spi->dev,
|
||||
"Failed to allocate 32-bit register map: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
madera->type = type;
|
||||
madera->type_name = name;
|
||||
madera->dev = &spi->dev;
|
||||
madera->irq = spi->irq;
|
||||
|
||||
return madera_dev_init(madera);
|
||||
}
|
||||
|
||||
static int madera_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct madera *madera = spi_get_drvdata(spi);
|
||||
|
||||
madera_dev_exit(madera);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id madera_spi_ids[] = {
|
||||
{ "cs47l35", CS47L35 },
|
||||
{ "cs47l85", CS47L85 },
|
||||
{ "cs47l90", CS47L90 },
|
||||
{ "cs47l91", CS47L91 },
|
||||
{ "wm1840", WM1840 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, madera_spi_ids);
|
||||
|
||||
static struct spi_driver madera_spi_driver = {
|
||||
.driver = {
|
||||
.name = "madera",
|
||||
.pm = &madera_pm_ops,
|
||||
.of_match_table = of_match_ptr(madera_of_match),
|
||||
},
|
||||
.probe = madera_spi_probe,
|
||||
.remove = madera_spi_remove,
|
||||
.id_table = madera_spi_ids,
|
||||
};
|
||||
|
||||
module_spi_driver(madera_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Madera SPI bus interface");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* MFD internals for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright 2015-2018 Cirrus Logic
|
||||
*
|
||||
* 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
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MADERA_MFD_H
|
||||
#define MADERA_MFD_H
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
struct madera;
|
||||
|
||||
extern const struct dev_pm_ops madera_pm_ops;
|
||||
extern const struct of_device_id madera_of_match[];
|
||||
|
||||
int madera_dev_init(struct madera *madera);
|
||||
int madera_dev_exit(struct madera *madera);
|
||||
|
||||
const char *madera_name_from_type(enum madera_type type);
|
||||
|
||||
extern const struct regmap_config cs47l35_16bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l35_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l35_16bit_i2c_regmap;
|
||||
extern const struct regmap_config cs47l35_32bit_i2c_regmap;
|
||||
int cs47l35_patch(struct madera *madera);
|
||||
|
||||
extern const struct regmap_config cs47l85_16bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l85_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l85_16bit_i2c_regmap;
|
||||
extern const struct regmap_config cs47l85_32bit_i2c_regmap;
|
||||
int cs47l85_patch(struct madera *madera);
|
||||
|
||||
extern const struct regmap_config cs47l90_16bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l90_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l90_16bit_i2c_regmap;
|
||||
extern const struct regmap_config cs47l90_32bit_i2c_regmap;
|
||||
int cs47l90_patch(struct madera *madera);
|
||||
#endif
|
|
@ -63,16 +63,6 @@
|
|||
#define RAVE_SP_TX_BUFFER_SIZE \
|
||||
(RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
|
||||
|
||||
#define RAVE_SP_BOOT_SOURCE_GET 0
|
||||
#define RAVE_SP_BOOT_SOURCE_SET 1
|
||||
|
||||
#define RAVE_SP_RDU2_BOARD_TYPE_RMB 0
|
||||
#define RAVE_SP_RDU2_BOARD_TYPE_DEB 1
|
||||
|
||||
#define RAVE_SP_BOOT_SOURCE_SD 0
|
||||
#define RAVE_SP_BOOT_SOURCE_EMMC 1
|
||||
#define RAVE_SP_BOOT_SOURCE_NOR 2
|
||||
|
||||
/**
|
||||
* enum rave_sp_deframer_state - Possible state for de-framer
|
||||
*
|
||||
|
@ -127,14 +117,44 @@ struct rave_sp_checksum {
|
|||
void (*subroutine)(const u8 *, size_t, u8 *);
|
||||
};
|
||||
|
||||
struct rave_sp_version {
|
||||
u8 hardware;
|
||||
__le16 major;
|
||||
u8 minor;
|
||||
u8 letter[2];
|
||||
} __packed;
|
||||
|
||||
struct rave_sp_status {
|
||||
struct rave_sp_version bootloader_version;
|
||||
struct rave_sp_version firmware_version;
|
||||
u16 rdu_eeprom_flag;
|
||||
u16 dds_eeprom_flag;
|
||||
u8 pic_flag;
|
||||
u8 orientation;
|
||||
u32 etc;
|
||||
s16 temp[2];
|
||||
u8 backlight_current[3];
|
||||
u8 dip_switch;
|
||||
u8 host_interrupt;
|
||||
u16 voltage_28;
|
||||
u8 i2c_device_status;
|
||||
u8 power_status;
|
||||
u8 general_status;
|
||||
u8 deprecated1;
|
||||
u8 power_led_status;
|
||||
u8 deprecated2;
|
||||
u8 periph_power_shutoff;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct rave_sp_variant_cmds - Variant specific command routines
|
||||
*
|
||||
* @translate: Generic to variant specific command mapping routine
|
||||
*
|
||||
* @get_status: Variant specific implementation of CMD_GET_STATUS
|
||||
*/
|
||||
struct rave_sp_variant_cmds {
|
||||
int (*translate)(enum rave_sp_command);
|
||||
int (*get_status)(struct rave_sp *sp, struct rave_sp_status *);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -180,35 +200,6 @@ struct rave_sp {
|
|||
const char *part_number_bootloader;
|
||||
};
|
||||
|
||||
struct rave_sp_version {
|
||||
u8 hardware;
|
||||
__le16 major;
|
||||
u8 minor;
|
||||
u8 letter[2];
|
||||
} __packed;
|
||||
|
||||
struct rave_sp_status {
|
||||
struct rave_sp_version bootloader_version;
|
||||
struct rave_sp_version firmware_version;
|
||||
u16 rdu_eeprom_flag;
|
||||
u16 dds_eeprom_flag;
|
||||
u8 pic_flag;
|
||||
u8 orientation;
|
||||
u32 etc;
|
||||
s16 temp[2];
|
||||
u8 backlight_current[3];
|
||||
u8 dip_switch;
|
||||
u8 host_interrupt;
|
||||
u16 voltage_28;
|
||||
u8 i2c_device_status;
|
||||
u8 power_status;
|
||||
u8 general_status;
|
||||
u8 deprecated1;
|
||||
u8 power_led_status;
|
||||
u8 deprecated2;
|
||||
u8 periph_power_shutoff;
|
||||
} __packed;
|
||||
|
||||
static bool rave_sp_id_is_event(u8 code)
|
||||
{
|
||||
return (code & 0xF0) == RAVE_SP_EVNT_BASE;
|
||||
|
@ -641,10 +632,14 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command)
|
|||
return 0x14;
|
||||
case RAVE_SP_CMD_SW_WDT:
|
||||
return 0x1C;
|
||||
case RAVE_SP_CMD_PET_WDT:
|
||||
return 0x1D;
|
||||
case RAVE_SP_CMD_RESET:
|
||||
return 0x1E;
|
||||
case RAVE_SP_CMD_RESET_REASON:
|
||||
return 0x1F;
|
||||
case RAVE_SP_CMD_RMB_EEPROM:
|
||||
return 0x20;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -666,18 +661,44 @@ static const char *devm_rave_sp_version(struct device *dev,
|
|||
version->letter[1]);
|
||||
}
|
||||
|
||||
static int rave_sp_get_status(struct rave_sp *sp)
|
||||
static int rave_sp_rdu1_get_status(struct rave_sp *sp,
|
||||
struct rave_sp_status *status)
|
||||
{
|
||||
struct device *dev = &sp->serdev->dev;
|
||||
u8 cmd[] = {
|
||||
[0] = RAVE_SP_CMD_STATUS,
|
||||
[1] = 0
|
||||
};
|
||||
|
||||
return rave_sp_exec(sp, cmd, sizeof(cmd), status, sizeof(*status));
|
||||
}
|
||||
|
||||
static int rave_sp_emulated_get_status(struct rave_sp *sp,
|
||||
struct rave_sp_status *status)
|
||||
{
|
||||
u8 cmd[] = {
|
||||
[0] = RAVE_SP_CMD_GET_FIRMWARE_VERSION,
|
||||
[1] = 0,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status->firmware_version,
|
||||
sizeof(status->firmware_version));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd[0] = RAVE_SP_CMD_GET_BOOTLOADER_VERSION;
|
||||
return rave_sp_exec(sp, cmd, sizeof(cmd), &status->bootloader_version,
|
||||
sizeof(status->bootloader_version));
|
||||
}
|
||||
|
||||
static int rave_sp_get_status(struct rave_sp *sp)
|
||||
{
|
||||
struct device *dev = &sp->serdev->dev;
|
||||
struct rave_sp_status status;
|
||||
const char *version;
|
||||
int ret;
|
||||
|
||||
ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
|
||||
ret = sp->variant->cmd.get_status(sp, &status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -707,9 +728,10 @@ static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
|
|||
};
|
||||
|
||||
static const struct rave_sp_variant rave_sp_legacy = {
|
||||
.checksum = &rave_sp_checksum_8b2c,
|
||||
.checksum = &rave_sp_checksum_ccitt,
|
||||
.cmd = {
|
||||
.translate = rave_sp_default_cmd_translate,
|
||||
.get_status = rave_sp_emulated_get_status,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -717,6 +739,7 @@ static const struct rave_sp_variant rave_sp_rdu1 = {
|
|||
.checksum = &rave_sp_checksum_8b2c,
|
||||
.cmd = {
|
||||
.translate = rave_sp_rdu1_cmd_translate,
|
||||
.get_status = rave_sp_rdu1_get_status,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -724,6 +747,7 @@ static const struct rave_sp_variant rave_sp_rdu2 = {
|
|||
.checksum = &rave_sp_checksum_ccitt,
|
||||
.cmd = {
|
||||
.translate = rave_sp_rdu2_cmd_translate,
|
||||
.get_status = rave_sp_emulated_get_status,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -776,6 +800,13 @@ static int rave_sp_probe(struct serdev_device *serdev)
|
|||
return ret;
|
||||
|
||||
serdev_device_set_baudrate(serdev, baud);
|
||||
serdev_device_set_flow_control(serdev, false);
|
||||
|
||||
ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set parity\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rave_sp_get_status(sp);
|
||||
if (ret) {
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Copyright (C) 2018 ROHM Semiconductors
|
||||
//
|
||||
// ROHM BD71837MWV PMIC driver
|
||||
//
|
||||
// Datasheet available from
|
||||
// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/rohm-bd718x7.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/*
|
||||
* gpio_keys.h requires definiton of bool. It is brought in
|
||||
* by above includes. Keep this as last until gpio_keys.h gets fixed.
|
||||
*/
|
||||
#include <linux/gpio_keys.h>
|
||||
|
||||
static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ };
|
||||
|
||||
static struct gpio_keys_button button = {
|
||||
.code = KEY_POWER,
|
||||
.gpio = -1,
|
||||
.type = EV_KEY,
|
||||
};
|
||||
|
||||
static struct gpio_keys_platform_data bd718xx_powerkey_data = {
|
||||
.buttons = &button,
|
||||
.nbuttons = 1,
|
||||
.name = "bd718xx-pwrkey",
|
||||
};
|
||||
|
||||
static struct mfd_cell bd71837_mfd_cells[] = {
|
||||
{
|
||||
.name = "gpio-keys",
|
||||
.platform_data = &bd718xx_powerkey_data,
|
||||
.pdata_size = sizeof(bd718xx_powerkey_data),
|
||||
},
|
||||
{ .name = "bd71837-clk", },
|
||||
{ .name = "bd71837-pmic", },
|
||||
};
|
||||
|
||||
static const struct regmap_irq bd71837_irqs[] = {
|
||||
REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK),
|
||||
REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK),
|
||||
REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK),
|
||||
REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK),
|
||||
REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK),
|
||||
REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK),
|
||||
REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip bd71837_irq_chip = {
|
||||
.name = "bd71837-irq",
|
||||
.irqs = bd71837_irqs,
|
||||
.num_irqs = ARRAY_SIZE(bd71837_irqs),
|
||||
.num_regs = 1,
|
||||
.irq_reg_stride = 1,
|
||||
.status_base = BD71837_REG_IRQ,
|
||||
.mask_base = BD71837_REG_MIRQ,
|
||||
.ack_base = BD71837_REG_IRQ,
|
||||
.init_ack_masked = true,
|
||||
.mask_invert = false,
|
||||
};
|
||||
|
||||
static const struct regmap_range pmic_status_range = {
|
||||
.range_min = BD71837_REG_IRQ,
|
||||
.range_max = BD71837_REG_POW_STATE,
|
||||
};
|
||||
|
||||
static const struct regmap_access_table volatile_regs = {
|
||||
.yes_ranges = &pmic_status_range,
|
||||
.n_yes_ranges = 1,
|
||||
};
|
||||
|
||||
static const struct regmap_config bd71837_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_table = &volatile_regs,
|
||||
.max_register = BD71837_MAX_REGISTER - 1,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int bd71837_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct bd71837 *bd71837;
|
||||
int ret, i;
|
||||
unsigned int val;
|
||||
|
||||
bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL);
|
||||
|
||||
if (!bd71837)
|
||||
return -ENOMEM;
|
||||
|
||||
bd71837->chip_irq = i2c->irq;
|
||||
|
||||
if (!bd71837->chip_irq) {
|
||||
dev_err(&i2c->dev, "No IRQ configured\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bd71837->dev = &i2c->dev;
|
||||
dev_set_drvdata(&i2c->dev, bd71837);
|
||||
|
||||
bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config);
|
||||
if (IS_ERR(bd71837->regmap)) {
|
||||
dev_err(&i2c->dev, "regmap initialization failed\n");
|
||||
return PTR_ERR(bd71837->regmap);
|
||||
}
|
||||
|
||||
ret = regmap_read(bd71837->regmap, BD71837_REG_REV, &val);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Read BD71837_REG_DEVICE failed\n");
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(supported_revisions); i++)
|
||||
if (supported_revisions[i] == val)
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(supported_revisions)) {
|
||||
dev_err(&i2c->dev, "Unsupported chip revision\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap,
|
||||
bd71837->chip_irq, IRQF_ONESHOT, 0,
|
||||
&bd71837_irq_chip, &bd71837->irq_data);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to add irq_chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure short press to 10 milliseconds */
|
||||
ret = regmap_update_bits(bd71837->regmap,
|
||||
BD71837_REG_PWRONCONFIG0,
|
||||
BD718XX_PWRBTN_PRESS_DURATION_MASK,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_10MS);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev,
|
||||
"Failed to configure button short press timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure long press to 10 seconds */
|
||||
ret = regmap_update_bits(bd71837->regmap,
|
||||
BD71837_REG_PWRONCONFIG1,
|
||||
BD718XX_PWRBTN_PRESS_DURATION_MASK,
|
||||
BD718XX_PWRBTN_LONG_PRESS_10S);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev,
|
||||
"Failed to configure button long press timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_irq_get_virq(bd71837->irq_data, BD71837_INT_PWRBTN_S);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "Failed to get the IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
button.irq = ret;
|
||||
|
||||
ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO,
|
||||
bd71837_mfd_cells,
|
||||
ARRAY_SIZE(bd71837_mfd_cells), NULL, 0,
|
||||
regmap_irq_get_domain(bd71837->irq_data));
|
||||
if (ret)
|
||||
dev_err(&i2c->dev, "Failed to create subdevices\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id bd71837_of_match[] = {
|
||||
{ .compatible = "rohm,bd71837", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bd71837_of_match);
|
||||
|
||||
static struct i2c_driver bd71837_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rohm-bd718x7",
|
||||
.of_match_table = bd71837_of_match,
|
||||
},
|
||||
.probe = bd71837_i2c_probe,
|
||||
};
|
||||
|
||||
static int __init bd71837_i2c_init(void)
|
||||
{
|
||||
return i2c_add_driver(&bd71837_i2c_driver);
|
||||
}
|
||||
|
||||
/* Initialise early so consumer devices can complete system boot */
|
||||
subsys_initcall(bd71837_i2c_init);
|
||||
|
||||
static void __exit bd71837_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&bd71837_i2c_driver);
|
||||
}
|
||||
module_exit(bd71837_i2c_exit);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("ROHM BD71837 Power Management IC driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -146,6 +146,7 @@ static const struct of_device_id sec_dt_match[] = {
|
|||
/* Sentinel */
|
||||
},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sec_dt_match);
|
||||
#endif
|
||||
|
||||
static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
|
||||
|
|
|
@ -715,6 +715,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name,
|
|||
smdev->pdev.name = name;
|
||||
smdev->pdev.id = sm->pdev_id;
|
||||
smdev->pdev.dev.parent = sm->dev;
|
||||
smdev->pdev.dev.coherent_dma_mask = 0xffffffff;
|
||||
|
||||
if (res_count) {
|
||||
smdev->pdev.resource = (struct resource *)(smdev+1);
|
||||
|
|
|
@ -209,14 +209,13 @@ static int ti_tscadc_probe(struct platform_device *pdev)
|
|||
* The TSC_ADC_SS controller design assumes the OCP clock is
|
||||
* at least 6x faster than the ADC clock.
|
||||
*/
|
||||
clk = clk_get(&pdev->dev, "adc_tsc_fck");
|
||||
clk = devm_clk_get(&pdev->dev, "adc_tsc_fck");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&pdev->dev, "failed to get TSC fck\n");
|
||||
err = PTR_ERR(clk);
|
||||
goto err_disable_clk;
|
||||
}
|
||||
clock_rate = clk_get_rate(clk);
|
||||
clk_put(clk);
|
||||
tscadc->clk_div = clock_rate / ADC_CLK;
|
||||
|
||||
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
|
||||
|
|
|
@ -302,6 +302,10 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
|
|||
if (of_find_property(np, "wlf,ldoena-always-driven", NULL))
|
||||
pdata->lineout2fb = true;
|
||||
|
||||
pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu");
|
||||
|
||||
pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd");
|
||||
|
||||
pdata->ldo[0].enable = of_get_named_gpio(np, "wlf,ldo1ena", 0);
|
||||
if (pdata->ldo[0].enable < 0)
|
||||
pdata->ldo[0].enable = 0;
|
||||
|
@ -513,14 +517,15 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||
break;
|
||||
default:
|
||||
dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
/* Explicitly put the device into reset in case regulators
|
||||
|
@ -531,7 +536,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||
wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
|
||||
if (ret != 0) {
|
||||
dev_err(wm8994->dev, "Failed to reset device: %d\n", ret);
|
||||
return ret;
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
if (regmap_patch) {
|
||||
|
@ -540,7 +545,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||
if (ret != 0) {
|
||||
dev_err(wm8994->dev, "Failed to register patch: %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
goto err_enable;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,6 +564,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||
|
||||
if (pdata->spkmode_pu)
|
||||
pulls |= WM8994_SPKMODE_PU;
|
||||
if (pdata->csnaddr_pd)
|
||||
pulls |= WM8994_CSNADDR_PD;
|
||||
|
||||
/* Disable unneeded pulls */
|
||||
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
|
||||
|
|
|
@ -361,6 +361,7 @@ source "drivers/pinctrl/vt8500/Kconfig"
|
|||
source "drivers/pinctrl/mediatek/Kconfig"
|
||||
source "drivers/pinctrl/zte/Kconfig"
|
||||
source "drivers/pinctrl/meson/Kconfig"
|
||||
source "drivers/pinctrl/cirrus/Kconfig"
|
||||
|
||||
config PINCTRL_XWAY
|
||||
bool
|
||||
|
|
|
@ -64,3 +64,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
|
|||
obj-$(CONFIG_ARCH_VT8500) += vt8500/
|
||||
obj-y += mediatek/
|
||||
obj-$(CONFIG_PINCTRL_ZX) += zte/
|
||||
obj-y += cirrus/
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# This is all selected by the Madera MFD driver Kconfig options
|
||||
config PINCTRL_MADERA
|
||||
tristate
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_CS47L35
|
||||
bool
|
||||
|
||||
config PINCTRL_CS47L85
|
||||
bool
|
||||
|
||||
config PINCTRL_CS47L90
|
||||
bool
|
|
@ -0,0 +1,13 @@
|
|||
# Cirrus Logic pinctrl drivers
|
||||
pinctrl-madera-objs := pinctrl-madera-core.o
|
||||
ifeq ($(CONFIG_PINCTRL_CS47L35),y)
|
||||
pinctrl-madera-objs += pinctrl-cs47l35.o
|
||||
endif
|
||||
ifeq ($(CONFIG_PINCTRL_CS47L85),y)
|
||||
pinctrl-madera-objs += pinctrl-cs47l85.o
|
||||
endif
|
||||
ifeq ($(CONFIG_PINCTRL_CS47L90),y)
|
||||
pinctrl-madera-objs += pinctrl-cs47l90.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_PINCTRL_MADERA) += pinctrl-madera.o
|
|
@ -0,0 +1,45 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Pinctrl for Cirrus Logic CS47L35
|
||||
*
|
||||
* Copyright (C) 2016-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/madera/core.h>
|
||||
|
||||
#include "pinctrl-madera.h"
|
||||
|
||||
/*
|
||||
* The alt func groups are the most commonly used functions we place these at
|
||||
* the lower function indexes for convenience, and the less commonly used gpio
|
||||
* functions at higher indexes.
|
||||
*
|
||||
* To stay consistent with the datasheet the function names are the same as
|
||||
* the group names for that function's pins
|
||||
*
|
||||
* Note - all 1 less than in datasheet because these are zero-indexed
|
||||
*/
|
||||
static const unsigned int cs47l35_aif3_pins[] = { 0, 1, 2, 3 };
|
||||
static const unsigned int cs47l35_spk_pins[] = { 4, 5 };
|
||||
static const unsigned int cs47l35_aif1_pins[] = { 7, 8, 9, 10 };
|
||||
static const unsigned int cs47l35_aif2_pins[] = { 11, 12, 13, 14 };
|
||||
static const unsigned int cs47l35_mif1_pins[] = { 6, 15 };
|
||||
|
||||
static const struct madera_pin_groups cs47l35_pin_groups[] = {
|
||||
{ "aif1", cs47l35_aif1_pins, ARRAY_SIZE(cs47l35_aif1_pins) },
|
||||
{ "aif2", cs47l35_aif2_pins, ARRAY_SIZE(cs47l35_aif2_pins) },
|
||||
{ "aif3", cs47l35_aif3_pins, ARRAY_SIZE(cs47l35_aif3_pins) },
|
||||
{ "mif1", cs47l35_mif1_pins, ARRAY_SIZE(cs47l35_mif1_pins) },
|
||||
{ "pdmspk1", cs47l35_spk_pins, ARRAY_SIZE(cs47l35_spk_pins) },
|
||||
};
|
||||
|
||||
const struct madera_pin_chip cs47l35_pin_chip = {
|
||||
.n_pins = CS47L35_NUM_GPIOS,
|
||||
.pin_groups = cs47l35_pin_groups,
|
||||
.n_pin_groups = ARRAY_SIZE(cs47l35_pin_groups),
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Pinctrl for Cirrus Logic CS47L85
|
||||
*
|
||||
* Copyright (C) 2016-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/madera/core.h>
|
||||
|
||||
#include "pinctrl-madera.h"
|
||||
|
||||
/*
|
||||
* The alt func groups are the most commonly used functions we place these at
|
||||
* the lower function indexes for convenience, and the less commonly used gpio
|
||||
* functions at higher indexes.
|
||||
*
|
||||
* To stay consistent with the datasheet the function names are the same as
|
||||
* the group names for that function's pins
|
||||
*
|
||||
* Note - all 1 less than in datasheet because these are zero-indexed
|
||||
*/
|
||||
static const unsigned int cs47l85_mif1_pins[] = { 8, 9 };
|
||||
static const unsigned int cs47l85_mif2_pins[] = { 10, 11 };
|
||||
static const unsigned int cs47l85_mif3_pins[] = { 12, 13 };
|
||||
static const unsigned int cs47l85_aif1_pins[] = { 14, 15, 16, 17 };
|
||||
static const unsigned int cs47l85_aif2_pins[] = { 18, 19, 20, 21 };
|
||||
static const unsigned int cs47l85_aif3_pins[] = { 22, 23, 24, 25 };
|
||||
static const unsigned int cs47l85_aif4_pins[] = { 26, 27, 28, 29 };
|
||||
static const unsigned int cs47l85_dmic4_pins[] = { 30, 31 };
|
||||
static const unsigned int cs47l85_dmic5_pins[] = { 32, 33 };
|
||||
static const unsigned int cs47l85_dmic6_pins[] = { 34, 35 };
|
||||
static const unsigned int cs47l85_spk1_pins[] = { 36, 38 };
|
||||
static const unsigned int cs47l85_spk2_pins[] = { 37, 39 };
|
||||
|
||||
static const struct madera_pin_groups cs47l85_pin_groups[] = {
|
||||
{ "aif1", cs47l85_aif1_pins, ARRAY_SIZE(cs47l85_aif1_pins) },
|
||||
{ "aif2", cs47l85_aif2_pins, ARRAY_SIZE(cs47l85_aif2_pins) },
|
||||
{ "aif3", cs47l85_aif3_pins, ARRAY_SIZE(cs47l85_aif3_pins) },
|
||||
{ "aif4", cs47l85_aif4_pins, ARRAY_SIZE(cs47l85_aif4_pins) },
|
||||
{ "mif1", cs47l85_mif1_pins, ARRAY_SIZE(cs47l85_mif1_pins) },
|
||||
{ "mif2", cs47l85_mif2_pins, ARRAY_SIZE(cs47l85_mif2_pins) },
|
||||
{ "mif3", cs47l85_mif3_pins, ARRAY_SIZE(cs47l85_mif3_pins) },
|
||||
{ "dmic4", cs47l85_dmic4_pins, ARRAY_SIZE(cs47l85_dmic4_pins) },
|
||||
{ "dmic5", cs47l85_dmic5_pins, ARRAY_SIZE(cs47l85_dmic5_pins) },
|
||||
{ "dmic6", cs47l85_dmic6_pins, ARRAY_SIZE(cs47l85_dmic6_pins) },
|
||||
{ "pdmspk1", cs47l85_spk1_pins, ARRAY_SIZE(cs47l85_spk1_pins) },
|
||||
{ "pdmspk2", cs47l85_spk2_pins, ARRAY_SIZE(cs47l85_spk2_pins) },
|
||||
};
|
||||
|
||||
const struct madera_pin_chip cs47l85_pin_chip = {
|
||||
.n_pins = CS47L85_NUM_GPIOS,
|
||||
.pin_groups = cs47l85_pin_groups,
|
||||
.n_pin_groups = ARRAY_SIZE(cs47l85_pin_groups),
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Pinctrl for Cirrus Logic CS47L90
|
||||
*
|
||||
* Copyright (C) 2016-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/madera/core.h>
|
||||
|
||||
#include "pinctrl-madera.h"
|
||||
|
||||
/*
|
||||
* The alt func groups are the most commonly used functions we place these at
|
||||
* the lower function indexes for convenience, and the less commonly used gpio
|
||||
* functions at higher indexes.
|
||||
*
|
||||
* To stay consistent with the datasheet the function names are the same as
|
||||
* the group names for that function's pins
|
||||
*
|
||||
* Note - all 1 less than in datasheet because these are zero-indexed
|
||||
*/
|
||||
static const unsigned int cs47l90_mif1_pins[] = { 8, 9 };
|
||||
static const unsigned int cs47l90_mif2_pins[] = { 10, 11 };
|
||||
static const unsigned int cs47l90_mif3_pins[] = { 12, 13 };
|
||||
static const unsigned int cs47l90_aif1_pins[] = { 14, 15, 16, 17 };
|
||||
static const unsigned int cs47l90_aif2_pins[] = { 18, 19, 20, 21 };
|
||||
static const unsigned int cs47l90_aif3_pins[] = { 22, 23, 24, 25 };
|
||||
static const unsigned int cs47l90_aif4_pins[] = { 26, 27, 28, 29 };
|
||||
static const unsigned int cs47l90_dmic4_pins[] = { 30, 31 };
|
||||
static const unsigned int cs47l90_dmic5_pins[] = { 32, 33 };
|
||||
static const unsigned int cs47l90_dmic3_pins[] = { 34, 35 };
|
||||
static const unsigned int cs47l90_spk1_pins[] = { 36, 37 };
|
||||
|
||||
static const struct madera_pin_groups cs47l90_pin_groups[] = {
|
||||
{ "aif1", cs47l90_aif1_pins, ARRAY_SIZE(cs47l90_aif1_pins) },
|
||||
{ "aif2", cs47l90_aif2_pins, ARRAY_SIZE(cs47l90_aif2_pins) },
|
||||
{ "aif3", cs47l90_aif3_pins, ARRAY_SIZE(cs47l90_aif3_pins) },
|
||||
{ "aif4", cs47l90_aif4_pins, ARRAY_SIZE(cs47l90_aif4_pins) },
|
||||
{ "mif1", cs47l90_mif1_pins, ARRAY_SIZE(cs47l90_mif1_pins) },
|
||||
{ "mif2", cs47l90_mif2_pins, ARRAY_SIZE(cs47l90_mif2_pins) },
|
||||
{ "mif3", cs47l90_mif3_pins, ARRAY_SIZE(cs47l90_mif3_pins) },
|
||||
{ "dmic3", cs47l90_dmic3_pins, ARRAY_SIZE(cs47l90_dmic3_pins) },
|
||||
{ "dmic4", cs47l90_dmic4_pins, ARRAY_SIZE(cs47l90_dmic4_pins) },
|
||||
{ "dmic5", cs47l90_dmic5_pins, ARRAY_SIZE(cs47l90_dmic5_pins) },
|
||||
{ "pdmspk1", cs47l90_spk1_pins, ARRAY_SIZE(cs47l90_spk1_pins) },
|
||||
};
|
||||
|
||||
const struct madera_pin_chip cs47l90_pin_chip = {
|
||||
.n_pins = CS47L90_NUM_GPIOS,
|
||||
.pin_groups = cs47l90_pin_groups,
|
||||
.n_pin_groups = ARRAY_SIZE(cs47l90_pin_groups),
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,41 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Pinctrl for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2016-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#ifndef PINCTRL_MADERA_H
|
||||
#define PINCTRL_MADERA_H
|
||||
|
||||
struct madera_pin_groups {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
unsigned int n_pins;
|
||||
};
|
||||
|
||||
struct madera_pin_chip {
|
||||
unsigned int n_pins;
|
||||
|
||||
const struct madera_pin_groups *pin_groups;
|
||||
unsigned int n_pin_groups;
|
||||
};
|
||||
|
||||
struct madera_pin_private {
|
||||
struct madera *madera;
|
||||
|
||||
const struct madera_pin_chip *chip; /* chip-specific groups */
|
||||
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl;
|
||||
};
|
||||
|
||||
extern const struct madera_pin_chip cs47l35_pin_chip;
|
||||
extern const struct madera_pin_chip cs47l85_pin_chip;
|
||||
extern const struct madera_pin_chip cs47l90_pin_chip;
|
||||
|
||||
#endif
|
|
@ -52,6 +52,26 @@ config CHROMEOS_TBMC
|
|||
config CROS_EC_CTL
|
||||
tristate
|
||||
|
||||
config CROS_EC_I2C
|
||||
tristate "ChromeOS Embedded Controller (I2C)"
|
||||
depends on MFD_CROS_EC && I2C
|
||||
|
||||
help
|
||||
If you say Y here, you get support for talking to the ChromeOS
|
||||
EC through an I2C bus. This uses a simple byte-level protocol with
|
||||
a checksum. Failing accesses will be retried three times to
|
||||
improve reliability.
|
||||
|
||||
config CROS_EC_SPI
|
||||
tristate "ChromeOS Embedded Controller (SPI)"
|
||||
depends on MFD_CROS_EC && SPI
|
||||
|
||||
---help---
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
through a SPI bus, using a byte-level protocol. Since the EC's
|
||||
response time cannot be guaranteed, we support ignoring
|
||||
'pre-amble' bytes before the response actually starts.
|
||||
|
||||
config CROS_EC_LPC
|
||||
tristate "ChromeOS Embedded Controller (LPC)"
|
||||
depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
|
||||
|
|
|
@ -6,6 +6,8 @@ obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
|
|||
cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \
|
||||
cros_ec_vbc.o cros_ec_debugfs.o
|
||||
obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o
|
||||
obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
|
||||
cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_reg.o
|
||||
cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
|
||||
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
|
||||
|
|
|
@ -506,10 +506,31 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
|
|||
}
|
||||
EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
|
||||
|
||||
static int get_next_event_xfer(struct cros_ec_device *ec_dev,
|
||||
struct cros_ec_command *msg,
|
||||
int version, uint32_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
msg->version = version;
|
||||
msg->command = EC_CMD_GET_NEXT_EVENT;
|
||||
msg->insize = size;
|
||||
msg->outsize = 0;
|
||||
|
||||
ret = cros_ec_cmd_xfer(ec_dev, msg);
|
||||
if (ret > 0) {
|
||||
ec_dev->event_size = ret - 1;
|
||||
memcpy(&ec_dev->event_data, msg->data, ec_dev->event_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_next_event(struct cros_ec_device *ec_dev)
|
||||
{
|
||||
u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
|
||||
struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
|
||||
static int cmd_version = 1;
|
||||
int ret;
|
||||
|
||||
if (ec_dev->suspended) {
|
||||
|
@ -517,18 +538,19 @@ static int get_next_event(struct cros_ec_device *ec_dev)
|
|||
return -EHOSTDOWN;
|
||||
}
|
||||
|
||||
msg->version = 0;
|
||||
msg->command = EC_CMD_GET_NEXT_EVENT;
|
||||
msg->insize = sizeof(ec_dev->event_data);
|
||||
msg->outsize = 0;
|
||||
if (cmd_version == 1) {
|
||||
ret = get_next_event_xfer(ec_dev, msg, cmd_version,
|
||||
sizeof(struct ec_response_get_next_event_v1));
|
||||
if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
|
||||
return ret;
|
||||
|
||||
ret = cros_ec_cmd_xfer(ec_dev, msg);
|
||||
if (ret > 0) {
|
||||
ec_dev->event_size = ret - 1;
|
||||
memcpy(&ec_dev->event_data, msg->data,
|
||||
sizeof(ec_dev->event_data));
|
||||
/* Fallback to version 0 for future send attempts */
|
||||
cmd_version = 0;
|
||||
}
|
||||
|
||||
ret = get_next_event_xfer(ec_dev, msg, cmd_version,
|
||||
sizeof(struct ec_response_get_next_event));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ struct da9063_regulator_info {
|
|||
struct da9063_dev_model {
|
||||
const struct da9063_regulator_info *regulator_info;
|
||||
unsigned n_regulators;
|
||||
unsigned dev_model;
|
||||
enum da9063_type type;
|
||||
};
|
||||
|
||||
/* Single regulator settings */
|
||||
|
@ -529,32 +529,11 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
|
|||
.ilimit = BFIELD(DA9063_REG_BUCK_ILIM_A,
|
||||
DA9063_BMEM_ILIM_MASK),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO2, 600, 20, 1860),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
|
||||
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL),
|
||||
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO5, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO5_CONT, DA9063_VLDO5_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
|
||||
|
@ -569,15 +548,39 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
|
|||
DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
|
||||
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
|
||||
},
|
||||
|
||||
/* The following LDOs are present only on DA9063, not on DA9063L */
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO2, 600, 20, 1860),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
|
||||
.suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL),
|
||||
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO5, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO5_CONT, DA9063_VLDO5_SEL),
|
||||
},
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL),
|
||||
},
|
||||
|
||||
{
|
||||
DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
|
||||
.suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL),
|
||||
},
|
||||
};
|
||||
|
||||
/* Link chip model with regulators info table */
|
||||
|
@ -585,7 +588,12 @@ static struct da9063_dev_model regulators_models[] = {
|
|||
{
|
||||
.regulator_info = da9063_regulator_info,
|
||||
.n_regulators = ARRAY_SIZE(da9063_regulator_info),
|
||||
.dev_model = PMIC_DA9063,
|
||||
.type = PMIC_TYPE_DA9063,
|
||||
},
|
||||
{
|
||||
.regulator_info = da9063_regulator_info,
|
||||
.n_regulators = ARRAY_SIZE(da9063_regulator_info) - 6,
|
||||
.type = PMIC_TYPE_DA9063L,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
@ -641,28 +649,34 @@ static struct of_regulator_match da9063_matches[] = {
|
|||
[DA9063_ID_BPERI] = { .name = "bperi", },
|
||||
[DA9063_ID_BCORES_MERGED] = { .name = "bcores-merged" },
|
||||
[DA9063_ID_BMEM_BIO_MERGED] = { .name = "bmem-bio-merged", },
|
||||
[DA9063_ID_LDO1] = { .name = "ldo1", },
|
||||
[DA9063_ID_LDO2] = { .name = "ldo2", },
|
||||
[DA9063_ID_LDO3] = { .name = "ldo3", },
|
||||
[DA9063_ID_LDO4] = { .name = "ldo4", },
|
||||
[DA9063_ID_LDO5] = { .name = "ldo5", },
|
||||
[DA9063_ID_LDO6] = { .name = "ldo6", },
|
||||
[DA9063_ID_LDO7] = { .name = "ldo7", },
|
||||
[DA9063_ID_LDO8] = { .name = "ldo8", },
|
||||
[DA9063_ID_LDO9] = { .name = "ldo9", },
|
||||
[DA9063_ID_LDO10] = { .name = "ldo10", },
|
||||
[DA9063_ID_LDO11] = { .name = "ldo11", },
|
||||
/* The following LDOs are present only on DA9063, not on DA9063L */
|
||||
[DA9063_ID_LDO1] = { .name = "ldo1", },
|
||||
[DA9063_ID_LDO2] = { .name = "ldo2", },
|
||||
[DA9063_ID_LDO4] = { .name = "ldo4", },
|
||||
[DA9063_ID_LDO5] = { .name = "ldo5", },
|
||||
[DA9063_ID_LDO6] = { .name = "ldo6", },
|
||||
[DA9063_ID_LDO10] = { .name = "ldo10", },
|
||||
};
|
||||
|
||||
static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
|
||||
struct platform_device *pdev,
|
||||
struct of_regulator_match **da9063_reg_matches)
|
||||
{
|
||||
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct da9063_regulators_pdata *pdata;
|
||||
struct da9063_regulator_data *rdata;
|
||||
struct device_node *node;
|
||||
int da9063_matches_len = ARRAY_SIZE(da9063_matches);
|
||||
int i, n, num;
|
||||
|
||||
if (da9063->type == PMIC_TYPE_DA9063L)
|
||||
da9063_matches_len -= 6;
|
||||
|
||||
node = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
|
||||
if (!node) {
|
||||
dev_err(&pdev->dev, "Regulators device node not found\n");
|
||||
|
@ -670,7 +684,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
|
|||
}
|
||||
|
||||
num = of_regulator_match(&pdev->dev, node, da9063_matches,
|
||||
ARRAY_SIZE(da9063_matches));
|
||||
da9063_matches_len);
|
||||
of_node_put(node);
|
||||
if (num < 0) {
|
||||
dev_err(&pdev->dev, "Failed to match regulators\n");
|
||||
|
@ -689,7 +703,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
|
|||
pdata->n_regulators = num;
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(da9063_matches); i++) {
|
||||
for (i = 0; i < da9063_matches_len; i++) {
|
||||
if (!da9063_matches[i].init_data)
|
||||
continue;
|
||||
|
||||
|
@ -741,12 +755,12 @@ static int da9063_regulator_probe(struct platform_device *pdev)
|
|||
|
||||
/* Find regulators set for particular device model */
|
||||
for (model = regulators_models; model->regulator_info; model++) {
|
||||
if (model->dev_model == da9063->model)
|
||||
if (model->type == da9063->type)
|
||||
break;
|
||||
}
|
||||
if (!model->regulator_info) {
|
||||
dev_err(&pdev->dev, "Chip model not recognised (%u)\n",
|
||||
da9063->model);
|
||||
da9063->type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,6 +296,8 @@
|
|||
#define AS3722_ADC1_CONV_NOTREADY BIT(7)
|
||||
#define AS3722_ADC1_SOURCE_SELECT_MASK 0x1F
|
||||
|
||||
#define AS3722_CTRL_SEQU1_AC_OK_PWR_ON BIT(0)
|
||||
|
||||
/* GPIO modes */
|
||||
#define AS3722_GPIO_MODE_MASK 0x07
|
||||
#define AS3722_GPIO_MODE_INPUT 0x00
|
||||
|
@ -391,6 +393,7 @@ struct as3722 {
|
|||
unsigned long irq_flags;
|
||||
bool en_intern_int_pullup;
|
||||
bool en_intern_i2c_pullup;
|
||||
bool en_ac_ok_pwr_on;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
};
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ struct cros_ec_device {
|
|||
bool mkbp_event_supported;
|
||||
struct blocking_notifier_head event_notifier;
|
||||
|
||||
struct ec_response_get_next_event event_data;
|
||||
struct ec_response_get_next_event_v1 event_data;
|
||||
int event_size;
|
||||
u32 host_event_wake_mask;
|
||||
};
|
||||
|
|
|
@ -804,6 +804,8 @@ enum ec_feature_code {
|
|||
EC_FEATURE_MOTION_SENSE_FIFO = 24,
|
||||
/* EC has RTC feature that can be controlled by host commands */
|
||||
EC_FEATURE_RTC = 27,
|
||||
/* EC supports CEC commands */
|
||||
EC_FEATURE_CEC = 35,
|
||||
};
|
||||
|
||||
#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
|
||||
|
@ -2078,6 +2080,12 @@ enum ec_mkbp_event {
|
|||
/* EC sent a sysrq command */
|
||||
EC_MKBP_EVENT_SYSRQ = 6,
|
||||
|
||||
/* Notify the AP that something happened on CEC */
|
||||
EC_MKBP_EVENT_CEC_EVENT = 8,
|
||||
|
||||
/* Send an incoming CEC message to the AP */
|
||||
EC_MKBP_EVENT_CEC_MESSAGE = 9,
|
||||
|
||||
/* Number of MKBP events */
|
||||
EC_MKBP_EVENT_COUNT,
|
||||
};
|
||||
|
@ -2093,12 +2101,28 @@ union ec_response_get_next_data {
|
|||
uint32_t sysrq;
|
||||
} __packed;
|
||||
|
||||
union ec_response_get_next_data_v1 {
|
||||
uint8_t key_matrix[16];
|
||||
uint32_t host_event;
|
||||
uint32_t buttons;
|
||||
uint32_t switches;
|
||||
uint32_t sysrq;
|
||||
uint32_t cec_events;
|
||||
uint8_t cec_message[16];
|
||||
} __packed;
|
||||
|
||||
struct ec_response_get_next_event {
|
||||
uint8_t event_type;
|
||||
/* Followed by event data if any */
|
||||
union ec_response_get_next_data data;
|
||||
} __packed;
|
||||
|
||||
struct ec_response_get_next_event_v1 {
|
||||
uint8_t event_type;
|
||||
/* Followed by event data if any */
|
||||
union ec_response_get_next_data_v1 data;
|
||||
} __packed;
|
||||
|
||||
/* Bit indices for buttons and switches.*/
|
||||
/* Buttons */
|
||||
#define EC_MKBP_POWER_BUTTON 0
|
||||
|
@ -2593,14 +2617,18 @@ struct ec_params_current_limit {
|
|||
} __packed;
|
||||
|
||||
/*
|
||||
* Set maximum external power current.
|
||||
* Set maximum external voltage / current.
|
||||
*/
|
||||
#define EC_CMD_EXT_POWER_CURRENT_LIMIT 0xa2
|
||||
#define EC_CMD_EXTERNAL_POWER_LIMIT 0x00A2
|
||||
|
||||
struct ec_params_ext_power_current_limit {
|
||||
uint32_t limit; /* in mA */
|
||||
/* Command v0 is used only on Spring and is obsolete + unsupported */
|
||||
struct ec_params_external_power_limit_v1 {
|
||||
uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
|
||||
uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
|
||||
} __packed;
|
||||
|
||||
#define EC_POWER_LIMIT_NONE 0xffff
|
||||
|
||||
/* Inform the EC when entering a sleep state */
|
||||
#define EC_CMD_HOST_SLEEP_EVENT 0xa9
|
||||
|
||||
|
@ -2829,6 +2857,79 @@ struct ec_params_reboot_ec {
|
|||
#define EC_ACPI_MEM_VERSION_CURRENT 1
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* HDMI CEC commands
|
||||
*
|
||||
* These commands are for sending and receiving message via HDMI CEC
|
||||
*/
|
||||
#define EC_MAX_CEC_MSG_LEN 16
|
||||
|
||||
/* CEC message from the AP to be written on the CEC bus */
|
||||
#define EC_CMD_CEC_WRITE_MSG 0x00B8
|
||||
|
||||
/**
|
||||
* struct ec_params_cec_write - Message to write to the CEC bus
|
||||
* @msg: message content to write to the CEC bus
|
||||
*/
|
||||
struct ec_params_cec_write {
|
||||
uint8_t msg[EC_MAX_CEC_MSG_LEN];
|
||||
} __packed;
|
||||
|
||||
/* Set various CEC parameters */
|
||||
#define EC_CMD_CEC_SET 0x00BA
|
||||
|
||||
/**
|
||||
* struct ec_params_cec_set - CEC parameters set
|
||||
* @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS
|
||||
* @val: in case cmd is CEC_CMD_ENABLE, this field can be 0 to disable CEC
|
||||
* or 1 to enable CEC functionality, in case cmd is CEC_CMD_LOGICAL_ADDRESS,
|
||||
* this field encodes the requested logical address between 0 and 15
|
||||
* or 0xff to unregister
|
||||
*/
|
||||
struct ec_params_cec_set {
|
||||
uint8_t cmd; /* enum cec_command */
|
||||
uint8_t val;
|
||||
} __packed;
|
||||
|
||||
/* Read various CEC parameters */
|
||||
#define EC_CMD_CEC_GET 0x00BB
|
||||
|
||||
/**
|
||||
* struct ec_params_cec_get - CEC parameters get
|
||||
* @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS
|
||||
*/
|
||||
struct ec_params_cec_get {
|
||||
uint8_t cmd; /* enum cec_command */
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct ec_response_cec_get - CEC parameters get response
|
||||
* @val: in case cmd was CEC_CMD_ENABLE, this field will 0 if CEC is
|
||||
* disabled or 1 if CEC functionality is enabled,
|
||||
* in case cmd was CEC_CMD_LOGICAL_ADDRESS, this will encode the
|
||||
* configured logical address between 0 and 15 or 0xff if unregistered
|
||||
*/
|
||||
struct ec_response_cec_get {
|
||||
uint8_t val;
|
||||
} __packed;
|
||||
|
||||
/* CEC parameters command */
|
||||
enum ec_cec_command {
|
||||
/* CEC reading, writing and events enable */
|
||||
CEC_CMD_ENABLE,
|
||||
/* CEC logical address */
|
||||
CEC_CMD_LOGICAL_ADDRESS,
|
||||
};
|
||||
|
||||
/* Events from CEC to AP */
|
||||
enum mkbp_cec_event {
|
||||
/* Outgoing message was acknowledged by a follower */
|
||||
EC_MKBP_CEC_SEND_OK = BIT(0),
|
||||
/* Outgoing message was not acknowledged */
|
||||
EC_MKBP_CEC_SEND_FAILED = BIT(1),
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Special commands
|
||||
|
@ -2974,6 +3075,12 @@ enum usb_chg_type {
|
|||
USB_CHG_TYPE_VBUS,
|
||||
USB_CHG_TYPE_UNKNOWN,
|
||||
};
|
||||
enum usb_power_roles {
|
||||
USB_PD_PORT_POWER_DISCONNECTED,
|
||||
USB_PD_PORT_POWER_SOURCE,
|
||||
USB_PD_PORT_POWER_SINK,
|
||||
USB_PD_PORT_POWER_SINK_NOT_CHARGING,
|
||||
};
|
||||
|
||||
struct usb_chg_measures {
|
||||
uint16_t voltage_max;
|
||||
|
@ -2991,6 +3098,120 @@ struct ec_response_usb_pd_power_info {
|
|||
uint32_t max_power;
|
||||
} __packed;
|
||||
|
||||
struct ec_params_usb_pd_info_request {
|
||||
uint8_t port;
|
||||
} __packed;
|
||||
|
||||
/* Read USB-PD Device discovery info */
|
||||
#define EC_CMD_USB_PD_DISCOVERY 0x0113
|
||||
struct ec_params_usb_pd_discovery_entry {
|
||||
uint16_t vid; /* USB-IF VID */
|
||||
uint16_t pid; /* USB-IF PID */
|
||||
uint8_t ptype; /* product type (hub,periph,cable,ama) */
|
||||
} __packed;
|
||||
|
||||
/* Override default charge behavior */
|
||||
#define EC_CMD_PD_CHARGE_PORT_OVERRIDE 0x0114
|
||||
|
||||
/* Negative port parameters have special meaning */
|
||||
enum usb_pd_override_ports {
|
||||
OVERRIDE_DONT_CHARGE = -2,
|
||||
OVERRIDE_OFF = -1,
|
||||
/* [0, CONFIG_USB_PD_PORT_COUNT): Port# */
|
||||
};
|
||||
|
||||
struct ec_params_charge_port_override {
|
||||
int16_t override_port; /* Override port# */
|
||||
} __packed;
|
||||
|
||||
/* Read (and delete) one entry of PD event log */
|
||||
#define EC_CMD_PD_GET_LOG_ENTRY 0x0115
|
||||
|
||||
struct ec_response_pd_log {
|
||||
uint32_t timestamp; /* relative timestamp in milliseconds */
|
||||
uint8_t type; /* event type : see PD_EVENT_xx below */
|
||||
uint8_t size_port; /* [7:5] port number [4:0] payload size in bytes */
|
||||
uint16_t data; /* type-defined data payload */
|
||||
uint8_t payload[0]; /* optional additional data payload: 0..16 bytes */
|
||||
} __packed;
|
||||
|
||||
/* The timestamp is the microsecond counter shifted to get about a ms. */
|
||||
#define PD_LOG_TIMESTAMP_SHIFT 10 /* 1 LSB = 1024us */
|
||||
|
||||
#define PD_LOG_SIZE_MASK 0x1f
|
||||
#define PD_LOG_PORT_MASK 0xe0
|
||||
#define PD_LOG_PORT_SHIFT 5
|
||||
#define PD_LOG_PORT_SIZE(port, size) (((port) << PD_LOG_PORT_SHIFT) | \
|
||||
((size) & PD_LOG_SIZE_MASK))
|
||||
#define PD_LOG_PORT(size_port) ((size_port) >> PD_LOG_PORT_SHIFT)
|
||||
#define PD_LOG_SIZE(size_port) ((size_port) & PD_LOG_SIZE_MASK)
|
||||
|
||||
/* PD event log : entry types */
|
||||
/* PD MCU events */
|
||||
#define PD_EVENT_MCU_BASE 0x00
|
||||
#define PD_EVENT_MCU_CHARGE (PD_EVENT_MCU_BASE+0)
|
||||
#define PD_EVENT_MCU_CONNECT (PD_EVENT_MCU_BASE+1)
|
||||
/* Reserved for custom board event */
|
||||
#define PD_EVENT_MCU_BOARD_CUSTOM (PD_EVENT_MCU_BASE+2)
|
||||
/* PD generic accessory events */
|
||||
#define PD_EVENT_ACC_BASE 0x20
|
||||
#define PD_EVENT_ACC_RW_FAIL (PD_EVENT_ACC_BASE+0)
|
||||
#define PD_EVENT_ACC_RW_ERASE (PD_EVENT_ACC_BASE+1)
|
||||
/* PD power supply events */
|
||||
#define PD_EVENT_PS_BASE 0x40
|
||||
#define PD_EVENT_PS_FAULT (PD_EVENT_PS_BASE+0)
|
||||
/* PD video dongles events */
|
||||
#define PD_EVENT_VIDEO_BASE 0x60
|
||||
#define PD_EVENT_VIDEO_DP_MODE (PD_EVENT_VIDEO_BASE+0)
|
||||
#define PD_EVENT_VIDEO_CODEC (PD_EVENT_VIDEO_BASE+1)
|
||||
/* Returned in the "type" field, when there is no entry available */
|
||||
#define PD_EVENT_NO_ENTRY 0xff
|
||||
|
||||
/*
|
||||
* PD_EVENT_MCU_CHARGE event definition :
|
||||
* the payload is "struct usb_chg_measures"
|
||||
* the data field contains the port state flags as defined below :
|
||||
*/
|
||||
/* Port partner is a dual role device */
|
||||
#define CHARGE_FLAGS_DUAL_ROLE BIT(15)
|
||||
/* Port is the pending override port */
|
||||
#define CHARGE_FLAGS_DELAYED_OVERRIDE BIT(14)
|
||||
/* Port is the override port */
|
||||
#define CHARGE_FLAGS_OVERRIDE BIT(13)
|
||||
/* Charger type */
|
||||
#define CHARGE_FLAGS_TYPE_SHIFT 3
|
||||
#define CHARGE_FLAGS_TYPE_MASK (0xf << CHARGE_FLAGS_TYPE_SHIFT)
|
||||
/* Power delivery role */
|
||||
#define CHARGE_FLAGS_ROLE_MASK (7 << 0)
|
||||
|
||||
/*
|
||||
* PD_EVENT_PS_FAULT data field flags definition :
|
||||
*/
|
||||
#define PS_FAULT_OCP 1
|
||||
#define PS_FAULT_FAST_OCP 2
|
||||
#define PS_FAULT_OVP 3
|
||||
#define PS_FAULT_DISCH 4
|
||||
|
||||
/*
|
||||
* PD_EVENT_VIDEO_CODEC payload is "struct mcdp_info".
|
||||
*/
|
||||
struct mcdp_version {
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
uint16_t build;
|
||||
} __packed;
|
||||
|
||||
struct mcdp_info {
|
||||
uint8_t family[2];
|
||||
uint8_t chipid[2];
|
||||
struct mcdp_version irom;
|
||||
struct mcdp_version fw;
|
||||
} __packed;
|
||||
|
||||
/* struct mcdp_info field decoding */
|
||||
#define MCDP_CHIPID(chipid) ((chipid[0] << 8) | chipid[1])
|
||||
#define MCDP_FAMILY(family) ((family[0] << 8) | family[1])
|
||||
|
||||
/* Get info about USB-C SS muxes */
|
||||
#define EC_CMD_USB_PD_MUX_INFO 0x11a
|
||||
|
||||
|
|
|
@ -29,8 +29,11 @@
|
|||
#define DA9063_DRVNAME_RTC "da9063-rtc"
|
||||
#define DA9063_DRVNAME_VIBRATION "da9063-vibration"
|
||||
|
||||
enum da9063_models {
|
||||
PMIC_DA9063 = 0x61,
|
||||
#define PMIC_CHIP_ID_DA9063 0x61
|
||||
|
||||
enum da9063_type {
|
||||
PMIC_TYPE_DA9063 = 0,
|
||||
PMIC_TYPE_DA9063L,
|
||||
};
|
||||
|
||||
enum da9063_variant_codes {
|
||||
|
@ -72,13 +75,10 @@ enum da9063_irqs {
|
|||
DA9063_IRQ_GPI15,
|
||||
};
|
||||
|
||||
#define DA9063_IRQ_BASE_OFFSET 0
|
||||
#define DA9063_NUM_IRQ (DA9063_IRQ_GPI15 + 1 - DA9063_IRQ_BASE_OFFSET)
|
||||
|
||||
struct da9063 {
|
||||
/* Device */
|
||||
struct device *dev;
|
||||
unsigned short model;
|
||||
enum da9063_type type;
|
||||
unsigned char variant_code;
|
||||
unsigned int flags;
|
||||
|
||||
|
@ -94,7 +94,4 @@ struct da9063 {
|
|||
int da9063_device_init(struct da9063 *da9063, unsigned int irq);
|
||||
int da9063_irq_init(struct da9063 *da9063);
|
||||
|
||||
void da9063_device_exit(struct da9063 *da9063);
|
||||
void da9063_irq_exit(struct da9063 *da9063);
|
||||
|
||||
#endif /* __MFD_DA9063_CORE_H__ */
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MFD internals for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#ifndef MADERA_CORE_H
|
||||
#define MADERA_CORE_H
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/madera/pdata.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
enum madera_type {
|
||||
/* 0 is reserved for indicating failure to identify */
|
||||
CS47L35 = 1,
|
||||
CS47L85 = 2,
|
||||
CS47L90 = 3,
|
||||
CS47L91 = 4,
|
||||
WM1840 = 7,
|
||||
};
|
||||
|
||||
#define MADERA_MAX_CORE_SUPPLIES 2
|
||||
#define MADERA_MAX_GPIOS 40
|
||||
|
||||
#define CS47L35_NUM_GPIOS 16
|
||||
#define CS47L85_NUM_GPIOS 40
|
||||
#define CS47L90_NUM_GPIOS 38
|
||||
|
||||
#define MADERA_MAX_MICBIAS 4
|
||||
|
||||
/* Notifier events */
|
||||
#define MADERA_NOTIFY_VOICE_TRIGGER 0x1
|
||||
#define MADERA_NOTIFY_HPDET 0x2
|
||||
#define MADERA_NOTIFY_MICDET 0x4
|
||||
|
||||
/* GPIO Function Definitions */
|
||||
#define MADERA_GP_FN_ALTERNATE 0x00
|
||||
#define MADERA_GP_FN_GPIO 0x01
|
||||
#define MADERA_GP_FN_DSP_GPIO 0x02
|
||||
#define MADERA_GP_FN_IRQ1 0x03
|
||||
#define MADERA_GP_FN_IRQ2 0x04
|
||||
#define MADERA_GP_FN_FLL1_CLOCK 0x10
|
||||
#define MADERA_GP_FN_FLL2_CLOCK 0x11
|
||||
#define MADERA_GP_FN_FLL3_CLOCK 0x12
|
||||
#define MADERA_GP_FN_FLLAO_CLOCK 0x13
|
||||
#define MADERA_GP_FN_FLL1_LOCK 0x18
|
||||
#define MADERA_GP_FN_FLL2_LOCK 0x19
|
||||
#define MADERA_GP_FN_FLL3_LOCK 0x1A
|
||||
#define MADERA_GP_FN_FLLAO_LOCK 0x1B
|
||||
#define MADERA_GP_FN_OPCLK_OUT 0x40
|
||||
#define MADERA_GP_FN_OPCLK_ASYNC_OUT 0x41
|
||||
#define MADERA_GP_FN_PWM1 0x48
|
||||
#define MADERA_GP_FN_PWM2 0x49
|
||||
#define MADERA_GP_FN_SPDIF_OUT 0x4C
|
||||
#define MADERA_GP_FN_HEADPHONE_DET 0x50
|
||||
#define MADERA_GP_FN_MIC_DET 0x58
|
||||
#define MADERA_GP_FN_DRC1_SIGNAL_DETECT 0x80
|
||||
#define MADERA_GP_FN_DRC2_SIGNAL_DETECT 0x81
|
||||
#define MADERA_GP_FN_ASRC1_IN1_LOCK 0x88
|
||||
#define MADERA_GP_FN_ASRC1_IN2_LOCK 0x89
|
||||
#define MADERA_GP_FN_ASRC2_IN1_LOCK 0x8A
|
||||
#define MADERA_GP_FN_ASRC2_IN2_LOCK 0x8B
|
||||
#define MADERA_GP_FN_DSP_IRQ1 0xA0
|
||||
#define MADERA_GP_FN_DSP_IRQ2 0xA1
|
||||
#define MADERA_GP_FN_DSP_IRQ3 0xA2
|
||||
#define MADERA_GP_FN_DSP_IRQ4 0xA3
|
||||
#define MADERA_GP_FN_DSP_IRQ5 0xA4
|
||||
#define MADERA_GP_FN_DSP_IRQ6 0xA5
|
||||
#define MADERA_GP_FN_DSP_IRQ7 0xA6
|
||||
#define MADERA_GP_FN_DSP_IRQ8 0xA7
|
||||
#define MADERA_GP_FN_DSP_IRQ9 0xA8
|
||||
#define MADERA_GP_FN_DSP_IRQ10 0xA9
|
||||
#define MADERA_GP_FN_DSP_IRQ11 0xAA
|
||||
#define MADERA_GP_FN_DSP_IRQ12 0xAB
|
||||
#define MADERA_GP_FN_DSP_IRQ13 0xAC
|
||||
#define MADERA_GP_FN_DSP_IRQ14 0xAD
|
||||
#define MADERA_GP_FN_DSP_IRQ15 0xAE
|
||||
#define MADERA_GP_FN_DSP_IRQ16 0xAF
|
||||
#define MADERA_GP_FN_HPOUT1L_SC 0xB0
|
||||
#define MADERA_GP_FN_HPOUT1R_SC 0xB1
|
||||
#define MADERA_GP_FN_HPOUT2L_SC 0xB2
|
||||
#define MADERA_GP_FN_HPOUT2R_SC 0xB3
|
||||
#define MADERA_GP_FN_HPOUT3L_SC 0xB4
|
||||
#define MADERA_GP_FN_HPOUT4R_SC 0xB5
|
||||
#define MADERA_GP_FN_SPKOUTL_SC 0xB6
|
||||
#define MADERA_GP_FN_SPKOUTR_SC 0xB7
|
||||
#define MADERA_GP_FN_HPOUT1L_ENA 0xC0
|
||||
#define MADERA_GP_FN_HPOUT1R_ENA 0xC1
|
||||
#define MADERA_GP_FN_HPOUT2L_ENA 0xC2
|
||||
#define MADERA_GP_FN_HPOUT2R_ENA 0xC3
|
||||
#define MADERA_GP_FN_HPOUT3L_ENA 0xC4
|
||||
#define MADERA_GP_FN_HPOUT4R_ENA 0xC5
|
||||
#define MADERA_GP_FN_SPKOUTL_ENA 0xC6
|
||||
#define MADERA_GP_FN_SPKOUTR_ENA 0xC7
|
||||
#define MADERA_GP_FN_HPOUT1L_DIS 0xD0
|
||||
#define MADERA_GP_FN_HPOUT1R_DIS 0xD1
|
||||
#define MADERA_GP_FN_HPOUT2L_DIS 0xD2
|
||||
#define MADERA_GP_FN_HPOUT2R_DIS 0xD3
|
||||
#define MADERA_GP_FN_HPOUT3L_DIS 0xD4
|
||||
#define MADERA_GP_FN_HPOUT4R_DIS 0xD5
|
||||
#define MADERA_GP_FN_SPKOUTL_DIS 0xD6
|
||||
#define MADERA_GP_FN_SPKOUTR_DIS 0xD7
|
||||
#define MADERA_GP_FN_SPK_SHUTDOWN 0xE0
|
||||
#define MADERA_GP_FN_SPK_OVH_SHUTDOWN 0xE1
|
||||
#define MADERA_GP_FN_SPK_OVH_WARN 0xE2
|
||||
#define MADERA_GP_FN_TIMER1_STATUS 0x140
|
||||
#define MADERA_GP_FN_TIMER2_STATUS 0x141
|
||||
#define MADERA_GP_FN_TIMER3_STATUS 0x142
|
||||
#define MADERA_GP_FN_TIMER4_STATUS 0x143
|
||||
#define MADERA_GP_FN_TIMER5_STATUS 0x144
|
||||
#define MADERA_GP_FN_TIMER6_STATUS 0x145
|
||||
#define MADERA_GP_FN_TIMER7_STATUS 0x146
|
||||
#define MADERA_GP_FN_TIMER8_STATUS 0x147
|
||||
#define MADERA_GP_FN_EVENTLOG1_FIFO_STS 0x150
|
||||
#define MADERA_GP_FN_EVENTLOG2_FIFO_STS 0x151
|
||||
#define MADERA_GP_FN_EVENTLOG3_FIFO_STS 0x152
|
||||
#define MADERA_GP_FN_EVENTLOG4_FIFO_STS 0x153
|
||||
#define MADERA_GP_FN_EVENTLOG5_FIFO_STS 0x154
|
||||
#define MADERA_GP_FN_EVENTLOG6_FIFO_STS 0x155
|
||||
#define MADERA_GP_FN_EVENTLOG7_FIFO_STS 0x156
|
||||
#define MADERA_GP_FN_EVENTLOG8_FIFO_STS 0x157
|
||||
|
||||
struct snd_soc_dapm_context;
|
||||
|
||||
/*
|
||||
* struct madera - internal data shared by the set of Madera drivers
|
||||
*
|
||||
* This should not be used by anything except child drivers of the Madera MFD
|
||||
*
|
||||
* @regmap: pointer to the regmap instance for 16-bit registers
|
||||
* @regmap_32bit: pointer to the regmap instance for 32-bit registers
|
||||
* @dev: pointer to the MFD device
|
||||
* @type: type of codec
|
||||
* @rev: silicon revision
|
||||
* @type_name: display name of this codec
|
||||
* @num_core_supplies: number of core supply regulators
|
||||
* @core_supplies: list of core supplies that are always required
|
||||
* @dcvdd: pointer to DCVDD regulator
|
||||
* @internal_dcvdd: true if DCVDD is supplied from the internal LDO1
|
||||
* @pdata: our pdata
|
||||
* @irq_dev: the irqchip child driver device
|
||||
* @irq: host irq number from SPI or I2C configuration
|
||||
* @out_clamp: indicates output clamp state for each analogue output
|
||||
* @out_shorted: indicates short circuit state for each analogue output
|
||||
* @hp_ena: bitflags of enable state for the headphone outputs
|
||||
* @num_micbias: number of MICBIAS outputs
|
||||
* @num_childbias: number of child biases for each MICBIAS
|
||||
* @dapm: pointer to codec driver DAPM context
|
||||
* @notifier: notifier for signalling events to ASoC machine driver
|
||||
*/
|
||||
struct madera {
|
||||
struct regmap *regmap;
|
||||
struct regmap *regmap_32bit;
|
||||
|
||||
struct device *dev;
|
||||
|
||||
enum madera_type type;
|
||||
unsigned int rev;
|
||||
const char *type_name;
|
||||
|
||||
int num_core_supplies;
|
||||
struct regulator_bulk_data core_supplies[MADERA_MAX_CORE_SUPPLIES];
|
||||
struct regulator *dcvdd;
|
||||
bool internal_dcvdd;
|
||||
|
||||
struct madera_pdata pdata;
|
||||
|
||||
struct device *irq_dev;
|
||||
int irq;
|
||||
|
||||
unsigned int num_micbias;
|
||||
unsigned int num_childbias[MADERA_MAX_MICBIAS];
|
||||
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
struct blocking_notifier_head notifier;
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,59 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Platform data for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#ifndef MADERA_PDATA_H
|
||||
#define MADERA_PDATA_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/regulator/arizona-ldo1.h>
|
||||
#include <linux/regulator/arizona-micsupp.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#define MADERA_MAX_MICBIAS 4
|
||||
#define MADERA_MAX_CHILD_MICBIAS 4
|
||||
|
||||
#define MADERA_MAX_GPSW 2
|
||||
|
||||
struct gpio_desc;
|
||||
struct pinctrl_map;
|
||||
struct madera_irqchip_pdata;
|
||||
struct madera_codec_pdata;
|
||||
|
||||
/**
|
||||
* struct madera_pdata - Configuration data for Madera devices
|
||||
*
|
||||
* @reset: GPIO controlling /RESET (NULL = none)
|
||||
* @ldo1: Substruct of pdata for the LDO1 regulator
|
||||
* @micvdd: Substruct of pdata for the MICVDD regulator
|
||||
* @irq_flags: Mode for primary IRQ (defaults to active low)
|
||||
* @gpio_base: Base GPIO number
|
||||
* @gpio_configs: Array of GPIO configurations (See Documentation/pinctrl.txt)
|
||||
* @n_gpio_configs: Number of entries in gpio_configs
|
||||
* @gpsw: General purpose switch mode setting. Depends on the external
|
||||
* hardware connected to the switch. (See the SW1_MODE field
|
||||
* in the datasheet for the available values for your codec)
|
||||
*/
|
||||
struct madera_pdata {
|
||||
struct gpio_desc *reset;
|
||||
|
||||
struct arizona_ldo1_pdata ldo1;
|
||||
struct arizona_micsupp_pdata micvdd;
|
||||
|
||||
unsigned int irq_flags;
|
||||
int gpio_base;
|
||||
|
||||
const struct pinctrl_map *gpio_configs;
|
||||
int n_gpio_configs;
|
||||
|
||||
u32 gpsw[MADERA_MAX_GPSW];
|
||||
};
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -21,6 +21,7 @@ enum rave_sp_command {
|
|||
RAVE_SP_CMD_STATUS = 0xA0,
|
||||
RAVE_SP_CMD_SW_WDT = 0xA1,
|
||||
RAVE_SP_CMD_PET_WDT = 0xA2,
|
||||
RAVE_SP_CMD_RMB_EEPROM = 0xA4,
|
||||
RAVE_SP_CMD_SET_BACKLIGHT = 0xA6,
|
||||
RAVE_SP_CMD_RESET = 0xA7,
|
||||
RAVE_SP_CMD_RESET_REASON = 0xA8,
|
||||
|
|
|
@ -0,0 +1,332 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2018 ROHM Semiconductors */
|
||||
|
||||
#ifndef __LINUX_MFD_BD71837_H__
|
||||
#define __LINUX_MFD_BD71837_H__
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum {
|
||||
BD71837_BUCK1 = 0,
|
||||
BD71837_BUCK2,
|
||||
BD71837_BUCK3,
|
||||
BD71837_BUCK4,
|
||||
BD71837_BUCK5,
|
||||
BD71837_BUCK6,
|
||||
BD71837_BUCK7,
|
||||
BD71837_BUCK8,
|
||||
BD71837_LDO1,
|
||||
BD71837_LDO2,
|
||||
BD71837_LDO3,
|
||||
BD71837_LDO4,
|
||||
BD71837_LDO5,
|
||||
BD71837_LDO6,
|
||||
BD71837_LDO7,
|
||||
BD71837_REGULATOR_CNT,
|
||||
};
|
||||
|
||||
#define BD71837_BUCK1_VOLTAGE_NUM 0x40
|
||||
#define BD71837_BUCK2_VOLTAGE_NUM 0x40
|
||||
#define BD71837_BUCK3_VOLTAGE_NUM 0x40
|
||||
#define BD71837_BUCK4_VOLTAGE_NUM 0x40
|
||||
|
||||
#define BD71837_BUCK5_VOLTAGE_NUM 0x08
|
||||
#define BD71837_BUCK6_VOLTAGE_NUM 0x04
|
||||
#define BD71837_BUCK7_VOLTAGE_NUM 0x08
|
||||
#define BD71837_BUCK8_VOLTAGE_NUM 0x40
|
||||
|
||||
#define BD71837_LDO1_VOLTAGE_NUM 0x04
|
||||
#define BD71837_LDO2_VOLTAGE_NUM 0x02
|
||||
#define BD71837_LDO3_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO4_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO5_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO6_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO7_VOLTAGE_NUM 0x10
|
||||
|
||||
enum {
|
||||
BD71837_REG_REV = 0x00,
|
||||
BD71837_REG_SWRESET = 0x01,
|
||||
BD71837_REG_I2C_DEV = 0x02,
|
||||
BD71837_REG_PWRCTRL0 = 0x03,
|
||||
BD71837_REG_PWRCTRL1 = 0x04,
|
||||
BD71837_REG_BUCK1_CTRL = 0x05,
|
||||
BD71837_REG_BUCK2_CTRL = 0x06,
|
||||
BD71837_REG_BUCK3_CTRL = 0x07,
|
||||
BD71837_REG_BUCK4_CTRL = 0x08,
|
||||
BD71837_REG_BUCK5_CTRL = 0x09,
|
||||
BD71837_REG_BUCK6_CTRL = 0x0A,
|
||||
BD71837_REG_BUCK7_CTRL = 0x0B,
|
||||
BD71837_REG_BUCK8_CTRL = 0x0C,
|
||||
BD71837_REG_BUCK1_VOLT_RUN = 0x0D,
|
||||
BD71837_REG_BUCK1_VOLT_IDLE = 0x0E,
|
||||
BD71837_REG_BUCK1_VOLT_SUSP = 0x0F,
|
||||
BD71837_REG_BUCK2_VOLT_RUN = 0x10,
|
||||
BD71837_REG_BUCK2_VOLT_IDLE = 0x11,
|
||||
BD71837_REG_BUCK3_VOLT_RUN = 0x12,
|
||||
BD71837_REG_BUCK4_VOLT_RUN = 0x13,
|
||||
BD71837_REG_BUCK5_VOLT = 0x14,
|
||||
BD71837_REG_BUCK6_VOLT = 0x15,
|
||||
BD71837_REG_BUCK7_VOLT = 0x16,
|
||||
BD71837_REG_BUCK8_VOLT = 0x17,
|
||||
BD71837_REG_LDO1_VOLT = 0x18,
|
||||
BD71837_REG_LDO2_VOLT = 0x19,
|
||||
BD71837_REG_LDO3_VOLT = 0x1A,
|
||||
BD71837_REG_LDO4_VOLT = 0x1B,
|
||||
BD71837_REG_LDO5_VOLT = 0x1C,
|
||||
BD71837_REG_LDO6_VOLT = 0x1D,
|
||||
BD71837_REG_LDO7_VOLT = 0x1E,
|
||||
BD71837_REG_TRANS_COND0 = 0x1F,
|
||||
BD71837_REG_TRANS_COND1 = 0x20,
|
||||
BD71837_REG_VRFAULTEN = 0x21,
|
||||
BD71837_REG_MVRFLTMASK0 = 0x22,
|
||||
BD71837_REG_MVRFLTMASK1 = 0x23,
|
||||
BD71837_REG_MVRFLTMASK2 = 0x24,
|
||||
BD71837_REG_RCVCFG = 0x25,
|
||||
BD71837_REG_RCVNUM = 0x26,
|
||||
BD71837_REG_PWRONCONFIG0 = 0x27,
|
||||
BD71837_REG_PWRONCONFIG1 = 0x28,
|
||||
BD71837_REG_RESETSRC = 0x29,
|
||||
BD71837_REG_MIRQ = 0x2A,
|
||||
BD71837_REG_IRQ = 0x2B,
|
||||
BD71837_REG_IN_MON = 0x2C,
|
||||
BD71837_REG_POW_STATE = 0x2D,
|
||||
BD71837_REG_OUT32K = 0x2E,
|
||||
BD71837_REG_REGLOCK = 0x2F,
|
||||
BD71837_REG_OTPVER = 0xFF,
|
||||
BD71837_MAX_REGISTER = 0x100,
|
||||
};
|
||||
|
||||
#define REGLOCK_PWRSEQ 0x1
|
||||
#define REGLOCK_VREG 0x10
|
||||
|
||||
/* Generic BUCK control masks */
|
||||
#define BD71837_BUCK_SEL 0x02
|
||||
#define BD71837_BUCK_EN 0x01
|
||||
#define BD71837_BUCK_RUN_ON 0x04
|
||||
|
||||
/* Generic LDO masks */
|
||||
#define BD71837_LDO_SEL 0x80
|
||||
#define BD71837_LDO_EN 0x40
|
||||
|
||||
/* BD71837 BUCK ramp rate CTRL reg bits */
|
||||
#define BUCK_RAMPRATE_MASK 0xC0
|
||||
#define BUCK_RAMPRATE_10P00MV 0x0
|
||||
#define BUCK_RAMPRATE_5P00MV 0x1
|
||||
#define BUCK_RAMPRATE_2P50MV 0x2
|
||||
#define BUCK_RAMPRATE_1P25MV 0x3
|
||||
|
||||
/* BD71837_REG_BUCK1_VOLT_RUN bits */
|
||||
#define BUCK1_RUN_MASK 0x3F
|
||||
#define BUCK1_RUN_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK1_VOLT_SUSP bits */
|
||||
#define BUCK1_SUSP_MASK 0x3F
|
||||
#define BUCK1_SUSP_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK1_VOLT_IDLE bits */
|
||||
#define BUCK1_IDLE_MASK 0x3F
|
||||
#define BUCK1_IDLE_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK2_VOLT_RUN bits */
|
||||
#define BUCK2_RUN_MASK 0x3F
|
||||
#define BUCK2_RUN_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_BUCK2_VOLT_IDLE bits */
|
||||
#define BUCK2_IDLE_MASK 0x3F
|
||||
#define BUCK2_IDLE_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK3_VOLT_RUN bits */
|
||||
#define BUCK3_RUN_MASK 0x3F
|
||||
#define BUCK3_RUN_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_BUCK4_VOLT_RUN bits */
|
||||
#define BUCK4_RUN_MASK 0x3F
|
||||
#define BUCK4_RUN_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_BUCK5_VOLT bits */
|
||||
#define BUCK5_MASK 0x07
|
||||
#define BUCK5_DEFAULT 0x02
|
||||
|
||||
/* BD71837_REG_BUCK6_VOLT bits */
|
||||
#define BUCK6_MASK 0x03
|
||||
#define BUCK6_DEFAULT 0x03
|
||||
|
||||
/* BD71837_REG_BUCK7_VOLT bits */
|
||||
#define BUCK7_MASK 0x07
|
||||
#define BUCK7_DEFAULT 0x03
|
||||
|
||||
/* BD71837_REG_BUCK8_VOLT bits */
|
||||
#define BUCK8_MASK 0x3F
|
||||
#define BUCK8_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_IRQ bits */
|
||||
#define IRQ_SWRST 0x40
|
||||
#define IRQ_PWRON_S 0x20
|
||||
#define IRQ_PWRON_L 0x10
|
||||
#define IRQ_PWRON 0x08
|
||||
#define IRQ_WDOG 0x04
|
||||
#define IRQ_ON_REQ 0x02
|
||||
#define IRQ_STBY_REQ 0x01
|
||||
|
||||
/* BD71837_REG_OUT32K bits */
|
||||
#define BD71837_OUT32K_EN 0x01
|
||||
|
||||
/* BD71837 gated clock rate */
|
||||
#define BD71837_CLK_RATE 32768
|
||||
|
||||
/* ROHM BD71837 irqs */
|
||||
enum {
|
||||
BD71837_INT_STBY_REQ,
|
||||
BD71837_INT_ON_REQ,
|
||||
BD71837_INT_WDOG,
|
||||
BD71837_INT_PWRBTN,
|
||||
BD71837_INT_PWRBTN_L,
|
||||
BD71837_INT_PWRBTN_S,
|
||||
BD71837_INT_SWRST
|
||||
};
|
||||
|
||||
/* ROHM BD71837 interrupt masks */
|
||||
#define BD71837_INT_SWRST_MASK 0x40
|
||||
#define BD71837_INT_PWRBTN_S_MASK 0x20
|
||||
#define BD71837_INT_PWRBTN_L_MASK 0x10
|
||||
#define BD71837_INT_PWRBTN_MASK 0x8
|
||||
#define BD71837_INT_WDOG_MASK 0x4
|
||||
#define BD71837_INT_ON_REQ_MASK 0x2
|
||||
#define BD71837_INT_STBY_REQ_MASK 0x1
|
||||
|
||||
/* BD71837_REG_LDO1_VOLT bits */
|
||||
#define LDO1_MASK 0x03
|
||||
|
||||
/* BD71837_REG_LDO1_VOLT bits */
|
||||
#define LDO2_MASK 0x20
|
||||
|
||||
/* BD71837_REG_LDO3_VOLT bits */
|
||||
#define LDO3_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO4_VOLT bits */
|
||||
#define LDO4_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO5_VOLT bits */
|
||||
#define LDO5_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO6_VOLT bits */
|
||||
#define LDO6_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO7_VOLT bits */
|
||||
#define LDO7_MASK 0x0F
|
||||
|
||||
/* Register write induced reset settings */
|
||||
|
||||
/*
|
||||
* Even though the bit zero is not SWRESET type we still want to write zero
|
||||
* to it when changing type. Bit zero is 'SWRESET' trigger bit and if we
|
||||
* write 1 to it we will trigger the action. So always write 0 to it when
|
||||
* changning SWRESET action - no matter what we read from it.
|
||||
*/
|
||||
#define BD71837_SWRESET_TYPE_MASK 7
|
||||
#define BD71837_SWRESET_TYPE_DISABLED 0
|
||||
#define BD71837_SWRESET_TYPE_COLD 4
|
||||
#define BD71837_SWRESET_TYPE_WARM 6
|
||||
|
||||
#define BD71837_SWRESET_RESET_MASK 1
|
||||
#define BD71837_SWRESET_RESET 1
|
||||
|
||||
/* Poweroff state transition conditions */
|
||||
|
||||
#define BD718XX_ON_REQ_POWEROFF_MASK 1
|
||||
#define BD718XX_SWRESET_POWEROFF_MASK 2
|
||||
#define BD718XX_WDOG_POWEROFF_MASK 4
|
||||
#define BD718XX_KEY_L_POWEROFF_MASK 8
|
||||
|
||||
#define BD718XX_POWOFF_TO_SNVS 0
|
||||
#define BD718XX_POWOFF_TO_RDY 0xF
|
||||
|
||||
#define BD718XX_POWOFF_TIME_MASK 0xF0
|
||||
enum {
|
||||
BD718XX_POWOFF_TIME_5MS = 0,
|
||||
BD718XX_POWOFF_TIME_10MS,
|
||||
BD718XX_POWOFF_TIME_15MS,
|
||||
BD718XX_POWOFF_TIME_20MS,
|
||||
BD718XX_POWOFF_TIME_25MS,
|
||||
BD718XX_POWOFF_TIME_30MS,
|
||||
BD718XX_POWOFF_TIME_35MS,
|
||||
BD718XX_POWOFF_TIME_40MS,
|
||||
BD718XX_POWOFF_TIME_45MS,
|
||||
BD718XX_POWOFF_TIME_50MS,
|
||||
BD718XX_POWOFF_TIME_75MS,
|
||||
BD718XX_POWOFF_TIME_100MS,
|
||||
BD718XX_POWOFF_TIME_250MS,
|
||||
BD718XX_POWOFF_TIME_500MS,
|
||||
BD718XX_POWOFF_TIME_750MS,
|
||||
BD718XX_POWOFF_TIME_1500MS
|
||||
};
|
||||
|
||||
/* Poweron sequence state transition conditions */
|
||||
#define BD718XX_RDY_TO_SNVS_MASK 0xF
|
||||
#define BD718XX_SNVS_TO_RUN_MASK 0xF0
|
||||
|
||||
#define BD718XX_PWR_TRIG_KEY_L 1
|
||||
#define BD718XX_PWR_TRIG_KEY_S 2
|
||||
#define BD718XX_PWR_TRIG_PMIC_ON 4
|
||||
#define BD718XX_PWR_TRIG_VSYS_UVLO 8
|
||||
#define BD718XX_RDY_TO_SNVS_SIFT 0
|
||||
#define BD718XX_SNVS_TO_RUN_SIFT 4
|
||||
|
||||
#define BD718XX_PWRBTN_PRESS_DURATION_MASK 0xF
|
||||
|
||||
/* Timeout value for detecting short press */
|
||||
enum {
|
||||
BD718XX_PWRBTN_SHORT_PRESS_10MS = 0,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_1000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_1500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_2000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_2500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_3000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_3500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_4000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_4500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_5000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_5500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_6000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_6500MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_7000MS,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_7500MS
|
||||
};
|
||||
|
||||
/* Timeout value for detecting LONG press */
|
||||
enum {
|
||||
BD718XX_PWRBTN_LONG_PRESS_10MS = 0,
|
||||
BD718XX_PWRBTN_LONG_PRESS_1S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_2S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_3S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_4S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_5S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_6S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_7S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_8S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_9S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_10S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_11S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_12S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_13S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_14S,
|
||||
BD718XX_PWRBTN_LONG_PRESS_15S
|
||||
};
|
||||
|
||||
struct bd71837_pmic;
|
||||
struct bd71837_clk;
|
||||
|
||||
struct bd71837 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
unsigned long int id;
|
||||
|
||||
int chip_irq;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
|
||||
struct bd71837_pmic *pmic;
|
||||
struct bd71837_clk *clk;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_MFD_BD71837_H__ */
|
|
@ -222,6 +222,12 @@ struct wm8994_pdata {
|
|||
*/
|
||||
bool spkmode_pu;
|
||||
|
||||
/*
|
||||
* CS/ADDR must be pulled internally by the device on this
|
||||
* system.
|
||||
*/
|
||||
bool csnaddr_pd;
|
||||
|
||||
/**
|
||||
* Maximum number of channels clocks will be generated for,
|
||||
* useful for systems where and I2S bus with multiple data
|
||||
|
|
|
@ -20,8 +20,10 @@ struct cec_notifier;
|
|||
#if IS_REACHABLE(CONFIG_CEC_CORE) && IS_ENABLED(CONFIG_CEC_NOTIFIER)
|
||||
|
||||
/**
|
||||
* cec_notifier_get - find or create a new cec_notifier for the given device.
|
||||
* cec_notifier_get_conn - find or create a new cec_notifier for the given
|
||||
* device and connector tuple.
|
||||
* @dev: device that sends the events.
|
||||
* @conn: the connector name from which the event occurs
|
||||
*
|
||||
* If a notifier for device @dev already exists, then increase the refcount
|
||||
* and return that notifier.
|
||||
|
@ -31,7 +33,8 @@ struct cec_notifier;
|
|||
*
|
||||
* Return NULL if the memory could not be allocated.
|
||||
*/
|
||||
struct cec_notifier *cec_notifier_get(struct device *dev);
|
||||
struct cec_notifier *cec_notifier_get_conn(struct device *dev,
|
||||
const char *conn);
|
||||
|
||||
/**
|
||||
* cec_notifier_put - decrease refcount and delete when the refcount reaches 0.
|
||||
|
@ -85,7 +88,8 @@ void cec_register_cec_notifier(struct cec_adapter *adap,
|
|||
struct cec_notifier *notifier);
|
||||
|
||||
#else
|
||||
static inline struct cec_notifier *cec_notifier_get(struct device *dev)
|
||||
static inline struct cec_notifier *cec_notifier_get_conn(struct device *dev,
|
||||
const char *conn)
|
||||
{
|
||||
/* A non-NULL pointer is expected on success */
|
||||
return (struct cec_notifier *)0xdeadfeed;
|
||||
|
@ -120,6 +124,23 @@ static inline void cec_register_cec_notifier(struct cec_adapter *adap,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cec_notifier_get - find or create a new cec_notifier for the given device.
|
||||
* @dev: device that sends the events.
|
||||
*
|
||||
* If a notifier for device @dev already exists, then increase the refcount
|
||||
* and return that notifier.
|
||||
*
|
||||
* If it doesn't exist, then allocate a new notifier struct and return a
|
||||
* pointer to that new struct.
|
||||
*
|
||||
* Return NULL if the memory could not be allocated.
|
||||
*/
|
||||
static inline struct cec_notifier *cec_notifier_get(struct device *dev)
|
||||
{
|
||||
return cec_notifier_get_conn(dev, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* cec_notifier_phys_addr_invalidate() - set the physical address to INVALID
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче